From 31d72f9441a52e6319fb161be93a8bdad60929d4 Mon Sep 17 00:00:00 2001 From: Eduardo Novella Date: Mon, 30 Nov 2020 14:19:57 +0100 Subject: [PATCH] Release source code for Uncrackable app Level4 (Radare2Pay) --- Android/Level4/app/.gitignore | 1 + Android/Level4/app/build.gradle | 63 + Android/Level4/app/proguard-rules.pro | 31 + .../re/pwnme/ExampleInstrumentedTest.java | 27 + .../Level4/app/src/main/AndroidManifest.xml | 21 + Android/Level4/app/src/main/c/CMakeLists.txt | 96 + .../src/main/c/arch/arm64-v8a/syscall_arch.h | 104 + .../main/c/arch/armeabi-v7a/syscall_arch.h | 138 + .../app/src/main/c/arch/x86/syscall_arch.h | 186 + .../app/src/main/c/arch/x86_64/syscall_arch.h | 70 + .../src/main/c/mbedtls/include/mbedtls/aes.h | 673 + .../main/c/mbedtls/include/mbedtls/aesni.h | 136 + .../src/main/c/mbedtls/include/mbedtls/arc4.h | 144 + .../src/main/c/mbedtls/include/mbedtls/aria.h | 369 + .../src/main/c/mbedtls/include/mbedtls/asn1.h | 607 + .../c/mbedtls/include/mbedtls/asn1write.h | 370 + .../main/c/mbedtls/include/mbedtls/base64.h | 96 + .../main/c/mbedtls/include/mbedtls/bignum.h | 1017 + .../main/c/mbedtls/include/mbedtls/blowfish.h | 285 + .../main/c/mbedtls/include/mbedtls/bn_mul.h | 938 + .../main/c/mbedtls/include/mbedtls/camellia.h | 324 + .../src/main/c/mbedtls/include/mbedtls/ccm.h | 308 + .../main/c/mbedtls/include/mbedtls/certs.h | 250 + .../main/c/mbedtls/include/mbedtls/chacha20.h | 225 + .../c/mbedtls/include/mbedtls/chachapoly.h | 357 + .../c/mbedtls/include/mbedtls/check_config.h | 885 + .../main/c/mbedtls/include/mbedtls/cipher.h | 944 + .../mbedtls/include/mbedtls/cipher_internal.h | 150 + .../src/main/c/mbedtls/include/mbedtls/cmac.h | 211 + .../c/mbedtls/include/mbedtls/compat-1.3.h | 2529 + .../main/c/mbedtls/include/mbedtls/config.h | 3770 ++ .../c/mbedtls/include/mbedtls/config_psa.h | 82 + .../main/c/mbedtls/include/mbedtls/ctr_drbg.h | 560 + .../main/c/mbedtls/include/mbedtls/debug.h | 262 + .../src/main/c/mbedtls/include/mbedtls/des.h | 354 + .../src/main/c/mbedtls/include/mbedtls/dhm.h | 1092 + .../src/main/c/mbedtls/include/mbedtls/ecdh.h | 446 + .../main/c/mbedtls/include/mbedtls/ecdsa.h | 626 + .../main/c/mbedtls/include/mbedtls/ecjpake.h | 275 + .../src/main/c/mbedtls/include/mbedtls/ecp.h | 1254 + .../c/mbedtls/include/mbedtls/ecp_internal.h | 297 + .../main/c/mbedtls/include/mbedtls/entropy.h | 287 + .../c/mbedtls/include/mbedtls/entropy_poll.h | 108 + .../main/c/mbedtls/include/mbedtls/error.h | 162 + .../src/main/c/mbedtls/include/mbedtls/gcm.h | 324 + .../main/c/mbedtls/include/mbedtls/havege.h | 80 + .../src/main/c/mbedtls/include/mbedtls/hkdf.h | 139 + .../c/mbedtls/include/mbedtls/hmac_drbg.h | 413 + .../src/main/c/mbedtls/include/mbedtls/md.h | 474 + .../src/main/c/mbedtls/include/mbedtls/md2.h | 304 + .../src/main/c/mbedtls/include/mbedtls/md4.h | 309 + .../src/main/c/mbedtls/include/mbedtls/md5.h | 309 + .../c/mbedtls/include/mbedtls/md_internal.h | 90 + .../include/mbedtls/memory_buffer_alloc.h | 149 + .../src/main/c/mbedtls/include/mbedtls/net.h | 35 + .../c/mbedtls/include/mbedtls/net_sockets.h | 276 + .../main/c/mbedtls/include/mbedtls/nist_kw.h | 182 + .../src/main/c/mbedtls/include/mbedtls/oid.h | 647 + .../main/c/mbedtls/include/mbedtls/padlock.h | 124 + .../src/main/c/mbedtls/include/mbedtls/pem.h | 144 + .../src/main/c/mbedtls/include/mbedtls/pk.h | 879 + .../c/mbedtls/include/mbedtls/pk_internal.h | 140 + .../main/c/mbedtls/include/mbedtls/pkcs11.h | 246 + .../main/c/mbedtls/include/mbedtls/pkcs12.h | 128 + .../main/c/mbedtls/include/mbedtls/pkcs5.h | 107 + .../main/c/mbedtls/include/mbedtls/platform.h | 417 + .../c/mbedtls/include/mbedtls/platform_time.h | 80 + .../c/mbedtls/include/mbedtls/platform_util.h | 194 + .../main/c/mbedtls/include/mbedtls/poly1305.h | 191 + .../main/c/mbedtls/include/mbedtls/psa_util.h | 422 + .../c/mbedtls/include/mbedtls/ripemd160.h | 235 + .../src/main/c/mbedtls/include/mbedtls/rsa.h | 1275 + .../c/mbedtls/include/mbedtls/rsa_internal.h | 224 + .../src/main/c/mbedtls/include/mbedtls/sha1.h | 350 + .../main/c/mbedtls/include/mbedtls/sha256.h | 295 + .../main/c/mbedtls/include/mbedtls/sha512.h | 314 + .../src/main/c/mbedtls/include/mbedtls/ssl.h | 4346 ++ .../c/mbedtls/include/mbedtls/ssl_cache.h | 149 + .../include/mbedtls/ssl_ciphersuites.h | 556 + .../c/mbedtls/include/mbedtls/ssl_cookie.h | 113 + .../c/mbedtls/include/mbedtls/ssl_internal.h | 1304 + .../c/mbedtls/include/mbedtls/ssl_ticket.h | 140 + .../c/mbedtls/include/mbedtls/threading.h | 120 + .../main/c/mbedtls/include/mbedtls/timing.h | 151 + .../main/c/mbedtls/include/mbedtls/version.h | 110 + .../src/main/c/mbedtls/include/mbedtls/x509.h | 359 + .../main/c/mbedtls/include/mbedtls/x509_crl.h | 172 + .../main/c/mbedtls/include/mbedtls/x509_crt.h | 1085 + .../main/c/mbedtls/include/mbedtls/x509_csr.h | 305 + .../src/main/c/mbedtls/include/mbedtls/xtea.h | 137 + .../src/main/c/mbedtls/include/psa/crypto.h | 3782 ++ .../mbedtls/include/psa/crypto_accel_driver.h | 823 + .../c/mbedtls/include/psa/crypto_compat.h | 230 + .../c/mbedtls/include/psa/crypto_config.h | 56 + .../include/psa/crypto_driver_common.h | 54 + .../include/psa/crypto_entropy_driver.h | 108 + .../main/c/mbedtls/include/psa/crypto_extra.h | 654 + .../c/mbedtls/include/psa/crypto_platform.h | 83 + .../c/mbedtls/include/psa/crypto_se_driver.h | 1392 + .../main/c/mbedtls/include/psa/crypto_sizes.h | 747 + .../c/mbedtls/include/psa/crypto_struct.h | 482 + .../main/c/mbedtls/include/psa/crypto_types.h | 395 + .../c/mbedtls/include/psa/crypto_values.h | 1868 + .../src/main/c/mbedtls/library/CMakeLists.txt | 231 + .../app/src/main/c/mbedtls/library/Makefile | 276 + .../app/src/main/c/mbedtls/library/aes.c | 2213 + .../app/src/main/c/mbedtls/library/aesni.c | 464 + .../app/src/main/c/mbedtls/library/arc4.c | 195 + .../app/src/main/c/mbedtls/library/aria.c | 1073 + .../src/main/c/mbedtls/library/asn1parse.c | 481 + .../src/main/c/mbedtls/library/asn1write.c | 480 + .../app/src/main/c/mbedtls/library/base64.c | 287 + .../app/src/main/c/mbedtls/library/bignum.c | 3010 + .../app/src/main/c/mbedtls/library/blowfish.c | 690 + .../app/src/main/c/mbedtls/library/camellia.c | 1108 + .../app/src/main/c/mbedtls/library/ccm.c | 547 + .../app/src/main/c/mbedtls/library/certs.c | 1746 + .../app/src/main/c/mbedtls/library/chacha20.c | 568 + .../src/main/c/mbedtls/library/chachapoly.c | 538 + .../app/src/main/c/mbedtls/library/cipher.c | 1519 + .../src/main/c/mbedtls/library/cipher_wrap.c | 2406 + .../app/src/main/c/mbedtls/library/cmac.c | 1073 + .../app/src/main/c/mbedtls/library/common.h | 53 + .../app/src/main/c/mbedtls/library/ctr_drbg.c | 810 + .../app/src/main/c/mbedtls/library/debug.c | 433 + .../app/src/main/c/mbedtls/library/des.c | 1058 + .../app/src/main/c/mbedtls/library/dhm.c | 735 + .../app/src/main/c/mbedtls/library/ecdh.c | 729 + .../app/src/main/c/mbedtls/library/ecdsa.c | 1002 + .../app/src/main/c/mbedtls/library/ecjpake.c | 1135 + .../app/src/main/c/mbedtls/library/ecp.c | 3505 ++ .../src/main/c/mbedtls/library/ecp_curves.c | 1484 + .../app/src/main/c/mbedtls/library/entropy.c | 724 + .../src/main/c/mbedtls/library/entropy_poll.c | 276 + .../app/src/main/c/mbedtls/library/error.c | 978 + .../app/src/main/c/mbedtls/library/gcm.c | 1015 + .../app/src/main/c/mbedtls/library/havege.c | 237 + .../app/src/main/c/mbedtls/library/hkdf.c | 189 + .../src/main/c/mbedtls/library/hmac_drbg.c | 620 + .../app/src/main/c/mbedtls/library/md.c | 890 + .../app/src/main/c/mbedtls/library/md2.c | 357 + .../app/src/main/c/mbedtls/library/md4.c | 478 + .../app/src/main/c/mbedtls/library/md5.c | 492 + .../c/mbedtls/library/memory_buffer_alloc.c | 744 + .../src/main/c/mbedtls/library/net_sockets.c | 680 + .../app/src/main/c/mbedtls/library/nist_kw.c | 750 + .../app/src/main/c/mbedtls/library/oid.c | 767 + .../app/src/main/c/mbedtls/library/padlock.c | 164 + .../app/src/main/c/mbedtls/library/pem.c | 485 + .../app/src/main/c/mbedtls/library/pk.c | 638 + .../app/src/main/c/mbedtls/library/pk_wrap.c | 1069 + .../app/src/main/c/mbedtls/library/pkcs11.c | 238 + .../app/src/main/c/mbedtls/library/pkcs12.c | 360 + .../app/src/main/c/mbedtls/library/pkcs5.c | 414 + .../app/src/main/c/mbedtls/library/pkparse.c | 1533 + .../app/src/main/c/mbedtls/library/pkwrite.c | 623 + .../app/src/main/c/mbedtls/library/platform.c | 386 + .../main/c/mbedtls/library/platform_util.c | 133 + .../app/src/main/c/mbedtls/library/poly1305.c | 557 + .../src/main/c/mbedtls/library/psa_crypto.c | 6363 +++ .../main/c/mbedtls/library/psa_crypto_core.h | 172 + .../library/psa_crypto_driver_wrappers.c | 940 + .../library/psa_crypto_driver_wrappers.h | 119 + .../c/mbedtls/library/psa_crypto_invasive.h | 77 + .../main/c/mbedtls/library/psa_crypto_its.h | 149 + .../main/c/mbedtls/library/psa_crypto_se.c | 383 + .../main/c/mbedtls/library/psa_crypto_se.h | 187 + .../library/psa_crypto_service_integration.h | 39 + .../library/psa_crypto_slot_management.c | 308 + .../library/psa_crypto_slot_management.h | 125 + .../c/mbedtls/library/psa_crypto_storage.c | 523 + .../c/mbedtls/library/psa_crypto_storage.h | 389 + .../src/main/c/mbedtls/library/psa_its_file.c | 259 + .../src/main/c/mbedtls/library/ripemd160.c | 553 + .../app/src/main/c/mbedtls/library/rsa.c | 2758 + .../src/main/c/mbedtls/library/rsa_internal.c | 486 + .../app/src/main/c/mbedtls/library/sha1.c | 568 + .../app/src/main/c/mbedtls/library/sha256.c | 581 + .../app/src/main/c/mbedtls/library/sha512.c | 673 + .../src/main/c/mbedtls/library/ssl_cache.c | 347 + .../main/c/mbedtls/library/ssl_ciphersuites.c | 2367 + .../app/src/main/c/mbedtls/library/ssl_cli.c | 4542 ++ .../src/main/c/mbedtls/library/ssl_cookie.c | 249 + .../src/main/c/mbedtls/library/ssl_invasive.h | 100 + .../app/src/main/c/mbedtls/library/ssl_msg.c | 6035 ++ .../app/src/main/c/mbedtls/library/ssl_srv.c | 4780 ++ .../src/main/c/mbedtls/library/ssl_ticket.c | 408 + .../app/src/main/c/mbedtls/library/ssl_tls.c | 7676 +++ .../main/c/mbedtls/library/ssl_tls13_keys.c | 349 + .../main/c/mbedtls/library/ssl_tls13_keys.h | 274 + .../src/main/c/mbedtls/library/threading.c | 181 + .../app/src/main/c/mbedtls/library/timing.c | 530 + .../app/src/main/c/mbedtls/library/version.c | 44 + .../main/c/mbedtls/library/version_features.c | 857 + .../app/src/main/c/mbedtls/library/x509.c | 1067 + .../src/main/c/mbedtls/library/x509_create.c | 374 + .../app/src/main/c/mbedtls/library/x509_crl.c | 768 + .../app/src/main/c/mbedtls/library/x509_crt.c | 3399 ++ .../app/src/main/c/mbedtls/library/x509_csr.c | 414 + .../main/c/mbedtls/library/x509write_crt.c | 544 + .../main/c/mbedtls/library/x509write_csr.c | 341 + .../app/src/main/c/mbedtls/library/xtea.c | 271 + Android/Level4/app/src/main/c/mylibc.h | 176 + Android/Level4/app/src/main/c/native-lib.c | 673 + .../src/main/c/rootdetector/rootdetector.h | 69 + .../Level4/app/src/main/c/swcrypto/pbkdf2.h | 29 + Android/Level4/app/src/main/c/syscalls.h | 42 + .../Level4/app/src/main/c/whitebox/Makefile | 47 + .../Level4/app/src/main/c/whitebox/README.md | 30 + .../app/src/main/c/whitebox/RandMat.cpp | 61 + .../Level4/app/src/main/c/whitebox/RandMat.h | 23 + Android/Level4/app/src/main/c/whitebox/aes.c | 139 + Android/Level4/app/src/main/c/whitebox/aes.h | 51 + .../app/src/main/c/whitebox/aes_table.c | 101 + .../app/src/main/c/whitebox/genTables.cpp | 301 + .../Level4/app/src/main/c/whitebox/tables.h | 45559 ++++++++++++++++ .../app/src/main/ic_launcher-playstore.png | Bin 0 -> 36634 bytes .../src/main/java/re/pwnme/MainActivity.java | 138 + .../drawable-v24/ic_launcher_foreground.xml | 34 + .../src/main/res/drawable/btn_background.xml | 9 + .../res/drawable/ic_launcher_background.xml | 74 + .../app/src/main/res/drawable/r2card.jpg | Bin 0 -> 33270 bytes .../app/src/main/res/drawable/r2pay.jpg | Bin 0 -> 33090 bytes .../app/src/main/res/layout/activity_main.xml | 106 + .../res/mipmap-anydpi-v26/ic_launcher.xml | 5 + .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 + .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 1963 bytes .../mipmap-hdpi/ic_launcher_foreground.png | Bin 0 -> 2899 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 3852 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 1257 bytes .../mipmap-mdpi/ic_launcher_foreground.png | Bin 0 -> 1679 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 2381 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 2805 bytes .../mipmap-xhdpi/ic_launcher_foreground.png | Bin 0 -> 4425 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 5638 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 4505 bytes .../mipmap-xxhdpi/ic_launcher_foreground.png | Bin 0 -> 8224 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 9179 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 6681 bytes .../mipmap-xxxhdpi/ic_launcher_foreground.png | Bin 0 -> 13246 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 13676 bytes .../Level4/app/src/main/res/values/colors.xml | 6 + .../res/values/ic_launcher_background.xml | 4 + .../app/src/main/res/values/strings.xml | 3 + .../Level4/app/src/main/res/values/styles.xml | 11 + Android/Level4/build.gradle | 27 + Android/Level4/gradle.properties | 20 + .../Level4/gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 54329 bytes .../gradle/wrapper/gradle-wrapper.properties | 6 + Android/Level4/gradlew | 172 + Android/Level4/gradlew.bat | 84 + Android/Level4/settings.gradle | 2 + 252 files changed, 195569 insertions(+) create mode 100644 Android/Level4/app/.gitignore create mode 100644 Android/Level4/app/build.gradle create mode 100644 Android/Level4/app/proguard-rules.pro create mode 100644 Android/Level4/app/src/androidTest/java/re/pwnme/ExampleInstrumentedTest.java create mode 100644 Android/Level4/app/src/main/AndroidManifest.xml create mode 100644 Android/Level4/app/src/main/c/CMakeLists.txt create mode 100644 Android/Level4/app/src/main/c/arch/arm64-v8a/syscall_arch.h create mode 100644 Android/Level4/app/src/main/c/arch/armeabi-v7a/syscall_arch.h create mode 100644 Android/Level4/app/src/main/c/arch/x86/syscall_arch.h create mode 100644 Android/Level4/app/src/main/c/arch/x86_64/syscall_arch.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/aes.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/aesni.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/arc4.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/aria.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/asn1.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/asn1write.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/base64.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/bignum.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/blowfish.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/bn_mul.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/camellia.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ccm.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/certs.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/chacha20.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/chachapoly.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/check_config.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/cipher.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/cipher_internal.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/cmac.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/compat-1.3.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/config.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/config_psa.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ctr_drbg.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/debug.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/des.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/dhm.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ecdh.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ecdsa.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ecjpake.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ecp.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ecp_internal.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/entropy.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/entropy_poll.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/error.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/gcm.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/havege.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/hkdf.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/hmac_drbg.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/md.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/md2.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/md4.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/md5.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/md_internal.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/memory_buffer_alloc.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/net.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/net_sockets.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/nist_kw.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/oid.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/padlock.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/pem.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/pk.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/pk_internal.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/pkcs11.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/pkcs12.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/pkcs5.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/platform.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/platform_time.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/platform_util.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/poly1305.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/psa_util.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ripemd160.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/rsa.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/rsa_internal.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/sha1.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/sha256.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/sha512.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ssl.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ssl_cache.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ssl_ciphersuites.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ssl_cookie.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ssl_internal.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ssl_ticket.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/threading.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/timing.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/version.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/x509.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/x509_crl.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/x509_crt.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/x509_csr.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/mbedtls/xtea.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/psa/crypto.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/psa/crypto_accel_driver.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/psa/crypto_compat.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/psa/crypto_config.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/psa/crypto_driver_common.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/psa/crypto_entropy_driver.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/psa/crypto_extra.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/psa/crypto_platform.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/psa/crypto_se_driver.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/psa/crypto_sizes.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/psa/crypto_struct.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/psa/crypto_types.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/include/psa/crypto_values.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/CMakeLists.txt create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/Makefile create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/aes.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/aesni.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/arc4.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/aria.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/asn1parse.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/asn1write.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/base64.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/bignum.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/blowfish.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/camellia.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/ccm.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/certs.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/chacha20.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/chachapoly.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/cipher.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/cipher_wrap.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/cmac.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/common.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/ctr_drbg.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/debug.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/des.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/dhm.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/ecdh.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/ecdsa.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/ecjpake.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/ecp.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/ecp_curves.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/entropy.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/entropy_poll.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/error.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/gcm.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/havege.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/hkdf.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/hmac_drbg.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/md.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/md2.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/md4.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/md5.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/memory_buffer_alloc.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/net_sockets.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/nist_kw.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/oid.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/padlock.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/pem.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/pk.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/pk_wrap.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/pkcs11.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/pkcs12.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/pkcs5.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/pkparse.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/pkwrite.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/platform.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/platform_util.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/poly1305.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/psa_crypto.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/psa_crypto_core.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/psa_crypto_driver_wrappers.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/psa_crypto_driver_wrappers.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/psa_crypto_invasive.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/psa_crypto_its.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/psa_crypto_se.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/psa_crypto_se.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/psa_crypto_service_integration.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/psa_crypto_slot_management.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/psa_crypto_slot_management.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/psa_crypto_storage.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/psa_crypto_storage.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/psa_its_file.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/ripemd160.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/rsa.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/rsa_internal.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/sha1.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/sha256.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/sha512.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/ssl_cache.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/ssl_ciphersuites.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/ssl_cli.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/ssl_cookie.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/ssl_invasive.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/ssl_msg.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/ssl_srv.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/ssl_ticket.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/ssl_tls.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/ssl_tls13_keys.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/ssl_tls13_keys.h create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/threading.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/timing.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/version.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/version_features.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/x509.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/x509_create.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/x509_crl.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/x509_crt.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/x509_csr.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/x509write_crt.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/x509write_csr.c create mode 100644 Android/Level4/app/src/main/c/mbedtls/library/xtea.c create mode 100644 Android/Level4/app/src/main/c/mylibc.h create mode 100644 Android/Level4/app/src/main/c/native-lib.c create mode 100644 Android/Level4/app/src/main/c/rootdetector/rootdetector.h create mode 100644 Android/Level4/app/src/main/c/swcrypto/pbkdf2.h create mode 100644 Android/Level4/app/src/main/c/syscalls.h create mode 100644 Android/Level4/app/src/main/c/whitebox/Makefile create mode 100644 Android/Level4/app/src/main/c/whitebox/README.md create mode 100644 Android/Level4/app/src/main/c/whitebox/RandMat.cpp create mode 100644 Android/Level4/app/src/main/c/whitebox/RandMat.h create mode 100644 Android/Level4/app/src/main/c/whitebox/aes.c create mode 100644 Android/Level4/app/src/main/c/whitebox/aes.h create mode 100644 Android/Level4/app/src/main/c/whitebox/aes_table.c create mode 100644 Android/Level4/app/src/main/c/whitebox/genTables.cpp create mode 100644 Android/Level4/app/src/main/c/whitebox/tables.h create mode 100644 Android/Level4/app/src/main/ic_launcher-playstore.png create mode 100644 Android/Level4/app/src/main/java/re/pwnme/MainActivity.java create mode 100644 Android/Level4/app/src/main/res/drawable-v24/ic_launcher_foreground.xml create mode 100644 Android/Level4/app/src/main/res/drawable/btn_background.xml create mode 100644 Android/Level4/app/src/main/res/drawable/ic_launcher_background.xml create mode 100644 Android/Level4/app/src/main/res/drawable/r2card.jpg create mode 100644 Android/Level4/app/src/main/res/drawable/r2pay.jpg create mode 100644 Android/Level4/app/src/main/res/layout/activity_main.xml create mode 100644 Android/Level4/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 Android/Level4/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml create mode 100644 Android/Level4/app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 Android/Level4/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png create mode 100644 Android/Level4/app/src/main/res/mipmap-hdpi/ic_launcher_round.png create mode 100644 Android/Level4/app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 Android/Level4/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png create mode 100644 Android/Level4/app/src/main/res/mipmap-mdpi/ic_launcher_round.png create mode 100644 Android/Level4/app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 Android/Level4/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png create mode 100644 Android/Level4/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png create mode 100644 Android/Level4/app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 Android/Level4/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png create mode 100644 Android/Level4/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 Android/Level4/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 Android/Level4/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png create mode 100644 Android/Level4/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 Android/Level4/app/src/main/res/values/colors.xml create mode 100644 Android/Level4/app/src/main/res/values/ic_launcher_background.xml create mode 100644 Android/Level4/app/src/main/res/values/strings.xml create mode 100644 Android/Level4/app/src/main/res/values/styles.xml create mode 100644 Android/Level4/build.gradle create mode 100644 Android/Level4/gradle.properties create mode 100644 Android/Level4/gradle/wrapper/gradle-wrapper.jar create mode 100644 Android/Level4/gradle/wrapper/gradle-wrapper.properties create mode 100755 Android/Level4/gradlew create mode 100644 Android/Level4/gradlew.bat create mode 100644 Android/Level4/settings.gradle diff --git a/Android/Level4/app/.gitignore b/Android/Level4/app/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/Android/Level4/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/Android/Level4/app/build.gradle b/Android/Level4/app/build.gradle new file mode 100644 index 0000000..9dfcc2d --- /dev/null +++ b/Android/Level4/app/build.gradle @@ -0,0 +1,63 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 29 + buildToolsVersion "29.0.3" + defaultConfig { + applicationId "re.pwnme" + minSdkVersion 21 + targetSdkVersion 29 + versionCode 1 + versionName "1.0" + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + externalNativeBuild { + cmake { + cppFlags "" + } + } + ndk { + abiFilters 'arm64-v8a', 'armeabi-v7a', 'x86_64' + } + } + buildTypes { + release { + debuggable false + // Enables code shrinking, obfuscation, and optimization for only + // your project's release build type. + minifyEnabled true + + // Enables resource shrinking, which is performed by the + // Android Gradle plugin. + shrinkResources true + + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + debug { + // Enables code shrinking, obfuscation, and optimization for only + // your project's release build type. + minifyEnabled true + + // Enables resource shrinking, which is performed by the + // Android Gradle plugin. + shrinkResources true + + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + externalNativeBuild { + cmake { + path "src/main/c/CMakeLists.txt" + version "3.10.2" + } + } +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation 'androidx.appcompat:appcompat:1.0.2' + implementation 'androidx.constraintlayout:constraintlayout:1.1.3' + implementation 'com.scottyab:rootbeer-lib:0.0.8' + testImplementation 'junit:junit:4.12' + androidTestImplementation 'androidx.test:runner:1.1.1' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' +} diff --git a/Android/Level4/app/proguard-rules.pro b/Android/Level4/app/proguard-rules.pro new file mode 100644 index 0000000..c114125 --- /dev/null +++ b/Android/Level4/app/proguard-rules.pro @@ -0,0 +1,31 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +-renamesourcefileattribute SourceFile + +-allowaccessmodification +-dontskipnonpubliclibraryclasses +-dontskipnonpubliclibraryclassmembers + +-keepattributes !LocalVariableTable,!LocalVariableTypeTable + +-optimizationpasses 3 +-overloadaggressively + diff --git a/Android/Level4/app/src/androidTest/java/re/pwnme/ExampleInstrumentedTest.java b/Android/Level4/app/src/androidTest/java/re/pwnme/ExampleInstrumentedTest.java new file mode 100644 index 0000000..a16fcc3 --- /dev/null +++ b/Android/Level4/app/src/androidTest/java/re/pwnme/ExampleInstrumentedTest.java @@ -0,0 +1,27 @@ +package re.pwnme; + +import android.content.Context; + +import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + + assertEquals("re.pwnme", appContext.getPackageName()); + } +} diff --git a/Android/Level4/app/src/main/AndroidManifest.xml b/Android/Level4/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..2c8eea1 --- /dev/null +++ b/Android/Level4/app/src/main/AndroidManifest.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Android/Level4/app/src/main/c/CMakeLists.txt b/Android/Level4/app/src/main/c/CMakeLists.txt new file mode 100644 index 0000000..8d8138c --- /dev/null +++ b/Android/Level4/app/src/main/c/CMakeLists.txt @@ -0,0 +1,96 @@ +# For more information about using CMake with Android Studio, read the +# documentation: https://d.android.com/studio/projects/add-native-code.html + +# Sets the minimum version of CMake required to build the native library. + +cmake_minimum_required(VERSION 3.4.1) + +# Creates and names a library, sets it as either STATIC +# or SHARED, and provides the relative paths to its source code. +# You can define multiple libraries, and CMake builds them for you. +# Gradle automatically packages shared libraries with your APK. +set(CMAKE_VERBOSE_MAKEFILE ON) + +#if(CMAKE_SYSTEM_NAME STREQUAL Linux) +# set(OLLVM_PATH ${CMAKE_HOME_DIRECTORY}/../../../../../ollvm-tll/build/bin_Linux) +#else(CMAKE_SYSTEM_NAME STREQUAL Darwin) +# set(OLLVM_PATH ${CMAKE_HOME_DIRECTORY}/../../../../../ollvm-tll/build/bin_Darwin) +#endif() + +if (UNIX AND NOT APPLE) + set(OLLVM_PATH ${CMAKE_HOME_DIRECTORY}/../../../../../ollvm-tll/build/bin_Linux) +else() + set(OLLVM_PATH ${CMAKE_HOME_DIRECTORY}/../../../../../ollvm-tll/build/bin_Darwin) +endif (UNIX AND NOT APPLE) + +set(OLLVM_C_COMPILER ${OLLVM_PATH}/clang) +set(OLLVM_CXX_COMPILER ${OLLVM_PATH}/clang++) + +set(OLLVM_C_FLAGS "-mllvm -bcf -mllvm -fla -mllvm -sub -mllvm -sobf") + +set(MARKER_PATH ${CMAKE_HOME_DIRECTORY}/marker) +set(MBEDTLS_PATH ${CMAKE_HOME_DIRECTORY}/mbedtls) +set(GO_PATH ${CMAKE_HOME_DIRECTORY}/../../../../injecthash) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OLLVM_C_FLAGS} -isystem /usr/lib/llvm-6.0/lib/clang/6.0.0/include") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OLLVM_C_FLAGS}") +set(CMAKE_C_COMPILER ${OLLVM_C_COMPILER}) +set(CMAKE_CXX_COMPILER ${OLLVM_CXX_COMPILER}) + +#Set flags to detect arm32 bit or arm64 bit for switching between elf structures +if(${ANDROID_ABI} STREQUAL "armeabi-v7a" OR ${ANDROID_ABI} STREQUAL "x86") + add_definitions("-D_32_BIT") +elseif(${ANDROID_ABI} STREQUAL "arm64-v8a" OR ${ANDROID_ABI} STREQUAL "x86_64") + add_definitions("-D_64_BIT") +endif() + +if(${CMAKE_BUILD_TYPE} STREQUAL "Debug" OR ${CMAKE_BUILD_TYPE} STREQUAL "debug" ) + add_definitions("-DDEBUG_ENABLED") + set(BUILD_TYPE "debug") +else() + if (UNIX AND NOT APPLE) + set(BUILD_TYPE "release") + else() + set(BUILD_TYPE "Release") + endif() +endif() + +SET(CMAKE_C_VISIBILITY_PRESET hidden) + +file(GLOB_RECURSE MBEDTLS_SRC ${MBEDTLS_PATH}/library/*.c) + + +add_library( # Sets the name of the library. + native-lib + + # Sets the library as a shared library. + SHARED + + # Provides a relative path to your source file(s). + native-lib.c + ${MBEDTLS_SRC} + whitebox/aes.c) + +target_include_directories(native-lib PRIVATE arch/${ANDROID_ABI} ${MBEDTLS_PATH}/include ) + + +# Links the target library to the log library +# included in the NDK. +if(${BUILD_TYPE} STREQUAL "debug") + find_library( # Sets the name of the path variable. + log-lib + + # Specifies the name of the NDK library that + # you want CMake to locate. + log) + + target_link_libraries( # Specifies the target library. + native-lib + ${log-lib}) +endif() + +add_custom_command( TARGET native-lib + POST_BUILD + COMMAND "${ANDROID_TOOLCHAIN_PREFIX}strip" -R .comment -R .strtab -R .symtab -g -S -d --strip-unneeded ${CMAKE_HOME_DIRECTORY}/../../../build/intermediates/cmake/${BUILD_TYPE}/obj/${ANDROID_ABI}/libnative-lib.so + COMMENT "Stripped native library" + ) diff --git a/Android/Level4/app/src/main/c/arch/arm64-v8a/syscall_arch.h b/Android/Level4/app/src/main/c/arch/arm64-v8a/syscall_arch.h new file mode 100644 index 0000000..04d2832 --- /dev/null +++ b/Android/Level4/app/src/main/c/arch/arm64-v8a/syscall_arch.h @@ -0,0 +1,104 @@ +/*---------------------------------------------------------------------- +Copyright © 2005-2020 Rich Felker, et al. + +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. +----------------------------------------------------------------------*/ +#define __SYSCALL_LL_E(x) (x) +#define __SYSCALL_LL_O(x) (x) + +#define __asm_syscall(...) do { \ + __asm__ __volatile__ ( "svc 0" \ + : "=r"(x0) : __VA_ARGS__ : "memory", "cc"); \ + return x0; \ + } while (0) + +__attribute__((always_inline)) +static inline long __syscall0(long n) +{ + register long x8 __asm__("x8") = n; + register long x0 __asm__("x0"); + __asm_syscall("r"(x8)); +} + +__attribute__((always_inline)) +static inline long __syscall1(long n, long a) +{ + register long x8 __asm__("x8") = n; + register long x0 __asm__("x0") = a; + __asm_syscall("r"(x8), "0"(x0)); +} +__attribute__((always_inline)) +static inline long __syscall2(long n, long a, long b) +{ + register long x8 __asm__("x8") = n; + register long x0 __asm__("x0") = a; + register long x1 __asm__("x1") = b; + __asm_syscall("r"(x8), "0"(x0), "r"(x1)); +} +__attribute__((always_inline)) +static inline long __syscall3(long n, long a, long b, long c) +{ + register long x8 __asm__("x8") = n; + register long x0 __asm__("x0") = a; + register long x1 __asm__("x1") = b; + register long x2 __asm__("x2") = c; + __asm_syscall("r"(x8), "0"(x0), "r"(x1), "r"(x2)); +} +__attribute__((always_inline)) +static inline long __syscall4(long n, long a, long b, long c, long d) +{ + register long x8 __asm__("x8") = n; + register long x0 __asm__("x0") = a; + register long x1 __asm__("x1") = b; + register long x2 __asm__("x2") = c; + register long x3 __asm__("x3") = d; + __asm_syscall("r"(x8), "0"(x0), "r"(x1), "r"(x2), "r"(x3)); +} + +__attribute__((always_inline)) +static inline long __syscall5(long n, long a, long b, long c, long d, long e) +{ + register long x8 __asm__("x8") = n; + register long x0 __asm__("x0") = a; + register long x1 __asm__("x1") = b; + register long x2 __asm__("x2") = c; + register long x3 __asm__("x3") = d; + register long x4 __asm__("x4") = e; + __asm_syscall("r"(x8), "0"(x0), "r"(x1), "r"(x2), "r"(x3), "r"(x4)); +} + +__attribute__((always_inline)) +static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f) +{ + register long x8 __asm__("x8") = n; + register long x0 __asm__("x0") = a; + register long x1 __asm__("x1") = b; + register long x2 __asm__("x2") = c; + register long x3 __asm__("x3") = d; + register long x4 __asm__("x4") = e; + register long x5 __asm__("x5") = f; + __asm_syscall("r"(x8), "0"(x0), "r"(x1), "r"(x2), "r"(x3), "r"(x4), "r"(x5)); +} + +#define VDSO_USEFUL +#define VDSO_CGT_SYM "__kernel_clock_gettime" +#define VDSO_CGT_VER "LINUX_2.6.39" + +#define IPC_64 0 diff --git a/Android/Level4/app/src/main/c/arch/armeabi-v7a/syscall_arch.h b/Android/Level4/app/src/main/c/arch/armeabi-v7a/syscall_arch.h new file mode 100644 index 0000000..7a39495 --- /dev/null +++ b/Android/Level4/app/src/main/c/arch/armeabi-v7a/syscall_arch.h @@ -0,0 +1,138 @@ +/*---------------------------------------------------------------------- +Copyright © 2005-2020 Rich Felker, et al. + +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. +----------------------------------------------------------------------*/ +#define __SYSCALL_LL_E(x) \ +((union { long long ll; long l[2]; }){ .ll = x }).l[0], \ +((union { long long ll; long l[2]; }){ .ll = x }).l[1] +#define __SYSCALL_LL_O(x) 0, __SYSCALL_LL_E((x)) + +#ifdef __thumb__ + +/* Avoid use of r7 in asm constraints when producing thumb code, + * since it's reserved as frame pointer and might not be supported. */ +#define __ASM____R7__ +#define __asm_syscall(...) do { \ + __asm__ __volatile__ ( "mov %1,r7 ; mov r7,%2 ; svc 0 ; mov r7,%1" \ + : "=r"(r0), "=&r"((int){0}) : __VA_ARGS__ : "memory"); \ + return r0; \ + } while (0) + +#else + +#define __ASM____R7__ __asm__("r7") +#define __asm_syscall(...) do { \ + __asm__ __volatile__ ( "svc 0" \ + : "=r"(r0) : __VA_ARGS__ : "memory"); \ + return r0; \ + } while (0) +#endif + +/* For thumb2, we can allow 8-bit immediate syscall numbers, saving a + * register in the above dance around r7. Does not work for thumb1 where + * only movs, not mov, supports immediates, and we can't use movs because + * it doesn't support high regs. */ +#ifdef __thumb2__ +#define R7_OPERAND "rI"(r7) +#else +#define R7_OPERAND "r"(r7) +#endif + +__attribute__((always_inline)) +static inline long __syscall0(long n) +{ + register long r7 __ASM____R7__ = n; + register long r0 __asm__("r0"); + __asm_syscall(R7_OPERAND); +} + +__attribute__((always_inline)) +static inline long __syscall1(long n, long a) +{ + register long r7 __ASM____R7__ = n; + register long r0 __asm__("r0") = a; + __asm_syscall(R7_OPERAND, "0"(r0)); +} + +__attribute__((always_inline)) +static inline long __syscall2(long n, long a, long b) +{ + register long r7 __ASM____R7__ = n; + register long r0 __asm__("r0") = a; + register long r1 __asm__("r1") = b; + __asm_syscall(R7_OPERAND, "0"(r0), "r"(r1)); +} + +__attribute__((always_inline)) +static inline long __syscall3(long n, long a, long b, long c) +{ + register long r7 __ASM____R7__ = n; + register long r0 __asm__("r0") = a; + register long r1 __asm__("r1") = b; + register long r2 __asm__("r2") = c; + __asm_syscall(R7_OPERAND, "0"(r0), "r"(r1), "r"(r2)); +} + +__attribute__((always_inline)) +static inline long __syscall4(long n, long a, long b, long c, long d) +{ + register long r7 __ASM____R7__ = n; + register long r0 __asm__("r0") = a; + register long r1 __asm__("r1") = b; + register long r2 __asm__("r2") = c; + register long r3 __asm__("r3") = d; + __asm_syscall(R7_OPERAND, "0"(r0), "r"(r1), "r"(r2), "r"(r3)); +} + +__attribute__((always_inline)) +static inline long __syscall5(long n, long a, long b, long c, long d, long e) +{ + register long r7 __ASM____R7__ = n; + register long r0 __asm__("r0") = a; + register long r1 __asm__("r1") = b; + register long r2 __asm__("r2") = c; + register long r3 __asm__("r3") = d; + register long r4 __asm__("r4") = e; + __asm_syscall(R7_OPERAND, "0"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4)); +} + +__attribute__((always_inline)) +static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f) +{ + register long r7 __ASM____R7__ = n; + register long r0 __asm__("r0") = a; + register long r1 __asm__("r1") = b; + register long r2 __asm__("r2") = c; + register long r3 __asm__("r3") = d; + register long r4 __asm__("r4") = e; + register long r5 __asm__("r5") = f; + __asm_syscall(R7_OPERAND, "0"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r5)); +} + +#define VDSO_USEFUL +#define VDSO_CGT32_SYM "__vdso_clock_gettime" +#define VDSO_CGT32_VER "LINUX_2.6" +#define VDSO_CGT_SYM "__vdso_clock_gettime64" +#define VDSO_CGT_VER "LINUX_2.6" + +#define SYSCALL_FADVISE_6_ARG + +#define SYSCALL_IPC_BROKEN_MODE diff --git a/Android/Level4/app/src/main/c/arch/x86/syscall_arch.h b/Android/Level4/app/src/main/c/arch/x86/syscall_arch.h new file mode 100644 index 0000000..38cb6cd --- /dev/null +++ b/Android/Level4/app/src/main/c/arch/x86/syscall_arch.h @@ -0,0 +1,186 @@ +//#define __SYSCALL_LL_E(x) (x) +//#define __SYSCALL_LL_O(x) (x) +// +//#define __scc(X) sizeof(1?(X):0ULL) < 8 ? (unsigned long) (X) : (long long) (X) +//typedef long long syscall_arg_t; +// +//static __inline long __syscall0(long long n) +//{ +// unsigned long ret; +// __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n) : "rcx", "r11", "memory"); +// return ret; +//} +// +//static __inline long __syscall1(long long n, long long a1) +//{ +// unsigned long ret; +// __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1) : "rcx", "r11", "memory"); +// return ret; +//} +// +//static __inline long __syscall2(long long n, long long a1, long long a2) +//{ +// unsigned long ret; +// __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2) +// : "rcx", "r11", "memory"); +// return ret; +//} +// +//static __inline long __syscall3(long long n, long long a1, long long a2, long long a3) +//{ +// unsigned long ret; +// __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2), +// "d"(a3) : "rcx", "r11", "memory"); +// return ret; +//} +// +//static __inline long __syscall4(long long n, long long a1, long long a2, long long a3, +// long long a4_) +//{ +// unsigned long ret; +// register long long a4 __asm__("r10") = a4_; +// __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2), +// "d"(a3), "r"(a4): "rcx", "r11", "memory"); +// return ret; +//} +// +//static __inline long __syscall5(long long n, long long a1, long long a2, long long a3, +// long long a4_, long long a5_) +//{ +// unsigned long ret; +// register long long a4 __asm__("r10") = a4_; +// register long long a5 __asm__("r8") = a5_; +// __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2), +// "d"(a3), "r"(a4), "r"(a5) : "rcx", "r11", "memory"); +// return ret; +//} +// +//static __inline long __syscall6(long long n, long long a1, long long a2, long long a3, +// long long a4_, long long a5_, long long a6_) +//{ +// unsigned long ret; +// register long long a4 __asm__("r10") = a4_; +// register long long a5 __asm__("r8") = a5_; +// register long long a6 __asm__("r9") = a6_; +// __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2), +// "d"(a3), "r"(a4), "r"(a5), "r"(a6) : "rcx", "r11", "memory"); +// return ret; +//} +// +//#undef SYS_futimesat +// +//#define SYS_clock_gettime64 SYS_clock_gettime +//#define SYS_clock_settime64 SYS_clock_settime +//#define SYS_clock_adjtime64 SYS_clock_adjtime +//#define SYS_clock_nanosleep_time64 SYS_clock_nanosleep +//#define SYS_timer_gettime64 SYS_timer_gettime +//#define SYS_timer_settime64 SYS_timer_settime +//#define SYS_timerfd_gettime64 SYS_timerfd_gettime +//#define SYS_timerfd_settime64 SYS_timerfd_settime +//#define SYS_utimensat_time64 SYS_utimensat +//#define SYS_pselect6_time64 SYS_pselect6 +//#define SYS_ppoll_time64 SYS_ppoll +//#define SYS_recvmmsg_time64 SYS_recvmmsg +//#define SYS_mq_timedsend_time64 SYS_mq_timedsend +//#define SYS_mq_timedreceive_time64 SYS_mq_timedreceive +//#define SYS_semtimedop_time64 SYS_semtimedop +//#define SYS_rt_sigtimedwait_time64 SYS_rt_sigtimedwait +//#define SYS_futex_time64 SYS_futex +//#define SYS_sched_rr_get_interval_time64 SYS_sched_rr_get_interval +//#define SYS_getrusage_time64 SYS_getrusage +//#define SYS_wait4_time64 SYS_wait4 +// +//#define IPC_64 0 + + +#define __SYSCALL_LL_E(x) \ +((union { long long ll; long l[2]; }){ .ll = x }).l[0], \ +((union { long long ll; long l[2]; }){ .ll = x }).l[1] +#define __SYSCALL_LL_O(x) __SYSCALL_LL_E((x)) + +#if SYSCALL_NO_TLS +#define SYSCALL_INSNS "int $128" +#else +#define SYSCALL_INSNS "call *%%gs:16" +#endif + +#define SYSCALL_INSNS_12 "xchg %%ebx,%%edx ; " SYSCALL_INSNS " ; xchg %%ebx,%%edx" +#define SYSCALL_INSNS_34 "xchg %%ebx,%%edi ; " SYSCALL_INSNS " ; xchg %%ebx,%%edi" + +static inline long __syscall0(long n) +{ + unsigned long __ret; + __asm__ __volatile__ (SYSCALL_INSNS : "=a"(__ret) : "a"(n) : "memory"); + return __ret; +} + +static inline long __syscall1(long n, long a1) +{ + unsigned long __ret; + __asm__ __volatile__ (SYSCALL_INSNS_12 : "=a"(__ret) : "a"(n), "d"(a1) : "memory"); + return __ret; +} + +static inline long __syscall2(long n, long a1, long a2) +{ + unsigned long __ret; + __asm__ __volatile__ (SYSCALL_INSNS_12 : "=a"(__ret) : "a"(n), "d"(a1), "c"(a2) : "memory"); + return __ret; +} + +static inline long __syscall3(long n, long a1, long a2, long a3) +{ + unsigned long __ret; +#if !defined(__PIC__) || !defined(BROKEN_EBX_ASM) + __asm__ __volatile__ (SYSCALL_INSNS : "=a"(__ret) : "a"(n), "b"(a1), "c"(a2), "d"(a3) : "memory"); +#else + __asm__ __volatile__ (SYSCALL_INSNS_34 : "=a"(__ret) : "a"(n), "D"(a1), "c"(a2), "d"(a3) : "memory"); +#endif + return __ret; +} + +static inline long __syscall4(long n, long a1, long a2, long a3, long a4) +{ + unsigned long __ret; +#if !defined(__PIC__) || !defined(BROKEN_EBX_ASM) + __asm__ __volatile__ (SYSCALL_INSNS : "=a"(__ret) : "a"(n), "b"(a1), "c"(a2), "d"(a3), "S"(a4) : "memory"); +#else + __asm__ __volatile__ (SYSCALL_INSNS_34 : "=a"(__ret) : "a"(n), "D"(a1), "c"(a2), "d"(a3), "S"(a4) : "memory"); +#endif + return __ret; +} + +static inline long __syscall5(long n, long a1, long a2, long a3, long a4, long a5) +{ + unsigned long __ret; +#if !defined(__PIC__) || !defined(BROKEN_EBX_ASM) + __asm__ __volatile__ (SYSCALL_INSNS + : "=a"(__ret) : "a"(n), "b"(a1), "c"(a2), "d"(a3), "S"(a4), "D"(a5) : "memory"); +#else + __asm__ __volatile__ ("pushl %2 ; push %%ebx ; mov 4(%%esp),%%ebx ; " SYSCALL_INSNS " ; pop %%ebx ; add $4,%%esp" + : "=a"(__ret) : "a"(n), "g"(a1), "c"(a2), "d"(a3), "S"(a4), "D"(a5) : "memory"); +#endif + return __ret; +} + +static inline long __syscall6(long n, long a1, long a2, long a3, long a4, long a5, long a6) +{ + unsigned long __ret; +#if !defined(__PIC__) || !defined(BROKEN_EBX_ASM) + __asm__ __volatile__ ("pushl %7 ; push %%ebp ; mov 4(%%esp),%%ebp ; " SYSCALL_INSNS " ; pop %%ebp ; add $4,%%esp" + : "=a"(__ret) : "a"(n), "b"(a1), "c"(a2), "d"(a3), "S"(a4), "D"(a5), "g"(a6) : "memory"); +#else + unsigned long a1a6[2] = { a1, a6 }; + __asm__ __volatile__ ("pushl %1 ; push %%ebx ; push %%ebp ; mov 8(%%esp),%%ebx ; mov 4(%%ebx),%%ebp ; mov (%%ebx),%%ebx ; " SYSCALL_INSNS " ; pop %%ebp ; pop %%ebx ; add $4,%%esp" + : "=a"(__ret) : "g"(&a1a6), "a"(n), "c"(a2), "d"(a3), "S"(a4), "D"(a5) : "memory"); +#endif + return __ret; +} + +#define VDSO_USEFUL +#define VDSO_CGT32_SYM "__vdso_clock_gettime" +#define VDSO_CGT32_VER "LINUX_2.6" +#define VDSO_CGT_SYM "__vdso_clock_gettime64" +#define VDSO_CGT_VER "LINUX_2.6" + +#define SYSCALL_USE_SOCKETCALL diff --git a/Android/Level4/app/src/main/c/arch/x86_64/syscall_arch.h b/Android/Level4/app/src/main/c/arch/x86_64/syscall_arch.h new file mode 100644 index 0000000..af25455 --- /dev/null +++ b/Android/Level4/app/src/main/c/arch/x86_64/syscall_arch.h @@ -0,0 +1,70 @@ +#define __SYSCALL_LL_E(x) (x) +#define __SYSCALL_LL_O(x) (x) + +static __inline long __syscall0(long n) +{ + unsigned long ret; + __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n) : "rcx", "r11", "memory"); + return ret; +} + +static __inline long __syscall1(long n, long a1) +{ + unsigned long ret; + __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1) : "rcx", "r11", "memory"); + return ret; +} + +static __inline long __syscall2(long n, long a1, long a2) +{ + unsigned long ret; + __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2) + : "rcx", "r11", "memory"); + return ret; +} + +static __inline long __syscall3(long n, long a1, long a2, long a3) +{ + unsigned long ret; + __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2), + "d"(a3) : "rcx", "r11", "memory"); + return ret; +} + +static __inline long __syscall4(long n, long a1, long a2, long a3, long a4) +{ + unsigned long ret; + register long r10 __asm__("r10") = a4; + __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2), + "d"(a3), "r"(r10): "rcx", "r11", "memory"); + return ret; +} + +static __inline long __syscall5(long n, long a1, long a2, long a3, long a4, long a5) +{ + unsigned long ret; + register long r10 __asm__("r10") = a4; + register long r8 __asm__("r8") = a5; + __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2), + "d"(a3), "r"(r10), "r"(r8) : "rcx", "r11", "memory"); + return ret; +} + +static __inline long __syscall6(long n, long a1, long a2, long a3, long a4, long a5, long a6) +{ + unsigned long ret; + register long r10 __asm__("r10") = a4; + register long r8 __asm__("r8") = a5; + register long r9 __asm__("r9") = a6; + __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2), + "d"(a3), "r"(r10), "r"(r8), "r"(r9) : "rcx", "r11", "memory"); + return ret; +} + +#define VDSO_USEFUL +#define VDSO_CGT_SYM "__vdso_clock_gettime" +#define VDSO_CGT_VER "LINUX_2.6" +#define VDSO_GETCPU_SYM "__vdso_getcpu" +#define VDSO_GETCPU_VER "LINUX_2.6" + +#define IPC_64 0 \ No newline at end of file diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/aes.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/aes.h new file mode 100644 index 0000000..052f47c --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/aes.h @@ -0,0 +1,673 @@ +/** + * \file aes.h + * + * \brief This file contains AES definitions and functions. + * + * The Advanced Encryption Standard (AES) specifies a FIPS-approved + * cryptographic algorithm that can be used to protect electronic + * data. + * + * The AES algorithm is a symmetric block cipher that can + * encrypt and decrypt information. For more information, see + * FIPS Publication 197: Advanced Encryption Standard and + * ISO/IEC 18033-2:2006: Information technology -- Security + * techniques -- Encryption algorithms -- Part 2: Asymmetric + * ciphers. + * + * The AES-XTS block mode is standardized by NIST SP 800-38E + * + * and described in detail by IEEE P1619 + * . + */ + +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_AES_H +#define MBEDTLS_AES_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +/* padlock.c and aesni.c rely on these values! */ +#define MBEDTLS_AES_ENCRYPT 1 /**< AES encryption. */ +#define MBEDTLS_AES_DECRYPT 0 /**< AES decryption. */ + +/* Error codes in range 0x0020-0x0022 */ +#define MBEDTLS_ERR_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */ +#define MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */ + +/* Error codes in range 0x0021-0x0025 */ +#define MBEDTLS_ERR_AES_BAD_INPUT_DATA -0x0021 /**< Invalid input data. */ + +/* MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE is deprecated and should not be used. */ +#define MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE -0x0023 /**< Feature not available. For example, an unsupported AES key size. */ + +/* MBEDTLS_ERR_AES_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_AES_HW_ACCEL_FAILED -0x0025 /**< AES hardware accelerator failed. */ + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_AES_ALT) +// Regular implementation +// + +/** + * \brief The AES context-type definition. + */ +typedef struct mbedtls_aes_context +{ + int nr; /*!< The number of rounds. */ + uint32_t *rk; /*!< AES round keys. */ + uint32_t buf[68]; /*!< Unaligned data buffer. This buffer can + hold 32 extra Bytes, which can be used for + one of the following purposes: +
  • Alignment if VIA padlock is + used.
  • +
  • Simplifying key expansion in the 256-bit + case by generating an extra round key. +
*/ +} +mbedtls_aes_context; + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +/** + * \brief The AES XTS context-type definition. + */ +typedef struct mbedtls_aes_xts_context +{ + mbedtls_aes_context crypt; /*!< The AES context to use for AES block + encryption or decryption. */ + mbedtls_aes_context tweak; /*!< The AES context used for tweak + computation. */ +} mbedtls_aes_xts_context; +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +#else /* MBEDTLS_AES_ALT */ +#include "aes_alt.h" +#endif /* MBEDTLS_AES_ALT */ + +/** + * \brief This function initializes the specified AES context. + * + * It must be the first API called before using + * the context. + * + * \param ctx The AES context to initialize. This must not be \c NULL. + */ +void mbedtls_aes_init( mbedtls_aes_context *ctx ); + +/** + * \brief This function releases and clears the specified AES context. + * + * \param ctx The AES context to clear. + * If this is \c NULL, this function does nothing. + * Otherwise, the context must have been at least initialized. + */ +void mbedtls_aes_free( mbedtls_aes_context *ctx ); + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +/** + * \brief This function initializes the specified AES XTS context. + * + * It must be the first API called before using + * the context. + * + * \param ctx The AES XTS context to initialize. This must not be \c NULL. + */ +void mbedtls_aes_xts_init( mbedtls_aes_xts_context *ctx ); + +/** + * \brief This function releases and clears the specified AES XTS context. + * + * \param ctx The AES XTS context to clear. + * If this is \c NULL, this function does nothing. + * Otherwise, the context must have been at least initialized. + */ +void mbedtls_aes_xts_free( mbedtls_aes_xts_context *ctx ); +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +/** + * \brief This function sets the encryption key. + * + * \param ctx The AES context to which the key should be bound. + * It must be initialized. + * \param key The encryption key. + * This must be a readable buffer of size \p keybits bits. + * \param keybits The size of data passed in bits. Valid options are: + *
  • 128 bits
  • + *
  • 192 bits
  • + *
  • 256 bits
+ * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. + */ +int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits ); + +/** + * \brief This function sets the decryption key. + * + * \param ctx The AES context to which the key should be bound. + * It must be initialized. + * \param key The decryption key. + * This must be a readable buffer of size \p keybits bits. + * \param keybits The size of data passed. Valid options are: + *
  • 128 bits
  • + *
  • 192 bits
  • + *
  • 256 bits
+ * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. + */ +int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits ); + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +/** + * \brief This function prepares an XTS context for encryption and + * sets the encryption key. + * + * \param ctx The AES XTS context to which the key should be bound. + * It must be initialized. + * \param key The encryption key. This is comprised of the XTS key1 + * concatenated with the XTS key2. + * This must be a readable buffer of size \p keybits bits. + * \param keybits The size of \p key passed in bits. Valid options are: + *
  • 256 bits (each of key1 and key2 is a 128-bit key)
  • + *
  • 512 bits (each of key1 and key2 is a 256-bit key)
+ * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. + */ +int mbedtls_aes_xts_setkey_enc( mbedtls_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief This function prepares an XTS context for decryption and + * sets the decryption key. + * + * \param ctx The AES XTS context to which the key should be bound. + * It must be initialized. + * \param key The decryption key. This is comprised of the XTS key1 + * concatenated with the XTS key2. + * This must be a readable buffer of size \p keybits bits. + * \param keybits The size of \p key passed in bits. Valid options are: + *
  • 256 bits (each of key1 and key2 is a 128-bit key)
  • + *
  • 512 bits (each of key1 and key2 is a 256-bit key)
+ * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. + */ +int mbedtls_aes_xts_setkey_dec( mbedtls_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits ); +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +/** + * \brief This function performs an AES single-block encryption or + * decryption operation. + * + * It performs the operation defined in the \p mode parameter + * (encrypt or decrypt), on the input data buffer defined in + * the \p input parameter. + * + * mbedtls_aes_init(), and either mbedtls_aes_setkey_enc() or + * mbedtls_aes_setkey_dec() must be called before the first + * call to this API with the same context. + * + * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT. + * \param input The buffer holding the input data. + * It must be readable and at least \c 16 Bytes long. + * \param output The buffer where the output data will be written. + * It must be writeable and at least \c 16 Bytes long. + + * \return \c 0 on success. + */ +int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief This function performs an AES-CBC encryption or decryption operation + * on full blocks. + * + * It performs the operation defined in the \p mode + * parameter (encrypt/decrypt), on the input data buffer defined in + * the \p input parameter. + * + * It can be called as many times as needed, until all the input + * data is processed. mbedtls_aes_init(), and either + * mbedtls_aes_setkey_enc() or mbedtls_aes_setkey_dec() must be called + * before the first call to this API with the same context. + * + * \note This function operates on full blocks, that is, the input size + * must be a multiple of the AES block size of \c 16 Bytes. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the same function again on the next + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If you need to retain the contents of the IV, you should + * either save it manually or use the cipher module instead. + * + * + * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT. + * \param length The length of the input data in Bytes. This must be a + * multiple of the block size (\c 16 Bytes). + * \param iv Initialization vector (updated after use). + * It must be a readable and writeable buffer of \c 16 Bytes. + * \param input The buffer holding the input data. + * It must be readable and of size \p length Bytes. + * \param output The buffer holding the output data. + * It must be writeable and of size \p length Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH + * on failure. + */ +int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +/** + * \brief This function performs an AES-XTS encryption or decryption + * operation for an entire XTS data unit. + * + * AES-XTS encrypts or decrypts blocks based on their location as + * defined by a data unit number. The data unit number must be + * provided by \p data_unit. + * + * NIST SP 800-38E limits the maximum size of a data unit to 2^20 + * AES blocks. If the data unit is larger than this, this function + * returns #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH. + * + * \param ctx The AES XTS context to use for AES XTS operations. + * It must be initialized and bound to a key. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT. + * \param length The length of a data unit in Bytes. This can be any + * length between 16 bytes and 2^24 bytes inclusive + * (between 1 and 2^20 block cipher blocks). + * \param data_unit The address of the data unit encoded as an array of 16 + * bytes in little-endian format. For disk encryption, this + * is typically the index of the block device sector that + * contains the data. + * \param input The buffer holding the input data (which is an entire + * data unit). This function reads \p length Bytes from \p + * input. + * \param output The buffer holding the output data (which is an entire + * data unit). This function writes \p length Bytes to \p + * output. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH if \p length is + * smaller than an AES block in size (16 Bytes) or if \p + * length is larger than 2^20 blocks (16 MiB). + */ +int mbedtls_aes_crypt_xts( mbedtls_aes_xts_context *ctx, + int mode, + size_t length, + const unsigned char data_unit[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/** + * \brief This function performs an AES-CFB128 encryption or decryption + * operation. + * + * It performs the operation defined in the \p mode + * parameter (encrypt or decrypt), on the input data buffer + * defined in the \p input parameter. + * + * For CFB, you must set up the context with mbedtls_aes_setkey_enc(), + * regardless of whether you are performing an encryption or decryption + * operation, that is, regardless of the \p mode parameter. This is + * because CFB mode uses the same key schedule for encryption and + * decryption. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the same function again on the next + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If you need to retain the contents of the + * IV, you must either save it manually or use the cipher + * module instead. + * + * + * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT. + * \param length The length of the input data in Bytes. + * \param iv_off The offset in IV (updated after use). + * It must point to a valid \c size_t. + * \param iv The initialization vector (updated after use). + * It must be a readable and writeable buffer of \c 16 Bytes. + * \param input The buffer holding the input data. + * It must be readable and of size \p length Bytes. + * \param output The buffer holding the output data. + * It must be writeable and of size \p length Bytes. + * + * \return \c 0 on success. + */ +int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function performs an AES-CFB8 encryption or decryption + * operation. + * + * It performs the operation defined in the \p mode + * parameter (encrypt/decrypt), on the input data buffer defined + * in the \p input parameter. + * + * Due to the nature of CFB, you must use the same key schedule for + * both encryption and decryption operations. Therefore, you must + * use the context initialized with mbedtls_aes_setkey_enc() for + * both #MBEDTLS_AES_ENCRYPT and #MBEDTLS_AES_DECRYPT. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the same function again on the next + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * + * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT + * \param length The length of the input data. + * \param iv The initialization vector (updated after use). + * It must be a readable and writeable buffer of \c 16 Bytes. + * \param input The buffer holding the input data. + * It must be readable and of size \p length Bytes. + * \param output The buffer holding the output data. + * It must be writeable and of size \p length Bytes. + * + * \return \c 0 on success. + */ +int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); +#endif /*MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_OFB) +/** + * \brief This function performs an AES-OFB (Output Feedback Mode) + * encryption or decryption operation. + * + * For OFB, you must set up the context with + * mbedtls_aes_setkey_enc(), regardless of whether you are + * performing an encryption or decryption operation. This is + * because OFB mode uses the same key schedule for encryption and + * decryption. + * + * The OFB operation is identical for encryption or decryption, + * therefore no operation mode needs to be specified. + * + * \note Upon exit, the content of iv, the Initialisation Vector, is + * updated so that you can call the same function again on the next + * block(s) of data and get the same result as if it was encrypted + * in one call. This allows a "streaming" usage, by initialising + * iv_off to 0 before the first call, and preserving its value + * between calls. + * + * For non-streaming use, the iv should be initialised on each call + * to a unique value, and iv_off set to 0 on each call. + * + * If you need to retain the contents of the initialisation vector, + * you must either save it manually or use the cipher module + * instead. + * + * \warning For the OFB mode, the initialisation vector must be unique + * every encryption operation. Reuse of an initialisation vector + * will compromise security. + * + * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. + * \param length The length of the input data. + * \param iv_off The offset in IV (updated after use). + * It must point to a valid \c size_t. + * \param iv The initialization vector (updated after use). + * It must be a readable and writeable buffer of \c 16 Bytes. + * \param input The buffer holding the input data. + * It must be readable and of size \p length Bytes. + * \param output The buffer holding the output data. + * It must be writeable and of size \p length Bytes. + * + * \return \c 0 on success. + */ +int mbedtls_aes_crypt_ofb( mbedtls_aes_context *ctx, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); + +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/** + * \brief This function performs an AES-CTR encryption or decryption + * operation. + * + * This function performs the operation defined in the \p mode + * parameter (encrypt/decrypt), on the input data buffer + * defined in the \p input parameter. + * + * Due to the nature of CTR, you must use the same key schedule + * for both encryption and decryption operations. Therefore, you + * must use the context initialized with mbedtls_aes_setkey_enc() + * for both #MBEDTLS_AES_ENCRYPT and #MBEDTLS_AES_DECRYPT. + * + * \warning You must never reuse a nonce value with the same key. Doing so + * would void the encryption for the two messages encrypted with + * the same nonce and key. + * + * There are two common strategies for managing nonces with CTR: + * + * 1. You can handle everything as a single message processed over + * successive calls to this function. In that case, you want to + * set \p nonce_counter and \p nc_off to 0 for the first call, and + * then preserve the values of \p nonce_counter, \p nc_off and \p + * stream_block across calls to this function as they will be + * updated by this function. + * + * With this strategy, you must not encrypt more than 2**128 + * blocks of data with the same key. + * + * 2. You can encrypt separate messages by dividing the \p + * nonce_counter buffer in two areas: the first one used for a + * per-message nonce, handled by yourself, and the second one + * updated by this function internally. + * + * For example, you might reserve the first 12 bytes for the + * per-message nonce, and the last 4 bytes for internal use. In that + * case, before calling this function on a new message you need to + * set the first 12 bytes of \p nonce_counter to your chosen nonce + * value, the last 4 to 0, and \p nc_off to 0 (which will cause \p + * stream_block to be ignored). That way, you can encrypt at most + * 2**96 messages of up to 2**32 blocks each with the same key. + * + * The per-message nonce (or information sufficient to reconstruct + * it) needs to be communicated with the ciphertext and must be unique. + * The recommended way to ensure uniqueness is to use a message + * counter. An alternative is to generate random nonces, but this + * limits the number of messages that can be securely encrypted: + * for example, with 96-bit random nonces, you should not encrypt + * more than 2**32 messages with the same key. + * + * Note that for both stategies, sizes are measured in blocks and + * that an AES block is 16 bytes. + * + * \warning Upon return, \p stream_block contains sensitive data. Its + * content must not be written to insecure storage and should be + * securely discarded as soon as it's no longer needed. + * + * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. + * \param length The length of the input data. + * \param nc_off The offset in the current \p stream_block, for + * resuming within the current cipher stream. The + * offset pointer should be 0 at the start of a stream. + * It must point to a valid \c size_t. + * \param nonce_counter The 128-bit nonce and counter. + * It must be a readable-writeable buffer of \c 16 Bytes. + * \param stream_block The saved stream block for resuming. This is + * overwritten by the function. + * It must be a readable-writeable buffer of \c 16 Bytes. + * \param input The buffer holding the input data. + * It must be readable and of size \p length Bytes. + * \param output The buffer holding the output data. + * It must be writeable and of size \p length Bytes. + * + * \return \c 0 on success. + */ +int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +/** + * \brief Internal AES block encryption function. This is only + * exposed to allow overriding it using + * \c MBEDTLS_AES_ENCRYPT_ALT. + * + * \param ctx The AES context to use for encryption. + * \param input The plaintext block. + * \param output The output (ciphertext) block. + * + * \return \c 0 on success. + */ +int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ); + +/** + * \brief Internal AES block decryption function. This is only + * exposed to allow overriding it using see + * \c MBEDTLS_AES_DECRYPT_ALT. + * + * \param ctx The AES context to use for decryption. + * \param input The ciphertext block. + * \param output The output (plaintext) block. + * + * \return \c 0 on success. + */ +int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Deprecated internal AES block encryption function + * without return value. + * + * \deprecated Superseded by mbedtls_internal_aes_encrypt() + * + * \param ctx The AES context to use for encryption. + * \param input Plaintext block. + * \param output Output (ciphertext) block. + */ +MBEDTLS_DEPRECATED void mbedtls_aes_encrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ); + +/** + * \brief Deprecated internal AES block decryption function + * without return value. + * + * \deprecated Superseded by mbedtls_internal_aes_decrypt() + * + * \param ctx The AES context to use for decryption. + * \param input Ciphertext block. + * \param output Output (plaintext) block. + */ +MBEDTLS_DEPRECATED void mbedtls_aes_decrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_aes_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* aes.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/aesni.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/aesni.h new file mode 100644 index 0000000..c1d22f5 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/aesni.h @@ -0,0 +1,136 @@ +/** + * \file aesni.h + * + * \brief AES-NI for hardware AES acceleration on some Intel processors + * + * \warning These functions are only for internal use by other library + * functions; you must not call them directly. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_AESNI_H +#define MBEDTLS_AESNI_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/aes.h" + +#define MBEDTLS_AESNI_AES 0x02000000u +#define MBEDTLS_AESNI_CLMUL 0x00000002u + +#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && \ + ( defined(__amd64__) || defined(__x86_64__) ) && \ + ! defined(MBEDTLS_HAVE_X86_64) +#define MBEDTLS_HAVE_X86_64 +#endif + +#if defined(MBEDTLS_HAVE_X86_64) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Internal function to detect the AES-NI feature in CPUs. + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. + * + * \param what The feature to detect + * (MBEDTLS_AESNI_AES or MBEDTLS_AESNI_CLMUL) + * + * \return 1 if CPU has support for the feature, 0 otherwise + */ +int mbedtls_aesni_has_support( unsigned int what ); + +/** + * \brief Internal AES-NI AES-ECB block encryption and decryption + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. + * + * \param ctx AES context + * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT + * \param input 16-byte input block + * \param output 16-byte output block + * + * \return 0 on success (cannot fail) + */ +int mbedtls_aesni_crypt_ecb( mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ); + +/** + * \brief Internal GCM multiplication: c = a * b in GF(2^128) + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. + * + * \param c Result + * \param a First operand + * \param b Second operand + * + * \note Both operands and result are bit strings interpreted as + * elements of GF(2^128) as per the GCM spec. + */ +void mbedtls_aesni_gcm_mult( unsigned char c[16], + const unsigned char a[16], + const unsigned char b[16] ); + +/** + * \brief Internal round key inversion. This function computes + * decryption round keys from the encryption round keys. + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. + * + * \param invkey Round keys for the equivalent inverse cipher + * \param fwdkey Original round keys (for encryption) + * \param nr Number of rounds (that is, number of round keys minus one) + */ +void mbedtls_aesni_inverse_key( unsigned char *invkey, + const unsigned char *fwdkey, + int nr ); + +/** + * \brief Internal key expansion for encryption + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. + * + * \param rk Destination buffer where the round keys are written + * \param key Encryption key + * \param bits Key size in bits (must be 128, 192 or 256) + * + * \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH + */ +int mbedtls_aesni_setkey_enc( unsigned char *rk, + const unsigned char *key, + size_t bits ); + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_HAVE_X86_64 */ + +#endif /* MBEDTLS_AESNI_H */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/arc4.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/arc4.h new file mode 100644 index 0000000..17728f4 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/arc4.h @@ -0,0 +1,144 @@ +/** + * \file arc4.h + * + * \brief The ARCFOUR stream cipher + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers instead. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_ARC4_H +#define MBEDTLS_ARC4_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +/* MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED -0x0019 /**< ARC4 hardware accelerator failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_ARC4_ALT) +// Regular implementation +// + +/** + * \brief ARC4 context structure + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers instead. + * + */ +typedef struct mbedtls_arc4_context +{ + int x; /*!< permutation index */ + int y; /*!< permutation index */ + unsigned char m[256]; /*!< permutation table */ +} +mbedtls_arc4_context; + +#else /* MBEDTLS_ARC4_ALT */ +#include "arc4_alt.h" +#endif /* MBEDTLS_ARC4_ALT */ + +/** + * \brief Initialize ARC4 context + * + * \param ctx ARC4 context to be initialized + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + * + */ +void mbedtls_arc4_init( mbedtls_arc4_context *ctx ); + +/** + * \brief Clear ARC4 context + * + * \param ctx ARC4 context to be cleared + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + * + */ +void mbedtls_arc4_free( mbedtls_arc4_context *ctx ); + +/** + * \brief ARC4 key schedule + * + * \param ctx ARC4 context to be setup + * \param key the secret key + * \param keylen length of the key, in bytes + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + * + */ +void mbedtls_arc4_setup( mbedtls_arc4_context *ctx, const unsigned char *key, + unsigned int keylen ); + +/** + * \brief ARC4 cipher function + * + * \param ctx ARC4 context + * \param length length of the input data + * \param input buffer holding the input data + * \param output buffer for the output data + * + * \return 0 if successful + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + * + */ +int mbedtls_arc4_crypt( mbedtls_arc4_context *ctx, size_t length, const unsigned char *input, + unsigned char *output ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + * + */ +int mbedtls_arc4_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* arc4.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/aria.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/aria.h new file mode 100644 index 0000000..a4b27b3 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/aria.h @@ -0,0 +1,369 @@ +/** + * \file aria.h + * + * \brief ARIA block cipher + * + * The ARIA algorithm is a symmetric block cipher that can encrypt and + * decrypt information. It is defined by the Korean Agency for + * Technology and Standards (KATS) in KS X 1213:2004 (in + * Korean, but see http://210.104.33.10/ARIA/index-e.html in English) + * and also described by the IETF in RFC 5794. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_ARIA_H +#define MBEDTLS_ARIA_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#include "mbedtls/platform_util.h" + +#define MBEDTLS_ARIA_ENCRYPT 1 /**< ARIA encryption. */ +#define MBEDTLS_ARIA_DECRYPT 0 /**< ARIA decryption. */ + +#define MBEDTLS_ARIA_BLOCKSIZE 16 /**< ARIA block size in bytes. */ +#define MBEDTLS_ARIA_MAX_ROUNDS 16 /**< Maxiumum number of rounds in ARIA. */ +#define MBEDTLS_ARIA_MAX_KEYSIZE 32 /**< Maximum size of an ARIA key in bytes. */ + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#define MBEDTLS_ERR_ARIA_INVALID_KEY_LENGTH MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( -0x005C ) +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ +#define MBEDTLS_ERR_ARIA_BAD_INPUT_DATA -0x005C /**< Bad input data. */ + +#define MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH -0x005E /**< Invalid data input length. */ + +/* MBEDTLS_ERR_ARIA_FEATURE_UNAVAILABLE is deprecated and should not be used. + */ +#define MBEDTLS_ERR_ARIA_FEATURE_UNAVAILABLE -0x005A /**< Feature not available. For example, an unsupported ARIA key size. */ + +/* MBEDTLS_ERR_ARIA_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_ARIA_HW_ACCEL_FAILED -0x0058 /**< ARIA hardware accelerator failed. */ + +#if !defined(MBEDTLS_ARIA_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief The ARIA context-type definition. + */ +typedef struct mbedtls_aria_context +{ + unsigned char nr; /*!< The number of rounds (12, 14 or 16) */ + /*! The ARIA round keys. */ + uint32_t rk[MBEDTLS_ARIA_MAX_ROUNDS + 1][MBEDTLS_ARIA_BLOCKSIZE / 4]; +} +mbedtls_aria_context; + +#else /* MBEDTLS_ARIA_ALT */ +#include "aria_alt.h" +#endif /* MBEDTLS_ARIA_ALT */ + +/** + * \brief This function initializes the specified ARIA context. + * + * It must be the first API called before using + * the context. + * + * \param ctx The ARIA context to initialize. This must not be \c NULL. + */ +void mbedtls_aria_init( mbedtls_aria_context *ctx ); + +/** + * \brief This function releases and clears the specified ARIA context. + * + * \param ctx The ARIA context to clear. This may be \c NULL, in which + * case this function returns immediately. If it is not \c NULL, + * it must point to an initialized ARIA context. + */ +void mbedtls_aria_free( mbedtls_aria_context *ctx ); + +/** + * \brief This function sets the encryption key. + * + * \param ctx The ARIA context to which the key should be bound. + * This must be initialized. + * \param key The encryption key. This must be a readable buffer + * of size \p keybits Bits. + * \param keybits The size of \p key in Bits. Valid options are: + *
  • 128 bits
  • + *
  • 192 bits
  • + *
  • 256 bits
+ * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_aria_setkey_enc( mbedtls_aria_context *ctx, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief This function sets the decryption key. + * + * \param ctx The ARIA context to which the key should be bound. + * This must be initialized. + * \param key The decryption key. This must be a readable buffer + * of size \p keybits Bits. + * \param keybits The size of data passed. Valid options are: + *
  • 128 bits
  • + *
  • 192 bits
  • + *
  • 256 bits
+ * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_aria_setkey_dec( mbedtls_aria_context *ctx, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief This function performs an ARIA single-block encryption or + * decryption operation. + * + * It performs encryption or decryption (depending on whether + * the key was set for encryption on decryption) on the input + * data buffer defined in the \p input parameter. + * + * mbedtls_aria_init(), and either mbedtls_aria_setkey_enc() or + * mbedtls_aria_setkey_dec() must be called before the first + * call to this API with the same context. + * + * \param ctx The ARIA context to use for encryption or decryption. + * This must be initialized and bound to a key. + * \param input The 16-Byte buffer holding the input data. + * \param output The 16-Byte buffer holding the output data. + + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_aria_crypt_ecb( mbedtls_aria_context *ctx, + const unsigned char input[MBEDTLS_ARIA_BLOCKSIZE], + unsigned char output[MBEDTLS_ARIA_BLOCKSIZE] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief This function performs an ARIA-CBC encryption or decryption operation + * on full blocks. + * + * It performs the operation defined in the \p mode + * parameter (encrypt/decrypt), on the input data buffer defined in + * the \p input parameter. + * + * It can be called as many times as needed, until all the input + * data is processed. mbedtls_aria_init(), and either + * mbedtls_aria_setkey_enc() or mbedtls_aria_setkey_dec() must be called + * before the first call to this API with the same context. + * + * \note This function operates on aligned blocks, that is, the input size + * must be a multiple of the ARIA block size of 16 Bytes. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the same function again on the next + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If you need to retain the contents of the IV, you should + * either save it manually or use the cipher module instead. + * + * + * \param ctx The ARIA context to use for encryption or decryption. + * This must be initialized and bound to a key. + * \param mode The mode of operation. This must be either + * #MBEDTLS_ARIA_ENCRYPT for encryption, or + * #MBEDTLS_ARIA_DECRYPT for decryption. + * \param length The length of the input data in Bytes. This must be a + * multiple of the block size (16 Bytes). + * \param iv Initialization vector (updated after use). + * This must be a readable buffer of size 16 Bytes. + * \param input The buffer holding the input data. This must + * be a readable buffer of length \p length Bytes. + * \param output The buffer holding the output data. This must + * be a writable buffer of length \p length Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_aria_crypt_cbc( mbedtls_aria_context *ctx, + int mode, + size_t length, + unsigned char iv[MBEDTLS_ARIA_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/** + * \brief This function performs an ARIA-CFB128 encryption or decryption + * operation. + * + * It performs the operation defined in the \p mode + * parameter (encrypt or decrypt), on the input data buffer + * defined in the \p input parameter. + * + * For CFB, you must set up the context with mbedtls_aria_setkey_enc(), + * regardless of whether you are performing an encryption or decryption + * operation, that is, regardless of the \p mode parameter. This is + * because CFB mode uses the same key schedule for encryption and + * decryption. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the same function again on the next + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If you need to retain the contents of the + * IV, you must either save it manually or use the cipher + * module instead. + * + * + * \param ctx The ARIA context to use for encryption or decryption. + * This must be initialized and bound to a key. + * \param mode The mode of operation. This must be either + * #MBEDTLS_ARIA_ENCRYPT for encryption, or + * #MBEDTLS_ARIA_DECRYPT for decryption. + * \param length The length of the input data \p input in Bytes. + * \param iv_off The offset in IV (updated after use). + * This must not be larger than 15. + * \param iv The initialization vector (updated after use). + * This must be a readable buffer of size 16 Bytes. + * \param input The buffer holding the input data. This must + * be a readable buffer of length \p length Bytes. + * \param output The buffer holding the output data. This must + * be a writable buffer of length \p length Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_aria_crypt_cfb128( mbedtls_aria_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[MBEDTLS_ARIA_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/** + * \brief This function performs an ARIA-CTR encryption or decryption + * operation. + * + * This function performs the operation defined in the \p mode + * parameter (encrypt/decrypt), on the input data buffer + * defined in the \p input parameter. + * + * Due to the nature of CTR, you must use the same key schedule + * for both encryption and decryption operations. Therefore, you + * must use the context initialized with mbedtls_aria_setkey_enc() + * for both #MBEDTLS_ARIA_ENCRYPT and #MBEDTLS_ARIA_DECRYPT. + * + * \warning You must never reuse a nonce value with the same key. Doing so + * would void the encryption for the two messages encrypted with + * the same nonce and key. + * + * There are two common strategies for managing nonces with CTR: + * + * 1. You can handle everything as a single message processed over + * successive calls to this function. In that case, you want to + * set \p nonce_counter and \p nc_off to 0 for the first call, and + * then preserve the values of \p nonce_counter, \p nc_off and \p + * stream_block across calls to this function as they will be + * updated by this function. + * + * With this strategy, you must not encrypt more than 2**128 + * blocks of data with the same key. + * + * 2. You can encrypt separate messages by dividing the \p + * nonce_counter buffer in two areas: the first one used for a + * per-message nonce, handled by yourself, and the second one + * updated by this function internally. + * + * For example, you might reserve the first 12 bytes for the + * per-message nonce, and the last 4 bytes for internal use. In that + * case, before calling this function on a new message you need to + * set the first 12 bytes of \p nonce_counter to your chosen nonce + * value, the last 4 to 0, and \p nc_off to 0 (which will cause \p + * stream_block to be ignored). That way, you can encrypt at most + * 2**96 messages of up to 2**32 blocks each with the same key. + * + * The per-message nonce (or information sufficient to reconstruct + * it) needs to be communicated with the ciphertext and must be unique. + * The recommended way to ensure uniqueness is to use a message + * counter. An alternative is to generate random nonces, but this + * limits the number of messages that can be securely encrypted: + * for example, with 96-bit random nonces, you should not encrypt + * more than 2**32 messages with the same key. + * + * Note that for both stategies, sizes are measured in blocks and + * that an ARIA block is 16 bytes. + * + * \warning Upon return, \p stream_block contains sensitive data. Its + * content must not be written to insecure storage and should be + * securely discarded as soon as it's no longer needed. + * + * \param ctx The ARIA context to use for encryption or decryption. + * This must be initialized and bound to a key. + * \param length The length of the input data \p input in Bytes. + * \param nc_off The offset in Bytes in the current \p stream_block, + * for resuming within the current cipher stream. The + * offset pointer should be \c 0 at the start of a + * stream. This must not be larger than \c 15 Bytes. + * \param nonce_counter The 128-bit nonce and counter. This must point to + * a read/write buffer of length \c 16 bytes. + * \param stream_block The saved stream block for resuming. This must + * point to a read/write buffer of length \c 16 bytes. + * This is overwritten by the function. + * \param input The buffer holding the input data. This must + * be a readable buffer of length \p length Bytes. + * \param output The buffer holding the output data. This must + * be a writable buffer of length \p length Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_aria_crypt_ctr( mbedtls_aria_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[MBEDTLS_ARIA_BLOCKSIZE], + unsigned char stream_block[MBEDTLS_ARIA_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine. + * + * \return \c 0 on success, or \c 1 on failure. + */ +int mbedtls_aria_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* aria.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/asn1.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/asn1.h new file mode 100644 index 0000000..6b79196 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/asn1.h @@ -0,0 +1,607 @@ +/** + * \file asn1.h + * + * \brief Generic ASN.1 parsing + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_ASN1_H +#define MBEDTLS_ASN1_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +#if defined(MBEDTLS_BIGNUM_C) +#include "mbedtls/bignum.h" +#endif + +/** + * \addtogroup asn1_module + * \{ + */ + +/** + * \name ASN1 Error codes + * These error codes are OR'ed to X509 error codes for + * higher error granularity. + * ASN1 is a standard to specify data structures. + * \{ + */ +#define MBEDTLS_ERR_ASN1_OUT_OF_DATA -0x0060 /**< Out of data when parsing an ASN1 data structure. */ +#define MBEDTLS_ERR_ASN1_UNEXPECTED_TAG -0x0062 /**< ASN1 tag was of an unexpected value. */ +#define MBEDTLS_ERR_ASN1_INVALID_LENGTH -0x0064 /**< Error when trying to determine the length or invalid length. */ +#define MBEDTLS_ERR_ASN1_LENGTH_MISMATCH -0x0066 /**< Actual length differs from expected length. */ +#define MBEDTLS_ERR_ASN1_INVALID_DATA -0x0068 /**< Data is invalid. */ +#define MBEDTLS_ERR_ASN1_ALLOC_FAILED -0x006A /**< Memory allocation failed */ +#define MBEDTLS_ERR_ASN1_BUF_TOO_SMALL -0x006C /**< Buffer too small when writing ASN.1 data structure. */ + +/* \} name */ + +/** + * \name DER constants + * These constants comply with the DER encoded ASN.1 type tags. + * DER encoding uses hexadecimal representation. + * An example DER sequence is:\n + * - 0x02 -- tag indicating INTEGER + * - 0x01 -- length in octets + * - 0x05 -- value + * Such sequences are typically read into \c ::mbedtls_x509_buf. + * \{ + */ +#define MBEDTLS_ASN1_BOOLEAN 0x01 +#define MBEDTLS_ASN1_INTEGER 0x02 +#define MBEDTLS_ASN1_BIT_STRING 0x03 +#define MBEDTLS_ASN1_OCTET_STRING 0x04 +#define MBEDTLS_ASN1_NULL 0x05 +#define MBEDTLS_ASN1_OID 0x06 +#define MBEDTLS_ASN1_ENUMERATED 0x0A +#define MBEDTLS_ASN1_UTF8_STRING 0x0C +#define MBEDTLS_ASN1_SEQUENCE 0x10 +#define MBEDTLS_ASN1_SET 0x11 +#define MBEDTLS_ASN1_PRINTABLE_STRING 0x13 +#define MBEDTLS_ASN1_T61_STRING 0x14 +#define MBEDTLS_ASN1_IA5_STRING 0x16 +#define MBEDTLS_ASN1_UTC_TIME 0x17 +#define MBEDTLS_ASN1_GENERALIZED_TIME 0x18 +#define MBEDTLS_ASN1_UNIVERSAL_STRING 0x1C +#define MBEDTLS_ASN1_BMP_STRING 0x1E +#define MBEDTLS_ASN1_PRIMITIVE 0x00 +#define MBEDTLS_ASN1_CONSTRUCTED 0x20 +#define MBEDTLS_ASN1_CONTEXT_SPECIFIC 0x80 + +/* Slightly smaller way to check if tag is a string tag + * compared to canonical implementation. */ +#define MBEDTLS_ASN1_IS_STRING_TAG( tag ) \ + ( ( tag ) < 32u && ( \ + ( ( 1u << ( tag ) ) & ( ( 1u << MBEDTLS_ASN1_BMP_STRING ) | \ + ( 1u << MBEDTLS_ASN1_UTF8_STRING ) | \ + ( 1u << MBEDTLS_ASN1_T61_STRING ) | \ + ( 1u << MBEDTLS_ASN1_IA5_STRING ) | \ + ( 1u << MBEDTLS_ASN1_UNIVERSAL_STRING ) | \ + ( 1u << MBEDTLS_ASN1_PRINTABLE_STRING ) | \ + ( 1u << MBEDTLS_ASN1_BIT_STRING ) ) ) != 0 ) ) + +/* + * Bit masks for each of the components of an ASN.1 tag as specified in + * ITU X.690 (08/2015), section 8.1 "General rules for encoding", + * paragraph 8.1.2.2: + * + * Bit 8 7 6 5 1 + * +-------+-----+------------+ + * | Class | P/C | Tag number | + * +-------+-----+------------+ + */ +#define MBEDTLS_ASN1_TAG_CLASS_MASK 0xC0 +#define MBEDTLS_ASN1_TAG_PC_MASK 0x20 +#define MBEDTLS_ASN1_TAG_VALUE_MASK 0x1F + +/* \} name */ +/* \} addtogroup asn1_module */ + +/** Returns the size of the binary string, without the trailing \\0 */ +#define MBEDTLS_OID_SIZE(x) (sizeof(x) - 1) + +/** + * Compares an mbedtls_asn1_buf structure to a reference OID. + * + * Only works for 'defined' oid_str values (MBEDTLS_OID_HMAC_SHA1), you cannot use a + * 'unsigned char *oid' here! + */ +#define MBEDTLS_OID_CMP(oid_str, oid_buf) \ + ( ( MBEDTLS_OID_SIZE(oid_str) != (oid_buf)->len ) || \ + memcmp( (oid_str), (oid_buf)->p, (oid_buf)->len) != 0 ) + +#define MBEDTLS_OID_CMP_RAW(oid_str, oid_buf, oid_buf_len) \ + ( ( MBEDTLS_OID_SIZE(oid_str) != (oid_buf_len) ) || \ + memcmp( (oid_str), (oid_buf), (oid_buf_len) ) != 0 ) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \name Functions to parse ASN.1 data structures + * \{ + */ + +/** + * Type-length-value structure that allows for ASN1 using DER. + */ +typedef struct mbedtls_asn1_buf +{ + int tag; /**< ASN1 type, e.g. MBEDTLS_ASN1_UTF8_STRING. */ + size_t len; /**< ASN1 length, in octets. */ + unsigned char *p; /**< ASN1 data, e.g. in ASCII. */ +} +mbedtls_asn1_buf; + +/** + * Container for ASN1 bit strings. + */ +typedef struct mbedtls_asn1_bitstring +{ + size_t len; /**< ASN1 length, in octets. */ + unsigned char unused_bits; /**< Number of unused bits at the end of the string */ + unsigned char *p; /**< Raw ASN1 data for the bit string */ +} +mbedtls_asn1_bitstring; + +/** + * Container for a sequence of ASN.1 items + */ +typedef struct mbedtls_asn1_sequence +{ + mbedtls_asn1_buf buf; /**< Buffer containing the given ASN.1 item. */ + struct mbedtls_asn1_sequence *next; /**< The next entry in the sequence. */ +} +mbedtls_asn1_sequence; + +/** + * Container for a sequence or list of 'named' ASN.1 data items + */ +typedef struct mbedtls_asn1_named_data +{ + mbedtls_asn1_buf oid; /**< The object identifier. */ + mbedtls_asn1_buf val; /**< The named value. */ + struct mbedtls_asn1_named_data *next; /**< The next entry in the sequence. */ + unsigned char next_merged; /**< Merge next item into the current one? */ +} +mbedtls_asn1_named_data; + +/** + * \brief Get the length of an ASN.1 element. + * Updates the pointer to immediately behind the length. + * + * \param p On entry, \c *p points to the first byte of the length, + * i.e. immediately after the tag. + * On successful completion, \c *p points to the first byte + * after the length, i.e. the first byte of the content. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param len On successful completion, \c *len contains the length + * read from the ASN.1 input. + * + * \return 0 if successful. + * \return #MBEDTLS_ERR_ASN1_OUT_OF_DATA if the ASN.1 element + * would end beyond \p end. + * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the length is unparseable. + */ +int mbedtls_asn1_get_len( unsigned char **p, + const unsigned char *end, + size_t *len ); + +/** + * \brief Get the tag and length of the element. + * Check for the requested tag. + * Updates the pointer to immediately behind the tag and length. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p points to the first byte + * after the length, i.e. the first byte of the content. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param len On successful completion, \c *len contains the length + * read from the ASN.1 input. + * \param tag The expected tag. + * + * \return 0 if successful. + * \return #MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if the data does not start + * with the requested tag. + * \return #MBEDTLS_ERR_ASN1_OUT_OF_DATA if the ASN.1 element + * would end beyond \p end. + * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the length is unparseable. + */ +int mbedtls_asn1_get_tag( unsigned char **p, + const unsigned char *end, + size_t *len, int tag ); + +/** + * \brief Retrieve a boolean ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p points to the first byte + * beyond the ASN.1 element. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param val On success, the parsed value (\c 0 or \c 1). + * + * \return 0 if successful. + * \return An ASN.1 error code if the input does not start with + * a valid ASN.1 BOOLEAN. + */ +int mbedtls_asn1_get_bool( unsigned char **p, + const unsigned char *end, + int *val ); + +/** + * \brief Retrieve an integer ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p points to the first byte + * beyond the ASN.1 element. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param val On success, the parsed value. + * + * \return 0 if successful. + * \return An ASN.1 error code if the input does not start with + * a valid ASN.1 INTEGER. + * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does + * not fit in an \c int. + */ +int mbedtls_asn1_get_int( unsigned char **p, + const unsigned char *end, + int *val ); + +/** + * \brief Retrieve an enumerated ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p points to the first byte + * beyond the ASN.1 element. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param val On success, the parsed value. + * + * \return 0 if successful. + * \return An ASN.1 error code if the input does not start with + * a valid ASN.1 ENUMERATED. + * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does + * not fit in an \c int. + */ +int mbedtls_asn1_get_enum( unsigned char **p, + const unsigned char *end, + int *val ); + +/** + * \brief Retrieve a bitstring ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p is equal to \p end. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param bs On success, ::mbedtls_asn1_bitstring information about + * the parsed value. + * + * \return 0 if successful. + * \return #MBEDTLS_ERR_ASN1_LENGTH_MISMATCH if the input contains + * extra data after a valid BIT STRING. + * \return An ASN.1 error code if the input does not start with + * a valid ASN.1 BIT STRING. + */ +int mbedtls_asn1_get_bitstring( unsigned char **p, const unsigned char *end, + mbedtls_asn1_bitstring *bs ); + +/** + * \brief Retrieve a bitstring ASN.1 tag without unused bits and its + * value. + * Updates the pointer to the beginning of the bit/octet string. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p points to the first byte + * of the content of the BIT STRING. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param len On success, \c *len is the length of the content in bytes. + * + * \return 0 if successful. + * \return #MBEDTLS_ERR_ASN1_INVALID_DATA if the input starts with + * a valid BIT STRING with a nonzero number of unused bits. + * \return An ASN.1 error code if the input does not start with + * a valid ASN.1 BIT STRING. + */ +int mbedtls_asn1_get_bitstring_null( unsigned char **p, + const unsigned char *end, + size_t *len ); + +/** + * \brief Parses and splits an ASN.1 "SEQUENCE OF ". + * Updates the pointer to immediately behind the full sequence tag. + * + * This function allocates memory for the sequence elements. You can free + * the allocated memory with mbedtls_asn1_sequence_free(). + * + * \note On error, this function may return a partial list in \p cur. + * You must set `cur->next = NULL` before calling this function! + * Otherwise it is impossible to distinguish a previously non-null + * pointer from a pointer to an object allocated by this function. + * + * \note If the sequence is empty, this function does not modify + * \c *cur. If the sequence is valid and non-empty, this + * function sets `cur->buf.tag` to \p tag. This allows + * callers to distinguish between an empty sequence and + * a one-element sequence. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p is equal to \p end. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param cur A ::mbedtls_asn1_sequence which this function fills. + * When this function returns, \c *cur is the head of a linked + * list. Each node in this list is allocated with + * mbedtls_calloc() apart from \p cur itself, and should + * therefore be freed with mbedtls_free(). + * The list describes the content of the sequence. + * The head of the list (i.e. \c *cur itself) describes the + * first element, `*cur->next` describes the second element, etc. + * For each element, `buf.tag == tag`, `buf.len` is the length + * of the content of the content of the element, and `buf.p` + * points to the first byte of the content (i.e. immediately + * past the length of the element). + * Note that list elements may be allocated even on error. + * \param tag Each element of the sequence must have this tag. + * + * \return 0 if successful. + * \return #MBEDTLS_ERR_ASN1_LENGTH_MISMATCH if the input contains + * extra data after a valid SEQUENCE OF \p tag. + * \return #MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if the input starts with + * an ASN.1 SEQUENCE in which an element has a tag that + * is different from \p tag. + * \return #MBEDTLS_ERR_ASN1_ALLOC_FAILED if a memory allocation failed. + * \return An ASN.1 error code if the input does not start with + * a valid ASN.1 SEQUENCE. + */ +int mbedtls_asn1_get_sequence_of( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_sequence *cur, + int tag ); +/** + * \brief Free a heap-allocated linked list presentation of + * an ASN.1 sequence, including the first element. + * + * There are two common ways to manage the memory used for the representation + * of a parsed ASN.1 sequence: + * - Allocate a head node `mbedtls_asn1_sequence *head` with mbedtls_calloc(). + * Pass this node as the `cur` argument to mbedtls_asn1_get_sequence_of(). + * When you have finished processing the sequence, + * call mbedtls_asn1_sequence_free() on `head`. + * - Allocate a head node `mbedtls_asn1_sequence *head` in any manner, + * for example on the stack. Make sure that `head->next == NULL`. + * Pass `head` as the `cur` argument to mbedtls_asn1_get_sequence_of(). + * When you have finished processing the sequence, + * call mbedtls_asn1_sequence_free() on `head->cur`, + * then free `head` itself in the appropriate manner. + * + * \param seq The address of the first sequence component. This may + * be \c NULL, in which case this functions returns + * immediately. + */ +void mbedtls_asn1_sequence_free( mbedtls_asn1_sequence *seq ); + +/** + * \brief Traverse an ASN.1 SEQUENCE container and + * call a callback for each entry. + * + * This function checks that the input is a SEQUENCE of elements that + * each have a "must" tag, and calls a callback function on the elements + * that have a "may" tag. + * + * For example, to validate that the input is a SEQUENCE of `tag1` and call + * `cb` on each element, use + * ``` + * mbedtls_asn1_traverse_sequence_of(&p, end, 0xff, tag1, 0, 0, cb, ctx); + * ``` + * + * To validate that the input is a SEQUENCE of ANY and call `cb` on + * each element, use + * ``` + * mbedtls_asn1_traverse_sequence_of(&p, end, 0, 0, 0, 0, cb, ctx); + * ``` + * + * To validate that the input is a SEQUENCE of CHOICE {NULL, OCTET STRING} + * and call `cb` on each element that is an OCTET STRING, use + * ``` + * mbedtls_asn1_traverse_sequence_of(&p, end, 0xfe, 0x04, 0xff, 0x04, cb, ctx); + * ``` + * + * The callback is called on the elements with a "may" tag from left to + * right. If the input is not a valid SEQUENCE of elements with a "must" tag, + * the callback is called on the elements up to the leftmost point where + * the input is invalid. + * + * \warning This function is still experimental and may change + * at any time. + * + * \param p The address of the pointer to the beginning of + * the ASN.1 SEQUENCE header. This is updated to + * point to the end of the ASN.1 SEQUENCE container + * on a successful invocation. + * \param end The end of the ASN.1 SEQUENCE container. + * \param tag_must_mask A mask to be applied to the ASN.1 tags found within + * the SEQUENCE before comparing to \p tag_must_value. + * \param tag_must_val The required value of each ASN.1 tag found in the + * SEQUENCE, after masking with \p tag_must_mask. + * Mismatching tags lead to an error. + * For example, a value of \c 0 for both \p tag_must_mask + * and \p tag_must_val means that every tag is allowed, + * while a value of \c 0xFF for \p tag_must_mask means + * that \p tag_must_val is the only allowed tag. + * \param tag_may_mask A mask to be applied to the ASN.1 tags found within + * the SEQUENCE before comparing to \p tag_may_value. + * \param tag_may_val The desired value of each ASN.1 tag found in the + * SEQUENCE, after masking with \p tag_may_mask. + * Mismatching tags will be silently ignored. + * For example, a value of \c 0 for \p tag_may_mask and + * \p tag_may_val means that any tag will be considered, + * while a value of \c 0xFF for \p tag_may_mask means + * that all tags with value different from \p tag_may_val + * will be ignored. + * \param cb The callback to trigger for each component + * in the ASN.1 SEQUENCE that matches \p tag_may_val. + * The callback function is called with the following + * parameters: + * - \p ctx. + * - The tag of the current element. + * - A pointer to the start of the current element's + * content inside the input. + * - The length of the content of the current element. + * If the callback returns a non-zero value, + * the function stops immediately, + * forwarding the callback's return value. + * \param ctx The context to be passed to the callback \p cb. + * + * \return \c 0 if successful the entire ASN.1 SEQUENCE + * was traversed without parsing or callback errors. + * \return #MBEDTLS_ERR_ASN1_LENGTH_MISMATCH if the input + * contains extra data after a valid SEQUENCE + * of elements with an accepted tag. + * \return #MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if the input starts + * with an ASN.1 SEQUENCE in which an element has a tag + * that is not accepted. + * \return An ASN.1 error code if the input does not start with + * a valid ASN.1 SEQUENCE. + * \return A non-zero error code forwarded from the callback + * \p cb in case the latter returns a non-zero value. + */ +int mbedtls_asn1_traverse_sequence_of( + unsigned char **p, + const unsigned char *end, + unsigned char tag_must_mask, unsigned char tag_must_val, + unsigned char tag_may_mask, unsigned char tag_may_val, + int (*cb)( void *ctx, int tag, + unsigned char* start, size_t len ), + void *ctx ); + +#if defined(MBEDTLS_BIGNUM_C) +/** + * \brief Retrieve an integer ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p points to the first byte + * beyond the ASN.1 element. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param X On success, the parsed value. + * + * \return 0 if successful. + * \return An ASN.1 error code if the input does not start with + * a valid ASN.1 INTEGER. + * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does + * not fit in an \c int. + * \return An MPI error code if the parsed value is too large. + */ +int mbedtls_asn1_get_mpi( unsigned char **p, + const unsigned char *end, + mbedtls_mpi *X ); +#endif /* MBEDTLS_BIGNUM_C */ + +/** + * \brief Retrieve an AlgorithmIdentifier ASN.1 sequence. + * Updates the pointer to immediately behind the full + * AlgorithmIdentifier. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p points to the first byte + * beyond the AlgorithmIdentifier element. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param alg The buffer to receive the OID. + * \param params The buffer to receive the parameters. + * This is zeroized if there are no parameters. + * + * \return 0 if successful or a specific ASN.1 or MPI error code. + */ +int mbedtls_asn1_get_alg( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params ); + +/** + * \brief Retrieve an AlgorithmIdentifier ASN.1 sequence with NULL or no + * params. + * Updates the pointer to immediately behind the full + * AlgorithmIdentifier. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p points to the first byte + * beyond the AlgorithmIdentifier element. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param alg The buffer to receive the OID. + * + * \return 0 if successful or a specific ASN.1 or MPI error code. + */ +int mbedtls_asn1_get_alg_null( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_buf *alg ); + +/** + * \brief Find a specific named_data entry in a sequence or list based on + * the OID. + * + * \param list The list to seek through + * \param oid The OID to look for + * \param len Size of the OID + * + * \return NULL if not found, or a pointer to the existing entry. + */ +mbedtls_asn1_named_data *mbedtls_asn1_find_named_data( mbedtls_asn1_named_data *list, + const char *oid, size_t len ); + +/** + * \brief Free a mbedtls_asn1_named_data entry + * + * \param entry The named data entry to free. + * This function calls mbedtls_free() on + * `entry->oid.p` and `entry->val.p`. + */ +void mbedtls_asn1_free_named_data( mbedtls_asn1_named_data *entry ); + +/** + * \brief Free all entries in a mbedtls_asn1_named_data list. + * + * \param head Pointer to the head of the list of named data entries to free. + * This function calls mbedtls_asn1_free_named_data() and + * mbedtls_free() on each list element and + * sets \c *head to \c NULL. + */ +void mbedtls_asn1_free_named_data_list( mbedtls_asn1_named_data **head ); + +#ifdef __cplusplus +} +#endif + +#endif /* asn1.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/asn1write.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/asn1write.h new file mode 100644 index 0000000..44afae0 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/asn1write.h @@ -0,0 +1,370 @@ +/** + * \file asn1write.h + * + * \brief ASN.1 buffer writing functionality + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_ASN1_WRITE_H +#define MBEDTLS_ASN1_WRITE_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/asn1.h" + +#define MBEDTLS_ASN1_CHK_ADD(g, f) \ + do \ + { \ + if( ( ret = (f) ) < 0 ) \ + return( ret ); \ + else \ + (g) += ret; \ + } while( 0 ) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Write a length field in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param len The length value to write. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, + size_t len ); +/** + * \brief Write an ASN.1 tag in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param tag The tag to write. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_tag( unsigned char **p, unsigned char *start, + unsigned char tag ); + +/** + * \brief Write raw buffer data. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param buf The data buffer to write. + * \param size The length of the data buffer. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_raw_buffer( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t size ); + +#if defined(MBEDTLS_BIGNUM_C) +/** + * \brief Write a arbitrary-precision number (#MBEDTLS_ASN1_INTEGER) + * in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param X The MPI to write. + * It must be non-negative. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_mpi( unsigned char **p, unsigned char *start, + const mbedtls_mpi *X ); +#endif /* MBEDTLS_BIGNUM_C */ + +/** + * \brief Write a NULL tag (#MBEDTLS_ASN1_NULL) with zero data + * in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_null( unsigned char **p, unsigned char *start ); + +/** + * \brief Write an OID tag (#MBEDTLS_ASN1_OID) and data + * in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param oid The OID to write. + * \param oid_len The length of the OID. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_oid( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len ); + +/** + * \brief Write an AlgorithmIdentifier sequence in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param oid The OID of the algorithm to write. + * \param oid_len The length of the algorithm's OID. + * \param par_len The length of the parameters, which must be already written. + * If 0, NULL parameters are added + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_algorithm_identifier( unsigned char **p, + unsigned char *start, + const char *oid, size_t oid_len, + size_t par_len ); + +/** + * \brief Write a boolean tag (#MBEDTLS_ASN1_BOOLEAN) and value + * in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param boolean The boolean value to write, either \c 0 or \c 1. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_bool( unsigned char **p, unsigned char *start, + int boolean ); + +/** + * \brief Write an int tag (#MBEDTLS_ASN1_INTEGER) and value + * in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param val The integer value to write. + * It must be non-negative. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val ); + +/** + * \brief Write an enum tag (#MBEDTLS_ASN1_ENUMERATED) and value + * in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param val The integer value to write. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_enum( unsigned char **p, unsigned char *start, int val ); + +/** + * \brief Write a string in ASN.1 format using a specific + * string encoding tag. + + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param tag The string encoding tag to write, e.g. + * #MBEDTLS_ASN1_UTF8_STRING. + * \param text The string to write. + * \param text_len The length of \p text in bytes (which might + * be strictly larger than the number of characters). + * + * \return The number of bytes written to \p p on success. + * \return A negative error code on failure. + */ +int mbedtls_asn1_write_tagged_string( unsigned char **p, unsigned char *start, + int tag, const char *text, + size_t text_len ); + +/** + * \brief Write a string in ASN.1 format using the PrintableString + * string encoding tag (#MBEDTLS_ASN1_PRINTABLE_STRING). + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param text The string to write. + * \param text_len The length of \p text in bytes (which might + * be strictly larger than the number of characters). + * + * \return The number of bytes written to \p p on success. + * \return A negative error code on failure. + */ +int mbedtls_asn1_write_printable_string( unsigned char **p, + unsigned char *start, + const char *text, size_t text_len ); + +/** + * \brief Write a UTF8 string in ASN.1 format using the UTF8String + * string encoding tag (#MBEDTLS_ASN1_UTF8_STRING). + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param text The string to write. + * \param text_len The length of \p text in bytes (which might + * be strictly larger than the number of characters). + * + * \return The number of bytes written to \p p on success. + * \return A negative error code on failure. + */ +int mbedtls_asn1_write_utf8_string( unsigned char **p, unsigned char *start, + const char *text, size_t text_len ); + +/** + * \brief Write a string in ASN.1 format using the IA5String + * string encoding tag (#MBEDTLS_ASN1_IA5_STRING). + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param text The string to write. + * \param text_len The length of \p text in bytes (which might + * be strictly larger than the number of characters). + * + * \return The number of bytes written to \p p on success. + * \return A negative error code on failure. + */ +int mbedtls_asn1_write_ia5_string( unsigned char **p, unsigned char *start, + const char *text, size_t text_len ); + +/** + * \brief Write a bitstring tag (#MBEDTLS_ASN1_BIT_STRING) and + * value in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param buf The bitstring to write. + * \param bits The total number of bits in the bitstring. + * + * \return The number of bytes written to \p p on success. + * \return A negative error code on failure. + */ +int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t bits ); + +/** + * \brief This function writes a named bitstring tag + * (#MBEDTLS_ASN1_BIT_STRING) and value in ASN.1 format. + * + * As stated in RFC 5280 Appendix B, trailing zeroes are + * omitted when encoding named bitstrings in DER. + * + * \note This function works backwards within the data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer which is used for bounds-checking. + * \param buf The bitstring to write. + * \param bits The total number of bits in the bitstring. + * + * \return The number of bytes written to \p p on success. + * \return A negative error code on failure. + */ +int mbedtls_asn1_write_named_bitstring( unsigned char **p, + unsigned char *start, + const unsigned char *buf, + size_t bits ); + +/** + * \brief Write an octet string tag (#MBEDTLS_ASN1_OCTET_STRING) + * and value in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param buf The buffer holding the data to write. + * \param size The length of the data buffer \p buf. + * + * \return The number of bytes written to \p p on success. + * \return A negative error code on failure. + */ +int mbedtls_asn1_write_octet_string( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t size ); + +/** + * \brief Create or find a specific named_data entry for writing in a + * sequence or list based on the OID. If not already in there, + * a new entry is added to the head of the list. + * Warning: Destructive behaviour for the val data! + * + * \param list The pointer to the location of the head of the list to seek + * through (will be updated in case of a new entry). + * \param oid The OID to look for. + * \param oid_len The size of the OID. + * \param val The associated data to store. If this is \c NULL, + * no data is copied to the new or existing buffer. + * \param val_len The minimum length of the data buffer needed. + * If this is 0, do not allocate a buffer for the associated + * data. + * If the OID was already present, enlarge, shrink or free + * the existing buffer to fit \p val_len. + * + * \return A pointer to the new / existing entry on success. + * \return \c NULL if if there was a memory allocation error. + */ +mbedtls_asn1_named_data *mbedtls_asn1_store_named_data( mbedtls_asn1_named_data **list, + const char *oid, size_t oid_len, + const unsigned char *val, + size_t val_len ); + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_ASN1_WRITE_H */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/base64.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/base64.h new file mode 100644 index 0000000..7e73a8b --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/base64.h @@ -0,0 +1,96 @@ +/** + * \file base64.h + * + * \brief RFC 1521 base64 encoding/decoding + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_BASE64_H +#define MBEDTLS_BASE64_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +#define MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL -0x002A /**< Output buffer too small. */ +#define MBEDTLS_ERR_BASE64_INVALID_CHARACTER -0x002C /**< Invalid character in input. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Encode a buffer into base64 format + * + * \param dst destination buffer + * \param dlen size of the destination buffer + * \param olen number of bytes written + * \param src source buffer + * \param slen amount of data to be encoded + * + * \return 0 if successful, or MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL. + * *olen is always updated to reflect the amount + * of data that has (or would have) been written. + * If that length cannot be represented, then no data is + * written to the buffer and *olen is set to the maximum + * length representable as a size_t. + * + * \note Call this function with dlen = 0 to obtain the + * required buffer size in *olen + */ +int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen, + const unsigned char *src, size_t slen ); + +/** + * \brief Decode a base64-formatted buffer + * + * \param dst destination buffer (can be NULL for checking size) + * \param dlen size of the destination buffer + * \param olen number of bytes written + * \param src source buffer + * \param slen amount of data to be decoded + * + * \return 0 if successful, MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL, or + * MBEDTLS_ERR_BASE64_INVALID_CHARACTER if the input data is + * not correct. *olen is always updated to reflect the amount + * of data that has (or would have) been written. + * + * \note Call this function with *dst = NULL or dlen = 0 to obtain + * the required buffer size in *olen + */ +int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen, + const unsigned char *src, size_t slen ); + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_base64_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* base64.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/bignum.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/bignum.h new file mode 100644 index 0000000..637360e --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/bignum.h @@ -0,0 +1,1017 @@ +/** + * \file bignum.h + * + * \brief Multi-precision integer library + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_BIGNUM_H +#define MBEDTLS_BIGNUM_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +#define MBEDTLS_ERR_MPI_FILE_IO_ERROR -0x0002 /**< An error occurred while reading from or writing to a file. */ +#define MBEDTLS_ERR_MPI_BAD_INPUT_DATA -0x0004 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_MPI_INVALID_CHARACTER -0x0006 /**< There is an invalid character in the digit string. */ +#define MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL -0x0008 /**< The buffer is too small to write to. */ +#define MBEDTLS_ERR_MPI_NEGATIVE_VALUE -0x000A /**< The input arguments are negative or result in illegal output. */ +#define MBEDTLS_ERR_MPI_DIVISION_BY_ZERO -0x000C /**< The input argument for division is zero, which is not allowed. */ +#define MBEDTLS_ERR_MPI_NOT_ACCEPTABLE -0x000E /**< The input arguments are not acceptable. */ +#define MBEDTLS_ERR_MPI_ALLOC_FAILED -0x0010 /**< Memory allocation failed. */ + +#define MBEDTLS_MPI_CHK(f) \ + do \ + { \ + if( ( ret = (f) ) != 0 ) \ + goto cleanup; \ + } while( 0 ) + +/* + * Maximum size MPIs are allowed to grow to in number of limbs. + */ +#define MBEDTLS_MPI_MAX_LIMBS 10000 + +#if !defined(MBEDTLS_MPI_WINDOW_SIZE) +/* + * Maximum window size used for modular exponentiation. Default: 6 + * Minimum value: 1. Maximum value: 6. + * + * Result is an array of ( 2 ** MBEDTLS_MPI_WINDOW_SIZE ) MPIs used + * for the sliding window calculation. (So 64 by default) + * + * Reduction in size, reduces speed. + */ +#define MBEDTLS_MPI_WINDOW_SIZE 6 /**< Maximum window size used. */ +#endif /* !MBEDTLS_MPI_WINDOW_SIZE */ + +#if !defined(MBEDTLS_MPI_MAX_SIZE) +/* + * Maximum size of MPIs allowed in bits and bytes for user-MPIs. + * ( Default: 512 bytes => 4096 bits, Maximum tested: 2048 bytes => 16384 bits ) + * + * Note: Calculations can temporarily result in larger MPIs. So the number + * of limbs required (MBEDTLS_MPI_MAX_LIMBS) is higher. + */ +#define MBEDTLS_MPI_MAX_SIZE 1024 /**< Maximum number of bytes for usable MPIs. */ +#endif /* !MBEDTLS_MPI_MAX_SIZE */ + +#define MBEDTLS_MPI_MAX_BITS ( 8 * MBEDTLS_MPI_MAX_SIZE ) /**< Maximum number of bits for usable MPIs. */ + +/* + * When reading from files with mbedtls_mpi_read_file() and writing to files with + * mbedtls_mpi_write_file() the buffer should have space + * for a (short) label, the MPI (in the provided radix), the newline + * characters and the '\0'. + * + * By default we assume at least a 10 char label, a minimum radix of 10 + * (decimal) and a maximum of 4096 bit numbers (1234 decimal chars). + * Autosized at compile time for at least a 10 char label, a minimum radix + * of 10 (decimal) for a number of MBEDTLS_MPI_MAX_BITS size. + * + * This used to be statically sized to 1250 for a maximum of 4096 bit + * numbers (1234 decimal chars). + * + * Calculate using the formula: + * MBEDTLS_MPI_RW_BUFFER_SIZE = ceil(MBEDTLS_MPI_MAX_BITS / ln(10) * ln(2)) + + * LabelSize + 6 + */ +#define MBEDTLS_MPI_MAX_BITS_SCALE100 ( 100 * MBEDTLS_MPI_MAX_BITS ) +#define MBEDTLS_LN_2_DIV_LN_10_SCALE100 332 +#define MBEDTLS_MPI_RW_BUFFER_SIZE ( ((MBEDTLS_MPI_MAX_BITS_SCALE100 + MBEDTLS_LN_2_DIV_LN_10_SCALE100 - 1) / MBEDTLS_LN_2_DIV_LN_10_SCALE100) + 10 + 6 ) + +/* + * Define the base integer type, architecture-wise. + * + * 32 or 64-bit integer types can be forced regardless of the underlying + * architecture by defining MBEDTLS_HAVE_INT32 or MBEDTLS_HAVE_INT64 + * respectively and undefining MBEDTLS_HAVE_ASM. + * + * Double-width integers (e.g. 128-bit in 64-bit architectures) can be + * disabled by defining MBEDTLS_NO_UDBL_DIVISION. + */ +#if !defined(MBEDTLS_HAVE_INT32) + #if defined(_MSC_VER) && defined(_M_AMD64) + /* Always choose 64-bit when using MSC */ + #if !defined(MBEDTLS_HAVE_INT64) + #define MBEDTLS_HAVE_INT64 + #endif /* !MBEDTLS_HAVE_INT64 */ + typedef int64_t mbedtls_mpi_sint; + typedef uint64_t mbedtls_mpi_uint; + #elif defined(__GNUC__) && ( \ + defined(__amd64__) || defined(__x86_64__) || \ + defined(__ppc64__) || defined(__powerpc64__) || \ + defined(__ia64__) || defined(__alpha__) || \ + ( defined(__sparc__) && defined(__arch64__) ) || \ + defined(__s390x__) || defined(__mips64) || \ + defined(__aarch64__) ) + #if !defined(MBEDTLS_HAVE_INT64) + #define MBEDTLS_HAVE_INT64 + #endif /* MBEDTLS_HAVE_INT64 */ + typedef int64_t mbedtls_mpi_sint; + typedef uint64_t mbedtls_mpi_uint; + #if !defined(MBEDTLS_NO_UDBL_DIVISION) + /* mbedtls_t_udbl defined as 128-bit unsigned int */ + typedef unsigned int mbedtls_t_udbl __attribute__((mode(TI))); + #define MBEDTLS_HAVE_UDBL + #endif /* !MBEDTLS_NO_UDBL_DIVISION */ + #elif defined(__ARMCC_VERSION) && defined(__aarch64__) + /* + * __ARMCC_VERSION is defined for both armcc and armclang and + * __aarch64__ is only defined by armclang when compiling 64-bit code + */ + #if !defined(MBEDTLS_HAVE_INT64) + #define MBEDTLS_HAVE_INT64 + #endif /* !MBEDTLS_HAVE_INT64 */ + typedef int64_t mbedtls_mpi_sint; + typedef uint64_t mbedtls_mpi_uint; + #if !defined(MBEDTLS_NO_UDBL_DIVISION) + /* mbedtls_t_udbl defined as 128-bit unsigned int */ + typedef __uint128_t mbedtls_t_udbl; + #define MBEDTLS_HAVE_UDBL + #endif /* !MBEDTLS_NO_UDBL_DIVISION */ + #elif defined(MBEDTLS_HAVE_INT64) + /* Force 64-bit integers with unknown compiler */ + typedef int64_t mbedtls_mpi_sint; + typedef uint64_t mbedtls_mpi_uint; + #endif +#endif /* !MBEDTLS_HAVE_INT32 */ + +#if !defined(MBEDTLS_HAVE_INT64) + /* Default to 32-bit compilation */ + #if !defined(MBEDTLS_HAVE_INT32) + #define MBEDTLS_HAVE_INT32 + #endif /* !MBEDTLS_HAVE_INT32 */ + typedef int32_t mbedtls_mpi_sint; + typedef uint32_t mbedtls_mpi_uint; + #if !defined(MBEDTLS_NO_UDBL_DIVISION) + typedef uint64_t mbedtls_t_udbl; + #define MBEDTLS_HAVE_UDBL + #endif /* !MBEDTLS_NO_UDBL_DIVISION */ +#endif /* !MBEDTLS_HAVE_INT64 */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief MPI structure + */ +typedef struct mbedtls_mpi +{ + int s; /*!< Sign: -1 if the mpi is negative, 1 otherwise */ + size_t n; /*!< total # of limbs */ + mbedtls_mpi_uint *p; /*!< pointer to limbs */ +} +mbedtls_mpi; + +/** + * \brief Initialize an MPI context. + * + * This makes the MPI ready to be set or freed, + * but does not define a value for the MPI. + * + * \param X The MPI context to initialize. This must not be \c NULL. + */ +void mbedtls_mpi_init( mbedtls_mpi *X ); + +/** + * \brief This function frees the components of an MPI context. + * + * \param X The MPI context to be cleared. This may be \c NULL, + * in which case this function is a no-op. If it is + * not \c NULL, it must point to an initialized MPI. + */ +void mbedtls_mpi_free( mbedtls_mpi *X ); + +/** + * \brief Enlarge an MPI to the specified number of limbs. + * + * \note This function does nothing if the MPI is + * already large enough. + * + * \param X The MPI to grow. It must be initialized. + * \param nblimbs The target number of limbs. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs ); + +/** + * \brief This function resizes an MPI downwards, keeping at least the + * specified number of limbs. + * + * If \c X is smaller than \c nblimbs, it is resized up + * instead. + * + * \param X The MPI to shrink. This must point to an initialized MPI. + * \param nblimbs The minimum number of limbs to keep. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * (this can only happen when resizing up). + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs ); + +/** + * \brief Make a copy of an MPI. + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param Y The source MPI. This must point to an initialized MPI. + * + * \note The limb-buffer in the destination MPI is enlarged + * if necessary to hold the value in the source MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y ); + +/** + * \brief Swap the contents of two MPIs. + * + * \param X The first MPI. It must be initialized. + * \param Y The second MPI. It must be initialized. + */ +void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y ); + +/** + * \brief Perform a safe conditional copy of MPI which doesn't + * reveal whether the condition was true or not. + * + * \param X The MPI to conditionally assign to. This must point + * to an initialized MPI. + * \param Y The MPI to be assigned from. This must point to an + * initialized MPI. + * \param assign The condition deciding whether to perform the + * assignment or not. Possible values: + * * \c 1: Perform the assignment `X = Y`. + * * \c 0: Keep the original value of \p X. + * + * \note This function is equivalent to + * `if( assign ) mbedtls_mpi_copy( X, Y );` + * except that it avoids leaking any information about whether + * the assignment was done or not (the above code may leak + * information through branch prediction and/or memory access + * patterns analysis). + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign ); + +/** + * \brief Perform a safe conditional swap which doesn't + * reveal whether the condition was true or not. + * + * \param X The first MPI. This must be initialized. + * \param Y The second MPI. This must be initialized. + * \param assign The condition deciding whether to perform + * the swap or not. Possible values: + * * \c 1: Swap the values of \p X and \p Y. + * * \c 0: Keep the original values of \p X and \p Y. + * + * \note This function is equivalent to + * if( assign ) mbedtls_mpi_swap( X, Y ); + * except that it avoids leaking any information about whether + * the assignment was done or not (the above code may leak + * information through branch prediction and/or memory access + * patterns analysis). + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on other kinds of failure. + * + */ +int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char assign ); + +/** + * \brief Store integer value in MPI. + * + * \param X The MPI to set. This must be initialized. + * \param z The value to use. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z ); + +/** + * \brief Get a specific bit from an MPI. + * + * \param X The MPI to query. This must be initialized. + * \param pos Zero-based index of the bit to query. + * + * \return \c 0 or \c 1 on success, depending on whether bit \c pos + * of \c X is unset or set. + * \return A negative error code on failure. + */ +int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos ); + +/** + * \brief Modify a specific bit in an MPI. + * + * \note This function will grow the target MPI if necessary to set a + * bit to \c 1 in a not yet existing limb. It will not grow if + * the bit should be set to \c 0. + * + * \param X The MPI to modify. This must be initialized. + * \param pos Zero-based index of the bit to modify. + * \param val The desired value of bit \c pos: \c 0 or \c 1. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val ); + +/** + * \brief Return the number of bits of value \c 0 before the + * least significant bit of value \c 1. + * + * \note This is the same as the zero-based index of + * the least significant bit of value \c 1. + * + * \param X The MPI to query. + * + * \return The number of bits of value \c 0 before the least significant + * bit of value \c 1 in \p X. + */ +size_t mbedtls_mpi_lsb( const mbedtls_mpi *X ); + +/** + * \brief Return the number of bits up to and including the most + * significant bit of value \c 1. + * + * * \note This is same as the one-based index of the most + * significant bit of value \c 1. + * + * \param X The MPI to query. This must point to an initialized MPI. + * + * \return The number of bits up to and including the most + * significant bit of value \c 1. + */ +size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X ); + +/** + * \brief Return the total size of an MPI value in bytes. + * + * \param X The MPI to use. This must point to an initialized MPI. + * + * \note The value returned by this function may be less than + * the number of bytes used to store \p X internally. + * This happens if and only if there are trailing bytes + * of value zero. + * + * \return The least number of bytes capable of storing + * the absolute value of \p X. + */ +size_t mbedtls_mpi_size( const mbedtls_mpi *X ); + +/** + * \brief Import an MPI from an ASCII string. + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param radix The numeric base of the input string. + * \param s Null-terminated string buffer. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s ); + +/** + * \brief Export an MPI to an ASCII string. + * + * \param X The source MPI. This must point to an initialized MPI. + * \param radix The numeric base of the output string. + * \param buf The buffer to write the string to. This must be writable + * buffer of length \p buflen Bytes. + * \param buflen The available size in Bytes of \p buf. + * \param olen The address at which to store the length of the string + * written, including the final \c NULL byte. This must + * not be \c NULL. + * + * \note You can call this function with `buflen == 0` to obtain the + * minimum required buffer size in `*olen`. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if the target buffer \p buf + * is too small to hold the value of \p X in the desired base. + * In this case, `*olen` is nonetheless updated to contain the + * size of \p buf required for a successful call. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix, + char *buf, size_t buflen, size_t *olen ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Read an MPI from a line in an opened file. + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param radix The numeric base of the string representation used + * in the source line. + * \param fin The input file handle to use. This must not be \c NULL. + * + * \note On success, this function advances the file stream + * to the end of the current line or to EOF. + * + * The function returns \c 0 on an empty line. + * + * Leading whitespaces are ignored, as is a + * '0x' prefix for radix \c 16. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if the file read buffer + * is too small. + * \return Another negative error code on failure. + */ +int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin ); + +/** + * \brief Export an MPI into an opened file. + * + * \param p A string prefix to emit prior to the MPI data. + * For example, this might be a label, or "0x" when + * printing in base \c 16. This may be \c NULL if no prefix + * is needed. + * \param X The source MPI. This must point to an initialized MPI. + * \param radix The numeric base to be used in the emitted string. + * \param fout The output file handle. This may be \c NULL, in which case + * the output is written to \c stdout. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, + int radix, FILE *fout ); +#endif /* MBEDTLS_FS_IO */ + +/** + * \brief Import an MPI from unsigned big endian binary data. + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param buf The input buffer. This must be a readable buffer of length + * \p buflen Bytes. + * \param buflen The length of the input buffer \p p in Bytes. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, + size_t buflen ); + +/** + * \brief Import X from unsigned binary data, little endian + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param buf The input buffer. This must be a readable buffer of length + * \p buflen Bytes. + * \param buflen The length of the input buffer \p p in Bytes. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_read_binary_le( mbedtls_mpi *X, + const unsigned char *buf, size_t buflen ); + +/** + * \brief Export X into unsigned binary data, big endian. + * Always fills the whole buffer, which will start with zeros + * if the number is smaller. + * + * \param X The source MPI. This must point to an initialized MPI. + * \param buf The output buffer. This must be a writable buffer of length + * \p buflen Bytes. + * \param buflen The size of the output buffer \p buf in Bytes. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p buf isn't + * large enough to hold the value of \p X. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, + size_t buflen ); + +/** + * \brief Export X into unsigned binary data, little endian. + * Always fills the whole buffer, which will end with zeros + * if the number is smaller. + * + * \param X The source MPI. This must point to an initialized MPI. + * \param buf The output buffer. This must be a writable buffer of length + * \p buflen Bytes. + * \param buflen The size of the output buffer \p buf in Bytes. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p buf isn't + * large enough to hold the value of \p X. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_write_binary_le( const mbedtls_mpi *X, + unsigned char *buf, size_t buflen ); + +/** + * \brief Perform a left-shift on an MPI: X <<= count + * + * \param X The MPI to shift. This must point to an initialized MPI. + * \param count The number of bits to shift by. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count ); + +/** + * \brief Perform a right-shift on an MPI: X >>= count + * + * \param X The MPI to shift. This must point to an initialized MPI. + * \param count The number of bits to shift by. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count ); + +/** + * \brief Compare the absolute values of two MPIs. + * + * \param X The left-hand MPI. This must point to an initialized MPI. + * \param Y The right-hand MPI. This must point to an initialized MPI. + * + * \return \c 1 if `|X|` is greater than `|Y|`. + * \return \c -1 if `|X|` is lesser than `|Y|`. + * \return \c 0 if `|X|` is equal to `|Y|`. + */ +int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y ); + +/** + * \brief Compare two MPIs. + * + * \param X The left-hand MPI. This must point to an initialized MPI. + * \param Y The right-hand MPI. This must point to an initialized MPI. + * + * \return \c 1 if \p X is greater than \p Y. + * \return \c -1 if \p X is lesser than \p Y. + * \return \c 0 if \p X is equal to \p Y. + */ +int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y ); + +/** + * \brief Check if an MPI is less than the other in constant time. + * + * \param X The left-hand MPI. This must point to an initialized MPI + * with the same allocated length as Y. + * \param Y The right-hand MPI. This must point to an initialized MPI + * with the same allocated length as X. + * \param ret The result of the comparison: + * \c 1 if \p X is less than \p Y. + * \c 0 if \p X is greater than or equal to \p Y. + * + * \return 0 on success. + * \return MBEDTLS_ERR_MPI_BAD_INPUT_DATA if the allocated length of + * the two input MPIs is not the same. + */ +int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y, + unsigned *ret ); + +/** + * \brief Compare an MPI with an integer. + * + * \param X The left-hand MPI. This must point to an initialized MPI. + * \param z The integer value to compare \p X to. + * + * \return \c 1 if \p X is greater than \p z. + * \return \c -1 if \p X is lesser than \p z. + * \return \c 0 if \p X is equal to \p z. + */ +int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z ); + +/** + * \brief Perform an unsigned addition of MPIs: X = |A| + |B| + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The first summand. This must point to an initialized MPI. + * \param B The second summand. This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *B ); + +/** + * \brief Perform an unsigned subtraction of MPIs: X = |A| - |B| + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The minuend. This must point to an initialized MPI. + * \param B The subtrahend. This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_NEGATIVE_VALUE if \p B is greater than \p A. + * \return Another negative error code on different kinds of failure. + * + */ +int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *B ); + +/** + * \brief Perform a signed addition of MPIs: X = A + B + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The first summand. This must point to an initialized MPI. + * \param B The second summand. This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *B ); + +/** + * \brief Perform a signed subtraction of MPIs: X = A - B + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The minuend. This must point to an initialized MPI. + * \param B The subtrahend. This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *B ); + +/** + * \brief Perform a signed addition of an MPI and an integer: X = A + b + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The first summand. This must point to an initialized MPI. + * \param b The second summand. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, + mbedtls_mpi_sint b ); + +/** + * \brief Perform a signed subtraction of an MPI and an integer: + * X = A - b + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The minuend. This must point to an initialized MPI. + * \param b The subtrahend. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, + mbedtls_mpi_sint b ); + +/** + * \brief Perform a multiplication of two MPIs: X = A * B + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The first factor. This must point to an initialized MPI. + * \param B The second factor. This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + * + */ +int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *B ); + +/** + * \brief Perform a multiplication of an MPI with an unsigned integer: + * X = A * b + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The first factor. This must point to an initialized MPI. + * \param b The second factor. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + * + */ +int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, + mbedtls_mpi_uint b ); + +/** + * \brief Perform a division with remainder of two MPIs: + * A = Q * B + R + * + * \param Q The destination MPI for the quotient. + * This may be \c NULL if the value of the + * quotient is not needed. + * \param R The destination MPI for the remainder value. + * This may be \c NULL if the value of the + * remainder is not needed. + * \param A The dividend. This must point to an initialized MPi. + * \param B The divisor. This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p B equals zero. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, + const mbedtls_mpi *B ); + +/** + * \brief Perform a division with remainder of an MPI by an integer: + * A = Q * b + R + * + * \param Q The destination MPI for the quotient. + * This may be \c NULL if the value of the + * quotient is not needed. + * \param R The destination MPI for the remainder value. + * This may be \c NULL if the value of the + * remainder is not needed. + * \param A The dividend. This must point to an initialized MPi. + * \param b The divisor. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p b equals zero. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, + mbedtls_mpi_sint b ); + +/** + * \brief Perform a modular reduction. R = A mod B + * + * \param R The destination MPI for the residue value. + * This must point to an initialized MPI. + * \param A The MPI to compute the residue of. + * This must point to an initialized MPI. + * \param B The base of the modular reduction. + * This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p B equals zero. + * \return #MBEDTLS_ERR_MPI_NEGATIVE_VALUE if \p B is negative. + * \return Another negative error code on different kinds of failure. + * + */ +int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, + const mbedtls_mpi *B ); + +/** + * \brief Perform a modular reduction with respect to an integer. + * r = A mod b + * + * \param r The address at which to store the residue. + * This must not be \c NULL. + * \param A The MPI to compute the residue of. + * This must point to an initialized MPi. + * \param b The integer base of the modular reduction. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p b equals zero. + * \return #MBEDTLS_ERR_MPI_NEGATIVE_VALUE if \p b is negative. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, + mbedtls_mpi_sint b ); + +/** + * \brief Perform a sliding-window exponentiation: X = A^E mod N + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The base of the exponentiation. + * This must point to an initialized MPI. + * \param E The exponent MPI. This must point to an initialized MPI. + * \param N The base for the modular reduction. This must point to an + * initialized MPI. + * \param _RR A helper MPI depending solely on \p N which can be used to + * speed-up multiple modular exponentiations for the same value + * of \p N. This may be \c NULL. If it is not \c NULL, it must + * point to an initialized MPI. If it hasn't been used after + * the call to mbedtls_mpi_init(), this function will compute + * the helper value and store it in \p _RR for reuse on + * subsequent calls to this function. Otherwise, the function + * will assume that \p _RR holds the helper value set by a + * previous call to mbedtls_mpi_exp_mod(), and reuse it. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \c N is negative or + * even, or if \c E is negative. + * \return Another negative error code on different kinds of failures. + * + */ +int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *E, const mbedtls_mpi *N, + mbedtls_mpi *_RR ); + +/** + * \brief Fill an MPI with a number of random bytes. + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param size The number of random bytes to generate. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context argument. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on failure. + * + * \note The bytes obtained from the RNG are interpreted + * as a big-endian representation of an MPI; this can + * be relevant in applications like deterministic ECDSA. + */ +int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Compute the greatest common divisor: G = gcd(A, B) + * + * \param G The destination MPI. This must point to an initialized MPI. + * \param A The first operand. This must point to an initialized MPI. + * \param B The second operand. This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, + const mbedtls_mpi *B ); + +/** + * \brief Compute the modular inverse: X = A^-1 mod N + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The MPI to calculate the modular inverse of. This must point + * to an initialized MPI. + * \param N The base of the modular inversion. This must point to an + * initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p N is less than + * or equal to one. + * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if \p has no modular inverse + * with respect to \p N. + */ +int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *N ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Perform a Miller-Rabin primality test with error + * probability of 2-80. + * + * \deprecated Superseded by mbedtls_mpi_is_prime_ext() which allows + * specifying the number of Miller-Rabin rounds. + * + * \param X The MPI to check for primality. + * This must point to an initialized MPI. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. + * This may be \c NULL if \p f_rng doesn't use a + * context parameter. + * + * \return \c 0 if successful, i.e. \p X is probably prime. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if \p X is not prime. + * \return Another negative error code on other kinds of failure. + */ +MBEDTLS_DEPRECATED int mbedtls_mpi_is_prime( const mbedtls_mpi *X, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Miller-Rabin primality test. + * + * \warning If \p X is potentially generated by an adversary, for example + * when validating cryptographic parameters that you didn't + * generate yourself and that are supposed to be prime, then + * \p rounds should be at least the half of the security + * strength of the cryptographic algorithm. On the other hand, + * if \p X is chosen uniformly or non-adversially (as is the + * case when mbedtls_mpi_gen_prime calls this function), then + * \p rounds can be much lower. + * + * \param X The MPI to check for primality. + * This must point to an initialized MPI. + * \param rounds The number of bases to perform the Miller-Rabin primality + * test for. The probability of returning 0 on a composite is + * at most 2-2*\p rounds. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. + * This may be \c NULL if \p f_rng doesn't use + * a context parameter. + * + * \return \c 0 if successful, i.e. \p X is probably prime. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if \p X is not prime. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +/** + * \brief Flags for mbedtls_mpi_gen_prime() + * + * Each of these flags is a constraint on the result X returned by + * mbedtls_mpi_gen_prime(). + */ +typedef enum { + MBEDTLS_MPI_GEN_PRIME_FLAG_DH = 0x0001, /**< (X-1)/2 is prime too */ + MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR = 0x0002, /**< lower error rate from 2-80 to 2-128 */ +} mbedtls_mpi_gen_prime_flag_t; + +/** + * \brief Generate a prime number. + * + * \param X The destination MPI to store the generated prime in. + * This must point to an initialized MPi. + * \param nbits The required size of the destination MPI in bits. + * This must be between \c 3 and #MBEDTLS_MPI_MAX_BITS. + * \param flags A mask of flags of type #mbedtls_mpi_gen_prime_flag_t. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. + * This may be \c NULL if \p f_rng doesn't use + * a context parameter. + * + * \return \c 0 if successful, in which case \p X holds a + * probably prime number. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if `nbits` is not between + * \c 3 and #MBEDTLS_MPI_MAX_BITS. + */ +int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_mpi_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* bignum.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/blowfish.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/blowfish.h new file mode 100644 index 0000000..c2a6ff9 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/blowfish.h @@ -0,0 +1,285 @@ +/** + * \file blowfish.h + * + * \brief Blowfish block cipher + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_BLOWFISH_H +#define MBEDTLS_BLOWFISH_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#include "mbedtls/platform_util.h" + +#define MBEDTLS_BLOWFISH_ENCRYPT 1 +#define MBEDTLS_BLOWFISH_DECRYPT 0 +#define MBEDTLS_BLOWFISH_MAX_KEY_BITS 448 +#define MBEDTLS_BLOWFISH_MIN_KEY_BITS 32 +#define MBEDTLS_BLOWFISH_ROUNDS 16 /**< Rounds to use. When increasing this value, make sure to extend the initialisation vectors */ +#define MBEDTLS_BLOWFISH_BLOCKSIZE 8 /* Blowfish uses 64 bit blocks */ + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#define MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( -0x0016 ) +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ +#define MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA -0x0016 /**< Bad input data. */ + +#define MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH -0x0018 /**< Invalid data input length. */ + +/* MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED is deprecated and should not be used. + */ +#define MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED -0x0017 /**< Blowfish hardware accelerator failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_BLOWFISH_ALT) +// Regular implementation +// + +/** + * \brief Blowfish context structure + */ +typedef struct mbedtls_blowfish_context +{ + uint32_t P[MBEDTLS_BLOWFISH_ROUNDS + 2]; /*!< Blowfish round keys */ + uint32_t S[4][256]; /*!< key dependent S-boxes */ +} +mbedtls_blowfish_context; + +#else /* MBEDTLS_BLOWFISH_ALT */ +#include "blowfish_alt.h" +#endif /* MBEDTLS_BLOWFISH_ALT */ + +/** + * \brief Initialize a Blowfish context. + * + * \param ctx The Blowfish context to be initialized. + * This must not be \c NULL. + */ +void mbedtls_blowfish_init( mbedtls_blowfish_context *ctx ); + +/** + * \brief Clear a Blowfish context. + * + * \param ctx The Blowfish context to be cleared. + * This may be \c NULL, in which case this function + * returns immediately. If it is not \c NULL, it must + * point to an initialized Blowfish context. + */ +void mbedtls_blowfish_free( mbedtls_blowfish_context *ctx ); + +/** + * \brief Perform a Blowfish key schedule operation. + * + * \param ctx The Blowfish context to perform the key schedule on. + * \param key The encryption key. This must be a readable buffer of + * length \p keybits Bits. + * \param keybits The length of \p key in Bits. This must be between + * \c 32 and \c 448 and a multiple of \c 8. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_blowfish_setkey( mbedtls_blowfish_context *ctx, const unsigned char *key, + unsigned int keybits ); + +/** + * \brief Perform a Blowfish-ECB block encryption/decryption operation. + * + * \param ctx The Blowfish context to use. This must be initialized + * and bound to a key. + * \param mode The mode of operation. Possible values are + * #MBEDTLS_BLOWFISH_ENCRYPT for encryption, or + * #MBEDTLS_BLOWFISH_DECRYPT for decryption. + * \param input The input block. This must be a readable buffer + * of size \c 8 Bytes. + * \param output The output block. This must be a writable buffer + * of size \c 8 Bytes. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_blowfish_crypt_ecb( mbedtls_blowfish_context *ctx, + int mode, + const unsigned char input[MBEDTLS_BLOWFISH_BLOCKSIZE], + unsigned char output[MBEDTLS_BLOWFISH_BLOCKSIZE] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief Perform a Blowfish-CBC buffer encryption/decryption operation. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx The Blowfish context to use. This must be initialized + * and bound to a key. + * \param mode The mode of operation. Possible values are + * #MBEDTLS_BLOWFISH_ENCRYPT for encryption, or + * #MBEDTLS_BLOWFISH_DECRYPT for decryption. + * \param length The length of the input data in Bytes. This must be + * multiple of \c 8. + * \param iv The initialization vector. This must be a read/write buffer + * of length \c 8 Bytes. It is updated by this function. + * \param input The input data. This must be a readable buffer of length + * \p length Bytes. + * \param output The output data. This must be a writable buffer of length + * \p length Bytes. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_blowfish_crypt_cbc( mbedtls_blowfish_context *ctx, + int mode, + size_t length, + unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/** + * \brief Perform a Blowfish CFB buffer encryption/decryption operation. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx The Blowfish context to use. This must be initialized + * and bound to a key. + * \param mode The mode of operation. Possible values are + * #MBEDTLS_BLOWFISH_ENCRYPT for encryption, or + * #MBEDTLS_BLOWFISH_DECRYPT for decryption. + * \param length The length of the input data in Bytes. + * \param iv_off The offset in the initialiation vector. + * The value pointed to must be smaller than \c 8 Bytes. + * It is updated by this function to support the aforementioned + * streaming usage. + * \param iv The initialization vector. This must be a read/write buffer + * of size \c 8 Bytes. It is updated after use. + * \param input The input data. This must be a readable buffer of length + * \p length Bytes. + * \param output The output data. This must be a writable buffer of length + * \p length Bytes. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_blowfish_crypt_cfb64( mbedtls_blowfish_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /*MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/** + * \brief Perform a Blowfish-CTR buffer encryption/decryption operation. + * + * \warning You must never reuse a nonce value with the same key. Doing so + * would void the encryption for the two messages encrypted with + * the same nonce and key. + * + * There are two common strategies for managing nonces with CTR: + * + * 1. You can handle everything as a single message processed over + * successive calls to this function. In that case, you want to + * set \p nonce_counter and \p nc_off to 0 for the first call, and + * then preserve the values of \p nonce_counter, \p nc_off and \p + * stream_block across calls to this function as they will be + * updated by this function. + * + * With this strategy, you must not encrypt more than 2**64 + * blocks of data with the same key. + * + * 2. You can encrypt separate messages by dividing the \p + * nonce_counter buffer in two areas: the first one used for a + * per-message nonce, handled by yourself, and the second one + * updated by this function internally. + * + * For example, you might reserve the first 4 bytes for the + * per-message nonce, and the last 4 bytes for internal use. In that + * case, before calling this function on a new message you need to + * set the first 4 bytes of \p nonce_counter to your chosen nonce + * value, the last 4 to 0, and \p nc_off to 0 (which will cause \p + * stream_block to be ignored). That way, you can encrypt at most + * 2**32 messages of up to 2**32 blocks each with the same key. + * + * The per-message nonce (or information sufficient to reconstruct + * it) needs to be communicated with the ciphertext and must be unique. + * The recommended way to ensure uniqueness is to use a message + * counter. + * + * Note that for both stategies, sizes are measured in blocks and + * that a Blowfish block is 8 bytes. + * + * \warning Upon return, \p stream_block contains sensitive data. Its + * content must not be written to insecure storage and should be + * securely discarded as soon as it's no longer needed. + * + * \param ctx The Blowfish context to use. This must be initialized + * and bound to a key. + * \param length The length of the input data in Bytes. + * \param nc_off The offset in the current stream_block (for resuming + * within current cipher stream). The offset pointer + * should be \c 0 at the start of a stream and must be + * smaller than \c 8. It is updated by this function. + * \param nonce_counter The 64-bit nonce and counter. This must point to a + * read/write buffer of length \c 8 Bytes. + * \param stream_block The saved stream-block for resuming. This must point to + * a read/write buffer of length \c 8 Bytes. + * \param input The input data. This must be a readable buffer of + * length \p length Bytes. + * \param output The output data. This must be a writable buffer of + * length \p length Bytes. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_blowfish_crypt_ctr( mbedtls_blowfish_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[MBEDTLS_BLOWFISH_BLOCKSIZE], + unsigned char stream_block[MBEDTLS_BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#ifdef __cplusplus +} +#endif + +#endif /* blowfish.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/bn_mul.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/bn_mul.h new file mode 100644 index 0000000..17d057f --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/bn_mul.h @@ -0,0 +1,938 @@ +/** + * \file bn_mul.h + * + * \brief Multi-precision integer library + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ +/* + * Multiply source vector [s] with b, add result + * to destination vector [d] and set carry c. + * + * Currently supports: + * + * . IA-32 (386+) . AMD64 / EM64T + * . IA-32 (SSE2) . Motorola 68000 + * . PowerPC, 32-bit . MicroBlaze + * . PowerPC, 64-bit . TriCore + * . SPARC v8 . ARM v3+ + * . Alpha . MIPS32 + * . C, longlong . C, generic + */ +#ifndef MBEDTLS_BN_MUL_H +#define MBEDTLS_BN_MUL_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/bignum.h" + +#if defined(MBEDTLS_HAVE_ASM) + +#ifndef asm +#define asm __asm +#endif + +/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */ +#if defined(__GNUC__) && \ + ( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 ) + +/* + * Disable use of the i386 assembly code below if option -O0, to disable all + * compiler optimisations, is passed, detected with __OPTIMIZE__ + * This is done as the number of registers used in the assembly code doesn't + * work with the -O0 option. + */ +#if defined(__i386__) && defined(__OPTIMIZE__) + +#define MULADDC_INIT \ + asm( \ + "movl %%ebx, %0 \n\t" \ + "movl %5, %%esi \n\t" \ + "movl %6, %%edi \n\t" \ + "movl %7, %%ecx \n\t" \ + "movl %8, %%ebx \n\t" + +#define MULADDC_CORE \ + "lodsl \n\t" \ + "mull %%ebx \n\t" \ + "addl %%ecx, %%eax \n\t" \ + "adcl $0, %%edx \n\t" \ + "addl (%%edi), %%eax \n\t" \ + "adcl $0, %%edx \n\t" \ + "movl %%edx, %%ecx \n\t" \ + "stosl \n\t" + +#if defined(MBEDTLS_HAVE_SSE2) + +#define MULADDC_HUIT \ + "movd %%ecx, %%mm1 \n\t" \ + "movd %%ebx, %%mm0 \n\t" \ + "movd (%%edi), %%mm3 \n\t" \ + "paddq %%mm3, %%mm1 \n\t" \ + "movd (%%esi), %%mm2 \n\t" \ + "pmuludq %%mm0, %%mm2 \n\t" \ + "movd 4(%%esi), %%mm4 \n\t" \ + "pmuludq %%mm0, %%mm4 \n\t" \ + "movd 8(%%esi), %%mm6 \n\t" \ + "pmuludq %%mm0, %%mm6 \n\t" \ + "movd 12(%%esi), %%mm7 \n\t" \ + "pmuludq %%mm0, %%mm7 \n\t" \ + "paddq %%mm2, %%mm1 \n\t" \ + "movd 4(%%edi), %%mm3 \n\t" \ + "paddq %%mm4, %%mm3 \n\t" \ + "movd 8(%%edi), %%mm5 \n\t" \ + "paddq %%mm6, %%mm5 \n\t" \ + "movd 12(%%edi), %%mm4 \n\t" \ + "paddq %%mm4, %%mm7 \n\t" \ + "movd %%mm1, (%%edi) \n\t" \ + "movd 16(%%esi), %%mm2 \n\t" \ + "pmuludq %%mm0, %%mm2 \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "movd 20(%%esi), %%mm4 \n\t" \ + "pmuludq %%mm0, %%mm4 \n\t" \ + "paddq %%mm3, %%mm1 \n\t" \ + "movd 24(%%esi), %%mm6 \n\t" \ + "pmuludq %%mm0, %%mm6 \n\t" \ + "movd %%mm1, 4(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "movd 28(%%esi), %%mm3 \n\t" \ + "pmuludq %%mm0, %%mm3 \n\t" \ + "paddq %%mm5, %%mm1 \n\t" \ + "movd 16(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm2 \n\t" \ + "movd %%mm1, 8(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm7, %%mm1 \n\t" \ + "movd 20(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm4 \n\t" \ + "movd %%mm1, 12(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm2, %%mm1 \n\t" \ + "movd 24(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm6 \n\t" \ + "movd %%mm1, 16(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm4, %%mm1 \n\t" \ + "movd 28(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm3 \n\t" \ + "movd %%mm1, 20(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm6, %%mm1 \n\t" \ + "movd %%mm1, 24(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm3, %%mm1 \n\t" \ + "movd %%mm1, 28(%%edi) \n\t" \ + "addl $32, %%edi \n\t" \ + "addl $32, %%esi \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "movd %%mm1, %%ecx \n\t" + +#define MULADDC_STOP \ + "emms \n\t" \ + "movl %4, %%ebx \n\t" \ + "movl %%ecx, %1 \n\t" \ + "movl %%edi, %2 \n\t" \ + "movl %%esi, %3 \n\t" \ + : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ + : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ + : "eax", "ebx", "ecx", "edx", "esi", "edi" \ + ); + +#else + +#define MULADDC_STOP \ + "movl %4, %%ebx \n\t" \ + "movl %%ecx, %1 \n\t" \ + "movl %%edi, %2 \n\t" \ + "movl %%esi, %3 \n\t" \ + : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ + : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ + : "eax", "ebx", "ecx", "edx", "esi", "edi" \ + ); +#endif /* SSE2 */ +#endif /* i386 */ + +#if defined(__amd64__) || defined (__x86_64__) + +#define MULADDC_INIT \ + asm( \ + "xorq %%r8, %%r8\n" + +#define MULADDC_CORE \ + "movq (%%rsi), %%rax\n" \ + "mulq %%rbx\n" \ + "addq $8, %%rsi\n" \ + "addq %%rcx, %%rax\n" \ + "movq %%r8, %%rcx\n" \ + "adcq $0, %%rdx\n" \ + "nop \n" \ + "addq %%rax, (%%rdi)\n" \ + "adcq %%rdx, %%rcx\n" \ + "addq $8, %%rdi\n" + +#define MULADDC_STOP \ + : "+c" (c), "+D" (d), "+S" (s) \ + : "b" (b) \ + : "rax", "rdx", "r8" \ + ); + +#endif /* AMD64 */ + +#if defined(__aarch64__) + +#define MULADDC_INIT \ + asm( + +#define MULADDC_CORE \ + "ldr x4, [%2], #8 \n\t" \ + "ldr x5, [%1] \n\t" \ + "mul x6, x4, %3 \n\t" \ + "umulh x7, x4, %3 \n\t" \ + "adds x5, x5, x6 \n\t" \ + "adc x7, x7, xzr \n\t" \ + "adds x5, x5, %0 \n\t" \ + "adc %0, x7, xzr \n\t" \ + "str x5, [%1], #8 \n\t" + +#define MULADDC_STOP \ + : "+r" (c), "+r" (d), "+r" (s) \ + : "r" (b) \ + : "x4", "x5", "x6", "x7", "cc" \ + ); + +#endif /* Aarch64 */ + +#if defined(__mc68020__) || defined(__mcpu32__) + +#define MULADDC_INIT \ + asm( \ + "movl %3, %%a2 \n\t" \ + "movl %4, %%a3 \n\t" \ + "movl %5, %%d3 \n\t" \ + "movl %6, %%d2 \n\t" \ + "moveq #0, %%d0 \n\t" + +#define MULADDC_CORE \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "moveq #0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "addxl %%d4, %%d3 \n\t" + +#define MULADDC_STOP \ + "movl %%d3, %0 \n\t" \ + "movl %%a3, %1 \n\t" \ + "movl %%a2, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "d0", "d1", "d2", "d3", "d4", "a2", "a3" \ + ); + +#define MULADDC_HUIT \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "addxl %%d0, %%d3 \n\t" + +#endif /* MC68000 */ + +#if defined(__powerpc64__) || defined(__ppc64__) + +#if defined(__MACH__) && defined(__APPLE__) + +#define MULADDC_INIT \ + asm( \ + "ld r3, %3 \n\t" \ + "ld r4, %4 \n\t" \ + "ld r5, %5 \n\t" \ + "ld r6, %6 \n\t" \ + "addi r3, r3, -8 \n\t" \ + "addi r4, r4, -8 \n\t" \ + "addic r5, r5, 0 \n\t" + +#define MULADDC_CORE \ + "ldu r7, 8(r3) \n\t" \ + "mulld r8, r7, r6 \n\t" \ + "mulhdu r9, r7, r6 \n\t" \ + "adde r8, r8, r5 \n\t" \ + "ld r7, 8(r4) \n\t" \ + "addze r5, r9 \n\t" \ + "addc r8, r8, r7 \n\t" \ + "stdu r8, 8(r4) \n\t" + +#define MULADDC_STOP \ + "addze r5, r5 \n\t" \ + "addi r4, r4, 8 \n\t" \ + "addi r3, r3, 8 \n\t" \ + "std r5, %0 \n\t" \ + "std r4, %1 \n\t" \ + "std r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + + +#else /* __MACH__ && __APPLE__ */ + +#define MULADDC_INIT \ + asm( \ + "ld %%r3, %3 \n\t" \ + "ld %%r4, %4 \n\t" \ + "ld %%r5, %5 \n\t" \ + "ld %%r6, %6 \n\t" \ + "addi %%r3, %%r3, -8 \n\t" \ + "addi %%r4, %%r4, -8 \n\t" \ + "addic %%r5, %%r5, 0 \n\t" + +#define MULADDC_CORE \ + "ldu %%r7, 8(%%r3) \n\t" \ + "mulld %%r8, %%r7, %%r6 \n\t" \ + "mulhdu %%r9, %%r7, %%r6 \n\t" \ + "adde %%r8, %%r8, %%r5 \n\t" \ + "ld %%r7, 8(%%r4) \n\t" \ + "addze %%r5, %%r9 \n\t" \ + "addc %%r8, %%r8, %%r7 \n\t" \ + "stdu %%r8, 8(%%r4) \n\t" + +#define MULADDC_STOP \ + "addze %%r5, %%r5 \n\t" \ + "addi %%r4, %%r4, 8 \n\t" \ + "addi %%r3, %%r3, 8 \n\t" \ + "std %%r5, %0 \n\t" \ + "std %%r4, %1 \n\t" \ + "std %%r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + +#endif /* __MACH__ && __APPLE__ */ + +#elif defined(__powerpc__) || defined(__ppc__) /* end PPC64/begin PPC32 */ + +#if defined(__MACH__) && defined(__APPLE__) + +#define MULADDC_INIT \ + asm( \ + "lwz r3, %3 \n\t" \ + "lwz r4, %4 \n\t" \ + "lwz r5, %5 \n\t" \ + "lwz r6, %6 \n\t" \ + "addi r3, r3, -4 \n\t" \ + "addi r4, r4, -4 \n\t" \ + "addic r5, r5, 0 \n\t" + +#define MULADDC_CORE \ + "lwzu r7, 4(r3) \n\t" \ + "mullw r8, r7, r6 \n\t" \ + "mulhwu r9, r7, r6 \n\t" \ + "adde r8, r8, r5 \n\t" \ + "lwz r7, 4(r4) \n\t" \ + "addze r5, r9 \n\t" \ + "addc r8, r8, r7 \n\t" \ + "stwu r8, 4(r4) \n\t" + +#define MULADDC_STOP \ + "addze r5, r5 \n\t" \ + "addi r4, r4, 4 \n\t" \ + "addi r3, r3, 4 \n\t" \ + "stw r5, %0 \n\t" \ + "stw r4, %1 \n\t" \ + "stw r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + +#else /* __MACH__ && __APPLE__ */ + +#define MULADDC_INIT \ + asm( \ + "lwz %%r3, %3 \n\t" \ + "lwz %%r4, %4 \n\t" \ + "lwz %%r5, %5 \n\t" \ + "lwz %%r6, %6 \n\t" \ + "addi %%r3, %%r3, -4 \n\t" \ + "addi %%r4, %%r4, -4 \n\t" \ + "addic %%r5, %%r5, 0 \n\t" + +#define MULADDC_CORE \ + "lwzu %%r7, 4(%%r3) \n\t" \ + "mullw %%r8, %%r7, %%r6 \n\t" \ + "mulhwu %%r9, %%r7, %%r6 \n\t" \ + "adde %%r8, %%r8, %%r5 \n\t" \ + "lwz %%r7, 4(%%r4) \n\t" \ + "addze %%r5, %%r9 \n\t" \ + "addc %%r8, %%r8, %%r7 \n\t" \ + "stwu %%r8, 4(%%r4) \n\t" + +#define MULADDC_STOP \ + "addze %%r5, %%r5 \n\t" \ + "addi %%r4, %%r4, 4 \n\t" \ + "addi %%r3, %%r3, 4 \n\t" \ + "stw %%r5, %0 \n\t" \ + "stw %%r4, %1 \n\t" \ + "stw %%r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + +#endif /* __MACH__ && __APPLE__ */ + +#endif /* PPC32 */ + +/* + * The Sparc(64) assembly is reported to be broken. + * Disable it for now, until we're able to fix it. + */ +#if 0 && defined(__sparc__) +#if defined(__sparc64__) + +#define MULADDC_INIT \ + asm( \ + "ldx %3, %%o0 \n\t" \ + "ldx %4, %%o1 \n\t" \ + "ld %5, %%o2 \n\t" \ + "ld %6, %%o3 \n\t" + +#define MULADDC_CORE \ + "ld [%%o0], %%o4 \n\t" \ + "inc 4, %%o0 \n\t" \ + "ld [%%o1], %%o5 \n\t" \ + "umul %%o3, %%o4, %%o4 \n\t" \ + "addcc %%o4, %%o2, %%o4 \n\t" \ + "rd %%y, %%g1 \n\t" \ + "addx %%g1, 0, %%g1 \n\t" \ + "addcc %%o4, %%o5, %%o4 \n\t" \ + "st %%o4, [%%o1] \n\t" \ + "addx %%g1, 0, %%o2 \n\t" \ + "inc 4, %%o1 \n\t" + + #define MULADDC_STOP \ + "st %%o2, %0 \n\t" \ + "stx %%o1, %1 \n\t" \ + "stx %%o0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "g1", "o0", "o1", "o2", "o3", "o4", \ + "o5" \ + ); + +#else /* __sparc64__ */ + +#define MULADDC_INIT \ + asm( \ + "ld %3, %%o0 \n\t" \ + "ld %4, %%o1 \n\t" \ + "ld %5, %%o2 \n\t" \ + "ld %6, %%o3 \n\t" + +#define MULADDC_CORE \ + "ld [%%o0], %%o4 \n\t" \ + "inc 4, %%o0 \n\t" \ + "ld [%%o1], %%o5 \n\t" \ + "umul %%o3, %%o4, %%o4 \n\t" \ + "addcc %%o4, %%o2, %%o4 \n\t" \ + "rd %%y, %%g1 \n\t" \ + "addx %%g1, 0, %%g1 \n\t" \ + "addcc %%o4, %%o5, %%o4 \n\t" \ + "st %%o4, [%%o1] \n\t" \ + "addx %%g1, 0, %%o2 \n\t" \ + "inc 4, %%o1 \n\t" + +#define MULADDC_STOP \ + "st %%o2, %0 \n\t" \ + "st %%o1, %1 \n\t" \ + "st %%o0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "g1", "o0", "o1", "o2", "o3", "o4", \ + "o5" \ + ); + +#endif /* __sparc64__ */ +#endif /* __sparc__ */ + +#if defined(__microblaze__) || defined(microblaze) + +#define MULADDC_INIT \ + asm( \ + "lwi r3, %3 \n\t" \ + "lwi r4, %4 \n\t" \ + "lwi r5, %5 \n\t" \ + "lwi r6, %6 \n\t" \ + "andi r7, r6, 0xffff \n\t" \ + "bsrli r6, r6, 16 \n\t" + +#define MULADDC_CORE \ + "lhui r8, r3, 0 \n\t" \ + "addi r3, r3, 2 \n\t" \ + "lhui r9, r3, 0 \n\t" \ + "addi r3, r3, 2 \n\t" \ + "mul r10, r9, r6 \n\t" \ + "mul r11, r8, r7 \n\t" \ + "mul r12, r9, r7 \n\t" \ + "mul r13, r8, r6 \n\t" \ + "bsrli r8, r10, 16 \n\t" \ + "bsrli r9, r11, 16 \n\t" \ + "add r13, r13, r8 \n\t" \ + "add r13, r13, r9 \n\t" \ + "bslli r10, r10, 16 \n\t" \ + "bslli r11, r11, 16 \n\t" \ + "add r12, r12, r10 \n\t" \ + "addc r13, r13, r0 \n\t" \ + "add r12, r12, r11 \n\t" \ + "addc r13, r13, r0 \n\t" \ + "lwi r10, r4, 0 \n\t" \ + "add r12, r12, r10 \n\t" \ + "addc r13, r13, r0 \n\t" \ + "add r12, r12, r5 \n\t" \ + "addc r5, r13, r0 \n\t" \ + "swi r12, r4, 0 \n\t" \ + "addi r4, r4, 4 \n\t" + +#define MULADDC_STOP \ + "swi r5, %0 \n\t" \ + "swi r4, %1 \n\t" \ + "swi r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", \ + "r9", "r10", "r11", "r12", "r13" \ + ); + +#endif /* MicroBlaze */ + +#if defined(__tricore__) + +#define MULADDC_INIT \ + asm( \ + "ld.a %%a2, %3 \n\t" \ + "ld.a %%a3, %4 \n\t" \ + "ld.w %%d4, %5 \n\t" \ + "ld.w %%d1, %6 \n\t" \ + "xor %%d5, %%d5 \n\t" + +#define MULADDC_CORE \ + "ld.w %%d0, [%%a2+] \n\t" \ + "madd.u %%e2, %%e4, %%d0, %%d1 \n\t" \ + "ld.w %%d0, [%%a3] \n\t" \ + "addx %%d2, %%d2, %%d0 \n\t" \ + "addc %%d3, %%d3, 0 \n\t" \ + "mov %%d4, %%d3 \n\t" \ + "st.w [%%a3+], %%d2 \n\t" + +#define MULADDC_STOP \ + "st.w %0, %%d4 \n\t" \ + "st.a %1, %%a3 \n\t" \ + "st.a %2, %%a2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "d0", "d1", "e2", "d4", "a2", "a3" \ + ); + +#endif /* TriCore */ + +/* + * Note, gcc -O0 by default uses r7 for the frame pointer, so it complains about + * our use of r7 below, unless -fomit-frame-pointer is passed. + * + * On the other hand, -fomit-frame-pointer is implied by any -Ox options with + * x !=0, which we can detect using __OPTIMIZE__ (which is also defined by + * clang and armcc5 under the same conditions). + * + * So, only use the optimized assembly below for optimized build, which avoids + * the build error and is pretty reasonable anyway. + */ +#if defined(__GNUC__) && !defined(__OPTIMIZE__) +#define MULADDC_CANNOT_USE_R7 +#endif + +#if defined(__arm__) && !defined(MULADDC_CANNOT_USE_R7) + +#if defined(__thumb__) && !defined(__thumb2__) + +#define MULADDC_INIT \ + asm( \ + "ldr r0, %3 \n\t" \ + "ldr r1, %4 \n\t" \ + "ldr r2, %5 \n\t" \ + "ldr r3, %6 \n\t" \ + "lsr r7, r3, #16 \n\t" \ + "mov r9, r7 \n\t" \ + "lsl r7, r3, #16 \n\t" \ + "lsr r7, r7, #16 \n\t" \ + "mov r8, r7 \n\t" + +#define MULADDC_CORE \ + "ldmia r0!, {r6} \n\t" \ + "lsr r7, r6, #16 \n\t" \ + "lsl r6, r6, #16 \n\t" \ + "lsr r6, r6, #16 \n\t" \ + "mov r4, r8 \n\t" \ + "mul r4, r6 \n\t" \ + "mov r3, r9 \n\t" \ + "mul r6, r3 \n\t" \ + "mov r5, r9 \n\t" \ + "mul r5, r7 \n\t" \ + "mov r3, r8 \n\t" \ + "mul r7, r3 \n\t" \ + "lsr r3, r6, #16 \n\t" \ + "add r5, r5, r3 \n\t" \ + "lsr r3, r7, #16 \n\t" \ + "add r5, r5, r3 \n\t" \ + "add r4, r4, r2 \n\t" \ + "mov r2, #0 \n\t" \ + "adc r5, r2 \n\t" \ + "lsl r3, r6, #16 \n\t" \ + "add r4, r4, r3 \n\t" \ + "adc r5, r2 \n\t" \ + "lsl r3, r7, #16 \n\t" \ + "add r4, r4, r3 \n\t" \ + "adc r5, r2 \n\t" \ + "ldr r3, [r1] \n\t" \ + "add r4, r4, r3 \n\t" \ + "adc r2, r5 \n\t" \ + "stmia r1!, {r4} \n\t" + +#define MULADDC_STOP \ + "str r2, %0 \n\t" \ + "str r1, %1 \n\t" \ + "str r0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r0", "r1", "r2", "r3", "r4", "r5", \ + "r6", "r7", "r8", "r9", "cc" \ + ); + +#elif (__ARM_ARCH >= 6) && \ + defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1) + +#define MULADDC_INIT \ + asm( + +#define MULADDC_CORE \ + "ldr r0, [%0], #4 \n\t" \ + "ldr r1, [%1] \n\t" \ + "umaal r1, %2, %3, r0 \n\t" \ + "str r1, [%1], #4 \n\t" + +#define MULADDC_STOP \ + : "=r" (s), "=r" (d), "=r" (c) \ + : "r" (b), "0" (s), "1" (d), "2" (c) \ + : "r0", "r1", "memory" \ + ); + +#else + +#define MULADDC_INIT \ + asm( \ + "ldr r0, %3 \n\t" \ + "ldr r1, %4 \n\t" \ + "ldr r2, %5 \n\t" \ + "ldr r3, %6 \n\t" + +#define MULADDC_CORE \ + "ldr r4, [r0], #4 \n\t" \ + "mov r5, #0 \n\t" \ + "ldr r6, [r1] \n\t" \ + "umlal r2, r5, r3, r4 \n\t" \ + "adds r7, r6, r2 \n\t" \ + "adc r2, r5, #0 \n\t" \ + "str r7, [r1], #4 \n\t" + +#define MULADDC_STOP \ + "str r2, %0 \n\t" \ + "str r1, %1 \n\t" \ + "str r0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r0", "r1", "r2", "r3", "r4", "r5", \ + "r6", "r7", "cc" \ + ); + +#endif /* Thumb */ + +#endif /* ARMv3 */ + +#if defined(__alpha__) + +#define MULADDC_INIT \ + asm( \ + "ldq $1, %3 \n\t" \ + "ldq $2, %4 \n\t" \ + "ldq $3, %5 \n\t" \ + "ldq $4, %6 \n\t" + +#define MULADDC_CORE \ + "ldq $6, 0($1) \n\t" \ + "addq $1, 8, $1 \n\t" \ + "mulq $6, $4, $7 \n\t" \ + "umulh $6, $4, $6 \n\t" \ + "addq $7, $3, $7 \n\t" \ + "cmpult $7, $3, $3 \n\t" \ + "ldq $5, 0($2) \n\t" \ + "addq $7, $5, $7 \n\t" \ + "cmpult $7, $5, $5 \n\t" \ + "stq $7, 0($2) \n\t" \ + "addq $2, 8, $2 \n\t" \ + "addq $6, $3, $3 \n\t" \ + "addq $5, $3, $3 \n\t" + +#define MULADDC_STOP \ + "stq $3, %0 \n\t" \ + "stq $2, %1 \n\t" \ + "stq $1, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "$1", "$2", "$3", "$4", "$5", "$6", "$7" \ + ); +#endif /* Alpha */ + +#if defined(__mips__) && !defined(__mips64) + +#define MULADDC_INIT \ + asm( \ + "lw $10, %3 \n\t" \ + "lw $11, %4 \n\t" \ + "lw $12, %5 \n\t" \ + "lw $13, %6 \n\t" + +#define MULADDC_CORE \ + "lw $14, 0($10) \n\t" \ + "multu $13, $14 \n\t" \ + "addi $10, $10, 4 \n\t" \ + "mflo $14 \n\t" \ + "mfhi $9 \n\t" \ + "addu $14, $12, $14 \n\t" \ + "lw $15, 0($11) \n\t" \ + "sltu $12, $14, $12 \n\t" \ + "addu $15, $14, $15 \n\t" \ + "sltu $14, $15, $14 \n\t" \ + "addu $12, $12, $9 \n\t" \ + "sw $15, 0($11) \n\t" \ + "addu $12, $12, $14 \n\t" \ + "addi $11, $11, 4 \n\t" + +#define MULADDC_STOP \ + "sw $12, %0 \n\t" \ + "sw $11, %1 \n\t" \ + "sw $10, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "$9", "$10", "$11", "$12", "$13", "$14", "$15", "lo", "hi" \ + ); + +#endif /* MIPS */ +#endif /* GNUC */ + +#if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) + +#define MULADDC_INIT \ + __asm mov esi, s \ + __asm mov edi, d \ + __asm mov ecx, c \ + __asm mov ebx, b + +#define MULADDC_CORE \ + __asm lodsd \ + __asm mul ebx \ + __asm add eax, ecx \ + __asm adc edx, 0 \ + __asm add eax, [edi] \ + __asm adc edx, 0 \ + __asm mov ecx, edx \ + __asm stosd + +#if defined(MBEDTLS_HAVE_SSE2) + +#define EMIT __asm _emit + +#define MULADDC_HUIT \ + EMIT 0x0F EMIT 0x6E EMIT 0xC9 \ + EMIT 0x0F EMIT 0x6E EMIT 0xC3 \ + EMIT 0x0F EMIT 0x6E EMIT 0x1F \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x6E EMIT 0x16 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x04 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x08 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x7E EMIT 0x0C \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF8 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ + EMIT 0x0F EMIT 0x6E EMIT 0x5F EMIT 0x04 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xDC \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x08 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xEE \ + EMIT 0x0F EMIT 0x6E EMIT 0x67 EMIT 0x0C \ + EMIT 0x0F EMIT 0xD4 EMIT 0xFC \ + EMIT 0x0F EMIT 0x7E EMIT 0x0F \ + EMIT 0x0F EMIT 0x6E EMIT 0x56 EMIT 0x10 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x14 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x18 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x04 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x6E EMIT 0x5E EMIT 0x1C \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD8 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCD \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x10 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xD5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x08 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCF \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x14 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xE5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x0C \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x18 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xF5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x10 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCC \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x1C \ + EMIT 0x0F EMIT 0xD4 EMIT 0xDD \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x14 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCE \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x18 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x1C \ + EMIT 0x83 EMIT 0xC7 EMIT 0x20 \ + EMIT 0x83 EMIT 0xC6 EMIT 0x20 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x7E EMIT 0xC9 + +#define MULADDC_STOP \ + EMIT 0x0F EMIT 0x77 \ + __asm mov c, ecx \ + __asm mov d, edi \ + __asm mov s, esi \ + +#else + +#define MULADDC_STOP \ + __asm mov c, ecx \ + __asm mov d, edi \ + __asm mov s, esi \ + +#endif /* SSE2 */ +#endif /* MSVC */ + +#endif /* MBEDTLS_HAVE_ASM */ + +#if !defined(MULADDC_CORE) +#if defined(MBEDTLS_HAVE_UDBL) + +#define MULADDC_INIT \ +{ \ + mbedtls_t_udbl r; \ + mbedtls_mpi_uint r0, r1; + +#define MULADDC_CORE \ + r = *(s++) * (mbedtls_t_udbl) b; \ + r0 = (mbedtls_mpi_uint) r; \ + r1 = (mbedtls_mpi_uint)( r >> biL ); \ + r0 += c; r1 += (r0 < c); \ + r0 += *d; r1 += (r0 < *d); \ + c = r1; *(d++) = r0; + +#define MULADDC_STOP \ +} + +#else +#define MULADDC_INIT \ +{ \ + mbedtls_mpi_uint s0, s1, b0, b1; \ + mbedtls_mpi_uint r0, r1, rx, ry; \ + b0 = ( b << biH ) >> biH; \ + b1 = ( b >> biH ); + +#define MULADDC_CORE \ + s0 = ( *s << biH ) >> biH; \ + s1 = ( *s >> biH ); s++; \ + rx = s0 * b1; r0 = s0 * b0; \ + ry = s1 * b0; r1 = s1 * b1; \ + r1 += ( rx >> biH ); \ + r1 += ( ry >> biH ); \ + rx <<= biH; ry <<= biH; \ + r0 += rx; r1 += (r0 < rx); \ + r0 += ry; r1 += (r0 < ry); \ + r0 += c; r1 += (r0 < c); \ + r0 += *d; r1 += (r0 < *d); \ + c = r1; *(d++) = r0; + +#define MULADDC_STOP \ +} + +#endif /* C (generic) */ +#endif /* C (longlong) */ + +#endif /* bn_mul.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/camellia.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/camellia.h new file mode 100644 index 0000000..f7d2b23 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/camellia.h @@ -0,0 +1,324 @@ +/** + * \file camellia.h + * + * \brief Camellia block cipher + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_CAMELLIA_H +#define MBEDTLS_CAMELLIA_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#include "mbedtls/platform_util.h" + +#define MBEDTLS_CAMELLIA_ENCRYPT 1 +#define MBEDTLS_CAMELLIA_DECRYPT 0 + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#define MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( -0x0024 ) +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ +#define MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA -0x0024 /**< Bad input data. */ + +#define MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH -0x0026 /**< Invalid data input length. */ + +/* MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED is deprecated and should not be used. + */ +#define MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED -0x0027 /**< Camellia hardware accelerator failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_CAMELLIA_ALT) +// Regular implementation +// + +/** + * \brief CAMELLIA context structure + */ +typedef struct mbedtls_camellia_context +{ + int nr; /*!< number of rounds */ + uint32_t rk[68]; /*!< CAMELLIA round keys */ +} +mbedtls_camellia_context; + +#else /* MBEDTLS_CAMELLIA_ALT */ +#include "camellia_alt.h" +#endif /* MBEDTLS_CAMELLIA_ALT */ + +/** + * \brief Initialize a CAMELLIA context. + * + * \param ctx The CAMELLIA context to be initialized. + * This must not be \c NULL. + */ +void mbedtls_camellia_init( mbedtls_camellia_context *ctx ); + +/** + * \brief Clear a CAMELLIA context. + * + * \param ctx The CAMELLIA context to be cleared. This may be \c NULL, + * in which case this function returns immediately. If it is not + * \c NULL, it must be initialized. + */ +void mbedtls_camellia_free( mbedtls_camellia_context *ctx ); + +/** + * \brief Perform a CAMELLIA key schedule operation for encryption. + * + * \param ctx The CAMELLIA context to use. This must be initialized. + * \param key The encryption key to use. This must be a readable buffer + * of size \p keybits Bits. + * \param keybits The length of \p key in Bits. This must be either \c 128, + * \c 192 or \c 256. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_camellia_setkey_enc( mbedtls_camellia_context *ctx, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief Perform a CAMELLIA key schedule operation for decryption. + * + * \param ctx The CAMELLIA context to use. This must be initialized. + * \param key The decryption key. This must be a readable buffer + * of size \p keybits Bits. + * \param keybits The length of \p key in Bits. This must be either \c 128, + * \c 192 or \c 256. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_camellia_setkey_dec( mbedtls_camellia_context *ctx, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief Perform a CAMELLIA-ECB block encryption/decryption operation. + * + * \param ctx The CAMELLIA context to use. This must be initialized + * and bound to a key. + * \param mode The mode of operation. This must be either + * #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT. + * \param input The input block. This must be a readable buffer + * of size \c 16 Bytes. + * \param output The output block. This must be a writable buffer + * of size \c 16 Bytes. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_camellia_crypt_ecb( mbedtls_camellia_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief Perform a CAMELLIA-CBC buffer encryption/decryption operation. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx The CAMELLIA context to use. This must be initialized + * and bound to a key. + * \param mode The mode of operation. This must be either + * #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT. + * \param length The length in Bytes of the input data \p input. + * This must be a multiple of \c 16 Bytes. + * \param iv The initialization vector. This must be a read/write buffer + * of length \c 16 Bytes. It is updated to allow streaming + * use as explained above. + * \param input The buffer holding the input data. This must point to a + * readable buffer of length \p length Bytes. + * \param output The buffer holding the output data. This must point to a + * writable buffer of length \p length Bytes. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_camellia_crypt_cbc( mbedtls_camellia_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/** + * \brief Perform a CAMELLIA-CFB128 buffer encryption/decryption + * operation. + * + * \note Due to the nature of CFB mode, you should use the same + * key for both encryption and decryption. In particular, calls + * to this function should be preceded by a key-schedule via + * mbedtls_camellia_setkey_enc() regardless of whether \p mode + * is #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx The CAMELLIA context to use. This must be initialized + * and bound to a key. + * \param mode The mode of operation. This must be either + * #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT. + * \param length The length of the input data \p input. Any value is allowed. + * \param iv_off The current offset in the IV. This must be smaller + * than \c 16 Bytes. It is updated after this call to allow + * the aforementioned streaming usage. + * \param iv The initialization vector. This must be a read/write buffer + * of length \c 16 Bytes. It is updated after this call to + * allow the aforementioned streaming usage. + * \param input The buffer holding the input data. This must be a readable + * buffer of size \p length Bytes. + * \param output The buffer to hold the output data. This must be a writable + * buffer of length \p length Bytes. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_camellia_crypt_cfb128( mbedtls_camellia_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/** + * \brief Perform a CAMELLIA-CTR buffer encryption/decryption operation. + * + * *note Due to the nature of CTR mode, you should use the same + * key for both encryption and decryption. In particular, calls + * to this function should be preceded by a key-schedule via + * mbedtls_camellia_setkey_enc() regardless of whether \p mode + * is #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT. + * + * \warning You must never reuse a nonce value with the same key. Doing so + * would void the encryption for the two messages encrypted with + * the same nonce and key. + * + * There are two common strategies for managing nonces with CTR: + * + * 1. You can handle everything as a single message processed over + * successive calls to this function. In that case, you want to + * set \p nonce_counter and \p nc_off to 0 for the first call, and + * then preserve the values of \p nonce_counter, \p nc_off and \p + * stream_block across calls to this function as they will be + * updated by this function. + * + * With this strategy, you must not encrypt more than 2**128 + * blocks of data with the same key. + * + * 2. You can encrypt separate messages by dividing the \p + * nonce_counter buffer in two areas: the first one used for a + * per-message nonce, handled by yourself, and the second one + * updated by this function internally. + * + * For example, you might reserve the first \c 12 Bytes for the + * per-message nonce, and the last \c 4 Bytes for internal use. + * In that case, before calling this function on a new message you + * need to set the first \c 12 Bytes of \p nonce_counter to your + * chosen nonce value, the last four to \c 0, and \p nc_off to \c 0 + * (which will cause \p stream_block to be ignored). That way, you + * can encrypt at most \c 2**96 messages of up to \c 2**32 blocks + * each with the same key. + * + * The per-message nonce (or information sufficient to reconstruct + * it) needs to be communicated with the ciphertext and must be + * unique. The recommended way to ensure uniqueness is to use a + * message counter. An alternative is to generate random nonces, + * but this limits the number of messages that can be securely + * encrypted: for example, with 96-bit random nonces, you should + * not encrypt more than 2**32 messages with the same key. + * + * Note that for both stategies, sizes are measured in blocks and + * that a CAMELLIA block is \c 16 Bytes. + * + * \warning Upon return, \p stream_block contains sensitive data. Its + * content must not be written to insecure storage and should be + * securely discarded as soon as it's no longer needed. + * + * \param ctx The CAMELLIA context to use. This must be initialized + * and bound to a key. + * \param length The length of the input data \p input in Bytes. + * Any value is allowed. + * \param nc_off The offset in the current \p stream_block (for resuming + * within current cipher stream). The offset pointer to + * should be \c 0 at the start of a stream. It is updated + * at the end of this call. + * \param nonce_counter The 128-bit nonce and counter. This must be a read/write + * buffer of length \c 16 Bytes. + * \param stream_block The saved stream-block for resuming. This must be a + * read/write buffer of length \c 16 Bytes. + * \param input The input data stream. This must be a readable buffer of + * size \p length Bytes. + * \param output The output data stream. This must be a writable buffer + * of size \p length Bytes. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_camellia_crypt_ctr( mbedtls_camellia_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_camellia_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* camellia.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ccm.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ccm.h new file mode 100644 index 0000000..7193863 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ccm.h @@ -0,0 +1,308 @@ +/** + * \file ccm.h + * + * \brief This file provides an API for the CCM authenticated encryption + * mode for block ciphers. + * + * CCM combines Counter mode encryption with CBC-MAC authentication + * for 128-bit block ciphers. + * + * Input to CCM includes the following elements: + *
  • Payload - data that is both authenticated and encrypted.
  • + *
  • Associated data (Adata) - data that is authenticated but not + * encrypted, For example, a header.
  • + *
  • Nonce - A unique value that is assigned to the payload and the + * associated data.
+ * + * Definition of CCM: + * http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf + * RFC 3610 "Counter with CBC-MAC (CCM)" + * + * Related: + * RFC 5116 "An Interface and Algorithms for Authenticated Encryption" + * + * Definition of CCM*: + * IEEE 802.15.4 - IEEE Standard for Local and metropolitan area networks + * Integer representation is fixed most-significant-octet-first order and + * the representation of octets is most-significant-bit-first order. This is + * consistent with RFC 3610. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_CCM_H +#define MBEDTLS_CCM_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/cipher.h" + +#define MBEDTLS_ERR_CCM_BAD_INPUT -0x000D /**< Bad input parameters to the function. */ +#define MBEDTLS_ERR_CCM_AUTH_FAILED -0x000F /**< Authenticated decryption failed. */ + +/* MBEDTLS_ERR_CCM_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_CCM_HW_ACCEL_FAILED -0x0011 /**< CCM hardware accelerator failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_CCM_ALT) +// Regular implementation +// + +/** + * \brief The CCM context-type definition. The CCM context is passed + * to the APIs called. + */ +typedef struct mbedtls_ccm_context +{ + mbedtls_cipher_context_t cipher_ctx; /*!< The cipher context used. */ +} +mbedtls_ccm_context; + +#else /* MBEDTLS_CCM_ALT */ +#include "ccm_alt.h" +#endif /* MBEDTLS_CCM_ALT */ + +/** + * \brief This function initializes the specified CCM context, + * to make references valid, and prepare the context + * for mbedtls_ccm_setkey() or mbedtls_ccm_free(). + * + * \param ctx The CCM context to initialize. This must not be \c NULL. + */ +void mbedtls_ccm_init( mbedtls_ccm_context *ctx ); + +/** + * \brief This function initializes the CCM context set in the + * \p ctx parameter and sets the encryption key. + * + * \param ctx The CCM context to initialize. This must be an initialized + * context. + * \param cipher The 128-bit block cipher to use. + * \param key The encryption key. This must not be \c NULL. + * \param keybits The key size in bits. This must be acceptable by the cipher. + * + * \return \c 0 on success. + * \return A CCM or cipher-specific error code on failure. + */ +int mbedtls_ccm_setkey( mbedtls_ccm_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief This function releases and clears the specified CCM context + * and underlying cipher sub-context. + * + * \param ctx The CCM context to clear. If this is \c NULL, the function + * has no effect. Otherwise, this must be initialized. + */ +void mbedtls_ccm_free( mbedtls_ccm_context *ctx ); + +/** + * \brief This function encrypts a buffer using CCM. + * + * \note The tag is written to a separate buffer. To concatenate + * the \p tag with the \p output, as done in RFC-3610: + * Counter with CBC-MAC (CCM), use + * \p tag = \p output + \p length, and make sure that the + * output buffer is at least \p length + \p tag_len wide. + * + * \param ctx The CCM context to use for encryption. This must be + * initialized and bound to a key. + * \param length The length of the input data in Bytes. + * \param iv The initialization vector (nonce). This must be a readable + * buffer of at least \p iv_len Bytes. + * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, + * or 13. The length L of the message length field is + * 15 - \p iv_len. + * \param add The additional data field. If \p add_len is greater than + * zero, \p add must be a readable buffer of at least that + * length. + * \param add_len The length of additional data in Bytes. + * This must be less than `2^16 - 2^8`. + * \param input The buffer holding the input data. If \p length is greater + * than zero, \p input must be a readable buffer of at least + * that length. + * \param output The buffer holding the output data. If \p length is greater + * than zero, \p output must be a writable buffer of at least + * that length. + * \param tag The buffer holding the authentication field. This must be a + * writable buffer of at least \p tag_len Bytes. + * \param tag_len The length of the authentication field to generate in Bytes: + * 4, 6, 8, 10, 12, 14 or 16. + * + * \return \c 0 on success. + * \return A CCM or cipher-specific error code on failure. + */ +int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + unsigned char *tag, size_t tag_len ); + +/** + * \brief This function encrypts a buffer using CCM*. + * + * \note The tag is written to a separate buffer. To concatenate + * the \p tag with the \p output, as done in RFC-3610: + * Counter with CBC-MAC (CCM), use + * \p tag = \p output + \p length, and make sure that the + * output buffer is at least \p length + \p tag_len wide. + * + * \note When using this function in a variable tag length context, + * the tag length has to be encoded into the \p iv passed to + * this function. + * + * \param ctx The CCM context to use for encryption. This must be + * initialized and bound to a key. + * \param length The length of the input data in Bytes. + * \param iv The initialization vector (nonce). This must be a readable + * buffer of at least \p iv_len Bytes. + * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, + * or 13. The length L of the message length field is + * 15 - \p iv_len. + * \param add The additional data field. This must be a readable buffer of + * at least \p add_len Bytes. + * \param add_len The length of additional data in Bytes. + * This must be less than 2^16 - 2^8. + * \param input The buffer holding the input data. If \p length is greater + * than zero, \p input must be a readable buffer of at least + * that length. + * \param output The buffer holding the output data. If \p length is greater + * than zero, \p output must be a writable buffer of at least + * that length. + * \param tag The buffer holding the authentication field. This must be a + * writable buffer of at least \p tag_len Bytes. + * \param tag_len The length of the authentication field to generate in Bytes: + * 0, 4, 6, 8, 10, 12, 14 or 16. + * + * \warning Passing \c 0 as \p tag_len means that the message is no + * longer authenticated. + * + * \return \c 0 on success. + * \return A CCM or cipher-specific error code on failure. + */ +int mbedtls_ccm_star_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + unsigned char *tag, size_t tag_len ); + +/** + * \brief This function performs a CCM authenticated decryption of a + * buffer. + * + * \param ctx The CCM context to use for decryption. This must be + * initialized and bound to a key. + * \param length The length of the input data in Bytes. + * \param iv The initialization vector (nonce). This must be a readable + * buffer of at least \p iv_len Bytes. + * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, + * or 13. The length L of the message length field is + * 15 - \p iv_len. + * \param add The additional data field. This must be a readable buffer + * of at least that \p add_len Bytes.. + * \param add_len The length of additional data in Bytes. + * This must be less than 2^16 - 2^8. + * \param input The buffer holding the input data. If \p length is greater + * than zero, \p input must be a readable buffer of at least + * that length. + * \param output The buffer holding the output data. If \p length is greater + * than zero, \p output must be a writable buffer of at least + * that length. + * \param tag The buffer holding the authentication field. This must be a + * readable buffer of at least \p tag_len Bytes. + * \param tag_len The length of the authentication field to generate in Bytes: + * 4, 6, 8, 10, 12, 14 or 16. + * + * \return \c 0 on success. This indicates that the message is authentic. + * \return #MBEDTLS_ERR_CCM_AUTH_FAILED if the tag does not match. + * \return A cipher-specific error code on calculation failure. + */ +int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + const unsigned char *tag, size_t tag_len ); + +/** + * \brief This function performs a CCM* authenticated decryption of a + * buffer. + * + * \note When using this function in a variable tag length context, + * the tag length has to be decoded from \p iv and passed to + * this function as \p tag_len. (\p tag needs to be adjusted + * accordingly.) + * + * \param ctx The CCM context to use for decryption. This must be + * initialized and bound to a key. + * \param length The length of the input data in Bytes. + * \param iv The initialization vector (nonce). This must be a readable + * buffer of at least \p iv_len Bytes. + * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, + * or 13. The length L of the message length field is + * 15 - \p iv_len. + * \param add The additional data field. This must be a readable buffer of + * at least that \p add_len Bytes. + * \param add_len The length of additional data in Bytes. + * This must be less than 2^16 - 2^8. + * \param input The buffer holding the input data. If \p length is greater + * than zero, \p input must be a readable buffer of at least + * that length. + * \param output The buffer holding the output data. If \p length is greater + * than zero, \p output must be a writable buffer of at least + * that length. + * \param tag The buffer holding the authentication field. This must be a + * readable buffer of at least \p tag_len Bytes. + * \param tag_len The length of the authentication field in Bytes. + * 0, 4, 6, 8, 10, 12, 14 or 16. + * + * \warning Passing \c 0 as \p tag_len means that the message is nos + * longer authenticated. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CCM_AUTH_FAILED if the tag does not match. + * \return A cipher-specific error code on calculation failure. + */ +int mbedtls_ccm_star_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + const unsigned char *tag, size_t tag_len ); + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +/** + * \brief The CCM checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_ccm_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CCM_H */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/certs.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/certs.h new file mode 100644 index 0000000..c93c741 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/certs.h @@ -0,0 +1,250 @@ +/** + * \file certs.h + * + * \brief Sample certificates and DHM parameters for testing + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_CERTS_H +#define MBEDTLS_CERTS_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* List of all PEM-encoded CA certificates, terminated by NULL; + * PEM encoded if MBEDTLS_PEM_PARSE_C is enabled, DER encoded + * otherwise. */ +extern const char * mbedtls_test_cas[]; +extern const size_t mbedtls_test_cas_len[]; + +/* List of all DER-encoded CA certificates, terminated by NULL */ +extern const unsigned char * mbedtls_test_cas_der[]; +extern const size_t mbedtls_test_cas_der_len[]; + +#if defined(MBEDTLS_PEM_PARSE_C) +/* Concatenation of all CA certificates in PEM format if available */ +extern const char mbedtls_test_cas_pem[]; +extern const size_t mbedtls_test_cas_pem_len; +#endif /* MBEDTLS_PEM_PARSE_C */ + +/* + * CA test certificates + */ + +extern const char mbedtls_test_ca_crt_ec_pem[]; +extern const char mbedtls_test_ca_key_ec_pem[]; +extern const char mbedtls_test_ca_pwd_ec_pem[]; +extern const char mbedtls_test_ca_key_rsa_pem[]; +extern const char mbedtls_test_ca_pwd_rsa_pem[]; +extern const char mbedtls_test_ca_crt_rsa_sha1_pem[]; +extern const char mbedtls_test_ca_crt_rsa_sha256_pem[]; + +extern const unsigned char mbedtls_test_ca_crt_ec_der[]; +extern const unsigned char mbedtls_test_ca_key_ec_der[]; +extern const unsigned char mbedtls_test_ca_key_rsa_der[]; +extern const unsigned char mbedtls_test_ca_crt_rsa_sha1_der[]; +extern const unsigned char mbedtls_test_ca_crt_rsa_sha256_der[]; + +extern const size_t mbedtls_test_ca_crt_ec_pem_len; +extern const size_t mbedtls_test_ca_key_ec_pem_len; +extern const size_t mbedtls_test_ca_pwd_ec_pem_len; +extern const size_t mbedtls_test_ca_key_rsa_pem_len; +extern const size_t mbedtls_test_ca_pwd_rsa_pem_len; +extern const size_t mbedtls_test_ca_crt_rsa_sha1_pem_len; +extern const size_t mbedtls_test_ca_crt_rsa_sha256_pem_len; + +extern const size_t mbedtls_test_ca_crt_ec_der_len; +extern const size_t mbedtls_test_ca_key_ec_der_len; +extern const size_t mbedtls_test_ca_pwd_ec_der_len; +extern const size_t mbedtls_test_ca_key_rsa_der_len; +extern const size_t mbedtls_test_ca_pwd_rsa_der_len; +extern const size_t mbedtls_test_ca_crt_rsa_sha1_der_len; +extern const size_t mbedtls_test_ca_crt_rsa_sha256_der_len; + +/* Config-dependent dispatch between PEM and DER encoding + * (PEM if enabled, otherwise DER) */ + +extern const char mbedtls_test_ca_crt_ec[]; +extern const char mbedtls_test_ca_key_ec[]; +extern const char mbedtls_test_ca_pwd_ec[]; +extern const char mbedtls_test_ca_key_rsa[]; +extern const char mbedtls_test_ca_pwd_rsa[]; +extern const char mbedtls_test_ca_crt_rsa_sha1[]; +extern const char mbedtls_test_ca_crt_rsa_sha256[]; + +extern const size_t mbedtls_test_ca_crt_ec_len; +extern const size_t mbedtls_test_ca_key_ec_len; +extern const size_t mbedtls_test_ca_pwd_ec_len; +extern const size_t mbedtls_test_ca_key_rsa_len; +extern const size_t mbedtls_test_ca_pwd_rsa_len; +extern const size_t mbedtls_test_ca_crt_rsa_sha1_len; +extern const size_t mbedtls_test_ca_crt_rsa_sha256_len; + +/* Config-dependent dispatch between SHA-1 and SHA-256 + * (SHA-256 if enabled, otherwise SHA-1) */ + +extern const char mbedtls_test_ca_crt_rsa[]; +extern const size_t mbedtls_test_ca_crt_rsa_len; + +/* Config-dependent dispatch between EC and RSA + * (RSA if enabled, otherwise EC) */ + +extern const char * mbedtls_test_ca_crt; +extern const char * mbedtls_test_ca_key; +extern const char * mbedtls_test_ca_pwd; +extern const size_t mbedtls_test_ca_crt_len; +extern const size_t mbedtls_test_ca_key_len; +extern const size_t mbedtls_test_ca_pwd_len; + +/* + * Server test certificates + */ + +extern const char mbedtls_test_srv_crt_ec_pem[]; +extern const char mbedtls_test_srv_key_ec_pem[]; +extern const char mbedtls_test_srv_pwd_ec_pem[]; +extern const char mbedtls_test_srv_key_rsa_pem[]; +extern const char mbedtls_test_srv_pwd_rsa_pem[]; +extern const char mbedtls_test_srv_crt_rsa_sha1_pem[]; +extern const char mbedtls_test_srv_crt_rsa_sha256_pem[]; + +extern const unsigned char mbedtls_test_srv_crt_ec_der[]; +extern const unsigned char mbedtls_test_srv_key_ec_der[]; +extern const unsigned char mbedtls_test_srv_key_rsa_der[]; +extern const unsigned char mbedtls_test_srv_crt_rsa_sha1_der[]; +extern const unsigned char mbedtls_test_srv_crt_rsa_sha256_der[]; + +extern const size_t mbedtls_test_srv_crt_ec_pem_len; +extern const size_t mbedtls_test_srv_key_ec_pem_len; +extern const size_t mbedtls_test_srv_pwd_ec_pem_len; +extern const size_t mbedtls_test_srv_key_rsa_pem_len; +extern const size_t mbedtls_test_srv_pwd_rsa_pem_len; +extern const size_t mbedtls_test_srv_crt_rsa_sha1_pem_len; +extern const size_t mbedtls_test_srv_crt_rsa_sha256_pem_len; + +extern const size_t mbedtls_test_srv_crt_ec_der_len; +extern const size_t mbedtls_test_srv_key_ec_der_len; +extern const size_t mbedtls_test_srv_pwd_ec_der_len; +extern const size_t mbedtls_test_srv_key_rsa_der_len; +extern const size_t mbedtls_test_srv_pwd_rsa_der_len; +extern const size_t mbedtls_test_srv_crt_rsa_sha1_der_len; +extern const size_t mbedtls_test_srv_crt_rsa_sha256_der_len; + +/* Config-dependent dispatch between PEM and DER encoding + * (PEM if enabled, otherwise DER) */ + +extern const char mbedtls_test_srv_crt_ec[]; +extern const char mbedtls_test_srv_key_ec[]; +extern const char mbedtls_test_srv_pwd_ec[]; +extern const char mbedtls_test_srv_key_rsa[]; +extern const char mbedtls_test_srv_pwd_rsa[]; +extern const char mbedtls_test_srv_crt_rsa_sha1[]; +extern const char mbedtls_test_srv_crt_rsa_sha256[]; + +extern const size_t mbedtls_test_srv_crt_ec_len; +extern const size_t mbedtls_test_srv_key_ec_len; +extern const size_t mbedtls_test_srv_pwd_ec_len; +extern const size_t mbedtls_test_srv_key_rsa_len; +extern const size_t mbedtls_test_srv_pwd_rsa_len; +extern const size_t mbedtls_test_srv_crt_rsa_sha1_len; +extern const size_t mbedtls_test_srv_crt_rsa_sha256_len; + +/* Config-dependent dispatch between SHA-1 and SHA-256 + * (SHA-256 if enabled, otherwise SHA-1) */ + +extern const char mbedtls_test_srv_crt_rsa[]; +extern const size_t mbedtls_test_srv_crt_rsa_len; + +/* Config-dependent dispatch between EC and RSA + * (RSA if enabled, otherwise EC) */ + +extern const char * mbedtls_test_srv_crt; +extern const char * mbedtls_test_srv_key; +extern const char * mbedtls_test_srv_pwd; +extern const size_t mbedtls_test_srv_crt_len; +extern const size_t mbedtls_test_srv_key_len; +extern const size_t mbedtls_test_srv_pwd_len; + +/* + * Client test certificates + */ + +extern const char mbedtls_test_cli_crt_ec_pem[]; +extern const char mbedtls_test_cli_key_ec_pem[]; +extern const char mbedtls_test_cli_pwd_ec_pem[]; +extern const char mbedtls_test_cli_key_rsa_pem[]; +extern const char mbedtls_test_cli_pwd_rsa_pem[]; +extern const char mbedtls_test_cli_crt_rsa_pem[]; + +extern const unsigned char mbedtls_test_cli_crt_ec_der[]; +extern const unsigned char mbedtls_test_cli_key_ec_der[]; +extern const unsigned char mbedtls_test_cli_key_rsa_der[]; +extern const unsigned char mbedtls_test_cli_crt_rsa_der[]; + +extern const size_t mbedtls_test_cli_crt_ec_pem_len; +extern const size_t mbedtls_test_cli_key_ec_pem_len; +extern const size_t mbedtls_test_cli_pwd_ec_pem_len; +extern const size_t mbedtls_test_cli_key_rsa_pem_len; +extern const size_t mbedtls_test_cli_pwd_rsa_pem_len; +extern const size_t mbedtls_test_cli_crt_rsa_pem_len; + +extern const size_t mbedtls_test_cli_crt_ec_der_len; +extern const size_t mbedtls_test_cli_key_ec_der_len; +extern const size_t mbedtls_test_cli_key_rsa_der_len; +extern const size_t mbedtls_test_cli_crt_rsa_der_len; + +/* Config-dependent dispatch between PEM and DER encoding + * (PEM if enabled, otherwise DER) */ + +extern const char mbedtls_test_cli_crt_ec[]; +extern const char mbedtls_test_cli_key_ec[]; +extern const char mbedtls_test_cli_pwd_ec[]; +extern const char mbedtls_test_cli_key_rsa[]; +extern const char mbedtls_test_cli_pwd_rsa[]; +extern const char mbedtls_test_cli_crt_rsa[]; + +extern const size_t mbedtls_test_cli_crt_ec_len; +extern const size_t mbedtls_test_cli_key_ec_len; +extern const size_t mbedtls_test_cli_pwd_ec_len; +extern const size_t mbedtls_test_cli_key_rsa_len; +extern const size_t mbedtls_test_cli_pwd_rsa_len; +extern const size_t mbedtls_test_cli_crt_rsa_len; + +/* Config-dependent dispatch between EC and RSA + * (RSA if enabled, otherwise EC) */ + +extern const char * mbedtls_test_cli_crt; +extern const char * mbedtls_test_cli_key; +extern const char * mbedtls_test_cli_pwd; +extern const size_t mbedtls_test_cli_crt_len; +extern const size_t mbedtls_test_cli_key_len; +extern const size_t mbedtls_test_cli_pwd_len; + +#ifdef __cplusplus +} +#endif + +#endif /* certs.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/chacha20.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/chacha20.h new file mode 100644 index 0000000..e59dd1f --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/chacha20.h @@ -0,0 +1,225 @@ +/** + * \file chacha20.h + * + * \brief This file contains ChaCha20 definitions and functions. + * + * ChaCha20 is a stream cipher that can encrypt and decrypt + * information. ChaCha was created by Daniel Bernstein as a variant of + * its Salsa cipher https://cr.yp.to/chacha/chacha-20080128.pdf + * ChaCha20 is the variant with 20 rounds, that was also standardized + * in RFC 7539. + * + * \author Daniel King + */ + +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_CHACHA20_H +#define MBEDTLS_CHACHA20_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#define MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA -0x0051 /**< Invalid input parameter(s). */ + +/* MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE is deprecated and should not be + * used. */ +#define MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE -0x0053 /**< Feature not available. For example, s part of the API is not implemented. */ + +/* MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED is deprecated and should not be used. + */ +#define MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED -0x0055 /**< Chacha20 hardware accelerator failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_CHACHA20_ALT) + +typedef struct mbedtls_chacha20_context +{ + uint32_t state[16]; /*! The state (before round operations). */ + uint8_t keystream8[64]; /*! Leftover keystream bytes. */ + size_t keystream_bytes_used; /*! Number of keystream bytes already used. */ +} +mbedtls_chacha20_context; + +#else /* MBEDTLS_CHACHA20_ALT */ +#include "chacha20_alt.h" +#endif /* MBEDTLS_CHACHA20_ALT */ + +/** + * \brief This function initializes the specified ChaCha20 context. + * + * It must be the first API called before using + * the context. + * + * It is usually followed by calls to + * \c mbedtls_chacha20_setkey() and + * \c mbedtls_chacha20_starts(), then one or more calls to + * to \c mbedtls_chacha20_update(), and finally to + * \c mbedtls_chacha20_free(). + * + * \param ctx The ChaCha20 context to initialize. + * This must not be \c NULL. + */ +void mbedtls_chacha20_init( mbedtls_chacha20_context *ctx ); + +/** + * \brief This function releases and clears the specified + * ChaCha20 context. + * + * \param ctx The ChaCha20 context to clear. This may be \c NULL, + * in which case this function is a no-op. If it is not + * \c NULL, it must point to an initialized context. + * + */ +void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx ); + +/** + * \brief This function sets the encryption/decryption key. + * + * \note After using this function, you must also call + * \c mbedtls_chacha20_starts() to set a nonce before you + * start encrypting/decrypting data with + * \c mbedtls_chacha_update(). + * + * \param ctx The ChaCha20 context to which the key should be bound. + * It must be initialized. + * \param key The encryption/decryption key. This must be \c 32 Bytes + * in length. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA if ctx or key is NULL. + */ +int mbedtls_chacha20_setkey( mbedtls_chacha20_context *ctx, + const unsigned char key[32] ); + +/** + * \brief This function sets the nonce and initial counter value. + * + * \note A ChaCha20 context can be re-used with the same key by + * calling this function to change the nonce. + * + * \warning You must never use the same nonce twice with the same key. + * This would void any confidentiality guarantees for the + * messages encrypted with the same nonce and key. + * + * \param ctx The ChaCha20 context to which the nonce should be bound. + * It must be initialized and bound to a key. + * \param nonce The nonce. This must be \c 12 Bytes in size. + * \param counter The initial counter value. This is usually \c 0. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA if ctx or nonce is + * NULL. + */ +int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx, + const unsigned char nonce[12], + uint32_t counter ); + +/** + * \brief This function encrypts or decrypts data. + * + * Since ChaCha20 is a stream cipher, the same operation is + * used for encrypting and decrypting data. + * + * \note The \p input and \p output pointers must either be equal or + * point to non-overlapping buffers. + * + * \note \c mbedtls_chacha20_setkey() and + * \c mbedtls_chacha20_starts() must be called at least once + * to setup the context before this function can be called. + * + * \note This function can be called multiple times in a row in + * order to encrypt of decrypt data piecewise with the same + * key and nonce. + * + * \param ctx The ChaCha20 context to use for encryption or decryption. + * It must be initialized and bound to a key and nonce. + * \param size The length of the input data in Bytes. + * \param input The buffer holding the input data. + * This pointer can be \c NULL if `size == 0`. + * \param output The buffer holding the output data. + * This must be able to hold \p size Bytes. + * This pointer can be \c NULL if `size == 0`. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx, + size_t size, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function encrypts or decrypts data with ChaCha20 and + * the given key and nonce. + * + * Since ChaCha20 is a stream cipher, the same operation is + * used for encrypting and decrypting data. + * + * \warning You must never use the same (key, nonce) pair more than + * once. This would void any confidentiality guarantees for + * the messages encrypted with the same nonce and key. + * + * \note The \p input and \p output pointers must either be equal or + * point to non-overlapping buffers. + * + * \param key The encryption/decryption key. + * This must be \c 32 Bytes in length. + * \param nonce The nonce. This must be \c 12 Bytes in size. + * \param counter The initial counter value. This is usually \c 0. + * \param size The length of the input data in Bytes. + * \param input The buffer holding the input data. + * This pointer can be \c NULL if `size == 0`. + * \param output The buffer holding the output data. + * This must be able to hold \p size Bytes. + * This pointer can be \c NULL if `size == 0`. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_chacha20_crypt( const unsigned char key[32], + const unsigned char nonce[12], + uint32_t counter, + size_t size, + const unsigned char* input, + unsigned char* output ); + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief The ChaCha20 checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_chacha20_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CHACHA20_H */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/chachapoly.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/chachapoly.h new file mode 100644 index 0000000..1007f95 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/chachapoly.h @@ -0,0 +1,357 @@ +/** + * \file chachapoly.h + * + * \brief This file contains the AEAD-ChaCha20-Poly1305 definitions and + * functions. + * + * ChaCha20-Poly1305 is an algorithm for Authenticated Encryption + * with Associated Data (AEAD) that can be used to encrypt and + * authenticate data. It is based on ChaCha20 and Poly1305 by Daniel + * Bernstein and was standardized in RFC 7539. + * + * \author Daniel King + */ + +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_CHACHAPOLY_H +#define MBEDTLS_CHACHAPOLY_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +/* for shared error codes */ +#include "mbedtls/poly1305.h" + +#define MBEDTLS_ERR_CHACHAPOLY_BAD_STATE -0x0054 /**< The requested operation is not permitted in the current state. */ +#define MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED -0x0056 /**< Authenticated decryption failed: data was not authentic. */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum +{ + MBEDTLS_CHACHAPOLY_ENCRYPT, /**< The mode value for performing encryption. */ + MBEDTLS_CHACHAPOLY_DECRYPT /**< The mode value for performing decryption. */ +} +mbedtls_chachapoly_mode_t; + +#if !defined(MBEDTLS_CHACHAPOLY_ALT) + +#include "mbedtls/chacha20.h" + +typedef struct mbedtls_chachapoly_context +{ + mbedtls_chacha20_context chacha20_ctx; /**< The ChaCha20 context. */ + mbedtls_poly1305_context poly1305_ctx; /**< The Poly1305 context. */ + uint64_t aad_len; /**< The length (bytes) of the Additional Authenticated Data. */ + uint64_t ciphertext_len; /**< The length (bytes) of the ciphertext. */ + int state; /**< The current state of the context. */ + mbedtls_chachapoly_mode_t mode; /**< Cipher mode (encrypt or decrypt). */ +} +mbedtls_chachapoly_context; + +#else /* !MBEDTLS_CHACHAPOLY_ALT */ +#include "chachapoly_alt.h" +#endif /* !MBEDTLS_CHACHAPOLY_ALT */ + +/** + * \brief This function initializes the specified ChaCha20-Poly1305 context. + * + * It must be the first API called before using + * the context. It must be followed by a call to + * \c mbedtls_chachapoly_setkey() before any operation can be + * done, and to \c mbedtls_chachapoly_free() once all + * operations with that context have been finished. + * + * In order to encrypt or decrypt full messages at once, for + * each message you should make a single call to + * \c mbedtls_chachapoly_crypt_and_tag() or + * \c mbedtls_chachapoly_auth_decrypt(). + * + * In order to encrypt messages piecewise, for each + * message you should make a call to + * \c mbedtls_chachapoly_starts(), then 0 or more calls to + * \c mbedtls_chachapoly_update_aad(), then 0 or more calls to + * \c mbedtls_chachapoly_update(), then one call to + * \c mbedtls_chachapoly_finish(). + * + * \warning Decryption with the piecewise API is discouraged! Always + * use \c mbedtls_chachapoly_auth_decrypt() when possible! + * + * If however this is not possible because the data is too + * large to fit in memory, you need to: + * + * - call \c mbedtls_chachapoly_starts() and (if needed) + * \c mbedtls_chachapoly_update_aad() as above, + * - call \c mbedtls_chachapoly_update() multiple times and + * ensure its output (the plaintext) is NOT used in any other + * way than placing it in temporary storage at this point, + * - call \c mbedtls_chachapoly_finish() to compute the + * authentication tag and compared it in constant time to the + * tag received with the ciphertext. + * + * If the tags are not equal, you must immediately discard + * all previous outputs of \c mbedtls_chachapoly_update(), + * otherwise you can now safely use the plaintext. + * + * \param ctx The ChachaPoly context to initialize. Must not be \c NULL. + */ +void mbedtls_chachapoly_init( mbedtls_chachapoly_context *ctx ); + +/** + * \brief This function releases and clears the specified + * ChaCha20-Poly1305 context. + * + * \param ctx The ChachaPoly context to clear. This may be \c NULL, in which + * case this function is a no-op. + */ +void mbedtls_chachapoly_free( mbedtls_chachapoly_context *ctx ); + +/** + * \brief This function sets the ChaCha20-Poly1305 + * symmetric encryption key. + * + * \param ctx The ChaCha20-Poly1305 context to which the key should be + * bound. This must be initialized. + * \param key The \c 256 Bit (\c 32 Bytes) key. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx, + const unsigned char key[32] ); + +/** + * \brief This function starts a ChaCha20-Poly1305 encryption or + * decryption operation. + * + * \warning You must never use the same nonce twice with the same key. + * This would void any confidentiality and authenticity + * guarantees for the messages encrypted with the same nonce + * and key. + * + * \note If the context is being used for AAD only (no data to + * encrypt or decrypt) then \p mode can be set to any value. + * + * \warning Decryption with the piecewise API is discouraged, see the + * warning on \c mbedtls_chachapoly_init(). + * + * \param ctx The ChaCha20-Poly1305 context. This must be initialized + * and bound to a key. + * \param nonce The nonce/IV to use for the message. + * This must be a redable buffer of length \c 12 Bytes. + * \param mode The operation to perform: #MBEDTLS_CHACHAPOLY_ENCRYPT or + * #MBEDTLS_CHACHAPOLY_DECRYPT (discouraged, see warning). + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_chachapoly_starts( mbedtls_chachapoly_context *ctx, + const unsigned char nonce[12], + mbedtls_chachapoly_mode_t mode ); + +/** + * \brief This function feeds additional data to be authenticated + * into an ongoing ChaCha20-Poly1305 operation. + * + * The Additional Authenticated Data (AAD), also called + * Associated Data (AD) is only authenticated but not + * encrypted nor included in the encrypted output. It is + * usually transmitted separately from the ciphertext or + * computed locally by each party. + * + * \note This function is called before data is encrypted/decrypted. + * I.e. call this function to process the AAD before calling + * \c mbedtls_chachapoly_update(). + * + * You may call this function multiple times to process + * an arbitrary amount of AAD. It is permitted to call + * this function 0 times, if no AAD is used. + * + * This function cannot be called any more if data has + * been processed by \c mbedtls_chachapoly_update(), + * or if the context has been finished. + * + * \warning Decryption with the piecewise API is discouraged, see the + * warning on \c mbedtls_chachapoly_init(). + * + * \param ctx The ChaCha20-Poly1305 context. This must be initialized + * and bound to a key. + * \param aad_len The length in Bytes of the AAD. The length has no + * restrictions. + * \param aad Buffer containing the AAD. + * This pointer can be \c NULL if `aad_len == 0`. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA + * if \p ctx or \p aad are NULL. + * \return #MBEDTLS_ERR_CHACHAPOLY_BAD_STATE + * if the operations has not been started or has been + * finished, or if the AAD has been finished. + */ +int mbedtls_chachapoly_update_aad( mbedtls_chachapoly_context *ctx, + const unsigned char *aad, + size_t aad_len ); + +/** + * \brief Thus function feeds data to be encrypted or decrypted + * into an on-going ChaCha20-Poly1305 + * operation. + * + * The direction (encryption or decryption) depends on the + * mode that was given when calling + * \c mbedtls_chachapoly_starts(). + * + * You may call this function multiple times to process + * an arbitrary amount of data. It is permitted to call + * this function 0 times, if no data is to be encrypted + * or decrypted. + * + * \warning Decryption with the piecewise API is discouraged, see the + * warning on \c mbedtls_chachapoly_init(). + * + * \param ctx The ChaCha20-Poly1305 context to use. This must be initialized. + * \param len The length (in bytes) of the data to encrypt or decrypt. + * \param input The buffer containing the data to encrypt or decrypt. + * This pointer can be \c NULL if `len == 0`. + * \param output The buffer to where the encrypted or decrypted data is + * written. This must be able to hold \p len bytes. + * This pointer can be \c NULL if `len == 0`. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CHACHAPOLY_BAD_STATE + * if the operation has not been started or has been + * finished. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx, + size_t len, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function finished the ChaCha20-Poly1305 operation and + * generates the MAC (authentication tag). + * + * \param ctx The ChaCha20-Poly1305 context to use. This must be initialized. + * \param mac The buffer to where the 128-bit (16 bytes) MAC is written. + * + * \warning Decryption with the piecewise API is discouraged, see the + * warning on \c mbedtls_chachapoly_init(). + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CHACHAPOLY_BAD_STATE + * if the operation has not been started or has been + * finished. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx, + unsigned char mac[16] ); + +/** + * \brief This function performs a complete ChaCha20-Poly1305 + * authenticated encryption with the previously-set key. + * + * \note Before using this function, you must set the key with + * \c mbedtls_chachapoly_setkey(). + * + * \warning You must never use the same nonce twice with the same key. + * This would void any confidentiality and authenticity + * guarantees for the messages encrypted with the same nonce + * and key. + * + * \param ctx The ChaCha20-Poly1305 context to use (holds the key). + * This must be initialized. + * \param length The length (in bytes) of the data to encrypt or decrypt. + * \param nonce The 96-bit (12 bytes) nonce/IV to use. + * \param aad The buffer containing the additional authenticated + * data (AAD). This pointer can be \c NULL if `aad_len == 0`. + * \param aad_len The length (in bytes) of the AAD data to process. + * \param input The buffer containing the data to encrypt or decrypt. + * This pointer can be \c NULL if `ilen == 0`. + * \param output The buffer to where the encrypted or decrypted data + * is written. This pointer can be \c NULL if `ilen == 0`. + * \param tag The buffer to where the computed 128-bit (16 bytes) MAC + * is written. This must not be \c NULL. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_chachapoly_encrypt_and_tag( mbedtls_chachapoly_context *ctx, + size_t length, + const unsigned char nonce[12], + const unsigned char *aad, + size_t aad_len, + const unsigned char *input, + unsigned char *output, + unsigned char tag[16] ); + +/** + * \brief This function performs a complete ChaCha20-Poly1305 + * authenticated decryption with the previously-set key. + * + * \note Before using this function, you must set the key with + * \c mbedtls_chachapoly_setkey(). + * + * \param ctx The ChaCha20-Poly1305 context to use (holds the key). + * \param length The length (in Bytes) of the data to decrypt. + * \param nonce The \c 96 Bit (\c 12 bytes) nonce/IV to use. + * \param aad The buffer containing the additional authenticated data (AAD). + * This pointer can be \c NULL if `aad_len == 0`. + * \param aad_len The length (in bytes) of the AAD data to process. + * \param tag The buffer holding the authentication tag. + * This must be a readable buffer of length \c 16 Bytes. + * \param input The buffer containing the data to decrypt. + * This pointer can be \c NULL if `ilen == 0`. + * \param output The buffer to where the decrypted data is written. + * This pointer can be \c NULL if `ilen == 0`. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED + * if the data was not authentic. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_chachapoly_auth_decrypt( mbedtls_chachapoly_context *ctx, + size_t length, + const unsigned char nonce[12], + const unsigned char *aad, + size_t aad_len, + const unsigned char tag[16], + const unsigned char *input, + unsigned char *output ); + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief The ChaCha20-Poly1305 checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_chachapoly_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CHACHAPOLY_H */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/check_config.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/check_config.h new file mode 100644 index 0000000..fd979db --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/check_config.h @@ -0,0 +1,885 @@ +/** + * \file check_config.h + * + * \brief Consistency checks for configuration options + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ + +/* + * It is recommended to include this file from your config.h + * in order to catch dependency issues early. + */ + +#ifndef MBEDTLS_CHECK_CONFIG_H +#define MBEDTLS_CHECK_CONFIG_H + +/* + * We assume CHAR_BIT is 8 in many places. In practice, this is true on our + * target platforms, so not an issue, but let's just be extra sure. + */ +#include +#if CHAR_BIT != 8 +#error "mbed TLS requires a platform with 8-bit chars" +#endif + +#if defined(_WIN32) +#if !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_C is required on Windows" +#endif + +/* Fix the config here. Not convenient to put an #ifdef _WIN32 in config.h as + * it would confuse config.py. */ +#if !defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) && \ + !defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) +#define MBEDTLS_PLATFORM_SNPRINTF_ALT +#endif + +#if !defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT) && \ + !defined(MBEDTLS_PLATFORM_VSNPRINTF_MACRO) +#define MBEDTLS_PLATFORM_VSNPRINTF_ALT +#endif +#endif /* _WIN32 */ + +#if defined(TARGET_LIKE_MBED) && \ + ( defined(MBEDTLS_NET_C) || defined(MBEDTLS_TIMING_C) ) +#error "The NET and TIMING modules are not available for mbed OS - please use the network and timing functions provided by mbed OS" +#endif + +#if defined(MBEDTLS_DEPRECATED_WARNING) && \ + !defined(__GNUC__) && !defined(__clang__) +#error "MBEDTLS_DEPRECATED_WARNING only works with GCC and Clang" +#endif + +#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_HAVE_TIME) +#error "MBEDTLS_HAVE_TIME_DATE without MBEDTLS_HAVE_TIME does not make sense" +#endif + +#if defined(MBEDTLS_AESNI_C) && !defined(MBEDTLS_HAVE_ASM) +#error "MBEDTLS_AESNI_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_CTR_DRBG_C) && !defined(MBEDTLS_AES_C) +#error "MBEDTLS_CTR_DRBG_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_DHM_C) && !defined(MBEDTLS_BIGNUM_C) +#error "MBEDTLS_DHM_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT) && !defined(MBEDTLS_SSL_TRUNCATED_HMAC) +#error "MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_CMAC_C) && \ + !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_DES_C) +#error "MBEDTLS_CMAC_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_NIST_KW_C) && \ + ( !defined(MBEDTLS_AES_C) || !defined(MBEDTLS_CIPHER_C) ) +#error "MBEDTLS_NIST_KW_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECDH_C) && !defined(MBEDTLS_ECP_C) +#error "MBEDTLS_ECDH_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECDSA_C) && \ + ( !defined(MBEDTLS_ECP_C) || \ + !( defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) ) || \ + !defined(MBEDTLS_ASN1_PARSE_C) || \ + !defined(MBEDTLS_ASN1_WRITE_C) ) +#error "MBEDTLS_ECDSA_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECJPAKE_C) && \ + ( !defined(MBEDTLS_ECP_C) || !defined(MBEDTLS_MD_C) ) +#error "MBEDTLS_ECJPAKE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_RESTARTABLE) && \ + ( defined(MBEDTLS_USE_PSA_CRYPTO) || \ + defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT) || \ + defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT) || \ + defined(MBEDTLS_ECDSA_SIGN_ALT) || \ + defined(MBEDTLS_ECDSA_VERIFY_ALT) || \ + defined(MBEDTLS_ECDSA_GENKEY_ALT) || \ + defined(MBEDTLS_ECP_INTERNAL_ALT) || \ + defined(MBEDTLS_ECP_ALT) ) +#error "MBEDTLS_ECP_RESTARTABLE defined, but it cannot coexist with an alternative or PSA-based ECP implementation" +#endif + +#if defined(MBEDTLS_ECP_RESTARTABLE) && \ + ! defined(MBEDTLS_ECDH_LEGACY_CONTEXT) +#error "MBEDTLS_ECP_RESTARTABLE defined, but not MBEDTLS_ECDH_LEGACY_CONTEXT" +#endif + +#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) && \ + defined(MBEDTLS_ECDH_LEGACY_CONTEXT) +#error "MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED defined, but MBEDTLS_ECDH_LEGACY_CONTEXT not disabled" +#endif + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) && !defined(MBEDTLS_HMAC_DRBG_C) +#error "MBEDTLS_ECDSA_DETERMINISTIC defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_C) && ( !defined(MBEDTLS_BIGNUM_C) || ( \ + !defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) ) ) +#error "MBEDTLS_ECP_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_C) && !( \ + defined(MBEDTLS_ECP_ALT) || \ + defined(MBEDTLS_CTR_DRBG_C) || \ + defined(MBEDTLS_HMAC_DRBG_C) || \ + defined(MBEDTLS_ECP_NO_INTERNAL_RNG)) +#error "MBEDTLS_ECP_C requires a DRBG module unless MBEDTLS_ECP_NO_INTERNAL_RNG is defined or an alternative implementation is used" +#endif + +#if defined(MBEDTLS_PK_PARSE_C) && !defined(MBEDTLS_ASN1_PARSE_C) +#error "MBEDTLS_PK_PARSE_C defined, but not all prerequesites" +#endif + +#if defined(MBEDTLS_ENTROPY_C) && (!defined(MBEDTLS_SHA512_C) && \ + !defined(MBEDTLS_SHA256_C)) +#error "MBEDTLS_ENTROPY_C defined, but not all prerequisites" +#endif +#if defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_SHA512_C) && \ + defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) && (MBEDTLS_CTR_DRBG_ENTROPY_LEN > 64) +#error "MBEDTLS_CTR_DRBG_ENTROPY_LEN value too high" +#endif +#if defined(MBEDTLS_ENTROPY_C) && \ + ( !defined(MBEDTLS_SHA512_C) || defined(MBEDTLS_ENTROPY_FORCE_SHA256) ) \ + && defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) && (MBEDTLS_CTR_DRBG_ENTROPY_LEN > 32) +#error "MBEDTLS_CTR_DRBG_ENTROPY_LEN value too high" +#endif +#if defined(MBEDTLS_ENTROPY_C) && \ + defined(MBEDTLS_ENTROPY_FORCE_SHA256) && !defined(MBEDTLS_SHA256_C) +#error "MBEDTLS_ENTROPY_FORCE_SHA256 defined, but not all prerequisites" +#endif + +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) +#define MBEDTLS_HAS_MEMSAN +#endif +#endif +#if defined(MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN) && !defined(MBEDTLS_HAS_MEMSAN) +#error "MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN requires building with MemorySanitizer" +#endif +#undef MBEDTLS_HAS_MEMSAN + +#if defined(MBEDTLS_TEST_NULL_ENTROPY) && \ + ( !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) ) +#error "MBEDTLS_TEST_NULL_ENTROPY defined, but not all prerequisites" +#endif +#if defined(MBEDTLS_TEST_NULL_ENTROPY) && \ + ( defined(MBEDTLS_ENTROPY_NV_SEED) || defined(MBEDTLS_ENTROPY_HARDWARE_ALT) || \ + defined(MBEDTLS_HAVEGE_C) ) +#error "MBEDTLS_TEST_NULL_ENTROPY defined, but entropy sources too" +#endif + +#if defined(MBEDTLS_GCM_C) && ( \ + !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_CAMELLIA_C) && !defined(MBEDTLS_ARIA_C) ) +#error "MBEDTLS_GCM_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_RANDOMIZE_JAC_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_ADD_MIXED_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_ADD_MIXED_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_DOUBLE_JAC_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_NORMALIZE_JAC_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_RANDOMIZE_MXZ_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_NORMALIZE_MXZ_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_HAVEGE_C) && !defined(MBEDTLS_TIMING_C) +#error "MBEDTLS_HAVEGE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_HKDF_C) && !defined(MBEDTLS_MD_C) +#error "MBEDTLS_HKDF_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_HMAC_DRBG_C) && !defined(MBEDTLS_MD_C) +#error "MBEDTLS_HMAC_DRBG_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) && \ + ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_ECDSA_C) || \ + !defined(MBEDTLS_X509_CRT_PARSE_C) ) +#error "MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ + ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_RSA_C) || \ + !defined(MBEDTLS_X509_CRT_PARSE_C) ) +#error "MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) && !defined(MBEDTLS_DHM_C) +#error "MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) && \ + !defined(MBEDTLS_ECDH_C) +#error "MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ + ( !defined(MBEDTLS_DHM_C) || !defined(MBEDTLS_RSA_C) || \ + !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ + ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_RSA_C) || \ + !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) && \ + ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_ECDSA_C) || \ + !defined(MBEDTLS_X509_CRT_PARSE_C) ) +#error "MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) && \ + ( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) || \ + !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ + ( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) || \ + !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_KEY_EXCHANGE_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \ + ( !defined(MBEDTLS_ECJPAKE_C) || !defined(MBEDTLS_SHA256_C) || \ + !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) ) +#error "MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) && \ + !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) && \ + ( !defined(MBEDTLS_SHA256_C) && \ + !defined(MBEDTLS_SHA512_C) && \ + !defined(MBEDTLS_SHA1_C) ) +#error "!MBEDTLS_SSL_KEEP_PEER_CERTIFICATE requires MBEDTLS_SHA512_C, MBEDTLS_SHA256_C or MBEDTLS_SHA1_C" +#endif + +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) && \ + ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) ) +#error "MBEDTLS_MEMORY_BUFFER_ALLOC_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_MEMORY_BACKTRACE) && !defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) +#error "MBEDTLS_MEMORY_BACKTRACE defined, but not all prerequesites" +#endif + +#if defined(MBEDTLS_MEMORY_DEBUG) && !defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) +#error "MBEDTLS_MEMORY_DEBUG defined, but not all prerequesites" +#endif + +#if defined(MBEDTLS_PADLOCK_C) && !defined(MBEDTLS_HAVE_ASM) +#error "MBEDTLS_PADLOCK_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) && !defined(MBEDTLS_BASE64_C) +#error "MBEDTLS_PEM_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PEM_WRITE_C) && !defined(MBEDTLS_BASE64_C) +#error "MBEDTLS_PEM_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PK_C) && \ + ( !defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_ECP_C) ) +#error "MBEDTLS_PK_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PK_PARSE_C) && !defined(MBEDTLS_PK_C) +#error "MBEDTLS_PK_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PK_WRITE_C) && !defined(MBEDTLS_PK_C) +#error "MBEDTLS_PK_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PKCS11_C) && !defined(MBEDTLS_PK_C) +#error "MBEDTLS_PKCS11_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PKCS11_C) +#if defined(MBEDTLS_DEPRECATED_REMOVED) +#error "MBEDTLS_PKCS11_C is deprecated and will be removed in a future version of Mbed TLS" +#elif defined(MBEDTLS_DEPRECATED_WARNING) +#warning "MBEDTLS_PKCS11_C is deprecated and will be removed in a future version of Mbed TLS" +#endif +#endif /* MBEDTLS_PKCS11_C */ + +#if defined(MBEDTLS_PLATFORM_EXIT_ALT) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_EXIT_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_EXIT_MACRO) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_EXIT_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_EXIT_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_EXIT) ||\ + defined(MBEDTLS_PLATFORM_EXIT_ALT) ) +#error "MBEDTLS_PLATFORM_EXIT_MACRO and MBEDTLS_PLATFORM_STD_EXIT/MBEDTLS_PLATFORM_EXIT_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_ALT) &&\ + ( !defined(MBEDTLS_PLATFORM_C) ||\ + !defined(MBEDTLS_HAVE_TIME) ) +#error "MBEDTLS_PLATFORM_TIME_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_MACRO) &&\ + ( !defined(MBEDTLS_PLATFORM_C) ||\ + !defined(MBEDTLS_HAVE_TIME) ) +#error "MBEDTLS_PLATFORM_TIME_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) &&\ + ( !defined(MBEDTLS_PLATFORM_C) ||\ + !defined(MBEDTLS_HAVE_TIME) ) +#error "MBEDTLS_PLATFORM_TIME_TYPE_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_TIME) ||\ + defined(MBEDTLS_PLATFORM_TIME_ALT) ) +#error "MBEDTLS_PLATFORM_TIME_MACRO and MBEDTLS_PLATFORM_STD_TIME/MBEDTLS_PLATFORM_TIME_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_TIME) ||\ + defined(MBEDTLS_PLATFORM_TIME_ALT) ) +#error "MBEDTLS_PLATFORM_TIME_TYPE_MACRO and MBEDTLS_PLATFORM_STD_TIME/MBEDTLS_PLATFORM_TIME_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_FPRINTF_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_FPRINTF_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_FPRINTF) ||\ + defined(MBEDTLS_PLATFORM_FPRINTF_ALT) ) +#error "MBEDTLS_PLATFORM_FPRINTF_MACRO and MBEDTLS_PLATFORM_STD_FPRINTF/MBEDTLS_PLATFORM_FPRINTF_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_FREE_MACRO) &&\ + ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) ) +#error "MBEDTLS_PLATFORM_FREE_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_FREE_MACRO) &&\ + defined(MBEDTLS_PLATFORM_STD_FREE) +#error "MBEDTLS_PLATFORM_FREE_MACRO and MBEDTLS_PLATFORM_STD_FREE cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_FREE_MACRO) && !defined(MBEDTLS_PLATFORM_CALLOC_MACRO) +#error "MBEDTLS_PLATFORM_CALLOC_MACRO must be defined if MBEDTLS_PLATFORM_FREE_MACRO is" +#endif + +#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&\ + ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) ) +#error "MBEDTLS_PLATFORM_CALLOC_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&\ + defined(MBEDTLS_PLATFORM_STD_CALLOC) +#error "MBEDTLS_PLATFORM_CALLOC_MACRO and MBEDTLS_PLATFORM_STD_CALLOC cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && !defined(MBEDTLS_PLATFORM_FREE_MACRO) +#error "MBEDTLS_PLATFORM_FREE_MACRO must be defined if MBEDTLS_PLATFORM_CALLOC_MACRO is" +#endif + +#if defined(MBEDTLS_PLATFORM_MEMORY) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_MEMORY defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_PRINTF_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_PRINTF_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_PRINTF) ||\ + defined(MBEDTLS_PLATFORM_PRINTF_ALT) ) +#error "MBEDTLS_PLATFORM_PRINTF_MACRO and MBEDTLS_PLATFORM_STD_PRINTF/MBEDTLS_PLATFORM_PRINTF_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_SNPRINTF_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_SNPRINTF_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_SNPRINTF) ||\ + defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) ) +#error "MBEDTLS_PLATFORM_SNPRINTF_MACRO and MBEDTLS_PLATFORM_STD_SNPRINTF/MBEDTLS_PLATFORM_SNPRINTF_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_MEM_HDR) &&\ + !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) +#error "MBEDTLS_PLATFORM_STD_MEM_HDR defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_CALLOC) && !defined(MBEDTLS_PLATFORM_MEMORY) +#error "MBEDTLS_PLATFORM_STD_CALLOC defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_CALLOC) && !defined(MBEDTLS_PLATFORM_MEMORY) +#error "MBEDTLS_PLATFORM_STD_CALLOC defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_FREE) && !defined(MBEDTLS_PLATFORM_MEMORY) +#error "MBEDTLS_PLATFORM_STD_FREE defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_EXIT) &&\ + !defined(MBEDTLS_PLATFORM_EXIT_ALT) +#error "MBEDTLS_PLATFORM_STD_EXIT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_TIME) &&\ + ( !defined(MBEDTLS_PLATFORM_TIME_ALT) ||\ + !defined(MBEDTLS_HAVE_TIME) ) +#error "MBEDTLS_PLATFORM_STD_TIME defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_FPRINTF) &&\ + !defined(MBEDTLS_PLATFORM_FPRINTF_ALT) +#error "MBEDTLS_PLATFORM_STD_FPRINTF defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_PRINTF) &&\ + !defined(MBEDTLS_PLATFORM_PRINTF_ALT) +#error "MBEDTLS_PLATFORM_STD_PRINTF defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_SNPRINTF) &&\ + !defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) +#error "MBEDTLS_PLATFORM_STD_SNPRINTF defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ENTROPY_NV_SEED) &&\ + ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_ENTROPY_C) ) +#error "MBEDTLS_ENTROPY_NV_SEED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) &&\ + !defined(MBEDTLS_ENTROPY_NV_SEED) +#error "MBEDTLS_PLATFORM_NV_SEED_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) &&\ + !defined(MBEDTLS_PLATFORM_NV_SEED_ALT) +#error "MBEDTLS_PLATFORM_STD_NV_SEED_READ defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) &&\ + !defined(MBEDTLS_PLATFORM_NV_SEED_ALT) +#error "MBEDTLS_PLATFORM_STD_NV_SEED_WRITE defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_NV_SEED_READ_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) ||\ + defined(MBEDTLS_PLATFORM_NV_SEED_ALT) ) +#error "MBEDTLS_PLATFORM_NV_SEED_READ_MACRO and MBEDTLS_PLATFORM_STD_NV_SEED_READ cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) ||\ + defined(MBEDTLS_PLATFORM_NV_SEED_ALT) ) +#error "MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO and MBEDTLS_PLATFORM_STD_NV_SEED_WRITE cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PSA_CRYPTO_C) && \ + !( defined(MBEDTLS_CTR_DRBG_C) && \ + defined(MBEDTLS_ENTROPY_C) ) +#error "MBEDTLS_PSA_CRYPTO_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PSA_CRYPTO_SPM) && !defined(MBEDTLS_PSA_CRYPTO_C) +#error "MBEDTLS_PSA_CRYPTO_SPM defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) && \ + ! ( defined(MBEDTLS_PSA_CRYPTO_C) && \ + defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) ) +#error "MBEDTLS_PSA_CRYPTO_SE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) && \ + ! defined(MBEDTLS_PSA_CRYPTO_C) +#error "MBEDTLS_PSA_CRYPTO_STORAGE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) && \ + !( defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) && \ + defined(MBEDTLS_ENTROPY_NV_SEED) ) +#error "MBEDTLS_PSA_INJECT_ENTROPY defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) && \ + !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) +#error "MBEDTLS_PSA_INJECT_ENTROPY is not compatible with actual entropy sources" +#endif + +#if defined(MBEDTLS_PSA_ITS_FILE_C) && \ + !defined(MBEDTLS_FS_IO) +#error "MBEDTLS_PSA_ITS_FILE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_RSA_C) && ( !defined(MBEDTLS_BIGNUM_C) || \ + !defined(MBEDTLS_OID_C) ) +#error "MBEDTLS_RSA_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_RSA_C) && ( !defined(MBEDTLS_PKCS1_V21) && \ + !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_RSA_C defined, but none of the PKCS1 versions enabled" +#endif + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && \ + ( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_PKCS1_V21) ) +#error "MBEDTLS_X509_RSASSA_PSS_SUPPORT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SHA512_NO_SHA384) && !defined(MBEDTLS_SHA512_C) +#error "MBEDTLS_SHA512_NO_SHA384 defined without MBEDTLS_SHA512_C" +#endif + +#if defined(MBEDTLS_SSL_PROTO_SSL3) && ( !defined(MBEDTLS_MD5_C) || \ + !defined(MBEDTLS_SHA1_C) ) +#error "MBEDTLS_SSL_PROTO_SSL3 defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1) && ( !defined(MBEDTLS_MD5_C) || \ + !defined(MBEDTLS_SHA1_C) ) +#error "MBEDTLS_SSL_PROTO_TLS1 defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) && ( !defined(MBEDTLS_MD5_C) || \ + !defined(MBEDTLS_SHA1_C) ) +#error "MBEDTLS_SSL_PROTO_TLS1_1 defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && ( !defined(MBEDTLS_SHA1_C) && \ + !defined(MBEDTLS_SHA256_C) && !defined(MBEDTLS_SHA512_C) ) +#error "MBEDTLS_SSL_PROTO_TLS1_2 defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL) && ( !defined(MBEDTLS_HKDF_C) && \ + !defined(MBEDTLS_SHA256_C) && !defined(MBEDTLS_SHA512_C) ) +#error "MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL defined, but not all prerequisites" +#endif + +#if (defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2)) && \ + !(defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) ) +#error "One or more versions of the TLS protocol are enabled " \ + "but no key exchange methods defined with MBEDTLS_KEY_EXCHANGE_xxxx" +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_2) +#error "MBEDTLS_SSL_PROTO_DTLS defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_CLI_C) && !defined(MBEDTLS_SSL_TLS_C) +#error "MBEDTLS_SSL_CLI_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) && ( !defined(MBEDTLS_CIPHER_C) || \ + !defined(MBEDTLS_MD_C) ) +#error "MBEDTLS_SSL_TLS_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_SRV_C) && !defined(MBEDTLS_SSL_TLS_C) +#error "MBEDTLS_SSL_SRV_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) && (!defined(MBEDTLS_SSL_PROTO_SSL3) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1) && !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_2)) +#error "MBEDTLS_SSL_TLS_C defined, but no protocols are active" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) && (defined(MBEDTLS_SSL_PROTO_SSL3) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) && !defined(MBEDTLS_SSL_PROTO_TLS1)) +#error "Illegal protocol selection" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) && (defined(MBEDTLS_SSL_PROTO_TLS1) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) && !defined(MBEDTLS_SSL_PROTO_TLS1_1)) +#error "Illegal protocol selection" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) && (defined(MBEDTLS_SSL_PROTO_SSL3) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) && (!defined(MBEDTLS_SSL_PROTO_TLS1) || \ + !defined(MBEDTLS_SSL_PROTO_TLS1_1))) +#error "Illegal protocol selection" +#endif + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && !defined(MBEDTLS_SSL_PROTO_DTLS) +#error "MBEDTLS_SSL_DTLS_HELLO_VERIFY defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && \ + !defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) +#error "MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) && \ + ( !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) ) +#error "MBEDTLS_SSL_DTLS_ANTI_REPLAY defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \ + ( !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) ) +#error "MBEDTLS_SSL_DTLS_CONNECTION_ID defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \ + defined(MBEDTLS_SSL_CID_IN_LEN_MAX) && \ + MBEDTLS_SSL_CID_IN_LEN_MAX > 255 +#error "MBEDTLS_SSL_CID_IN_LEN_MAX too large (max 255)" +#endif + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \ + defined(MBEDTLS_SSL_CID_OUT_LEN_MAX) && \ + MBEDTLS_SSL_CID_OUT_LEN_MAX > 255 +#error "MBEDTLS_SSL_CID_OUT_LEN_MAX too large (max 255)" +#endif + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) && \ + ( !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) ) +#error "MBEDTLS_SSL_DTLS_BADMAC_LIMIT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_2) +#error "MBEDTLS_SSL_ENCRYPT_THEN_MAC defined, but not all prerequsites" +#endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_2) +#error "MBEDTLS_SSL_EXTENDED_MASTER_SECRET defined, but not all prerequsites" +#endif + +#if defined(MBEDTLS_SSL_TICKET_C) && !defined(MBEDTLS_CIPHER_C) +#error "MBEDTLS_SSL_TICKET_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) && \ + !defined(MBEDTLS_SSL_PROTO_SSL3) && !defined(MBEDTLS_SSL_PROTO_TLS1) +#error "MBEDTLS_SSL_CBC_RECORD_SPLITTING defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) && \ + !defined(MBEDTLS_X509_CRT_PARSE_C) +#error "MBEDTLS_SSL_SERVER_NAME_INDICATION defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_THREADING_PTHREAD) +#if !defined(MBEDTLS_THREADING_C) || defined(MBEDTLS_THREADING_IMPL) +#error "MBEDTLS_THREADING_PTHREAD defined, but not all prerequisites" +#endif +#define MBEDTLS_THREADING_IMPL +#endif + +#if defined(MBEDTLS_THREADING_ALT) +#if !defined(MBEDTLS_THREADING_C) || defined(MBEDTLS_THREADING_IMPL) +#error "MBEDTLS_THREADING_ALT defined, but not all prerequisites" +#endif +#define MBEDTLS_THREADING_IMPL +#endif + +#if defined(MBEDTLS_THREADING_C) && !defined(MBEDTLS_THREADING_IMPL) +#error "MBEDTLS_THREADING_C defined, single threading implementation required" +#endif +#undef MBEDTLS_THREADING_IMPL + +#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_PSA_CRYPTO_C) +#error "MBEDTLS_USE_PSA_CRYPTO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_VERSION_FEATURES) && !defined(MBEDTLS_VERSION_C) +#error "MBEDTLS_VERSION_FEATURES defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_USE_C) && ( !defined(MBEDTLS_BIGNUM_C) || \ + !defined(MBEDTLS_OID_C) || !defined(MBEDTLS_ASN1_PARSE_C) || \ + !defined(MBEDTLS_PK_PARSE_C) ) +#error "MBEDTLS_X509_USE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CREATE_C) && ( !defined(MBEDTLS_BIGNUM_C) || \ + !defined(MBEDTLS_OID_C) || !defined(MBEDTLS_ASN1_WRITE_C) || \ + !defined(MBEDTLS_PK_WRITE_C) ) +#error "MBEDTLS_X509_CREATE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_CERTS_C) && !defined(MBEDTLS_X509_USE_C) +#error "MBEDTLS_CERTS_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) ) +#error "MBEDTLS_X509_CRT_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CRL_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) ) +#error "MBEDTLS_X509_CRL_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CSR_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) ) +#error "MBEDTLS_X509_CSR_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CRT_WRITE_C) && ( !defined(MBEDTLS_X509_CREATE_C) ) +#error "MBEDTLS_X509_CRT_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CSR_WRITE_C) && ( !defined(MBEDTLS_X509_CREATE_C) ) +#error "MBEDTLS_X509_CSR_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_HAVE_INT32) && defined(MBEDTLS_HAVE_INT64) +#error "MBEDTLS_HAVE_INT32 and MBEDTLS_HAVE_INT64 cannot be defined simultaneously" +#endif /* MBEDTLS_HAVE_INT32 && MBEDTLS_HAVE_INT64 */ + +#if ( defined(MBEDTLS_HAVE_INT32) || defined(MBEDTLS_HAVE_INT64) ) && \ + defined(MBEDTLS_HAVE_ASM) +#error "MBEDTLS_HAVE_INT32/MBEDTLS_HAVE_INT64 and MBEDTLS_HAVE_ASM cannot be defined simultaneously" +#endif /* (MBEDTLS_HAVE_INT32 || MBEDTLS_HAVE_INT64) && MBEDTLS_HAVE_ASM */ + +#if defined(MBEDTLS_SSL_PROTO_SSL3) +#if defined(MBEDTLS_DEPRECATED_REMOVED) +#error "MBEDTLS_SSL_PROTO_SSL3 is deprecated and will be removed in a future version of Mbed TLS" +#elif defined(MBEDTLS_DEPRECATED_WARNING) +#warning "MBEDTLS_SSL_PROTO_SSL3 is deprecated and will be removed in a future version of Mbed TLS" +#endif +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + +#if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) +#if defined(MBEDTLS_DEPRECATED_REMOVED) +#error "MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO is deprecated and will be removed in a future version of Mbed TLS" +#elif defined(MBEDTLS_DEPRECATED_WARNING) +#warning "MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO is deprecated and will be removed in a future version of Mbed TLS" +#endif +#endif /* MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO */ + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) +#if defined(MBEDTLS_DEPRECATED_REMOVED) +#error "MBEDTLS_SSL_HW_RECORD_ACCEL is deprecated and will be removed in a future version of Mbed TLS" +#elif defined(MBEDTLS_DEPRECATED_WARNING) +#warning "MBEDTLS_SSL_HW_RECORD_ACCEL is deprecated and will be removed in a future version of Mbed TLS" +#endif /* MBEDTLS_DEPRECATED_REMOVED */ +#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ + +#if defined(MBEDTLS_SSL_DTLS_SRTP) && ( !defined(MBEDTLS_SSL_PROTO_DTLS) ) +#error "MBEDTLS_SSL_DTLS_SRTP defined, but not all prerequisites" +#endif + +/* + * Avoid warning from -pedantic. This is a convenient place for this + * workaround since this is included by every single file before the + * #if defined(MBEDTLS_xxx_C) that results in empty translation units. + */ +typedef int mbedtls_iso_c_forbids_empty_translation_units; + +#endif /* MBEDTLS_CHECK_CONFIG_H */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/cipher.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/cipher.h new file mode 100644 index 0000000..8827e0b --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/cipher.h @@ -0,0 +1,944 @@ +/** + * \file cipher.h + * + * \brief This file contains an abstraction interface for use with the cipher + * primitives provided by the library. It provides a common interface to all of + * the available cipher operations. + * + * \author Adriaan de Jong + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_CIPHER_H +#define MBEDTLS_CIPHER_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include "mbedtls/platform_util.h" + +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) || defined(MBEDTLS_CHACHAPOLY_C) +#define MBEDTLS_CIPHER_MODE_AEAD +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#define MBEDTLS_CIPHER_MODE_WITH_PADDING +#endif + +#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) || \ + defined(MBEDTLS_CHACHA20_C) +#define MBEDTLS_CIPHER_MODE_STREAM +#endif + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#define MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE -0x6080 /**< The selected feature is not available. */ +#define MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA -0x6100 /**< Bad input parameters. */ +#define MBEDTLS_ERR_CIPHER_ALLOC_FAILED -0x6180 /**< Failed to allocate memory. */ +#define MBEDTLS_ERR_CIPHER_INVALID_PADDING -0x6200 /**< Input data contains invalid padding and is rejected. */ +#define MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED -0x6280 /**< Decryption of block requires a full block. */ +#define MBEDTLS_ERR_CIPHER_AUTH_FAILED -0x6300 /**< Authentication failed (for AEAD modes). */ +#define MBEDTLS_ERR_CIPHER_INVALID_CONTEXT -0x6380 /**< The context is invalid. For example, because it was freed. */ + +/* MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED -0x6400 /**< Cipher hardware accelerator failed. */ + +#define MBEDTLS_CIPHER_VARIABLE_IV_LEN 0x01 /**< Cipher accepts IVs of variable length. */ +#define MBEDTLS_CIPHER_VARIABLE_KEY_LEN 0x02 /**< Cipher accepts keys of variable length. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Supported cipher types. + * + * \warning RC4 and DES are considered weak ciphers and their use + * constitutes a security risk. Arm recommends considering stronger + * ciphers instead. + */ +typedef enum { + MBEDTLS_CIPHER_ID_NONE = 0, /**< Placeholder to mark the end of cipher ID lists. */ + MBEDTLS_CIPHER_ID_NULL, /**< The identity cipher, treated as a stream cipher. */ + MBEDTLS_CIPHER_ID_AES, /**< The AES cipher. */ + MBEDTLS_CIPHER_ID_DES, /**< The DES cipher. */ + MBEDTLS_CIPHER_ID_3DES, /**< The Triple DES cipher. */ + MBEDTLS_CIPHER_ID_CAMELLIA, /**< The Camellia cipher. */ + MBEDTLS_CIPHER_ID_BLOWFISH, /**< The Blowfish cipher. */ + MBEDTLS_CIPHER_ID_ARC4, /**< The RC4 cipher. */ + MBEDTLS_CIPHER_ID_ARIA, /**< The Aria cipher. */ + MBEDTLS_CIPHER_ID_CHACHA20, /**< The ChaCha20 cipher. */ +} mbedtls_cipher_id_t; + +/** + * \brief Supported {cipher type, cipher mode} pairs. + * + * \warning RC4 and DES are considered weak ciphers and their use + * constitutes a security risk. Arm recommends considering stronger + * ciphers instead. + */ +typedef enum { + MBEDTLS_CIPHER_NONE = 0, /**< Placeholder to mark the end of cipher-pair lists. */ + MBEDTLS_CIPHER_NULL, /**< The identity stream cipher. */ + MBEDTLS_CIPHER_AES_128_ECB, /**< AES cipher with 128-bit ECB mode. */ + MBEDTLS_CIPHER_AES_192_ECB, /**< AES cipher with 192-bit ECB mode. */ + MBEDTLS_CIPHER_AES_256_ECB, /**< AES cipher with 256-bit ECB mode. */ + MBEDTLS_CIPHER_AES_128_CBC, /**< AES cipher with 128-bit CBC mode. */ + MBEDTLS_CIPHER_AES_192_CBC, /**< AES cipher with 192-bit CBC mode. */ + MBEDTLS_CIPHER_AES_256_CBC, /**< AES cipher with 256-bit CBC mode. */ + MBEDTLS_CIPHER_AES_128_CFB128, /**< AES cipher with 128-bit CFB128 mode. */ + MBEDTLS_CIPHER_AES_192_CFB128, /**< AES cipher with 192-bit CFB128 mode. */ + MBEDTLS_CIPHER_AES_256_CFB128, /**< AES cipher with 256-bit CFB128 mode. */ + MBEDTLS_CIPHER_AES_128_CTR, /**< AES cipher with 128-bit CTR mode. */ + MBEDTLS_CIPHER_AES_192_CTR, /**< AES cipher with 192-bit CTR mode. */ + MBEDTLS_CIPHER_AES_256_CTR, /**< AES cipher with 256-bit CTR mode. */ + MBEDTLS_CIPHER_AES_128_GCM, /**< AES cipher with 128-bit GCM mode. */ + MBEDTLS_CIPHER_AES_192_GCM, /**< AES cipher with 192-bit GCM mode. */ + MBEDTLS_CIPHER_AES_256_GCM, /**< AES cipher with 256-bit GCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_ECB, /**< Camellia cipher with 128-bit ECB mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_ECB, /**< Camellia cipher with 192-bit ECB mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_ECB, /**< Camellia cipher with 256-bit ECB mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_CBC, /**< Camellia cipher with 128-bit CBC mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_CBC, /**< Camellia cipher with 192-bit CBC mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_CBC, /**< Camellia cipher with 256-bit CBC mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_CFB128, /**< Camellia cipher with 128-bit CFB128 mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_CFB128, /**< Camellia cipher with 192-bit CFB128 mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_CFB128, /**< Camellia cipher with 256-bit CFB128 mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_CTR, /**< Camellia cipher with 128-bit CTR mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_CTR, /**< Camellia cipher with 192-bit CTR mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_CTR, /**< Camellia cipher with 256-bit CTR mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_GCM, /**< Camellia cipher with 128-bit GCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_GCM, /**< Camellia cipher with 192-bit GCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_GCM, /**< Camellia cipher with 256-bit GCM mode. */ + MBEDTLS_CIPHER_DES_ECB, /**< DES cipher with ECB mode. */ + MBEDTLS_CIPHER_DES_CBC, /**< DES cipher with CBC mode. */ + MBEDTLS_CIPHER_DES_EDE_ECB, /**< DES cipher with EDE ECB mode. */ + MBEDTLS_CIPHER_DES_EDE_CBC, /**< DES cipher with EDE CBC mode. */ + MBEDTLS_CIPHER_DES_EDE3_ECB, /**< DES cipher with EDE3 ECB mode. */ + MBEDTLS_CIPHER_DES_EDE3_CBC, /**< DES cipher with EDE3 CBC mode. */ + MBEDTLS_CIPHER_BLOWFISH_ECB, /**< Blowfish cipher with ECB mode. */ + MBEDTLS_CIPHER_BLOWFISH_CBC, /**< Blowfish cipher with CBC mode. */ + MBEDTLS_CIPHER_BLOWFISH_CFB64, /**< Blowfish cipher with CFB64 mode. */ + MBEDTLS_CIPHER_BLOWFISH_CTR, /**< Blowfish cipher with CTR mode. */ + MBEDTLS_CIPHER_ARC4_128, /**< RC4 cipher with 128-bit mode. */ + MBEDTLS_CIPHER_AES_128_CCM, /**< AES cipher with 128-bit CCM mode. */ + MBEDTLS_CIPHER_AES_192_CCM, /**< AES cipher with 192-bit CCM mode. */ + MBEDTLS_CIPHER_AES_256_CCM, /**< AES cipher with 256-bit CCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_CCM, /**< Camellia cipher with 128-bit CCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_CCM, /**< Camellia cipher with 192-bit CCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_CCM, /**< Camellia cipher with 256-bit CCM mode. */ + MBEDTLS_CIPHER_ARIA_128_ECB, /**< Aria cipher with 128-bit key and ECB mode. */ + MBEDTLS_CIPHER_ARIA_192_ECB, /**< Aria cipher with 192-bit key and ECB mode. */ + MBEDTLS_CIPHER_ARIA_256_ECB, /**< Aria cipher with 256-bit key and ECB mode. */ + MBEDTLS_CIPHER_ARIA_128_CBC, /**< Aria cipher with 128-bit key and CBC mode. */ + MBEDTLS_CIPHER_ARIA_192_CBC, /**< Aria cipher with 192-bit key and CBC mode. */ + MBEDTLS_CIPHER_ARIA_256_CBC, /**< Aria cipher with 256-bit key and CBC mode. */ + MBEDTLS_CIPHER_ARIA_128_CFB128, /**< Aria cipher with 128-bit key and CFB-128 mode. */ + MBEDTLS_CIPHER_ARIA_192_CFB128, /**< Aria cipher with 192-bit key and CFB-128 mode. */ + MBEDTLS_CIPHER_ARIA_256_CFB128, /**< Aria cipher with 256-bit key and CFB-128 mode. */ + MBEDTLS_CIPHER_ARIA_128_CTR, /**< Aria cipher with 128-bit key and CTR mode. */ + MBEDTLS_CIPHER_ARIA_192_CTR, /**< Aria cipher with 192-bit key and CTR mode. */ + MBEDTLS_CIPHER_ARIA_256_CTR, /**< Aria cipher with 256-bit key and CTR mode. */ + MBEDTLS_CIPHER_ARIA_128_GCM, /**< Aria cipher with 128-bit key and GCM mode. */ + MBEDTLS_CIPHER_ARIA_192_GCM, /**< Aria cipher with 192-bit key and GCM mode. */ + MBEDTLS_CIPHER_ARIA_256_GCM, /**< Aria cipher with 256-bit key and GCM mode. */ + MBEDTLS_CIPHER_ARIA_128_CCM, /**< Aria cipher with 128-bit key and CCM mode. */ + MBEDTLS_CIPHER_ARIA_192_CCM, /**< Aria cipher with 192-bit key and CCM mode. */ + MBEDTLS_CIPHER_ARIA_256_CCM, /**< Aria cipher with 256-bit key and CCM mode. */ + MBEDTLS_CIPHER_AES_128_OFB, /**< AES 128-bit cipher in OFB mode. */ + MBEDTLS_CIPHER_AES_192_OFB, /**< AES 192-bit cipher in OFB mode. */ + MBEDTLS_CIPHER_AES_256_OFB, /**< AES 256-bit cipher in OFB mode. */ + MBEDTLS_CIPHER_AES_128_XTS, /**< AES 128-bit cipher in XTS block mode. */ + MBEDTLS_CIPHER_AES_256_XTS, /**< AES 256-bit cipher in XTS block mode. */ + MBEDTLS_CIPHER_CHACHA20, /**< ChaCha20 stream cipher. */ + MBEDTLS_CIPHER_CHACHA20_POLY1305, /**< ChaCha20-Poly1305 AEAD cipher. */ + MBEDTLS_CIPHER_AES_128_KW, /**< AES cipher with 128-bit NIST KW mode. */ + MBEDTLS_CIPHER_AES_192_KW, /**< AES cipher with 192-bit NIST KW mode. */ + MBEDTLS_CIPHER_AES_256_KW, /**< AES cipher with 256-bit NIST KW mode. */ + MBEDTLS_CIPHER_AES_128_KWP, /**< AES cipher with 128-bit NIST KWP mode. */ + MBEDTLS_CIPHER_AES_192_KWP, /**< AES cipher with 192-bit NIST KWP mode. */ + MBEDTLS_CIPHER_AES_256_KWP, /**< AES cipher with 256-bit NIST KWP mode. */ +} mbedtls_cipher_type_t; + +/** Supported cipher modes. */ +typedef enum { + MBEDTLS_MODE_NONE = 0, /**< None. */ + MBEDTLS_MODE_ECB, /**< The ECB cipher mode. */ + MBEDTLS_MODE_CBC, /**< The CBC cipher mode. */ + MBEDTLS_MODE_CFB, /**< The CFB cipher mode. */ + MBEDTLS_MODE_OFB, /**< The OFB cipher mode. */ + MBEDTLS_MODE_CTR, /**< The CTR cipher mode. */ + MBEDTLS_MODE_GCM, /**< The GCM cipher mode. */ + MBEDTLS_MODE_STREAM, /**< The stream cipher mode. */ + MBEDTLS_MODE_CCM, /**< The CCM cipher mode. */ + MBEDTLS_MODE_XTS, /**< The XTS cipher mode. */ + MBEDTLS_MODE_CHACHAPOLY, /**< The ChaCha-Poly cipher mode. */ + MBEDTLS_MODE_KW, /**< The SP800-38F KW mode */ + MBEDTLS_MODE_KWP, /**< The SP800-38F KWP mode */ +} mbedtls_cipher_mode_t; + +/** Supported cipher padding types. */ +typedef enum { + MBEDTLS_PADDING_PKCS7 = 0, /**< PKCS7 padding (default). */ + MBEDTLS_PADDING_ONE_AND_ZEROS, /**< ISO/IEC 7816-4 padding. */ + MBEDTLS_PADDING_ZEROS_AND_LEN, /**< ANSI X.923 padding. */ + MBEDTLS_PADDING_ZEROS, /**< Zero padding (not reversible). */ + MBEDTLS_PADDING_NONE, /**< Never pad (full blocks only). */ +} mbedtls_cipher_padding_t; + +/** Type of operation. */ +typedef enum { + MBEDTLS_OPERATION_NONE = -1, + MBEDTLS_DECRYPT = 0, + MBEDTLS_ENCRYPT, +} mbedtls_operation_t; + +enum { + /** Undefined key length. */ + MBEDTLS_KEY_LENGTH_NONE = 0, + /** Key length, in bits (including parity), for DES keys. */ + MBEDTLS_KEY_LENGTH_DES = 64, + /** Key length in bits, including parity, for DES in two-key EDE. */ + MBEDTLS_KEY_LENGTH_DES_EDE = 128, + /** Key length in bits, including parity, for DES in three-key EDE. */ + MBEDTLS_KEY_LENGTH_DES_EDE3 = 192, +}; + +/** Maximum length of any IV, in Bytes. */ +/* This should ideally be derived automatically from list of ciphers. + * This should be kept in sync with MBEDTLS_SSL_MAX_IV_LENGTH defined + * in ssl_internal.h. */ +#define MBEDTLS_MAX_IV_LENGTH 16 + +/** Maximum block size of any cipher, in Bytes. */ +/* This should ideally be derived automatically from list of ciphers. + * This should be kept in sync with MBEDTLS_SSL_MAX_BLOCK_LENGTH defined + * in ssl_internal.h. */ +#define MBEDTLS_MAX_BLOCK_LENGTH 16 + +/** Maximum key length, in Bytes. */ +/* This should ideally be derived automatically from list of ciphers. + * For now, only check whether XTS is enabled which uses 64 Byte keys, + * and use 32 Bytes as an upper bound for the maximum key length otherwise. + * This should be kept in sync with MBEDTLS_SSL_MAX_BLOCK_LENGTH defined + * in ssl_internal.h, which however deliberately ignores the case of XTS + * since the latter isn't used in SSL/TLS. */ +#if defined(MBEDTLS_CIPHER_MODE_XTS) +#define MBEDTLS_MAX_KEY_LENGTH 64 +#else +#define MBEDTLS_MAX_KEY_LENGTH 32 +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +/** + * Base cipher information (opaque struct). + */ +typedef struct mbedtls_cipher_base_t mbedtls_cipher_base_t; + +/** + * CMAC context (opaque struct). + */ +typedef struct mbedtls_cmac_context_t mbedtls_cmac_context_t; + +/** + * Cipher information. Allows calling cipher functions + * in a generic way. + */ +typedef struct mbedtls_cipher_info_t +{ + /** Full cipher identifier. For example, + * MBEDTLS_CIPHER_AES_256_CBC. + */ + mbedtls_cipher_type_t type; + + /** The cipher mode. For example, MBEDTLS_MODE_CBC. */ + mbedtls_cipher_mode_t mode; + + /** The cipher key length, in bits. This is the + * default length for variable sized ciphers. + * Includes parity bits for ciphers like DES. + */ + unsigned int key_bitlen; + + /** Name of the cipher. */ + const char * name; + + /** IV or nonce size, in Bytes. + * For ciphers that accept variable IV sizes, + * this is the recommended size. + */ + unsigned int iv_size; + + /** Bitflag comprised of MBEDTLS_CIPHER_VARIABLE_IV_LEN and + * MBEDTLS_CIPHER_VARIABLE_KEY_LEN indicating whether the + * cipher supports variable IV or variable key sizes, respectively. + */ + int flags; + + /** The block size, in Bytes. */ + unsigned int block_size; + + /** Struct for base cipher information and functions. */ + const mbedtls_cipher_base_t *base; + +} mbedtls_cipher_info_t; + +/** + * Generic cipher context. + */ +typedef struct mbedtls_cipher_context_t +{ + /** Information about the associated cipher. */ + const mbedtls_cipher_info_t *cipher_info; + + /** Key length to use. */ + int key_bitlen; + + /** Operation that the key of the context has been + * initialized for. + */ + mbedtls_operation_t operation; + +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) + /** Padding functions to use, if relevant for + * the specific cipher mode. + */ + void (*add_padding)( unsigned char *output, size_t olen, size_t data_len ); + int (*get_padding)( unsigned char *input, size_t ilen, size_t *data_len ); +#endif + + /** Buffer for input that has not been processed yet. */ + unsigned char unprocessed_data[MBEDTLS_MAX_BLOCK_LENGTH]; + + /** Number of Bytes that have not been processed yet. */ + size_t unprocessed_len; + + /** Current IV or NONCE_COUNTER for CTR-mode, data unit (or sector) number + * for XTS-mode. */ + unsigned char iv[MBEDTLS_MAX_IV_LENGTH]; + + /** IV size in Bytes, for ciphers with variable-length IVs. */ + size_t iv_size; + + /** The cipher-specific context. */ + void *cipher_ctx; + +#if defined(MBEDTLS_CMAC_C) + /** CMAC-specific context. */ + mbedtls_cmac_context_t *cmac_ctx; +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + /** Indicates whether the cipher operations should be performed + * by Mbed TLS' own crypto library or an external implementation + * of the PSA Crypto API. + * This is unset if the cipher context was established through + * mbedtls_cipher_setup(), and set if it was established through + * mbedtls_cipher_setup_psa(). + */ + unsigned char psa_enabled; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +} mbedtls_cipher_context_t; + +/** + * \brief This function retrieves the list of ciphers supported + * by the generic cipher module. + * + * For any cipher identifier in the returned list, you can + * obtain the corresponding generic cipher information structure + * via mbedtls_cipher_info_from_type(), which can then be used + * to prepare a cipher context via mbedtls_cipher_setup(). + * + * + * \return A statically-allocated array of cipher identifiers + * of type cipher_type_t. The last entry is zero. + */ +const int *mbedtls_cipher_list( void ); + +/** + * \brief This function retrieves the cipher-information + * structure associated with the given cipher name. + * + * \param cipher_name Name of the cipher to search for. This must not be + * \c NULL. + * + * \return The cipher information structure associated with the + * given \p cipher_name. + * \return \c NULL if the associated cipher information is not found. + */ +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( const char *cipher_name ); + +/** + * \brief This function retrieves the cipher-information + * structure associated with the given cipher type. + * + * \param cipher_type Type of the cipher to search for. + * + * \return The cipher information structure associated with the + * given \p cipher_type. + * \return \c NULL if the associated cipher information is not found. + */ +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( const mbedtls_cipher_type_t cipher_type ); + +/** + * \brief This function retrieves the cipher-information + * structure associated with the given cipher ID, + * key size and mode. + * + * \param cipher_id The ID of the cipher to search for. For example, + * #MBEDTLS_CIPHER_ID_AES. + * \param key_bitlen The length of the key in bits. + * \param mode The cipher mode. For example, #MBEDTLS_MODE_CBC. + * + * \return The cipher information structure associated with the + * given \p cipher_id. + * \return \c NULL if the associated cipher information is not found. + */ +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( const mbedtls_cipher_id_t cipher_id, + int key_bitlen, + const mbedtls_cipher_mode_t mode ); + +/** + * \brief This function initializes a \p cipher_context as NONE. + * + * \param ctx The context to be initialized. This must not be \c NULL. + */ +void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx ); + +/** + * \brief This function frees and clears the cipher-specific + * context of \p ctx. Freeing \p ctx itself remains the + * responsibility of the caller. + * + * \param ctx The context to be freed. If this is \c NULL, the + * function has no effect, otherwise this must point to an + * initialized context. + */ +void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx ); + + +/** + * \brief This function initializes a cipher context for + * use with the given cipher primitive. + * + * \param ctx The context to initialize. This must be initialized. + * \param cipher_info The cipher to use. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_ALLOC_FAILED if allocation of the + * cipher-specific context fails. + * + * \internal Currently, the function also clears the structure. + * In future versions, the caller will be required to call + * mbedtls_cipher_init() on the structure first. + */ +int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, + const mbedtls_cipher_info_t *cipher_info ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/** + * \brief This function initializes a cipher context for + * PSA-based use with the given cipher primitive. + * + * \note See #MBEDTLS_USE_PSA_CRYPTO for information on PSA. + * + * \param ctx The context to initialize. May not be \c NULL. + * \param cipher_info The cipher to use. + * \param taglen For AEAD ciphers, the length in bytes of the + * authentication tag to use. Subsequent uses of + * mbedtls_cipher_auth_encrypt() or + * mbedtls_cipher_auth_decrypt() must provide + * the same tag length. + * For non-AEAD ciphers, the value must be \c 0. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_ALLOC_FAILED if allocation of the + * cipher-specific context fails. + */ +int mbedtls_cipher_setup_psa( mbedtls_cipher_context_t *ctx, + const mbedtls_cipher_info_t *cipher_info, + size_t taglen ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +/** + * \brief This function returns the block size of the given cipher. + * + * \param ctx The context of the cipher. This must be initialized. + * + * \return The block size of the underlying cipher. + * \return \c 0 if \p ctx has not been initialized. + */ +static inline unsigned int mbedtls_cipher_get_block_size( + const mbedtls_cipher_context_t *ctx ) +{ + MBEDTLS_INTERNAL_VALIDATE_RET( ctx != NULL, 0 ); + if( ctx->cipher_info == NULL ) + return 0; + + return ctx->cipher_info->block_size; +} + +/** + * \brief This function returns the mode of operation for + * the cipher. For example, MBEDTLS_MODE_CBC. + * + * \param ctx The context of the cipher. This must be initialized. + * + * \return The mode of operation. + * \return #MBEDTLS_MODE_NONE if \p ctx has not been initialized. + */ +static inline mbedtls_cipher_mode_t mbedtls_cipher_get_cipher_mode( + const mbedtls_cipher_context_t *ctx ) +{ + MBEDTLS_INTERNAL_VALIDATE_RET( ctx != NULL, MBEDTLS_MODE_NONE ); + if( ctx->cipher_info == NULL ) + return MBEDTLS_MODE_NONE; + + return ctx->cipher_info->mode; +} + +/** + * \brief This function returns the size of the IV or nonce + * of the cipher, in Bytes. + * + * \param ctx The context of the cipher. This must be initialized. + * + * \return The recommended IV size if no IV has been set. + * \return \c 0 for ciphers not using an IV or a nonce. + * \return The actual size if an IV has been set. + */ +static inline int mbedtls_cipher_get_iv_size( + const mbedtls_cipher_context_t *ctx ) +{ + MBEDTLS_INTERNAL_VALIDATE_RET( ctx != NULL, 0 ); + if( ctx->cipher_info == NULL ) + return 0; + + if( ctx->iv_size != 0 ) + return (int) ctx->iv_size; + + return (int) ctx->cipher_info->iv_size; +} + +/** + * \brief This function returns the type of the given cipher. + * + * \param ctx The context of the cipher. This must be initialized. + * + * \return The type of the cipher. + * \return #MBEDTLS_CIPHER_NONE if \p ctx has not been initialized. + */ +static inline mbedtls_cipher_type_t mbedtls_cipher_get_type( + const mbedtls_cipher_context_t *ctx ) +{ + MBEDTLS_INTERNAL_VALIDATE_RET( + ctx != NULL, MBEDTLS_CIPHER_NONE ); + if( ctx->cipher_info == NULL ) + return MBEDTLS_CIPHER_NONE; + + return ctx->cipher_info->type; +} + +/** + * \brief This function returns the name of the given cipher + * as a string. + * + * \param ctx The context of the cipher. This must be initialized. + * + * \return The name of the cipher. + * \return NULL if \p ctx has not been not initialized. + */ +static inline const char *mbedtls_cipher_get_name( + const mbedtls_cipher_context_t *ctx ) +{ + MBEDTLS_INTERNAL_VALIDATE_RET( ctx != NULL, 0 ); + if( ctx->cipher_info == NULL ) + return 0; + + return ctx->cipher_info->name; +} + +/** + * \brief This function returns the key length of the cipher. + * + * \param ctx The context of the cipher. This must be initialized. + * + * \return The key length of the cipher in bits. + * \return #MBEDTLS_KEY_LENGTH_NONE if ctx \p has not been + * initialized. + */ +static inline int mbedtls_cipher_get_key_bitlen( + const mbedtls_cipher_context_t *ctx ) +{ + MBEDTLS_INTERNAL_VALIDATE_RET( + ctx != NULL, MBEDTLS_KEY_LENGTH_NONE ); + if( ctx->cipher_info == NULL ) + return MBEDTLS_KEY_LENGTH_NONE; + + return (int) ctx->cipher_info->key_bitlen; +} + +/** + * \brief This function returns the operation of the given cipher. + * + * \param ctx The context of the cipher. This must be initialized. + * + * \return The type of operation: #MBEDTLS_ENCRYPT or #MBEDTLS_DECRYPT. + * \return #MBEDTLS_OPERATION_NONE if \p ctx has not been initialized. + */ +static inline mbedtls_operation_t mbedtls_cipher_get_operation( + const mbedtls_cipher_context_t *ctx ) +{ + MBEDTLS_INTERNAL_VALIDATE_RET( + ctx != NULL, MBEDTLS_OPERATION_NONE ); + if( ctx->cipher_info == NULL ) + return MBEDTLS_OPERATION_NONE; + + return ctx->operation; +} + +/** + * \brief This function sets the key to use with the given context. + * + * \param ctx The generic cipher context. This must be initialized and + * bound to a cipher information structure. + * \param key The key to use. This must be a readable buffer of at + * least \p key_bitlen Bits. + * \param key_bitlen The key length to use, in Bits. + * \param operation The operation that the key will be used for: + * #MBEDTLS_ENCRYPT or #MBEDTLS_DECRYPT. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, + const unsigned char *key, + int key_bitlen, + const mbedtls_operation_t operation ); + +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) +/** + * \brief This function sets the padding mode, for cipher modes + * that use padding. + * + * The default passing mode is PKCS7 padding. + * + * \param ctx The generic cipher context. This must be initialized and + * bound to a cipher information structure. + * \param mode The padding mode. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE + * if the selected padding mode is not supported. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if the cipher mode + * does not support padding. + */ +int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, + mbedtls_cipher_padding_t mode ); +#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ + +/** + * \brief This function sets the initialization vector (IV) + * or nonce. + * + * \note Some ciphers do not use IVs nor nonce. For these + * ciphers, this function has no effect. + * + * \param ctx The generic cipher context. This must be initialized and + * bound to a cipher information structure. + * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. This + * must be a readable buffer of at least \p iv_len Bytes. + * \param iv_len The IV length for ciphers with variable-size IV. + * This parameter is discarded by ciphers with fixed-size IV. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + */ +int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, + size_t iv_len ); + +/** + * \brief This function resets the cipher state. + * + * \param ctx The generic cipher context. This must be initialized. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + */ +int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx ); + +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) +/** + * \brief This function adds additional data for AEAD ciphers. + * Currently supported with GCM and ChaCha20+Poly1305. + * This must be called exactly once, after + * mbedtls_cipher_reset(). + * + * \param ctx The generic cipher context. This must be initialized. + * \param ad The additional data to use. This must be a readable + * buffer of at least \p ad_len Bytes. + * \param ad_len The length of \p ad in Bytes. + * + * \return \c 0 on success. + * \return A specific error code on failure. + */ +int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx, + const unsigned char *ad, size_t ad_len ); +#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ + +/** + * \brief The generic cipher update function. It encrypts or + * decrypts using the given cipher context. Writes as + * many block-sized blocks of data as possible to output. + * Any data that cannot be written immediately is either + * added to the next block, or flushed when + * mbedtls_cipher_finish() is called. + * Exception: For MBEDTLS_MODE_ECB, expects a single block + * in size. For example, 16 Bytes for AES. + * + * \note If the underlying cipher is used in GCM mode, all calls + * to this function, except for the last one before + * mbedtls_cipher_finish(), must have \p ilen as a + * multiple of the block size of the cipher. + * + * \param ctx The generic cipher context. This must be initialized and + * bound to a key. + * \param input The buffer holding the input data. This must be a + * readable buffer of at least \p ilen Bytes. + * \param ilen The length of the input data. + * \param output The buffer for the output data. This must be able to + * hold at least `ilen + block_size`. This must not be the + * same buffer as \p input. + * \param olen The length of the output data, to be updated with the + * actual number of Bytes written. This must not be + * \c NULL. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE on an + * unsupported mode for a cipher. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, + const unsigned char *input, + size_t ilen, unsigned char *output, + size_t *olen ); + +/** + * \brief The generic cipher finalization function. If data still + * needs to be flushed from an incomplete block, the data + * contained in it is padded to the size of + * the last block, and written to the \p output buffer. + * + * \param ctx The generic cipher context. This must be initialized and + * bound to a key. + * \param output The buffer to write data to. This needs to be a writable + * buffer of at least \p block_size Bytes. + * \param olen The length of the data written to the \p output buffer. + * This may not be \c NULL. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED on decryption + * expecting a full block but not receiving one. + * \return #MBEDTLS_ERR_CIPHER_INVALID_PADDING on invalid padding + * while decrypting. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx, + unsigned char *output, size_t *olen ); + +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) +/** + * \brief This function writes a tag for AEAD ciphers. + * Currently supported with GCM and ChaCha20+Poly1305. + * This must be called after mbedtls_cipher_finish(). + * + * \param ctx The generic cipher context. This must be initialized, + * bound to a key, and have just completed a cipher + * operation through mbedtls_cipher_finish() the tag for + * which should be written. + * \param tag The buffer to write the tag to. This must be a writable + * buffer of at least \p tag_len Bytes. + * \param tag_len The length of the tag to write. + * + * \return \c 0 on success. + * \return A specific error code on failure. + */ +int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx, + unsigned char *tag, size_t tag_len ); + +/** + * \brief This function checks the tag for AEAD ciphers. + * Currently supported with GCM and ChaCha20+Poly1305. + * This must be called after mbedtls_cipher_finish(). + * + * \param ctx The generic cipher context. This must be initialized. + * \param tag The buffer holding the tag. This must be a readable + * buffer of at least \p tag_len Bytes. + * \param tag_len The length of the tag to check. + * + * \return \c 0 on success. + * \return A specific error code on failure. + */ +int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx, + const unsigned char *tag, size_t tag_len ); +#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ + +/** + * \brief The generic all-in-one encryption/decryption function, + * for all ciphers except AEAD constructs. + * + * \param ctx The generic cipher context. This must be initialized. + * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. + * This must be a readable buffer of at least \p iv_len + * Bytes. + * \param iv_len The IV length for ciphers with variable-size IV. + * This parameter is discarded by ciphers with fixed-size + * IV. + * \param input The buffer holding the input data. This must be a + * readable buffer of at least \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * \param output The buffer for the output data. This must be able to + * hold at least `ilen + block_size`. This must not be the + * same buffer as \p input. + * \param olen The length of the output data, to be updated with the + * actual number of Bytes written. This must not be + * \c NULL. + * + * \note Some ciphers do not use IVs nor nonce. For these + * ciphers, use \p iv = NULL and \p iv_len = 0. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED on decryption + * expecting a full block but not receiving one. + * \return #MBEDTLS_ERR_CIPHER_INVALID_PADDING on invalid padding + * while decrypting. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen ); + +#if defined(MBEDTLS_CIPHER_MODE_AEAD) +/** + * \brief The generic autenticated encryption (AEAD) function. + * + * \param ctx The generic cipher context. This must be initialized and + * bound to a key. + * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. + * This must be a readable buffer of at least \p iv_len + * Bytes. + * \param iv_len The IV length for ciphers with variable-size IV. + * This parameter is discarded by ciphers with fixed-size IV. + * \param ad The additional data to authenticate. This must be a + * readable buffer of at least \p ad_len Bytes. + * \param ad_len The length of \p ad. + * \param input The buffer holding the input data. This must be a + * readable buffer of at least \p ilen Bytes. + * \param ilen The length of the input data. + * \param output The buffer for the output data. This must be able to + * hold at least \p ilen Bytes. + * \param olen The length of the output data, to be updated with the + * actual number of Bytes written. This must not be + * \c NULL. + * \param tag The buffer for the authentication tag. This must be a + * writable buffer of at least \p tag_len Bytes. + * \param tag_len The desired length of the authentication tag. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, + unsigned char *tag, size_t tag_len ); + +/** + * \brief The generic autenticated decryption (AEAD) function. + * + * \note If the data is not authentic, then the output buffer + * is zeroed out to prevent the unauthentic plaintext being + * used, making this interface safer. + * + * \param ctx The generic cipher context. This must be initialized and + * and bound to a key. + * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. + * This must be a readable buffer of at least \p iv_len + * Bytes. + * \param iv_len The IV length for ciphers with variable-size IV. + * This parameter is discarded by ciphers with fixed-size IV. + * \param ad The additional data to be authenticated. This must be a + * readable buffer of at least \p ad_len Bytes. + * \param ad_len The length of \p ad. + * \param input The buffer holding the input data. This must be a + * readable buffer of at least \p ilen Bytes. + * \param ilen The length of the input data. + * \param output The buffer for the output data. + * This must be able to hold at least \p ilen Bytes. + * \param olen The length of the output data, to be updated with the + * actual number of Bytes written. This must not be + * \c NULL. + * \param tag The buffer holding the authentication tag. This must be + * a readable buffer of at least \p tag_len Bytes. + * \param tag_len The length of the authentication tag. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_AUTH_FAILED if data is not authentic. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, + const unsigned char *tag, size_t tag_len ); +#endif /* MBEDTLS_CIPHER_MODE_AEAD */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CIPHER_H */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/cipher_internal.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/cipher_internal.h new file mode 100644 index 0000000..d283108 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/cipher_internal.h @@ -0,0 +1,150 @@ +/** + * \file cipher_internal.h + * + * \brief Cipher wrappers. + * + * \author Adriaan de Jong + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_CIPHER_WRAP_H +#define MBEDTLS_CIPHER_WRAP_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/cipher.h" + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Base cipher information. The non-mode specific functions and values. + */ +struct mbedtls_cipher_base_t +{ + /** Base Cipher type (e.g. MBEDTLS_CIPHER_ID_AES) */ + mbedtls_cipher_id_t cipher; + + /** Encrypt using ECB */ + int (*ecb_func)( void *ctx, mbedtls_operation_t mode, + const unsigned char *input, unsigned char *output ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + /** Encrypt using CBC */ + int (*cbc_func)( void *ctx, mbedtls_operation_t mode, size_t length, + unsigned char *iv, const unsigned char *input, + unsigned char *output ); +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CFB) + /** Encrypt using CFB (Full length) */ + int (*cfb_func)( void *ctx, mbedtls_operation_t mode, size_t length, size_t *iv_off, + unsigned char *iv, const unsigned char *input, + unsigned char *output ); +#endif + +#if defined(MBEDTLS_CIPHER_MODE_OFB) + /** Encrypt using OFB (Full length) */ + int (*ofb_func)( void *ctx, size_t length, size_t *iv_off, + unsigned char *iv, + const unsigned char *input, + unsigned char *output ); +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CTR) + /** Encrypt using CTR */ + int (*ctr_func)( void *ctx, size_t length, size_t *nc_off, + unsigned char *nonce_counter, unsigned char *stream_block, + const unsigned char *input, unsigned char *output ); +#endif + +#if defined(MBEDTLS_CIPHER_MODE_XTS) + /** Encrypt or decrypt using XTS. */ + int (*xts_func)( void *ctx, mbedtls_operation_t mode, size_t length, + const unsigned char data_unit[16], + const unsigned char *input, unsigned char *output ); +#endif + +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + /** Encrypt using STREAM */ + int (*stream_func)( void *ctx, size_t length, + const unsigned char *input, unsigned char *output ); +#endif + + /** Set key for encryption purposes */ + int (*setkey_enc_func)( void *ctx, const unsigned char *key, + unsigned int key_bitlen ); + + /** Set key for decryption purposes */ + int (*setkey_dec_func)( void *ctx, const unsigned char *key, + unsigned int key_bitlen); + + /** Allocate a new context */ + void * (*ctx_alloc_func)( void ); + + /** Free the given context */ + void (*ctx_free_func)( void *ctx ); + +}; + +typedef struct +{ + mbedtls_cipher_type_t type; + const mbedtls_cipher_info_t *info; +} mbedtls_cipher_definition_t; + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +typedef enum +{ + MBEDTLS_CIPHER_PSA_KEY_UNSET = 0, + MBEDTLS_CIPHER_PSA_KEY_OWNED, /* Used for PSA-based cipher contexts which */ + /* use raw key material internally imported */ + /* as a volatile key, and which hence need */ + /* to destroy that key when the context is */ + /* freed. */ + MBEDTLS_CIPHER_PSA_KEY_NOT_OWNED, /* Used for PSA-based cipher contexts */ + /* which use a key provided by the */ + /* user, and which hence will not be */ + /* destroyed when the context is freed. */ +} mbedtls_cipher_psa_key_ownership; + +typedef struct +{ + psa_algorithm_t alg; + psa_key_handle_t slot; + mbedtls_cipher_psa_key_ownership slot_state; +} mbedtls_cipher_context_psa; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +extern const mbedtls_cipher_definition_t mbedtls_cipher_definitions[]; + +extern int mbedtls_cipher_supported[]; + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CIPHER_WRAP_H */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/cmac.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/cmac.h new file mode 100644 index 0000000..cb538d0 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/cmac.h @@ -0,0 +1,211 @@ +/** + * \file cmac.h + * + * \brief This file contains CMAC definitions and functions. + * + * The Cipher-based Message Authentication Code (CMAC) Mode for + * Authentication is defined in RFC-4493: The AES-CMAC Algorithm. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_CMAC_H +#define MBEDTLS_CMAC_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/cipher.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED -0x007A /**< CMAC hardware accelerator failed. */ + +#define MBEDTLS_AES_BLOCK_SIZE 16 +#define MBEDTLS_DES3_BLOCK_SIZE 8 + +#if defined(MBEDTLS_AES_C) +#define MBEDTLS_CIPHER_BLKSIZE_MAX 16 /**< The longest block used by CMAC is that of AES. */ +#else +#define MBEDTLS_CIPHER_BLKSIZE_MAX 8 /**< The longest block used by CMAC is that of 3DES. */ +#endif + +#if !defined(MBEDTLS_CMAC_ALT) + +/** + * The CMAC context structure. + */ +struct mbedtls_cmac_context_t +{ + /** The internal state of the CMAC algorithm. */ + unsigned char state[MBEDTLS_CIPHER_BLKSIZE_MAX]; + + /** Unprocessed data - either data that was not block aligned and is still + * pending processing, or the final block. */ + unsigned char unprocessed_block[MBEDTLS_CIPHER_BLKSIZE_MAX]; + + /** The length of data pending processing. */ + size_t unprocessed_len; +}; + +#else /* !MBEDTLS_CMAC_ALT */ +#include "cmac_alt.h" +#endif /* !MBEDTLS_CMAC_ALT */ + +/** + * \brief This function sets the CMAC key, and prepares to authenticate + * the input data. + * Must be called with an initialized cipher context. + * + * \param ctx The cipher context used for the CMAC operation, initialized + * as one of the following types: MBEDTLS_CIPHER_AES_128_ECB, + * MBEDTLS_CIPHER_AES_192_ECB, MBEDTLS_CIPHER_AES_256_ECB, + * or MBEDTLS_CIPHER_DES_EDE3_ECB. + * \param key The CMAC key. + * \param keybits The length of the CMAC key in bits. + * Must be supported by the cipher. + * + * \return \c 0 on success. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_cmac_starts( mbedtls_cipher_context_t *ctx, + const unsigned char *key, size_t keybits ); + +/** + * \brief This function feeds an input buffer into an ongoing CMAC + * computation. + * + * It is called between mbedtls_cipher_cmac_starts() or + * mbedtls_cipher_cmac_reset(), and mbedtls_cipher_cmac_finish(). + * Can be called repeatedly. + * + * \param ctx The cipher context used for the CMAC operation. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA + * if parameter verification fails. + */ +int mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx, + const unsigned char *input, size_t ilen ); + +/** + * \brief This function finishes the CMAC operation, and writes + * the result to the output buffer. + * + * It is called after mbedtls_cipher_cmac_update(). + * It can be followed by mbedtls_cipher_cmac_reset() and + * mbedtls_cipher_cmac_update(), or mbedtls_cipher_free(). + * + * \param ctx The cipher context used for the CMAC operation. + * \param output The output buffer for the CMAC checksum result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA + * if parameter verification fails. + */ +int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx, + unsigned char *output ); + +/** + * \brief This function prepares the authentication of another + * message with the same key as the previous CMAC + * operation. + * + * It is called after mbedtls_cipher_cmac_finish() + * and before mbedtls_cipher_cmac_update(). + * + * \param ctx The cipher context used for the CMAC operation. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA + * if parameter verification fails. + */ +int mbedtls_cipher_cmac_reset( mbedtls_cipher_context_t *ctx ); + +/** + * \brief This function calculates the full generic CMAC + * on the input buffer with the provided key. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The CMAC result is calculated as + * output = generic CMAC(cmac key, input buffer). + * + * + * \param cipher_info The cipher information. + * \param key The CMAC key. + * \param keylen The length of the CMAC key in bits. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The buffer for the generic CMAC result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA + * if parameter verification fails. + */ +int mbedtls_cipher_cmac( const mbedtls_cipher_info_t *cipher_info, + const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output ); + +#if defined(MBEDTLS_AES_C) +/** + * \brief This function implements the AES-CMAC-PRF-128 pseudorandom + * function, as defined in + * RFC-4615: The Advanced Encryption Standard-Cipher-based + * Message Authentication Code-Pseudo-Random Function-128 + * (AES-CMAC-PRF-128) Algorithm for the Internet Key + * Exchange Protocol (IKE). + * + * \param key The key to use. + * \param key_len The key length in Bytes. + * \param input The buffer holding the input data. + * \param in_len The length of the input data in Bytes. + * \param output The buffer holding the generated 16 Bytes of + * pseudorandom output. + * + * \return \c 0 on success. + */ +int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_len, + const unsigned char *input, size_t in_len, + unsigned char output[16] ); +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_SELF_TEST) && ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) ) +/** + * \brief The CMAC checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_cmac_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST && ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CMAC_H */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/compat-1.3.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/compat-1.3.h new file mode 100644 index 0000000..4017751 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/compat-1.3.h @@ -0,0 +1,2529 @@ +/** + * \file compat-1.3.h + * + * \brief Compatibility definitions for using mbed TLS with client code written + * for the PolarSSL naming conventions. + * + * \deprecated Use the new names directly instead + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) + +#if defined(MBEDTLS_DEPRECATED_WARNING) +#warning "Including compat-1.3.h is deprecated" +#endif + +#ifndef MBEDTLS_COMPAT13_H +#define MBEDTLS_COMPAT13_H + +/* + * config.h options + */ +#if defined MBEDTLS_AESNI_C +#define POLARSSL_AESNI_C MBEDTLS_AESNI_C +#endif +#if defined MBEDTLS_AES_ALT +#define POLARSSL_AES_ALT MBEDTLS_AES_ALT +#endif +#if defined MBEDTLS_AES_C +#define POLARSSL_AES_C MBEDTLS_AES_C +#endif +#if defined MBEDTLS_AES_ROM_TABLES +#define POLARSSL_AES_ROM_TABLES MBEDTLS_AES_ROM_TABLES +#endif +#if defined MBEDTLS_ARC4_ALT +#define POLARSSL_ARC4_ALT MBEDTLS_ARC4_ALT +#endif +#if defined MBEDTLS_ARC4_C +#define POLARSSL_ARC4_C MBEDTLS_ARC4_C +#endif +#if defined MBEDTLS_ASN1_PARSE_C +#define POLARSSL_ASN1_PARSE_C MBEDTLS_ASN1_PARSE_C +#endif +#if defined MBEDTLS_ASN1_WRITE_C +#define POLARSSL_ASN1_WRITE_C MBEDTLS_ASN1_WRITE_C +#endif +#if defined MBEDTLS_BASE64_C +#define POLARSSL_BASE64_C MBEDTLS_BASE64_C +#endif +#if defined MBEDTLS_BIGNUM_C +#define POLARSSL_BIGNUM_C MBEDTLS_BIGNUM_C +#endif +#if defined MBEDTLS_BLOWFISH_ALT +#define POLARSSL_BLOWFISH_ALT MBEDTLS_BLOWFISH_ALT +#endif +#if defined MBEDTLS_BLOWFISH_C +#define POLARSSL_BLOWFISH_C MBEDTLS_BLOWFISH_C +#endif +#if defined MBEDTLS_CAMELLIA_ALT +#define POLARSSL_CAMELLIA_ALT MBEDTLS_CAMELLIA_ALT +#endif +#if defined MBEDTLS_CAMELLIA_C +#define POLARSSL_CAMELLIA_C MBEDTLS_CAMELLIA_C +#endif +#if defined MBEDTLS_CAMELLIA_SMALL_MEMORY +#define POLARSSL_CAMELLIA_SMALL_MEMORY MBEDTLS_CAMELLIA_SMALL_MEMORY +#endif +#if defined MBEDTLS_CCM_C +#define POLARSSL_CCM_C MBEDTLS_CCM_C +#endif +#if defined MBEDTLS_CERTS_C +#define POLARSSL_CERTS_C MBEDTLS_CERTS_C +#endif +#if defined MBEDTLS_CIPHER_C +#define POLARSSL_CIPHER_C MBEDTLS_CIPHER_C +#endif +#if defined MBEDTLS_CIPHER_MODE_CBC +#define POLARSSL_CIPHER_MODE_CBC MBEDTLS_CIPHER_MODE_CBC +#endif +#if defined MBEDTLS_CIPHER_MODE_CFB +#define POLARSSL_CIPHER_MODE_CFB MBEDTLS_CIPHER_MODE_CFB +#endif +#if defined MBEDTLS_CIPHER_MODE_CTR +#define POLARSSL_CIPHER_MODE_CTR MBEDTLS_CIPHER_MODE_CTR +#endif +#if defined MBEDTLS_CIPHER_NULL_CIPHER +#define POLARSSL_CIPHER_NULL_CIPHER MBEDTLS_CIPHER_NULL_CIPHER +#endif +#if defined MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS +#define POLARSSL_CIPHER_PADDING_ONE_AND_ZEROS MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS +#endif +#if defined MBEDTLS_CIPHER_PADDING_PKCS7 +#define POLARSSL_CIPHER_PADDING_PKCS7 MBEDTLS_CIPHER_PADDING_PKCS7 +#endif +#if defined MBEDTLS_CIPHER_PADDING_ZEROS +#define POLARSSL_CIPHER_PADDING_ZEROS MBEDTLS_CIPHER_PADDING_ZEROS +#endif +#if defined MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN +#define POLARSSL_CIPHER_PADDING_ZEROS_AND_LEN MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN +#endif +#if defined MBEDTLS_CTR_DRBG_C +#define POLARSSL_CTR_DRBG_C MBEDTLS_CTR_DRBG_C +#endif +#if defined MBEDTLS_DEBUG_C +#define POLARSSL_DEBUG_C MBEDTLS_DEBUG_C +#endif +#if defined MBEDTLS_DEPRECATED_REMOVED +#define POLARSSL_DEPRECATED_REMOVED MBEDTLS_DEPRECATED_REMOVED +#endif +#if defined MBEDTLS_DEPRECATED_WARNING +#define POLARSSL_DEPRECATED_WARNING MBEDTLS_DEPRECATED_WARNING +#endif +#if defined MBEDTLS_DES_ALT +#define POLARSSL_DES_ALT MBEDTLS_DES_ALT +#endif +#if defined MBEDTLS_DES_C +#define POLARSSL_DES_C MBEDTLS_DES_C +#endif +#if defined MBEDTLS_DHM_C +#define POLARSSL_DHM_C MBEDTLS_DHM_C +#endif +#if defined MBEDTLS_ECDH_C +#define POLARSSL_ECDH_C MBEDTLS_ECDH_C +#endif +#if defined MBEDTLS_ECDSA_C +#define POLARSSL_ECDSA_C MBEDTLS_ECDSA_C +#endif +#if defined MBEDTLS_ECDSA_DETERMINISTIC +#define POLARSSL_ECDSA_DETERMINISTIC MBEDTLS_ECDSA_DETERMINISTIC +#endif +#if defined MBEDTLS_ECP_C +#define POLARSSL_ECP_C MBEDTLS_ECP_C +#endif +#if defined MBEDTLS_ECP_DP_BP256R1_ENABLED +#define POLARSSL_ECP_DP_BP256R1_ENABLED MBEDTLS_ECP_DP_BP256R1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_BP384R1_ENABLED +#define POLARSSL_ECP_DP_BP384R1_ENABLED MBEDTLS_ECP_DP_BP384R1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_BP512R1_ENABLED +#define POLARSSL_ECP_DP_BP512R1_ENABLED MBEDTLS_ECP_DP_BP512R1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_CURVE25519_ENABLED +#define POLARSSL_ECP_DP_M255_ENABLED MBEDTLS_ECP_DP_CURVE25519_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_SECP192K1_ENABLED +#define POLARSSL_ECP_DP_SECP192K1_ENABLED MBEDTLS_ECP_DP_SECP192K1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_SECP192R1_ENABLED +#define POLARSSL_ECP_DP_SECP192R1_ENABLED MBEDTLS_ECP_DP_SECP192R1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_SECP224K1_ENABLED +#define POLARSSL_ECP_DP_SECP224K1_ENABLED MBEDTLS_ECP_DP_SECP224K1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_SECP224R1_ENABLED +#define POLARSSL_ECP_DP_SECP224R1_ENABLED MBEDTLS_ECP_DP_SECP224R1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_SECP256K1_ENABLED +#define POLARSSL_ECP_DP_SECP256K1_ENABLED MBEDTLS_ECP_DP_SECP256K1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_SECP256R1_ENABLED +#define POLARSSL_ECP_DP_SECP256R1_ENABLED MBEDTLS_ECP_DP_SECP256R1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_SECP384R1_ENABLED +#define POLARSSL_ECP_DP_SECP384R1_ENABLED MBEDTLS_ECP_DP_SECP384R1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_SECP521R1_ENABLED +#define POLARSSL_ECP_DP_SECP521R1_ENABLED MBEDTLS_ECP_DP_SECP521R1_ENABLED +#endif +#if defined MBEDTLS_ECP_FIXED_POINT_OPTIM +#define POLARSSL_ECP_FIXED_POINT_OPTIM MBEDTLS_ECP_FIXED_POINT_OPTIM +#endif +#if defined MBEDTLS_ECP_MAX_BITS +#define POLARSSL_ECP_MAX_BITS MBEDTLS_ECP_MAX_BITS +#endif +#if defined MBEDTLS_ECP_NIST_OPTIM +#define POLARSSL_ECP_NIST_OPTIM MBEDTLS_ECP_NIST_OPTIM +#endif +#if defined MBEDTLS_ECP_WINDOW_SIZE +#define POLARSSL_ECP_WINDOW_SIZE MBEDTLS_ECP_WINDOW_SIZE +#endif +#if defined MBEDTLS_ENABLE_WEAK_CIPHERSUITES +#define POLARSSL_ENABLE_WEAK_CIPHERSUITES MBEDTLS_ENABLE_WEAK_CIPHERSUITES +#endif +#if defined MBEDTLS_ENTROPY_C +#define POLARSSL_ENTROPY_C MBEDTLS_ENTROPY_C +#endif +#if defined MBEDTLS_ENTROPY_FORCE_SHA256 +#define POLARSSL_ENTROPY_FORCE_SHA256 MBEDTLS_ENTROPY_FORCE_SHA256 +#endif +#if defined MBEDTLS_ERROR_C +#define POLARSSL_ERROR_C MBEDTLS_ERROR_C +#endif +#if defined MBEDTLS_ERROR_STRERROR_DUMMY +#define POLARSSL_ERROR_STRERROR_DUMMY MBEDTLS_ERROR_STRERROR_DUMMY +#endif +#if defined MBEDTLS_FS_IO +#define POLARSSL_FS_IO MBEDTLS_FS_IO +#endif +#if defined MBEDTLS_GCM_C +#define POLARSSL_GCM_C MBEDTLS_GCM_C +#endif +#if defined MBEDTLS_GENPRIME +#define POLARSSL_GENPRIME MBEDTLS_GENPRIME +#endif +#if defined MBEDTLS_HAVEGE_C +#define POLARSSL_HAVEGE_C MBEDTLS_HAVEGE_C +#endif +#if defined MBEDTLS_HAVE_ASM +#define POLARSSL_HAVE_ASM MBEDTLS_HAVE_ASM +#endif +#if defined MBEDTLS_HAVE_SSE2 +#define POLARSSL_HAVE_SSE2 MBEDTLS_HAVE_SSE2 +#endif +#if defined MBEDTLS_HAVE_TIME +#define POLARSSL_HAVE_TIME MBEDTLS_HAVE_TIME +#endif +#if defined MBEDTLS_HMAC_DRBG_C +#define POLARSSL_HMAC_DRBG_C MBEDTLS_HMAC_DRBG_C +#endif +#if defined MBEDTLS_HMAC_DRBG_MAX_INPUT +#define POLARSSL_HMAC_DRBG_MAX_INPUT MBEDTLS_HMAC_DRBG_MAX_INPUT +#endif +#if defined MBEDTLS_HMAC_DRBG_MAX_REQUEST +#define POLARSSL_HMAC_DRBG_MAX_REQUEST MBEDTLS_HMAC_DRBG_MAX_REQUEST +#endif +#if defined MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT +#define POLARSSL_HMAC_DRBG_MAX_SEED_INPUT MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT +#endif +#if defined MBEDTLS_HMAC_DRBG_RESEED_INTERVAL +#define POLARSSL_HMAC_DRBG_RESEED_INTERVAL MBEDTLS_HMAC_DRBG_RESEED_INTERVAL +#endif +#if defined MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED +#define POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED +#define POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +#define POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED +#define POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED +#define POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED +#define POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED +#define POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_PSK_ENABLED +#define POLARSSL_KEY_EXCHANGE_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_PSK_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_RSA_ENABLED +#define POLARSSL_KEY_EXCHANGE_RSA_ENABLED MBEDTLS_KEY_EXCHANGE_RSA_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED +#define POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED +#endif +#if defined MBEDTLS_MD2_ALT +#define POLARSSL_MD2_ALT MBEDTLS_MD2_ALT +#endif +#if defined MBEDTLS_MD2_C +#define POLARSSL_MD2_C MBEDTLS_MD2_C +#endif +#if defined MBEDTLS_MD2_PROCESS_ALT +#define POLARSSL_MD2_PROCESS_ALT MBEDTLS_MD2_PROCESS_ALT +#endif +#if defined MBEDTLS_MD4_ALT +#define POLARSSL_MD4_ALT MBEDTLS_MD4_ALT +#endif +#if defined MBEDTLS_MD4_C +#define POLARSSL_MD4_C MBEDTLS_MD4_C +#endif +#if defined MBEDTLS_MD4_PROCESS_ALT +#define POLARSSL_MD4_PROCESS_ALT MBEDTLS_MD4_PROCESS_ALT +#endif +#if defined MBEDTLS_MD5_ALT +#define POLARSSL_MD5_ALT MBEDTLS_MD5_ALT +#endif +#if defined MBEDTLS_MD5_C +#define POLARSSL_MD5_C MBEDTLS_MD5_C +#endif +#if defined MBEDTLS_MD5_PROCESS_ALT +#define POLARSSL_MD5_PROCESS_ALT MBEDTLS_MD5_PROCESS_ALT +#endif +#if defined MBEDTLS_MD_C +#define POLARSSL_MD_C MBEDTLS_MD_C +#endif +#if defined MBEDTLS_MEMORY_ALIGN_MULTIPLE +#define POLARSSL_MEMORY_ALIGN_MULTIPLE MBEDTLS_MEMORY_ALIGN_MULTIPLE +#endif +#if defined MBEDTLS_MEMORY_BACKTRACE +#define POLARSSL_MEMORY_BACKTRACE MBEDTLS_MEMORY_BACKTRACE +#endif +#if defined MBEDTLS_MEMORY_BUFFER_ALLOC_C +#define POLARSSL_MEMORY_BUFFER_ALLOC_C MBEDTLS_MEMORY_BUFFER_ALLOC_C +#endif +#if defined MBEDTLS_MEMORY_DEBUG +#define POLARSSL_MEMORY_DEBUG MBEDTLS_MEMORY_DEBUG +#endif +#if defined MBEDTLS_MPI_MAX_SIZE +#define POLARSSL_MPI_MAX_SIZE MBEDTLS_MPI_MAX_SIZE +#endif +#if defined MBEDTLS_MPI_WINDOW_SIZE +#define POLARSSL_MPI_WINDOW_SIZE MBEDTLS_MPI_WINDOW_SIZE +#endif +#if defined MBEDTLS_NET_C +#define POLARSSL_NET_C MBEDTLS_NET_C +#endif +#if defined MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES +#define POLARSSL_NO_DEFAULT_ENTROPY_SOURCES MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES +#endif +#if defined MBEDTLS_NO_PLATFORM_ENTROPY +#define POLARSSL_NO_PLATFORM_ENTROPY MBEDTLS_NO_PLATFORM_ENTROPY +#endif +#if defined MBEDTLS_OID_C +#define POLARSSL_OID_C MBEDTLS_OID_C +#endif +#if defined MBEDTLS_PADLOCK_C +#define POLARSSL_PADLOCK_C MBEDTLS_PADLOCK_C +#endif +#if defined MBEDTLS_PEM_PARSE_C +#define POLARSSL_PEM_PARSE_C MBEDTLS_PEM_PARSE_C +#endif +#if defined MBEDTLS_PEM_WRITE_C +#define POLARSSL_PEM_WRITE_C MBEDTLS_PEM_WRITE_C +#endif +#if defined MBEDTLS_PKCS11_C +#define POLARSSL_PKCS11_C MBEDTLS_PKCS11_C +#endif +#if defined MBEDTLS_PKCS12_C +#define POLARSSL_PKCS12_C MBEDTLS_PKCS12_C +#endif +#if defined MBEDTLS_PKCS1_V15 +#define POLARSSL_PKCS1_V15 MBEDTLS_PKCS1_V15 +#endif +#if defined MBEDTLS_PKCS1_V21 +#define POLARSSL_PKCS1_V21 MBEDTLS_PKCS1_V21 +#endif +#if defined MBEDTLS_PKCS5_C +#define POLARSSL_PKCS5_C MBEDTLS_PKCS5_C +#endif +#if defined MBEDTLS_PK_C +#define POLARSSL_PK_C MBEDTLS_PK_C +#endif +#if defined MBEDTLS_PK_PARSE_C +#define POLARSSL_PK_PARSE_C MBEDTLS_PK_PARSE_C +#endif +#if defined MBEDTLS_PK_PARSE_EC_EXTENDED +#define POLARSSL_PK_PARSE_EC_EXTENDED MBEDTLS_PK_PARSE_EC_EXTENDED +#endif +#if defined MBEDTLS_PK_RSA_ALT_SUPPORT +#define POLARSSL_PK_RSA_ALT_SUPPORT MBEDTLS_PK_RSA_ALT_SUPPORT +#endif +#if defined MBEDTLS_PK_WRITE_C +#define POLARSSL_PK_WRITE_C MBEDTLS_PK_WRITE_C +#endif +#if defined MBEDTLS_PLATFORM_C +#define POLARSSL_PLATFORM_C MBEDTLS_PLATFORM_C +#endif +#if defined MBEDTLS_PLATFORM_EXIT_ALT +#define POLARSSL_PLATFORM_EXIT_ALT MBEDTLS_PLATFORM_EXIT_ALT +#endif +#if defined MBEDTLS_PLATFORM_EXIT_MACRO +#define POLARSSL_PLATFORM_EXIT_MACRO MBEDTLS_PLATFORM_EXIT_MACRO +#endif +#if defined MBEDTLS_PLATFORM_FPRINTF_ALT +#define POLARSSL_PLATFORM_FPRINTF_ALT MBEDTLS_PLATFORM_FPRINTF_ALT +#endif +#if defined MBEDTLS_PLATFORM_FPRINTF_MACRO +#define POLARSSL_PLATFORM_FPRINTF_MACRO MBEDTLS_PLATFORM_FPRINTF_MACRO +#endif +#if defined MBEDTLS_PLATFORM_FREE_MACRO +#define POLARSSL_PLATFORM_FREE_MACRO MBEDTLS_PLATFORM_FREE_MACRO +#endif +#if defined MBEDTLS_PLATFORM_MEMORY +#define POLARSSL_PLATFORM_MEMORY MBEDTLS_PLATFORM_MEMORY +#endif +#if defined MBEDTLS_PLATFORM_NO_STD_FUNCTIONS +#define POLARSSL_PLATFORM_NO_STD_FUNCTIONS MBEDTLS_PLATFORM_NO_STD_FUNCTIONS +#endif +#if defined MBEDTLS_PLATFORM_PRINTF_ALT +#define POLARSSL_PLATFORM_PRINTF_ALT MBEDTLS_PLATFORM_PRINTF_ALT +#endif +#if defined MBEDTLS_PLATFORM_PRINTF_MACRO +#define POLARSSL_PLATFORM_PRINTF_MACRO MBEDTLS_PLATFORM_PRINTF_MACRO +#endif +#if defined MBEDTLS_PLATFORM_SNPRINTF_ALT +#define POLARSSL_PLATFORM_SNPRINTF_ALT MBEDTLS_PLATFORM_SNPRINTF_ALT +#endif +#if defined MBEDTLS_PLATFORM_SNPRINTF_MACRO +#define POLARSSL_PLATFORM_SNPRINTF_MACRO MBEDTLS_PLATFORM_SNPRINTF_MACRO +#endif +#if defined MBEDTLS_PLATFORM_STD_EXIT +#define POLARSSL_PLATFORM_STD_EXIT MBEDTLS_PLATFORM_STD_EXIT +#endif +#if defined MBEDTLS_PLATFORM_STD_FPRINTF +#define POLARSSL_PLATFORM_STD_FPRINTF MBEDTLS_PLATFORM_STD_FPRINTF +#endif +#if defined MBEDTLS_PLATFORM_STD_FREE +#define POLARSSL_PLATFORM_STD_FREE MBEDTLS_PLATFORM_STD_FREE +#endif +#if defined MBEDTLS_PLATFORM_STD_MEM_HDR +#define POLARSSL_PLATFORM_STD_MEM_HDR MBEDTLS_PLATFORM_STD_MEM_HDR +#endif +#if defined MBEDTLS_PLATFORM_STD_PRINTF +#define POLARSSL_PLATFORM_STD_PRINTF MBEDTLS_PLATFORM_STD_PRINTF +#endif +#if defined MBEDTLS_PLATFORM_STD_SNPRINTF +#define POLARSSL_PLATFORM_STD_SNPRINTF MBEDTLS_PLATFORM_STD_SNPRINTF +#endif +#if defined MBEDTLS_PSK_MAX_LEN +#define POLARSSL_PSK_MAX_LEN MBEDTLS_PSK_MAX_LEN +#endif +#if defined MBEDTLS_REMOVE_ARC4_CIPHERSUITES +#define POLARSSL_REMOVE_ARC4_CIPHERSUITES MBEDTLS_REMOVE_ARC4_CIPHERSUITES +#endif +#if defined MBEDTLS_RIPEMD160_ALT +#define POLARSSL_RIPEMD160_ALT MBEDTLS_RIPEMD160_ALT +#endif +#if defined MBEDTLS_RIPEMD160_C +#define POLARSSL_RIPEMD160_C MBEDTLS_RIPEMD160_C +#endif +#if defined MBEDTLS_RIPEMD160_PROCESS_ALT +#define POLARSSL_RIPEMD160_PROCESS_ALT MBEDTLS_RIPEMD160_PROCESS_ALT +#endif +#if defined MBEDTLS_RSA_C +#define POLARSSL_RSA_C MBEDTLS_RSA_C +#endif +#if defined MBEDTLS_RSA_NO_CRT +#define POLARSSL_RSA_NO_CRT MBEDTLS_RSA_NO_CRT +#endif +#if defined MBEDTLS_SELF_TEST +#define POLARSSL_SELF_TEST MBEDTLS_SELF_TEST +#endif +#if defined MBEDTLS_SHA1_ALT +#define POLARSSL_SHA1_ALT MBEDTLS_SHA1_ALT +#endif +#if defined MBEDTLS_SHA1_C +#define POLARSSL_SHA1_C MBEDTLS_SHA1_C +#endif +#if defined MBEDTLS_SHA1_PROCESS_ALT +#define POLARSSL_SHA1_PROCESS_ALT MBEDTLS_SHA1_PROCESS_ALT +#endif +#if defined MBEDTLS_SHA256_ALT +#define POLARSSL_SHA256_ALT MBEDTLS_SHA256_ALT +#endif +#if defined MBEDTLS_SHA256_C +#define POLARSSL_SHA256_C MBEDTLS_SHA256_C +#endif +#if defined MBEDTLS_SHA256_PROCESS_ALT +#define POLARSSL_SHA256_PROCESS_ALT MBEDTLS_SHA256_PROCESS_ALT +#endif +#if defined MBEDTLS_SHA512_ALT +#define POLARSSL_SHA512_ALT MBEDTLS_SHA512_ALT +#endif +#if defined MBEDTLS_SHA512_C +#define POLARSSL_SHA512_C MBEDTLS_SHA512_C +#endif +#if defined MBEDTLS_SHA512_PROCESS_ALT +#define POLARSSL_SHA512_PROCESS_ALT MBEDTLS_SHA512_PROCESS_ALT +#endif +#if defined MBEDTLS_SSL_ALL_ALERT_MESSAGES +#define POLARSSL_SSL_ALL_ALERT_MESSAGES MBEDTLS_SSL_ALL_ALERT_MESSAGES +#endif +#if defined MBEDTLS_SSL_ALPN +#define POLARSSL_SSL_ALPN MBEDTLS_SSL_ALPN +#endif +#if defined MBEDTLS_SSL_CACHE_C +#define POLARSSL_SSL_CACHE_C MBEDTLS_SSL_CACHE_C +#endif +#if defined MBEDTLS_SSL_CBC_RECORD_SPLITTING +#define POLARSSL_SSL_CBC_RECORD_SPLITTING MBEDTLS_SSL_CBC_RECORD_SPLITTING +#endif +#if defined MBEDTLS_SSL_CLI_C +#define POLARSSL_SSL_CLI_C MBEDTLS_SSL_CLI_C +#endif +#if defined MBEDTLS_SSL_COOKIE_C +#define POLARSSL_SSL_COOKIE_C MBEDTLS_SSL_COOKIE_C +#endif +#if defined MBEDTLS_SSL_COOKIE_TIMEOUT +#define POLARSSL_SSL_COOKIE_TIMEOUT MBEDTLS_SSL_COOKIE_TIMEOUT +#endif +#if defined MBEDTLS_SSL_DEBUG_ALL +#define POLARSSL_SSL_DEBUG_ALL MBEDTLS_SSL_DEBUG_ALL +#endif +#if defined MBEDTLS_SSL_DTLS_ANTI_REPLAY +#define POLARSSL_SSL_DTLS_ANTI_REPLAY MBEDTLS_SSL_DTLS_ANTI_REPLAY +#endif +#if defined MBEDTLS_SSL_DTLS_BADMAC_LIMIT +#define POLARSSL_SSL_DTLS_BADMAC_LIMIT MBEDTLS_SSL_DTLS_BADMAC_LIMIT +#endif +#if defined MBEDTLS_SSL_DTLS_HELLO_VERIFY +#define POLARSSL_SSL_DTLS_HELLO_VERIFY MBEDTLS_SSL_DTLS_HELLO_VERIFY +#endif +#if defined MBEDTLS_SSL_ENCRYPT_THEN_MAC +#define POLARSSL_SSL_ENCRYPT_THEN_MAC MBEDTLS_SSL_ENCRYPT_THEN_MAC +#endif +#if defined MBEDTLS_SSL_EXTENDED_MASTER_SECRET +#define POLARSSL_SSL_EXTENDED_MASTER_SECRET MBEDTLS_SSL_EXTENDED_MASTER_SECRET +#endif +#if defined MBEDTLS_SSL_FALLBACK_SCSV +#define POLARSSL_SSL_FALLBACK_SCSV MBEDTLS_SSL_FALLBACK_SCSV +#endif +#if defined MBEDTLS_SSL_HW_RECORD_ACCEL +#define POLARSSL_SSL_HW_RECORD_ACCEL MBEDTLS_SSL_HW_RECORD_ACCEL +#endif +#if defined MBEDTLS_SSL_MAX_FRAGMENT_LENGTH +#define POLARSSL_SSL_MAX_FRAGMENT_LENGTH MBEDTLS_SSL_MAX_FRAGMENT_LENGTH +#endif +#if defined MBEDTLS_SSL_PROTO_DTLS +#define POLARSSL_SSL_PROTO_DTLS MBEDTLS_SSL_PROTO_DTLS +#endif +#if defined MBEDTLS_SSL_PROTO_SSL3 +#define POLARSSL_SSL_PROTO_SSL3 MBEDTLS_SSL_PROTO_SSL3 +#endif +#if defined MBEDTLS_SSL_PROTO_TLS1 +#define POLARSSL_SSL_PROTO_TLS1 MBEDTLS_SSL_PROTO_TLS1 +#endif +#if defined MBEDTLS_SSL_PROTO_TLS1_1 +#define POLARSSL_SSL_PROTO_TLS1_1 MBEDTLS_SSL_PROTO_TLS1_1 +#endif +#if defined MBEDTLS_SSL_PROTO_TLS1_2 +#define POLARSSL_SSL_PROTO_TLS1_2 MBEDTLS_SSL_PROTO_TLS1_2 +#endif +#if defined MBEDTLS_SSL_RENEGOTIATION +#define POLARSSL_SSL_RENEGOTIATION MBEDTLS_SSL_RENEGOTIATION +#endif +#if defined MBEDTLS_SSL_SERVER_NAME_INDICATION +#define POLARSSL_SSL_SERVER_NAME_INDICATION MBEDTLS_SSL_SERVER_NAME_INDICATION +#endif +#if defined MBEDTLS_SSL_SESSION_TICKETS +#define POLARSSL_SSL_SESSION_TICKETS MBEDTLS_SSL_SESSION_TICKETS +#endif +#if defined MBEDTLS_SSL_SRV_C +#define POLARSSL_SSL_SRV_C MBEDTLS_SSL_SRV_C +#endif +#if defined MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE +#define POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE +#endif +#if defined MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO +#define POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO +#endif +#if defined MBEDTLS_SSL_TLS_C +#define POLARSSL_SSL_TLS_C MBEDTLS_SSL_TLS_C +#endif +#if defined MBEDTLS_SSL_TRUNCATED_HMAC +#define POLARSSL_SSL_TRUNCATED_HMAC MBEDTLS_SSL_TRUNCATED_HMAC +#endif +#if defined MBEDTLS_THREADING_ALT +#define POLARSSL_THREADING_ALT MBEDTLS_THREADING_ALT +#endif +#if defined MBEDTLS_THREADING_C +#define POLARSSL_THREADING_C MBEDTLS_THREADING_C +#endif +#if defined MBEDTLS_THREADING_PTHREAD +#define POLARSSL_THREADING_PTHREAD MBEDTLS_THREADING_PTHREAD +#endif +#if defined MBEDTLS_TIMING_ALT +#define POLARSSL_TIMING_ALT MBEDTLS_TIMING_ALT +#endif +#if defined MBEDTLS_TIMING_C +#define POLARSSL_TIMING_C MBEDTLS_TIMING_C +#endif +#if defined MBEDTLS_VERSION_C +#define POLARSSL_VERSION_C MBEDTLS_VERSION_C +#endif +#if defined MBEDTLS_VERSION_FEATURES +#define POLARSSL_VERSION_FEATURES MBEDTLS_VERSION_FEATURES +#endif +#if defined MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 +#define POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3 MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 +#endif +#if defined MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION +#define POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION +#endif +#if defined MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE +#define POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE +#endif +#if defined MBEDTLS_X509_CHECK_KEY_USAGE +#define POLARSSL_X509_CHECK_KEY_USAGE MBEDTLS_X509_CHECK_KEY_USAGE +#endif +#if defined MBEDTLS_X509_CREATE_C +#define POLARSSL_X509_CREATE_C MBEDTLS_X509_CREATE_C +#endif +#if defined MBEDTLS_X509_CRL_PARSE_C +#define POLARSSL_X509_CRL_PARSE_C MBEDTLS_X509_CRL_PARSE_C +#endif +#if defined MBEDTLS_X509_CRT_PARSE_C +#define POLARSSL_X509_CRT_PARSE_C MBEDTLS_X509_CRT_PARSE_C +#endif +#if defined MBEDTLS_X509_CRT_WRITE_C +#define POLARSSL_X509_CRT_WRITE_C MBEDTLS_X509_CRT_WRITE_C +#endif +#if defined MBEDTLS_X509_CSR_PARSE_C +#define POLARSSL_X509_CSR_PARSE_C MBEDTLS_X509_CSR_PARSE_C +#endif +#if defined MBEDTLS_X509_CSR_WRITE_C +#define POLARSSL_X509_CSR_WRITE_C MBEDTLS_X509_CSR_WRITE_C +#endif +#if defined MBEDTLS_X509_MAX_INTERMEDIATE_CA +#define POLARSSL_X509_MAX_INTERMEDIATE_CA MBEDTLS_X509_MAX_INTERMEDIATE_CA +#endif +#if defined MBEDTLS_X509_RSASSA_PSS_SUPPORT +#define POLARSSL_X509_RSASSA_PSS_SUPPORT MBEDTLS_X509_RSASSA_PSS_SUPPORT +#endif +#if defined MBEDTLS_X509_USE_C +#define POLARSSL_X509_USE_C MBEDTLS_X509_USE_C +#endif +#if defined MBEDTLS_XTEA_ALT +#define POLARSSL_XTEA_ALT MBEDTLS_XTEA_ALT +#endif +#if defined MBEDTLS_XTEA_C +#define POLARSSL_XTEA_C MBEDTLS_XTEA_C +#endif +#if defined MBEDTLS_ZLIB_SUPPORT +#define POLARSSL_ZLIB_SUPPORT MBEDTLS_ZLIB_SUPPORT +#endif + +/* + * Misc names (macros, types, functions, enum constants...) + */ +#define AES_DECRYPT MBEDTLS_AES_DECRYPT +#define AES_ENCRYPT MBEDTLS_AES_ENCRYPT +#define ASN1_BIT_STRING MBEDTLS_ASN1_BIT_STRING +#define ASN1_BMP_STRING MBEDTLS_ASN1_BMP_STRING +#define ASN1_BOOLEAN MBEDTLS_ASN1_BOOLEAN +#define ASN1_CHK_ADD MBEDTLS_ASN1_CHK_ADD +#define ASN1_CONSTRUCTED MBEDTLS_ASN1_CONSTRUCTED +#define ASN1_CONTEXT_SPECIFIC MBEDTLS_ASN1_CONTEXT_SPECIFIC +#define ASN1_GENERALIZED_TIME MBEDTLS_ASN1_GENERALIZED_TIME +#define ASN1_IA5_STRING MBEDTLS_ASN1_IA5_STRING +#define ASN1_INTEGER MBEDTLS_ASN1_INTEGER +#define ASN1_NULL MBEDTLS_ASN1_NULL +#define ASN1_OCTET_STRING MBEDTLS_ASN1_OCTET_STRING +#define ASN1_OID MBEDTLS_ASN1_OID +#define ASN1_PRIMITIVE MBEDTLS_ASN1_PRIMITIVE +#define ASN1_PRINTABLE_STRING MBEDTLS_ASN1_PRINTABLE_STRING +#define ASN1_SEQUENCE MBEDTLS_ASN1_SEQUENCE +#define ASN1_SET MBEDTLS_ASN1_SET +#define ASN1_T61_STRING MBEDTLS_ASN1_T61_STRING +#define ASN1_UNIVERSAL_STRING MBEDTLS_ASN1_UNIVERSAL_STRING +#define ASN1_UTC_TIME MBEDTLS_ASN1_UTC_TIME +#define ASN1_UTF8_STRING MBEDTLS_ASN1_UTF8_STRING +#define BADCERT_CN_MISMATCH MBEDTLS_X509_BADCERT_CN_MISMATCH +#define BADCERT_EXPIRED MBEDTLS_X509_BADCERT_EXPIRED +#define BADCERT_FUTURE MBEDTLS_X509_BADCERT_FUTURE +#define BADCERT_MISSING MBEDTLS_X509_BADCERT_MISSING +#define BADCERT_NOT_TRUSTED MBEDTLS_X509_BADCERT_NOT_TRUSTED +#define BADCERT_OTHER MBEDTLS_X509_BADCERT_OTHER +#define BADCERT_REVOKED MBEDTLS_X509_BADCERT_REVOKED +#define BADCERT_SKIP_VERIFY MBEDTLS_X509_BADCERT_SKIP_VERIFY +#define BADCRL_EXPIRED MBEDTLS_X509_BADCRL_EXPIRED +#define BADCRL_FUTURE MBEDTLS_X509_BADCRL_FUTURE +#define BADCRL_NOT_TRUSTED MBEDTLS_X509_BADCRL_NOT_TRUSTED +#define BLOWFISH_BLOCKSIZE MBEDTLS_BLOWFISH_BLOCKSIZE +#define BLOWFISH_DECRYPT MBEDTLS_BLOWFISH_DECRYPT +#define BLOWFISH_ENCRYPT MBEDTLS_BLOWFISH_ENCRYPT +#define BLOWFISH_MAX_KEY MBEDTLS_BLOWFISH_MAX_KEY_BITS +#define BLOWFISH_MIN_KEY MBEDTLS_BLOWFISH_MIN_KEY_BITS +#define BLOWFISH_ROUNDS MBEDTLS_BLOWFISH_ROUNDS +#define CAMELLIA_DECRYPT MBEDTLS_CAMELLIA_DECRYPT +#define CAMELLIA_ENCRYPT MBEDTLS_CAMELLIA_ENCRYPT +#define COLLECT_SIZE MBEDTLS_HAVEGE_COLLECT_SIZE +#define CTR_DRBG_BLOCKSIZE MBEDTLS_CTR_DRBG_BLOCKSIZE +#define CTR_DRBG_ENTROPY_LEN MBEDTLS_CTR_DRBG_ENTROPY_LEN +#define CTR_DRBG_KEYBITS MBEDTLS_CTR_DRBG_KEYBITS +#define CTR_DRBG_KEYSIZE MBEDTLS_CTR_DRBG_KEYSIZE +#define CTR_DRBG_MAX_INPUT MBEDTLS_CTR_DRBG_MAX_INPUT +#define CTR_DRBG_MAX_REQUEST MBEDTLS_CTR_DRBG_MAX_REQUEST +#define CTR_DRBG_MAX_SEED_INPUT MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +#define CTR_DRBG_PR_OFF MBEDTLS_CTR_DRBG_PR_OFF +#define CTR_DRBG_PR_ON MBEDTLS_CTR_DRBG_PR_ON +#define CTR_DRBG_RESEED_INTERVAL MBEDTLS_CTR_DRBG_RESEED_INTERVAL +#define CTR_DRBG_SEEDLEN MBEDTLS_CTR_DRBG_SEEDLEN +#define DEPRECATED MBEDTLS_DEPRECATED +#define DES_DECRYPT MBEDTLS_DES_DECRYPT +#define DES_ENCRYPT MBEDTLS_DES_ENCRYPT +#define DES_KEY_SIZE MBEDTLS_DES_KEY_SIZE +#define ENTROPY_BLOCK_SIZE MBEDTLS_ENTROPY_BLOCK_SIZE +#define ENTROPY_MAX_GATHER MBEDTLS_ENTROPY_MAX_GATHER +#define ENTROPY_MAX_SEED_SIZE MBEDTLS_ENTROPY_MAX_SEED_SIZE +#define ENTROPY_MAX_SOURCES MBEDTLS_ENTROPY_MAX_SOURCES +#define ENTROPY_MIN_HARDCLOCK MBEDTLS_ENTROPY_MIN_HARDCLOCK +#define ENTROPY_MIN_HAVEGE MBEDTLS_ENTROPY_MIN_HAVEGE +#define ENTROPY_MIN_PLATFORM MBEDTLS_ENTROPY_MIN_PLATFORM +#define ENTROPY_SOURCE_MANUAL MBEDTLS_ENTROPY_SOURCE_MANUAL +#define EXT_AUTHORITY_KEY_IDENTIFIER MBEDTLS_X509_EXT_AUTHORITY_KEY_IDENTIFIER +#define EXT_BASIC_CONSTRAINTS MBEDTLS_X509_EXT_BASIC_CONSTRAINTS +#define EXT_CERTIFICATE_POLICIES MBEDTLS_X509_EXT_CERTIFICATE_POLICIES +#define EXT_CRL_DISTRIBUTION_POINTS MBEDTLS_X509_EXT_CRL_DISTRIBUTION_POINTS +#define EXT_EXTENDED_KEY_USAGE MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE +#define EXT_FRESHEST_CRL MBEDTLS_X509_EXT_FRESHEST_CRL +#define EXT_INIHIBIT_ANYPOLICY MBEDTLS_X509_EXT_INIHIBIT_ANYPOLICY +#define EXT_ISSUER_ALT_NAME MBEDTLS_X509_EXT_ISSUER_ALT_NAME +#define EXT_KEY_USAGE MBEDTLS_X509_EXT_KEY_USAGE +#define EXT_NAME_CONSTRAINTS MBEDTLS_X509_EXT_NAME_CONSTRAINTS +#define EXT_NS_CERT_TYPE MBEDTLS_X509_EXT_NS_CERT_TYPE +#define EXT_POLICY_CONSTRAINTS MBEDTLS_X509_EXT_POLICY_CONSTRAINTS +#define EXT_POLICY_MAPPINGS MBEDTLS_X509_EXT_POLICY_MAPPINGS +#define EXT_SUBJECT_ALT_NAME MBEDTLS_X509_EXT_SUBJECT_ALT_NAME +#define EXT_SUBJECT_DIRECTORY_ATTRS MBEDTLS_X509_EXT_SUBJECT_DIRECTORY_ATTRS +#define EXT_SUBJECT_KEY_IDENTIFIER MBEDTLS_X509_EXT_SUBJECT_KEY_IDENTIFIER +#define GCM_DECRYPT MBEDTLS_GCM_DECRYPT +#define GCM_ENCRYPT MBEDTLS_GCM_ENCRYPT +#define KU_CRL_SIGN MBEDTLS_X509_KU_CRL_SIGN +#define KU_DATA_ENCIPHERMENT MBEDTLS_X509_KU_DATA_ENCIPHERMENT +#define KU_DIGITAL_SIGNATURE MBEDTLS_X509_KU_DIGITAL_SIGNATURE +#define KU_KEY_AGREEMENT MBEDTLS_X509_KU_KEY_AGREEMENT +#define KU_KEY_CERT_SIGN MBEDTLS_X509_KU_KEY_CERT_SIGN +#define KU_KEY_ENCIPHERMENT MBEDTLS_X509_KU_KEY_ENCIPHERMENT +#define KU_NON_REPUDIATION MBEDTLS_X509_KU_NON_REPUDIATION +#define LN_2_DIV_LN_10_SCALE100 MBEDTLS_LN_2_DIV_LN_10_SCALE100 +#define MEMORY_VERIFY_ALLOC MBEDTLS_MEMORY_VERIFY_ALLOC +#define MEMORY_VERIFY_ALWAYS MBEDTLS_MEMORY_VERIFY_ALWAYS +#define MEMORY_VERIFY_FREE MBEDTLS_MEMORY_VERIFY_FREE +#define MEMORY_VERIFY_NONE MBEDTLS_MEMORY_VERIFY_NONE +#define MPI_CHK MBEDTLS_MPI_CHK +#define NET_PROTO_TCP MBEDTLS_NET_PROTO_TCP +#define NET_PROTO_UDP MBEDTLS_NET_PROTO_UDP +#define NS_CERT_TYPE_EMAIL MBEDTLS_X509_NS_CERT_TYPE_EMAIL +#define NS_CERT_TYPE_EMAIL_CA MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA +#define NS_CERT_TYPE_OBJECT_SIGNING MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING +#define NS_CERT_TYPE_OBJECT_SIGNING_CA MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA +#define NS_CERT_TYPE_RESERVED MBEDTLS_X509_NS_CERT_TYPE_RESERVED +#define NS_CERT_TYPE_SSL_CA MBEDTLS_X509_NS_CERT_TYPE_SSL_CA +#define NS_CERT_TYPE_SSL_CLIENT MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT +#define NS_CERT_TYPE_SSL_SERVER MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER +#define OID_ANSI_X9_62 MBEDTLS_OID_ANSI_X9_62 +#define OID_ANSI_X9_62_FIELD_TYPE MBEDTLS_OID_ANSI_X9_62_FIELD_TYPE +#define OID_ANSI_X9_62_PRIME_FIELD MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD +#define OID_ANSI_X9_62_SIG MBEDTLS_OID_ANSI_X9_62_SIG +#define OID_ANSI_X9_62_SIG_SHA2 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 +#define OID_ANY_EXTENDED_KEY_USAGE MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE +#define OID_AT MBEDTLS_OID_AT +#define OID_AT_CN MBEDTLS_OID_AT_CN +#define OID_AT_COUNTRY MBEDTLS_OID_AT_COUNTRY +#define OID_AT_DN_QUALIFIER MBEDTLS_OID_AT_DN_QUALIFIER +#define OID_AT_GENERATION_QUALIFIER MBEDTLS_OID_AT_GENERATION_QUALIFIER +#define OID_AT_GIVEN_NAME MBEDTLS_OID_AT_GIVEN_NAME +#define OID_AT_INITIALS MBEDTLS_OID_AT_INITIALS +#define OID_AT_LOCALITY MBEDTLS_OID_AT_LOCALITY +#define OID_AT_ORGANIZATION MBEDTLS_OID_AT_ORGANIZATION +#define OID_AT_ORG_UNIT MBEDTLS_OID_AT_ORG_UNIT +#define OID_AT_POSTAL_ADDRESS MBEDTLS_OID_AT_POSTAL_ADDRESS +#define OID_AT_POSTAL_CODE MBEDTLS_OID_AT_POSTAL_CODE +#define OID_AT_PSEUDONYM MBEDTLS_OID_AT_PSEUDONYM +#define OID_AT_SERIAL_NUMBER MBEDTLS_OID_AT_SERIAL_NUMBER +#define OID_AT_STATE MBEDTLS_OID_AT_STATE +#define OID_AT_SUR_NAME MBEDTLS_OID_AT_SUR_NAME +#define OID_AT_TITLE MBEDTLS_OID_AT_TITLE +#define OID_AT_UNIQUE_IDENTIFIER MBEDTLS_OID_AT_UNIQUE_IDENTIFIER +#define OID_AUTHORITY_KEY_IDENTIFIER MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER +#define OID_BASIC_CONSTRAINTS MBEDTLS_OID_BASIC_CONSTRAINTS +#define OID_CERTICOM MBEDTLS_OID_CERTICOM +#define OID_CERTIFICATE_POLICIES MBEDTLS_OID_CERTIFICATE_POLICIES +#define OID_CLIENT_AUTH MBEDTLS_OID_CLIENT_AUTH +#define OID_CMP MBEDTLS_OID_CMP +#define OID_CODE_SIGNING MBEDTLS_OID_CODE_SIGNING +#define OID_COUNTRY_US MBEDTLS_OID_COUNTRY_US +#define OID_CRL_DISTRIBUTION_POINTS MBEDTLS_OID_CRL_DISTRIBUTION_POINTS +#define OID_CRL_NUMBER MBEDTLS_OID_CRL_NUMBER +#define OID_DES_CBC MBEDTLS_OID_DES_CBC +#define OID_DES_EDE3_CBC MBEDTLS_OID_DES_EDE3_CBC +#define OID_DIGEST_ALG_MD2 MBEDTLS_OID_DIGEST_ALG_MD2 +#define OID_DIGEST_ALG_MD4 MBEDTLS_OID_DIGEST_ALG_MD4 +#define OID_DIGEST_ALG_MD5 MBEDTLS_OID_DIGEST_ALG_MD5 +#define OID_DIGEST_ALG_SHA1 MBEDTLS_OID_DIGEST_ALG_SHA1 +#define OID_DIGEST_ALG_SHA224 MBEDTLS_OID_DIGEST_ALG_SHA224 +#define OID_DIGEST_ALG_SHA256 MBEDTLS_OID_DIGEST_ALG_SHA256 +#define OID_DIGEST_ALG_SHA384 MBEDTLS_OID_DIGEST_ALG_SHA384 +#define OID_DIGEST_ALG_SHA512 MBEDTLS_OID_DIGEST_ALG_SHA512 +#define OID_DOMAIN_COMPONENT MBEDTLS_OID_DOMAIN_COMPONENT +#define OID_ECDSA_SHA1 MBEDTLS_OID_ECDSA_SHA1 +#define OID_ECDSA_SHA224 MBEDTLS_OID_ECDSA_SHA224 +#define OID_ECDSA_SHA256 MBEDTLS_OID_ECDSA_SHA256 +#define OID_ECDSA_SHA384 MBEDTLS_OID_ECDSA_SHA384 +#define OID_ECDSA_SHA512 MBEDTLS_OID_ECDSA_SHA512 +#define OID_EC_ALG_ECDH MBEDTLS_OID_EC_ALG_ECDH +#define OID_EC_ALG_UNRESTRICTED MBEDTLS_OID_EC_ALG_UNRESTRICTED +#define OID_EC_BRAINPOOL_V1 MBEDTLS_OID_EC_BRAINPOOL_V1 +#define OID_EC_GRP_BP256R1 MBEDTLS_OID_EC_GRP_BP256R1 +#define OID_EC_GRP_BP384R1 MBEDTLS_OID_EC_GRP_BP384R1 +#define OID_EC_GRP_BP512R1 MBEDTLS_OID_EC_GRP_BP512R1 +#define OID_EC_GRP_SECP192K1 MBEDTLS_OID_EC_GRP_SECP192K1 +#define OID_EC_GRP_SECP192R1 MBEDTLS_OID_EC_GRP_SECP192R1 +#define OID_EC_GRP_SECP224K1 MBEDTLS_OID_EC_GRP_SECP224K1 +#define OID_EC_GRP_SECP224R1 MBEDTLS_OID_EC_GRP_SECP224R1 +#define OID_EC_GRP_SECP256K1 MBEDTLS_OID_EC_GRP_SECP256K1 +#define OID_EC_GRP_SECP256R1 MBEDTLS_OID_EC_GRP_SECP256R1 +#define OID_EC_GRP_SECP384R1 MBEDTLS_OID_EC_GRP_SECP384R1 +#define OID_EC_GRP_SECP521R1 MBEDTLS_OID_EC_GRP_SECP521R1 +#define OID_EMAIL_PROTECTION MBEDTLS_OID_EMAIL_PROTECTION +#define OID_EXTENDED_KEY_USAGE MBEDTLS_OID_EXTENDED_KEY_USAGE +#define OID_FRESHEST_CRL MBEDTLS_OID_FRESHEST_CRL +#define OID_GOV MBEDTLS_OID_GOV +#define OID_HMAC_SHA1 MBEDTLS_OID_HMAC_SHA1 +#define OID_ID_CE MBEDTLS_OID_ID_CE +#define OID_INIHIBIT_ANYPOLICY MBEDTLS_OID_INIHIBIT_ANYPOLICY +#define OID_ISO_CCITT_DS MBEDTLS_OID_ISO_CCITT_DS +#define OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ISO_IDENTIFIED_ORG +#define OID_ISO_ITU_COUNTRY MBEDTLS_OID_ISO_ITU_COUNTRY +#define OID_ISO_ITU_US_ORG MBEDTLS_OID_ISO_ITU_US_ORG +#define OID_ISO_MEMBER_BODIES MBEDTLS_OID_ISO_MEMBER_BODIES +#define OID_ISSUER_ALT_NAME MBEDTLS_OID_ISSUER_ALT_NAME +#define OID_KEY_USAGE MBEDTLS_OID_KEY_USAGE +#define OID_KP MBEDTLS_OID_KP +#define OID_MGF1 MBEDTLS_OID_MGF1 +#define OID_NAME_CONSTRAINTS MBEDTLS_OID_NAME_CONSTRAINTS +#define OID_NETSCAPE MBEDTLS_OID_NETSCAPE +#define OID_NS_BASE_URL MBEDTLS_OID_NS_BASE_URL +#define OID_NS_CA_POLICY_URL MBEDTLS_OID_NS_CA_POLICY_URL +#define OID_NS_CA_REVOCATION_URL MBEDTLS_OID_NS_CA_REVOCATION_URL +#define OID_NS_CERT MBEDTLS_OID_NS_CERT +#define OID_NS_CERT_SEQUENCE MBEDTLS_OID_NS_CERT_SEQUENCE +#define OID_NS_CERT_TYPE MBEDTLS_OID_NS_CERT_TYPE +#define OID_NS_COMMENT MBEDTLS_OID_NS_COMMENT +#define OID_NS_DATA_TYPE MBEDTLS_OID_NS_DATA_TYPE +#define OID_NS_RENEWAL_URL MBEDTLS_OID_NS_RENEWAL_URL +#define OID_NS_REVOCATION_URL MBEDTLS_OID_NS_REVOCATION_URL +#define OID_NS_SSL_SERVER_NAME MBEDTLS_OID_NS_SSL_SERVER_NAME +#define OID_OCSP_SIGNING MBEDTLS_OID_OCSP_SIGNING +#define OID_OIW_SECSIG MBEDTLS_OID_OIW_SECSIG +#define OID_OIW_SECSIG_ALG MBEDTLS_OID_OIW_SECSIG_ALG +#define OID_OIW_SECSIG_SHA1 MBEDTLS_OID_OIW_SECSIG_SHA1 +#define OID_ORGANIZATION MBEDTLS_OID_ORGANIZATION +#define OID_ORG_ANSI_X9_62 MBEDTLS_OID_ORG_ANSI_X9_62 +#define OID_ORG_CERTICOM MBEDTLS_OID_ORG_CERTICOM +#define OID_ORG_DOD MBEDTLS_OID_ORG_DOD +#define OID_ORG_GOV MBEDTLS_OID_ORG_GOV +#define OID_ORG_NETSCAPE MBEDTLS_OID_ORG_NETSCAPE +#define OID_ORG_OIW MBEDTLS_OID_ORG_OIW +#define OID_ORG_RSA_DATA_SECURITY MBEDTLS_OID_ORG_RSA_DATA_SECURITY +#define OID_ORG_TELETRUST MBEDTLS_OID_ORG_TELETRUST +#define OID_PKCS MBEDTLS_OID_PKCS +#define OID_PKCS1 MBEDTLS_OID_PKCS1 +#define OID_PKCS12 MBEDTLS_OID_PKCS12 +#define OID_PKCS12_PBE MBEDTLS_OID_PKCS12_PBE +#define OID_PKCS12_PBE_SHA1_DES2_EDE_CBC MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC +#define OID_PKCS12_PBE_SHA1_DES3_EDE_CBC MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC +#define OID_PKCS12_PBE_SHA1_RC2_128_CBC MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_128_CBC +#define OID_PKCS12_PBE_SHA1_RC2_40_CBC MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_40_CBC +#define OID_PKCS12_PBE_SHA1_RC4_128 MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_128 +#define OID_PKCS12_PBE_SHA1_RC4_40 MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_40 +#define OID_PKCS1_MD2 MBEDTLS_OID_PKCS1_MD2 +#define OID_PKCS1_MD4 MBEDTLS_OID_PKCS1_MD4 +#define OID_PKCS1_MD5 MBEDTLS_OID_PKCS1_MD5 +#define OID_PKCS1_RSA MBEDTLS_OID_PKCS1_RSA +#define OID_PKCS1_SHA1 MBEDTLS_OID_PKCS1_SHA1 +#define OID_PKCS1_SHA224 MBEDTLS_OID_PKCS1_SHA224 +#define OID_PKCS1_SHA256 MBEDTLS_OID_PKCS1_SHA256 +#define OID_PKCS1_SHA384 MBEDTLS_OID_PKCS1_SHA384 +#define OID_PKCS1_SHA512 MBEDTLS_OID_PKCS1_SHA512 +#define OID_PKCS5 MBEDTLS_OID_PKCS5 +#define OID_PKCS5_PBES2 MBEDTLS_OID_PKCS5_PBES2 +#define OID_PKCS5_PBE_MD2_DES_CBC MBEDTLS_OID_PKCS5_PBE_MD2_DES_CBC +#define OID_PKCS5_PBE_MD2_RC2_CBC MBEDTLS_OID_PKCS5_PBE_MD2_RC2_CBC +#define OID_PKCS5_PBE_MD5_DES_CBC MBEDTLS_OID_PKCS5_PBE_MD5_DES_CBC +#define OID_PKCS5_PBE_MD5_RC2_CBC MBEDTLS_OID_PKCS5_PBE_MD5_RC2_CBC +#define OID_PKCS5_PBE_SHA1_DES_CBC MBEDTLS_OID_PKCS5_PBE_SHA1_DES_CBC +#define OID_PKCS5_PBE_SHA1_RC2_CBC MBEDTLS_OID_PKCS5_PBE_SHA1_RC2_CBC +#define OID_PKCS5_PBKDF2 MBEDTLS_OID_PKCS5_PBKDF2 +#define OID_PKCS5_PBMAC1 MBEDTLS_OID_PKCS5_PBMAC1 +#define OID_PKCS9 MBEDTLS_OID_PKCS9 +#define OID_PKCS9_CSR_EXT_REQ MBEDTLS_OID_PKCS9_CSR_EXT_REQ +#define OID_PKCS9_EMAIL MBEDTLS_OID_PKCS9_EMAIL +#define OID_PKIX MBEDTLS_OID_PKIX +#define OID_POLICY_CONSTRAINTS MBEDTLS_OID_POLICY_CONSTRAINTS +#define OID_POLICY_MAPPINGS MBEDTLS_OID_POLICY_MAPPINGS +#define OID_PRIVATE_KEY_USAGE_PERIOD MBEDTLS_OID_PRIVATE_KEY_USAGE_PERIOD +#define OID_RSASSA_PSS MBEDTLS_OID_RSASSA_PSS +#define OID_RSA_COMPANY MBEDTLS_OID_RSA_COMPANY +#define OID_RSA_SHA_OBS MBEDTLS_OID_RSA_SHA_OBS +#define OID_SERVER_AUTH MBEDTLS_OID_SERVER_AUTH +#define OID_SIZE MBEDTLS_OID_SIZE +#define OID_SUBJECT_ALT_NAME MBEDTLS_OID_SUBJECT_ALT_NAME +#define OID_SUBJECT_DIRECTORY_ATTRS MBEDTLS_OID_SUBJECT_DIRECTORY_ATTRS +#define OID_SUBJECT_KEY_IDENTIFIER MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER +#define OID_TELETRUST MBEDTLS_OID_TELETRUST +#define OID_TIME_STAMPING MBEDTLS_OID_TIME_STAMPING +#define PADLOCK_ACE MBEDTLS_PADLOCK_ACE +#define PADLOCK_ALIGN16 MBEDTLS_PADLOCK_ALIGN16 +#define PADLOCK_PHE MBEDTLS_PADLOCK_PHE +#define PADLOCK_PMM MBEDTLS_PADLOCK_PMM +#define PADLOCK_RNG MBEDTLS_PADLOCK_RNG +#define PKCS12_DERIVE_IV MBEDTLS_PKCS12_DERIVE_IV +#define PKCS12_DERIVE_KEY MBEDTLS_PKCS12_DERIVE_KEY +#define PKCS12_DERIVE_MAC_KEY MBEDTLS_PKCS12_DERIVE_MAC_KEY +#define PKCS12_PBE_DECRYPT MBEDTLS_PKCS12_PBE_DECRYPT +#define PKCS12_PBE_ENCRYPT MBEDTLS_PKCS12_PBE_ENCRYPT +#define PKCS5_DECRYPT MBEDTLS_PKCS5_DECRYPT +#define PKCS5_ENCRYPT MBEDTLS_PKCS5_ENCRYPT +#define POLARSSL_AESNI_AES MBEDTLS_AESNI_AES +#define POLARSSL_AESNI_CLMUL MBEDTLS_AESNI_CLMUL +#define POLARSSL_AESNI_H MBEDTLS_AESNI_H +#define POLARSSL_AES_H MBEDTLS_AES_H +#define POLARSSL_ARC4_H MBEDTLS_ARC4_H +#define POLARSSL_ASN1_H MBEDTLS_ASN1_H +#define POLARSSL_ASN1_WRITE_H MBEDTLS_ASN1_WRITE_H +#define POLARSSL_BASE64_H MBEDTLS_BASE64_H +#define POLARSSL_BIGNUM_H MBEDTLS_BIGNUM_H +#define POLARSSL_BLOWFISH_H MBEDTLS_BLOWFISH_H +#define POLARSSL_BN_MUL_H MBEDTLS_BN_MUL_H +#define POLARSSL_CAMELLIA_H MBEDTLS_CAMELLIA_H +#define POLARSSL_CCM_H MBEDTLS_CCM_H +#define POLARSSL_CERTS_H MBEDTLS_CERTS_H +#define POLARSSL_CHECK_CONFIG_H MBEDTLS_CHECK_CONFIG_H +#define POLARSSL_CIPHERSUITE_NODTLS MBEDTLS_CIPHERSUITE_NODTLS +#define POLARSSL_CIPHERSUITE_SHORT_TAG MBEDTLS_CIPHERSUITE_SHORT_TAG +#define POLARSSL_CIPHERSUITE_WEAK MBEDTLS_CIPHERSUITE_WEAK +#define POLARSSL_CIPHER_AES_128_CBC MBEDTLS_CIPHER_AES_128_CBC +#define POLARSSL_CIPHER_AES_128_CCM MBEDTLS_CIPHER_AES_128_CCM +#define POLARSSL_CIPHER_AES_128_CFB128 MBEDTLS_CIPHER_AES_128_CFB128 +#define POLARSSL_CIPHER_AES_128_CTR MBEDTLS_CIPHER_AES_128_CTR +#define POLARSSL_CIPHER_AES_128_ECB MBEDTLS_CIPHER_AES_128_ECB +#define POLARSSL_CIPHER_AES_128_GCM MBEDTLS_CIPHER_AES_128_GCM +#define POLARSSL_CIPHER_AES_192_CBC MBEDTLS_CIPHER_AES_192_CBC +#define POLARSSL_CIPHER_AES_192_CCM MBEDTLS_CIPHER_AES_192_CCM +#define POLARSSL_CIPHER_AES_192_CFB128 MBEDTLS_CIPHER_AES_192_CFB128 +#define POLARSSL_CIPHER_AES_192_CTR MBEDTLS_CIPHER_AES_192_CTR +#define POLARSSL_CIPHER_AES_192_ECB MBEDTLS_CIPHER_AES_192_ECB +#define POLARSSL_CIPHER_AES_192_GCM MBEDTLS_CIPHER_AES_192_GCM +#define POLARSSL_CIPHER_AES_256_CBC MBEDTLS_CIPHER_AES_256_CBC +#define POLARSSL_CIPHER_AES_256_CCM MBEDTLS_CIPHER_AES_256_CCM +#define POLARSSL_CIPHER_AES_256_CFB128 MBEDTLS_CIPHER_AES_256_CFB128 +#define POLARSSL_CIPHER_AES_256_CTR MBEDTLS_CIPHER_AES_256_CTR +#define POLARSSL_CIPHER_AES_256_ECB MBEDTLS_CIPHER_AES_256_ECB +#define POLARSSL_CIPHER_AES_256_GCM MBEDTLS_CIPHER_AES_256_GCM +#define POLARSSL_CIPHER_ARC4_128 MBEDTLS_CIPHER_ARC4_128 +#define POLARSSL_CIPHER_BLOWFISH_CBC MBEDTLS_CIPHER_BLOWFISH_CBC +#define POLARSSL_CIPHER_BLOWFISH_CFB64 MBEDTLS_CIPHER_BLOWFISH_CFB64 +#define POLARSSL_CIPHER_BLOWFISH_CTR MBEDTLS_CIPHER_BLOWFISH_CTR +#define POLARSSL_CIPHER_BLOWFISH_ECB MBEDTLS_CIPHER_BLOWFISH_ECB +#define POLARSSL_CIPHER_CAMELLIA_128_CBC MBEDTLS_CIPHER_CAMELLIA_128_CBC +#define POLARSSL_CIPHER_CAMELLIA_128_CCM MBEDTLS_CIPHER_CAMELLIA_128_CCM +#define POLARSSL_CIPHER_CAMELLIA_128_CFB128 MBEDTLS_CIPHER_CAMELLIA_128_CFB128 +#define POLARSSL_CIPHER_CAMELLIA_128_CTR MBEDTLS_CIPHER_CAMELLIA_128_CTR +#define POLARSSL_CIPHER_CAMELLIA_128_ECB MBEDTLS_CIPHER_CAMELLIA_128_ECB +#define POLARSSL_CIPHER_CAMELLIA_128_GCM MBEDTLS_CIPHER_CAMELLIA_128_GCM +#define POLARSSL_CIPHER_CAMELLIA_192_CBC MBEDTLS_CIPHER_CAMELLIA_192_CBC +#define POLARSSL_CIPHER_CAMELLIA_192_CCM MBEDTLS_CIPHER_CAMELLIA_192_CCM +#define POLARSSL_CIPHER_CAMELLIA_192_CFB128 MBEDTLS_CIPHER_CAMELLIA_192_CFB128 +#define POLARSSL_CIPHER_CAMELLIA_192_CTR MBEDTLS_CIPHER_CAMELLIA_192_CTR +#define POLARSSL_CIPHER_CAMELLIA_192_ECB MBEDTLS_CIPHER_CAMELLIA_192_ECB +#define POLARSSL_CIPHER_CAMELLIA_192_GCM MBEDTLS_CIPHER_CAMELLIA_192_GCM +#define POLARSSL_CIPHER_CAMELLIA_256_CBC MBEDTLS_CIPHER_CAMELLIA_256_CBC +#define POLARSSL_CIPHER_CAMELLIA_256_CCM MBEDTLS_CIPHER_CAMELLIA_256_CCM +#define POLARSSL_CIPHER_CAMELLIA_256_CFB128 MBEDTLS_CIPHER_CAMELLIA_256_CFB128 +#define POLARSSL_CIPHER_CAMELLIA_256_CTR MBEDTLS_CIPHER_CAMELLIA_256_CTR +#define POLARSSL_CIPHER_CAMELLIA_256_ECB MBEDTLS_CIPHER_CAMELLIA_256_ECB +#define POLARSSL_CIPHER_CAMELLIA_256_GCM MBEDTLS_CIPHER_CAMELLIA_256_GCM +#define POLARSSL_CIPHER_DES_CBC MBEDTLS_CIPHER_DES_CBC +#define POLARSSL_CIPHER_DES_ECB MBEDTLS_CIPHER_DES_ECB +#define POLARSSL_CIPHER_DES_EDE3_CBC MBEDTLS_CIPHER_DES_EDE3_CBC +#define POLARSSL_CIPHER_DES_EDE3_ECB MBEDTLS_CIPHER_DES_EDE3_ECB +#define POLARSSL_CIPHER_DES_EDE_CBC MBEDTLS_CIPHER_DES_EDE_CBC +#define POLARSSL_CIPHER_DES_EDE_ECB MBEDTLS_CIPHER_DES_EDE_ECB +#define POLARSSL_CIPHER_H MBEDTLS_CIPHER_H +#define POLARSSL_CIPHER_ID_3DES MBEDTLS_CIPHER_ID_3DES +#define POLARSSL_CIPHER_ID_AES MBEDTLS_CIPHER_ID_AES +#define POLARSSL_CIPHER_ID_ARC4 MBEDTLS_CIPHER_ID_ARC4 +#define POLARSSL_CIPHER_ID_BLOWFISH MBEDTLS_CIPHER_ID_BLOWFISH +#define POLARSSL_CIPHER_ID_CAMELLIA MBEDTLS_CIPHER_ID_CAMELLIA +#define POLARSSL_CIPHER_ID_DES MBEDTLS_CIPHER_ID_DES +#define POLARSSL_CIPHER_ID_NONE MBEDTLS_CIPHER_ID_NONE +#define POLARSSL_CIPHER_ID_NULL MBEDTLS_CIPHER_ID_NULL +#define POLARSSL_CIPHER_MODE_AEAD MBEDTLS_CIPHER_MODE_AEAD +#define POLARSSL_CIPHER_MODE_STREAM MBEDTLS_CIPHER_MODE_STREAM +#define POLARSSL_CIPHER_MODE_WITH_PADDING MBEDTLS_CIPHER_MODE_WITH_PADDING +#define POLARSSL_CIPHER_NONE MBEDTLS_CIPHER_NONE +#define POLARSSL_CIPHER_NULL MBEDTLS_CIPHER_NULL +#define POLARSSL_CIPHER_VARIABLE_IV_LEN MBEDTLS_CIPHER_VARIABLE_IV_LEN +#define POLARSSL_CIPHER_VARIABLE_KEY_LEN MBEDTLS_CIPHER_VARIABLE_KEY_LEN +#define POLARSSL_CIPHER_WRAP_H MBEDTLS_CIPHER_WRAP_H +#define POLARSSL_CONFIG_H MBEDTLS_CONFIG_H +#define POLARSSL_CTR_DRBG_H MBEDTLS_CTR_DRBG_H +#define POLARSSL_DEBUG_H MBEDTLS_DEBUG_H +#define POLARSSL_DECRYPT MBEDTLS_DECRYPT +#define POLARSSL_DES_H MBEDTLS_DES_H +#define POLARSSL_DHM_H MBEDTLS_DHM_H +#define POLARSSL_DHM_RFC3526_MODP_2048_G MBEDTLS_DHM_RFC3526_MODP_2048_G +#define POLARSSL_DHM_RFC3526_MODP_2048_P MBEDTLS_DHM_RFC3526_MODP_2048_P +#define POLARSSL_DHM_RFC3526_MODP_3072_G MBEDTLS_DHM_RFC3526_MODP_3072_G +#define POLARSSL_DHM_RFC3526_MODP_3072_P MBEDTLS_DHM_RFC3526_MODP_3072_P +#define POLARSSL_DHM_RFC5114_MODP_2048_G MBEDTLS_DHM_RFC5114_MODP_2048_G +#define POLARSSL_DHM_RFC5114_MODP_2048_P MBEDTLS_DHM_RFC5114_MODP_2048_P +#define POLARSSL_ECDH_H MBEDTLS_ECDH_H +#define POLARSSL_ECDH_OURS MBEDTLS_ECDH_OURS +#define POLARSSL_ECDH_THEIRS MBEDTLS_ECDH_THEIRS +#define POLARSSL_ECDSA_H MBEDTLS_ECDSA_H +#define POLARSSL_ECP_DP_BP256R1 MBEDTLS_ECP_DP_BP256R1 +#define POLARSSL_ECP_DP_BP384R1 MBEDTLS_ECP_DP_BP384R1 +#define POLARSSL_ECP_DP_BP512R1 MBEDTLS_ECP_DP_BP512R1 +#define POLARSSL_ECP_DP_M255 MBEDTLS_ECP_DP_CURVE25519 +#define POLARSSL_ECP_DP_MAX MBEDTLS_ECP_DP_MAX +#define POLARSSL_ECP_DP_NONE MBEDTLS_ECP_DP_NONE +#define POLARSSL_ECP_DP_SECP192K1 MBEDTLS_ECP_DP_SECP192K1 +#define POLARSSL_ECP_DP_SECP192R1 MBEDTLS_ECP_DP_SECP192R1 +#define POLARSSL_ECP_DP_SECP224K1 MBEDTLS_ECP_DP_SECP224K1 +#define POLARSSL_ECP_DP_SECP224R1 MBEDTLS_ECP_DP_SECP224R1 +#define POLARSSL_ECP_DP_SECP256K1 MBEDTLS_ECP_DP_SECP256K1 +#define POLARSSL_ECP_DP_SECP256R1 MBEDTLS_ECP_DP_SECP256R1 +#define POLARSSL_ECP_DP_SECP384R1 MBEDTLS_ECP_DP_SECP384R1 +#define POLARSSL_ECP_DP_SECP521R1 MBEDTLS_ECP_DP_SECP521R1 +#define POLARSSL_ECP_H MBEDTLS_ECP_H +#define POLARSSL_ECP_MAX_BYTES MBEDTLS_ECP_MAX_BYTES +#define POLARSSL_ECP_MAX_PT_LEN MBEDTLS_ECP_MAX_PT_LEN +#define POLARSSL_ECP_PF_COMPRESSED MBEDTLS_ECP_PF_COMPRESSED +#define POLARSSL_ECP_PF_UNCOMPRESSED MBEDTLS_ECP_PF_UNCOMPRESSED +#define POLARSSL_ECP_TLS_NAMED_CURVE MBEDTLS_ECP_TLS_NAMED_CURVE +#define POLARSSL_ENCRYPT MBEDTLS_ENCRYPT +#define POLARSSL_ENTROPY_H MBEDTLS_ENTROPY_H +#define POLARSSL_ENTROPY_POLL_H MBEDTLS_ENTROPY_POLL_H +#define POLARSSL_ENTROPY_SHA256_ACCUMULATOR MBEDTLS_ENTROPY_SHA256_ACCUMULATOR +#define POLARSSL_ENTROPY_SHA512_ACCUMULATOR MBEDTLS_ENTROPY_SHA512_ACCUMULATOR +#define POLARSSL_ERROR_H MBEDTLS_ERROR_H +#define POLARSSL_ERR_AES_INVALID_INPUT_LENGTH MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH +#define POLARSSL_ERR_AES_INVALID_KEY_LENGTH MBEDTLS_ERR_AES_INVALID_KEY_LENGTH +#define POLARSSL_ERR_ASN1_BUF_TOO_SMALL MBEDTLS_ERR_ASN1_BUF_TOO_SMALL +#define POLARSSL_ERR_ASN1_INVALID_DATA MBEDTLS_ERR_ASN1_INVALID_DATA +#define POLARSSL_ERR_ASN1_INVALID_LENGTH MBEDTLS_ERR_ASN1_INVALID_LENGTH +#define POLARSSL_ERR_ASN1_LENGTH_MISMATCH MBEDTLS_ERR_ASN1_LENGTH_MISMATCH +#define POLARSSL_ERR_ASN1_MALLOC_FAILED MBEDTLS_ERR_ASN1_ALLOC_FAILED +#define POLARSSL_ERR_ASN1_OUT_OF_DATA MBEDTLS_ERR_ASN1_OUT_OF_DATA +#define POLARSSL_ERR_ASN1_UNEXPECTED_TAG MBEDTLS_ERR_ASN1_UNEXPECTED_TAG +#define POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL +#define POLARSSL_ERR_BASE64_INVALID_CHARACTER MBEDTLS_ERR_BASE64_INVALID_CHARACTER +#define POLARSSL_ERR_BLOWFISH_INVALID_INPUT_LENGTH MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH +#define POLARSSL_ERR_BLOWFISH_INVALID_KEY_LENGTH MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH +#define POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH +#define POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH +#define POLARSSL_ERR_CCM_AUTH_FAILED MBEDTLS_ERR_CCM_AUTH_FAILED +#define POLARSSL_ERR_CCM_BAD_INPUT MBEDTLS_ERR_CCM_BAD_INPUT +#define POLARSSL_ERR_CIPHER_ALLOC_FAILED MBEDTLS_ERR_CIPHER_ALLOC_FAILED +#define POLARSSL_ERR_CIPHER_AUTH_FAILED MBEDTLS_ERR_CIPHER_AUTH_FAILED +#define POLARSSL_ERR_CIPHER_BAD_INPUT_DATA MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA +#define POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED +#define POLARSSL_ERR_CIPHER_INVALID_PADDING MBEDTLS_ERR_CIPHER_INVALID_PADDING +#define POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED +#define POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR +#define POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG +#define POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG +#define POLARSSL_ERR_DES_INVALID_INPUT_LENGTH MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH +#define POLARSSL_ERR_DHM_BAD_INPUT_DATA MBEDTLS_ERR_DHM_BAD_INPUT_DATA +#define POLARSSL_ERR_DHM_CALC_SECRET_FAILED MBEDTLS_ERR_DHM_CALC_SECRET_FAILED +#define POLARSSL_ERR_DHM_FILE_IO_ERROR MBEDTLS_ERR_DHM_FILE_IO_ERROR +#define POLARSSL_ERR_DHM_INVALID_FORMAT MBEDTLS_ERR_DHM_INVALID_FORMAT +#define POLARSSL_ERR_DHM_MAKE_PARAMS_FAILED MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED +#define POLARSSL_ERR_DHM_MAKE_PUBLIC_FAILED MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED +#define POLARSSL_ERR_DHM_MALLOC_FAILED MBEDTLS_ERR_DHM_ALLOC_FAILED +#define POLARSSL_ERR_DHM_READ_PARAMS_FAILED MBEDTLS_ERR_DHM_READ_PARAMS_FAILED +#define POLARSSL_ERR_DHM_READ_PUBLIC_FAILED MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED +#define POLARSSL_ERR_ECP_BAD_INPUT_DATA MBEDTLS_ERR_ECP_BAD_INPUT_DATA +#define POLARSSL_ERR_ECP_BUFFER_TOO_SMALL MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL +#define POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_ECP_INVALID_KEY MBEDTLS_ERR_ECP_INVALID_KEY +#define POLARSSL_ERR_ECP_MALLOC_FAILED MBEDTLS_ERR_ECP_ALLOC_FAILED +#define POLARSSL_ERR_ECP_RANDOM_FAILED MBEDTLS_ERR_ECP_RANDOM_FAILED +#define POLARSSL_ERR_ECP_SIG_LEN_MISMATCH MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH +#define POLARSSL_ERR_ECP_VERIFY_FAILED MBEDTLS_ERR_ECP_VERIFY_FAILED +#define POLARSSL_ERR_ENTROPY_FILE_IO_ERROR MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR +#define POLARSSL_ERR_ENTROPY_MAX_SOURCES MBEDTLS_ERR_ENTROPY_MAX_SOURCES +#define POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED +#define POLARSSL_ERR_ENTROPY_SOURCE_FAILED MBEDTLS_ERR_ENTROPY_SOURCE_FAILED +#define POLARSSL_ERR_GCM_AUTH_FAILED MBEDTLS_ERR_GCM_AUTH_FAILED +#define POLARSSL_ERR_GCM_BAD_INPUT MBEDTLS_ERR_GCM_BAD_INPUT +#define POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED +#define POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR +#define POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG +#define POLARSSL_ERR_HMAC_DRBG_REQUEST_TOO_BIG MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG +#define POLARSSL_ERR_MD_ALLOC_FAILED MBEDTLS_ERR_MD_ALLOC_FAILED +#define POLARSSL_ERR_MD_BAD_INPUT_DATA MBEDTLS_ERR_MD_BAD_INPUT_DATA +#define POLARSSL_ERR_MD_FEATURE_UNAVAILABLE MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_MD_FILE_IO_ERROR MBEDTLS_ERR_MD_FILE_IO_ERROR +#define POLARSSL_ERR_MPI_BAD_INPUT_DATA MBEDTLS_ERR_MPI_BAD_INPUT_DATA +#define POLARSSL_ERR_MPI_BUFFER_TOO_SMALL MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL +#define POLARSSL_ERR_MPI_DIVISION_BY_ZERO MBEDTLS_ERR_MPI_DIVISION_BY_ZERO +#define POLARSSL_ERR_MPI_FILE_IO_ERROR MBEDTLS_ERR_MPI_FILE_IO_ERROR +#define POLARSSL_ERR_MPI_INVALID_CHARACTER MBEDTLS_ERR_MPI_INVALID_CHARACTER +#define POLARSSL_ERR_MPI_MALLOC_FAILED MBEDTLS_ERR_MPI_ALLOC_FAILED +#define POLARSSL_ERR_MPI_NEGATIVE_VALUE MBEDTLS_ERR_MPI_NEGATIVE_VALUE +#define POLARSSL_ERR_MPI_NOT_ACCEPTABLE MBEDTLS_ERR_MPI_NOT_ACCEPTABLE +#define POLARSSL_ERR_NET_ACCEPT_FAILED MBEDTLS_ERR_NET_ACCEPT_FAILED +#define POLARSSL_ERR_NET_BIND_FAILED MBEDTLS_ERR_NET_BIND_FAILED +#define POLARSSL_ERR_NET_CONNECT_FAILED MBEDTLS_ERR_NET_CONNECT_FAILED +#define POLARSSL_ERR_NET_CONN_RESET MBEDTLS_ERR_NET_CONN_RESET +#define POLARSSL_ERR_NET_LISTEN_FAILED MBEDTLS_ERR_NET_LISTEN_FAILED +#define POLARSSL_ERR_NET_RECV_FAILED MBEDTLS_ERR_NET_RECV_FAILED +#define POLARSSL_ERR_NET_SEND_FAILED MBEDTLS_ERR_NET_SEND_FAILED +#define POLARSSL_ERR_NET_SOCKET_FAILED MBEDTLS_ERR_NET_SOCKET_FAILED +#define POLARSSL_ERR_NET_TIMEOUT MBEDTLS_ERR_SSL_TIMEOUT +#define POLARSSL_ERR_NET_UNKNOWN_HOST MBEDTLS_ERR_NET_UNKNOWN_HOST +#define POLARSSL_ERR_NET_WANT_READ MBEDTLS_ERR_SSL_WANT_READ +#define POLARSSL_ERR_NET_WANT_WRITE MBEDTLS_ERR_SSL_WANT_WRITE +#define POLARSSL_ERR_OID_BUF_TOO_SMALL MBEDTLS_ERR_OID_BUF_TOO_SMALL +#define POLARSSL_ERR_OID_NOT_FOUND MBEDTLS_ERR_OID_NOT_FOUND +#define POLARSSL_ERR_PADLOCK_DATA_MISALIGNED MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED +#define POLARSSL_ERR_PEM_BAD_INPUT_DATA MBEDTLS_ERR_PEM_BAD_INPUT_DATA +#define POLARSSL_ERR_PEM_FEATURE_UNAVAILABLE MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_PEM_INVALID_DATA MBEDTLS_ERR_PEM_INVALID_DATA +#define POLARSSL_ERR_PEM_INVALID_ENC_IV MBEDTLS_ERR_PEM_INVALID_ENC_IV +#define POLARSSL_ERR_PEM_MALLOC_FAILED MBEDTLS_ERR_PEM_ALLOC_FAILED +#define POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT +#define POLARSSL_ERR_PEM_PASSWORD_MISMATCH MBEDTLS_ERR_PEM_PASSWORD_MISMATCH +#define POLARSSL_ERR_PEM_PASSWORD_REQUIRED MBEDTLS_ERR_PEM_PASSWORD_REQUIRED +#define POLARSSL_ERR_PEM_UNKNOWN_ENC_ALG MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG +#define POLARSSL_ERR_PKCS12_BAD_INPUT_DATA MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA +#define POLARSSL_ERR_PKCS12_FEATURE_UNAVAILABLE MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_PKCS12_PASSWORD_MISMATCH MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH +#define POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT +#define POLARSSL_ERR_PKCS5_BAD_INPUT_DATA MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA +#define POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_PKCS5_INVALID_FORMAT MBEDTLS_ERR_PKCS5_INVALID_FORMAT +#define POLARSSL_ERR_PKCS5_PASSWORD_MISMATCH MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH +#define POLARSSL_ERR_PK_BAD_INPUT_DATA MBEDTLS_ERR_PK_BAD_INPUT_DATA +#define POLARSSL_ERR_PK_FEATURE_UNAVAILABLE MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_PK_FILE_IO_ERROR MBEDTLS_ERR_PK_FILE_IO_ERROR +#define POLARSSL_ERR_PK_INVALID_ALG MBEDTLS_ERR_PK_INVALID_ALG +#define POLARSSL_ERR_PK_INVALID_PUBKEY MBEDTLS_ERR_PK_INVALID_PUBKEY +#define POLARSSL_ERR_PK_KEY_INVALID_FORMAT MBEDTLS_ERR_PK_KEY_INVALID_FORMAT +#define POLARSSL_ERR_PK_KEY_INVALID_VERSION MBEDTLS_ERR_PK_KEY_INVALID_VERSION +#define POLARSSL_ERR_PK_MALLOC_FAILED MBEDTLS_ERR_PK_ALLOC_FAILED +#define POLARSSL_ERR_PK_PASSWORD_MISMATCH MBEDTLS_ERR_PK_PASSWORD_MISMATCH +#define POLARSSL_ERR_PK_PASSWORD_REQUIRED MBEDTLS_ERR_PK_PASSWORD_REQUIRED +#define POLARSSL_ERR_PK_SIG_LEN_MISMATCH MBEDTLS_ERR_PK_SIG_LEN_MISMATCH +#define POLARSSL_ERR_PK_TYPE_MISMATCH MBEDTLS_ERR_PK_TYPE_MISMATCH +#define POLARSSL_ERR_PK_UNKNOWN_NAMED_CURVE MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE +#define POLARSSL_ERR_PK_UNKNOWN_PK_ALG MBEDTLS_ERR_PK_UNKNOWN_PK_ALG +#define POLARSSL_ERR_RSA_BAD_INPUT_DATA MBEDTLS_ERR_RSA_BAD_INPUT_DATA +#define POLARSSL_ERR_RSA_INVALID_PADDING MBEDTLS_ERR_RSA_INVALID_PADDING +#define POLARSSL_ERR_RSA_KEY_CHECK_FAILED MBEDTLS_ERR_RSA_KEY_CHECK_FAILED +#define POLARSSL_ERR_RSA_KEY_GEN_FAILED MBEDTLS_ERR_RSA_KEY_GEN_FAILED +#define POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE +#define POLARSSL_ERR_RSA_PRIVATE_FAILED MBEDTLS_ERR_RSA_PRIVATE_FAILED +#define POLARSSL_ERR_RSA_PUBLIC_FAILED MBEDTLS_ERR_RSA_PUBLIC_FAILED +#define POLARSSL_ERR_RSA_RNG_FAILED MBEDTLS_ERR_RSA_RNG_FAILED +#define POLARSSL_ERR_RSA_VERIFY_FAILED MBEDTLS_ERR_RSA_VERIFY_FAILED +#define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE +#define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST +#define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY +#define POLARSSL_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC +#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO +#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE +#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS +#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP +#define POLARSSL_ERR_SSL_BAD_HS_FINISHED MBEDTLS_ERR_SSL_BAD_HS_FINISHED +#define POLARSSL_ERR_SSL_BAD_HS_NEW_SESSION_TICKET MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET +#define POLARSSL_ERR_SSL_BAD_HS_PROTOCOL_VERSION MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION +#define POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO +#define POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO_DONE MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE +#define POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE +#define POLARSSL_ERR_SSL_BAD_INPUT_DATA MBEDTLS_ERR_SSL_BAD_INPUT_DATA +#define POLARSSL_ERR_SSL_BUFFER_TOO_SMALL MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL +#define POLARSSL_ERR_SSL_CA_CHAIN_REQUIRED MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED +#define POLARSSL_ERR_SSL_CERTIFICATE_REQUIRED MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED +#define POLARSSL_ERR_SSL_CERTIFICATE_TOO_LARGE MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE +#define POLARSSL_ERR_SSL_COMPRESSION_FAILED MBEDTLS_ERR_SSL_COMPRESSION_FAILED +#define POLARSSL_ERR_SSL_CONN_EOF MBEDTLS_ERR_SSL_CONN_EOF +#define POLARSSL_ERR_SSL_COUNTER_WRAPPING MBEDTLS_ERR_SSL_COUNTER_WRAPPING +#define POLARSSL_ERR_SSL_FATAL_ALERT_MESSAGE MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE +#define POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_SSL_HELLO_VERIFY_REQUIRED MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED +#define POLARSSL_ERR_SSL_HW_ACCEL_FAILED MBEDTLS_ERR_SSL_HW_ACCEL_FAILED +#define POLARSSL_ERR_SSL_HW_ACCEL_FALLTHROUGH MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH +#define POLARSSL_ERR_SSL_INTERNAL_ERROR MBEDTLS_ERR_SSL_INTERNAL_ERROR +#define POLARSSL_ERR_SSL_INVALID_MAC MBEDTLS_ERR_SSL_INVALID_MAC +#define POLARSSL_ERR_SSL_INVALID_RECORD MBEDTLS_ERR_SSL_INVALID_RECORD +#define POLARSSL_ERR_SSL_MALLOC_FAILED MBEDTLS_ERR_SSL_ALLOC_FAILED +#define POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN +#define POLARSSL_ERR_SSL_NO_CLIENT_CERTIFICATE MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE +#define POLARSSL_ERR_SSL_NO_RNG MBEDTLS_ERR_SSL_NO_RNG +#define POLARSSL_ERR_SSL_NO_USABLE_CIPHERSUITE MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE +#define POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY +#define POLARSSL_ERR_SSL_PEER_VERIFY_FAILED MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED +#define POLARSSL_ERR_SSL_PK_TYPE_MISMATCH MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH +#define POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED +#define POLARSSL_ERR_SSL_SESSION_TICKET_EXPIRED MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED +#define POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE +#define POLARSSL_ERR_SSL_UNKNOWN_CIPHER MBEDTLS_ERR_SSL_UNKNOWN_CIPHER +#define POLARSSL_ERR_SSL_UNKNOWN_IDENTITY MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY +#define POLARSSL_ERR_SSL_WAITING_SERVER_HELLO_RENEGO MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO +#define POLARSSL_ERR_THREADING_BAD_INPUT_DATA MBEDTLS_ERR_THREADING_BAD_INPUT_DATA +#define POLARSSL_ERR_THREADING_FEATURE_UNAVAILABLE MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_THREADING_MUTEX_ERROR MBEDTLS_ERR_THREADING_MUTEX_ERROR +#define POLARSSL_ERR_X509_BAD_INPUT_DATA MBEDTLS_ERR_X509_BAD_INPUT_DATA +#define POLARSSL_ERR_X509_CERT_UNKNOWN_FORMAT MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT +#define POLARSSL_ERR_X509_CERT_VERIFY_FAILED MBEDTLS_ERR_X509_CERT_VERIFY_FAILED +#define POLARSSL_ERR_X509_FEATURE_UNAVAILABLE MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_X509_FILE_IO_ERROR MBEDTLS_ERR_X509_FILE_IO_ERROR +#define POLARSSL_ERR_X509_INVALID_ALG MBEDTLS_ERR_X509_INVALID_ALG +#define POLARSSL_ERR_X509_INVALID_DATE MBEDTLS_ERR_X509_INVALID_DATE +#define POLARSSL_ERR_X509_INVALID_EXTENSIONS MBEDTLS_ERR_X509_INVALID_EXTENSIONS +#define POLARSSL_ERR_X509_INVALID_FORMAT MBEDTLS_ERR_X509_INVALID_FORMAT +#define POLARSSL_ERR_X509_INVALID_NAME MBEDTLS_ERR_X509_INVALID_NAME +#define POLARSSL_ERR_X509_INVALID_SERIAL MBEDTLS_ERR_X509_INVALID_SERIAL +#define POLARSSL_ERR_X509_INVALID_SIGNATURE MBEDTLS_ERR_X509_INVALID_SIGNATURE +#define POLARSSL_ERR_X509_INVALID_VERSION MBEDTLS_ERR_X509_INVALID_VERSION +#define POLARSSL_ERR_X509_MALLOC_FAILED MBEDTLS_ERR_X509_ALLOC_FAILED +#define POLARSSL_ERR_X509_SIG_MISMATCH MBEDTLS_ERR_X509_SIG_MISMATCH +#define POLARSSL_ERR_X509_UNKNOWN_OID MBEDTLS_ERR_X509_UNKNOWN_OID +#define POLARSSL_ERR_X509_UNKNOWN_SIG_ALG MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG +#define POLARSSL_ERR_X509_UNKNOWN_VERSION MBEDTLS_ERR_X509_UNKNOWN_VERSION +#define POLARSSL_ERR_XTEA_INVALID_INPUT_LENGTH MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH +#define POLARSSL_GCM_H MBEDTLS_GCM_H +#define POLARSSL_HAVEGE_H MBEDTLS_HAVEGE_H +#define POLARSSL_HAVE_INT32 MBEDTLS_HAVE_INT32 +#define POLARSSL_HAVE_INT64 MBEDTLS_HAVE_INT64 +#define POLARSSL_HAVE_UDBL MBEDTLS_HAVE_UDBL +#define POLARSSL_HAVE_X86 MBEDTLS_HAVE_X86 +#define POLARSSL_HAVE_X86_64 MBEDTLS_HAVE_X86_64 +#define POLARSSL_HMAC_DRBG_H MBEDTLS_HMAC_DRBG_H +#define POLARSSL_HMAC_DRBG_PR_OFF MBEDTLS_HMAC_DRBG_PR_OFF +#define POLARSSL_HMAC_DRBG_PR_ON MBEDTLS_HMAC_DRBG_PR_ON +#define POLARSSL_KEY_EXCHANGE_DHE_PSK MBEDTLS_KEY_EXCHANGE_DHE_PSK +#define POLARSSL_KEY_EXCHANGE_DHE_RSA MBEDTLS_KEY_EXCHANGE_DHE_RSA +#define POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA +#define POLARSSL_KEY_EXCHANGE_ECDHE_PSK MBEDTLS_KEY_EXCHANGE_ECDHE_PSK +#define POLARSSL_KEY_EXCHANGE_ECDHE_RSA MBEDTLS_KEY_EXCHANGE_ECDHE_RSA +#define POLARSSL_KEY_EXCHANGE_ECDH_ECDSA MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA +#define POLARSSL_KEY_EXCHANGE_ECDH_RSA MBEDTLS_KEY_EXCHANGE_ECDH_RSA +#define POLARSSL_KEY_EXCHANGE_NONE MBEDTLS_KEY_EXCHANGE_NONE +#define POLARSSL_KEY_EXCHANGE_PSK MBEDTLS_KEY_EXCHANGE_PSK +#define POLARSSL_KEY_EXCHANGE_RSA MBEDTLS_KEY_EXCHANGE_RSA +#define POLARSSL_KEY_EXCHANGE_RSA_PSK MBEDTLS_KEY_EXCHANGE_RSA_PSK +#define POLARSSL_KEY_EXCHANGE__SOME__ECDHE_ENABLED MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED +#define POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED +#define POLARSSL_KEY_EXCHANGE__WITH_CERT__ENABLED MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED +#define POLARSSL_KEY_LENGTH_DES MBEDTLS_KEY_LENGTH_DES +#define POLARSSL_KEY_LENGTH_DES_EDE MBEDTLS_KEY_LENGTH_DES_EDE +#define POLARSSL_KEY_LENGTH_DES_EDE3 MBEDTLS_KEY_LENGTH_DES_EDE3 +#define POLARSSL_KEY_LENGTH_NONE MBEDTLS_KEY_LENGTH_NONE +#define POLARSSL_MAX_BLOCK_LENGTH MBEDTLS_MAX_BLOCK_LENGTH +#define POLARSSL_MAX_IV_LENGTH MBEDTLS_MAX_IV_LENGTH +#define POLARSSL_MD2_H MBEDTLS_MD2_H +#define POLARSSL_MD4_H MBEDTLS_MD4_H +#define POLARSSL_MD5_H MBEDTLS_MD5_H +#define POLARSSL_MD_H MBEDTLS_MD_H +#define POLARSSL_MD_MAX_SIZE MBEDTLS_MD_MAX_SIZE +#define POLARSSL_MD_MD2 MBEDTLS_MD_MD2 +#define POLARSSL_MD_MD4 MBEDTLS_MD_MD4 +#define POLARSSL_MD_MD5 MBEDTLS_MD_MD5 +#define POLARSSL_MD_NONE MBEDTLS_MD_NONE +#define POLARSSL_MD_RIPEMD160 MBEDTLS_MD_RIPEMD160 +#define POLARSSL_MD_SHA1 MBEDTLS_MD_SHA1 +#define POLARSSL_MD_SHA224 MBEDTLS_MD_SHA224 +#define POLARSSL_MD_SHA256 MBEDTLS_MD_SHA256 +#define POLARSSL_MD_SHA384 MBEDTLS_MD_SHA384 +#define POLARSSL_MD_SHA512 MBEDTLS_MD_SHA512 +#define POLARSSL_MD_WRAP_H MBEDTLS_MD_WRAP_H +#define POLARSSL_MEMORY_BUFFER_ALLOC_H MBEDTLS_MEMORY_BUFFER_ALLOC_H +#define POLARSSL_MODE_CBC MBEDTLS_MODE_CBC +#define POLARSSL_MODE_CCM MBEDTLS_MODE_CCM +#define POLARSSL_MODE_CFB MBEDTLS_MODE_CFB +#define POLARSSL_MODE_CTR MBEDTLS_MODE_CTR +#define POLARSSL_MODE_ECB MBEDTLS_MODE_ECB +#define POLARSSL_MODE_GCM MBEDTLS_MODE_GCM +#define POLARSSL_MODE_NONE MBEDTLS_MODE_NONE +#define POLARSSL_MODE_OFB MBEDTLS_MODE_OFB +#define POLARSSL_MODE_STREAM MBEDTLS_MODE_STREAM +#define POLARSSL_MPI_MAX_BITS MBEDTLS_MPI_MAX_BITS +#define POLARSSL_MPI_MAX_BITS_SCALE100 MBEDTLS_MPI_MAX_BITS_SCALE100 +#define POLARSSL_MPI_MAX_LIMBS MBEDTLS_MPI_MAX_LIMBS +#define POLARSSL_MPI_RW_BUFFER_SIZE MBEDTLS_MPI_RW_BUFFER_SIZE +#define POLARSSL_NET_H MBEDTLS_NET_SOCKETS_H +#define POLARSSL_NET_LISTEN_BACKLOG MBEDTLS_NET_LISTEN_BACKLOG +#define POLARSSL_OID_H MBEDTLS_OID_H +#define POLARSSL_OPERATION_NONE MBEDTLS_OPERATION_NONE +#define POLARSSL_PADDING_NONE MBEDTLS_PADDING_NONE +#define POLARSSL_PADDING_ONE_AND_ZEROS MBEDTLS_PADDING_ONE_AND_ZEROS +#define POLARSSL_PADDING_PKCS7 MBEDTLS_PADDING_PKCS7 +#define POLARSSL_PADDING_ZEROS MBEDTLS_PADDING_ZEROS +#define POLARSSL_PADDING_ZEROS_AND_LEN MBEDTLS_PADDING_ZEROS_AND_LEN +#define POLARSSL_PADLOCK_H MBEDTLS_PADLOCK_H +#define POLARSSL_PEM_H MBEDTLS_PEM_H +#define POLARSSL_PKCS11_H MBEDTLS_PKCS11_H +#define POLARSSL_PKCS12_H MBEDTLS_PKCS12_H +#define POLARSSL_PKCS5_H MBEDTLS_PKCS5_H +#define POLARSSL_PK_DEBUG_ECP MBEDTLS_PK_DEBUG_ECP +#define POLARSSL_PK_DEBUG_MAX_ITEMS MBEDTLS_PK_DEBUG_MAX_ITEMS +#define POLARSSL_PK_DEBUG_MPI MBEDTLS_PK_DEBUG_MPI +#define POLARSSL_PK_DEBUG_NONE MBEDTLS_PK_DEBUG_NONE +#define POLARSSL_PK_ECDSA MBEDTLS_PK_ECDSA +#define POLARSSL_PK_ECKEY MBEDTLS_PK_ECKEY +#define POLARSSL_PK_ECKEY_DH MBEDTLS_PK_ECKEY_DH +#define POLARSSL_PK_H MBEDTLS_PK_H +#define POLARSSL_PK_NONE MBEDTLS_PK_NONE +#define POLARSSL_PK_RSA MBEDTLS_PK_RSA +#define POLARSSL_PK_RSASSA_PSS MBEDTLS_PK_RSASSA_PSS +#define POLARSSL_PK_RSA_ALT MBEDTLS_PK_RSA_ALT +#define POLARSSL_PK_WRAP_H MBEDTLS_PK_WRAP_H +#define POLARSSL_PLATFORM_H MBEDTLS_PLATFORM_H +#define POLARSSL_PREMASTER_SIZE MBEDTLS_PREMASTER_SIZE +#define POLARSSL_RIPEMD160_H MBEDTLS_RIPEMD160_H +#define POLARSSL_RSA_H MBEDTLS_RSA_H +#define POLARSSL_SHA1_H MBEDTLS_SHA1_H +#define POLARSSL_SHA256_H MBEDTLS_SHA256_H +#define POLARSSL_SHA512_H MBEDTLS_SHA512_H +#define POLARSSL_SSL_CACHE_H MBEDTLS_SSL_CACHE_H +#define POLARSSL_SSL_CIPHERSUITES_H MBEDTLS_SSL_CIPHERSUITES_H +#define POLARSSL_SSL_COOKIE_H MBEDTLS_SSL_COOKIE_H +#define POLARSSL_SSL_H MBEDTLS_SSL_H +#define POLARSSL_THREADING_H MBEDTLS_THREADING_H +#define POLARSSL_THREADING_IMPL MBEDTLS_THREADING_IMPL +#define POLARSSL_TIMING_H MBEDTLS_TIMING_H +#define POLARSSL_VERSION_H MBEDTLS_VERSION_H +#define POLARSSL_VERSION_MAJOR MBEDTLS_VERSION_MAJOR +#define POLARSSL_VERSION_MINOR MBEDTLS_VERSION_MINOR +#define POLARSSL_VERSION_NUMBER MBEDTLS_VERSION_NUMBER +#define POLARSSL_VERSION_PATCH MBEDTLS_VERSION_PATCH +#define POLARSSL_VERSION_STRING MBEDTLS_VERSION_STRING +#define POLARSSL_VERSION_STRING_FULL MBEDTLS_VERSION_STRING_FULL +#define POLARSSL_X509_CRL_H MBEDTLS_X509_CRL_H +#define POLARSSL_X509_CRT_H MBEDTLS_X509_CRT_H +#define POLARSSL_X509_CSR_H MBEDTLS_X509_CSR_H +#define POLARSSL_X509_H MBEDTLS_X509_H +#define POLARSSL_XTEA_H MBEDTLS_XTEA_H +#define RSA_CRYPT MBEDTLS_RSA_CRYPT +#define RSA_PKCS_V15 MBEDTLS_RSA_PKCS_V15 +#define RSA_PKCS_V21 MBEDTLS_RSA_PKCS_V21 +#define RSA_PRIVATE MBEDTLS_RSA_PRIVATE +#define RSA_PUBLIC MBEDTLS_RSA_PUBLIC +#define RSA_SALT_LEN_ANY MBEDTLS_RSA_SALT_LEN_ANY +#define RSA_SIGN MBEDTLS_RSA_SIGN +#define SSL_ALERT_LEVEL_FATAL MBEDTLS_SSL_ALERT_LEVEL_FATAL +#define SSL_ALERT_LEVEL_WARNING MBEDTLS_SSL_ALERT_LEVEL_WARNING +#define SSL_ALERT_MSG_ACCESS_DENIED MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED +#define SSL_ALERT_MSG_BAD_CERT MBEDTLS_SSL_ALERT_MSG_BAD_CERT +#define SSL_ALERT_MSG_BAD_RECORD_MAC MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC +#define SSL_ALERT_MSG_CERT_EXPIRED MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED +#define SSL_ALERT_MSG_CERT_REVOKED MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED +#define SSL_ALERT_MSG_CERT_UNKNOWN MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN +#define SSL_ALERT_MSG_CLOSE_NOTIFY MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY +#define SSL_ALERT_MSG_DECODE_ERROR MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR +#define SSL_ALERT_MSG_DECOMPRESSION_FAILURE MBEDTLS_SSL_ALERT_MSG_DECOMPRESSION_FAILURE +#define SSL_ALERT_MSG_DECRYPTION_FAILED MBEDTLS_SSL_ALERT_MSG_DECRYPTION_FAILED +#define SSL_ALERT_MSG_DECRYPT_ERROR MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR +#define SSL_ALERT_MSG_EXPORT_RESTRICTION MBEDTLS_SSL_ALERT_MSG_EXPORT_RESTRICTION +#define SSL_ALERT_MSG_HANDSHAKE_FAILURE MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE +#define SSL_ALERT_MSG_ILLEGAL_PARAMETER MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER +#define SSL_ALERT_MSG_INAPROPRIATE_FALLBACK MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK +#define SSL_ALERT_MSG_INSUFFICIENT_SECURITY MBEDTLS_SSL_ALERT_MSG_INSUFFICIENT_SECURITY +#define SSL_ALERT_MSG_INTERNAL_ERROR MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR +#define SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL +#define SSL_ALERT_MSG_NO_CERT MBEDTLS_SSL_ALERT_MSG_NO_CERT +#define SSL_ALERT_MSG_NO_RENEGOTIATION MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION +#define SSL_ALERT_MSG_PROTOCOL_VERSION MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION +#define SSL_ALERT_MSG_RECORD_OVERFLOW MBEDTLS_SSL_ALERT_MSG_RECORD_OVERFLOW +#define SSL_ALERT_MSG_UNEXPECTED_MESSAGE MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE +#define SSL_ALERT_MSG_UNKNOWN_CA MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA +#define SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY +#define SSL_ALERT_MSG_UNRECOGNIZED_NAME MBEDTLS_SSL_ALERT_MSG_UNRECOGNIZED_NAME +#define SSL_ALERT_MSG_UNSUPPORTED_CERT MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT +#define SSL_ALERT_MSG_UNSUPPORTED_EXT MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT +#define SSL_ALERT_MSG_USER_CANCELED MBEDTLS_SSL_ALERT_MSG_USER_CANCELED +#define SSL_ANTI_REPLAY_DISABLED MBEDTLS_SSL_ANTI_REPLAY_DISABLED +#define SSL_ANTI_REPLAY_ENABLED MBEDTLS_SSL_ANTI_REPLAY_ENABLED +#define SSL_ARC4_DISABLED MBEDTLS_SSL_ARC4_DISABLED +#define SSL_ARC4_ENABLED MBEDTLS_SSL_ARC4_ENABLED +#define SSL_BUFFER_LEN ( ( ( MBEDTLS_SSL_IN_BUFFER_LEN ) < ( MBEDTLS_SSL_OUT_BUFFER_LEN ) ) \ + ? ( MBEDTLS_SSL_IN_BUFFER_LEN ) : ( MBEDTLS_SSL_OUT_BUFFER_LEN ) ) +#define SSL_CACHE_DEFAULT_MAX_ENTRIES MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES +#define SSL_CACHE_DEFAULT_TIMEOUT MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT +#define SSL_CBC_RECORD_SPLITTING_DISABLED MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED +#define SSL_CBC_RECORD_SPLITTING_ENABLED MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED +#define SSL_CERTIFICATE_REQUEST MBEDTLS_SSL_CERTIFICATE_REQUEST +#define SSL_CERTIFICATE_VERIFY MBEDTLS_SSL_CERTIFICATE_VERIFY +#define SSL_CERT_TYPE_ECDSA_SIGN MBEDTLS_SSL_CERT_TYPE_ECDSA_SIGN +#define SSL_CERT_TYPE_RSA_SIGN MBEDTLS_SSL_CERT_TYPE_RSA_SIGN +#define SSL_CHANNEL_INBOUND MBEDTLS_SSL_CHANNEL_INBOUND +#define SSL_CHANNEL_OUTBOUND MBEDTLS_SSL_CHANNEL_OUTBOUND +#define SSL_CIPHERSUITES MBEDTLS_SSL_CIPHERSUITES +#define SSL_CLIENT_CERTIFICATE MBEDTLS_SSL_CLIENT_CERTIFICATE +#define SSL_CLIENT_CHANGE_CIPHER_SPEC MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC +#define SSL_CLIENT_FINISHED MBEDTLS_SSL_CLIENT_FINISHED +#define SSL_CLIENT_HELLO MBEDTLS_SSL_CLIENT_HELLO +#define SSL_CLIENT_KEY_EXCHANGE MBEDTLS_SSL_CLIENT_KEY_EXCHANGE +#define SSL_COMPRESSION_ADD MBEDTLS_SSL_COMPRESSION_ADD +#define SSL_COMPRESS_DEFLATE MBEDTLS_SSL_COMPRESS_DEFLATE +#define SSL_COMPRESS_NULL MBEDTLS_SSL_COMPRESS_NULL +#define SSL_DEBUG_BUF MBEDTLS_SSL_DEBUG_BUF +#define SSL_DEBUG_CRT MBEDTLS_SSL_DEBUG_CRT +#define SSL_DEBUG_ECP MBEDTLS_SSL_DEBUG_ECP +#define SSL_DEBUG_MPI MBEDTLS_SSL_DEBUG_MPI +#define SSL_DEBUG_MSG MBEDTLS_SSL_DEBUG_MSG +#define SSL_DEBUG_RET MBEDTLS_SSL_DEBUG_RET +#define SSL_DEFAULT_TICKET_LIFETIME MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME +#define SSL_DTLS_TIMEOUT_DFL_MAX MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX +#define SSL_DTLS_TIMEOUT_DFL_MIN MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN +#define SSL_EMPTY_RENEGOTIATION_INFO MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO +#define SSL_ETM_DISABLED MBEDTLS_SSL_ETM_DISABLED +#define SSL_ETM_ENABLED MBEDTLS_SSL_ETM_ENABLED +#define SSL_EXTENDED_MS_DISABLED MBEDTLS_SSL_EXTENDED_MS_DISABLED +#define SSL_EXTENDED_MS_ENABLED MBEDTLS_SSL_EXTENDED_MS_ENABLED +#define SSL_FALLBACK_SCSV MBEDTLS_SSL_FALLBACK_SCSV +#define SSL_FLUSH_BUFFERS MBEDTLS_SSL_FLUSH_BUFFERS +#define SSL_HANDSHAKE_OVER MBEDTLS_SSL_HANDSHAKE_OVER +#define SSL_HANDSHAKE_WRAPUP MBEDTLS_SSL_HANDSHAKE_WRAPUP +#define SSL_HASH_MD5 MBEDTLS_SSL_HASH_MD5 +#define SSL_HASH_NONE MBEDTLS_SSL_HASH_NONE +#define SSL_HASH_SHA1 MBEDTLS_SSL_HASH_SHA1 +#define SSL_HASH_SHA224 MBEDTLS_SSL_HASH_SHA224 +#define SSL_HASH_SHA256 MBEDTLS_SSL_HASH_SHA256 +#define SSL_HASH_SHA384 MBEDTLS_SSL_HASH_SHA384 +#define SSL_HASH_SHA512 MBEDTLS_SSL_HASH_SHA512 +#define SSL_HELLO_REQUEST MBEDTLS_SSL_HELLO_REQUEST +#define SSL_HS_CERTIFICATE MBEDTLS_SSL_HS_CERTIFICATE +#define SSL_HS_CERTIFICATE_REQUEST MBEDTLS_SSL_HS_CERTIFICATE_REQUEST +#define SSL_HS_CERTIFICATE_VERIFY MBEDTLS_SSL_HS_CERTIFICATE_VERIFY +#define SSL_HS_CLIENT_HELLO MBEDTLS_SSL_HS_CLIENT_HELLO +#define SSL_HS_CLIENT_KEY_EXCHANGE MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE +#define SSL_HS_FINISHED MBEDTLS_SSL_HS_FINISHED +#define SSL_HS_HELLO_REQUEST MBEDTLS_SSL_HS_HELLO_REQUEST +#define SSL_HS_HELLO_VERIFY_REQUEST MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST +#define SSL_HS_NEW_SESSION_TICKET MBEDTLS_SSL_HS_NEW_SESSION_TICKET +#define SSL_HS_SERVER_HELLO MBEDTLS_SSL_HS_SERVER_HELLO +#define SSL_HS_SERVER_HELLO_DONE MBEDTLS_SSL_HS_SERVER_HELLO_DONE +#define SSL_HS_SERVER_KEY_EXCHANGE MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE +#define SSL_INITIAL_HANDSHAKE MBEDTLS_SSL_INITIAL_HANDSHAKE +#define SSL_IS_CLIENT MBEDTLS_SSL_IS_CLIENT +#define SSL_IS_FALLBACK MBEDTLS_SSL_IS_FALLBACK +#define SSL_IS_NOT_FALLBACK MBEDTLS_SSL_IS_NOT_FALLBACK +#define SSL_IS_SERVER MBEDTLS_SSL_IS_SERVER +#define SSL_LEGACY_ALLOW_RENEGOTIATION MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION +#define SSL_LEGACY_BREAK_HANDSHAKE MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE +#define SSL_LEGACY_NO_RENEGOTIATION MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION +#define SSL_LEGACY_RENEGOTIATION MBEDTLS_SSL_LEGACY_RENEGOTIATION +#define SSL_MAC_ADD MBEDTLS_SSL_MAC_ADD +#define SSL_MAJOR_VERSION_3 MBEDTLS_SSL_MAJOR_VERSION_3 +#define SSL_MAX_CONTENT_LEN MBEDTLS_SSL_MAX_CONTENT_LEN +#define SSL_MAX_FRAG_LEN_1024 MBEDTLS_SSL_MAX_FRAG_LEN_1024 +#define SSL_MAX_FRAG_LEN_2048 MBEDTLS_SSL_MAX_FRAG_LEN_2048 +#define SSL_MAX_FRAG_LEN_4096 MBEDTLS_SSL_MAX_FRAG_LEN_4096 +#define SSL_MAX_FRAG_LEN_512 MBEDTLS_SSL_MAX_FRAG_LEN_512 +#define SSL_MAX_FRAG_LEN_INVALID MBEDTLS_SSL_MAX_FRAG_LEN_INVALID +#define SSL_MAX_FRAG_LEN_NONE MBEDTLS_SSL_MAX_FRAG_LEN_NONE +#define SSL_MAX_MAJOR_VERSION MBEDTLS_SSL_MAX_MAJOR_VERSION +#define SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MAX_MINOR_VERSION +#define SSL_MINOR_VERSION_0 MBEDTLS_SSL_MINOR_VERSION_0 +#define SSL_MINOR_VERSION_1 MBEDTLS_SSL_MINOR_VERSION_1 +#define SSL_MINOR_VERSION_2 MBEDTLS_SSL_MINOR_VERSION_2 +#define SSL_MINOR_VERSION_3 MBEDTLS_SSL_MINOR_VERSION_3 +#define SSL_MIN_MAJOR_VERSION MBEDTLS_SSL_MIN_MAJOR_VERSION +#define SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MIN_MINOR_VERSION +#define SSL_MSG_ALERT MBEDTLS_SSL_MSG_ALERT +#define SSL_MSG_APPLICATION_DATA MBEDTLS_SSL_MSG_APPLICATION_DATA +#define SSL_MSG_CHANGE_CIPHER_SPEC MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC +#define SSL_MSG_HANDSHAKE MBEDTLS_SSL_MSG_HANDSHAKE +#define SSL_PADDING_ADD MBEDTLS_SSL_PADDING_ADD +#define SSL_RENEGOTIATION MBEDTLS_SSL_RENEGOTIATION +#define SSL_RENEGOTIATION_DISABLED MBEDTLS_SSL_RENEGOTIATION_DISABLED +#define SSL_RENEGOTIATION_DONE MBEDTLS_SSL_RENEGOTIATION_DONE +#define SSL_RENEGOTIATION_ENABLED MBEDTLS_SSL_RENEGOTIATION_ENABLED +#define SSL_RENEGOTIATION_NOT_ENFORCED MBEDTLS_SSL_RENEGOTIATION_NOT_ENFORCED +#define SSL_RENEGOTIATION_PENDING MBEDTLS_SSL_RENEGOTIATION_PENDING +#define SSL_RENEGO_MAX_RECORDS_DEFAULT MBEDTLS_SSL_RENEGO_MAX_RECORDS_DEFAULT +#define SSL_RETRANS_FINISHED MBEDTLS_SSL_RETRANS_FINISHED +#define SSL_RETRANS_PREPARING MBEDTLS_SSL_RETRANS_PREPARING +#define SSL_RETRANS_SENDING MBEDTLS_SSL_RETRANS_SENDING +#define SSL_RETRANS_WAITING MBEDTLS_SSL_RETRANS_WAITING +#define SSL_SECURE_RENEGOTIATION MBEDTLS_SSL_SECURE_RENEGOTIATION +#define SSL_SERVER_CERTIFICATE MBEDTLS_SSL_SERVER_CERTIFICATE +#define SSL_SERVER_CHANGE_CIPHER_SPEC MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC +#define SSL_SERVER_FINISHED MBEDTLS_SSL_SERVER_FINISHED +#define SSL_SERVER_HELLO MBEDTLS_SSL_SERVER_HELLO +#define SSL_SERVER_HELLO_DONE MBEDTLS_SSL_SERVER_HELLO_DONE +#define SSL_SERVER_HELLO_VERIFY_REQUEST_SENT MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT +#define SSL_SERVER_KEY_EXCHANGE MBEDTLS_SSL_SERVER_KEY_EXCHANGE +#define SSL_SERVER_NEW_SESSION_TICKET MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET +#define SSL_SESSION_TICKETS_DISABLED MBEDTLS_SSL_SESSION_TICKETS_DISABLED +#define SSL_SESSION_TICKETS_ENABLED MBEDTLS_SSL_SESSION_TICKETS_ENABLED +#define SSL_SIG_ANON MBEDTLS_SSL_SIG_ANON +#define SSL_SIG_ECDSA MBEDTLS_SSL_SIG_ECDSA +#define SSL_SIG_RSA MBEDTLS_SSL_SIG_RSA +#define SSL_TRANSPORT_DATAGRAM MBEDTLS_SSL_TRANSPORT_DATAGRAM +#define SSL_TRANSPORT_STREAM MBEDTLS_SSL_TRANSPORT_STREAM +#define SSL_TRUNCATED_HMAC_LEN MBEDTLS_SSL_TRUNCATED_HMAC_LEN +#define SSL_TRUNC_HMAC_DISABLED MBEDTLS_SSL_TRUNC_HMAC_DISABLED +#define SSL_TRUNC_HMAC_ENABLED MBEDTLS_SSL_TRUNC_HMAC_ENABLED +#define SSL_VERIFY_DATA_MAX_LEN MBEDTLS_SSL_VERIFY_DATA_MAX_LEN +#define SSL_VERIFY_NONE MBEDTLS_SSL_VERIFY_NONE +#define SSL_VERIFY_OPTIONAL MBEDTLS_SSL_VERIFY_OPTIONAL +#define SSL_VERIFY_REQUIRED MBEDTLS_SSL_VERIFY_REQUIRED +#define TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA +#define TLS_DHE_PSK_WITH_AES_128_CBC_SHA MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA +#define TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 +#define TLS_DHE_PSK_WITH_AES_128_CCM MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM +#define TLS_DHE_PSK_WITH_AES_128_CCM_8 MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8 +#define TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 +#define TLS_DHE_PSK_WITH_AES_256_CBC_SHA MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA +#define TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 +#define TLS_DHE_PSK_WITH_AES_256_CCM MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM +#define TLS_DHE_PSK_WITH_AES_256_CCM_8 MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8 +#define TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 +#define TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 +#define TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_DHE_PSK_WITH_NULL_SHA MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA +#define TLS_DHE_PSK_WITH_NULL_SHA256 MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256 +#define TLS_DHE_PSK_WITH_NULL_SHA384 MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384 +#define TLS_DHE_PSK_WITH_RC4_128_SHA MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA +#define TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA +#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA +#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 +#define TLS_DHE_RSA_WITH_AES_128_CCM MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM +#define TLS_DHE_RSA_WITH_AES_128_CCM_8 MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8 +#define TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 +#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA +#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 +#define TLS_DHE_RSA_WITH_AES_256_CCM MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM +#define TLS_DHE_RSA_WITH_AES_256_CCM_8 MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8 +#define TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 +#define TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA +#define TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA +#define TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 +#define TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_DHE_RSA_WITH_DES_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA +#define TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA +#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA +#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 +#define TLS_ECDHE_ECDSA_WITH_AES_128_CCM MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM +#define TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 +#define TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 +#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA +#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 +#define TLS_ECDHE_ECDSA_WITH_AES_256_CCM MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM +#define TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 +#define TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 +#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 +#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_ECDHE_ECDSA_WITH_NULL_SHA MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA +#define TLS_ECDHE_ECDSA_WITH_RC4_128_SHA MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA +#define TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA +#define TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA +#define TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 +#define TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA +#define TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 +#define TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 +#define TLS_ECDHE_PSK_WITH_NULL_SHA MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA +#define TLS_ECDHE_PSK_WITH_NULL_SHA256 MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256 +#define TLS_ECDHE_PSK_WITH_NULL_SHA384 MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384 +#define TLS_ECDHE_PSK_WITH_RC4_128_SHA MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA +#define TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA +#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA +#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 +#define TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 +#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA +#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 +#define TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 +#define TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 +#define TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_ECDHE_RSA_WITH_NULL_SHA MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA +#define TLS_ECDHE_RSA_WITH_RC4_128_SHA MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA +#define TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA +#define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA +#define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 +#define TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 +#define TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA +#define TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 +#define TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 +#define TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 +#define TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_ECDH_ECDSA_WITH_NULL_SHA MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA +#define TLS_ECDH_ECDSA_WITH_RC4_128_SHA MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA +#define TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA +#define TLS_ECDH_RSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA +#define TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 +#define TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 +#define TLS_ECDH_RSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA +#define TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 +#define TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 +#define TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 +#define TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_ECDH_RSA_WITH_NULL_SHA MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA +#define TLS_ECDH_RSA_WITH_RC4_128_SHA MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA +#define TLS_EXT_ALPN MBEDTLS_TLS_EXT_ALPN +#define TLS_EXT_ENCRYPT_THEN_MAC MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC +#define TLS_EXT_EXTENDED_MASTER_SECRET MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET +#define TLS_EXT_MAX_FRAGMENT_LENGTH MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH +#define TLS_EXT_RENEGOTIATION_INFO MBEDTLS_TLS_EXT_RENEGOTIATION_INFO +#define TLS_EXT_SERVERNAME MBEDTLS_TLS_EXT_SERVERNAME +#define TLS_EXT_SERVERNAME_HOSTNAME MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME +#define TLS_EXT_SESSION_TICKET MBEDTLS_TLS_EXT_SESSION_TICKET +#define TLS_EXT_SIG_ALG MBEDTLS_TLS_EXT_SIG_ALG +#define TLS_EXT_SUPPORTED_ELLIPTIC_CURVES MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES +#define TLS_EXT_SUPPORTED_POINT_FORMATS MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS +#define TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT +#define TLS_EXT_TRUNCATED_HMAC MBEDTLS_TLS_EXT_TRUNCATED_HMAC +#define TLS_PSK_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA +#define TLS_PSK_WITH_AES_128_CBC_SHA MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA +#define TLS_PSK_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 +#define TLS_PSK_WITH_AES_128_CCM MBEDTLS_TLS_PSK_WITH_AES_128_CCM +#define TLS_PSK_WITH_AES_128_CCM_8 MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8 +#define TLS_PSK_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 +#define TLS_PSK_WITH_AES_256_CBC_SHA MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA +#define TLS_PSK_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 +#define TLS_PSK_WITH_AES_256_CCM MBEDTLS_TLS_PSK_WITH_AES_256_CCM +#define TLS_PSK_WITH_AES_256_CCM_8 MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8 +#define TLS_PSK_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 +#define TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 +#define TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_PSK_WITH_NULL_SHA MBEDTLS_TLS_PSK_WITH_NULL_SHA +#define TLS_PSK_WITH_NULL_SHA256 MBEDTLS_TLS_PSK_WITH_NULL_SHA256 +#define TLS_PSK_WITH_NULL_SHA384 MBEDTLS_TLS_PSK_WITH_NULL_SHA384 +#define TLS_PSK_WITH_RC4_128_SHA MBEDTLS_TLS_PSK_WITH_RC4_128_SHA +#define TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA +#define TLS_RSA_PSK_WITH_AES_128_CBC_SHA MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA +#define TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 +#define TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 +#define TLS_RSA_PSK_WITH_AES_256_CBC_SHA MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA +#define TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 +#define TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 +#define TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 +#define TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_RSA_PSK_WITH_NULL_SHA MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA +#define TLS_RSA_PSK_WITH_NULL_SHA256 MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256 +#define TLS_RSA_PSK_WITH_NULL_SHA384 MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384 +#define TLS_RSA_PSK_WITH_RC4_128_SHA MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA +#define TLS_RSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA +#define TLS_RSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA +#define TLS_RSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 +#define TLS_RSA_WITH_AES_128_CCM MBEDTLS_TLS_RSA_WITH_AES_128_CCM +#define TLS_RSA_WITH_AES_128_CCM_8 MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8 +#define TLS_RSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 +#define TLS_RSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA +#define TLS_RSA_WITH_AES_256_CBC_SHA256 MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 +#define TLS_RSA_WITH_AES_256_CCM MBEDTLS_TLS_RSA_WITH_AES_256_CCM +#define TLS_RSA_WITH_AES_256_CCM_8 MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8 +#define TLS_RSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 +#define TLS_RSA_WITH_CAMELLIA_128_CBC_SHA MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA +#define TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_RSA_WITH_CAMELLIA_256_CBC_SHA MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA +#define TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 +#define TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_RSA_WITH_DES_CBC_SHA MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA +#define TLS_RSA_WITH_NULL_MD5 MBEDTLS_TLS_RSA_WITH_NULL_MD5 +#define TLS_RSA_WITH_NULL_SHA MBEDTLS_TLS_RSA_WITH_NULL_SHA +#define TLS_RSA_WITH_NULL_SHA256 MBEDTLS_TLS_RSA_WITH_NULL_SHA256 +#define TLS_RSA_WITH_RC4_128_MD5 MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 +#define TLS_RSA_WITH_RC4_128_SHA MBEDTLS_TLS_RSA_WITH_RC4_128_SHA +#define X509_CRT_VERSION_1 MBEDTLS_X509_CRT_VERSION_1 +#define X509_CRT_VERSION_2 MBEDTLS_X509_CRT_VERSION_2 +#define X509_CRT_VERSION_3 MBEDTLS_X509_CRT_VERSION_3 +#define X509_FORMAT_DER MBEDTLS_X509_FORMAT_DER +#define X509_FORMAT_PEM MBEDTLS_X509_FORMAT_PEM +#define X509_MAX_DN_NAME_SIZE MBEDTLS_X509_MAX_DN_NAME_SIZE +#define X509_RFC5280_MAX_SERIAL_LEN MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN +#define X509_RFC5280_UTC_TIME_LEN MBEDTLS_X509_RFC5280_UTC_TIME_LEN +#define XTEA_DECRYPT MBEDTLS_XTEA_DECRYPT +#define XTEA_ENCRYPT MBEDTLS_XTEA_ENCRYPT +#define _asn1_bitstring mbedtls_asn1_bitstring +#define _asn1_buf mbedtls_asn1_buf +#define _asn1_named_data mbedtls_asn1_named_data +#define _asn1_sequence mbedtls_asn1_sequence +#define _ssl_cache_context mbedtls_ssl_cache_context +#define _ssl_cache_entry mbedtls_ssl_cache_entry +#define _ssl_ciphersuite_t mbedtls_ssl_ciphersuite_t +#define _ssl_context mbedtls_ssl_context +#define _ssl_flight_item mbedtls_ssl_flight_item +#define _ssl_handshake_params mbedtls_ssl_handshake_params +#define _ssl_key_cert mbedtls_ssl_key_cert +#define _ssl_premaster_secret mbedtls_ssl_premaster_secret +#define _ssl_session mbedtls_ssl_session +#define _ssl_transform mbedtls_ssl_transform +#define _x509_crl mbedtls_x509_crl +#define _x509_crl_entry mbedtls_x509_crl_entry +#define _x509_crt mbedtls_x509_crt +#define _x509_csr mbedtls_x509_csr +#define _x509_time mbedtls_x509_time +#define _x509write_cert mbedtls_x509write_cert +#define _x509write_csr mbedtls_x509write_csr +#define aes_context mbedtls_aes_context +#define aes_crypt_cbc mbedtls_aes_crypt_cbc +#define aes_crypt_cfb128 mbedtls_aes_crypt_cfb128 +#define aes_crypt_cfb8 mbedtls_aes_crypt_cfb8 +#define aes_crypt_ctr mbedtls_aes_crypt_ctr +#define aes_crypt_ecb mbedtls_aes_crypt_ecb +#define aes_free mbedtls_aes_free +#define aes_init mbedtls_aes_init +#define aes_self_test mbedtls_aes_self_test +#define aes_setkey_dec mbedtls_aes_setkey_dec +#define aes_setkey_enc mbedtls_aes_setkey_enc +#define aesni_crypt_ecb mbedtls_aesni_crypt_ecb +#define aesni_gcm_mult mbedtls_aesni_gcm_mult +#define aesni_inverse_key mbedtls_aesni_inverse_key +#define aesni_setkey_enc mbedtls_aesni_setkey_enc +#define aesni_supports mbedtls_aesni_has_support +#define alarmed mbedtls_timing_alarmed +#define arc4_context mbedtls_arc4_context +#define arc4_crypt mbedtls_arc4_crypt +#define arc4_free mbedtls_arc4_free +#define arc4_init mbedtls_arc4_init +#define arc4_self_test mbedtls_arc4_self_test +#define arc4_setup mbedtls_arc4_setup +#define asn1_bitstring mbedtls_asn1_bitstring +#define asn1_buf mbedtls_asn1_buf +#define asn1_find_named_data mbedtls_asn1_find_named_data +#define asn1_free_named_data mbedtls_asn1_free_named_data +#define asn1_free_named_data_list mbedtls_asn1_free_named_data_list +#define asn1_get_alg mbedtls_asn1_get_alg +#define asn1_get_alg_null mbedtls_asn1_get_alg_null +#define asn1_get_bitstring mbedtls_asn1_get_bitstring +#define asn1_get_bitstring_null mbedtls_asn1_get_bitstring_null +#define asn1_get_bool mbedtls_asn1_get_bool +#define asn1_get_int mbedtls_asn1_get_int +#define asn1_get_len mbedtls_asn1_get_len +#define asn1_get_mpi mbedtls_asn1_get_mpi +#define asn1_get_sequence_of mbedtls_asn1_get_sequence_of +#define asn1_get_tag mbedtls_asn1_get_tag +#define asn1_named_data mbedtls_asn1_named_data +#define asn1_sequence mbedtls_asn1_sequence +#define asn1_store_named_data mbedtls_asn1_store_named_data +#define asn1_write_algorithm_identifier mbedtls_asn1_write_algorithm_identifier +#define asn1_write_bitstring mbedtls_asn1_write_bitstring +#define asn1_write_bool mbedtls_asn1_write_bool +#define asn1_write_ia5_string mbedtls_asn1_write_ia5_string +#define asn1_write_int mbedtls_asn1_write_int +#define asn1_write_len mbedtls_asn1_write_len +#define asn1_write_mpi mbedtls_asn1_write_mpi +#define asn1_write_null mbedtls_asn1_write_null +#define asn1_write_octet_string mbedtls_asn1_write_octet_string +#define asn1_write_oid mbedtls_asn1_write_oid +#define asn1_write_printable_string mbedtls_asn1_write_printable_string +#define asn1_write_raw_buffer mbedtls_asn1_write_raw_buffer +#define asn1_write_tag mbedtls_asn1_write_tag +#define base64_decode mbedtls_base64_decode +#define base64_encode mbedtls_base64_encode +#define base64_self_test mbedtls_base64_self_test +#define blowfish_context mbedtls_blowfish_context +#define blowfish_crypt_cbc mbedtls_blowfish_crypt_cbc +#define blowfish_crypt_cfb64 mbedtls_blowfish_crypt_cfb64 +#define blowfish_crypt_ctr mbedtls_blowfish_crypt_ctr +#define blowfish_crypt_ecb mbedtls_blowfish_crypt_ecb +#define blowfish_free mbedtls_blowfish_free +#define blowfish_init mbedtls_blowfish_init +#define blowfish_setkey mbedtls_blowfish_setkey +#define camellia_context mbedtls_camellia_context +#define camellia_crypt_cbc mbedtls_camellia_crypt_cbc +#define camellia_crypt_cfb128 mbedtls_camellia_crypt_cfb128 +#define camellia_crypt_ctr mbedtls_camellia_crypt_ctr +#define camellia_crypt_ecb mbedtls_camellia_crypt_ecb +#define camellia_free mbedtls_camellia_free +#define camellia_init mbedtls_camellia_init +#define camellia_self_test mbedtls_camellia_self_test +#define camellia_setkey_dec mbedtls_camellia_setkey_dec +#define camellia_setkey_enc mbedtls_camellia_setkey_enc +#define ccm_auth_decrypt mbedtls_ccm_auth_decrypt +#define ccm_context mbedtls_ccm_context +#define ccm_encrypt_and_tag mbedtls_ccm_encrypt_and_tag +#define ccm_free mbedtls_ccm_free +#define ccm_init mbedtls_ccm_init +#define ccm_self_test mbedtls_ccm_self_test +#define cipher_auth_decrypt mbedtls_cipher_auth_decrypt +#define cipher_auth_encrypt mbedtls_cipher_auth_encrypt +#define cipher_base_t mbedtls_cipher_base_t +#define cipher_check_tag mbedtls_cipher_check_tag +#define cipher_context_t mbedtls_cipher_context_t +#define cipher_crypt mbedtls_cipher_crypt +#define cipher_definition_t mbedtls_cipher_definition_t +#define cipher_definitions mbedtls_cipher_definitions +#define cipher_finish mbedtls_cipher_finish +#define cipher_free mbedtls_cipher_free +#define cipher_get_block_size mbedtls_cipher_get_block_size +#define cipher_get_cipher_mode mbedtls_cipher_get_cipher_mode +#define cipher_get_iv_size mbedtls_cipher_get_iv_size +#define cipher_get_key_size mbedtls_cipher_get_key_bitlen +#define cipher_get_name mbedtls_cipher_get_name +#define cipher_get_operation mbedtls_cipher_get_operation +#define cipher_get_type mbedtls_cipher_get_type +#define cipher_id_t mbedtls_cipher_id_t +#define cipher_info_from_string mbedtls_cipher_info_from_string +#define cipher_info_from_type mbedtls_cipher_info_from_type +#define cipher_info_from_values mbedtls_cipher_info_from_values +#define cipher_info_t mbedtls_cipher_info_t +#define cipher_init mbedtls_cipher_init +#define cipher_init_ctx mbedtls_cipher_setup +#define cipher_list mbedtls_cipher_list +#define cipher_mode_t mbedtls_cipher_mode_t +#define cipher_padding_t mbedtls_cipher_padding_t +#define cipher_reset mbedtls_cipher_reset +#define cipher_set_iv mbedtls_cipher_set_iv +#define cipher_set_padding_mode mbedtls_cipher_set_padding_mode +#define cipher_setkey mbedtls_cipher_setkey +#define cipher_type_t mbedtls_cipher_type_t +#define cipher_update mbedtls_cipher_update +#define cipher_update_ad mbedtls_cipher_update_ad +#define cipher_write_tag mbedtls_cipher_write_tag +#define ctr_drbg_context mbedtls_ctr_drbg_context +#define ctr_drbg_free mbedtls_ctr_drbg_free +#define ctr_drbg_init mbedtls_ctr_drbg_init +#define ctr_drbg_random mbedtls_ctr_drbg_random +#define ctr_drbg_random_with_add mbedtls_ctr_drbg_random_with_add +#define ctr_drbg_reseed mbedtls_ctr_drbg_reseed +#define ctr_drbg_self_test mbedtls_ctr_drbg_self_test +#define ctr_drbg_set_entropy_len mbedtls_ctr_drbg_set_entropy_len +#define ctr_drbg_set_prediction_resistance mbedtls_ctr_drbg_set_prediction_resistance +#define ctr_drbg_set_reseed_interval mbedtls_ctr_drbg_set_reseed_interval +#define ctr_drbg_update mbedtls_ctr_drbg_update +#define ctr_drbg_update_seed_file mbedtls_ctr_drbg_update_seed_file +#define ctr_drbg_write_seed_file mbedtls_ctr_drbg_write_seed_file +#define debug_print_buf mbedtls_debug_print_buf +#define debug_print_crt mbedtls_debug_print_crt +#define debug_print_ecp mbedtls_debug_print_ecp +#define debug_print_mpi mbedtls_debug_print_mpi +#define debug_print_msg mbedtls_debug_print_msg +#define debug_print_ret mbedtls_debug_print_ret +#define debug_set_threshold mbedtls_debug_set_threshold +#define des3_context mbedtls_des3_context +#define des3_crypt_cbc mbedtls_des3_crypt_cbc +#define des3_crypt_ecb mbedtls_des3_crypt_ecb +#define des3_free mbedtls_des3_free +#define des3_init mbedtls_des3_init +#define des3_set2key_dec mbedtls_des3_set2key_dec +#define des3_set2key_enc mbedtls_des3_set2key_enc +#define des3_set3key_dec mbedtls_des3_set3key_dec +#define des3_set3key_enc mbedtls_des3_set3key_enc +#define des_context mbedtls_des_context +#define des_crypt_cbc mbedtls_des_crypt_cbc +#define des_crypt_ecb mbedtls_des_crypt_ecb +#define des_free mbedtls_des_free +#define des_init mbedtls_des_init +#define des_key_check_key_parity mbedtls_des_key_check_key_parity +#define des_key_check_weak mbedtls_des_key_check_weak +#define des_key_set_parity mbedtls_des_key_set_parity +#define des_self_test mbedtls_des_self_test +#define des_setkey_dec mbedtls_des_setkey_dec +#define des_setkey_enc mbedtls_des_setkey_enc +#define dhm_calc_secret mbedtls_dhm_calc_secret +#define dhm_context mbedtls_dhm_context +#define dhm_free mbedtls_dhm_free +#define dhm_init mbedtls_dhm_init +#define dhm_make_params mbedtls_dhm_make_params +#define dhm_make_public mbedtls_dhm_make_public +#define dhm_parse_dhm mbedtls_dhm_parse_dhm +#define dhm_parse_dhmfile mbedtls_dhm_parse_dhmfile +#define dhm_read_params mbedtls_dhm_read_params +#define dhm_read_public mbedtls_dhm_read_public +#define dhm_self_test mbedtls_dhm_self_test +#define ecdh_calc_secret mbedtls_ecdh_calc_secret +#define ecdh_compute_shared mbedtls_ecdh_compute_shared +#define ecdh_context mbedtls_ecdh_context +#define ecdh_free mbedtls_ecdh_free +#define ecdh_gen_public mbedtls_ecdh_gen_public +#define ecdh_get_params mbedtls_ecdh_get_params +#define ecdh_init mbedtls_ecdh_init +#define ecdh_make_params mbedtls_ecdh_make_params +#define ecdh_make_public mbedtls_ecdh_make_public +#define ecdh_read_params mbedtls_ecdh_read_params +#define ecdh_read_public mbedtls_ecdh_read_public +#define ecdh_side mbedtls_ecdh_side +#define ecdsa_context mbedtls_ecdsa_context +#define ecdsa_free mbedtls_ecdsa_free +#define ecdsa_from_keypair mbedtls_ecdsa_from_keypair +#define ecdsa_genkey mbedtls_ecdsa_genkey +#define ecdsa_info mbedtls_ecdsa_info +#define ecdsa_init mbedtls_ecdsa_init +#define ecdsa_read_signature mbedtls_ecdsa_read_signature +#define ecdsa_sign mbedtls_ecdsa_sign +#define ecdsa_sign_det mbedtls_ecdsa_sign_det +#define ecdsa_verify mbedtls_ecdsa_verify +#define ecdsa_write_signature mbedtls_ecdsa_write_signature +#define ecdsa_write_signature_det mbedtls_ecdsa_write_signature_det +#define eckey_info mbedtls_eckey_info +#define eckeydh_info mbedtls_eckeydh_info +#define ecp_check_privkey mbedtls_ecp_check_privkey +#define ecp_check_pub_priv mbedtls_ecp_check_pub_priv +#define ecp_check_pubkey mbedtls_ecp_check_pubkey +#define ecp_copy mbedtls_ecp_copy +#define ecp_curve_info mbedtls_ecp_curve_info +#define ecp_curve_info_from_grp_id mbedtls_ecp_curve_info_from_grp_id +#define ecp_curve_info_from_name mbedtls_ecp_curve_info_from_name +#define ecp_curve_info_from_tls_id mbedtls_ecp_curve_info_from_tls_id +#define ecp_curve_list mbedtls_ecp_curve_list +#define ecp_gen_key mbedtls_ecp_gen_key +#define ecp_gen_keypair mbedtls_ecp_gen_keypair +#define ecp_group mbedtls_ecp_group +#define ecp_group_copy mbedtls_ecp_group_copy +#define ecp_group_free mbedtls_ecp_group_free +#define ecp_group_id mbedtls_ecp_group_id +#define ecp_group_init mbedtls_ecp_group_init +#define ecp_grp_id_list mbedtls_ecp_grp_id_list +#define ecp_is_zero mbedtls_ecp_is_zero +#define ecp_keypair mbedtls_ecp_keypair +#define ecp_keypair_free mbedtls_ecp_keypair_free +#define ecp_keypair_init mbedtls_ecp_keypair_init +#define ecp_mul mbedtls_ecp_mul +#define ecp_point mbedtls_ecp_point +#define ecp_point_free mbedtls_ecp_point_free +#define ecp_point_init mbedtls_ecp_point_init +#define ecp_point_read_binary mbedtls_ecp_point_read_binary +#define ecp_point_read_string mbedtls_ecp_point_read_string +#define ecp_point_write_binary mbedtls_ecp_point_write_binary +#define ecp_self_test mbedtls_ecp_self_test +#define ecp_set_zero mbedtls_ecp_set_zero +#define ecp_tls_read_group mbedtls_ecp_tls_read_group +#define ecp_tls_read_point mbedtls_ecp_tls_read_point +#define ecp_tls_write_group mbedtls_ecp_tls_write_group +#define ecp_tls_write_point mbedtls_ecp_tls_write_point +#define ecp_use_known_dp mbedtls_ecp_group_load +#define entropy_add_source mbedtls_entropy_add_source +#define entropy_context mbedtls_entropy_context +#define entropy_free mbedtls_entropy_free +#define entropy_func mbedtls_entropy_func +#define entropy_gather mbedtls_entropy_gather +#define entropy_init mbedtls_entropy_init +#define entropy_self_test mbedtls_entropy_self_test +#define entropy_update_manual mbedtls_entropy_update_manual +#define entropy_update_seed_file mbedtls_entropy_update_seed_file +#define entropy_write_seed_file mbedtls_entropy_write_seed_file +#define error_strerror mbedtls_strerror +#define f_source_ptr mbedtls_entropy_f_source_ptr +#define gcm_auth_decrypt mbedtls_gcm_auth_decrypt +#define gcm_context mbedtls_gcm_context +#define gcm_crypt_and_tag mbedtls_gcm_crypt_and_tag +#define gcm_finish mbedtls_gcm_finish +#define gcm_free mbedtls_gcm_free +#define gcm_init mbedtls_gcm_init +#define gcm_self_test mbedtls_gcm_self_test +#define gcm_starts mbedtls_gcm_starts +#define gcm_update mbedtls_gcm_update +#define get_timer mbedtls_timing_get_timer +#define hardclock mbedtls_timing_hardclock +#define hardclock_poll mbedtls_hardclock_poll +#define havege_free mbedtls_havege_free +#define havege_init mbedtls_havege_init +#define havege_poll mbedtls_havege_poll +#define havege_random mbedtls_havege_random +#define havege_state mbedtls_havege_state +#define hmac_drbg_context mbedtls_hmac_drbg_context +#define hmac_drbg_free mbedtls_hmac_drbg_free +#define hmac_drbg_init mbedtls_hmac_drbg_init +#define hmac_drbg_random mbedtls_hmac_drbg_random +#define hmac_drbg_random_with_add mbedtls_hmac_drbg_random_with_add +#define hmac_drbg_reseed mbedtls_hmac_drbg_reseed +#define hmac_drbg_self_test mbedtls_hmac_drbg_self_test +#define hmac_drbg_set_entropy_len mbedtls_hmac_drbg_set_entropy_len +#define hmac_drbg_set_prediction_resistance mbedtls_hmac_drbg_set_prediction_resistance +#define hmac_drbg_set_reseed_interval mbedtls_hmac_drbg_set_reseed_interval +#define hmac_drbg_update mbedtls_hmac_drbg_update +#define hmac_drbg_update_seed_file mbedtls_hmac_drbg_update_seed_file +#define hmac_drbg_write_seed_file mbedtls_hmac_drbg_write_seed_file +#define hr_time mbedtls_timing_hr_time +#define key_exchange_type_t mbedtls_key_exchange_type_t +#define md mbedtls_md +#define md2 mbedtls_md2 +#define md2_context mbedtls_md2_context +#define md2_finish mbedtls_md2_finish +#define md2_free mbedtls_md2_free +#define md2_info mbedtls_md2_info +#define md2_init mbedtls_md2_init +#define md2_process mbedtls_md2_process +#define md2_self_test mbedtls_md2_self_test +#define md2_starts mbedtls_md2_starts +#define md2_update mbedtls_md2_update +#define md4 mbedtls_md4 +#define md4_context mbedtls_md4_context +#define md4_finish mbedtls_md4_finish +#define md4_free mbedtls_md4_free +#define md4_info mbedtls_md4_info +#define md4_init mbedtls_md4_init +#define md4_process mbedtls_md4_process +#define md4_self_test mbedtls_md4_self_test +#define md4_starts mbedtls_md4_starts +#define md4_update mbedtls_md4_update +#define md5 mbedtls_md5 +#define md5_context mbedtls_md5_context +#define md5_finish mbedtls_md5_finish +#define md5_free mbedtls_md5_free +#define md5_info mbedtls_md5_info +#define md5_init mbedtls_md5_init +#define md5_process mbedtls_md5_process +#define md5_self_test mbedtls_md5_self_test +#define md5_starts mbedtls_md5_starts +#define md5_update mbedtls_md5_update +#define md_context_t mbedtls_md_context_t +#define md_file mbedtls_md_file +#define md_finish mbedtls_md_finish +#define md_free mbedtls_md_free +#define md_get_name mbedtls_md_get_name +#define md_get_size mbedtls_md_get_size +#define md_get_type mbedtls_md_get_type +#define md_hmac mbedtls_md_hmac +#define md_hmac_finish mbedtls_md_hmac_finish +#define md_hmac_reset mbedtls_md_hmac_reset +#define md_hmac_starts mbedtls_md_hmac_starts +#define md_hmac_update mbedtls_md_hmac_update +#define md_info_from_string mbedtls_md_info_from_string +#define md_info_from_type mbedtls_md_info_from_type +#define md_info_t mbedtls_md_info_t +#define md_init mbedtls_md_init +#define md_init_ctx mbedtls_md_init_ctx +#define md_list mbedtls_md_list +#define md_process mbedtls_md_process +#define md_starts mbedtls_md_starts +#define md_type_t mbedtls_md_type_t +#define md_update mbedtls_md_update +#define memory_buffer_alloc_cur_get mbedtls_memory_buffer_alloc_cur_get +#define memory_buffer_alloc_free mbedtls_memory_buffer_alloc_free +#define memory_buffer_alloc_init mbedtls_memory_buffer_alloc_init +#define memory_buffer_alloc_max_get mbedtls_memory_buffer_alloc_max_get +#define memory_buffer_alloc_max_reset mbedtls_memory_buffer_alloc_max_reset +#define memory_buffer_alloc_self_test mbedtls_memory_buffer_alloc_self_test +#define memory_buffer_alloc_status mbedtls_memory_buffer_alloc_status +#define memory_buffer_alloc_verify mbedtls_memory_buffer_alloc_verify +#define memory_buffer_set_verify mbedtls_memory_buffer_set_verify +#define mpi mbedtls_mpi +#define mpi_add_abs mbedtls_mpi_add_abs +#define mpi_add_int mbedtls_mpi_add_int +#define mpi_add_mpi mbedtls_mpi_add_mpi +#define mpi_cmp_abs mbedtls_mpi_cmp_abs +#define mpi_cmp_int mbedtls_mpi_cmp_int +#define mpi_cmp_mpi mbedtls_mpi_cmp_mpi +#define mpi_copy mbedtls_mpi_copy +#define mpi_div_int mbedtls_mpi_div_int +#define mpi_div_mpi mbedtls_mpi_div_mpi +#define mpi_exp_mod mbedtls_mpi_exp_mod +#define mpi_fill_random mbedtls_mpi_fill_random +#define mpi_free mbedtls_mpi_free +#define mpi_gcd mbedtls_mpi_gcd +#define mpi_gen_prime mbedtls_mpi_gen_prime +#define mpi_get_bit mbedtls_mpi_get_bit +#define mpi_grow mbedtls_mpi_grow +#define mpi_init mbedtls_mpi_init +#define mpi_inv_mod mbedtls_mpi_inv_mod +#define mpi_is_prime mbedtls_mpi_is_prime +#define mpi_lsb mbedtls_mpi_lsb +#define mpi_lset mbedtls_mpi_lset +#define mpi_mod_int mbedtls_mpi_mod_int +#define mpi_mod_mpi mbedtls_mpi_mod_mpi +#define mpi_msb mbedtls_mpi_bitlen +#define mpi_mul_int mbedtls_mpi_mul_int +#define mpi_mul_mpi mbedtls_mpi_mul_mpi +#define mpi_read_binary mbedtls_mpi_read_binary +#define mpi_read_file mbedtls_mpi_read_file +#define mpi_read_string mbedtls_mpi_read_string +#define mpi_safe_cond_assign mbedtls_mpi_safe_cond_assign +#define mpi_safe_cond_swap mbedtls_mpi_safe_cond_swap +#define mpi_self_test mbedtls_mpi_self_test +#define mpi_set_bit mbedtls_mpi_set_bit +#define mpi_shift_l mbedtls_mpi_shift_l +#define mpi_shift_r mbedtls_mpi_shift_r +#define mpi_shrink mbedtls_mpi_shrink +#define mpi_size mbedtls_mpi_size +#define mpi_sub_abs mbedtls_mpi_sub_abs +#define mpi_sub_int mbedtls_mpi_sub_int +#define mpi_sub_mpi mbedtls_mpi_sub_mpi +#define mpi_swap mbedtls_mpi_swap +#define mpi_write_binary mbedtls_mpi_write_binary +#define mpi_write_file mbedtls_mpi_write_file +#define mpi_write_string mbedtls_mpi_write_string +#define net_accept mbedtls_net_accept +#define net_bind mbedtls_net_bind +#define net_close mbedtls_net_free +#define net_connect mbedtls_net_connect +#define net_recv mbedtls_net_recv +#define net_recv_timeout mbedtls_net_recv_timeout +#define net_send mbedtls_net_send +#define net_set_block mbedtls_net_set_block +#define net_set_nonblock mbedtls_net_set_nonblock +#define net_usleep mbedtls_net_usleep +#define oid_descriptor_t mbedtls_oid_descriptor_t +#define oid_get_attr_short_name mbedtls_oid_get_attr_short_name +#define oid_get_cipher_alg mbedtls_oid_get_cipher_alg +#define oid_get_ec_grp mbedtls_oid_get_ec_grp +#define oid_get_extended_key_usage mbedtls_oid_get_extended_key_usage +#define oid_get_md_alg mbedtls_oid_get_md_alg +#define oid_get_numeric_string mbedtls_oid_get_numeric_string +#define oid_get_oid_by_ec_grp mbedtls_oid_get_oid_by_ec_grp +#define oid_get_oid_by_md mbedtls_oid_get_oid_by_md +#define oid_get_oid_by_pk_alg mbedtls_oid_get_oid_by_pk_alg +#define oid_get_oid_by_sig_alg mbedtls_oid_get_oid_by_sig_alg +#define oid_get_pk_alg mbedtls_oid_get_pk_alg +#define oid_get_pkcs12_pbe_alg mbedtls_oid_get_pkcs12_pbe_alg +#define oid_get_sig_alg mbedtls_oid_get_sig_alg +#define oid_get_sig_alg_desc mbedtls_oid_get_sig_alg_desc +#define oid_get_x509_ext_type mbedtls_oid_get_x509_ext_type +#define operation_t mbedtls_operation_t +#define padlock_supports mbedtls_padlock_has_support +#define padlock_xcryptcbc mbedtls_padlock_xcryptcbc +#define padlock_xcryptecb mbedtls_padlock_xcryptecb +#define pem_context mbedtls_pem_context +#define pem_free mbedtls_pem_free +#define pem_init mbedtls_pem_init +#define pem_read_buffer mbedtls_pem_read_buffer +#define pem_write_buffer mbedtls_pem_write_buffer +#define pk_can_do mbedtls_pk_can_do +#define pk_check_pair mbedtls_pk_check_pair +#define pk_context mbedtls_pk_context +#define pk_debug mbedtls_pk_debug +#define pk_debug_item mbedtls_pk_debug_item +#define pk_debug_type mbedtls_pk_debug_type +#define pk_decrypt mbedtls_pk_decrypt +#define pk_ec mbedtls_pk_ec +#define pk_encrypt mbedtls_pk_encrypt +#define pk_free mbedtls_pk_free +#define pk_get_len mbedtls_pk_get_len +#define pk_get_name mbedtls_pk_get_name +#define pk_get_size mbedtls_pk_get_bitlen +#define pk_get_type mbedtls_pk_get_type +#define pk_info_from_type mbedtls_pk_info_from_type +#define pk_info_t mbedtls_pk_info_t +#define pk_init mbedtls_pk_init +#define pk_init_ctx mbedtls_pk_setup +#define pk_init_ctx_rsa_alt mbedtls_pk_setup_rsa_alt +#define pk_load_file mbedtls_pk_load_file +#define pk_parse_key mbedtls_pk_parse_key +#define pk_parse_keyfile mbedtls_pk_parse_keyfile +#define pk_parse_public_key mbedtls_pk_parse_public_key +#define pk_parse_public_keyfile mbedtls_pk_parse_public_keyfile +#define pk_parse_subpubkey mbedtls_pk_parse_subpubkey +#define pk_rsa mbedtls_pk_rsa +#define pk_rsa_alt_decrypt_func mbedtls_pk_rsa_alt_decrypt_func +#define pk_rsa_alt_key_len_func mbedtls_pk_rsa_alt_key_len_func +#define pk_rsa_alt_sign_func mbedtls_pk_rsa_alt_sign_func +#define pk_rsassa_pss_options mbedtls_pk_rsassa_pss_options +#define pk_sign mbedtls_pk_sign +#define pk_type_t mbedtls_pk_type_t +#define pk_verify mbedtls_pk_verify +#define pk_verify_ext mbedtls_pk_verify_ext +#define pk_write_key_der mbedtls_pk_write_key_der +#define pk_write_key_pem mbedtls_pk_write_key_pem +#define pk_write_pubkey mbedtls_pk_write_pubkey +#define pk_write_pubkey_der mbedtls_pk_write_pubkey_der +#define pk_write_pubkey_pem mbedtls_pk_write_pubkey_pem +#define pkcs11_context mbedtls_pkcs11_context +#define pkcs11_decrypt mbedtls_pkcs11_decrypt +#define pkcs11_priv_key_free mbedtls_pkcs11_priv_key_free +#define pkcs11_priv_key_init mbedtls_pkcs11_priv_key_bind +#define pkcs11_sign mbedtls_pkcs11_sign +#define pkcs11_x509_cert_init mbedtls_pkcs11_x509_cert_bind +#define pkcs12_derivation mbedtls_pkcs12_derivation +#define pkcs12_pbe mbedtls_pkcs12_pbe +#define pkcs12_pbe_sha1_rc4_128 mbedtls_pkcs12_pbe_sha1_rc4_128 +#define pkcs5_pbes2 mbedtls_pkcs5_pbes2 +#define pkcs5_pbkdf2_hmac mbedtls_pkcs5_pbkdf2_hmac +#define pkcs5_self_test mbedtls_pkcs5_self_test +#define platform_entropy_poll mbedtls_platform_entropy_poll +#define platform_set_exit mbedtls_platform_set_exit +#define platform_set_fprintf mbedtls_platform_set_fprintf +#define platform_set_printf mbedtls_platform_set_printf +#define platform_set_snprintf mbedtls_platform_set_snprintf +#define polarssl_exit mbedtls_exit +#define polarssl_fprintf mbedtls_fprintf +#define polarssl_free mbedtls_free +#define polarssl_mutex_free mbedtls_mutex_free +#define polarssl_mutex_init mbedtls_mutex_init +#define polarssl_mutex_lock mbedtls_mutex_lock +#define polarssl_mutex_unlock mbedtls_mutex_unlock +#define polarssl_printf mbedtls_printf +#define polarssl_snprintf mbedtls_snprintf +#define polarssl_strerror mbedtls_strerror +#define ripemd160 mbedtls_ripemd160 +#define ripemd160_context mbedtls_ripemd160_context +#define ripemd160_finish mbedtls_ripemd160_finish +#define ripemd160_free mbedtls_ripemd160_free +#define ripemd160_info mbedtls_ripemd160_info +#define ripemd160_init mbedtls_ripemd160_init +#define ripemd160_process mbedtls_ripemd160_process +#define ripemd160_self_test mbedtls_ripemd160_self_test +#define ripemd160_starts mbedtls_ripemd160_starts +#define ripemd160_update mbedtls_ripemd160_update +#define rsa_alt_context mbedtls_rsa_alt_context +#define rsa_alt_info mbedtls_rsa_alt_info +#define rsa_check_privkey mbedtls_rsa_check_privkey +#define rsa_check_pub_priv mbedtls_rsa_check_pub_priv +#define rsa_check_pubkey mbedtls_rsa_check_pubkey +#define rsa_context mbedtls_rsa_context +#define rsa_copy mbedtls_rsa_copy +#define rsa_free mbedtls_rsa_free +#define rsa_gen_key mbedtls_rsa_gen_key +#define rsa_info mbedtls_rsa_info +#define rsa_init mbedtls_rsa_init +#define rsa_pkcs1_decrypt mbedtls_rsa_pkcs1_decrypt +#define rsa_pkcs1_encrypt mbedtls_rsa_pkcs1_encrypt +#define rsa_pkcs1_sign mbedtls_rsa_pkcs1_sign +#define rsa_pkcs1_verify mbedtls_rsa_pkcs1_verify +#define rsa_private mbedtls_rsa_private +#define rsa_public mbedtls_rsa_public +#define rsa_rsaes_oaep_decrypt mbedtls_rsa_rsaes_oaep_decrypt +#define rsa_rsaes_oaep_encrypt mbedtls_rsa_rsaes_oaep_encrypt +#define rsa_rsaes_pkcs1_v15_decrypt mbedtls_rsa_rsaes_pkcs1_v15_decrypt +#define rsa_rsaes_pkcs1_v15_encrypt mbedtls_rsa_rsaes_pkcs1_v15_encrypt +#define rsa_rsassa_pkcs1_v15_sign mbedtls_rsa_rsassa_pkcs1_v15_sign +#define rsa_rsassa_pkcs1_v15_verify mbedtls_rsa_rsassa_pkcs1_v15_verify +#define rsa_rsassa_pss_sign mbedtls_rsa_rsassa_pss_sign +#define rsa_rsassa_pss_verify mbedtls_rsa_rsassa_pss_verify +#define rsa_rsassa_pss_verify_ext mbedtls_rsa_rsassa_pss_verify_ext +#define rsa_self_test mbedtls_rsa_self_test +#define rsa_set_padding mbedtls_rsa_set_padding +#define safer_memcmp mbedtls_ssl_safer_memcmp +#define set_alarm mbedtls_set_alarm +#define sha1 mbedtls_sha1 +#define sha1_context mbedtls_sha1_context +#define sha1_finish mbedtls_sha1_finish +#define sha1_free mbedtls_sha1_free +#define sha1_info mbedtls_sha1_info +#define sha1_init mbedtls_sha1_init +#define sha1_process mbedtls_sha1_process +#define sha1_self_test mbedtls_sha1_self_test +#define sha1_starts mbedtls_sha1_starts +#define sha1_update mbedtls_sha1_update +#define sha224_info mbedtls_sha224_info +#define sha256 mbedtls_sha256 +#define sha256_context mbedtls_sha256_context +#define sha256_finish mbedtls_sha256_finish +#define sha256_free mbedtls_sha256_free +#define sha256_info mbedtls_sha256_info +#define sha256_init mbedtls_sha256_init +#define sha256_process mbedtls_sha256_process +#define sha256_self_test mbedtls_sha256_self_test +#define sha256_starts mbedtls_sha256_starts +#define sha256_update mbedtls_sha256_update +#define sha384_info mbedtls_sha384_info +#define sha512 mbedtls_sha512 +#define sha512_context mbedtls_sha512_context +#define sha512_finish mbedtls_sha512_finish +#define sha512_free mbedtls_sha512_free +#define sha512_info mbedtls_sha512_info +#define sha512_init mbedtls_sha512_init +#define sha512_process mbedtls_sha512_process +#define sha512_self_test mbedtls_sha512_self_test +#define sha512_starts mbedtls_sha512_starts +#define sha512_update mbedtls_sha512_update +#define source_state mbedtls_entropy_source_state +#define ssl_cache_context mbedtls_ssl_cache_context +#define ssl_cache_entry mbedtls_ssl_cache_entry +#define ssl_cache_free mbedtls_ssl_cache_free +#define ssl_cache_get mbedtls_ssl_cache_get +#define ssl_cache_init mbedtls_ssl_cache_init +#define ssl_cache_set mbedtls_ssl_cache_set +#define ssl_cache_set_max_entries mbedtls_ssl_cache_set_max_entries +#define ssl_cache_set_timeout mbedtls_ssl_cache_set_timeout +#define ssl_check_cert_usage mbedtls_ssl_check_cert_usage +#define ssl_ciphersuite_from_id mbedtls_ssl_ciphersuite_from_id +#define ssl_ciphersuite_from_string mbedtls_ssl_ciphersuite_from_string +#define ssl_ciphersuite_t mbedtls_ssl_ciphersuite_t +#define ssl_ciphersuite_uses_ec mbedtls_ssl_ciphersuite_uses_ec +#define ssl_ciphersuite_uses_psk mbedtls_ssl_ciphersuite_uses_psk +#define ssl_close_notify mbedtls_ssl_close_notify +#define ssl_context mbedtls_ssl_context +#define ssl_cookie_check mbedtls_ssl_cookie_check +#define ssl_cookie_check_t mbedtls_ssl_cookie_check_t +#define ssl_cookie_ctx mbedtls_ssl_cookie_ctx +#define ssl_cookie_free mbedtls_ssl_cookie_free +#define ssl_cookie_init mbedtls_ssl_cookie_init +#define ssl_cookie_set_timeout mbedtls_ssl_cookie_set_timeout +#define ssl_cookie_setup mbedtls_ssl_cookie_setup +#define ssl_cookie_write mbedtls_ssl_cookie_write +#define ssl_cookie_write_t mbedtls_ssl_cookie_write_t +#define ssl_derive_keys mbedtls_ssl_derive_keys +#define ssl_dtls_replay_check mbedtls_ssl_dtls_replay_check +#define ssl_dtls_replay_update mbedtls_ssl_dtls_replay_update +#define ssl_fetch_input mbedtls_ssl_fetch_input +#define ssl_flight_item mbedtls_ssl_flight_item +#define ssl_flush_output mbedtls_ssl_flush_output +#define ssl_free mbedtls_ssl_free +#define ssl_get_alpn_protocol mbedtls_ssl_get_alpn_protocol +#define ssl_get_bytes_avail mbedtls_ssl_get_bytes_avail +#define ssl_get_ciphersuite mbedtls_ssl_get_ciphersuite +#define ssl_get_ciphersuite_id mbedtls_ssl_get_ciphersuite_id +#define ssl_get_ciphersuite_name mbedtls_ssl_get_ciphersuite_name +#define ssl_get_ciphersuite_sig_pk_alg mbedtls_ssl_get_ciphersuite_sig_pk_alg +#define ssl_get_peer_cert mbedtls_ssl_get_peer_cert +#define ssl_get_record_expansion mbedtls_ssl_get_record_expansion +#define ssl_get_session mbedtls_ssl_get_session +#define ssl_get_verify_result mbedtls_ssl_get_verify_result +#define ssl_get_version mbedtls_ssl_get_version +#define ssl_handshake mbedtls_ssl_handshake +#define ssl_handshake_client_step mbedtls_ssl_handshake_client_step +#define ssl_handshake_free mbedtls_ssl_handshake_free +#define ssl_handshake_params mbedtls_ssl_handshake_params +#define ssl_handshake_server_step mbedtls_ssl_handshake_server_step +#define ssl_handshake_step mbedtls_ssl_handshake_step +#define ssl_handshake_wrapup mbedtls_ssl_handshake_wrapup +#define ssl_hdr_len mbedtls_ssl_hdr_len +#define ssl_hs_hdr_len mbedtls_ssl_hs_hdr_len +#define ssl_hw_record_activate mbedtls_ssl_hw_record_activate +#define ssl_hw_record_finish mbedtls_ssl_hw_record_finish +#define ssl_hw_record_init mbedtls_ssl_hw_record_init +#define ssl_hw_record_read mbedtls_ssl_hw_record_read +#define ssl_hw_record_reset mbedtls_ssl_hw_record_reset +#define ssl_hw_record_write mbedtls_ssl_hw_record_write +#define ssl_init mbedtls_ssl_init +#define ssl_key_cert mbedtls_ssl_key_cert +#define ssl_legacy_renegotiation mbedtls_ssl_conf_legacy_renegotiation +#define ssl_list_ciphersuites mbedtls_ssl_list_ciphersuites +#define ssl_md_alg_from_hash mbedtls_ssl_md_alg_from_hash +#define ssl_optimize_checksum mbedtls_ssl_optimize_checksum +#define ssl_own_cert mbedtls_ssl_own_cert +#define ssl_own_key mbedtls_ssl_own_key +#define ssl_parse_certificate mbedtls_ssl_parse_certificate +#define ssl_parse_change_cipher_spec mbedtls_ssl_parse_change_cipher_spec +#define ssl_parse_finished mbedtls_ssl_parse_finished +#define ssl_pk_alg_from_sig mbedtls_ssl_pk_alg_from_sig +#define ssl_pkcs11_decrypt mbedtls_ssl_pkcs11_decrypt +#define ssl_pkcs11_key_len mbedtls_ssl_pkcs11_key_len +#define ssl_pkcs11_sign mbedtls_ssl_pkcs11_sign +#define ssl_psk_derive_premaster mbedtls_ssl_psk_derive_premaster +#define ssl_read mbedtls_ssl_read +#define ssl_read_record mbedtls_ssl_read_record +#define ssl_read_version mbedtls_ssl_read_version +#define ssl_recv_flight_completed mbedtls_ssl_recv_flight_completed +#define ssl_renegotiate mbedtls_ssl_renegotiate +#define ssl_resend mbedtls_ssl_resend +#define ssl_reset_checksum mbedtls_ssl_reset_checksum +#define ssl_send_alert_message mbedtls_ssl_send_alert_message +#define ssl_send_fatal_handshake_failure mbedtls_ssl_send_fatal_handshake_failure +#define ssl_send_flight_completed mbedtls_ssl_send_flight_completed +#define ssl_session mbedtls_ssl_session +#define ssl_session_free mbedtls_ssl_session_free +#define ssl_session_init mbedtls_ssl_session_init +#define ssl_session_reset mbedtls_ssl_session_reset +#define ssl_set_alpn_protocols mbedtls_ssl_conf_alpn_protocols +#define ssl_set_arc4_support mbedtls_ssl_conf_arc4_support +#define ssl_set_authmode mbedtls_ssl_conf_authmode +#define ssl_set_bio mbedtls_ssl_set_bio +#define ssl_set_ca_chain mbedtls_ssl_conf_ca_chain +#define ssl_set_cbc_record_splitting mbedtls_ssl_conf_cbc_record_splitting +#define ssl_set_ciphersuites mbedtls_ssl_conf_ciphersuites +#define ssl_set_ciphersuites_for_version mbedtls_ssl_conf_ciphersuites_for_version +#define ssl_set_client_transport_id mbedtls_ssl_set_client_transport_id +#define ssl_set_curves mbedtls_ssl_conf_curves +#define ssl_set_dbg mbedtls_ssl_conf_dbg +#define ssl_set_dh_param mbedtls_ssl_conf_dh_param +#define ssl_set_dh_param_ctx mbedtls_ssl_conf_dh_param_ctx +#define ssl_set_dtls_anti_replay mbedtls_ssl_conf_dtls_anti_replay +#define ssl_set_dtls_badmac_limit mbedtls_ssl_conf_dtls_badmac_limit +#define ssl_set_dtls_cookies mbedtls_ssl_conf_dtls_cookies +#define ssl_set_encrypt_then_mac mbedtls_ssl_conf_encrypt_then_mac +#define ssl_set_endpoint mbedtls_ssl_conf_endpoint +#define ssl_set_extended_master_secret mbedtls_ssl_conf_extended_master_secret +#define ssl_set_fallback mbedtls_ssl_conf_fallback +#define ssl_set_handshake_timeout mbedtls_ssl_conf_handshake_timeout +#define ssl_set_hostname mbedtls_ssl_set_hostname +#define ssl_set_max_frag_len mbedtls_ssl_conf_max_frag_len +#define ssl_set_max_version mbedtls_ssl_conf_max_version +#define ssl_set_min_version mbedtls_ssl_conf_min_version +#define ssl_set_own_cert mbedtls_ssl_conf_own_cert +#define ssl_set_psk mbedtls_ssl_conf_psk +#define ssl_set_psk_cb mbedtls_ssl_conf_psk_cb +#define ssl_set_renegotiation mbedtls_ssl_conf_renegotiation +#define ssl_set_renegotiation_enforced mbedtls_ssl_conf_renegotiation_enforced +#define ssl_set_renegotiation_period mbedtls_ssl_conf_renegotiation_period +#define ssl_set_rng mbedtls_ssl_conf_rng +#define ssl_set_session mbedtls_ssl_set_session +#define ssl_set_session_cache mbedtls_ssl_conf_session_cache +#define ssl_set_session_tickets mbedtls_ssl_conf_session_tickets +#define ssl_set_sni mbedtls_ssl_conf_sni +#define ssl_set_transport mbedtls_ssl_conf_transport +#define ssl_set_truncated_hmac mbedtls_ssl_conf_truncated_hmac +#define ssl_set_verify mbedtls_ssl_conf_verify +#define ssl_sig_from_pk mbedtls_ssl_sig_from_pk +#define ssl_states mbedtls_ssl_states +#define ssl_transform mbedtls_ssl_transform +#define ssl_transform_free mbedtls_ssl_transform_free +#define ssl_write mbedtls_ssl_write +#define ssl_write_certificate mbedtls_ssl_write_certificate +#define ssl_write_change_cipher_spec mbedtls_ssl_write_change_cipher_spec +#define ssl_write_finished mbedtls_ssl_write_finished +#define ssl_write_record mbedtls_ssl_write_record +#define ssl_write_version mbedtls_ssl_write_version +#define supported_ciphers mbedtls_cipher_supported +#define t_sint mbedtls_mpi_sint +#define t_udbl mbedtls_t_udbl +#define t_uint mbedtls_mpi_uint +#define test_ca_crt mbedtls_test_ca_crt +#define test_ca_crt_ec mbedtls_test_ca_crt_ec +#define test_ca_crt_rsa mbedtls_test_ca_crt_rsa +#define test_ca_key mbedtls_test_ca_key +#define test_ca_key_ec mbedtls_test_ca_key_ec +#define test_ca_key_rsa mbedtls_test_ca_key_rsa +#define test_ca_list mbedtls_test_cas_pem +#define test_ca_pwd mbedtls_test_ca_pwd +#define test_ca_pwd_ec mbedtls_test_ca_pwd_ec +#define test_ca_pwd_rsa mbedtls_test_ca_pwd_rsa +#define test_cli_crt mbedtls_test_cli_crt +#define test_cli_crt_ec mbedtls_test_cli_crt_ec +#define test_cli_crt_rsa mbedtls_test_cli_crt_rsa +#define test_cli_key mbedtls_test_cli_key +#define test_cli_key_ec mbedtls_test_cli_key_ec +#define test_cli_key_rsa mbedtls_test_cli_key_rsa +#define test_srv_crt mbedtls_test_srv_crt +#define test_srv_crt_ec mbedtls_test_srv_crt_ec +#define test_srv_crt_rsa mbedtls_test_srv_crt_rsa +#define test_srv_key mbedtls_test_srv_key +#define test_srv_key_ec mbedtls_test_srv_key_ec +#define test_srv_key_rsa mbedtls_test_srv_key_rsa +#define threading_mutex_t mbedtls_threading_mutex_t +#define threading_set_alt mbedtls_threading_set_alt +#define timing_self_test mbedtls_timing_self_test +#define version_check_feature mbedtls_version_check_feature +#define version_get_number mbedtls_version_get_number +#define version_get_string mbedtls_version_get_string +#define version_get_string_full mbedtls_version_get_string_full +#define x509_bitstring mbedtls_x509_bitstring +#define x509_buf mbedtls_x509_buf +#define x509_crl mbedtls_x509_crl +#define x509_crl_entry mbedtls_x509_crl_entry +#define x509_crl_free mbedtls_x509_crl_free +#define x509_crl_info mbedtls_x509_crl_info +#define x509_crl_init mbedtls_x509_crl_init +#define x509_crl_parse mbedtls_x509_crl_parse +#define x509_crl_parse_der mbedtls_x509_crl_parse_der +#define x509_crl_parse_file mbedtls_x509_crl_parse_file +#define x509_crt mbedtls_x509_crt +#define x509_crt_check_extended_key_usage mbedtls_x509_crt_check_extended_key_usage +#define x509_crt_check_key_usage mbedtls_x509_crt_check_key_usage +#define x509_crt_free mbedtls_x509_crt_free +#define x509_crt_info mbedtls_x509_crt_info +#define x509_crt_init mbedtls_x509_crt_init +#define x509_crt_parse mbedtls_x509_crt_parse +#define x509_crt_parse_der mbedtls_x509_crt_parse_der +#define x509_crt_parse_file mbedtls_x509_crt_parse_file +#define x509_crt_parse_path mbedtls_x509_crt_parse_path +#define x509_crt_revoked mbedtls_x509_crt_is_revoked +#define x509_crt_verify mbedtls_x509_crt_verify +#define x509_csr mbedtls_x509_csr +#define x509_csr_free mbedtls_x509_csr_free +#define x509_csr_info mbedtls_x509_csr_info +#define x509_csr_init mbedtls_x509_csr_init +#define x509_csr_parse mbedtls_x509_csr_parse +#define x509_csr_parse_der mbedtls_x509_csr_parse_der +#define x509_csr_parse_file mbedtls_x509_csr_parse_file +#define x509_dn_gets mbedtls_x509_dn_gets +#define x509_get_alg mbedtls_x509_get_alg +#define x509_get_alg_null mbedtls_x509_get_alg_null +#define x509_get_ext mbedtls_x509_get_ext +#define x509_get_name mbedtls_x509_get_name +#define x509_get_rsassa_pss_params mbedtls_x509_get_rsassa_pss_params +#define x509_get_serial mbedtls_x509_get_serial +#define x509_get_sig mbedtls_x509_get_sig +#define x509_get_sig_alg mbedtls_x509_get_sig_alg +#define x509_get_time mbedtls_x509_get_time +#define x509_key_size_helper mbedtls_x509_key_size_helper +#define x509_name mbedtls_x509_name +#define x509_self_test mbedtls_x509_self_test +#define x509_sequence mbedtls_x509_sequence +#define x509_serial_gets mbedtls_x509_serial_gets +#define x509_set_extension mbedtls_x509_set_extension +#define x509_sig_alg_gets mbedtls_x509_sig_alg_gets +#define x509_string_to_names mbedtls_x509_string_to_names +#define x509_time mbedtls_x509_time +#define x509_time_expired mbedtls_x509_time_is_past +#define x509_time_future mbedtls_x509_time_is_future +#define x509_write_extensions mbedtls_x509_write_extensions +#define x509_write_names mbedtls_x509_write_names +#define x509_write_sig mbedtls_x509_write_sig +#define x509write_cert mbedtls_x509write_cert +#define x509write_crt_der mbedtls_x509write_crt_der +#define x509write_crt_free mbedtls_x509write_crt_free +#define x509write_crt_init mbedtls_x509write_crt_init +#define x509write_crt_pem mbedtls_x509write_crt_pem +#define x509write_crt_set_authority_key_identifier mbedtls_x509write_crt_set_authority_key_identifier +#define x509write_crt_set_basic_constraints mbedtls_x509write_crt_set_basic_constraints +#define x509write_crt_set_extension mbedtls_x509write_crt_set_extension +#define x509write_crt_set_issuer_key mbedtls_x509write_crt_set_issuer_key +#define x509write_crt_set_issuer_name mbedtls_x509write_crt_set_issuer_name +#define x509write_crt_set_key_usage mbedtls_x509write_crt_set_key_usage +#define x509write_crt_set_md_alg mbedtls_x509write_crt_set_md_alg +#define x509write_crt_set_ns_cert_type mbedtls_x509write_crt_set_ns_cert_type +#define x509write_crt_set_serial mbedtls_x509write_crt_set_serial +#define x509write_crt_set_subject_key mbedtls_x509write_crt_set_subject_key +#define x509write_crt_set_subject_key_identifier mbedtls_x509write_crt_set_subject_key_identifier +#define x509write_crt_set_subject_name mbedtls_x509write_crt_set_subject_name +#define x509write_crt_set_validity mbedtls_x509write_crt_set_validity +#define x509write_crt_set_version mbedtls_x509write_crt_set_version +#define x509write_csr mbedtls_x509write_csr +#define x509write_csr_der mbedtls_x509write_csr_der +#define x509write_csr_free mbedtls_x509write_csr_free +#define x509write_csr_init mbedtls_x509write_csr_init +#define x509write_csr_pem mbedtls_x509write_csr_pem +#define x509write_csr_set_extension mbedtls_x509write_csr_set_extension +#define x509write_csr_set_key mbedtls_x509write_csr_set_key +#define x509write_csr_set_key_usage mbedtls_x509write_csr_set_key_usage +#define x509write_csr_set_md_alg mbedtls_x509write_csr_set_md_alg +#define x509write_csr_set_ns_cert_type mbedtls_x509write_csr_set_ns_cert_type +#define x509write_csr_set_subject_name mbedtls_x509write_csr_set_subject_name +#define xtea_context mbedtls_xtea_context +#define xtea_crypt_cbc mbedtls_xtea_crypt_cbc +#define xtea_crypt_ecb mbedtls_xtea_crypt_ecb +#define xtea_free mbedtls_xtea_free +#define xtea_init mbedtls_xtea_init +#define xtea_self_test mbedtls_xtea_self_test +#define xtea_setup mbedtls_xtea_setup + +#endif /* compat-1.3.h */ +#endif /* MBEDTLS_DEPRECATED_REMOVED */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/config.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/config.h new file mode 100644 index 0000000..24e4856 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/config.h @@ -0,0 +1,3770 @@ +/** + * \file config.h + * + * \brief Configuration options (set of defines) + * + * This set of compile-time options may be used to enable + * or disable features selectively, and reduce the global + * memory footprint. + */ +/* + * Copyright (C) 2006-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 file is part of mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_CONFIG_H +#define MBEDTLS_CONFIG_H + +#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) +#define _CRT_SECURE_NO_DEPRECATE 1 +#endif + +/** + * \name SECTION: System support + * + * This section sets system specific settings. + * \{ + */ + +/** + * \def MBEDTLS_HAVE_ASM + * + * The compiler has support for asm(). + * + * Requires support for asm() in compiler. + * + * Used in: + * library/aria.c + * library/timing.c + * include/mbedtls/bn_mul.h + * + * Required by: + * MBEDTLS_AESNI_C + * MBEDTLS_PADLOCK_C + * + * Comment to disable the use of assembly code. + */ +//#define MBEDTLS_HAVE_ASM + +/** + * \def MBEDTLS_NO_UDBL_DIVISION + * + * The platform lacks support for double-width integer division (64-bit + * division on a 32-bit platform, 128-bit division on a 64-bit platform). + * + * Used in: + * include/mbedtls/bignum.h + * library/bignum.c + * + * The bignum code uses double-width division to speed up some operations. + * Double-width division is often implemented in software that needs to + * be linked with the program. The presence of a double-width integer + * type is usually detected automatically through preprocessor macros, + * but the automatic detection cannot know whether the code needs to + * and can be linked with an implementation of division for that type. + * By default division is assumed to be usable if the type is present. + * Uncomment this option to prevent the use of double-width division. + * + * Note that division for the native integer type is always required. + * Furthermore, a 64-bit type is always required even on a 32-bit + * platform, but it need not support multiplication or division. In some + * cases it is also desirable to disable some double-width operations. For + * example, if double-width division is implemented in software, disabling + * it can reduce code size in some embedded targets. + */ +//#define MBEDTLS_NO_UDBL_DIVISION + +/** + * \def MBEDTLS_NO_64BIT_MULTIPLICATION + * + * The platform lacks support for 32x32 -> 64-bit multiplication. + * + * Used in: + * library/poly1305.c + * + * Some parts of the library may use multiplication of two unsigned 32-bit + * operands with a 64-bit result in order to speed up computations. On some + * platforms, this is not available in hardware and has to be implemented in + * software, usually in a library provided by the toolchain. + * + * Sometimes it is not desirable to have to link to that library. This option + * removes the dependency of that library on platforms that lack a hardware + * 64-bit multiplier by embedding a software implementation in Mbed TLS. + * + * Note that depending on the compiler, this may decrease performance compared + * to using the library function provided by the toolchain. + */ +//#define MBEDTLS_NO_64BIT_MULTIPLICATION + +/** + * \def MBEDTLS_HAVE_SSE2 + * + * CPU supports SSE2 instruction set. + * + * Uncomment if the CPU supports SSE2 (IA-32 specific). + */ +//#define MBEDTLS_HAVE_SSE2 + +/** + * \def MBEDTLS_HAVE_TIME + * + * System has time.h and time(). + * The time does not need to be correct, only time differences are used, + * by contrast with MBEDTLS_HAVE_TIME_DATE + * + * Defining MBEDTLS_HAVE_TIME allows you to specify MBEDTLS_PLATFORM_TIME_ALT, + * MBEDTLS_PLATFORM_TIME_MACRO, MBEDTLS_PLATFORM_TIME_TYPE_MACRO and + * MBEDTLS_PLATFORM_STD_TIME. + * + * Comment if your system does not support time functions + */ +#define MBEDTLS_HAVE_TIME + +/** + * \def MBEDTLS_HAVE_TIME_DATE + * + * System has time.h, time(), and an implementation for + * mbedtls_platform_gmtime_r() (see below). + * The time needs to be correct (not necessarily very accurate, but at least + * the date should be correct). This is used to verify the validity period of + * X.509 certificates. + * + * Comment if your system does not have a correct clock. + * + * \note mbedtls_platform_gmtime_r() is an abstraction in platform_util.h that + * behaves similarly to the gmtime_r() function from the C standard. Refer to + * the documentation for mbedtls_platform_gmtime_r() for more information. + * + * \note It is possible to configure an implementation for + * mbedtls_platform_gmtime_r() at compile-time by using the macro + * MBEDTLS_PLATFORM_GMTIME_R_ALT. + */ +#define MBEDTLS_HAVE_TIME_DATE + +/** + * \def MBEDTLS_PLATFORM_MEMORY + * + * Enable the memory allocation layer. + * + * By default mbed TLS uses the system-provided calloc() and free(). + * This allows different allocators (self-implemented or provided) to be + * provided to the platform abstraction layer. + * + * Enabling MBEDTLS_PLATFORM_MEMORY without the + * MBEDTLS_PLATFORM_{FREE,CALLOC}_MACROs will provide + * "mbedtls_platform_set_calloc_free()" allowing you to set an alternative calloc() and + * free() function pointer at runtime. + * + * Enabling MBEDTLS_PLATFORM_MEMORY and specifying + * MBEDTLS_PLATFORM_{CALLOC,FREE}_MACROs will allow you to specify the + * alternate function at compile time. + * + * Requires: MBEDTLS_PLATFORM_C + * + * Enable this layer to allow use of alternative memory allocators. + */ +//#define MBEDTLS_PLATFORM_MEMORY + +/** + * \def MBEDTLS_PLATFORM_NO_STD_FUNCTIONS + * + * Do not assign standard functions in the platform layer (e.g. calloc() to + * MBEDTLS_PLATFORM_STD_CALLOC and printf() to MBEDTLS_PLATFORM_STD_PRINTF) + * + * This makes sure there are no linking errors on platforms that do not support + * these functions. You will HAVE to provide alternatives, either at runtime + * via the platform_set_xxx() functions or at compile time by setting + * the MBEDTLS_PLATFORM_STD_XXX defines, or enabling a + * MBEDTLS_PLATFORM_XXX_MACRO. + * + * Requires: MBEDTLS_PLATFORM_C + * + * Uncomment to prevent default assignment of standard functions in the + * platform layer. + */ +//#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS + +/** + * \def MBEDTLS_PLATFORM_EXIT_ALT + * + * MBEDTLS_PLATFORM_XXX_ALT: Uncomment a macro to let mbed TLS support the + * function in the platform abstraction layer. + * + * Example: In case you uncomment MBEDTLS_PLATFORM_PRINTF_ALT, mbed TLS will + * provide a function "mbedtls_platform_set_printf()" that allows you to set an + * alternative printf function pointer. + * + * All these define require MBEDTLS_PLATFORM_C to be defined! + * + * \note MBEDTLS_PLATFORM_SNPRINTF_ALT is required on Windows; + * it will be enabled automatically by check_config.h + * + * \warning MBEDTLS_PLATFORM_XXX_ALT cannot be defined at the same time as + * MBEDTLS_PLATFORM_XXX_MACRO! + * + * Requires: MBEDTLS_PLATFORM_TIME_ALT requires MBEDTLS_HAVE_TIME + * + * Uncomment a macro to enable alternate implementation of specific base + * platform function + */ +//#define MBEDTLS_PLATFORM_EXIT_ALT +//#define MBEDTLS_PLATFORM_TIME_ALT +//#define MBEDTLS_PLATFORM_FPRINTF_ALT +//#define MBEDTLS_PLATFORM_PRINTF_ALT +//#define MBEDTLS_PLATFORM_SNPRINTF_ALT +//#define MBEDTLS_PLATFORM_VSNPRINTF_ALT +//#define MBEDTLS_PLATFORM_NV_SEED_ALT +//#define MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT + +/** + * \def MBEDTLS_DEPRECATED_WARNING + * + * Mark deprecated functions and features so that they generate a warning if + * used. Functionality deprecated in one version will usually be removed in the + * next version. You can enable this to help you prepare the transition to a + * new major version by making sure your code is not using this functionality. + * + * This only works with GCC and Clang. With other compilers, you may want to + * use MBEDTLS_DEPRECATED_REMOVED + * + * Uncomment to get warnings on using deprecated functions and features. + */ +//#define MBEDTLS_DEPRECATED_WARNING + +/** + * \def MBEDTLS_DEPRECATED_REMOVED + * + * Remove deprecated functions and features so that they generate an error if + * used. Functionality deprecated in one version will usually be removed in the + * next version. You can enable this to help you prepare the transition to a + * new major version by making sure your code is not using this functionality. + * + * Uncomment to get errors on using deprecated functions and features. + */ +//#define MBEDTLS_DEPRECATED_REMOVED + +/** + * \def MBEDTLS_CHECK_PARAMS + * + * This configuration option controls whether the library validates more of + * the parameters passed to it. + * + * When this flag is not defined, the library only attempts to validate an + * input parameter if: (1) they may come from the outside world (such as the + * network, the filesystem, etc.) or (2) not validating them could result in + * internal memory errors such as overflowing a buffer controlled by the + * library. On the other hand, it doesn't attempt to validate parameters whose + * values are fully controlled by the application (such as pointers). + * + * When this flag is defined, the library additionally attempts to validate + * parameters that are fully controlled by the application, and should always + * be valid if the application code is fully correct and trusted. + * + * For example, when a function accepts as input a pointer to a buffer that may + * contain untrusted data, and its documentation mentions that this pointer + * must not be NULL: + * - The pointer is checked to be non-NULL only if this option is enabled. + * - The content of the buffer is always validated. + * + * When this flag is defined, if a library function receives a parameter that + * is invalid: + * 1. The function will invoke the macro MBEDTLS_PARAM_FAILED(). + * 2. If MBEDTLS_PARAM_FAILED() did not terminate the program, the function + * will immediately return. If the function returns an Mbed TLS error code, + * the error code in this case is MBEDTLS_ERR_xxx_BAD_INPUT_DATA. + * + * When defining this flag, you also need to arrange a definition for + * MBEDTLS_PARAM_FAILED(). You can do this by any of the following methods: + * - By default, the library defines MBEDTLS_PARAM_FAILED() to call a + * function mbedtls_param_failed(), but the library does not define this + * function. If you do not make any other arrangements, you must provide + * the function mbedtls_param_failed() in your application. + * See `platform_util.h` for its prototype. + * - If you enable the macro #MBEDTLS_CHECK_PARAMS_ASSERT, then the + * library defines MBEDTLS_PARAM_FAILED(\c cond) to be `assert(cond)`. + * You can still supply an alternative definition of + * MBEDTLS_PARAM_FAILED(), which may call `assert`. + * - If you define a macro MBEDTLS_PARAM_FAILED() before including `config.h` + * or you uncomment the definition of MBEDTLS_PARAM_FAILED() in `config.h`, + * the library will call the macro that you defined and will not supply + * its own version. Note that if MBEDTLS_PARAM_FAILED() calls `assert`, + * you need to enable #MBEDTLS_CHECK_PARAMS_ASSERT so that library source + * files include ``. + * + * Uncomment to enable validation of application-controlled parameters. + */ +//#define MBEDTLS_CHECK_PARAMS + +/** + * \def MBEDTLS_CHECK_PARAMS_ASSERT + * + * Allow MBEDTLS_PARAM_FAILED() to call `assert`, and make it default to + * `assert`. This macro is only used if #MBEDTLS_CHECK_PARAMS is defined. + * + * If this macro is not defined, then MBEDTLS_PARAM_FAILED() defaults to + * calling a function mbedtls_param_failed(). See the documentation of + * #MBEDTLS_CHECK_PARAMS for details. + * + * Uncomment to allow MBEDTLS_PARAM_FAILED() to call `assert`. + */ +//#define MBEDTLS_CHECK_PARAMS_ASSERT + +/* \} name SECTION: System support */ + +/** + * \name SECTION: mbed TLS feature support + * + * This section sets support for features that are or are not needed + * within the modules that are enabled. + * \{ + */ + +/** + * \def MBEDTLS_TIMING_ALT + * + * Uncomment to provide your own alternate implementation for mbedtls_timing_hardclock(), + * mbedtls_timing_get_timer(), mbedtls_set_alarm(), mbedtls_set/get_delay() + * + * Only works if you have MBEDTLS_TIMING_C enabled. + * + * You will need to provide a header "timing_alt.h" and an implementation at + * compile time. + */ +//#define MBEDTLS_TIMING_ALT + +/** + * \def MBEDTLS_AES_ALT + * + * MBEDTLS__MODULE_NAME__ALT: Uncomment a macro to let mbed TLS use your + * alternate core implementation of a symmetric crypto, an arithmetic or hash + * module (e.g. platform specific assembly optimized implementations). Keep + * in mind that the function prototypes should remain the same. + * + * This replaces the whole module. If you only want to replace one of the + * functions, use one of the MBEDTLS__FUNCTION_NAME__ALT flags. + * + * Example: In case you uncomment MBEDTLS_AES_ALT, mbed TLS will no longer + * provide the "struct mbedtls_aes_context" definition and omit the base + * function declarations and implementations. "aes_alt.h" will be included from + * "aes.h" to include the new function definitions. + * + * Uncomment a macro to enable alternate implementation of the corresponding + * module. + * + * \warning MD2, MD4, MD5, ARC4, DES and SHA-1 are considered weak and their + * use constitutes a security risk. If possible, we recommend + * avoiding dependencies on them, and considering stronger message + * digests and ciphers instead. + * + */ +//#define MBEDTLS_AES_ALT +//#define MBEDTLS_ARC4_ALT +//#define MBEDTLS_ARIA_ALT +//#define MBEDTLS_BLOWFISH_ALT +//#define MBEDTLS_CAMELLIA_ALT +//#define MBEDTLS_CCM_ALT +//#define MBEDTLS_CHACHA20_ALT +//#define MBEDTLS_CHACHAPOLY_ALT +//#define MBEDTLS_CMAC_ALT +//#define MBEDTLS_DES_ALT +//#define MBEDTLS_DHM_ALT +//#define MBEDTLS_ECJPAKE_ALT +//#define MBEDTLS_GCM_ALT +//#define MBEDTLS_NIST_KW_ALT +//#define MBEDTLS_MD2_ALT +//#define MBEDTLS_MD4_ALT +//#define MBEDTLS_MD5_ALT +//#define MBEDTLS_POLY1305_ALT +//#define MBEDTLS_RIPEMD160_ALT +//#define MBEDTLS_RSA_ALT +//#define MBEDTLS_SHA1_ALT +//#define MBEDTLS_SHA256_ALT +//#define MBEDTLS_SHA512_ALT +//#define MBEDTLS_XTEA_ALT + +/* + * When replacing the elliptic curve module, pleace consider, that it is + * implemented with two .c files: + * - ecp.c + * - ecp_curves.c + * You can replace them very much like all the other MBEDTLS__MODULE_NAME__ALT + * macros as described above. The only difference is that you have to make sure + * that you provide functionality for both .c files. + */ +//#define MBEDTLS_ECP_ALT + +/** + * \def MBEDTLS_MD2_PROCESS_ALT + * + * MBEDTLS__FUNCTION_NAME__ALT: Uncomment a macro to let mbed TLS use you + * alternate core implementation of symmetric crypto or hash function. Keep in + * mind that function prototypes should remain the same. + * + * This replaces only one function. The header file from mbed TLS is still + * used, in contrast to the MBEDTLS__MODULE_NAME__ALT flags. + * + * Example: In case you uncomment MBEDTLS_SHA256_PROCESS_ALT, mbed TLS will + * no longer provide the mbedtls_sha1_process() function, but it will still provide + * the other function (using your mbedtls_sha1_process() function) and the definition + * of mbedtls_sha1_context, so your implementation of mbedtls_sha1_process must be compatible + * with this definition. + * + * \note Because of a signature change, the core AES encryption and decryption routines are + * currently named mbedtls_aes_internal_encrypt and mbedtls_aes_internal_decrypt, + * respectively. When setting up alternative implementations, these functions should + * be overridden, but the wrapper functions mbedtls_aes_decrypt and mbedtls_aes_encrypt + * must stay untouched. + * + * \note If you use the AES_xxx_ALT macros, then is is recommended to also set + * MBEDTLS_AES_ROM_TABLES in order to help the linker garbage-collect the AES + * tables. + * + * Uncomment a macro to enable alternate implementation of the corresponding + * function. + * + * \warning MD2, MD4, MD5, DES and SHA-1 are considered weak and their use + * constitutes a security risk. If possible, we recommend avoiding + * dependencies on them, and considering stronger message digests + * and ciphers instead. + * + * \warning If both MBEDTLS_ECDSA_SIGN_ALT and MBEDTLS_ECDSA_DETERMINISTIC are + * enabled, then the deterministic ECDH signature functions pass the + * the static HMAC-DRBG as RNG to mbedtls_ecdsa_sign(). Therefore + * alternative implementations should use the RNG only for generating + * the ephemeral key and nothing else. If this is not possible, then + * MBEDTLS_ECDSA_DETERMINISTIC should be disabled and an alternative + * implementation should be provided for mbedtls_ecdsa_sign_det_ext() + * (and for mbedtls_ecdsa_sign_det() too if backward compatibility is + * desirable). + * + */ +//#define MBEDTLS_MD2_PROCESS_ALT +//#define MBEDTLS_MD4_PROCESS_ALT +//#define MBEDTLS_MD5_PROCESS_ALT +//#define MBEDTLS_RIPEMD160_PROCESS_ALT +//#define MBEDTLS_SHA1_PROCESS_ALT +//#define MBEDTLS_SHA256_PROCESS_ALT +//#define MBEDTLS_SHA512_PROCESS_ALT +//#define MBEDTLS_DES_SETKEY_ALT +//#define MBEDTLS_DES_CRYPT_ECB_ALT +//#define MBEDTLS_DES3_CRYPT_ECB_ALT +//#define MBEDTLS_AES_SETKEY_ENC_ALT +//#define MBEDTLS_AES_SETKEY_DEC_ALT +//#define MBEDTLS_AES_ENCRYPT_ALT +//#define MBEDTLS_AES_DECRYPT_ALT +//#define MBEDTLS_ECDH_GEN_PUBLIC_ALT +//#define MBEDTLS_ECDH_COMPUTE_SHARED_ALT +//#define MBEDTLS_ECDSA_VERIFY_ALT +//#define MBEDTLS_ECDSA_SIGN_ALT +//#define MBEDTLS_ECDSA_GENKEY_ALT + +/** + * \def MBEDTLS_ECP_INTERNAL_ALT + * + * Expose a part of the internal interface of the Elliptic Curve Point module. + * + * MBEDTLS_ECP__FUNCTION_NAME__ALT: Uncomment a macro to let mbed TLS use your + * alternative core implementation of elliptic curve arithmetic. Keep in mind + * that function prototypes should remain the same. + * + * This partially replaces one function. The header file from mbed TLS is still + * used, in contrast to the MBEDTLS_ECP_ALT flag. The original implementation + * is still present and it is used for group structures not supported by the + * alternative. + * + * Any of these options become available by defining MBEDTLS_ECP_INTERNAL_ALT + * and implementing the following functions: + * unsigned char mbedtls_internal_ecp_grp_capable( + * const mbedtls_ecp_group *grp ) + * int mbedtls_internal_ecp_init( const mbedtls_ecp_group *grp ) + * void mbedtls_internal_ecp_free( const mbedtls_ecp_group *grp ) + * The mbedtls_internal_ecp_grp_capable function should return 1 if the + * replacement functions implement arithmetic for the given group and 0 + * otherwise. + * The functions mbedtls_internal_ecp_init and mbedtls_internal_ecp_free are + * called before and after each point operation and provide an opportunity to + * implement optimized set up and tear down instructions. + * + * Example: In case you uncomment MBEDTLS_ECP_INTERNAL_ALT and + * MBEDTLS_ECP_DOUBLE_JAC_ALT, mbed TLS will still provide the ecp_double_jac + * function, but will use your mbedtls_internal_ecp_double_jac if the group is + * supported (your mbedtls_internal_ecp_grp_capable function returns 1 when + * receives it as an argument). If the group is not supported then the original + * implementation is used. The other functions and the definition of + * mbedtls_ecp_group and mbedtls_ecp_point will not change, so your + * implementation of mbedtls_internal_ecp_double_jac and + * mbedtls_internal_ecp_grp_capable must be compatible with this definition. + * + * Uncomment a macro to enable alternate implementation of the corresponding + * function. + */ +/* Required for all the functions in this section */ +//#define MBEDTLS_ECP_INTERNAL_ALT +/* Support for Weierstrass curves with Jacobi representation */ +//#define MBEDTLS_ECP_RANDOMIZE_JAC_ALT +//#define MBEDTLS_ECP_ADD_MIXED_ALT +//#define MBEDTLS_ECP_DOUBLE_JAC_ALT +//#define MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT +//#define MBEDTLS_ECP_NORMALIZE_JAC_ALT +/* Support for curves with Montgomery arithmetic */ +//#define MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT +//#define MBEDTLS_ECP_RANDOMIZE_MXZ_ALT +//#define MBEDTLS_ECP_NORMALIZE_MXZ_ALT + +/** + * \def MBEDTLS_TEST_NULL_ENTROPY + * + * Enables testing and use of mbed TLS without any configured entropy sources. + * This permits use of the library on platforms before an entropy source has + * been integrated (see for example the MBEDTLS_ENTROPY_HARDWARE_ALT or the + * MBEDTLS_ENTROPY_NV_SEED switches). + * + * WARNING! This switch MUST be disabled in production builds, and is suitable + * only for development. + * Enabling the switch negates any security provided by the library. + * + * Requires MBEDTLS_ENTROPY_C, MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES + * + */ +//#define MBEDTLS_TEST_NULL_ENTROPY + +/** + * \def MBEDTLS_ENTROPY_HARDWARE_ALT + * + * Uncomment this macro to let mbed TLS use your own implementation of a + * hardware entropy collector. + * + * Your function must be called \c mbedtls_hardware_poll(), have the same + * prototype as declared in entropy_poll.h, and accept NULL as first argument. + * + * Uncomment to use your own hardware entropy collector. + */ +//#define MBEDTLS_ENTROPY_HARDWARE_ALT + +/** + * \def MBEDTLS_AES_ROM_TABLES + * + * Use precomputed AES tables stored in ROM. + * + * Uncomment this macro to use precomputed AES tables stored in ROM. + * Comment this macro to generate AES tables in RAM at runtime. + * + * Tradeoff: Using precomputed ROM tables reduces RAM usage by ~8kb + * (or ~2kb if \c MBEDTLS_AES_FEWER_TABLES is used) and reduces the + * initialization time before the first AES operation can be performed. + * It comes at the cost of additional ~8kb ROM use (resp. ~2kb if \c + * MBEDTLS_AES_FEWER_TABLES below is used), and potentially degraded + * performance if ROM access is slower than RAM access. + * + * This option is independent of \c MBEDTLS_AES_FEWER_TABLES. + * + */ +//#define MBEDTLS_AES_ROM_TABLES + +/** + * \def MBEDTLS_AES_FEWER_TABLES + * + * Use less ROM/RAM for AES tables. + * + * Uncommenting this macro omits 75% of the AES tables from + * ROM / RAM (depending on the value of \c MBEDTLS_AES_ROM_TABLES) + * by computing their values on the fly during operations + * (the tables are entry-wise rotations of one another). + * + * Tradeoff: Uncommenting this reduces the RAM / ROM footprint + * by ~6kb but at the cost of more arithmetic operations during + * runtime. Specifically, one has to compare 4 accesses within + * different tables to 4 accesses with additional arithmetic + * operations within the same table. The performance gain/loss + * depends on the system and memory details. + * + * This option is independent of \c MBEDTLS_AES_ROM_TABLES. + * + */ +//#define MBEDTLS_AES_FEWER_TABLES + +/** + * \def MBEDTLS_CAMELLIA_SMALL_MEMORY + * + * Use less ROM for the Camellia implementation (saves about 768 bytes). + * + * Uncomment this macro to use less memory for Camellia. + */ +//#define MBEDTLS_CAMELLIA_SMALL_MEMORY + +/** + * \def MBEDTLS_CIPHER_MODE_CBC + * + * Enable Cipher Block Chaining mode (CBC) for symmetric ciphers. + */ +//#define MBEDTLS_CIPHER_MODE_CBC + +/** + * \def MBEDTLS_CIPHER_MODE_CFB + * + * Enable Cipher Feedback mode (CFB) for symmetric ciphers. + */ +//#define MBEDTLS_CIPHER_MODE_CFB + +/** + * \def MBEDTLS_CIPHER_MODE_CTR + * + * Enable Counter Block Cipher mode (CTR) for symmetric ciphers. + */ +//#define MBEDTLS_CIPHER_MODE_CTR + +/** + * \def MBEDTLS_CIPHER_MODE_OFB + * + * Enable Output Feedback mode (OFB) for symmetric ciphers. + */ +//#define MBEDTLS_CIPHER_MODE_OFB + +/** + * \def MBEDTLS_CIPHER_MODE_XTS + * + * Enable Xor-encrypt-xor with ciphertext stealing mode (XTS) for AES. + */ +//#define MBEDTLS_CIPHER_MODE_XTS + +/** + * \def MBEDTLS_CIPHER_NULL_CIPHER + * + * Enable NULL cipher. + * Warning: Only do so when you know what you are doing. This allows for + * encryption or channels without any security! + * + * Requires MBEDTLS_ENABLE_WEAK_CIPHERSUITES as well to enable + * the following ciphersuites: + * MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA + * MBEDTLS_TLS_RSA_WITH_NULL_SHA256 + * MBEDTLS_TLS_RSA_WITH_NULL_SHA + * MBEDTLS_TLS_RSA_WITH_NULL_MD5 + * MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA + * MBEDTLS_TLS_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_PSK_WITH_NULL_SHA + * + * Uncomment this macro to enable the NULL cipher and ciphersuites + */ +//#define MBEDTLS_CIPHER_NULL_CIPHER + +/** + * \def MBEDTLS_CIPHER_PADDING_PKCS7 + * + * MBEDTLS_CIPHER_PADDING_XXX: Uncomment or comment macros to add support for + * specific padding modes in the cipher layer with cipher modes that support + * padding (e.g. CBC) + * + * If you disable all padding modes, only full blocks can be used with CBC. + * + * Enable padding modes in the cipher layer. + */ +//#define MBEDTLS_CIPHER_PADDING_PKCS7 +//#define MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS +//#define MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN +//#define MBEDTLS_CIPHER_PADDING_ZEROS + +/** \def MBEDTLS_CTR_DRBG_USE_128_BIT_KEY + * + * Uncomment this macro to use a 128-bit key in the CTR_DRBG module. + * By default, CTR_DRBG uses a 256-bit key. + */ +//#define MBEDTLS_CTR_DRBG_USE_128_BIT_KEY + +/** + * \def MBEDTLS_ENABLE_WEAK_CIPHERSUITES + * + * Enable weak ciphersuites in SSL / TLS. + * Warning: Only do so when you know what you are doing. This allows for + * channels with virtually no security at all! + * + * This enables the following ciphersuites: + * MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA + * + * Uncomment this macro to enable weak ciphersuites + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers instead. + */ +//#define MBEDTLS_ENABLE_WEAK_CIPHERSUITES + +/** + * \def MBEDTLS_REMOVE_ARC4_CIPHERSUITES + * + * Remove RC4 ciphersuites by default in SSL / TLS. + * This flag removes the ciphersuites based on RC4 from the default list as + * returned by mbedtls_ssl_list_ciphersuites(). However, it is still possible to + * enable (some of) them with mbedtls_ssl_conf_ciphersuites() by including them + * explicitly. + * + * Uncomment this macro to remove RC4 ciphersuites by default. + */ +//#define MBEDTLS_REMOVE_ARC4_CIPHERSUITES + +/** + * \def MBEDTLS_REMOVE_3DES_CIPHERSUITES + * + * Remove 3DES ciphersuites by default in SSL / TLS. + * This flag removes the ciphersuites based on 3DES from the default list as + * returned by mbedtls_ssl_list_ciphersuites(). However, it is still possible + * to enable (some of) them with mbedtls_ssl_conf_ciphersuites() by including + * them explicitly. + * + * A man-in-the-browser attacker can recover authentication tokens sent through + * a TLS connection using a 3DES based cipher suite (see "On the Practical + * (In-)Security of 64-bit Block Ciphers" by Karthikeyan Bhargavan and Gaëtan + * Leurent, see https://sweet32.info/SWEET32_CCS16.pdf). If this attack falls + * in your threat model or you are unsure, then you should keep this option + * enabled to remove 3DES based cipher suites. + * + * Comment this macro to keep 3DES in the default ciphersuite list. + */ +//#define MBEDTLS_REMOVE_3DES_CIPHERSUITES + +/** + * \def MBEDTLS_ECP_DP_SECP192R1_ENABLED + * + * MBEDTLS_ECP_XXXX_ENABLED: Enables specific curves within the Elliptic Curve + * module. By default all supported curves are enabled. + * + * Comment macros to disable the curve and functions for it + */ +// #define MBEDTLS_ECP_DP_SECP192R1_ENABLED +// #define MBEDTLS_ECP_DP_SECP224R1_ENABLED +// #define MBEDTLS_ECP_DP_SECP256R1_ENABLED +// #define MBEDTLS_ECP_DP_SECP384R1_ENABLED +// #define MBEDTLS_ECP_DP_SECP521R1_ENABLED +// #define MBEDTLS_ECP_DP_SECP192K1_ENABLED +// #define MBEDTLS_ECP_DP_SECP224K1_ENABLED +// #define MBEDTLS_ECP_DP_SECP256K1_ENABLED +// #define MBEDTLS_ECP_DP_BP256R1_ENABLED +// #define MBEDTLS_ECP_DP_BP384R1_ENABLED +// #define MBEDTLS_ECP_DP_BP512R1_ENABLED +// #define MBEDTLS_ECP_DP_CURVE25519_ENABLED +// #define MBEDTLS_ECP_DP_CURVE448_ENABLED + +/** + * \def MBEDTLS_ECP_NIST_OPTIM + * + * Enable specific 'modulo p' routines for each NIST prime. + * Depending on the prime and architecture, makes operations 4 to 8 times + * faster on the corresponding curve. + * + * Comment this macro to disable NIST curves optimisation. + */ +//#define MBEDTLS_ECP_NIST_OPTIM/ + +/** + * \def MBEDTLS_ECP_NO_INTERNAL_RNG + * + * When this option is disabled, mbedtls_ecp_mul() will make use of an + * internal RNG when called with a NULL \c f_rng argument, in order to protect + * against some side-channel attacks. + * + * This protection introduces a dependency of the ECP module on one of the + * DRBG modules. For very constrained implementations that don't require this + * protection (for example, because you're only doing signature verification, + * so not manipulating any secret, or because local/physical side-channel + * attacks are outside your threat model), it might be desirable to get rid of + * that dependency. + * + * \warning Enabling this option makes some uses of ECP vulnerable to some + * side-channel attacks. Only enable it if you know that's not a problem for + * your use case. + * + * Uncomment this macro to disable some counter-measures in ECP. + */ +//#define MBEDTLS_ECP_NO_INTERNAL_RNG + +/** + * \def MBEDTLS_ECP_RESTARTABLE + * + * Enable "non-blocking" ECC operations that can return early and be resumed. + * + * This allows various functions to pause by returning + * #MBEDTLS_ERR_ECP_IN_PROGRESS (or, for functions in the SSL module, + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) and then be called later again in + * order to further progress and eventually complete their operation. This is + * controlled through mbedtls_ecp_set_max_ops() which limits the maximum + * number of ECC operations a function may perform before pausing; see + * mbedtls_ecp_set_max_ops() for more information. + * + * This is useful in non-threaded environments if you want to avoid blocking + * for too long on ECC (and, hence, X.509 or SSL/TLS) operations. + * + * Uncomment this macro to enable restartable ECC computations. + * + * \note This option only works with the default software implementation of + * elliptic curve functionality. It is incompatible with + * MBEDTLS_ECP_ALT, MBEDTLS_ECDH_XXX_ALT, MBEDTLS_ECDSA_XXX_ALT + * and MBEDTLS_ECDH_LEGACY_CONTEXT. + */ +//#define MBEDTLS_ECP_RESTARTABLE + +/** + * \def MBEDTLS_ECDH_LEGACY_CONTEXT + * + * Use a backward compatible ECDH context. + * + * Mbed TLS supports two formats for ECDH contexts (#mbedtls_ecdh_context + * defined in `ecdh.h`). For most applications, the choice of format makes + * no difference, since all library functions can work with either format, + * except that the new format is incompatible with MBEDTLS_ECP_RESTARTABLE. + + * The new format used when this option is disabled is smaller + * (56 bytes on a 32-bit platform). In future versions of the library, it + * will support alternative implementations of ECDH operations. + * The new format is incompatible with applications that access + * context fields directly and with restartable ECP operations. + * + * Define this macro if you enable MBEDTLS_ECP_RESTARTABLE or if you + * want to access ECDH context fields directly. Otherwise you should + * comment out this macro definition. + * + * This option has no effect if #MBEDTLS_ECDH_C is not enabled. + * + * \note This configuration option is experimental. Future versions of the + * library may modify the way the ECDH context layout is configured + * and may modify the layout of the new context type. + */ +//#define MBEDTLS_ECDH_LEGACY_CONTEXT + +/** + * \def MBEDTLS_ECDSA_DETERMINISTIC + * + * Enable deterministic ECDSA (RFC 6979). + * Standard ECDSA is "fragile" in the sense that lack of entropy when signing + * may result in a compromise of the long-term signing key. This is avoided by + * the deterministic variant. + * + * Requires: MBEDTLS_HMAC_DRBG_C + * + * Comment this macro to disable deterministic ECDSA. + */ +//#define MBEDTLS_ECDSA_DETERMINISTIC + +/** + * \def MBEDTLS_KEY_EXCHANGE_PSK_ENABLED + * + * Enable the PSK based ciphersuite modes in SSL / TLS. + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_RC4_128_SHA + */ +//#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED + * + * Enable the DHE-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_DHM_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA + * + * \warning Using DHE constitutes a security risk as it + * is not possible to validate custom DH parameters. + * If possible, it is recommended users should consider + * preferring other methods of key exchange. + * See dhm.h for more details. + * + */ +//#define MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED + * + * Enable the ECDHE-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA + */ +//#define MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED + * + * Enable the RSA-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA + */ +//#define MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_RSA_ENABLED + * + * Enable the RSA-only based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 + */ +//#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED + * + * Enable the DHE-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_DHM_C, MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + * + * \warning Using DHE constitutes a security risk as it + * is not possible to validate custom DH parameters. + * If possible, it is recommended users should consider + * preferring other methods of key exchange. + * See dhm.h for more details. + * + */ +//#define MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED + * + * Enable the ECDHE-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA + */ +//#define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED + * + * Enable the ECDHE-ECDSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_ECDSA_C, MBEDTLS_X509_CRT_PARSE_C, + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA + */ +//#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED + * + * Enable the ECDH-ECDSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + */ +//#define MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED + * + * Enable the ECDH-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 + */ +//#define MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED + * + * Enable the ECJPAKE based ciphersuite modes in SSL / TLS. + * + * \warning This is currently experimental. EC J-PAKE support is based on the + * Thread v1.0.0 specification; incompatible changes to the specification + * might still happen. For this reason, this is disabled by default. + * + * Requires: MBEDTLS_ECJPAKE_C + * MBEDTLS_SHA256_C + * MBEDTLS_ECP_DP_SECP256R1_ENABLED + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8 + */ +//#define MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED + +/** + * \def MBEDTLS_PK_PARSE_EC_EXTENDED + * + * Enhance support for reading EC keys using variants of SEC1 not allowed by + * RFC 5915 and RFC 5480. + * + * Currently this means parsing the SpecifiedECDomain choice of EC + * parameters (only known groups are supported, not arbitrary domains, to + * avoid validation issues). + * + * Disable if you only need to support RFC 5915 + 5480 key formats. + */ +//#define MBEDTLS_PK_PARSE_EC_EXTENDED + +/** + * \def MBEDTLS_ERROR_STRERROR_DUMMY + * + * Enable a dummy error function to make use of mbedtls_strerror() in + * third party libraries easier when MBEDTLS_ERROR_C is disabled + * (no effect when MBEDTLS_ERROR_C is enabled). + * + * You can safely disable this if MBEDTLS_ERROR_C is enabled, or if you're + * not using mbedtls_strerror() or error_strerror() in your application. + * + * Disable if you run into name conflicts and want to really remove the + * mbedtls_strerror() + */ +//#define MBEDTLS_ERROR_STRERROR_DUMMY + +/** + * \def MBEDTLS_GENPRIME + * + * Enable the prime-number generation code. + * + * Requires: MBEDTLS_BIGNUM_C + */ +//#define MBEDTLS_GENPRIME + +/** + * \def MBEDTLS_FS_IO + * + * Enable functions that use the filesystem. + */ +//#define MBEDTLS_FS_IO + +/** + * \def MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES + * + * Do not add default entropy sources. These are the platform specific, + * mbedtls_timing_hardclock and HAVEGE based poll functions. + * + * This is useful to have more control over the added entropy sources in an + * application. + * + * Uncomment this macro to prevent loading of default entropy functions. + */ +//#define MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES + +/** + * \def MBEDTLS_NO_PLATFORM_ENTROPY + * + * Do not use built-in platform entropy functions. + * This is useful if your platform does not support + * standards like the /dev/urandom or Windows CryptoAPI. + * + * Uncomment this macro to disable the built-in platform entropy functions. + */ +//#define MBEDTLS_NO_PLATFORM_ENTROPY + +/** + * \def MBEDTLS_ENTROPY_FORCE_SHA256 + * + * Force the entropy accumulator to use a SHA-256 accumulator instead of the + * default SHA-512 based one (if both are available). + * + * Requires: MBEDTLS_SHA256_C + * + * On 32-bit systems SHA-256 can be much faster than SHA-512. Use this option + * if you have performance concerns. + * + * This option is only useful if both MBEDTLS_SHA256_C and + * MBEDTLS_SHA512_C are defined. Otherwise the available hash module is used. + */ +//#define MBEDTLS_ENTROPY_FORCE_SHA256 + +/** + * \def MBEDTLS_ENTROPY_NV_SEED + * + * Enable the non-volatile (NV) seed file-based entropy source. + * (Also enables the NV seed read/write functions in the platform layer) + * + * This is crucial (if not required) on systems that do not have a + * cryptographic entropy source (in hardware or kernel) available. + * + * Requires: MBEDTLS_ENTROPY_C, MBEDTLS_PLATFORM_C + * + * \note The read/write functions that are used by the entropy source are + * determined in the platform layer, and can be modified at runtime and/or + * compile-time depending on the flags (MBEDTLS_PLATFORM_NV_SEED_*) used. + * + * \note If you use the default implementation functions that read a seedfile + * with regular fopen(), please make sure you make a seedfile with the + * proper name (defined in MBEDTLS_PLATFORM_STD_NV_SEED_FILE) and at + * least MBEDTLS_ENTROPY_BLOCK_SIZE bytes in size that can be read from + * and written to or you will get an entropy source error! The default + * implementation will only use the first MBEDTLS_ENTROPY_BLOCK_SIZE + * bytes from the file. + * + * \note The entropy collector will write to the seed file before entropy is + * given to an external source, to update it. + */ +//#define MBEDTLS_ENTROPY_NV_SEED + +/* MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER + * + * In PSA key storage, encode the owner of the key. + * + * This is only meaningful when building the library as part of a + * multi-client service. When you activate this option, you must provide + * an implementation of the type psa_key_owner_id_t and a translation + * from psa_key_file_id_t to file name in all the storage backends that + * you wish to support. + * + * Note that this option is meant for internal use only and may be removed + * without notice. + */ +//#define MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER + +/** + * \def MBEDTLS_MEMORY_DEBUG + * + * Enable debugging of buffer allocator memory issues. Automatically prints + * (to stderr) all (fatal) messages on memory allocation issues. Enables + * function for 'debug output' of allocated memory. + * + * Requires: MBEDTLS_MEMORY_BUFFER_ALLOC_C + * + * Uncomment this macro to let the buffer allocator print out error messages. + */ +//#define MBEDTLS_MEMORY_DEBUG + +/** + * \def MBEDTLS_MEMORY_BACKTRACE + * + * Include backtrace information with each allocated block. + * + * Requires: MBEDTLS_MEMORY_BUFFER_ALLOC_C + * GLIBC-compatible backtrace() an backtrace_symbols() support + * + * Uncomment this macro to include backtrace information + */ +//#define MBEDTLS_MEMORY_BACKTRACE + +/** + * \def MBEDTLS_PK_RSA_ALT_SUPPORT + * + * Support external private RSA keys (eg from a HSM) in the PK layer. + * + * Comment this macro to disable support for external private RSA keys. + */ +//#define MBEDTLS_PK_RSA_ALT_SUPPORT + +/** + * \def MBEDTLS_PKCS1_V15 + * + * Enable support for PKCS#1 v1.5 encoding. + * + * Requires: MBEDTLS_RSA_C + * + * This enables support for PKCS#1 v1.5 operations. + */ +//#define MBEDTLS_PKCS1_V15 + +/** + * \def MBEDTLS_PKCS1_V21 + * + * Enable support for PKCS#1 v2.1 encoding. + * + * Requires: MBEDTLS_MD_C, MBEDTLS_RSA_C + * + * This enables support for RSAES-OAEP and RSASSA-PSS operations. + */ +//#define MBEDTLS_PKCS1_V21 + +/** + * \def MBEDTLS_PSA_CRYPTO_SPM + * + * When MBEDTLS_PSA_CRYPTO_SPM is defined, the code is built for SPM (Secure + * Partition Manager) integration which separates the code into two parts: a + * NSPE (Non-Secure Process Environment) and an SPE (Secure Process + * Environment). + * + * Module: library/psa_crypto.c + * Requires: MBEDTLS_PSA_CRYPTO_C + * + */ +//#define MBEDTLS_PSA_CRYPTO_SPM + +/** + * \def MBEDTLS_PSA_INJECT_ENTROPY + * + * Enable support for entropy injection at first boot. This feature is + * required on systems that do not have a built-in entropy source (TRNG). + * This feature is currently not supported on systems that have a built-in + * entropy source. + * + * Requires: MBEDTLS_PSA_CRYPTO_STORAGE_C, MBEDTLS_ENTROPY_NV_SEED + * + */ +//#define MBEDTLS_PSA_INJECT_ENTROPY + +/** + * \def MBEDTLS_RSA_NO_CRT + * + * Do not use the Chinese Remainder Theorem + * for the RSA private operation. + * + * Uncomment this macro to disable the use of CRT in RSA. + * + */ +//#define MBEDTLS_RSA_NO_CRT + +/** + * \def MBEDTLS_SELF_TEST + * + * Enable the checkup functions (*_self_test). + */ +//#define MBEDTLS_SELF_TEST + +/** + * \def MBEDTLS_SHA256_SMALLER + * + * Enable an implementation of SHA-256 that has lower ROM footprint but also + * lower performance. + * + * The default implementation is meant to be a reasonnable compromise between + * performance and size. This version optimizes more aggressively for size at + * the expense of performance. Eg on Cortex-M4 it reduces the size of + * mbedtls_sha256_process() from ~2KB to ~0.5KB for a performance hit of about + * 30%. + * + * Uncomment to enable the smaller implementation of SHA256. + */ +//#define MBEDTLS_SHA256_SMALLER + +/** + * \def MBEDTLS_SHA512_SMALLER + * + * Enable an implementation of SHA-512 that has lower ROM footprint but also + * lower performance. + * + * Uncomment to enable the smaller implementation of SHA512. + */ +//#define MBEDTLS_SHA512_SMALLER + +/** + * \def MBEDTLS_SHA512_NO_SHA384 + * + * Disable the SHA-384 option of the SHA-512 module. Use this to save some + * code size on devices that don't use SHA-384. + * + * Requires: MBEDTLS_SHA512_C + * + * Uncomment to disable SHA-384 + */ +//#define MBEDTLS_SHA512_NO_SHA384 + +/** + * \def MBEDTLS_SSL_ALL_ALERT_MESSAGES + * + * Enable sending of alert messages in case of encountered errors as per RFC. + * If you choose not to send the alert messages, mbed TLS can still communicate + * with other servers, only debugging of failures is harder. + * + * The advantage of not sending alert messages, is that no information is given + * about reasons for failures thus preventing adversaries of gaining intel. + * + * Enable sending of all alert messages + */ +//#define MBEDTLS_SSL_ALL_ALERT_MESSAGES + +/** + * \def MBEDTLS_SSL_RECORD_CHECKING + * + * Enable the function mbedtls_ssl_check_record() which can be used to check + * the validity and authenticity of an incoming record, to verify that it has + * not been seen before. These checks are performed without modifying the + * externally visible state of the SSL context. + * + * See mbedtls_ssl_check_record() for more information. + * + * Uncomment to enable support for record checking. + */ +//#define MBEDTLS_SSL_RECORD_CHECKING + +/** + * \def MBEDTLS_SSL_DTLS_CONNECTION_ID + * + * Enable support for the DTLS Connection ID extension + * (version draft-ietf-tls-dtls-connection-id-05, + * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05) + * which allows to identify DTLS connections across changes + * in the underlying transport. + * + * Setting this option enables the SSL APIs `mbedtls_ssl_set_cid()`, + * `mbedtls_ssl_get_peer_cid()` and `mbedtls_ssl_conf_cid()`. + * See the corresponding documentation for more information. + * + * \warning The Connection ID extension is still in draft state. + * We make no stability promises for the availability + * or the shape of the API controlled by this option. + * + * The maximum lengths of outgoing and incoming CIDs can be configured + * through the options + * - MBEDTLS_SSL_CID_OUT_LEN_MAX + * - MBEDTLS_SSL_CID_IN_LEN_MAX. + * + * Requires: MBEDTLS_SSL_PROTO_DTLS + * + * Uncomment to enable the Connection ID extension. + */ +//#define MBEDTLS_SSL_DTLS_CONNECTION_ID + +/** + * \def MBEDTLS_SSL_ASYNC_PRIVATE + * + * Enable asynchronous external private key operations in SSL. This allows + * you to configure an SSL connection to call an external cryptographic + * module to perform private key operations instead of performing the + * operation inside the library. + * + */ +//#define MBEDTLS_SSL_ASYNC_PRIVATE + +/** + * \def MBEDTLS_SSL_CONTEXT_SERIALIZATION + * + * Enable serialization of the TLS context structures, through use of the + * functions mbedtls_ssl_context_save() and mbedtls_ssl_context_load(). + * + * This pair of functions allows one side of a connection to serialize the + * context associated with the connection, then free or re-use that context + * while the serialized state is persisted elsewhere, and finally deserialize + * that state to a live context for resuming read/write operations on the + * connection. From a protocol perspective, the state of the connection is + * unaffected, in particular this is entirely transparent to the peer. + * + * Note: this is distinct from TLS session resumption, which is part of the + * protocol and fully visible by the peer. TLS session resumption enables + * establishing new connections associated to a saved session with shorter, + * lighter handshakes, while context serialization is a local optimization in + * handling a single, potentially long-lived connection. + * + * Enabling these APIs makes some SSL structures larger, as 64 extra bytes are + * saved after the handshake to allow for more efficient serialization, so if + * you don't need this feature you'll save RAM by disabling it. + * + * Comment to disable the context serialization APIs. + */ +//#define MBEDTLS_SSL_CONTEXT_SERIALIZATION + +/** + * \def MBEDTLS_SSL_DEBUG_ALL + * + * Enable the debug messages in SSL module for all issues. + * Debug messages have been disabled in some places to prevent timing + * attacks due to (unbalanced) debugging function calls. + * + * If you need all error reporting you should enable this during debugging, + * but remove this for production servers that should log as well. + * + * Uncomment this macro to report all debug messages on errors introducing + * a timing side-channel. + * + */ +//#define MBEDTLS_SSL_DEBUG_ALL + +/** \def MBEDTLS_SSL_ENCRYPT_THEN_MAC + * + * Enable support for Encrypt-then-MAC, RFC 7366. + * + * This allows peers that both support it to use a more robust protection for + * ciphersuites using CBC, providing deep resistance against timing attacks + * on the padding or underlying cipher. + * + * This only affects CBC ciphersuites, and is useless if none is defined. + * + * Requires: MBEDTLS_SSL_PROTO_TLS1 or + * MBEDTLS_SSL_PROTO_TLS1_1 or + * MBEDTLS_SSL_PROTO_TLS1_2 + * + * Comment this macro to disable support for Encrypt-then-MAC + */ +//#define MBEDTLS_SSL_ENCRYPT_THEN_MAC + +/** \def MBEDTLS_SSL_EXTENDED_MASTER_SECRET + * + * Enable support for RFC 7627: Session Hash and Extended Master Secret + * Extension. + * + * This was introduced as "the proper fix" to the Triple Handshake familiy of + * attacks, but it is recommended to always use it (even if you disable + * renegotiation), since it actually fixes a more fundamental issue in the + * original SSL/TLS design, and has implications beyond Triple Handshake. + * + * Requires: MBEDTLS_SSL_PROTO_TLS1 or + * MBEDTLS_SSL_PROTO_TLS1_1 or + * MBEDTLS_SSL_PROTO_TLS1_2 + * + * Comment this macro to disable support for Extended Master Secret. + */ +//#define MBEDTLS_SSL_EXTENDED_MASTER_SECRET + +/** + * \def MBEDTLS_SSL_FALLBACK_SCSV + * + * Enable support for RFC 7507: Fallback Signaling Cipher Suite Value (SCSV) + * for Preventing Protocol Downgrade Attacks. + * + * For servers, it is recommended to always enable this, unless you support + * only one version of TLS, or know for sure that none of your clients + * implements a fallback strategy. + * + * For clients, you only need this if you're using a fallback strategy, which + * is not recommended in the first place, unless you absolutely need it to + * interoperate with buggy (version-intolerant) servers. + * + * Comment this macro to disable support for FALLBACK_SCSV + */ +//#define MBEDTLS_SSL_FALLBACK_SCSV + +/** + * \def MBEDTLS_SSL_KEEP_PEER_CERTIFICATE + * + * This option controls the availability of the API mbedtls_ssl_get_peer_cert() + * giving access to the peer's certificate after completion of the handshake. + * + * Unless you need mbedtls_ssl_peer_cert() in your application, it is + * recommended to disable this option for reduced RAM usage. + * + * \note If this option is disabled, mbedtls_ssl_get_peer_cert() is still + * defined, but always returns \c NULL. + * + * \note This option has no influence on the protection against the + * triple handshake attack. Even if it is disabled, Mbed TLS will + * still ensure that certificates do not change during renegotiation, + * for exaple by keeping a hash of the peer's certificate. + * + * Comment this macro to disable storing the peer's certificate + * after the handshake. + */ +//#define MBEDTLS_SSL_KEEP_PEER_CERTIFICATE + +/** + * \def MBEDTLS_SSL_HW_RECORD_ACCEL + * + * Enable hooking functions in SSL module for hardware acceleration of + * individual records. + * + * \deprecated This option is deprecated and will be removed in a future + * version of Mbed TLS. + * + * Uncomment this macro to enable hooking functions. + */ +//#define MBEDTLS_SSL_HW_RECORD_ACCEL + +/** + * \def MBEDTLS_SSL_CBC_RECORD_SPLITTING + * + * Enable 1/n-1 record splitting for CBC mode in SSLv3 and TLS 1.0. + * + * This is a countermeasure to the BEAST attack, which also minimizes the risk + * of interoperability issues compared to sending 0-length records. + * + * Comment this macro to disable 1/n-1 record splitting. + */ +//#define MBEDTLS_SSL_CBC_RECORD_SPLITTING + +/** + * \def MBEDTLS_SSL_RENEGOTIATION + * + * Enable support for TLS renegotiation. + * + * The two main uses of renegotiation are (1) refresh keys on long-lived + * connections and (2) client authentication after the initial handshake. + * If you don't need renegotiation, it's probably better to disable it, since + * it has been associated with security issues in the past and is easy to + * misuse/misunderstand. + * + * Comment this to disable support for renegotiation. + * + * \note Even if this option is disabled, both client and server are aware + * of the Renegotiation Indication Extension (RFC 5746) used to + * prevent the SSL renegotiation attack (see RFC 5746 Sect. 1). + * (See \c mbedtls_ssl_conf_legacy_renegotiation for the + * configuration of this extension). + * + */ +//#define MBEDTLS_SSL_RENEGOTIATION + +/** + * \def MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO + * + * Enable support for receiving and parsing SSLv2 Client Hello messages for the + * SSL Server module (MBEDTLS_SSL_SRV_C). + * + * \deprecated This option is deprecated and will be removed in a future + * version of Mbed TLS. + * + * Uncomment this macro to enable support for SSLv2 Client Hello messages. + */ +//#define MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO + +/** + * \def MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE + * + * Pick the ciphersuite according to the client's preferences rather than ours + * in the SSL Server module (MBEDTLS_SSL_SRV_C). + * + * Uncomment this macro to respect client's ciphersuite order + */ +//#define MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE + +/** + * \def MBEDTLS_SSL_MAX_FRAGMENT_LENGTH + * + * Enable support for RFC 6066 max_fragment_length extension in SSL. + * + * Comment this macro to disable support for the max_fragment_length extension + */ +//#define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH + +/** + * \def MBEDTLS_SSL_PROTO_SSL3 + * + * Enable support for SSL 3.0. + * + * Requires: MBEDTLS_MD5_C + * MBEDTLS_SHA1_C + * + * \deprecated This option is deprecated and will be removed in a future + * version of Mbed TLS. + * + * Comment this macro to disable support for SSL 3.0 + */ +//#define MBEDTLS_SSL_PROTO_SSL3 + +/** + * \def MBEDTLS_SSL_PROTO_TLS1 + * + * Enable support for TLS 1.0. + * + * Requires: MBEDTLS_MD5_C + * MBEDTLS_SHA1_C + * + * Comment this macro to disable support for TLS 1.0 + */ +//#define MBEDTLS_SSL_PROTO_TLS1 + +/** + * \def MBEDTLS_SSL_PROTO_TLS1_1 + * + * Enable support for TLS 1.1 (and DTLS 1.0 if DTLS is enabled). + * + * Requires: MBEDTLS_MD5_C + * MBEDTLS_SHA1_C + * + * Comment this macro to disable support for TLS 1.1 / DTLS 1.0 + */ +//#define MBEDTLS_SSL_PROTO_TLS1_1 + +/** + * \def MBEDTLS_SSL_PROTO_TLS1_2 + * + * Enable support for TLS 1.2 (and DTLS 1.2 if DTLS is enabled). + * + * Requires: MBEDTLS_SHA1_C or MBEDTLS_SHA256_C or MBEDTLS_SHA512_C + * (Depends on ciphersuites) + * + * Comment this macro to disable support for TLS 1.2 / DTLS 1.2 + */ +//#define MBEDTLS_SSL_PROTO_TLS1_2 + +/** + * \def MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL + * + * This macro is used to selectively enable experimental parts + * of the code that contribute to the ongoing development of + * the prototype TLS 1.3 and DTLS 1.3 implementation, and provide + * no other purpose. + * + * \warning TLS 1.3 and DTLS 1.3 aren't yet supported in Mbed TLS, + * and no feature exposed through this macro is part of the + * public API. In particular, features under the control + * of this macro are experimental and don't come with any + * stability guarantees. + * + * Uncomment this macro to enable experimental and partial + * functionality specific to TLS 1.3. + */ +//#define MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL + +/** + * \def MBEDTLS_SSL_PROTO_DTLS + * + * Enable support for DTLS (all available versions). + * + * Enable this and MBEDTLS_SSL_PROTO_TLS1_1 to enable DTLS 1.0, + * and/or this and MBEDTLS_SSL_PROTO_TLS1_2 to enable DTLS 1.2. + * + * Requires: MBEDTLS_SSL_PROTO_TLS1_1 + * or MBEDTLS_SSL_PROTO_TLS1_2 + * + * Comment this macro to disable support for DTLS + */ +//#define MBEDTLS_SSL_PROTO_DTLS + +/** + * \def MBEDTLS_SSL_ALPN + * + * Enable support for RFC 7301 Application Layer Protocol Negotiation. + * + * Comment this macro to disable support for ALPN. + */ +//#define MBEDTLS_SSL_ALPN + +/** + * \def MBEDTLS_SSL_DTLS_ANTI_REPLAY + * + * Enable support for the anti-replay mechanism in DTLS. + * + * Requires: MBEDTLS_SSL_TLS_C + * MBEDTLS_SSL_PROTO_DTLS + * + * \warning Disabling this is often a security risk! + * See mbedtls_ssl_conf_dtls_anti_replay() for details. + * + * Comment this to disable anti-replay in DTLS. + */ +//#define MBEDTLS_SSL_DTLS_ANTI_REPLAY + +/** + * \def MBEDTLS_SSL_DTLS_HELLO_VERIFY + * + * Enable support for HelloVerifyRequest on DTLS servers. + * + * This feature is highly recommended to prevent DTLS servers being used as + * amplifiers in DoS attacks against other hosts. It should always be enabled + * unless you know for sure amplification cannot be a problem in the + * environment in which your server operates. + * + * \warning Disabling this can ba a security risk! (see above) + * + * Requires: MBEDTLS_SSL_PROTO_DTLS + * + * Comment this to disable support for HelloVerifyRequest. + */ +//#define MBEDTLS_SSL_DTLS_HELLO_VERIFY + +/** + * \def MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE + * + * Enable server-side support for clients that reconnect from the same port. + * + * Some clients unexpectedly close the connection and try to reconnect using the + * same source port. This needs special support from the server to handle the + * new connection securely, as described in section 4.2.8 of RFC 6347. This + * flag enables that support. + * + * Requires: MBEDTLS_SSL_DTLS_HELLO_VERIFY + * + * Comment this to disable support for clients reusing the source port. + */ +//#define MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE + +/** + * \def MBEDTLS_SSL_DTLS_BADMAC_LIMIT + * + * Enable support for a limit of records with bad MAC. + * + * See mbedtls_ssl_conf_dtls_badmac_limit(). + * + * Requires: MBEDTLS_SSL_PROTO_DTLS + */ +//#define MBEDTLS_SSL_DTLS_BADMAC_LIMIT + +/** + * \def MBEDTLS_SSL_SESSION_TICKETS + * + * Enable support for RFC 5077 session tickets in SSL. + * Client-side, provides full support for session tickets (maintenance of a + * session store remains the responsibility of the application, though). + * Server-side, you also need to provide callbacks for writing and parsing + * tickets, including authenticated encryption and key management. Example + * callbacks are provided by MBEDTLS_SSL_TICKET_C. + * + * Comment this macro to disable support for SSL session tickets + */ +//#define MBEDTLS_SSL_SESSION_TICKETS + +/** + * \def MBEDTLS_SSL_EXPORT_KEYS + * + * Enable support for exporting key block and master secret. + * This is required for certain users of TLS, e.g. EAP-TLS. + * + * Comment this macro to disable support for key export + */ +//#define MBEDTLS_SSL_EXPORT_KEYS + +/** + * \def MBEDTLS_SSL_SERVER_NAME_INDICATION + * + * Enable support for RFC 6066 server name indication (SNI) in SSL. + * + * Requires: MBEDTLS_X509_CRT_PARSE_C + * + * Comment this macro to disable support for server name indication in SSL + */ +//#define MBEDTLS_SSL_SERVER_NAME_INDICATION + +/** + * \def MBEDTLS_SSL_TRUNCATED_HMAC + * + * Enable support for RFC 6066 truncated HMAC in SSL. + * + * Comment this macro to disable support for truncated HMAC in SSL + */ +//#define MBEDTLS_SSL_TRUNCATED_HMAC + +/** + * \def MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT + * + * Fallback to old (pre-2.7), non-conforming implementation of the truncated + * HMAC extension which also truncates the HMAC key. Note that this option is + * only meant for a transitory upgrade period and will be removed in a future + * version of the library. + * + * \warning The old implementation is non-compliant and has a security weakness + * (2^80 brute force attack on the HMAC key used for a single, + * uninterrupted connection). This should only be enabled temporarily + * when (1) the use of truncated HMAC is essential in order to save + * bandwidth, and (2) the peer is an Mbed TLS stack that doesn't use + * the fixed implementation yet (pre-2.7). + * + * \deprecated This option is deprecated and will be removed in a + * future version of Mbed TLS. + * + * Uncomment to fallback to old, non-compliant truncated HMAC implementation. + * + * Requires: MBEDTLS_SSL_TRUNCATED_HMAC + */ +//#define MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT + +/** + * \def MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH + * + * Enable modifying the maximum I/O buffer size. + */ +//#define MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH + +/** + * \def MBEDTLS_TEST_HOOKS + * + * Enable features for invasive testing such as introspection functions and + * hooks for fault injection. This enables additional unit tests. + * + * Merely enabling this feature should not change the behavior of the product. + * It only adds new code, and new branching points where the default behavior + * is the same as when this feature is disabled. + * However, this feature increases the attack surface: there is an added + * risk of vulnerabilities, and more gadgets that can make exploits easier. + * Therefore this feature must never be enabled in production. + * + * See `docs/architecture/testing/mbed-crypto-invasive-testing.md` for more + * information. + * + * Uncomment to enable invasive tests. + */ +//#define MBEDTLS_TEST_HOOKS + +/** + * \def MBEDTLS_THREADING_ALT + * + * Provide your own alternate threading implementation. + * + * Requires: MBEDTLS_THREADING_C + * + * Uncomment this to allow your own alternate threading implementation. + */ +//#define MBEDTLS_THREADING_ALT + +/** + * \def MBEDTLS_THREADING_PTHREAD + * + * Enable the pthread wrapper layer for the threading layer. + * + * Requires: MBEDTLS_THREADING_C + * + * Uncomment this to enable pthread mutexes. + */ +//#define MBEDTLS_THREADING_PTHREAD + +/** + * \def MBEDTLS_USE_PSA_CRYPTO + * + * Make the X.509 and TLS library use PSA for cryptographic operations, and + * enable new APIs for using keys handled by PSA Crypto. + * + * \note Development of this option is currently in progress, and parts of Mbed + * TLS's X.509 and TLS modules are not ported to PSA yet. However, these parts + * will still continue to work as usual, so enabling this option should not + * break backwards compatibility. + * + * \warning The PSA Crypto API is in beta stage. While you're welcome to + * experiment using it, incompatible API changes are still possible, and some + * parts may not have reached the same quality as the rest of Mbed TLS yet. + * + * \warning This option enables new Mbed TLS APIs that are dependent on the + * PSA Crypto API, so can't come with the same stability guarantees as the + * rest of the Mbed TLS APIs. You're welcome to experiment with them, but for + * now, access to these APIs is opt-in (via enabling the present option), in + * order to clearly differentiate them from the stable Mbed TLS APIs. + * + * Requires: MBEDTLS_PSA_CRYPTO_C. + * + * Uncomment this to enable internal use of PSA Crypto and new associated APIs. + */ +//#define MBEDTLS_USE_PSA_CRYPTO + +/** + * \def MBEDTLS_VERSION_FEATURES + * + * Allow run-time checking of compile-time enabled features. Thus allowing users + * to check at run-time if the library is for instance compiled with threading + * support via mbedtls_version_check_feature(). + * + * Requires: MBEDTLS_VERSION_C + * + * Comment this to disable run-time checking and save ROM space + */ +//#define MBEDTLS_VERSION_FEATURES + +/** + * \def MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 + * + * If set, the X509 parser will not break-off when parsing an X509 certificate + * and encountering an extension in a v1 or v2 certificate. + * + * Uncomment to prevent an error. + */ +//#define MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 + +/** + * \def MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION + * + * If set, the X509 parser will not break-off when parsing an X509 certificate + * and encountering an unknown critical extension. + * + * \warning Depending on your PKI use, enabling this can be a security risk! + * + * Uncomment to prevent an error. + */ +//#define MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION + +/** + * \def MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK + * + * If set, this enables the X.509 API `mbedtls_x509_crt_verify_with_ca_cb()` + * and the SSL API `mbedtls_ssl_conf_ca_cb()` which allow users to configure + * the set of trusted certificates through a callback instead of a linked + * list. + * + * This is useful for example in environments where a large number of trusted + * certificates is present and storing them in a linked list isn't efficient + * enough, or when the set of trusted certificates changes frequently. + * + * See the documentation of `mbedtls_x509_crt_verify_with_ca_cb()` and + * `mbedtls_ssl_conf_ca_cb()` for more information. + * + * Uncomment to enable trusted certificate callbacks. + */ +//#define MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK + +/** + * \def MBEDTLS_X509_CHECK_KEY_USAGE + * + * Enable verification of the keyUsage extension (CA and leaf certificates). + * + * Disabling this avoids problems with mis-issued and/or misused + * (intermediate) CA and leaf certificates. + * + * \warning Depending on your PKI use, disabling this can be a security risk! + * + * Comment to skip keyUsage checking for both CA and leaf certificates. + */ +//#define MBEDTLS_X509_CHECK_KEY_USAGE + +/** + * \def MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE + * + * Enable verification of the extendedKeyUsage extension (leaf certificates). + * + * Disabling this avoids problems with mis-issued and/or misused certificates. + * + * \warning Depending on your PKI use, disabling this can be a security risk! + * + * Comment to skip extendedKeyUsage checking for certificates. + */ +//#define MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE + +/** + * \def MBEDTLS_X509_RSASSA_PSS_SUPPORT + * + * Enable parsing and verification of X.509 certificates, CRLs and CSRS + * signed with RSASSA-PSS (aka PKCS#1 v2.1). + * + * Comment this macro to disallow using RSASSA-PSS in certificates. + */ +//#define MBEDTLS_X509_RSASSA_PSS_SUPPORT + +/** + * \def MBEDTLS_ZLIB_SUPPORT + * + * If set, the SSL/TLS module uses ZLIB to support compression and + * decompression of packet data. + * + * \warning TLS-level compression MAY REDUCE SECURITY! See for example the + * CRIME attack. Before enabling this option, you should examine with care if + * CRIME or similar exploits may be applicable to your use case. + * + * \note Currently compression can't be used with DTLS. + * + * \deprecated This feature is deprecated and will be removed + * in the next major revision of the library. + * + * Used in: library/ssl_tls.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * This feature requires zlib library and headers to be present. + * + * Uncomment to enable use of ZLIB + */ +//#define MBEDTLS_ZLIB_SUPPORT +/* \} name SECTION: mbed TLS feature support */ + +/** + * \name SECTION: mbed TLS modules + * + * This section enables or disables entire modules in mbed TLS + * \{ + */ + +/** + * \def MBEDTLS_AESNI_C + * + * Enable AES-NI support on x86-64. + * + * Module: library/aesni.c + * Caller: library/aes.c + * + * Requires: MBEDTLS_HAVE_ASM + * + * This modules adds support for the AES-NI instructions on x86-64 + */ +//#define MBEDTLS_AESNI_C + +/** + * \def MBEDTLS_AES_C + * + * Enable the AES block cipher. + * + * Module: library/aes.c + * Caller: library/cipher.c + * library/pem.c + * library/ctr_drbg.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA + * + * PEM_PARSE uses AES for decrypting encrypted keys. + */ +//#define MBEDTLS_AES_C + +/** + * \def MBEDTLS_ARC4_C + * + * Enable the ARCFOUR stream cipher. + * + * Module: library/arc4.c + * Caller: library/cipher.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA + * MBEDTLS_TLS_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 + * MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA + * MBEDTLS_TLS_PSK_WITH_RC4_128_SHA + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. If possible, we recommend avoidng dependencies on + * it, and considering stronger ciphers instead. + * + */ +//#define MBEDTLS_ARC4_C + +/** + * \def MBEDTLS_ASN1_PARSE_C + * + * Enable the generic ASN1 parser. + * + * Module: library/asn1.c + * Caller: library/x509.c + * library/dhm.c + * library/pkcs12.c + * library/pkcs5.c + * library/pkparse.c + */ +//#define MBEDTLS_ASN1_PARSE_C + +/** + * \def MBEDTLS_ASN1_WRITE_C + * + * Enable the generic ASN1 writer. + * + * Module: library/asn1write.c + * Caller: library/ecdsa.c + * library/pkwrite.c + * library/x509_create.c + * library/x509write_crt.c + * library/x509write_csr.c + */ +//#define MBEDTLS_ASN1_WRITE_C + +/** + * \def MBEDTLS_BASE64_C + * + * Enable the Base64 module. + * + * Module: library/base64.c + * Caller: library/pem.c + * + * This module is required for PEM support (required by X.509). + */ +//#define MBEDTLS_BASE64_C + +/** + * \def MBEDTLS_BIGNUM_C + * + * Enable the multi-precision integer library. + * + * Module: library/bignum.c + * Caller: library/dhm.c + * library/ecp.c + * library/ecdsa.c + * library/rsa.c + * library/rsa_internal.c + * library/ssl_tls.c + * + * This module is required for RSA, DHM and ECC (ECDH, ECDSA) support. + */ +//#define MBEDTLS_BIGNUM_C + +/** + * \def MBEDTLS_BLOWFISH_C + * + * Enable the Blowfish block cipher. + * + * Module: library/blowfish.c + */ +//#define MBEDTLS_BLOWFISH_C + +/** + * \def MBEDTLS_CAMELLIA_C + * + * Enable the Camellia block cipher. + * + * Module: library/camellia.c + * Caller: library/cipher.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 + */ +//#define MBEDTLS_CAMELLIA_C + +/** + * \def MBEDTLS_ARIA_C + * + * Enable the ARIA block cipher. + * + * Module: library/aria.c + * Caller: library/cipher.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * + * MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 + */ +//#define MBEDTLS_ARIA_C + +/** + * \def MBEDTLS_CCM_C + * + * Enable the Counter with CBC-MAC (CCM) mode for 128-bit block cipher. + * + * Module: library/ccm.c + * + * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C + * + * This module enables the AES-CCM ciphersuites, if other requisites are + * enabled as well. + */ +//#define MBEDTLS_CCM_C + +/** + * \def MBEDTLS_CERTS_C + * + * Enable the test certificates. + * + * Module: library/certs.c + * Caller: + * + * This module is used for testing (ssl_client/server). + */ +//#define MBEDTLS_CERTS_C + +/** + * \def MBEDTLS_CHACHA20_C + * + * Enable the ChaCha20 stream cipher. + * + * Module: library/chacha20.c + */ +//#define MBEDTLS_CHACHA20_C + +/** + * \def MBEDTLS_CHACHAPOLY_C + * + * Enable the ChaCha20-Poly1305 AEAD algorithm. + * + * Module: library/chachapoly.c + * + * This module requires: MBEDTLS_CHACHA20_C, MBEDTLS_POLY1305_C + */ +//#define MBEDTLS_CHACHAPOLY_C + +/** + * \def MBEDTLS_CIPHER_C + * + * Enable the generic cipher layer. + * + * Module: library/cipher.c + * Caller: library/ssl_tls.c + * + * Uncomment to enable generic cipher wrappers. + */ +//#define MBEDTLS_CIPHER_C + +/** + * \def MBEDTLS_CMAC_C + * + * Enable the CMAC (Cipher-based Message Authentication Code) mode for block + * ciphers. + * + * Module: library/cmac.c + * + * Requires: MBEDTLS_AES_C or MBEDTLS_DES_C + * + */ +//#define MBEDTLS_CMAC_C + +/** + * \def MBEDTLS_CTR_DRBG_C + * + * Enable the CTR_DRBG AES-based random generator. + * The CTR_DRBG generator uses AES-256 by default. + * To use AES-128 instead, enable \c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY above. + * + * \note To achieve a 256-bit security strength with CTR_DRBG, + * you must use AES-256 *and* use sufficient entropy. + * See ctr_drbg.h for more details. + * + * Module: library/ctr_drbg.c + * Caller: + * + * Requires: MBEDTLS_AES_C + * + * This module provides the CTR_DRBG AES random number generator. + */ +//#define MBEDTLS_CTR_DRBG_C + +/** + * \def MBEDTLS_DEBUG_C + * + * Enable the debug functions. + * + * Module: library/debug.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * This module provides debugging functions. + */ +//#define MBEDTLS_DEBUG_C + +/** + * \def MBEDTLS_DES_C + * + * Enable the DES block cipher. + * + * Module: library/des.c + * Caller: library/pem.c + * library/cipher.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA + * + * PEM_PARSE uses DES/3DES for decrypting encrypted keys. + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers instead. + */ +//#define MBEDTLS_DES_C + +/** + * \def MBEDTLS_DHM_C + * + * Enable the Diffie-Hellman-Merkle module. + * + * Module: library/dhm.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * This module is used by the following key exchanges: + * DHE-RSA, DHE-PSK + * + * \warning Using DHE constitutes a security risk as it + * is not possible to validate custom DH parameters. + * If possible, it is recommended users should consider + * preferring other methods of key exchange. + * See dhm.h for more details. + * + */ +//#define MBEDTLS_DHM_C + +/** + * \def MBEDTLS_ECDH_C + * + * Enable the elliptic curve Diffie-Hellman library. + * + * Module: library/ecdh.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * This module is used by the following key exchanges: + * ECDHE-ECDSA, ECDHE-RSA, DHE-PSK + * + * Requires: MBEDTLS_ECP_C + */ +//#define MBEDTLS_ECDH_C + +/** + * \def MBEDTLS_ECDSA_C + * + * Enable the elliptic curve DSA library. + * + * Module: library/ecdsa.c + * Caller: + * + * This module is used by the following key exchanges: + * ECDHE-ECDSA + * + * Requires: MBEDTLS_ECP_C, MBEDTLS_ASN1_WRITE_C, MBEDTLS_ASN1_PARSE_C + */ +//#define MBEDTLS_ECDSA_C + +/** + * \def MBEDTLS_ECJPAKE_C + * + * Enable the elliptic curve J-PAKE library. + * + * \warning This is currently experimental. EC J-PAKE support is based on the + * Thread v1.0.0 specification; incompatible changes to the specification + * might still happen. For this reason, this is disabled by default. + * + * Module: library/ecjpake.c + * Caller: + * + * This module is used by the following key exchanges: + * ECJPAKE + * + * Requires: MBEDTLS_ECP_C, MBEDTLS_MD_C + */ +//#define MBEDTLS_ECJPAKE_C + +/** + * \def MBEDTLS_ECP_C + * + * Enable the elliptic curve over GF(p) library. + * + * Module: library/ecp.c + * Caller: library/ecdh.c + * library/ecdsa.c + * library/ecjpake.c + * + * Requires: MBEDTLS_BIGNUM_C and at least one MBEDTLS_ECP_DP_XXX_ENABLED + */ +//#define MBEDTLS_ECP_C + +/** + * \def MBEDTLS_ENTROPY_C + * + * Enable the platform-specific entropy code. + * + * Module: library/entropy.c + * Caller: + * + * Requires: MBEDTLS_SHA512_C or MBEDTLS_SHA256_C + * + * This module provides a generic entropy pool + */ +//#define MBEDTLS_ENTROPY_C + +/** + * \def MBEDTLS_ERROR_C + * + * Enable error code to error string conversion. + * + * Module: library/error.c + * Caller: + * + * This module enables mbedtls_strerror(). + */ +//#define MBEDTLS_ERROR_C + +/** + * \def MBEDTLS_GCM_C + * + * Enable the Galois/Counter Mode (GCM). + * + * Module: library/gcm.c + * + * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C or MBEDTLS_ARIA_C + * + * This module enables the AES-GCM and CAMELLIA-GCM ciphersuites, if other + * requisites are enabled as well. + */ +//#define MBEDTLS_GCM_C + +/** + * \def MBEDTLS_HAVEGE_C + * + * Enable the HAVEGE random generator. + * + * Warning: the HAVEGE random generator is not suitable for virtualized + * environments + * + * Warning: the HAVEGE random generator is dependent on timing and specific + * processor traits. It is therefore not advised to use HAVEGE as + * your applications primary random generator or primary entropy pool + * input. As a secondary input to your entropy pool, it IS able add + * the (limited) extra entropy it provides. + * + * Module: library/havege.c + * Caller: + * + * Requires: MBEDTLS_TIMING_C + * + * Uncomment to enable the HAVEGE random generator. + */ +//#define MBEDTLS_HAVEGE_C + +/** + * \def MBEDTLS_HKDF_C + * + * Enable the HKDF algorithm (RFC 5869). + * + * Module: library/hkdf.c + * Caller: + * + * Requires: MBEDTLS_MD_C + * + * This module adds support for the Hashed Message Authentication Code + * (HMAC)-based key derivation function (HKDF). + */ +//#define MBEDTLS_HKDF_C + +/** + * \def MBEDTLS_HMAC_DRBG_C + * + * Enable the HMAC_DRBG random generator. + * + * Module: library/hmac_drbg.c + * Caller: + * + * Requires: MBEDTLS_MD_C + * + * Uncomment to enable the HMAC_DRBG random number geerator. + */ +//#define MBEDTLS_HMAC_DRBG_C + +/** + * \def MBEDTLS_NIST_KW_C + * + * Enable the Key Wrapping mode for 128-bit block ciphers, + * as defined in NIST SP 800-38F. Only KW and KWP modes + * are supported. At the moment, only AES is approved by NIST. + * + * Module: library/nist_kw.c + * + * Requires: MBEDTLS_AES_C and MBEDTLS_CIPHER_C + */ +//#define MBEDTLS_NIST_KW_C + +/** + * \def MBEDTLS_MD_C + * + * Enable the generic message digest layer. + * + * Module: library/md.c + * Caller: + * + * Uncomment to enable generic message digest wrappers. + */ +#define MBEDTLS_MD_C + +/** + * \def MBEDTLS_MD2_C + * + * Enable the MD2 hash algorithm. + * + * Module: library/md2.c + * Caller: + * + * Uncomment to enable support for (rare) MD2-signed X.509 certs. + * + * \warning MD2 is considered a weak message digest and its use constitutes a + * security risk. If possible, we recommend avoiding dependencies on + * it, and considering stronger message digests instead. + * + */ +//#define MBEDTLS_MD2_C + +/** + * \def MBEDTLS_MD4_C + * + * Enable the MD4 hash algorithm. + * + * Module: library/md4.c + * Caller: + * + * Uncomment to enable support for (rare) MD4-signed X.509 certs. + * + * \warning MD4 is considered a weak message digest and its use constitutes a + * security risk. If possible, we recommend avoiding dependencies on + * it, and considering stronger message digests instead. + * + */ +//#define MBEDTLS_MD4_C + +/** + * \def MBEDTLS_MD5_C + * + * Enable the MD5 hash algorithm. + * + * Module: library/md5.c + * Caller: library/md.c + * library/pem.c + * library/ssl_tls.c + * + * This module is required for SSL/TLS up to version 1.1, and for TLS 1.2 + * depending on the handshake parameters. Further, it is used for checking + * MD5-signed certificates, and for PBKDF1 when decrypting PEM-encoded + * encrypted keys. + * + * \warning MD5 is considered a weak message digest and its use constitutes a + * security risk. If possible, we recommend avoiding dependencies on + * it, and considering stronger message digests instead. + * + */ +//#define MBEDTLS_MD5_C + +/** + * \def MBEDTLS_MEMORY_BUFFER_ALLOC_C + * + * Enable the buffer allocator implementation that makes use of a (stack) + * based buffer to 'allocate' dynamic memory. (replaces calloc() and free() + * calls) + * + * Module: library/memory_buffer_alloc.c + * + * Requires: MBEDTLS_PLATFORM_C + * MBEDTLS_PLATFORM_MEMORY (to use it within mbed TLS) + * + * Enable this module to enable the buffer memory allocator. + */ +//#define MBEDTLS_MEMORY_BUFFER_ALLOC_C + +/** + * \def MBEDTLS_NET_C + * + * Enable the TCP and UDP over IPv6/IPv4 networking routines. + * + * \note This module only works on POSIX/Unix (including Linux, BSD and OS X) + * and Windows. For other platforms, you'll want to disable it, and write your + * own networking callbacks to be passed to \c mbedtls_ssl_set_bio(). + * + * \note See also our Knowledge Base article about porting to a new + * environment: + * https://tls.mbed.org/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS + * + * Module: library/net_sockets.c + * + * This module provides networking routines. + */ +//#define MBEDTLS_NET_C + +/** + * \def MBEDTLS_OID_C + * + * Enable the OID database. + * + * Module: library/oid.c + * Caller: library/asn1write.c + * library/pkcs5.c + * library/pkparse.c + * library/pkwrite.c + * library/rsa.c + * library/x509.c + * library/x509_create.c + * library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * library/x509write_crt.c + * library/x509write_csr.c + * + * This modules translates between OIDs and internal values. + */ +//#define MBEDTLS_OID_C + +/** + * \def MBEDTLS_PADLOCK_C + * + * Enable VIA Padlock support on x86. + * + * Module: library/padlock.c + * Caller: library/aes.c + * + * Requires: MBEDTLS_HAVE_ASM + * + * This modules adds support for the VIA PadLock on x86. + */ +//#define MBEDTLS_PADLOCK_C + +/** + * \def MBEDTLS_PEM_PARSE_C + * + * Enable PEM decoding / parsing. + * + * Module: library/pem.c + * Caller: library/dhm.c + * library/pkparse.c + * library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * + * Requires: MBEDTLS_BASE64_C + * + * This modules adds support for decoding / parsing PEM files. + */ +//#define MBEDTLS_PEM_PARSE_C + +/** + * \def MBEDTLS_PEM_WRITE_C + * + * Enable PEM encoding / writing. + * + * Module: library/pem.c + * Caller: library/pkwrite.c + * library/x509write_crt.c + * library/x509write_csr.c + * + * Requires: MBEDTLS_BASE64_C + * + * This modules adds support for encoding / writing PEM files. + */ +//#define MBEDTLS_PEM_WRITE_C + +/** + * \def MBEDTLS_PK_C + * + * Enable the generic public (asymetric) key layer. + * + * Module: library/pk.c + * Caller: library/ssl_tls.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * Requires: MBEDTLS_RSA_C or MBEDTLS_ECP_C + * + * Uncomment to enable generic public key wrappers. + */ +//#define MBEDTLS_PK_C + +/** + * \def MBEDTLS_PK_PARSE_C + * + * Enable the generic public (asymetric) key parser. + * + * Module: library/pkparse.c + * Caller: library/x509_crt.c + * library/x509_csr.c + * + * Requires: MBEDTLS_PK_C + * + * Uncomment to enable generic public key parse functions. + */ +//#define MBEDTLS_PK_PARSE_C + +/** + * \def MBEDTLS_PK_WRITE_C + * + * Enable the generic public (asymetric) key writer. + * + * Module: library/pkwrite.c + * Caller: library/x509write.c + * + * Requires: MBEDTLS_PK_C + * + * Uncomment to enable generic public key write functions. + */ +//#define MBEDTLS_PK_WRITE_C + +/** + * \def MBEDTLS_PKCS5_C + * + * Enable PKCS#5 functions. + * + * Module: library/pkcs5.c + * + * Requires: MBEDTLS_MD_C + * + * This module adds support for the PKCS#5 functions. + */ +#define MBEDTLS_PKCS5_C + +/** + * \def MBEDTLS_PKCS11_C + * + * Enable wrapper for PKCS#11 smartcard support via the pkcs11-helper library. + * + * \deprecated This option is deprecated and will be removed in a future + * version of Mbed TLS. + * + * Module: library/pkcs11.c + * Caller: library/pk.c + * + * Requires: MBEDTLS_PK_C + * + * This module enables SSL/TLS PKCS #11 smartcard support. + * Requires the presence of the PKCS#11 helper library (libpkcs11-helper) + */ +//#define MBEDTLS_PKCS11_C + +/** + * \def MBEDTLS_PKCS12_C + * + * Enable PKCS#12 PBE functions. + * Adds algorithms for parsing PKCS#8 encrypted private keys + * + * Module: library/pkcs12.c + * Caller: library/pkparse.c + * + * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_CIPHER_C, MBEDTLS_MD_C + * Can use: MBEDTLS_ARC4_C + * + * This module enables PKCS#12 functions. + */ +//#define MBEDTLS_PKCS12_C + +/** + * \def MBEDTLS_PLATFORM_C + * + * Enable the platform abstraction layer that allows you to re-assign + * functions like calloc(), free(), snprintf(), printf(), fprintf(), exit(). + * + * Enabling MBEDTLS_PLATFORM_C enables to use of MBEDTLS_PLATFORM_XXX_ALT + * or MBEDTLS_PLATFORM_XXX_MACRO directives, allowing the functions mentioned + * above to be specified at runtime or compile time respectively. + * + * \note This abstraction layer must be enabled on Windows (including MSYS2) + * as other module rely on it for a fixed snprintf implementation. + * + * Module: library/platform.c + * Caller: Most other .c files + * + * This module enables abstraction of common (libc) functions. + */ +//#define MBEDTLS_PLATFORM_C + +/** + * \def MBEDTLS_POLY1305_C + * + * Enable the Poly1305 MAC algorithm. + * + * Module: library/poly1305.c + * Caller: library/chachapoly.c + */ +//#define MBEDTLS_POLY1305_C + +/** + * \def MBEDTLS_PSA_CRYPTO_C + * + * Enable the Platform Security Architecture cryptography API. + * + * \warning The PSA Crypto API is still beta status. While you're welcome to + * experiment using it, incompatible API changes are still possible, and some + * parts may not have reached the same quality as the rest of Mbed TLS yet. + * + * Module: library/psa_crypto.c + * + * Requires: MBEDTLS_CTR_DRBG_C, MBEDTLS_ENTROPY_C + * + */ +//#define MBEDTLS_PSA_CRYPTO_C + +/** + * \def MBEDTLS_PSA_CRYPTO_SE_C + * + * Enable secure element support in the Platform Security Architecture + * cryptography API. + * + * \warning This feature is not yet suitable for production. It is provided + * for API evaluation and testing purposes only. + * + * Module: library/psa_crypto_se.c + * + * Requires: MBEDTLS_PSA_CRYPTO_C, MBEDTLS_PSA_CRYPTO_STORAGE_C + * + */ +//#define MBEDTLS_PSA_CRYPTO_SE_C + +/** + * \def MBEDTLS_PSA_CRYPTO_STORAGE_C + * + * Enable the Platform Security Architecture persistent key storage. + * + * Module: library/psa_crypto_storage.c + * + * Requires: MBEDTLS_PSA_CRYPTO_C, + * either MBEDTLS_PSA_ITS_FILE_C or a native implementation of + * the PSA ITS interface + */ +//#define MBEDTLS_PSA_CRYPTO_STORAGE_C + +/** + * \def MBEDTLS_PSA_ITS_FILE_C + * + * Enable the emulation of the Platform Security Architecture + * Internal Trusted Storage (PSA ITS) over files. + * + * Module: library/psa_its_file.c + * + * Requires: MBEDTLS_FS_IO + */ +//#define MBEDTLS_PSA_ITS_FILE_C + +/** + * \def MBEDTLS_RIPEMD160_C + * + * Enable the RIPEMD-160 hash algorithm. + * + * Module: library/ripemd160.c + * Caller: library/md.c + * + */ +//#define MBEDTLS_RIPEMD160_C + +/** + * \def MBEDTLS_RSA_C + * + * Enable the RSA public-key cryptosystem. + * + * Module: library/rsa.c + * library/rsa_internal.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * library/x509.c + * + * This module is used by the following key exchanges: + * RSA, DHE-RSA, ECDHE-RSA, RSA-PSK + * + * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C + */ +//#define MBEDTLS_RSA_C + +/** + * \def MBEDTLS_SHA1_C + * + * Enable the SHA1 cryptographic hash algorithm. + * + * Module: library/sha1.c + * Caller: library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * library/x509write_crt.c + * + * This module is required for SSL/TLS up to version 1.1, for TLS 1.2 + * depending on the handshake parameters, and for SHA1-signed certificates. + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. If possible, we recommend avoiding dependencies + * on it, and considering stronger message digests instead. + * + */ +//#define MBEDTLS_SHA1_C + +/** + * \def MBEDTLS_SHA256_C + * + * Enable the SHA-224 and SHA-256 cryptographic hash algorithms. + * + * Module: library/sha256.c + * Caller: library/entropy.c + * library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * This module adds support for SHA-224 and SHA-256. + * This module is required for the SSL/TLS 1.2 PRF function. + */ +#define MBEDTLS_SHA256_C + +/** + * \def MBEDTLS_SHA512_C + * + * Enable the SHA-384 and SHA-512 cryptographic hash algorithms. + * + * Module: library/sha512.c + * Caller: library/entropy.c + * library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * This module adds support for SHA-384 and SHA-512. + */ +//#define MBEDTLS_SHA512_C + +/** + * \def MBEDTLS_SSL_CACHE_C + * + * Enable simple SSL cache implementation. + * + * Module: library/ssl_cache.c + * Caller: + * + * Requires: MBEDTLS_SSL_CACHE_C + */ +//#define MBEDTLS_SSL_CACHE_C + +/** + * \def MBEDTLS_SSL_COOKIE_C + * + * Enable basic implementation of DTLS cookies for hello verification. + * + * Module: library/ssl_cookie.c + * Caller: + */ +//#define MBEDTLS_SSL_COOKIE_C + +/** + * \def MBEDTLS_SSL_TICKET_C + * + * Enable an implementation of TLS server-side callbacks for session tickets. + * + * Module: library/ssl_ticket.c + * Caller: + * + * Requires: MBEDTLS_CIPHER_C + */ +//#define MBEDTLS_SSL_TICKET_C + +/** + * \def MBEDTLS_SSL_CLI_C + * + * Enable the SSL/TLS client code. + * + * Module: library/ssl_cli.c + * Caller: + * + * Requires: MBEDTLS_SSL_TLS_C + * + * This module is required for SSL/TLS client support. + */ +//#define MBEDTLS_SSL_CLI_C + +/** + * \def MBEDTLS_SSL_SRV_C + * + * Enable the SSL/TLS server code. + * + * Module: library/ssl_srv.c + * Caller: + * + * Requires: MBEDTLS_SSL_TLS_C + * + * This module is required for SSL/TLS server support. + */ +//#define MBEDTLS_SSL_SRV_C + +/** + * \def MBEDTLS_SSL_TLS_C + * + * Enable the generic SSL/TLS code. + * + * Module: library/ssl_tls.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * Requires: MBEDTLS_CIPHER_C, MBEDTLS_MD_C + * and at least one of the MBEDTLS_SSL_PROTO_XXX defines + * + * This module is required for SSL/TLS. + */ +//#define MBEDTLS_SSL_TLS_C + +/** + * \def MBEDTLS_THREADING_C + * + * Enable the threading abstraction layer. + * By default mbed TLS assumes it is used in a non-threaded environment or that + * contexts are not shared between threads. If you do intend to use contexts + * between threads, you will need to enable this layer to prevent race + * conditions. See also our Knowledge Base article about threading: + * https://tls.mbed.org/kb/development/thread-safety-and-multi-threading + * + * Module: library/threading.c + * + * This allows different threading implementations (self-implemented or + * provided). + * + * You will have to enable either MBEDTLS_THREADING_ALT or + * MBEDTLS_THREADING_PTHREAD. + * + * Enable this layer to allow use of mutexes within mbed TLS + */ +//#define MBEDTLS_THREADING_C + +/** + * \def MBEDTLS_TIMING_C + * + * Enable the semi-portable timing interface. + * + * \note The provided implementation only works on POSIX/Unix (including Linux, + * BSD and OS X) and Windows. On other platforms, you can either disable that + * module and provide your own implementations of the callbacks needed by + * \c mbedtls_ssl_set_timer_cb() for DTLS, or leave it enabled and provide + * your own implementation of the whole module by setting + * \c MBEDTLS_TIMING_ALT in the current file. + * + * \note See also our Knowledge Base article about porting to a new + * environment: + * https://tls.mbed.org/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS + * + * Module: library/timing.c + * Caller: library/havege.c + * + * This module is used by the HAVEGE random number generator. + */ +//#define MBEDTLS_TIMING_C + +/** + * \def MBEDTLS_VERSION_C + * + * Enable run-time version information. + * + * Module: library/version.c + * + * This module provides run-time version information. + */ +//#define MBEDTLS_VERSION_C + +/** + * \def MBEDTLS_X509_USE_C + * + * Enable X.509 core for using certificates. + * + * Module: library/x509.c + * Caller: library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * + * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_BIGNUM_C, MBEDTLS_OID_C, + * MBEDTLS_PK_PARSE_C + * + * This module is required for the X.509 parsing modules. + */ +//#define MBEDTLS_X509_USE_C + +/** + * \def MBEDTLS_X509_CRT_PARSE_C + * + * Enable X.509 certificate parsing. + * + * Module: library/x509_crt.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * Requires: MBEDTLS_X509_USE_C + * + * This module is required for X.509 certificate parsing. + */ +//#define MBEDTLS_X509_CRT_PARSE_C + +/** + * \def MBEDTLS_X509_CRL_PARSE_C + * + * Enable X.509 CRL parsing. + * + * Module: library/x509_crl.c + * Caller: library/x509_crt.c + * + * Requires: MBEDTLS_X509_USE_C + * + * This module is required for X.509 CRL parsing. + */ +//#define MBEDTLS_X509_CRL_PARSE_C + +/** + * \def MBEDTLS_X509_CSR_PARSE_C + * + * Enable X.509 Certificate Signing Request (CSR) parsing. + * + * Module: library/x509_csr.c + * Caller: library/x509_crt_write.c + * + * Requires: MBEDTLS_X509_USE_C + * + * This module is used for reading X.509 certificate request. + */ +//#define MBEDTLS_X509_CSR_PARSE_C + +/** + * \def MBEDTLS_X509_CREATE_C + * + * Enable X.509 core for creating certificates. + * + * Module: library/x509_create.c + * + * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C, MBEDTLS_PK_WRITE_C + * + * This module is the basis for creating X.509 certificates and CSRs. + */ +//#define MBEDTLS_X509_CREATE_C + +/** + * \def MBEDTLS_X509_CRT_WRITE_C + * + * Enable creating X.509 certificates. + * + * Module: library/x509_crt_write.c + * + * Requires: MBEDTLS_X509_CREATE_C + * + * This module is required for X.509 certificate creation. + */ +//#define MBEDTLS_X509_CRT_WRITE_C + +/** + * \def MBEDTLS_X509_CSR_WRITE_C + * + * Enable creating X.509 Certificate Signing Requests (CSR). + * + * Module: library/x509_csr_write.c + * + * Requires: MBEDTLS_X509_CREATE_C + * + * This module is required for X.509 certificate request writing. + */ +//#define MBEDTLS_X509_CSR_WRITE_C + +/** + * \def MBEDTLS_XTEA_C + * + * Enable the XTEA block cipher. + * + * Module: library/xtea.c + * Caller: + */ +//#define MBEDTLS_XTEA_C + +/* \} name SECTION: mbed TLS modules */ + +/** + * \name SECTION: Module configuration options + * + * This section allows for the setting of module specific sizes and + * configuration options. The default values are already present in the + * relevant header files and should suffice for the regular use cases. + * + * Our advice is to enable options and change their values here + * only if you have a good reason and know the consequences. + * + * Please check the respective header file for documentation on these + * parameters (to prevent duplicate documentation). + * \{ + */ + +/* MPI / BIGNUM options */ +//#define MBEDTLS_MPI_WINDOW_SIZE 6 /**< Maximum windows size used. */ +//#define MBEDTLS_MPI_MAX_SIZE 1024 /**< Maximum number of bytes for usable MPIs. */ + +/* CTR_DRBG options */ +//#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 48 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */ +//#define MBEDTLS_CTR_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ +//#define MBEDTLS_CTR_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +//#define MBEDTLS_CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +//#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ + +/* HMAC_DRBG options */ +//#define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ +//#define MBEDTLS_HMAC_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +//#define MBEDTLS_HMAC_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +//#define MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ + +/* ECP options */ +//#define MBEDTLS_ECP_MAX_BITS 521 /**< Maximum bit size of groups */ +//#define MBEDTLS_ECP_WINDOW_SIZE 6 /**< Maximum window size used */ +//#define MBEDTLS_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up */ + +/* Entropy options */ +//#define MBEDTLS_ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */ +//#define MBEDTLS_ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */ +//#define MBEDTLS_ENTROPY_MIN_HARDWARE 32 /**< Default minimum number of bytes required for the hardware entropy source mbedtls_hardware_poll() before entropy is released */ + +/* Memory buffer allocator options */ +//#define MBEDTLS_MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */ + +/* Platform options */ +//#define MBEDTLS_PLATFORM_STD_MEM_HDR /**< Header to include if MBEDTLS_PLATFORM_NO_STD_FUNCTIONS is defined. Don't define if no header is needed. */ +//#define MBEDTLS_PLATFORM_STD_CALLOC calloc /**< Default allocator to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_FREE free /**< Default free to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_EXIT exit /**< Default exit to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_TIME time /**< Default time to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ +//#define MBEDTLS_PLATFORM_STD_FPRINTF fprintf /**< Default fprintf to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_PRINTF printf /**< Default printf to use, can be undefined */ +/* Note: your snprintf must correctly zero-terminate the buffer! */ +//#define MBEDTLS_PLATFORM_STD_SNPRINTF snprintf /**< Default snprintf to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_EXIT_SUCCESS 0 /**< Default exit value to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_EXIT_FAILURE 1 /**< Default exit value to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_NV_SEED_READ mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_NV_SEED_FILE "seedfile" /**< Seed file to read/write with default implementation */ + +/* To Use Function Macros MBEDTLS_PLATFORM_C must be enabled */ +/* MBEDTLS_PLATFORM_XXX_MACRO and MBEDTLS_PLATFORM_XXX_ALT cannot both be defined */ +//#define MBEDTLS_PLATFORM_CALLOC_MACRO calloc /**< Default allocator macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_FREE_MACRO free /**< Default free macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_EXIT_MACRO exit /**< Default exit macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_TIME_MACRO time /**< Default time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ +//#define MBEDTLS_PLATFORM_TIME_TYPE_MACRO time_t /**< Default time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ +//#define MBEDTLS_PLATFORM_FPRINTF_MACRO fprintf /**< Default fprintf macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_PRINTF_MACRO printf /**< Default printf macro to use, can be undefined */ +/* Note: your snprintf must correctly zero-terminate the buffer! */ +//#define MBEDTLS_PLATFORM_SNPRINTF_MACRO snprintf /**< Default snprintf macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_VSNPRINTF_MACRO vsnprintf /**< Default vsnprintf macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_NV_SEED_READ_MACRO mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */ +//#define MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */ + +/** + * \brief This macro is invoked by the library when an invalid parameter + * is detected that is only checked with #MBEDTLS_CHECK_PARAMS + * (see the documentation of that option for context). + * + * When you leave this undefined here, the library provides + * a default definition. If the macro #MBEDTLS_CHECK_PARAMS_ASSERT + * is defined, the default definition is `assert(cond)`, + * otherwise the default definition calls a function + * mbedtls_param_failed(). This function is declared in + * `platform_util.h` for the benefit of the library, but + * you need to define in your application. + * + * When you define this here, this replaces the default + * definition in platform_util.h (which no longer declares the + * function mbedtls_param_failed()) and it is your responsibility + * to make sure this macro expands to something suitable (in + * particular, that all the necessary declarations are visible + * from within the library - you can ensure that by providing + * them in this file next to the macro definition). + * If you define this macro to call `assert`, also define + * #MBEDTLS_CHECK_PARAMS_ASSERT so that library source files + * include ``. + * + * Note that you may define this macro to expand to nothing, in + * which case you don't have to worry about declarations or + * definitions. However, you will then be notified about invalid + * parameters only in non-void functions, and void function will + * just silently return early on invalid parameters, which + * partially negates the benefits of enabling + * #MBEDTLS_CHECK_PARAMS in the first place, so is discouraged. + * + * \param cond The expression that should evaluate to true, but doesn't. + */ +//#define MBEDTLS_PARAM_FAILED( cond ) assert( cond ) + +/* SSL Cache options */ +//#define MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT 86400 /**< 1 day */ +//#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /**< Maximum entries in cache */ + +/* SSL options */ + +/** \def MBEDTLS_SSL_MAX_CONTENT_LEN + * + * Maximum length (in bytes) of incoming and outgoing plaintext fragments. + * + * This determines the size of both the incoming and outgoing TLS I/O buffers + * in such a way that both are capable of holding the specified amount of + * plaintext data, regardless of the protection mechanism used. + * + * To configure incoming and outgoing I/O buffers separately, use + * #MBEDTLS_SSL_IN_CONTENT_LEN and #MBEDTLS_SSL_OUT_CONTENT_LEN, + * which overwrite the value set by this option. + * + * \note When using a value less than the default of 16KB on the client, it is + * recommended to use the Maximum Fragment Length (MFL) extension to + * inform the server about this limitation. On the server, there + * is no supported, standardized way of informing the client about + * restriction on the maximum size of incoming messages, and unless + * the limitation has been communicated by other means, it is recommended + * to only change the outgoing buffer size #MBEDTLS_SSL_OUT_CONTENT_LEN + * while keeping the default value of 16KB for the incoming buffer. + * + * Uncomment to set the maximum plaintext size of both + * incoming and outgoing I/O buffers. + */ +//#define MBEDTLS_SSL_MAX_CONTENT_LEN 16384 + +/** \def MBEDTLS_SSL_IN_CONTENT_LEN + * + * Maximum length (in bytes) of incoming plaintext fragments. + * + * This determines the size of the incoming TLS I/O buffer in such a way + * that it is capable of holding the specified amount of plaintext data, + * regardless of the protection mechanism used. + * + * If this option is undefined, it inherits its value from + * #MBEDTLS_SSL_MAX_CONTENT_LEN. + * + * \note When using a value less than the default of 16KB on the client, it is + * recommended to use the Maximum Fragment Length (MFL) extension to + * inform the server about this limitation. On the server, there + * is no supported, standardized way of informing the client about + * restriction on the maximum size of incoming messages, and unless + * the limitation has been communicated by other means, it is recommended + * to only change the outgoing buffer size #MBEDTLS_SSL_OUT_CONTENT_LEN + * while keeping the default value of 16KB for the incoming buffer. + * + * Uncomment to set the maximum plaintext size of the incoming I/O buffer + * independently of the outgoing I/O buffer. + */ +//#define MBEDTLS_SSL_IN_CONTENT_LEN 16384 + +/** \def MBEDTLS_SSL_CID_IN_LEN_MAX + * + * The maximum length of CIDs used for incoming DTLS messages. + * + */ +//#define MBEDTLS_SSL_CID_IN_LEN_MAX 32 + +/** \def MBEDTLS_SSL_CID_OUT_LEN_MAX + * + * The maximum length of CIDs used for outgoing DTLS messages. + * + */ +//#define MBEDTLS_SSL_CID_OUT_LEN_MAX 32 + +/** \def MBEDTLS_SSL_CID_PADDING_GRANULARITY + * + * This option controls the use of record plaintext padding + * when using the Connection ID extension in DTLS 1.2. + * + * The padding will always be chosen so that the length of the + * padded plaintext is a multiple of the value of this option. + * + * Note: A value of \c 1 means that no padding will be used + * for outgoing records. + * + * Note: On systems lacking division instructions, + * a power of two should be preferred. + * + */ +//#define MBEDTLS_SSL_CID_PADDING_GRANULARITY 16 + +/** \def MBEDTLS_SSL_TLS1_3_PADDING_GRANULARITY + * + * This option controls the use of record plaintext padding + * in TLS 1.3. + * + * The padding will always be chosen so that the length of the + * padded plaintext is a multiple of the value of this option. + * + * Note: A value of \c 1 means that no padding will be used + * for outgoing records. + * + * Note: On systems lacking division instructions, + * a power of two should be preferred. + */ +//#define MBEDTLS_SSL_TLS1_3_PADDING_GRANULARITY 1 + +/** \def MBEDTLS_SSL_OUT_CONTENT_LEN + * + * Maximum length (in bytes) of outgoing plaintext fragments. + * + * This determines the size of the outgoing TLS I/O buffer in such a way + * that it is capable of holding the specified amount of plaintext data, + * regardless of the protection mechanism used. + * + * If this option undefined, it inherits its value from + * #MBEDTLS_SSL_MAX_CONTENT_LEN. + * + * It is possible to save RAM by setting a smaller outward buffer, while keeping + * the default inward 16384 byte buffer to conform to the TLS specification. + * + * The minimum required outward buffer size is determined by the handshake + * protocol's usage. Handshaking will fail if the outward buffer is too small. + * The specific size requirement depends on the configured ciphers and any + * certificate data which is sent during the handshake. + * + * Uncomment to set the maximum plaintext size of the outgoing I/O buffer + * independently of the incoming I/O buffer. + */ +//#define MBEDTLS_SSL_OUT_CONTENT_LEN 16384 + +/** \def MBEDTLS_SSL_DTLS_MAX_BUFFERING + * + * Maximum number of heap-allocated bytes for the purpose of + * DTLS handshake message reassembly and future message buffering. + * + * This should be at least 9/8 * MBEDTLSSL_IN_CONTENT_LEN + * to account for a reassembled handshake message of maximum size, + * together with its reassembly bitmap. + * + * A value of 2 * MBEDTLS_SSL_IN_CONTENT_LEN (32768 by default) + * should be sufficient for all practical situations as it allows + * to reassembly a large handshake message (such as a certificate) + * while buffering multiple smaller handshake messages. + * + */ +//#define MBEDTLS_SSL_DTLS_MAX_BUFFERING 32768 + +//#define MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME 86400 /**< Lifetime of session tickets (if enabled) */ +//#define MBEDTLS_PSK_MAX_LEN 32 /**< Max size of TLS pre-shared keys, in bytes (default 256 bits) */ +//#define MBEDTLS_SSL_COOKIE_TIMEOUT 60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */ + +/** + * Complete list of ciphersuites to use, in order of preference. + * + * \warning No dependency checking is done on that field! This option can only + * be used to restrict the set of available ciphersuites. It is your + * responsibility to make sure the needed modules are active. + * + * Use this to save a few hundred bytes of ROM (default ordering of all + * available ciphersuites) and a few to a few hundred bytes of RAM. + * + * The value below is only an example, not the default. + */ +//#define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + +/* X509 options */ +//#define MBEDTLS_X509_MAX_INTERMEDIATE_CA 8 /**< Maximum number of intermediate CAs in a verification chain. */ +//#define MBEDTLS_X509_MAX_FILE_PATH_LEN 512 /**< Maximum length of a path/filename string in bytes including the null terminator character ('\0'). */ + +/** + * Allow SHA-1 in the default TLS configuration for certificate signing. + * Without this build-time option, SHA-1 support must be activated explicitly + * through mbedtls_ssl_conf_cert_profile. Turning on this option is not + * recommended because of it is possible to generate SHA-1 collisions, however + * this may be safe for legacy infrastructure where additional controls apply. + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. If possible, we recommend avoiding dependencies + * on it, and considering stronger message digests instead. + * + */ +//#define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES + +/** + * Allow SHA-1 in the default TLS configuration for TLS 1.2 handshake + * signature and ciphersuite selection. Without this build-time option, SHA-1 + * support must be activated explicitly through mbedtls_ssl_conf_sig_hashes. + * The use of SHA-1 in TLS <= 1.1 and in HMAC-SHA-1 is always allowed by + * default. At the time of writing, there is no practical attack on the use + * of SHA-1 in handshake signatures, hence this option is turned on by default + * to preserve compatibility with existing peers, but the general + * warning applies nonetheless: + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. If possible, we recommend avoiding dependencies + * on it, and considering stronger message digests instead. + * + */ +//#define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE + +/** + * Uncomment the macro to let mbed TLS use your alternate implementation of + * mbedtls_platform_zeroize(). This replaces the default implementation in + * platform_util.c. + * + * mbedtls_platform_zeroize() is a widely used function across the library to + * zero a block of memory. The implementation is expected to be secure in the + * sense that it has been written to prevent the compiler from removing calls + * to mbedtls_platform_zeroize() as part of redundant code elimination + * optimizations. However, it is difficult to guarantee that calls to + * mbedtls_platform_zeroize() will not be optimized by the compiler as older + * versions of the C language standards do not provide a secure implementation + * of memset(). Therefore, MBEDTLS_PLATFORM_ZEROIZE_ALT enables users to + * configure their own implementation of mbedtls_platform_zeroize(), for + * example by using directives specific to their compiler, features from newer + * C standards (e.g using memset_s() in C11) or calling a secure memset() from + * their system (e.g explicit_bzero() in BSD). + */ +//#define MBEDTLS_PLATFORM_ZEROIZE_ALT + +/** + * Uncomment the macro to let Mbed TLS use your alternate implementation of + * mbedtls_platform_gmtime_r(). This replaces the default implementation in + * platform_util.c. + * + * gmtime() is not a thread-safe function as defined in the C standard. The + * library will try to use safer implementations of this function, such as + * gmtime_r() when available. However, if Mbed TLS cannot identify the target + * system, the implementation of mbedtls_platform_gmtime_r() will default to + * using the standard gmtime(). In this case, calls from the library to + * gmtime() will be guarded by the global mutex mbedtls_threading_gmtime_mutex + * if MBEDTLS_THREADING_C is enabled. We recommend that calls from outside the + * library are also guarded with this mutex to avoid race conditions. However, + * if the macro MBEDTLS_PLATFORM_GMTIME_R_ALT is defined, Mbed TLS will + * unconditionally use the implementation for mbedtls_platform_gmtime_r() + * supplied at compile time. + */ +//#define MBEDTLS_PLATFORM_GMTIME_R_ALT + +/** + * Enable the verified implementations of ECDH primitives from Project Everest + * (currently only Curve25519). This feature changes the layout of ECDH + * contexts and therefore is a compatibility break for applications that access + * fields of a mbedtls_ecdh_context structure directly. See also + * MBEDTLS_ECDH_LEGACY_CONTEXT in include/mbedtls/ecdh.h. + */ +//#define MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED + +/* \} name SECTION: Customisation configuration options */ + +/* Target and application specific configurations + * + * Allow user to override any previous default. + * + */ +#if defined(MBEDTLS_USER_CONFIG_FILE) +#include MBEDTLS_USER_CONFIG_FILE +#endif + +#include "mbedtls/check_config.h" + +#endif /* MBEDTLS_CONFIG_H */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/config_psa.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/config_psa.h new file mode 100644 index 0000000..6af4d19 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/config_psa.h @@ -0,0 +1,82 @@ +/** + * \file mbedtls/config_psa.h + * \brief PSA crypto configuration options (set of defines) + * + * This set of compile-time options takes settings defined in + * include/mbedtls/config.h and include/psa/crypto_config.h and uses + * those definitions to define symbols used in the library code. + * + * Users and integrators should not edit this file, please edit + * include/mbedtls/config.h for MBETLS_XXX settings or + * include/psa/crypto_config.h for PSA_WANT_XXX settings. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_CONFIG_PSA_H +#define MBEDTLS_CONFIG_PSA_H + +#if defined(MBEDTLS_PSA_CRYPTO_CONFIG) +#include "psa/crypto_config.h" +#endif /* defined(MBEDTLS_PSA_CRYPTO_CONFIG) */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_PSA_CRYPTO_CONFIG) + +#if defined(PSA_WANT_ALG_ECDSA) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_ECDSA) +#define MBEDTLS_PSA_BUILTIN_ALG_ECDSA 1 +#define MBEDTLS_ECDSA_C +#endif /* !MBEDTLS_PSA_ACCEL_ALG_ECDSA */ +#endif /* PSA_WANT_ALG_ECDSA */ + +#if defined(PSA_WANT_ALG_DETERMINISTIC_ECDSA) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_DETERMINISTIC_ECDSA) +#define MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA 1 +#define MBEDTLS_ECDSA_DETERMINISTIC +#define MBEDTLS_ECDSA_C +#define MBEDTLS_HMAC_DRBG_C +#define MBEDTLS_MD_C +#endif /* MBEDTLS_PSA_ACCEL_ALG_DETERMINISTIC_ECDSA */ +#endif /* PSA_WANT_ALG_DETERMINISTIC_ECDSA */ + +#else /* MBEDTLS_PSA_CRYPTO_CONFIG */ + +/* + * Ensure PSA_WANT_* defines are setup properly if MBEDTLS_PSA_CRYPTO_CONFIG + * is not defined + */ +#if defined(MBEDTLS_ECDSA_C) +#define MBEDTLS_PSA_BUILTIN_ALG_ECDSA + +// Only add in DETERMINISTIC support if ECDSA is also enabled +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +#define MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ + +#endif /* MBEDTLS_ECDSA_C */ + +#endif /* MBEDTLS_PSA_CRYPTO_CONFIG */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CONFIG_PSA_H */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ctr_drbg.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ctr_drbg.h new file mode 100644 index 0000000..6c48ec1 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ctr_drbg.h @@ -0,0 +1,560 @@ +/** + * \file ctr_drbg.h + * + * \brief This file contains definitions and functions for the + * CTR_DRBG pseudorandom generator. + * + * CTR_DRBG is a standardized way of building a PRNG from a block-cipher + * in counter mode operation, as defined in NIST SP 800-90A: + * Recommendation for Random Number Generation Using Deterministic Random + * Bit Generators. + * + * The Mbed TLS implementation of CTR_DRBG uses AES-256 (default) or AES-128 + * (if \c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is enabled at compile time) + * as the underlying block cipher, with a derivation function. + * + * The security strength as defined in NIST SP 800-90A is + * 128 bits when AES-128 is used (\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY enabled) + * and 256 bits otherwise, provided that #MBEDTLS_CTR_DRBG_ENTROPY_LEN is + * kept at its default value (and not overridden in config.h) and that the + * DRBG instance is set up with default parameters. + * See the documentation of mbedtls_ctr_drbg_seed() for more + * information. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_CTR_DRBG_H +#define MBEDTLS_CTR_DRBG_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/aes.h" + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +#define MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED -0x0034 /**< The entropy source failed. */ +#define MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG -0x0036 /**< The requested random buffer length is too big. */ +#define MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG -0x0038 /**< The input (entropy + additional data) is too large. */ +#define MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR -0x003A /**< Read or write error in file. */ + +#define MBEDTLS_CTR_DRBG_BLOCKSIZE 16 /**< The block size used by the cipher. */ + +#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) +#define MBEDTLS_CTR_DRBG_KEYSIZE 16 +/**< The key size in bytes used by the cipher. + * + * Compile-time choice: 16 bytes (128 bits) + * because #MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is enabled. + */ +#else +#define MBEDTLS_CTR_DRBG_KEYSIZE 32 +/**< The key size in bytes used by the cipher. + * + * Compile-time choice: 32 bytes (256 bits) + * because \c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is disabled. + */ +#endif + +#define MBEDTLS_CTR_DRBG_KEYBITS ( MBEDTLS_CTR_DRBG_KEYSIZE * 8 ) /**< The key size for the DRBG operation, in bits. */ +#define MBEDTLS_CTR_DRBG_SEEDLEN ( MBEDTLS_CTR_DRBG_KEYSIZE + MBEDTLS_CTR_DRBG_BLOCKSIZE ) /**< The seed length, calculated as (counter + AES key). */ + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them using the compiler command + * line. + * \{ + */ + +/** \def MBEDTLS_CTR_DRBG_ENTROPY_LEN + * + * \brief The amount of entropy used per seed by default, in bytes. + */ +#if !defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) +#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) +/** This is 48 bytes because the entropy module uses SHA-512 + * (\c MBEDTLS_ENTROPY_FORCE_SHA256 is disabled). + */ +#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 48 + +#else /* defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) */ + +/** This is 32 bytes because the entropy module uses SHA-256 + * (the SHA512 module is disabled or + * \c MBEDTLS_ENTROPY_FORCE_SHA256 is enabled). + */ +#if !defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) +/** \warning To achieve a 256-bit security strength, you must pass a nonce + * to mbedtls_ctr_drbg_seed(). + */ +#endif /* !defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) */ +#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 32 +#endif /* defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) */ +#endif /* !defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) */ + +#if !defined(MBEDTLS_CTR_DRBG_RESEED_INTERVAL) +#define MBEDTLS_CTR_DRBG_RESEED_INTERVAL 10000 +/**< The interval before reseed is performed by default. */ +#endif + +#if !defined(MBEDTLS_CTR_DRBG_MAX_INPUT) +#define MBEDTLS_CTR_DRBG_MAX_INPUT 256 +/**< The maximum number of additional input Bytes. */ +#endif + +#if !defined(MBEDTLS_CTR_DRBG_MAX_REQUEST) +#define MBEDTLS_CTR_DRBG_MAX_REQUEST 1024 +/**< The maximum number of requested Bytes per call. */ +#endif + +#if !defined(MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) +#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384 +/**< The maximum size of seed or reseed buffer in bytes. */ +#endif + +/* \} name SECTION: Module settings */ + +#define MBEDTLS_CTR_DRBG_PR_OFF 0 +/**< Prediction resistance is disabled. */ +#define MBEDTLS_CTR_DRBG_PR_ON 1 +/**< Prediction resistance is enabled. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if MBEDTLS_CTR_DRBG_ENTROPY_LEN >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2 +/** The default length of the nonce read from the entropy source. + * + * This is \c 0 because a single read from the entropy source is sufficient + * to include a nonce. + * See the documentation of mbedtls_ctr_drbg_seed() for more information. + */ +#define MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN 0 +#else +/** The default length of the nonce read from the entropy source. + * + * This is half of the default entropy length because a single read from + * the entropy source does not provide enough material to form a nonce. + * See the documentation of mbedtls_ctr_drbg_seed() for more information. + */ +#define MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN ( MBEDTLS_CTR_DRBG_ENTROPY_LEN + 1 ) / 2 +#endif + +/** + * \brief The CTR_DRBG context structure. + */ +typedef struct mbedtls_ctr_drbg_context +{ + unsigned char counter[16]; /*!< The counter (V). */ + int reseed_counter; /*!< The reseed counter. + * This is the number of requests that have + * been made since the last (re)seeding, + * minus one. + * Before the initial seeding, this field + * contains the amount of entropy in bytes + * to use as a nonce for the initial seeding, + * or -1 if no nonce length has been explicitly + * set (see mbedtls_ctr_drbg_set_nonce_len()). + */ + int prediction_resistance; /*!< This determines whether prediction + resistance is enabled, that is + whether to systematically reseed before + each random generation. */ + size_t entropy_len; /*!< The amount of entropy grabbed on each + seed or reseed operation, in bytes. */ + int reseed_interval; /*!< The reseed interval. + * This is the maximum number of requests + * that can be made between reseedings. */ + + mbedtls_aes_context aes_ctx; /*!< The AES context. */ + + /* + * Callbacks (Entropy) + */ + int (*f_entropy)(void *, unsigned char *, size_t); + /*!< The entropy callback function. */ + + void *p_entropy; /*!< The context for the entropy function. */ + +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; +#endif +} +mbedtls_ctr_drbg_context; + +/** + * \brief This function initializes the CTR_DRBG context, + * and prepares it for mbedtls_ctr_drbg_seed() + * or mbedtls_ctr_drbg_free(). + * + * \param ctx The CTR_DRBG context to initialize. + */ +void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ); + +/** + * \brief This function seeds and sets up the CTR_DRBG + * entropy source for future reseeds. + * + * A typical choice for the \p f_entropy and \p p_entropy parameters is + * to use the entropy module: + * - \p f_entropy is mbedtls_entropy_func(); + * - \p p_entropy is an instance of ::mbedtls_entropy_context initialized + * with mbedtls_entropy_init() (which registers the platform's default + * entropy sources). + * + * The entropy length is #MBEDTLS_CTR_DRBG_ENTROPY_LEN by default. + * You can override it by calling mbedtls_ctr_drbg_set_entropy_len(). + * + * The entropy nonce length is: + * - \c 0 if the entropy length is at least 3/2 times the entropy length, + * which guarantees that the security strength is the maximum permitted + * by the key size and entropy length according to NIST SP 800-90A §10.2.1; + * - Half the entropy length otherwise. + * You can override it by calling mbedtls_ctr_drbg_set_nonce_len(). + * With the default entropy length, the entropy nonce length is + * #MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN. + * + * You can provide a nonce and personalization string in addition to the + * entropy source, to make this instantiation as unique as possible. + * See SP 800-90A §8.6.7 for more details about nonces. + * + * The _seed_material_ value passed to the derivation function in + * the CTR_DRBG Instantiate Process described in NIST SP 800-90A §10.2.1.3.2 + * is the concatenation of the following strings: + * - A string obtained by calling \p f_entropy function for the entropy + * length. + */ +#if MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN == 0 +/** + * - If mbedtls_ctr_drbg_set_nonce_len() has been called, a string + * obtained by calling \p f_entropy function for the specified length. + */ +#else +/** + * - A string obtained by calling \p f_entropy function for the entropy nonce + * length. If the entropy nonce length is \c 0, this function does not + * make a second call to \p f_entropy. + */ +#endif +/** + * - The \p custom string. + * + * \note To achieve the nominal security strength permitted + * by CTR_DRBG, the entropy length must be: + * - at least 16 bytes for a 128-bit strength + * (maximum achievable strength when using AES-128); + * - at least 32 bytes for a 256-bit strength + * (maximum achievable strength when using AES-256). + * + * In addition, if you do not pass a nonce in \p custom, + * the sum of the entropy length + * and the entropy nonce length must be: + * - at least 24 bytes for a 128-bit strength + * (maximum achievable strength when using AES-128); + * - at least 48 bytes for a 256-bit strength + * (maximum achievable strength when using AES-256). + * + * \param ctx The CTR_DRBG context to seed. + * It must have been initialized with + * mbedtls_ctr_drbg_init(). + * After a successful call to mbedtls_ctr_drbg_seed(), + * you may not call mbedtls_ctr_drbg_seed() again on + * the same context unless you call + * mbedtls_ctr_drbg_free() and mbedtls_ctr_drbg_init() + * again first. + * \param f_entropy The entropy callback, taking as arguments the + * \p p_entropy context, the buffer to fill, and the + * length of the buffer. + * \p f_entropy is always called with a buffer size + * less than or equal to the entropy length. + * \param p_entropy The entropy context to pass to \p f_entropy. + * \param custom The personalization string. + * This can be \c NULL, in which case the personalization + * string is empty regardless of the value of \p len. + * \param len The length of the personalization string. + * This must be at most + * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + * - #MBEDTLS_CTR_DRBG_ENTROPY_LEN. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on failure. + */ +int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx, + int (*f_entropy)(void *, unsigned char *, size_t), + void *p_entropy, + const unsigned char *custom, + size_t len ); + +/** + * \brief This function clears CTR_CRBG context data. + * + * \param ctx The CTR_DRBG context to clear. + */ +void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx ); + +/** + * \brief This function turns prediction resistance on or off. + * The default value is off. + * + * \note If enabled, entropy is gathered at the beginning of + * every call to mbedtls_ctr_drbg_random_with_add() + * or mbedtls_ctr_drbg_random(). + * Only use this if your entropy source has sufficient + * throughput. + * + * \param ctx The CTR_DRBG context. + * \param resistance #MBEDTLS_CTR_DRBG_PR_ON or #MBEDTLS_CTR_DRBG_PR_OFF. + */ +void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, + int resistance ); + +/** + * \brief This function sets the amount of entropy grabbed on each + * seed or reseed. + * + * The default value is #MBEDTLS_CTR_DRBG_ENTROPY_LEN. + * + * \note The security strength of CTR_DRBG is bounded by the + * entropy length. Thus: + * - When using AES-256 + * (\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is disabled, + * which is the default), + * \p len must be at least 32 (in bytes) + * to achieve a 256-bit strength. + * - When using AES-128 + * (\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is enabled) + * \p len must be at least 16 (in bytes) + * to achieve a 128-bit strength. + * + * \param ctx The CTR_DRBG context. + * \param len The amount of entropy to grab, in bytes. + * This must be at most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + * and at most the maximum length accepted by the + * entropy function that is set in the context. + */ +void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, + size_t len ); + +/** + * \brief This function sets the amount of entropy grabbed + * as a nonce for the initial seeding. + * + * Call this function before calling mbedtls_ctr_drbg_seed() to read + * a nonce from the entropy source during the initial seeding. + * + * \param ctx The CTR_DRBG context. + * \param len The amount of entropy to grab for the nonce, in bytes. + * This must be at most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + * and at most the maximum length accepted by the + * entropy function that is set in the context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG if \p len is + * more than #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED + * if the initial seeding has already taken place. + */ +int mbedtls_ctr_drbg_set_nonce_len( mbedtls_ctr_drbg_context *ctx, + size_t len ); + +/** + * \brief This function sets the reseed interval. + * + * The reseed interval is the number of calls to mbedtls_ctr_drbg_random() + * or mbedtls_ctr_drbg_random_with_add() after which the entropy function + * is called again. + * + * The default value is #MBEDTLS_CTR_DRBG_RESEED_INTERVAL. + * + * \param ctx The CTR_DRBG context. + * \param interval The reseed interval. + */ +void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, + int interval ); + +/** + * \brief This function reseeds the CTR_DRBG context, that is + * extracts data from the entropy source. + * + * \param ctx The CTR_DRBG context. + * \param additional Additional data to add to the state. Can be \c NULL. + * \param len The length of the additional data. + * This must be less than + * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - \c entropy_len + * where \c entropy_len is the entropy length + * configured for the context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on failure. + */ +int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, size_t len ); + +/** + * \brief This function updates the state of the CTR_DRBG context. + * + * \param ctx The CTR_DRBG context. + * \param additional The data to update the state with. This must not be + * \c NULL unless \p add_len is \c 0. + * \param add_len Length of \p additional in bytes. This must be at + * most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG if + * \p add_len is more than + * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT. + * \return An error from the underlying AES cipher on failure. + */ +int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, + size_t add_len ); + +/** + * \brief This function updates a CTR_DRBG instance with additional + * data and uses it to generate random data. + * + * This function automatically reseeds if the reseed counter is exceeded + * or prediction resistance is enabled. + * + * \param p_rng The CTR_DRBG context. This must be a pointer to a + * #mbedtls_ctr_drbg_context structure. + * \param output The buffer to fill. + * \param output_len The length of the buffer in bytes. + * \param additional Additional data to update. Can be \c NULL, in which + * case the additional data is empty regardless of + * the value of \p add_len. + * \param add_len The length of the additional data + * if \p additional is not \c NULL. + * This must be less than #MBEDTLS_CTR_DRBG_MAX_INPUT + * and less than + * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - \c entropy_len + * where \c entropy_len is the entropy length + * configured for the context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or + * #MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG on failure. + */ +int mbedtls_ctr_drbg_random_with_add( void *p_rng, + unsigned char *output, size_t output_len, + const unsigned char *additional, size_t add_len ); + +/** + * \brief This function uses CTR_DRBG to generate random data. + * + * This function automatically reseeds if the reseed counter is exceeded + * or prediction resistance is enabled. + * + * + * \param p_rng The CTR_DRBG context. This must be a pointer to a + * #mbedtls_ctr_drbg_context structure. + * \param output The buffer to fill. + * \param output_len The length of the buffer in bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or + * #MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG on failure. + */ +int mbedtls_ctr_drbg_random( void *p_rng, + unsigned char *output, size_t output_len ); + + +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function updates the state of the CTR_DRBG context. + * + * \deprecated Superseded by mbedtls_ctr_drbg_update_ret() + * in 2.16.0. + * + * \note If \p add_len is greater than + * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT, only the first + * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT Bytes are used. + * The remaining Bytes are silently discarded. + * + * \param ctx The CTR_DRBG context. + * \param additional The data to update the state with. + * \param add_len Length of \p additional data. + */ +MBEDTLS_DEPRECATED void mbedtls_ctr_drbg_update( + mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, + size_t add_len ); +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_FS_IO) +/** + * \brief This function writes a seed file. + * + * \param ctx The CTR_DRBG context. + * \param path The name of the file. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on reseed + * failure. + */ +int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ); + +/** + * \brief This function reads and updates a seed file. The seed + * is added to this instance. + * + * \param ctx The CTR_DRBG context. + * \param path The name of the file. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on + * reseed failure. + * \return #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG if the existing + * seed file is too large. + */ +int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ); +#endif /* MBEDTLS_FS_IO */ + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief The CTR_DRBG checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_ctr_drbg_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* ctr_drbg.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/debug.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/debug.h new file mode 100644 index 0000000..ab5b037 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/debug.h @@ -0,0 +1,262 @@ +/** + * \file debug.h + * + * \brief Functions for controlling and providing debug output from the library. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_DEBUG_H +#define MBEDTLS_DEBUG_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/ssl.h" + +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/ecp.h" +#endif + +#if defined(MBEDTLS_DEBUG_C) + +#define MBEDTLS_DEBUG_STRIP_PARENS( ... ) __VA_ARGS__ + +#define MBEDTLS_SSL_DEBUG_MSG( level, args ) \ + mbedtls_debug_print_msg( ssl, level, __FILE__, __LINE__, \ + MBEDTLS_DEBUG_STRIP_PARENS args ) + +#define MBEDTLS_SSL_DEBUG_RET( level, text, ret ) \ + mbedtls_debug_print_ret( ssl, level, __FILE__, __LINE__, text, ret ) + +#define MBEDTLS_SSL_DEBUG_BUF( level, text, buf, len ) \ + mbedtls_debug_print_buf( ssl, level, __FILE__, __LINE__, text, buf, len ) + +#if defined(MBEDTLS_BIGNUM_C) +#define MBEDTLS_SSL_DEBUG_MPI( level, text, X ) \ + mbedtls_debug_print_mpi( ssl, level, __FILE__, __LINE__, text, X ) +#endif + +#if defined(MBEDTLS_ECP_C) +#define MBEDTLS_SSL_DEBUG_ECP( level, text, X ) \ + mbedtls_debug_print_ecp( ssl, level, __FILE__, __LINE__, text, X ) +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#define MBEDTLS_SSL_DEBUG_CRT( level, text, crt ) \ + mbedtls_debug_print_crt( ssl, level, __FILE__, __LINE__, text, crt ) +#endif + +#if defined(MBEDTLS_ECDH_C) +#define MBEDTLS_SSL_DEBUG_ECDH( level, ecdh, attr ) \ + mbedtls_debug_printf_ecdh( ssl, level, __FILE__, __LINE__, ecdh, attr ) +#endif + +#else /* MBEDTLS_DEBUG_C */ + +#define MBEDTLS_SSL_DEBUG_MSG( level, args ) do { } while( 0 ) +#define MBEDTLS_SSL_DEBUG_RET( level, text, ret ) do { } while( 0 ) +#define MBEDTLS_SSL_DEBUG_BUF( level, text, buf, len ) do { } while( 0 ) +#define MBEDTLS_SSL_DEBUG_MPI( level, text, X ) do { } while( 0 ) +#define MBEDTLS_SSL_DEBUG_ECP( level, text, X ) do { } while( 0 ) +#define MBEDTLS_SSL_DEBUG_CRT( level, text, crt ) do { } while( 0 ) +#define MBEDTLS_SSL_DEBUG_ECDH( level, ecdh, attr ) do { } while( 0 ) + +#endif /* MBEDTLS_DEBUG_C */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Set the threshold error level to handle globally all debug output. + * Debug messages that have a level over the threshold value are + * discarded. + * (Default value: 0 = No debug ) + * + * \param threshold theshold level of messages to filter on. Messages at a + * higher level will be discarded. + * - Debug levels + * - 0 No debug + * - 1 Error + * - 2 State change + * - 3 Informational + * - 4 Verbose + */ +void mbedtls_debug_set_threshold( int threshold ); + +/** + * \brief Print a message to the debug output. This function is always used + * through the MBEDTLS_SSL_DEBUG_MSG() macro, which supplies the ssl + * context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the message has occurred in + * \param line line number the message has occurred at + * \param format format specifier, in printf format + * \param ... variables used by the format specifier + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_print_msg( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *format, ... ); + +/** + * \brief Print the return value of a function to the debug output. This + * function is always used through the MBEDTLS_SSL_DEBUG_RET() macro, + * which supplies the ssl context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param text the name of the function that returned the error + * \param ret the return code value + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_print_ret( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, int ret ); + +/** + * \brief Output a buffer of size len bytes to the debug output. This function + * is always used through the MBEDTLS_SSL_DEBUG_BUF() macro, + * which supplies the ssl context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param text a name or label for the buffer being dumped. Normally the + * variable or buffer name + * \param buf the buffer to be outputted + * \param len length of the buffer + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_print_buf( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, const char *text, + const unsigned char *buf, size_t len ); + +#if defined(MBEDTLS_BIGNUM_C) +/** + * \brief Print a MPI variable to the debug output. This function is always + * used through the MBEDTLS_SSL_DEBUG_MPI() macro, which supplies the + * ssl context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param text a name or label for the MPI being output. Normally the + * variable name + * \param X the MPI variable + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_print_mpi( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_mpi *X ); +#endif + +#if defined(MBEDTLS_ECP_C) +/** + * \brief Print an ECP point to the debug output. This function is always + * used through the MBEDTLS_SSL_DEBUG_ECP() macro, which supplies the + * ssl context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param text a name or label for the ECP point being output. Normally the + * variable name + * \param X the ECP point + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_print_ecp( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_ecp_point *X ); +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * \brief Print a X.509 certificate structure to the debug output. This + * function is always used through the MBEDTLS_SSL_DEBUG_CRT() macro, + * which supplies the ssl context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param text a name or label for the certificate being output + * \param crt X.509 certificate structure + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_print_crt( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_x509_crt *crt ); +#endif + +#if defined(MBEDTLS_ECDH_C) +typedef enum +{ + MBEDTLS_DEBUG_ECDH_Q, + MBEDTLS_DEBUG_ECDH_QP, + MBEDTLS_DEBUG_ECDH_Z, +} mbedtls_debug_ecdh_attr; + +/** + * \brief Print a field of the ECDH structure in the SSL context to the debug + * output. This function is always used through the + * MBEDTLS_SSL_DEBUG_ECDH() macro, which supplies the ssl context, file + * and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param ecdh the ECDH context + * \param attr the identifier of the attribute being output + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_printf_ecdh( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const mbedtls_ecdh_context *ecdh, + mbedtls_debug_ecdh_attr attr ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* debug.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/des.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/des.h new file mode 100644 index 0000000..549d19b --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/des.h @@ -0,0 +1,354 @@ +/** + * \file des.h + * + * \brief DES block cipher + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_DES_H +#define MBEDTLS_DES_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#define MBEDTLS_DES_ENCRYPT 1 +#define MBEDTLS_DES_DECRYPT 0 + +#define MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH -0x0032 /**< The data input has an invalid length. */ + +/* MBEDTLS_ERR_DES_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_DES_HW_ACCEL_FAILED -0x0033 /**< DES hardware accelerator failed. */ + +#define MBEDTLS_DES_KEY_SIZE 8 + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_DES_ALT) +// Regular implementation +// + +/** + * \brief DES context structure + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +typedef struct mbedtls_des_context +{ + uint32_t sk[32]; /*!< DES subkeys */ +} +mbedtls_des_context; + +/** + * \brief Triple-DES context structure + */ +typedef struct mbedtls_des3_context +{ + uint32_t sk[96]; /*!< 3DES subkeys */ +} +mbedtls_des3_context; + +#else /* MBEDTLS_DES_ALT */ +#include "des_alt.h" +#endif /* MBEDTLS_DES_ALT */ + +/** + * \brief Initialize DES context + * + * \param ctx DES context to be initialized + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +void mbedtls_des_init( mbedtls_des_context *ctx ); + +/** + * \brief Clear DES context + * + * \param ctx DES context to be cleared + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +void mbedtls_des_free( mbedtls_des_context *ctx ); + +/** + * \brief Initialize Triple-DES context + * + * \param ctx DES3 context to be initialized + */ +void mbedtls_des3_init( mbedtls_des3_context *ctx ); + +/** + * \brief Clear Triple-DES context + * + * \param ctx DES3 context to be cleared + */ +void mbedtls_des3_free( mbedtls_des3_context *ctx ); + +/** + * \brief Set key parity on the given key to odd. + * + * DES keys are 56 bits long, but each byte is padded with + * a parity bit to allow verification. + * + * \param key 8-byte secret key + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +void mbedtls_des_key_set_parity( unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief Check that key parity on the given key is odd. + * + * DES keys are 56 bits long, but each byte is padded with + * a parity bit to allow verification. + * + * \param key 8-byte secret key + * + * \return 0 is parity was ok, 1 if parity was not correct. + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +int mbedtls_des_key_check_key_parity( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief Check that key is not a weak or semi-weak DES key + * + * \param key 8-byte secret key + * + * \return 0 if no weak key was found, 1 if a weak key was identified. + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +int mbedtls_des_key_check_weak( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief DES key schedule (56-bit, encryption) + * + * \param ctx DES context to be initialized + * \param key 8-byte secret key + * + * \return 0 + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +int mbedtls_des_setkey_enc( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief DES key schedule (56-bit, decryption) + * + * \param ctx DES context to be initialized + * \param key 8-byte secret key + * + * \return 0 + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +int mbedtls_des_setkey_dec( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief Triple-DES key schedule (112-bit, encryption) + * + * \param ctx 3DES context to be initialized + * \param key 16-byte secret key + * + * \return 0 + */ +int mbedtls_des3_set2key_enc( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ); + +/** + * \brief Triple-DES key schedule (112-bit, decryption) + * + * \param ctx 3DES context to be initialized + * \param key 16-byte secret key + * + * \return 0 + */ +int mbedtls_des3_set2key_dec( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ); + +/** + * \brief Triple-DES key schedule (168-bit, encryption) + * + * \param ctx 3DES context to be initialized + * \param key 24-byte secret key + * + * \return 0 + */ +int mbedtls_des3_set3key_enc( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ); + +/** + * \brief Triple-DES key schedule (168-bit, decryption) + * + * \param ctx 3DES context to be initialized + * \param key 24-byte secret key + * + * \return 0 + */ +int mbedtls_des3_set3key_dec( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ); + +/** + * \brief DES-ECB block encryption/decryption + * + * \param ctx DES context + * \param input 64-bit input block + * \param output 64-bit output block + * + * \return 0 if successful + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +int mbedtls_des_crypt_ecb( mbedtls_des_context *ctx, + const unsigned char input[8], + unsigned char output[8] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief DES-CBC buffer encryption/decryption + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx DES context + * \param mode MBEDTLS_DES_ENCRYPT or MBEDTLS_DES_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +int mbedtls_des_crypt_cbc( mbedtls_des_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +/** + * \brief 3DES-ECB block encryption/decryption + * + * \param ctx 3DES context + * \param input 64-bit input block + * \param output 64-bit output block + * + * \return 0 if successful + */ +int mbedtls_des3_crypt_ecb( mbedtls_des3_context *ctx, + const unsigned char input[8], + unsigned char output[8] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief 3DES-CBC buffer encryption/decryption + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx 3DES context + * \param mode MBEDTLS_DES_ENCRYPT or MBEDTLS_DES_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful, or MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH + */ +int mbedtls_des3_crypt_cbc( mbedtls_des3_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +/** + * \brief Internal function for key expansion. + * (Only exposed to allow overriding it, + * see MBEDTLS_DES_SETKEY_ALT) + * + * \param SK Round keys + * \param key Base key + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +void mbedtls_des_setkey( uint32_t SK[32], + const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_des_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* des.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/dhm.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/dhm.h new file mode 100644 index 0000000..c7830b9 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/dhm.h @@ -0,0 +1,1092 @@ +/** + * \file dhm.h + * + * \brief This file contains Diffie-Hellman-Merkle (DHM) key exchange + * definitions and functions. + * + * Diffie-Hellman-Merkle (DHM) key exchange is defined in + * RFC-2631: Diffie-Hellman Key Agreement Method and + * Public-Key Cryptography Standards (PKCS) #3: Diffie + * Hellman Key Agreement Standard. + * + * RFC-3526: More Modular Exponential (MODP) Diffie-Hellman groups for + * Internet Key Exchange (IKE) defines a number of standardized + * Diffie-Hellman groups for IKE. + * + * RFC-5114: Additional Diffie-Hellman Groups for Use with IETF + * Standards defines a number of standardized Diffie-Hellman + * groups that can be used. + * + * \warning The security of the DHM key exchange relies on the proper choice + * of prime modulus - optimally, it should be a safe prime. The usage + * of non-safe primes both decreases the difficulty of the underlying + * discrete logarithm problem and can lead to small subgroup attacks + * leaking private exponent bits when invalid public keys are used + * and not detected. This is especially relevant if the same DHM + * parameters are reused for multiple key exchanges as in static DHM, + * while the criticality of small-subgroup attacks is lower for + * ephemeral DHM. + * + * \warning For performance reasons, the code does neither perform primality + * nor safe primality tests, nor the expensive checks for invalid + * subgroups. Moreover, even if these were performed, non-standardized + * primes cannot be trusted because of the possibility of backdoors + * that can't be effectively checked for. + * + * \warning Diffie-Hellman-Merkle is therefore a security risk when not using + * standardized primes generated using a trustworthy ("nothing up + * my sleeve") method, such as the RFC 3526 / 7919 primes. In the TLS + * protocol, DH parameters need to be negotiated, so using the default + * primes systematically is not always an option. If possible, use + * Elliptic Curve Diffie-Hellman (ECDH), which has better performance, + * and for which the TLS protocol mandates the use of standard + * parameters. + * + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_DHM_H +#define MBEDTLS_DHM_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif +#include "mbedtls/bignum.h" + +/* + * DHM Error codes + */ +#define MBEDTLS_ERR_DHM_BAD_INPUT_DATA -0x3080 /**< Bad input parameters. */ +#define MBEDTLS_ERR_DHM_READ_PARAMS_FAILED -0x3100 /**< Reading of the DHM parameters failed. */ +#define MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED -0x3180 /**< Making of the DHM parameters failed. */ +#define MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED -0x3200 /**< Reading of the public values failed. */ +#define MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED -0x3280 /**< Making of the public value failed. */ +#define MBEDTLS_ERR_DHM_CALC_SECRET_FAILED -0x3300 /**< Calculation of the DHM secret failed. */ +#define MBEDTLS_ERR_DHM_INVALID_FORMAT -0x3380 /**< The ASN.1 data is not formatted correctly. */ +#define MBEDTLS_ERR_DHM_ALLOC_FAILED -0x3400 /**< Allocation of memory failed. */ +#define MBEDTLS_ERR_DHM_FILE_IO_ERROR -0x3480 /**< Read or write of file failed. */ + +/* MBEDTLS_ERR_DHM_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_DHM_HW_ACCEL_FAILED -0x3500 /**< DHM hardware accelerator failed. */ + +#define MBEDTLS_ERR_DHM_SET_GROUP_FAILED -0x3580 /**< Setting the modulus and generator failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_DHM_ALT) + +/** + * \brief The DHM context structure. + */ +typedef struct mbedtls_dhm_context +{ + size_t len; /*!< The size of \p P in Bytes. */ + mbedtls_mpi P; /*!< The prime modulus. */ + mbedtls_mpi G; /*!< The generator. */ + mbedtls_mpi X; /*!< Our secret value. */ + mbedtls_mpi GX; /*!< Our public key = \c G^X mod \c P. */ + mbedtls_mpi GY; /*!< The public key of the peer = \c G^Y mod \c P. */ + mbedtls_mpi K; /*!< The shared secret = \c G^(XY) mod \c P. */ + mbedtls_mpi RP; /*!< The cached value = \c R^2 mod \c P. */ + mbedtls_mpi Vi; /*!< The blinding value. */ + mbedtls_mpi Vf; /*!< The unblinding value. */ + mbedtls_mpi pX; /*!< The previous \c X. */ +} +mbedtls_dhm_context; + +#else /* MBEDTLS_DHM_ALT */ +#include "dhm_alt.h" +#endif /* MBEDTLS_DHM_ALT */ + +/** + * \brief This function initializes the DHM context. + * + * \param ctx The DHM context to initialize. + */ +void mbedtls_dhm_init( mbedtls_dhm_context *ctx ); + +/** + * \brief This function parses the DHM parameters in a + * TLS ServerKeyExchange handshake message + * (DHM modulus, generator, and public key). + * + * \note In a TLS handshake, this is the how the client + * sets up its DHM context from the server's public + * DHM key material. + * + * \param ctx The DHM context to use. This must be initialized. + * \param p On input, *p must be the start of the input buffer. + * On output, *p is updated to point to the end of the data + * that has been read. On success, this is the first byte + * past the end of the ServerKeyExchange parameters. + * On error, this is the point at which an error has been + * detected, which is usually not useful except to debug + * failures. + * \param end The end of the input buffer. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. + */ +int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx, + unsigned char **p, + const unsigned char *end ); + +/** + * \brief This function generates a DHM key pair and exports its + * public part together with the DHM parameters in the format + * used in a TLS ServerKeyExchange handshake message. + * + * \note This function assumes that the DHM parameters \c ctx->P + * and \c ctx->G have already been properly set. For that, use + * mbedtls_dhm_set_group() below in conjunction with + * mbedtls_mpi_read_binary() and mbedtls_mpi_read_string(). + * + * \note In a TLS handshake, this is the how the server generates + * and exports its DHM key material. + * + * \param ctx The DHM context to use. This must be initialized + * and have the DHM parameters set. It may or may not + * already have imported the peer's public key. + * \param x_size The private key size in Bytes. + * \param olen The address at which to store the number of Bytes + * written on success. This must not be \c NULL. + * \param output The destination buffer. This must be a writable buffer of + * sufficient size to hold the reduced binary presentation of + * the modulus, the generator and the public key, each wrapped + * with a 2-byte length field. It is the responsibility of the + * caller to ensure that enough space is available. Refer to + * mbedtls_mpi_size() to computing the byte-size of an MPI. + * \param f_rng The RNG function. Must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context parameter. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. + */ +int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size, + unsigned char *output, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function sets the prime modulus and generator. + * + * \note This function can be used to set \c ctx->P, \c ctx->G + * in preparation for mbedtls_dhm_make_params(). + * + * \param ctx The DHM context to configure. This must be initialized. + * \param P The MPI holding the DHM prime modulus. This must be + * an initialized MPI. + * \param G The MPI holding the DHM generator. This must be an + * initialized MPI. + * + * \return \c 0 if successful. + * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. + */ +int mbedtls_dhm_set_group( mbedtls_dhm_context *ctx, + const mbedtls_mpi *P, + const mbedtls_mpi *G ); + +/** + * \brief This function imports the raw public value of the peer. + * + * \note In a TLS handshake, this is the how the server imports + * the Client's public DHM key. + * + * \param ctx The DHM context to use. This must be initialized and have + * its DHM parameters set, e.g. via mbedtls_dhm_set_group(). + * It may or may not already have generated its own private key. + * \param input The input buffer containing the \c G^Y value of the peer. + * This must be a readable buffer of size \p ilen Bytes. + * \param ilen The size of the input buffer \p input in Bytes. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. + */ +int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx, + const unsigned char *input, size_t ilen ); + +/** + * \brief This function creates a DHM key pair and exports + * the raw public key in big-endian format. + * + * \note The destination buffer is always fully written + * so as to contain a big-endian representation of G^X mod P. + * If it is larger than \c ctx->len, it is padded accordingly + * with zero-bytes at the beginning. + * + * \param ctx The DHM context to use. This must be initialized and + * have the DHM parameters set. It may or may not already + * have imported the peer's public key. + * \param x_size The private key size in Bytes. + * \param output The destination buffer. This must be a writable buffer of + * size \p olen Bytes. + * \param olen The length of the destination buffer. This must be at least + * equal to `ctx->len` (the size of \c P). + * \param f_rng The RNG function. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL + * if \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. + */ +int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size, + unsigned char *output, size_t olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function derives and exports the shared secret + * \c (G^Y)^X mod \c P. + * + * \note If \p f_rng is not \c NULL, it is used to blind the input as + * a countermeasure against timing attacks. Blinding is used + * only if our private key \c X is re-used, and not used + * otherwise. We recommend always passing a non-NULL + * \p f_rng argument. + * + * \param ctx The DHM context to use. This must be initialized + * and have its own private key generated and the peer's + * public key imported. + * \param output The buffer to write the generated shared key to. This + * must be a writable buffer of size \p output_size Bytes. + * \param output_size The size of the destination buffer. This must be at + * least the size of \c ctx->len (the size of \c P). + * \param olen On exit, holds the actual number of Bytes written. + * \param f_rng The RNG function, for blinding purposes. This may + * b \c NULL if blinding isn't needed. + * \param p_rng The RNG context. This may be \c NULL if \p f_rng + * doesn't need a context argument. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. + */ +int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx, + unsigned char *output, size_t output_size, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function frees and clears the components + * of a DHM context. + * + * \param ctx The DHM context to free and clear. This may be \c NULL, + * in which case this function is a no-op. If it is not \c NULL, + * it must point to an initialized DHM context. + */ +void mbedtls_dhm_free( mbedtls_dhm_context *ctx ); + +#if defined(MBEDTLS_ASN1_PARSE_C) +/** + * \brief This function parses DHM parameters in PEM or DER format. + * + * \param dhm The DHM context to import the DHM parameters into. + * This must be initialized. + * \param dhmin The input buffer. This must be a readable buffer of + * length \p dhminlen Bytes. + * \param dhminlen The size of the input buffer \p dhmin, including the + * terminating \c NULL Byte for PEM data. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_DHM_XXX or \c MBEDTLS_ERR_PEM_XXX error + * code on failure. + */ +int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin, + size_t dhminlen ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief This function loads and parses DHM parameters from a file. + * + * \param dhm The DHM context to load the parameters to. + * This must be initialized. + * \param path The filename to read the DHM parameters from. + * This must not be \c NULL. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_DHM_XXX or \c MBEDTLS_ERR_PEM_XXX + * error code on failure. + */ +int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path ); +#endif /* MBEDTLS_FS_IO */ +#endif /* MBEDTLS_ASN1_PARSE_C */ + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief The DMH checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_dhm_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ +#ifdef __cplusplus +} +#endif + +/** + * RFC 3526, RFC 5114 and RFC 7919 standardize a number of + * Diffie-Hellman groups, some of which are included here + * for use within the SSL/TLS module and the user's convenience + * when configuring the Diffie-Hellman parameters by hand + * through \c mbedtls_ssl_conf_dh_param. + * + * The following lists the source of the above groups in the standards: + * - RFC 5114 section 2.2: 2048-bit MODP Group with 224-bit Prime Order Subgroup + * - RFC 3526 section 3: 2048-bit MODP Group + * - RFC 3526 section 4: 3072-bit MODP Group + * - RFC 3526 section 5: 4096-bit MODP Group + * - RFC 7919 section A.1: ffdhe2048 + * - RFC 7919 section A.2: ffdhe3072 + * - RFC 7919 section A.3: ffdhe4096 + * - RFC 7919 section A.4: ffdhe6144 + * - RFC 7919 section A.5: ffdhe8192 + * + * The constants with suffix "_p" denote the chosen prime moduli, while + * the constants with suffix "_g" denote the chosen generator + * of the associated prime field. + * + * The constants further suffixed with "_bin" are provided in binary format, + * while all other constants represent null-terminated strings holding the + * hexadecimal presentation of the respective numbers. + * + * The primes from RFC 3526 and RFC 7919 have been generating by the following + * trust-worthy procedure: + * - Fix N in { 2048, 3072, 4096, 6144, 8192 } and consider the N-bit number + * the first and last 64 bits are all 1, and the remaining N - 128 bits of + * which are 0x7ff...ff. + * - Add the smallest multiple of the first N - 129 bits of the binary expansion + * of pi (for RFC 5236) or e (for RFC 7919) to this intermediate bit-string + * such that the resulting integer is a safe-prime. + * - The result is the respective RFC 3526 / 7919 prime, and the corresponding + * generator is always chosen to be 2 (which is a square for these prime, + * hence the corresponding subgroup has order (p-1)/2 and avoids leaking a + * bit in the private exponent). + * + */ + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + +/** + * \warning The origin of the primes in RFC 5114 is not documented and + * their use therefore constitutes a security risk! + * + * \deprecated The hex-encoded primes from RFC 5114 are deprecated and are + * likely to be removed in a future version of the library without + * replacement. + */ + +/** + * The hexadecimal presentation of the prime underlying the + * 2048-bit MODP Group with 224-bit Prime Order Subgroup, as defined + * in RFC-5114: Additional Diffie-Hellman Groups for Use with + * IETF Standards. + */ +#define MBEDTLS_DHM_RFC5114_MODP_2048_P \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( \ + "AD107E1E9123A9D0D660FAA79559C51FA20D64E5683B9FD1" \ + "B54B1597B61D0A75E6FA141DF95A56DBAF9A3C407BA1DF15" \ + "EB3D688A309C180E1DE6B85A1274A0A66D3F8152AD6AC212" \ + "9037C9EDEFDA4DF8D91E8FEF55B7394B7AD5B7D0B6C12207" \ + "C9F98D11ED34DBF6C6BA0B2C8BBC27BE6A00E0A0B9C49708" \ + "B3BF8A317091883681286130BC8985DB1602E714415D9330" \ + "278273C7DE31EFDC7310F7121FD5A07415987D9ADC0A486D" \ + "CDF93ACC44328387315D75E198C641A480CD86A1B9E587E8" \ + "BE60E69CC928B2B9C52172E413042E9B23F10B0E16E79763" \ + "C9B53DCF4BA80A29E3FB73C16B8E75B97EF363E2FFA31F71" \ + "CF9DE5384E71B81C0AC4DFFE0C10E64F" ) + +/** + * The hexadecimal presentation of the chosen generator of the 2048-bit MODP + * Group with 224-bit Prime Order Subgroup, as defined in RFC-5114: + * Additional Diffie-Hellman Groups for Use with IETF Standards. + */ +#define MBEDTLS_DHM_RFC5114_MODP_2048_G \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( \ + "AC4032EF4F2D9AE39DF30B5C8FFDAC506CDEBE7B89998CAF" \ + "74866A08CFE4FFE3A6824A4E10B9A6F0DD921F01A70C4AFA" \ + "AB739D7700C29F52C57DB17C620A8652BE5E9001A8D66AD7" \ + "C17669101999024AF4D027275AC1348BB8A762D0521BC98A" \ + "E247150422EA1ED409939D54DA7460CDB5F6C6B250717CBE" \ + "F180EB34118E98D119529A45D6F834566E3025E316A330EF" \ + "BB77A86F0C1AB15B051AE3D428C8F8ACB70A8137150B8EEB" \ + "10E183EDD19963DDD9E263E4770589EF6AA21E7F5F2FF381" \ + "B539CCE3409D13CD566AFBB48D6C019181E1BCFE94B30269" \ + "EDFE72FE9B6AA4BD7B5A0F1C71CFFF4C19C418E1F6EC0179" \ + "81BC087F2A7065B384B890D3191F2BFA" ) + +/** + * The hexadecimal presentation of the prime underlying the 2048-bit MODP + * Group, as defined in RFC-3526: More Modular Exponential (MODP) + * Diffie-Hellman groups for Internet Key Exchange (IKE). + * + * \deprecated The hex-encoded primes from RFC 3625 are deprecated and + * superseded by the corresponding macros providing them as + * binary constants. Their hex-encoded constants are likely + * to be removed in a future version of the library. + * + */ +#define MBEDTLS_DHM_RFC3526_MODP_2048_P \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( \ + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ + "15728E5A8AACAA68FFFFFFFFFFFFFFFF" ) + +/** + * The hexadecimal presentation of the chosen generator of the 2048-bit MODP + * Group, as defined in RFC-3526: More Modular Exponential (MODP) + * Diffie-Hellman groups for Internet Key Exchange (IKE). + */ +#define MBEDTLS_DHM_RFC3526_MODP_2048_G \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( "02" ) + +/** + * The hexadecimal presentation of the prime underlying the 3072-bit MODP + * Group, as defined in RFC-3072: More Modular Exponential (MODP) + * Diffie-Hellman groups for Internet Key Exchange (IKE). + */ +#define MBEDTLS_DHM_RFC3526_MODP_3072_P \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( \ + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" \ + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" \ + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" \ + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" \ + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" \ + "43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF" ) + +/** + * The hexadecimal presentation of the chosen generator of the 3072-bit MODP + * Group, as defined in RFC-3526: More Modular Exponential (MODP) + * Diffie-Hellman groups for Internet Key Exchange (IKE). + */ +#define MBEDTLS_DHM_RFC3526_MODP_3072_G \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( "02" ) + +/** + * The hexadecimal presentation of the prime underlying the 4096-bit MODP + * Group, as defined in RFC-3526: More Modular Exponential (MODP) + * Diffie-Hellman groups for Internet Key Exchange (IKE). + */ +#define MBEDTLS_DHM_RFC3526_MODP_4096_P \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( \ + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" \ + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" \ + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" \ + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" \ + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" \ + "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" \ + "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" \ + "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" \ + "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" \ + "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" \ + "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199" \ + "FFFFFFFFFFFFFFFF" ) + +/** + * The hexadecimal presentation of the chosen generator of the 4096-bit MODP + * Group, as defined in RFC-3526: More Modular Exponential (MODP) + * Diffie-Hellman groups for Internet Key Exchange (IKE). + */ +#define MBEDTLS_DHM_RFC3526_MODP_4096_G \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( "02" ) + +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/* + * Trustworthy DHM parameters in binary form + */ + +#define MBEDTLS_DHM_RFC3526_MODP_2048_P_BIN { \ + 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 } + +#define MBEDTLS_DHM_RFC3526_MODP_2048_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC3526_MODP_3072_P_BIN { \ + 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, 0xAA, 0xC4, 0x2D, \ + 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, \ + 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, \ + 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, \ + 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, \ + 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, \ + 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, \ + 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, \ + 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, \ + 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, \ + 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, \ + 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, \ + 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, \ + 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, \ + 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, \ + 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, \ + 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x3A, 0xD2, 0xCA, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC3526_MODP_3072_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC3526_MODP_4096_P_BIN { \ + 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, 0xAA, 0xC4, 0x2D, \ + 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, \ + 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, \ + 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, \ + 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, \ + 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, \ + 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, \ + 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, \ + 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, \ + 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, \ + 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, \ + 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, \ + 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, \ + 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, \ + 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, \ + 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, \ + 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, \ + 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, \ + 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, \ + 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C, \ + 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, \ + 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, \ + 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, \ + 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6, \ + 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, \ + 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2, \ + 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, \ + 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, \ + 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, \ + 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9, \ + 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, \ + 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F, \ + 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC3526_MODP_4096_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC7919_FFDHE2048_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x28, 0x5C, 0x97, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, } + +#define MBEDTLS_DHM_RFC7919_FFDHE2048_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC7919_FFDHE3072_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, \ + 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, \ + 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, \ + 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, \ + 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, \ + 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, \ + 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, \ + 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, \ + 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, \ + 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, \ + 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, \ + 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, \ + 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, \ + 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, \ + 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, \ + 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, \ + 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0xC6, 0x2E, 0x37, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC7919_FFDHE3072_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC7919_FFDHE4096_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, \ + 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, \ + 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, \ + 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, \ + 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, \ + 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, \ + 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, \ + 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, \ + 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, \ + 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, \ + 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, \ + 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, \ + 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, \ + 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, \ + 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, \ + 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, \ + 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1, \ + 0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB, \ + 0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6, \ + 0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18, \ + 0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04, \ + 0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A, \ + 0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A, \ + 0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32, \ + 0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4, \ + 0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38, \ + 0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A, \ + 0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C, \ + 0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC, \ + 0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF, \ + 0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B, \ + 0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1, \ + 0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x65, 0x5F, 0x6A, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC7919_FFDHE4096_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC7919_FFDHE6144_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, \ + 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, \ + 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, \ + 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, \ + 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, \ + 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, \ + 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, \ + 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, \ + 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, \ + 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, \ + 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, \ + 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, \ + 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, \ + 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, \ + 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, \ + 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, \ + 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1, \ + 0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB, \ + 0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6, \ + 0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18, \ + 0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04, \ + 0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A, \ + 0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A, \ + 0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32, \ + 0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4, \ + 0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38, \ + 0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A, \ + 0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C, \ + 0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC, \ + 0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF, \ + 0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B, \ + 0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1, \ + 0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x0D, 0xD9, 0x02, \ + 0x0B, 0xFD, 0x64, 0xB6, 0x45, 0x03, 0x6C, 0x7A, \ + 0x4E, 0x67, 0x7D, 0x2C, 0x38, 0x53, 0x2A, 0x3A, \ + 0x23, 0xBA, 0x44, 0x42, 0xCA, 0xF5, 0x3E, 0xA6, \ + 0x3B, 0xB4, 0x54, 0x32, 0x9B, 0x76, 0x24, 0xC8, \ + 0x91, 0x7B, 0xDD, 0x64, 0xB1, 0xC0, 0xFD, 0x4C, \ + 0xB3, 0x8E, 0x8C, 0x33, 0x4C, 0x70, 0x1C, 0x3A, \ + 0xCD, 0xAD, 0x06, 0x57, 0xFC, 0xCF, 0xEC, 0x71, \ + 0x9B, 0x1F, 0x5C, 0x3E, 0x4E, 0x46, 0x04, 0x1F, \ + 0x38, 0x81, 0x47, 0xFB, 0x4C, 0xFD, 0xB4, 0x77, \ + 0xA5, 0x24, 0x71, 0xF7, 0xA9, 0xA9, 0x69, 0x10, \ + 0xB8, 0x55, 0x32, 0x2E, 0xDB, 0x63, 0x40, 0xD8, \ + 0xA0, 0x0E, 0xF0, 0x92, 0x35, 0x05, 0x11, 0xE3, \ + 0x0A, 0xBE, 0xC1, 0xFF, 0xF9, 0xE3, 0xA2, 0x6E, \ + 0x7F, 0xB2, 0x9F, 0x8C, 0x18, 0x30, 0x23, 0xC3, \ + 0x58, 0x7E, 0x38, 0xDA, 0x00, 0x77, 0xD9, 0xB4, \ + 0x76, 0x3E, 0x4E, 0x4B, 0x94, 0xB2, 0xBB, 0xC1, \ + 0x94, 0xC6, 0x65, 0x1E, 0x77, 0xCA, 0xF9, 0x92, \ + 0xEE, 0xAA, 0xC0, 0x23, 0x2A, 0x28, 0x1B, 0xF6, \ + 0xB3, 0xA7, 0x39, 0xC1, 0x22, 0x61, 0x16, 0x82, \ + 0x0A, 0xE8, 0xDB, 0x58, 0x47, 0xA6, 0x7C, 0xBE, \ + 0xF9, 0xC9, 0x09, 0x1B, 0x46, 0x2D, 0x53, 0x8C, \ + 0xD7, 0x2B, 0x03, 0x74, 0x6A, 0xE7, 0x7F, 0x5E, \ + 0x62, 0x29, 0x2C, 0x31, 0x15, 0x62, 0xA8, 0x46, \ + 0x50, 0x5D, 0xC8, 0x2D, 0xB8, 0x54, 0x33, 0x8A, \ + 0xE4, 0x9F, 0x52, 0x35, 0xC9, 0x5B, 0x91, 0x17, \ + 0x8C, 0xCF, 0x2D, 0xD5, 0xCA, 0xCE, 0xF4, 0x03, \ + 0xEC, 0x9D, 0x18, 0x10, 0xC6, 0x27, 0x2B, 0x04, \ + 0x5B, 0x3B, 0x71, 0xF9, 0xDC, 0x6B, 0x80, 0xD6, \ + 0x3F, 0xDD, 0x4A, 0x8E, 0x9A, 0xDB, 0x1E, 0x69, \ + 0x62, 0xA6, 0x95, 0x26, 0xD4, 0x31, 0x61, 0xC1, \ + 0xA4, 0x1D, 0x57, 0x0D, 0x79, 0x38, 0xDA, 0xD4, \ + 0xA4, 0x0E, 0x32, 0x9C, 0xD0, 0xE4, 0x0E, 0x65, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC7919_FFDHE6144_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC7919_FFDHE8192_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, \ + 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, \ + 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, \ + 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, \ + 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, \ + 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, \ + 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, \ + 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, \ + 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, \ + 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, \ + 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, \ + 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, \ + 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, \ + 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, \ + 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, \ + 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, \ + 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1, \ + 0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB, \ + 0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6, \ + 0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18, \ + 0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04, \ + 0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A, \ + 0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A, \ + 0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32, \ + 0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4, \ + 0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38, \ + 0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A, \ + 0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C, \ + 0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC, \ + 0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF, \ + 0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B, \ + 0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1, \ + 0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x0D, 0xD9, 0x02, \ + 0x0B, 0xFD, 0x64, 0xB6, 0x45, 0x03, 0x6C, 0x7A, \ + 0x4E, 0x67, 0x7D, 0x2C, 0x38, 0x53, 0x2A, 0x3A, \ + 0x23, 0xBA, 0x44, 0x42, 0xCA, 0xF5, 0x3E, 0xA6, \ + 0x3B, 0xB4, 0x54, 0x32, 0x9B, 0x76, 0x24, 0xC8, \ + 0x91, 0x7B, 0xDD, 0x64, 0xB1, 0xC0, 0xFD, 0x4C, \ + 0xB3, 0x8E, 0x8C, 0x33, 0x4C, 0x70, 0x1C, 0x3A, \ + 0xCD, 0xAD, 0x06, 0x57, 0xFC, 0xCF, 0xEC, 0x71, \ + 0x9B, 0x1F, 0x5C, 0x3E, 0x4E, 0x46, 0x04, 0x1F, \ + 0x38, 0x81, 0x47, 0xFB, 0x4C, 0xFD, 0xB4, 0x77, \ + 0xA5, 0x24, 0x71, 0xF7, 0xA9, 0xA9, 0x69, 0x10, \ + 0xB8, 0x55, 0x32, 0x2E, 0xDB, 0x63, 0x40, 0xD8, \ + 0xA0, 0x0E, 0xF0, 0x92, 0x35, 0x05, 0x11, 0xE3, \ + 0x0A, 0xBE, 0xC1, 0xFF, 0xF9, 0xE3, 0xA2, 0x6E, \ + 0x7F, 0xB2, 0x9F, 0x8C, 0x18, 0x30, 0x23, 0xC3, \ + 0x58, 0x7E, 0x38, 0xDA, 0x00, 0x77, 0xD9, 0xB4, \ + 0x76, 0x3E, 0x4E, 0x4B, 0x94, 0xB2, 0xBB, 0xC1, \ + 0x94, 0xC6, 0x65, 0x1E, 0x77, 0xCA, 0xF9, 0x92, \ + 0xEE, 0xAA, 0xC0, 0x23, 0x2A, 0x28, 0x1B, 0xF6, \ + 0xB3, 0xA7, 0x39, 0xC1, 0x22, 0x61, 0x16, 0x82, \ + 0x0A, 0xE8, 0xDB, 0x58, 0x47, 0xA6, 0x7C, 0xBE, \ + 0xF9, 0xC9, 0x09, 0x1B, 0x46, 0x2D, 0x53, 0x8C, \ + 0xD7, 0x2B, 0x03, 0x74, 0x6A, 0xE7, 0x7F, 0x5E, \ + 0x62, 0x29, 0x2C, 0x31, 0x15, 0x62, 0xA8, 0x46, \ + 0x50, 0x5D, 0xC8, 0x2D, 0xB8, 0x54, 0x33, 0x8A, \ + 0xE4, 0x9F, 0x52, 0x35, 0xC9, 0x5B, 0x91, 0x17, \ + 0x8C, 0xCF, 0x2D, 0xD5, 0xCA, 0xCE, 0xF4, 0x03, \ + 0xEC, 0x9D, 0x18, 0x10, 0xC6, 0x27, 0x2B, 0x04, \ + 0x5B, 0x3B, 0x71, 0xF9, 0xDC, 0x6B, 0x80, 0xD6, \ + 0x3F, 0xDD, 0x4A, 0x8E, 0x9A, 0xDB, 0x1E, 0x69, \ + 0x62, 0xA6, 0x95, 0x26, 0xD4, 0x31, 0x61, 0xC1, \ + 0xA4, 0x1D, 0x57, 0x0D, 0x79, 0x38, 0xDA, 0xD4, \ + 0xA4, 0x0E, 0x32, 0x9C, 0xCF, 0xF4, 0x6A, 0xAA, \ + 0x36, 0xAD, 0x00, 0x4C, 0xF6, 0x00, 0xC8, 0x38, \ + 0x1E, 0x42, 0x5A, 0x31, 0xD9, 0x51, 0xAE, 0x64, \ + 0xFD, 0xB2, 0x3F, 0xCE, 0xC9, 0x50, 0x9D, 0x43, \ + 0x68, 0x7F, 0xEB, 0x69, 0xED, 0xD1, 0xCC, 0x5E, \ + 0x0B, 0x8C, 0xC3, 0xBD, 0xF6, 0x4B, 0x10, 0xEF, \ + 0x86, 0xB6, 0x31, 0x42, 0xA3, 0xAB, 0x88, 0x29, \ + 0x55, 0x5B, 0x2F, 0x74, 0x7C, 0x93, 0x26, 0x65, \ + 0xCB, 0x2C, 0x0F, 0x1C, 0xC0, 0x1B, 0xD7, 0x02, \ + 0x29, 0x38, 0x88, 0x39, 0xD2, 0xAF, 0x05, 0xE4, \ + 0x54, 0x50, 0x4A, 0xC7, 0x8B, 0x75, 0x82, 0x82, \ + 0x28, 0x46, 0xC0, 0xBA, 0x35, 0xC3, 0x5F, 0x5C, \ + 0x59, 0x16, 0x0C, 0xC0, 0x46, 0xFD, 0x82, 0x51, \ + 0x54, 0x1F, 0xC6, 0x8C, 0x9C, 0x86, 0xB0, 0x22, \ + 0xBB, 0x70, 0x99, 0x87, 0x6A, 0x46, 0x0E, 0x74, \ + 0x51, 0xA8, 0xA9, 0x31, 0x09, 0x70, 0x3F, 0xEE, \ + 0x1C, 0x21, 0x7E, 0x6C, 0x38, 0x26, 0xE5, 0x2C, \ + 0x51, 0xAA, 0x69, 0x1E, 0x0E, 0x42, 0x3C, 0xFC, \ + 0x99, 0xE9, 0xE3, 0x16, 0x50, 0xC1, 0x21, 0x7B, \ + 0x62, 0x48, 0x16, 0xCD, 0xAD, 0x9A, 0x95, 0xF9, \ + 0xD5, 0xB8, 0x01, 0x94, 0x88, 0xD9, 0xC0, 0xA0, \ + 0xA1, 0xFE, 0x30, 0x75, 0xA5, 0x77, 0xE2, 0x31, \ + 0x83, 0xF8, 0x1D, 0x4A, 0x3F, 0x2F, 0xA4, 0x57, \ + 0x1E, 0xFC, 0x8C, 0xE0, 0xBA, 0x8A, 0x4F, 0xE8, \ + 0xB6, 0x85, 0x5D, 0xFE, 0x72, 0xB0, 0xA6, 0x6E, \ + 0xDE, 0xD2, 0xFB, 0xAB, 0xFB, 0xE5, 0x8A, 0x30, \ + 0xFA, 0xFA, 0xBE, 0x1C, 0x5D, 0x71, 0xA8, 0x7E, \ + 0x2F, 0x74, 0x1E, 0xF8, 0xC1, 0xFE, 0x86, 0xFE, \ + 0xA6, 0xBB, 0xFD, 0xE5, 0x30, 0x67, 0x7F, 0x0D, \ + 0x97, 0xD1, 0x1D, 0x49, 0xF7, 0xA8, 0x44, 0x3D, \ + 0x08, 0x22, 0xE5, 0x06, 0xA9, 0xF4, 0x61, 0x4E, \ + 0x01, 0x1E, 0x2A, 0x94, 0x83, 0x8F, 0xF8, 0x8C, \ + 0xD6, 0x8C, 0x8B, 0xB7, 0xC5, 0xC6, 0x42, 0x4C, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC7919_FFDHE8192_G_BIN { 0x02 } + +#endif /* dhm.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ecdh.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ecdh.h new file mode 100644 index 0000000..05855cd --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ecdh.h @@ -0,0 +1,446 @@ +/** + * \file ecdh.h + * + * \brief This file contains ECDH definitions and functions. + * + * The Elliptic Curve Diffie-Hellman (ECDH) protocol is an anonymous + * key agreement protocol allowing two parties to establish a shared + * secret over an insecure channel. Each party must have an + * elliptic-curve public–private key pair. + * + * For more information, see NIST SP 800-56A Rev. 2: Recommendation for + * Pair-Wise Key Establishment Schemes Using Discrete Logarithm + * Cryptography. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_ECDH_H +#define MBEDTLS_ECDH_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/ecp.h" + +#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) +#undef MBEDTLS_ECDH_LEGACY_CONTEXT +#include "everest/everest.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Defines the source of the imported EC key. + */ +typedef enum +{ + MBEDTLS_ECDH_OURS, /**< Our key. */ + MBEDTLS_ECDH_THEIRS, /**< The key of the peer. */ +} mbedtls_ecdh_side; + +#if !defined(MBEDTLS_ECDH_LEGACY_CONTEXT) +/** + * Defines the ECDH implementation used. + * + * Later versions of the library may add new variants, therefore users should + * not make any assumptions about them. + */ +typedef enum +{ + MBEDTLS_ECDH_VARIANT_NONE = 0, /*!< Implementation not defined. */ + MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0,/*!< The default Mbed TLS implementation */ +#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) + MBEDTLS_ECDH_VARIANT_EVEREST /*!< Everest implementation */ +#endif +} mbedtls_ecdh_variant; + +/** + * The context used by the default ECDH implementation. + * + * Later versions might change the structure of this context, therefore users + * should not make any assumptions about the structure of + * mbedtls_ecdh_context_mbed. + */ +typedef struct mbedtls_ecdh_context_mbed +{ + mbedtls_ecp_group grp; /*!< The elliptic curve used. */ + mbedtls_mpi d; /*!< The private key. */ + mbedtls_ecp_point Q; /*!< The public key. */ + mbedtls_ecp_point Qp; /*!< The value of the public key of the peer. */ + mbedtls_mpi z; /*!< The shared secret. */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_ecp_restart_ctx rs; /*!< The restart context for EC computations. */ +#endif +} mbedtls_ecdh_context_mbed; +#endif + +/** + * + * \warning Performing multiple operations concurrently on the same + * ECDSA context is not supported; objects of this type + * should not be shared between multiple threads. + * \brief The ECDH context structure. + */ +typedef struct mbedtls_ecdh_context +{ +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + mbedtls_ecp_group grp; /*!< The elliptic curve used. */ + mbedtls_mpi d; /*!< The private key. */ + mbedtls_ecp_point Q; /*!< The public key. */ + mbedtls_ecp_point Qp; /*!< The value of the public key of the peer. */ + mbedtls_mpi z; /*!< The shared secret. */ + int point_format; /*!< The format of point export in TLS messages. */ + mbedtls_ecp_point Vi; /*!< The blinding value. */ + mbedtls_ecp_point Vf; /*!< The unblinding value. */ + mbedtls_mpi _d; /*!< The previous \p d. */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + int restart_enabled; /*!< The flag for restartable mode. */ + mbedtls_ecp_restart_ctx rs; /*!< The restart context for EC computations. */ +#endif /* MBEDTLS_ECP_RESTARTABLE */ +#else + uint8_t point_format; /*!< The format of point export in TLS messages + as defined in RFC 4492. */ + mbedtls_ecp_group_id grp_id;/*!< The elliptic curve used. */ + mbedtls_ecdh_variant var; /*!< The ECDH implementation/structure used. */ + union + { + mbedtls_ecdh_context_mbed mbed_ecdh; +#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) + mbedtls_ecdh_context_everest everest_ecdh; +#endif + } ctx; /*!< Implementation-specific context. The + context in use is specified by the \c var + field. */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + uint8_t restart_enabled; /*!< The flag for restartable mode. Functions of + an alternative implementation not supporting + restartable mode must return + MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED error + if this flag is set. */ +#endif /* MBEDTLS_ECP_RESTARTABLE */ +#endif /* MBEDTLS_ECDH_LEGACY_CONTEXT */ +} +mbedtls_ecdh_context; + +/** + * \brief Check whether a given group can be used for ECDH. + * + * \param gid The ECP group ID to check. + * + * \return \c 1 if the group can be used, \c 0 otherwise + */ +int mbedtls_ecdh_can_do( mbedtls_ecp_group_id gid ); + +/** + * \brief This function generates an ECDH keypair on an elliptic + * curve. + * + * This function performs the first of two core computations + * implemented during the ECDH key exchange. The second core + * computation is performed by mbedtls_ecdh_compute_shared(). + * + * \see ecp.h + * + * \param grp The ECP group to use. This must be initialized and have + * domain parameters loaded, for example through + * mbedtls_ecp_load() or mbedtls_ecp_tls_read_group(). + * \param d The destination MPI (private key). + * This must be initialized. + * \param Q The destination point (public key). + * This must be initialized. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL in case \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return Another \c MBEDTLS_ERR_ECP_XXX or + * \c MBEDTLS_MPI_XXX error code on failure. + */ +int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function computes the shared secret. + * + * This function performs the second of two core computations + * implemented during the ECDH key exchange. The first core + * computation is performed by mbedtls_ecdh_gen_public(). + * + * \see ecp.h + * + * \note If \p f_rng is not NULL, it is used to implement + * countermeasures against side-channel attacks. + * For more information, see mbedtls_ecp_mul(). + * + * \param grp The ECP group to use. This must be initialized and have + * domain parameters loaded, for example through + * mbedtls_ecp_load() or mbedtls_ecp_tls_read_group(). + * \param z The destination MPI (shared secret). + * This must be initialized. + * \param Q The public key from another party. + * This must be initialized. + * \param d Our secret exponent (private key). + * This must be initialized. + * \param f_rng The RNG function. This may be \c NULL if randomization + * of intermediate results during the ECP computations is + * not needed (discouraged). See the documentation of + * mbedtls_ecp_mul() for more. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't need a + * context argument. + * + * \return \c 0 on success. + * \return Another \c MBEDTLS_ERR_ECP_XXX or + * \c MBEDTLS_MPI_XXX error code on failure. + */ +int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z, + const mbedtls_ecp_point *Q, const mbedtls_mpi *d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function initializes an ECDH context. + * + * \param ctx The ECDH context to initialize. This must not be \c NULL. + */ +void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx ); + +/** + * \brief This function sets up the ECDH context with the information + * given. + * + * This function should be called after mbedtls_ecdh_init() but + * before mbedtls_ecdh_make_params(). There is no need to call + * this function before mbedtls_ecdh_read_params(). + * + * This is the first function used by a TLS server for ECDHE + * ciphersuites. + * + * \param ctx The ECDH context to set up. This must be initialized. + * \param grp_id The group id of the group to set up the context for. + * + * \return \c 0 on success. + */ +int mbedtls_ecdh_setup( mbedtls_ecdh_context *ctx, + mbedtls_ecp_group_id grp_id ); + +/** + * \brief This function frees a context. + * + * \param ctx The context to free. This may be \c NULL, in which + * case this function does nothing. If it is not \c NULL, + * it must point to an initialized ECDH context. + */ +void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx ); + +/** + * \brief This function generates an EC key pair and exports its + * in the format used in a TLS ServerKeyExchange handshake + * message. + * + * This is the second function used by a TLS server for ECDHE + * ciphersuites. (It is called after mbedtls_ecdh_setup().) + * + * \see ecp.h + * + * \param ctx The ECDH context to use. This must be initialized + * and bound to a group, for example via mbedtls_ecdh_setup(). + * \param olen The address at which to store the number of Bytes written. + * \param buf The destination buffer. This must be a writable buffer of + * length \p blen Bytes. + * \param blen The length of the destination buffer \p buf in Bytes. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL in case \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure. + */ +int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function parses the ECDHE parameters in a + * TLS ServerKeyExchange handshake message. + * + * \note In a TLS handshake, this is the how the client + * sets up its ECDHE context from the server's public + * ECDHE key material. + * + * \see ecp.h + * + * \param ctx The ECDHE context to use. This must be initialized. + * \param buf On input, \c *buf must be the start of the input buffer. + * On output, \c *buf is updated to point to the end of the + * data that has been read. On success, this is the first byte + * past the end of the ServerKeyExchange parameters. + * On error, this is the point at which an error has been + * detected, which is usually not useful except to debug + * failures. + * \param end The end of the input buffer. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX error code on failure. + * + */ +int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx, + const unsigned char **buf, + const unsigned char *end ); + +/** + * \brief This function sets up an ECDH context from an EC key. + * + * It is used by clients and servers in place of the + * ServerKeyEchange for static ECDH, and imports ECDH + * parameters from the EC key information of a certificate. + * + * \see ecp.h + * + * \param ctx The ECDH context to set up. This must be initialized. + * \param key The EC key to use. This must be initialized. + * \param side Defines the source of the key. Possible values are: + * - #MBEDTLS_ECDH_OURS: The key is ours. + * - #MBEDTLS_ECDH_THEIRS: The key is that of the peer. + * + * \return \c 0 on success. + * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure. + * + */ +int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, + const mbedtls_ecp_keypair *key, + mbedtls_ecdh_side side ); + +/** + * \brief This function generates a public key and exports it + * as a TLS ClientKeyExchange payload. + * + * This is the second function used by a TLS client for ECDH(E) + * ciphersuites. + * + * \see ecp.h + * + * \param ctx The ECDH context to use. This must be initialized + * and bound to a group, the latter usually by + * mbedtls_ecdh_read_params(). + * \param olen The address at which to store the number of Bytes written. + * This must not be \c NULL. + * \param buf The destination buffer. This must be a writable buffer + * of length \p blen Bytes. + * \param blen The size of the destination buffer \p buf in Bytes. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL in case \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure. + */ +int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function parses and processes the ECDHE payload of a + * TLS ClientKeyExchange message. + * + * This is the third function used by a TLS server for ECDH(E) + * ciphersuites. (It is called after mbedtls_ecdh_setup() and + * mbedtls_ecdh_make_params().) + * + * \see ecp.h + * + * \param ctx The ECDH context to use. This must be initialized + * and bound to a group, for example via mbedtls_ecdh_setup(). + * \param buf The pointer to the ClientKeyExchange payload. This must + * be a readable buffer of length \p blen Bytes. + * \param blen The length of the input buffer \p buf in Bytes. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX error code on failure. + */ +int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx, + const unsigned char *buf, size_t blen ); + +/** + * \brief This function derives and exports the shared secret. + * + * This is the last function used by both TLS client + * and servers. + * + * \note If \p f_rng is not NULL, it is used to implement + * countermeasures against side-channel attacks. + * For more information, see mbedtls_ecp_mul(). + * + * \see ecp.h + + * \param ctx The ECDH context to use. This must be initialized + * and have its own private key generated and the peer's + * public key imported. + * \param olen The address at which to store the total number of + * Bytes written on success. This must not be \c NULL. + * \param buf The buffer to write the generated shared key to. This + * must be a writable buffer of size \p blen Bytes. + * \param blen The length of the destination buffer \p buf in Bytes. + * \param f_rng The RNG function, for blinding purposes. This may + * b \c NULL if blinding isn't needed. + * \param p_rng The RNG context. This may be \c NULL if \p f_rng + * doesn't need a context argument. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure. + */ +int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief This function enables restartable EC computations for this + * context. (Default: disabled.) + * + * \see \c mbedtls_ecp_set_max_ops() + * + * \note It is not possible to safely disable restartable + * computations once enabled, except by free-ing the context, + * which cancels possible in-progress operations. + * + * \param ctx The ECDH context to use. This must be initialized. + */ +void mbedtls_ecdh_enable_restart( mbedtls_ecdh_context *ctx ); +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +#ifdef __cplusplus +} +#endif + +#endif /* ecdh.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ecdsa.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ecdsa.h new file mode 100644 index 0000000..264a638 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ecdsa.h @@ -0,0 +1,626 @@ +/** + * \file ecdsa.h + * + * \brief This file contains ECDSA definitions and functions. + * + * The Elliptic Curve Digital Signature Algorithm (ECDSA) is defined in + * Standards for Efficient Cryptography Group (SECG): + * SEC1 Elliptic Curve Cryptography. + * The use of ECDSA for TLS is defined in RFC-4492: Elliptic Curve + * Cryptography (ECC) Cipher Suites for Transport Layer Security (TLS). + * + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_ECDSA_H +#define MBEDTLS_ECDSA_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/ecp.h" +#include "mbedtls/md.h" + +/** + * \brief Maximum ECDSA signature size for a given curve bit size + * + * \param bits Curve size in bits + * \return Maximum signature size in bytes + * + * \note This macro returns a compile-time constant if its argument + * is one. It may evaluate its argument multiple times. + */ +/* + * Ecdsa-Sig-Value ::= SEQUENCE { + * r INTEGER, + * s INTEGER + * } + * + * For each of r and s, the value (V) may include an extra initial "0" bit. + */ +#define MBEDTLS_ECDSA_MAX_SIG_LEN( bits ) \ + ( /*T,L of SEQUENCE*/ ( ( bits ) >= 61 * 8 ? 3 : 2 ) + \ + /*T,L of r,s*/ 2 * ( ( ( bits ) >= 127 * 8 ? 3 : 2 ) + \ + /*V of r,s*/ ( ( bits ) + 8 ) / 8 ) ) + +/** The maximal size of an ECDSA signature in Bytes. */ +#define MBEDTLS_ECDSA_MAX_LEN MBEDTLS_ECDSA_MAX_SIG_LEN( MBEDTLS_ECP_MAX_BITS ) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief The ECDSA context structure. + * + * \warning Performing multiple operations concurrently on the same + * ECDSA context is not supported; objects of this type + * should not be shared between multiple threads. + */ +typedef mbedtls_ecp_keypair mbedtls_ecdsa_context; + +#if defined(MBEDTLS_ECP_RESTARTABLE) + +/** + * \brief Internal restart context for ecdsa_verify() + * + * \note Opaque struct, defined in ecdsa.c + */ +typedef struct mbedtls_ecdsa_restart_ver mbedtls_ecdsa_restart_ver_ctx; + +/** + * \brief Internal restart context for ecdsa_sign() + * + * \note Opaque struct, defined in ecdsa.c + */ +typedef struct mbedtls_ecdsa_restart_sig mbedtls_ecdsa_restart_sig_ctx; + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +/** + * \brief Internal restart context for ecdsa_sign_det() + * + * \note Opaque struct, defined in ecdsa.c + */ +typedef struct mbedtls_ecdsa_restart_det mbedtls_ecdsa_restart_det_ctx; +#endif + +/** + * \brief General context for resuming ECDSA operations + */ +typedef struct +{ + mbedtls_ecp_restart_ctx ecp; /*!< base context for ECP restart and + shared administrative info */ + mbedtls_ecdsa_restart_ver_ctx *ver; /*!< ecdsa_verify() sub-context */ + mbedtls_ecdsa_restart_sig_ctx *sig; /*!< ecdsa_sign() sub-context */ +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) + mbedtls_ecdsa_restart_det_ctx *det; /*!< ecdsa_sign_det() sub-context */ +#endif +} mbedtls_ecdsa_restart_ctx; + +#else /* MBEDTLS_ECP_RESTARTABLE */ + +/* Now we can declare functions that take a pointer to that */ +typedef void mbedtls_ecdsa_restart_ctx; + +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +/** + * \brief This function checks whether a given group can be used + * for ECDSA. + * + * \param gid The ECP group ID to check. + * + * \return \c 1 if the group can be used, \c 0 otherwise + */ +int mbedtls_ecdsa_can_do( mbedtls_ecp_group_id gid ); + +/** + * \brief This function computes the ECDSA signature of a + * previously-hashed message. + * + * \note The deterministic version implemented in + * mbedtls_ecdsa_sign_det() is usually preferred. + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated + * as defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.3, step 5. + * + * \see ecp.h + * + * \param grp The context for the elliptic curve to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param r The MPI context in which to store the first part + * the signature. This must be initialized. + * \param s The MPI context in which to store the second part + * the signature. This must be initialized. + * \param d The private signing key. This must be initialized. + * \param buf The content to be signed. This is usually the hash of + * the original data to be signed. This must be a readable + * buffer of length \p blen Bytes. It may be \c NULL if + * \p blen is zero. + * \param blen The length of \p buf in Bytes. + * \param f_rng The RNG function. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context parameter. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX + * or \c MBEDTLS_MPI_XXX error code on failure. + */ +int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function computes the ECDSA signature of a + * previously-hashed message, deterministic version. + * + * For more information, see RFC-6979: Deterministic + * Usage of the Digital Signature Algorithm (DSA) and Elliptic + * Curve Digital Signature Algorithm (ECDSA). + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.3, step 5. + * + * \warning Since the output of the internal RNG is always the same for + * the same key and message, this limits the efficiency of + * blinding and leaks information through side channels. For + * secure behavior use mbedtls_ecdsa_sign_det_ext() instead. + * + * (Optimally the blinding is a random value that is different + * on every execution. In this case the blinding is still + * random from the attackers perspective, but is the same on + * each execution. This means that this blinding does not + * prevent attackers from recovering secrets by combining + * several measurement traces, but may prevent some attacks + * that exploit relationships between secret data.) + * + * \see ecp.h + * + * \param grp The context for the elliptic curve to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param r The MPI context in which to store the first part + * the signature. This must be initialized. + * \param s The MPI context in which to store the second part + * the signature. This must be initialized. + * \param d The private signing key. This must be initialized + * and setup, for example through mbedtls_ecp_gen_privkey(). + * \param buf The hashed content to be signed. This must be a readable + * buffer of length \p blen Bytes. It may be \c NULL if + * \p blen is zero. + * \param blen The length of \p buf in Bytes. + * \param md_alg The hash algorithm used to hash the original data. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX + * error code on failure. + */ +int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, + mbedtls_mpi *s, const mbedtls_mpi *d, + const unsigned char *buf, size_t blen, + mbedtls_md_type_t md_alg ) MBEDTLS_DEPRECATED; +#undef MBEDTLS_DEPRECATED +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief This function computes the ECDSA signature of a + * previously-hashed message, deterministic version. + * + * For more information, see RFC-6979: Deterministic + * Usage of the Digital Signature Algorithm (DSA) and Elliptic + * Curve Digital Signature Algorithm (ECDSA). + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.3, step 5. + * + * \see ecp.h + * + * \param grp The context for the elliptic curve to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param r The MPI context in which to store the first part + * the signature. This must be initialized. + * \param s The MPI context in which to store the second part + * the signature. This must be initialized. + * \param d The private signing key. This must be initialized + * and setup, for example through mbedtls_ecp_gen_privkey(). + * \param buf The hashed content to be signed. This must be a readable + * buffer of length \p blen Bytes. It may be \c NULL if + * \p blen is zero. + * \param blen The length of \p buf in Bytes. + * \param md_alg The hash algorithm used to hash the original data. + * \param f_rng_blind The RNG function used for blinding. This must not be + * \c NULL. + * \param p_rng_blind The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context parameter. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX + * error code on failure. + */ +int mbedtls_ecdsa_sign_det_ext( mbedtls_ecp_group *grp, mbedtls_mpi *r, + mbedtls_mpi *s, const mbedtls_mpi *d, + const unsigned char *buf, size_t blen, + mbedtls_md_type_t md_alg, + int (*f_rng_blind)(void *, unsigned char *, size_t), + void *p_rng_blind ); +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ + +/** + * \brief This function verifies the ECDSA signature of a + * previously-hashed message. + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.4, step 3. + * + * \see ecp.h + * + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param buf The hashed content that was signed. This must be a readable + * buffer of length \p blen Bytes. It may be \c NULL if + * \p blen is zero. + * \param blen The length of \p buf in Bytes. + * \param Q The public key to use for verification. This must be + * initialized and setup. + * \param r The first integer of the signature. + * This must be initialized. + * \param s The second integer of the signature. + * This must be initialized. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the signature + * is invalid. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX + * error code on failure for any other reason. + */ +int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp, + const unsigned char *buf, size_t blen, + const mbedtls_ecp_point *Q, const mbedtls_mpi *r, + const mbedtls_mpi *s); + +/** + * \brief This function computes the ECDSA signature and writes it + * to a buffer, serialized as defined in RFC-4492: + * Elliptic Curve Cryptography (ECC) Cipher Suites for + * Transport Layer Security (TLS). + * + * \warning It is not thread-safe to use the same context in + * multiple threads. + * + * \note The deterministic version is used if + * #MBEDTLS_ECDSA_DETERMINISTIC is defined. For more + * information, see RFC-6979: Deterministic Usage + * of the Digital Signature Algorithm (DSA) and Elliptic + * Curve Digital Signature Algorithm (ECDSA). + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.3, step 5. + * + * \see ecp.h + * + * \param ctx The ECDSA context to use. This must be initialized + * and have a group and private key bound to it, for example + * via mbedtls_ecdsa_genkey() or mbedtls_ecdsa_from_keypair(). + * \param md_alg The message digest that was used to hash the message. + * \param hash The message hash to be signed. This must be a readable + * buffer of length \p blen Bytes. + * \param hlen The length of the hash \p hash in Bytes. + * \param sig The buffer to which to write the signature. This must be a + * writable buffer of length at least twice as large as the + * size of the curve used, plus 9. For example, 73 Bytes if + * a 256-bit curve is used. A buffer length of + * #MBEDTLS_ECDSA_MAX_LEN is always safe. + * \param slen The address at which to store the actual length of + * the signature written. Must not be \c NULL. + * \param f_rng The RNG function. This must not be \c NULL if + * #MBEDTLS_ECDSA_DETERMINISTIC is unset. Otherwise, + * it is used only for blinding and may be set to \c NULL, but + * doing so is DEPRECATED. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't use a context. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or + * \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function computes the ECDSA signature and writes it + * to a buffer, in a restartable way. + * + * \see \c mbedtls_ecdsa_write_signature() + * + * \note This function is like \c mbedtls_ecdsa_write_signature() + * but it can return early and restart according to the limit + * set with \c mbedtls_ecp_set_max_ops() to reduce blocking. + * + * \param ctx The ECDSA context to use. This must be initialized + * and have a group and private key bound to it, for example + * via mbedtls_ecdsa_genkey() or mbedtls_ecdsa_from_keypair(). + * \param md_alg The message digest that was used to hash the message. + * \param hash The message hash to be signed. This must be a readable + * buffer of length \p blen Bytes. + * \param hlen The length of the hash \p hash in Bytes. + * \param sig The buffer to which to write the signature. This must be a + * writable buffer of length at least twice as large as the + * size of the curve used, plus 9. For example, 73 Bytes if + * a 256-bit curve is used. A buffer length of + * #MBEDTLS_ECDSA_MAX_LEN is always safe. + * \param slen The address at which to store the actual length of + * the signature written. Must not be \c NULL. + * \param f_rng The RNG function. This must not be \c NULL if + * #MBEDTLS_ECDSA_DETERMINISTIC is unset. Otherwise, + * it is unused and may be set to \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't use a context. + * \param rs_ctx The restart context to use. This may be \c NULL to disable + * restarting. If it is not \c NULL, it must point to an + * initialized restart context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or + * \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_ecdsa_write_signature_restartable( mbedtls_ecdsa_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_ecdsa_restart_ctx *rs_ctx ); + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function computes an ECDSA signature and writes + * it to a buffer, serialized as defined in RFC-4492: + * Elliptic Curve Cryptography (ECC) Cipher Suites for + * Transport Layer Security (TLS). + * + * The deterministic version is defined in RFC-6979: + * Deterministic Usage of the Digital Signature Algorithm (DSA) + * and Elliptic Curve Digital Signature Algorithm (ECDSA). + * + * \warning It is not thread-safe to use the same context in + * multiple threads. + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.3, step 5. + * + * \see ecp.h + * + * \deprecated Superseded by mbedtls_ecdsa_write_signature() in + * Mbed TLS version 2.0 and later. + * + * \param ctx The ECDSA context to use. This must be initialized + * and have a group and private key bound to it, for example + * via mbedtls_ecdsa_genkey() or mbedtls_ecdsa_from_keypair(). + * \param hash The message hash to be signed. This must be a readable + * buffer of length \p blen Bytes. + * \param hlen The length of the hash \p hash in Bytes. + * \param sig The buffer to which to write the signature. This must be a + * writable buffer of length at least twice as large as the + * size of the curve used, plus 9. For example, 73 Bytes if + * a 256-bit curve is used. A buffer length of + * #MBEDTLS_ECDSA_MAX_LEN is always safe. + * \param slen The address at which to store the actual length of + * the signature written. Must not be \c NULL. + * \param md_alg The message digest that was used to hash the message. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or + * \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_ecdsa_write_signature_det( mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + mbedtls_md_type_t md_alg ) MBEDTLS_DEPRECATED; +#undef MBEDTLS_DEPRECATED +#endif /* MBEDTLS_DEPRECATED_REMOVED */ +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ + +/** + * \brief This function reads and verifies an ECDSA signature. + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.4, step 3. + * + * \see ecp.h + * + * \param ctx The ECDSA context to use. This must be initialized + * and have a group and public key bound to it. + * \param hash The message hash that was signed. This must be a readable + * buffer of length \p size Bytes. + * \param hlen The size of the hash \p hash. + * \param sig The signature to read and verify. This must be a readable + * buffer of length \p slen Bytes. + * \param slen The size of \p sig in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if signature is invalid. + * \return #MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH if there is a valid + * signature in \p sig, but its length is less than \p siglen. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_ERR_MPI_XXX + * error code on failure for any other reason. + */ +int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + const unsigned char *sig, size_t slen ); + +/** + * \brief This function reads and verifies an ECDSA signature, + * in a restartable way. + * + * \see \c mbedtls_ecdsa_read_signature() + * + * \note This function is like \c mbedtls_ecdsa_read_signature() + * but it can return early and restart according to the limit + * set with \c mbedtls_ecp_set_max_ops() to reduce blocking. + * + * \param ctx The ECDSA context to use. This must be initialized + * and have a group and public key bound to it. + * \param hash The message hash that was signed. This must be a readable + * buffer of length \p size Bytes. + * \param hlen The size of the hash \p hash. + * \param sig The signature to read and verify. This must be a readable + * buffer of length \p slen Bytes. + * \param slen The size of \p sig in Bytes. + * \param rs_ctx The restart context to use. This may be \c NULL to disable + * restarting. If it is not \c NULL, it must point to an + * initialized restart context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if signature is invalid. + * \return #MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH if there is a valid + * signature in \p sig, but its length is less than \p siglen. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_ERR_MPI_XXX + * error code on failure for any other reason. + */ +int mbedtls_ecdsa_read_signature_restartable( mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + const unsigned char *sig, size_t slen, + mbedtls_ecdsa_restart_ctx *rs_ctx ); + +/** + * \brief This function generates an ECDSA keypair on the given curve. + * + * \see ecp.h + * + * \param ctx The ECDSA context to store the keypair in. + * This must be initialized. + * \param gid The elliptic curve to use. One of the various + * \c MBEDTLS_ECP_DP_XXX macros depending on configuration. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX code on failure. + */ +int mbedtls_ecdsa_genkey( mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief This function sets up an ECDSA context from an EC key pair. + * + * \see ecp.h + * + * \param ctx The ECDSA context to setup. This must be initialized. + * \param key The EC key to use. This must be initialized and hold + * a private-public key pair or a public key. In the former + * case, the ECDSA context may be used for signature creation + * and verification after this call. In the latter case, it + * may be used for signature verification. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX code on failure. + */ +int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, + const mbedtls_ecp_keypair *key ); + +/** + * \brief This function initializes an ECDSA context. + * + * \param ctx The ECDSA context to initialize. + * This must not be \c NULL. + */ +void mbedtls_ecdsa_init( mbedtls_ecdsa_context *ctx ); + +/** + * \brief This function frees an ECDSA context. + * + * \param ctx The ECDSA context to free. This may be \c NULL, + * in which case this function does nothing. If it + * is not \c NULL, it must be initialized. + */ +void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Initialize a restart context. + * + * \param ctx The restart context to initialize. + * This must not be \c NULL. + */ +void mbedtls_ecdsa_restart_init( mbedtls_ecdsa_restart_ctx *ctx ); + +/** + * \brief Free the components of a restart context. + * + * \param ctx The restart context to free. This may be \c NULL, + * in which case this function does nothing. If it + * is not \c NULL, it must be initialized. + */ +void mbedtls_ecdsa_restart_free( mbedtls_ecdsa_restart_ctx *ctx ); +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +#ifdef __cplusplus +} +#endif + +#endif /* ecdsa.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ecjpake.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ecjpake.h new file mode 100644 index 0000000..891705d --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ecjpake.h @@ -0,0 +1,275 @@ +/** + * \file ecjpake.h + * + * \brief Elliptic curve J-PAKE + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_ECJPAKE_H +#define MBEDTLS_ECJPAKE_H + +/* + * J-PAKE is a password-authenticated key exchange that allows deriving a + * strong shared secret from a (potentially low entropy) pre-shared + * passphrase, with forward secrecy and mutual authentication. + * https://en.wikipedia.org/wiki/Password_Authenticated_Key_Exchange_by_Juggling + * + * This file implements the Elliptic Curve variant of J-PAKE, + * as defined in Chapter 7.4 of the Thread v1.0 Specification, + * available to members of the Thread Group http://threadgroup.org/ + * + * As the J-PAKE algorithm is inherently symmetric, so is our API. + * Each party needs to send its first round message, in any order, to the + * other party, then each sends its second round message, in any order. + * The payloads are serialized in a way suitable for use in TLS, but could + * also be use outside TLS. + */ +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/ecp.h" +#include "mbedtls/md.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Roles in the EC J-PAKE exchange + */ +typedef enum { + MBEDTLS_ECJPAKE_CLIENT = 0, /**< Client */ + MBEDTLS_ECJPAKE_SERVER, /**< Server */ +} mbedtls_ecjpake_role; + +#if !defined(MBEDTLS_ECJPAKE_ALT) +/** + * EC J-PAKE context structure. + * + * J-PAKE is a symmetric protocol, except for the identifiers used in + * Zero-Knowledge Proofs, and the serialization of the second message + * (KeyExchange) as defined by the Thread spec. + * + * In order to benefit from this symmetry, we choose a different naming + * convetion from the Thread v1.0 spec. Correspondance is indicated in the + * description as a pair C: client name, S: server name + */ +typedef struct mbedtls_ecjpake_context +{ + const mbedtls_md_info_t *md_info; /**< Hash to use */ + mbedtls_ecp_group grp; /**< Elliptic curve */ + mbedtls_ecjpake_role role; /**< Are we client or server? */ + int point_format; /**< Format for point export */ + + mbedtls_ecp_point Xm1; /**< My public key 1 C: X1, S: X3 */ + mbedtls_ecp_point Xm2; /**< My public key 2 C: X2, S: X4 */ + mbedtls_ecp_point Xp1; /**< Peer public key 1 C: X3, S: X1 */ + mbedtls_ecp_point Xp2; /**< Peer public key 2 C: X4, S: X2 */ + mbedtls_ecp_point Xp; /**< Peer public key C: Xs, S: Xc */ + + mbedtls_mpi xm1; /**< My private key 1 C: x1, S: x3 */ + mbedtls_mpi xm2; /**< My private key 2 C: x2, S: x4 */ + + mbedtls_mpi s; /**< Pre-shared secret (passphrase) */ +} mbedtls_ecjpake_context; + +#else /* MBEDTLS_ECJPAKE_ALT */ +#include "ecjpake_alt.h" +#endif /* MBEDTLS_ECJPAKE_ALT */ + +/** + * \brief Initialize an ECJPAKE context. + * + * \param ctx The ECJPAKE context to initialize. + * This must not be \c NULL. + */ +void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx ); + +/** + * \brief Set up an ECJPAKE context for use. + * + * \note Currently the only values for hash/curve allowed by the + * standard are #MBEDTLS_MD_SHA256/#MBEDTLS_ECP_DP_SECP256R1. + * + * \param ctx The ECJPAKE context to set up. This must be initialized. + * \param role The role of the caller. This must be either + * #MBEDTLS_ECJPAKE_CLIENT or #MBEDTLS_ECJPAKE_SERVER. + * \param hash The identifier of the hash function to use, + * for example #MBEDTLS_MD_SHA256. + * \param curve The identifier of the elliptic curve to use, + * for example #MBEDTLS_ECP_DP_SECP256R1. + * \param secret The pre-shared secret (passphrase). This must be + * a readable buffer of length \p len Bytes. It need + * only be valid for the duration of this call. + * \param len The length of the pre-shared secret \p secret. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx, + mbedtls_ecjpake_role role, + mbedtls_md_type_t hash, + mbedtls_ecp_group_id curve, + const unsigned char *secret, + size_t len ); + +/** + * \brief Check if an ECJPAKE context is ready for use. + * + * \param ctx The ECJPAKE context to check. This must be + * initialized. + * + * \return \c 0 if the context is ready for use. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA otherwise. + */ +int mbedtls_ecjpake_check( const mbedtls_ecjpake_context *ctx ); + +/** + * \brief Generate and write the first round message + * (TLS: contents of the Client/ServerHello extension, + * excluding extension type and length bytes). + * + * \param ctx The ECJPAKE context to use. This must be + * initialized and set up. + * \param buf The buffer to write the contents to. This must be a + * writable buffer of length \p len Bytes. + * \param len The length of \p buf in Bytes. + * \param olen The address at which to store the total number + * of Bytes written to \p buf. This must not be \c NULL. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. This + * may be \c NULL if \p f_rng doesn't use a context. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx, + unsigned char *buf, size_t len, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Read and process the first round message + * (TLS: contents of the Client/ServerHello extension, + * excluding extension type and length bytes). + * + * \param ctx The ECJPAKE context to use. This must be initialized + * and set up. + * \param buf The buffer holding the first round message. This must + * be a readable buffer of length \p len Bytes. + * \param len The length in Bytes of \p buf. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx, + const unsigned char *buf, + size_t len ); + +/** + * \brief Generate and write the second round message + * (TLS: contents of the Client/ServerKeyExchange). + * + * \param ctx The ECJPAKE context to use. This must be initialized, + * set up, and already have performed round one. + * \param buf The buffer to write the round two contents to. + * This must be a writable buffer of length \p len Bytes. + * \param len The size of \p buf in Bytes. + * \param olen The address at which to store the total number of Bytes + * written to \p buf. This must not be \c NULL. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. This + * may be \c NULL if \p f_rng doesn't use a context. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx, + unsigned char *buf, size_t len, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Read and process the second round message + * (TLS: contents of the Client/ServerKeyExchange). + * + * \param ctx The ECJPAKE context to use. This must be initialized + * and set up and already have performed round one. + * \param buf The buffer holding the second round message. This must + * be a readable buffer of length \p len Bytes. + * \param len The length in Bytes of \p buf. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx, + const unsigned char *buf, + size_t len ); + +/** + * \brief Derive the shared secret + * (TLS: Pre-Master Secret). + * + * \param ctx The ECJPAKE context to use. This must be initialized, + * set up and have performed both round one and two. + * \param buf The buffer to write the derived secret to. This must + * be a writable buffer of length \p len Bytes. + * \param len The length of \p buf in Bytes. + * \param olen The address at which to store the total number of Bytes + * written to \p buf. This must not be \c NULL. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. This + * may be \c NULL if \p f_rng doesn't use a context. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx, + unsigned char *buf, size_t len, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This clears an ECJPAKE context and frees any + * embedded data structure. + * + * \param ctx The ECJPAKE context to free. This may be \c NULL, + * in which case this function does nothing. If it is not + * \c NULL, it must point to an initialized ECJPAKE context. + */ +void mbedtls_ecjpake_free( mbedtls_ecjpake_context *ctx ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_ecjpake_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + + +#endif /* ecjpake.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ecp.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ecp.h new file mode 100644 index 0000000..34dd0ea --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ecp.h @@ -0,0 +1,1254 @@ +/** + * \file ecp.h + * + * \brief This file provides an API for Elliptic Curves over GF(P) (ECP). + * + * The use of ECP in cryptography and TLS is defined in + * Standards for Efficient Cryptography Group (SECG): SEC1 + * Elliptic Curve Cryptography and + * RFC-4492: Elliptic Curve Cryptography (ECC) Cipher Suites + * for Transport Layer Security (TLS). + * + * RFC-2409: The Internet Key Exchange (IKE) defines ECP + * group types. + * + */ + +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_ECP_H +#define MBEDTLS_ECP_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/bignum.h" + +/* + * ECP error codes + */ +#define MBEDTLS_ERR_ECP_BAD_INPUT_DATA -0x4F80 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL -0x4F00 /**< The buffer is too small to write to. */ +#define MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE -0x4E80 /**< The requested feature is not available, for example, the requested curve is not supported. */ +#define MBEDTLS_ERR_ECP_VERIFY_FAILED -0x4E00 /**< The signature is not valid. */ +#define MBEDTLS_ERR_ECP_ALLOC_FAILED -0x4D80 /**< Memory allocation failed. */ +#define MBEDTLS_ERR_ECP_RANDOM_FAILED -0x4D00 /**< Generation of random value, such as ephemeral key, failed. */ +#define MBEDTLS_ERR_ECP_INVALID_KEY -0x4C80 /**< Invalid private or public key. */ +#define MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH -0x4C00 /**< The buffer contains a valid signature followed by more data. */ + +/* MBEDTLS_ERR_ECP_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_ECP_HW_ACCEL_FAILED -0x4B80 /**< The ECP hardware accelerator failed. */ + +#define MBEDTLS_ERR_ECP_IN_PROGRESS -0x4B00 /**< Operation in progress, call again with the same parameters to continue. */ + +/* Flags indicating whether to include code that is specific to certain + * types of curves. These flags are for internal library use only. */ +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +#define MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED +#endif +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) || \ + defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) +#define MBEDTLS_ECP_MONTGOMERY_ENABLED +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Domain-parameter identifiers: curve, subgroup, and generator. + * + * \note Only curves over prime fields are supported. + * + * \warning This library does not support validation of arbitrary domain + * parameters. Therefore, only standardized domain parameters from trusted + * sources should be used. See mbedtls_ecp_group_load(). + */ +/* Note: when adding a new curve: + * - Add it at the end of this enum, otherwise you'll break the ABI by + * changing the numerical value for existing curves. + * - Increment MBEDTLS_ECP_DP_MAX below if needed. + * - Add the corresponding MBEDTLS_ECP_DP_xxx_ENABLED macro definition to + * config.h. + * - List the curve as a dependency of MBEDTLS_ECP_C and + * MBEDTLS_ECDSA_C if supported in check_config.h. + * - Add the curve to the appropriate curve type macro + * MBEDTLS_ECP_yyy_ENABLED above. + * - Add the necessary definitions to ecp_curves.c. + * - Add the curve to the ecp_supported_curves array in ecp.c. + * - Add the curve to applicable profiles in x509_crt.c if applicable. + */ +typedef enum +{ + MBEDTLS_ECP_DP_NONE = 0, /*!< Curve not defined. */ + MBEDTLS_ECP_DP_SECP192R1, /*!< Domain parameters for the 192-bit curve defined by FIPS 186-4 and SEC1. */ + MBEDTLS_ECP_DP_SECP224R1, /*!< Domain parameters for the 224-bit curve defined by FIPS 186-4 and SEC1. */ + MBEDTLS_ECP_DP_SECP256R1, /*!< Domain parameters for the 256-bit curve defined by FIPS 186-4 and SEC1. */ + MBEDTLS_ECP_DP_SECP384R1, /*!< Domain parameters for the 384-bit curve defined by FIPS 186-4 and SEC1. */ + MBEDTLS_ECP_DP_SECP521R1, /*!< Domain parameters for the 521-bit curve defined by FIPS 186-4 and SEC1. */ + MBEDTLS_ECP_DP_BP256R1, /*!< Domain parameters for 256-bit Brainpool curve. */ + MBEDTLS_ECP_DP_BP384R1, /*!< Domain parameters for 384-bit Brainpool curve. */ + MBEDTLS_ECP_DP_BP512R1, /*!< Domain parameters for 512-bit Brainpool curve. */ + MBEDTLS_ECP_DP_CURVE25519, /*!< Domain parameters for Curve25519. */ + MBEDTLS_ECP_DP_SECP192K1, /*!< Domain parameters for 192-bit "Koblitz" curve. */ + MBEDTLS_ECP_DP_SECP224K1, /*!< Domain parameters for 224-bit "Koblitz" curve. */ + MBEDTLS_ECP_DP_SECP256K1, /*!< Domain parameters for 256-bit "Koblitz" curve. */ + MBEDTLS_ECP_DP_CURVE448, /*!< Domain parameters for Curve448. */ +} mbedtls_ecp_group_id; + +/** + * The number of supported curves, plus one for #MBEDTLS_ECP_DP_NONE. + * + * \note Montgomery curves are currently excluded. + */ +#define MBEDTLS_ECP_DP_MAX 12 + +/* + * Curve types + */ +typedef enum +{ + MBEDTLS_ECP_TYPE_NONE = 0, + MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS, /* y^2 = x^3 + a x + b */ + MBEDTLS_ECP_TYPE_MONTGOMERY, /* y^2 = x^3 + a x^2 + x */ +} mbedtls_ecp_curve_type; + +/** + * Curve information, for use by other modules. + */ +typedef struct mbedtls_ecp_curve_info +{ + mbedtls_ecp_group_id grp_id; /*!< An internal identifier. */ + uint16_t tls_id; /*!< The TLS NamedCurve identifier. */ + uint16_t bit_size; /*!< The curve size in bits. */ + const char *name; /*!< A human-friendly name. */ +} mbedtls_ecp_curve_info; + +/** + * \brief The ECP point structure, in Jacobian coordinates. + * + * \note All functions expect and return points satisfying + * the following condition: Z == 0 or + * Z == 1. Other values of \p Z are + * used only by internal functions. + * The point is zero, or "at infinity", if Z == 0. + * Otherwise, \p X and \p Y are its standard (affine) + * coordinates. + */ +typedef struct mbedtls_ecp_point +{ + mbedtls_mpi X; /*!< The X coordinate of the ECP point. */ + mbedtls_mpi Y; /*!< The Y coordinate of the ECP point. */ + mbedtls_mpi Z; /*!< The Z coordinate of the ECP point. */ +} +mbedtls_ecp_point; + +#if !defined(MBEDTLS_ECP_ALT) +/* + * default mbed TLS elliptic curve arithmetic implementation + * + * (in case MBEDTLS_ECP_ALT is defined then the developer has to provide an + * alternative implementation for the whole module and it will replace this + * one.) + */ + +/** + * \brief The ECP group structure. + * + * We consider two types of curve equations: + *
  • Short Weierstrass: y^2 = x^3 + A x + B mod P + * (SEC1 + RFC-4492)
  • + *
  • Montgomery: y^2 = x^3 + A x^2 + x mod P (Curve25519, + * Curve448)
+ * In both cases, the generator (\p G) for a prime-order subgroup is fixed. + * + * For Short Weierstrass, this subgroup is the whole curve, and its + * cardinality is denoted by \p N. Our code requires that \p N is an + * odd prime as mbedtls_ecp_mul() requires an odd number, and + * mbedtls_ecdsa_sign() requires that it is prime for blinding purposes. + * + * For Montgomery curves, we do not store \p A, but (A + 2) / 4, + * which is the quantity used in the formulas. Additionally, \p nbits is + * not the size of \p N but the required size for private keys. + * + * If \p modp is NULL, reduction modulo \p P is done using a generic algorithm. + * Otherwise, \p modp must point to a function that takes an \p mbedtls_mpi in the + * range of 0..2^(2*pbits)-1, and transforms it in-place to an integer + * which is congruent mod \p P to the given MPI, and is close enough to \p pbits + * in size, so that it may be efficiently brought in the 0..P-1 range by a few + * additions or subtractions. Therefore, it is only an approximative modular + * reduction. It must return 0 on success and non-zero on failure. + * + * \note Alternative implementations must keep the group IDs distinct. If + * two group structures have the same ID, then they must be + * identical. + * + */ +typedef struct mbedtls_ecp_group +{ + mbedtls_ecp_group_id id; /*!< An internal group identifier. */ + mbedtls_mpi P; /*!< The prime modulus of the base field. */ + mbedtls_mpi A; /*!< For Short Weierstrass: \p A in the equation. For + Montgomery curves: (A + 2) / 4. */ + mbedtls_mpi B; /*!< For Short Weierstrass: \p B in the equation. + For Montgomery curves: unused. */ + mbedtls_ecp_point G; /*!< The generator of the subgroup used. */ + mbedtls_mpi N; /*!< The order of \p G. */ + size_t pbits; /*!< The number of bits in \p P.*/ + size_t nbits; /*!< For Short Weierstrass: The number of bits in \p P. + For Montgomery curves: the number of bits in the + private keys. */ + unsigned int h; /*!< \internal 1 if the constants are static. */ + int (*modp)(mbedtls_mpi *); /*!< The function for fast pseudo-reduction + mod \p P (see above).*/ + int (*t_pre)(mbedtls_ecp_point *, void *); /*!< Unused. */ + int (*t_post)(mbedtls_ecp_point *, void *); /*!< Unused. */ + void *t_data; /*!< Unused. */ + mbedtls_ecp_point *T; /*!< Pre-computed points for ecp_mul_comb(). */ + size_t T_size; /*!< The number of pre-computed points. */ +} +mbedtls_ecp_group; + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h, or define them using the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_ECP_MAX_BITS) +/** + * The maximum size of the groups, that is, of \c N and \c P. + */ +#define MBEDTLS_ECP_MAX_BITS 521 /**< The maximum size of groups, in bits. */ +#endif + +#define MBEDTLS_ECP_MAX_BYTES ( ( MBEDTLS_ECP_MAX_BITS + 7 ) / 8 ) +#define MBEDTLS_ECP_MAX_PT_LEN ( 2 * MBEDTLS_ECP_MAX_BYTES + 1 ) + +#if !defined(MBEDTLS_ECP_WINDOW_SIZE) +/* + * Maximum "window" size used for point multiplication. + * Default: 6. + * Minimum value: 2. Maximum value: 7. + * + * Result is an array of at most ( 1 << ( MBEDTLS_ECP_WINDOW_SIZE - 1 ) ) + * points used for point multiplication. This value is directly tied to EC + * peak memory usage, so decreasing it by one should roughly cut memory usage + * by two (if large curves are in use). + * + * Reduction in size may reduce speed, but larger curves are impacted first. + * Sample performances (in ECDHE handshakes/s, with FIXED_POINT_OPTIM = 1): + * w-size: 6 5 4 3 2 + * 521 145 141 135 120 97 + * 384 214 209 198 177 146 + * 256 320 320 303 262 226 + * 224 475 475 453 398 342 + * 192 640 640 633 587 476 + */ +#define MBEDTLS_ECP_WINDOW_SIZE 6 /**< The maximum window size used. */ +#endif /* MBEDTLS_ECP_WINDOW_SIZE */ + +#if !defined(MBEDTLS_ECP_FIXED_POINT_OPTIM) +/* + * Trade memory for speed on fixed-point multiplication. + * + * This speeds up repeated multiplication of the generator (that is, the + * multiplication in ECDSA signatures, and half of the multiplications in + * ECDSA verification and ECDHE) by a factor roughly 3 to 4. + * + * The cost is increasing EC peak memory usage by a factor roughly 2. + * + * Change this value to 0 to reduce peak memory usage. + */ +#define MBEDTLS_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up. */ +#endif /* MBEDTLS_ECP_FIXED_POINT_OPTIM */ + +/* \} name SECTION: Module settings */ + +#else /* MBEDTLS_ECP_ALT */ +#include "ecp_alt.h" +#endif /* MBEDTLS_ECP_ALT */ + +#if defined(MBEDTLS_ECP_RESTARTABLE) + +/** + * \brief Internal restart context for multiplication + * + * \note Opaque struct + */ +typedef struct mbedtls_ecp_restart_mul mbedtls_ecp_restart_mul_ctx; + +/** + * \brief Internal restart context for ecp_muladd() + * + * \note Opaque struct + */ +typedef struct mbedtls_ecp_restart_muladd mbedtls_ecp_restart_muladd_ctx; + +/** + * \brief General context for resuming ECC operations + */ +typedef struct +{ + unsigned ops_done; /*!< current ops count */ + unsigned depth; /*!< call depth (0 = top-level) */ + mbedtls_ecp_restart_mul_ctx *rsm; /*!< ecp_mul_comb() sub-context */ + mbedtls_ecp_restart_muladd_ctx *ma; /*!< ecp_muladd() sub-context */ +} mbedtls_ecp_restart_ctx; + +/* + * Operation counts for restartable functions + */ +#define MBEDTLS_ECP_OPS_CHK 3 /*!< basic ops count for ecp_check_pubkey() */ +#define MBEDTLS_ECP_OPS_DBL 8 /*!< basic ops count for ecp_double_jac() */ +#define MBEDTLS_ECP_OPS_ADD 11 /*!< basic ops count for see ecp_add_mixed() */ +#define MBEDTLS_ECP_OPS_INV 120 /*!< empirical equivalent for mpi_mod_inv() */ + +/** + * \brief Internal; for restartable functions in other modules. + * Check and update basic ops budget. + * + * \param grp Group structure + * \param rs_ctx Restart context + * \param ops Number of basic ops to do + * + * \return \c 0 if doing \p ops basic ops is still allowed, + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS otherwise. + */ +int mbedtls_ecp_check_budget( const mbedtls_ecp_group *grp, + mbedtls_ecp_restart_ctx *rs_ctx, + unsigned ops ); + +/* Utility macro for checking and updating ops budget */ +#define MBEDTLS_ECP_BUDGET( ops ) \ + MBEDTLS_MPI_CHK( mbedtls_ecp_check_budget( grp, rs_ctx, \ + (unsigned) (ops) ) ); + +#else /* MBEDTLS_ECP_RESTARTABLE */ + +#define MBEDTLS_ECP_BUDGET( ops ) /* no-op; for compatibility */ + +/* We want to declare restartable versions of existing functions anyway */ +typedef void mbedtls_ecp_restart_ctx; + +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +/** + * \brief The ECP key-pair structure. + * + * A generic key-pair that may be used for ECDSA and fixed ECDH, for example. + * + * \note Members are deliberately in the same order as in the + * ::mbedtls_ecdsa_context structure. + */ +typedef struct mbedtls_ecp_keypair +{ + mbedtls_ecp_group grp; /*!< Elliptic curve and base point */ + mbedtls_mpi d; /*!< our secret value */ + mbedtls_ecp_point Q; /*!< our public value */ +} +mbedtls_ecp_keypair; + +/* + * Point formats, from RFC 4492's enum ECPointFormat + */ +#define MBEDTLS_ECP_PF_UNCOMPRESSED 0 /**< Uncompressed point format. */ +#define MBEDTLS_ECP_PF_COMPRESSED 1 /**< Compressed point format. */ + +/* + * Some other constants from RFC 4492 + */ +#define MBEDTLS_ECP_TLS_NAMED_CURVE 3 /**< The named_curve of ECCurveType. */ + +#if defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Set the maximum number of basic operations done in a row. + * + * If more operations are needed to complete a computation, + * #MBEDTLS_ERR_ECP_IN_PROGRESS will be returned by the + * function performing the computation. It is then the + * caller's responsibility to either call again with the same + * parameters until it returns 0 or an error code; or to free + * the restart context if the operation is to be aborted. + * + * It is strictly required that all input parameters and the + * restart context be the same on successive calls for the + * same operation, but output parameters need not be the + * same; they must not be used until the function finally + * returns 0. + * + * This only applies to functions whose documentation + * mentions they may return #MBEDTLS_ERR_ECP_IN_PROGRESS (or + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS for functions in the + * SSL module). For functions that accept a "restart context" + * argument, passing NULL disables restart and makes the + * function equivalent to the function with the same name + * with \c _restartable removed. For functions in the ECDH + * module, restart is disabled unless the function accepts + * an "ECDH context" argument and + * mbedtls_ecdh_enable_restart() was previously called on + * that context. For function in the SSL module, restart is + * only enabled for specific sides and key exchanges + * (currently only for clients and ECDHE-ECDSA). + * + * \param max_ops Maximum number of basic operations done in a row. + * Default: 0 (unlimited). + * Lower (non-zero) values mean ECC functions will block for + * a lesser maximum amount of time. + * + * \note A "basic operation" is defined as a rough equivalent of a + * multiplication in GF(p) for the NIST P-256 curve. + * As an indication, with default settings, a scalar + * multiplication (full run of \c mbedtls_ecp_mul()) is: + * - about 3300 basic operations for P-256 + * - about 9400 basic operations for P-384 + * + * \note Very low values are not always respected: sometimes + * functions need to block for a minimum number of + * operations, and will do so even if max_ops is set to a + * lower value. That minimum depends on the curve size, and + * can be made lower by decreasing the value of + * \c MBEDTLS_ECP_WINDOW_SIZE. As an indication, here is the + * lowest effective value for various curves and values of + * that parameter (w for short): + * w=6 w=5 w=4 w=3 w=2 + * P-256 208 208 160 136 124 + * P-384 682 416 320 272 248 + * P-521 1364 832 640 544 496 + * + * \note This setting is currently ignored by Curve25519. + */ +void mbedtls_ecp_set_max_ops( unsigned max_ops ); + +/** + * \brief Check if restart is enabled (max_ops != 0) + * + * \return \c 0 if \c max_ops == 0 (restart disabled) + * \return \c 1 otherwise (restart enabled) + */ +int mbedtls_ecp_restart_is_enabled( void ); +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +/* + * Get the type of a curve + */ +mbedtls_ecp_curve_type mbedtls_ecp_get_type( const mbedtls_ecp_group *grp ); + +/** + * \brief This function retrieves the information defined in + * mbedtls_ecp_curve_info() for all supported curves in order + * of preference. + * + * \note This function returns information about all curves + * supported by the library. Some curves may not be + * supported for all algorithms. Call mbedtls_ecdh_can_do() + * or mbedtls_ecdsa_can_do() to check if a curve is + * supported for ECDH or ECDSA. + * + * \return A statically allocated array. The last entry is 0. + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list( void ); + +/** + * \brief This function retrieves the list of internal group + * identifiers of all supported curves in the order of + * preference. + * + * \note This function returns information about all curves + * supported by the library. Some curves may not be + * supported for all algorithms. Call mbedtls_ecdh_can_do() + * or mbedtls_ecdsa_can_do() to check if a curve is + * supported for ECDH or ECDSA. + * + * \return A statically allocated array, + * terminated with MBEDTLS_ECP_DP_NONE. + */ +const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list( void ); + +/** + * \brief This function retrieves curve information from an internal + * group identifier. + * + * \param grp_id An \c MBEDTLS_ECP_DP_XXX value. + * + * \return The associated curve information on success. + * \return NULL on failure. + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_grp_id( mbedtls_ecp_group_id grp_id ); + +/** + * \brief This function retrieves curve information from a TLS + * NamedCurve value. + * + * \param tls_id An \c MBEDTLS_ECP_DP_XXX value. + * + * \return The associated curve information on success. + * \return NULL on failure. + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id( uint16_t tls_id ); + +/** + * \brief This function retrieves curve information from a + * human-readable name. + * + * \param name The human-readable name. + * + * \return The associated curve information on success. + * \return NULL on failure. + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name( const char *name ); + +/** + * \brief This function initializes a point as zero. + * + * \param pt The point to initialize. + */ +void mbedtls_ecp_point_init( mbedtls_ecp_point *pt ); + +/** + * \brief This function initializes an ECP group context + * without loading any domain parameters. + * + * \note After this function is called, domain parameters + * for various ECP groups can be loaded through the + * mbedtls_ecp_group_load() or mbedtls_ecp_tls_read_group() + * functions. + */ +void mbedtls_ecp_group_init( mbedtls_ecp_group *grp ); + +/** + * \brief This function initializes a key pair as an invalid one. + * + * \param key The key pair to initialize. + */ +void mbedtls_ecp_keypair_init( mbedtls_ecp_keypair *key ); + +/** + * \brief This function frees the components of a point. + * + * \param pt The point to free. + */ +void mbedtls_ecp_point_free( mbedtls_ecp_point *pt ); + +/** + * \brief This function frees the components of an ECP group. + * + * \param grp The group to free. This may be \c NULL, in which + * case this function returns immediately. If it is not + * \c NULL, it must point to an initialized ECP group. + */ +void mbedtls_ecp_group_free( mbedtls_ecp_group *grp ); + +/** + * \brief This function frees the components of a key pair. + * + * \param key The key pair to free. This may be \c NULL, in which + * case this function returns immediately. If it is not + * \c NULL, it must point to an initialized ECP key pair. + */ +void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Initialize a restart context. + * + * \param ctx The restart context to initialize. This must + * not be \c NULL. + */ +void mbedtls_ecp_restart_init( mbedtls_ecp_restart_ctx *ctx ); + +/** + * \brief Free the components of a restart context. + * + * \param ctx The restart context to free. This may be \c NULL, in which + * case this function returns immediately. If it is not + * \c NULL, it must point to an initialized restart context. + */ +void mbedtls_ecp_restart_free( mbedtls_ecp_restart_ctx *ctx ); +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +/** + * \brief This function copies the contents of point \p Q into + * point \p P. + * + * \param P The destination point. This must be initialized. + * \param Q The source point. This must be initialized. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return Another negative error code for other kinds of failure. + */ +int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ); + +/** + * \brief This function copies the contents of group \p src into + * group \p dst. + * + * \param dst The destination group. This must be initialized. + * \param src The source group. This must be initialized. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, + const mbedtls_ecp_group *src ); + +/** + * \brief This function sets a point to the point at infinity. + * + * \param pt The point to set. This must be initialized. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt ); + +/** + * \brief This function checks if a point is the point at infinity. + * + * \param pt The point to test. This must be initialized. + * + * \return \c 1 if the point is zero. + * \return \c 0 if the point is non-zero. + * \return A negative error code on failure. + */ +int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt ); + +/** + * \brief This function compares two points. + * + * \note This assumes that the points are normalized. Otherwise, + * they may compare as "not equal" even if they are. + * + * \param P The first point to compare. This must be initialized. + * \param Q The second point to compare. This must be initialized. + * + * \return \c 0 if the points are equal. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the points are not equal. + */ +int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P, + const mbedtls_ecp_point *Q ); + +/** + * \brief This function imports a non-zero point from two ASCII + * strings. + * + * \param P The destination point. This must be initialized. + * \param radix The numeric base of the input. + * \param x The first affine coordinate, as a null-terminated string. + * \param y The second affine coordinate, as a null-terminated string. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_MPI_XXX error code on failure. + */ +int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix, + const char *x, const char *y ); + +/** + * \brief This function exports a point into unsigned binary data. + * + * \param grp The group to which the point should belong. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param P The point to export. This must be initialized. + * \param format The point format. This must be either + * #MBEDTLS_ECP_PF_COMPRESSED or #MBEDTLS_ECP_PF_UNCOMPRESSED. + * (For groups without these formats, this parameter is + * ignored. But it still has to be either of the above + * values.) + * \param olen The address at which to store the length of + * the output in Bytes. This must not be \c NULL. + * \param buf The output buffer. This must be a writable buffer + * of length \p buflen Bytes. + * \param buflen The length of the output buffer \p buf in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the output buffer + * is too small to hold the point. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the point format + * or the export for the given group is not implemented. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp, + const mbedtls_ecp_point *P, + int format, size_t *olen, + unsigned char *buf, size_t buflen ); + +/** + * \brief This function imports a point from unsigned binary data. + * + * \note This function does not check that the point actually + * belongs to the given group, see mbedtls_ecp_check_pubkey() + * for that. + * + * \param grp The group to which the point should belong. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param P The destination context to import the point to. + * This must be initialized. + * \param buf The input buffer. This must be a readable buffer + * of length \p ilen Bytes. + * \param ilen The length of the input buffer \p buf in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the input is invalid. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the import for the + * given group is not implemented. + */ +int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *P, + const unsigned char *buf, size_t ilen ); + +/** + * \brief This function imports a point from a TLS ECPoint record. + * + * \note On function return, \p *buf is updated to point immediately + * after the ECPoint record. + * + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param pt The destination point. + * \param buf The address of the pointer to the start of the input buffer. + * \param len The length of the buffer. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_MPI_XXX error code on initialization + * failure. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid. + */ +int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *pt, + const unsigned char **buf, size_t len ); + +/** + * \brief This function exports a point as a TLS ECPoint record + * defined in RFC 4492, Section 5.4. + * + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param pt The point to be exported. This must be initialized. + * \param format The point format to use. This must be either + * #MBEDTLS_ECP_PF_COMPRESSED or #MBEDTLS_ECP_PF_UNCOMPRESSED. + * \param olen The address at which to store the length in Bytes + * of the data written. + * \param buf The target buffer. This must be a writable buffer of + * length \p blen Bytes. + * \param blen The length of the target buffer \p buf in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the input is invalid. + * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the target buffer + * is too small to hold the exported point. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, + const mbedtls_ecp_point *pt, + int format, size_t *olen, + unsigned char *buf, size_t blen ); + +/** + * \brief This function sets up an ECP group context + * from a standardized set of domain parameters. + * + * \note The index should be a value of the NamedCurve enum, + * as defined in RFC-4492: Elliptic Curve Cryptography + * (ECC) Cipher Suites for Transport Layer Security (TLS), + * usually in the form of an \c MBEDTLS_ECP_DP_XXX macro. + * + * \param grp The group context to setup. This must be initialized. + * \param id The identifier of the domain parameter set to load. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if \p id doesn't + * correspond to a known group. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_group_load( mbedtls_ecp_group *grp, mbedtls_ecp_group_id id ); + +/** + * \brief This function sets up an ECP group context from a TLS + * ECParameters record as defined in RFC 4492, Section 5.4. + * + * \note The read pointer \p buf is updated to point right after + * the ECParameters record on exit. + * + * \param grp The group context to setup. This must be initialized. + * \param buf The address of the pointer to the start of the input buffer. + * \param len The length of the input buffer \c *buf in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the group is not + * recognized. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp, + const unsigned char **buf, size_t len ); + +/** + * \brief This function extracts an elliptic curve group ID from a + * TLS ECParameters record as defined in RFC 4492, Section 5.4. + * + * \note The read pointer \p buf is updated to point right after + * the ECParameters record on exit. + * + * \param grp The address at which to store the group id. + * This must not be \c NULL. + * \param buf The address of the pointer to the start of the input buffer. + * \param len The length of the input buffer \c *buf in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the group is not + * recognized. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_tls_read_group_id( mbedtls_ecp_group_id *grp, + const unsigned char **buf, + size_t len ); +/** + * \brief This function exports an elliptic curve as a TLS + * ECParameters record as defined in RFC 4492, Section 5.4. + * + * \param grp The ECP group to be exported. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param olen The address at which to store the number of Bytes written. + * This must not be \c NULL. + * \param buf The buffer to write to. This must be a writable buffer + * of length \p blen Bytes. + * \param blen The length of the output buffer \p buf in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the output + * buffer is too small to hold the exported group. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, + size_t *olen, + unsigned char *buf, size_t blen ); + +/** + * \brief This function performs a scalar multiplication of a point + * by an integer: \p R = \p m * \p P. + * + * It is not thread-safe to use same group in multiple threads. + * + * \note To prevent timing attacks, this function + * executes the exact same sequence of base-field + * operations for any valid \p m. It avoids any if-branch or + * array index depending on the value of \p m. + * + * \note If \p f_rng is not NULL, it is used to randomize + * intermediate results to prevent potential timing attacks + * targeting these results. We recommend always providing + * a non-NULL \p f_rng. The overhead is negligible. + * Note: unless #MBEDTLS_ECP_NO_INTERNAL_RNG is defined, when + * \p f_rng is NULL, an internal RNG (seeded from the value + * of \p m) will be used instead. + * + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param R The point in which to store the result of the calculation. + * This must be initialized. + * \param m The integer by which to multiply. This must be initialized. + * \param P The point to multiply. This must be initialized. + * \param f_rng The RNG function. This may be \c NULL if randomization + * of intermediate results isn't desired (discouraged). + * \param p_rng The RNG context to be passed to \p p_rng. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m is not a valid private + * key, or \p P is not a valid public key. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief This function performs multiplication of a point by + * an integer: \p R = \p m * \p P in a restartable way. + * + * \see mbedtls_ecp_mul() + * + * \note This function does the same as \c mbedtls_ecp_mul(), but + * it can return early and restart according to the limit set + * with \c mbedtls_ecp_set_max_ops() to reduce blocking. + * + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param R The point in which to store the result of the calculation. + * This must be initialized. + * \param m The integer by which to multiply. This must be initialized. + * \param P The point to multiply. This must be initialized. + * \param f_rng The RNG function. This may be \c NULL if randomization + * of intermediate results isn't desired (discouraged). + * \param p_rng The RNG context to be passed to \p p_rng. + * \param rs_ctx The restart context (NULL disables restart). + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m is not a valid private + * key, or \p P is not a valid public key. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ); + +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) +/** + * \brief This function performs multiplication and addition of two + * points by integers: \p R = \p m * \p P + \p n * \p Q + * + * It is not thread-safe to use same group in multiple threads. + * + * \note In contrast to mbedtls_ecp_mul(), this function does not + * guarantee a constant execution flow and timing. + * + * \note This function is only defined for short Weierstrass curves. + * It may not be included in builds without any short + * Weierstrass curve. + * + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param R The point in which to store the result of the calculation. + * This must be initialized. + * \param m The integer by which to multiply \p P. + * This must be initialized. + * \param P The point to multiply by \p m. This must be initialized. + * \param n The integer by which to multiply \p Q. + * This must be initialized. + * \param Q The point to be multiplied by \p n. + * This must be initialized. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m or \p n are not + * valid private keys, or \p P or \p Q are not valid public + * keys. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if \p grp does not + * designate a short Weierstrass curve. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + const mbedtls_mpi *n, const mbedtls_ecp_point *Q ); + +/** + * \brief This function performs multiplication and addition of two + * points by integers: \p R = \p m * \p P + \p n * \p Q in a + * restartable way. + * + * \see \c mbedtls_ecp_muladd() + * + * \note This function works the same as \c mbedtls_ecp_muladd(), + * but it can return early and restart according to the limit + * set with \c mbedtls_ecp_set_max_ops() to reduce blocking. + * + * \note This function is only defined for short Weierstrass curves. + * It may not be included in builds without any short + * Weierstrass curve. + * + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param R The point in which to store the result of the calculation. + * This must be initialized. + * \param m The integer by which to multiply \p P. + * This must be initialized. + * \param P The point to multiply by \p m. This must be initialized. + * \param n The integer by which to multiply \p Q. + * This must be initialized. + * \param Q The point to be multiplied by \p n. + * This must be initialized. + * \param rs_ctx The restart context (NULL disables restart). + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m or \p n are not + * valid private keys, or \p P or \p Q are not valid public + * keys. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if \p grp does not + * designate a short Weierstrass curve. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_muladd_restartable( + mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + const mbedtls_mpi *n, const mbedtls_ecp_point *Q, + mbedtls_ecp_restart_ctx *rs_ctx ); +#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ + +/** + * \brief This function checks that a point is a valid public key + * on this curve. + * + * It only checks that the point is non-zero, has + * valid coordinates and lies on the curve. It does not verify + * that it is indeed a multiple of \p G. This additional + * check is computationally more expensive, is not required + * by standards, and should not be necessary if the group + * used has a small cofactor. In particular, it is useless for + * the NIST groups which all have a cofactor of 1. + * + * \note This function uses bare components rather than an + * ::mbedtls_ecp_keypair structure, to ease use with other + * structures, such as ::mbedtls_ecdh_context or + * ::mbedtls_ecdsa_context. + * + * \param grp The ECP group the point should belong to. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param pt The point to check. This must be initialized. + * + * \return \c 0 if the point is a valid public key. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY if the point is not + * a valid public key for the given curve. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, + const mbedtls_ecp_point *pt ); + +/** + * \brief This function checks that an \p mbedtls_mpi is a + * valid private key for this curve. + * + * \note This function uses bare components rather than an + * ::mbedtls_ecp_keypair structure to ease use with other + * structures, such as ::mbedtls_ecdh_context or + * ::mbedtls_ecdsa_context. + * + * \param grp The ECP group the private key should belong to. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param d The integer to check. This must be initialized. + * + * \return \c 0 if the point is a valid private key. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY if the point is not a valid + * private key for the given curve. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, + const mbedtls_mpi *d ); + +/** + * \brief This function generates a private key. + * + * \param grp The ECP group to generate a private key for. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param d The destination MPI (secret part). This must be initialized. + * \param f_rng The RNG function. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX error code + * on failure. + */ +int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp, + mbedtls_mpi *d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function generates a keypair with a configurable base + * point. + * + * \note This function uses bare components rather than an + * ::mbedtls_ecp_keypair structure to ease use with other + * structures, such as ::mbedtls_ecdh_context or + * ::mbedtls_ecdsa_context. + * + * \param grp The ECP group to generate a key pair for. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param G The base point to use. This must be initialized + * and belong to \p grp. It replaces the default base + * point \c grp->G used by mbedtls_ecp_gen_keypair(). + * \param d The destination MPI (secret part). + * This must be initialized. + * \param Q The destination point (public part). + * This must be initialized. + * \param f_rng The RNG function. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may + * be \c NULL if \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX error code + * on failure. + */ +int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp, + const mbedtls_ecp_point *G, + mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function generates an ECP keypair. + * + * \note This function uses bare components rather than an + * ::mbedtls_ecp_keypair structure to ease use with other + * structures, such as ::mbedtls_ecdh_context or + * ::mbedtls_ecdsa_context. + * + * \param grp The ECP group to generate a key pair for. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param d The destination MPI (secret part). + * This must be initialized. + * \param Q The destination point (public part). + * This must be initialized. + * \param f_rng The RNG function. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may + * be \c NULL if \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX error code + * on failure. + */ +int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp, mbedtls_mpi *d, + mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function generates an ECP key. + * + * \param grp_id The ECP group identifier. + * \param key The destination key. This must be initialized. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may + * be \c NULL if \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX error code + * on failure. + */ +int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function reads an elliptic curve private key. + * + * \param grp_id The ECP group identifier. + * \param key The destination key. + * \param buf The the buffer containing the binary representation of the + * key. (Big endian integer for Weierstrass curves, byte + * string for Montgomery curves.) + * \param buflen The length of the buffer in bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY error if the key is + * invalid. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the operation for + * the group is not implemented. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_ecp_read_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, + const unsigned char *buf, size_t buflen ); + +/** + * \brief This function exports an elliptic curve private key. + * + * \param key The private key. + * \param buf The output buffer for containing the binary representation + * of the key. (Big endian integer for Weierstrass curves, byte + * string for Montgomery curves.) + * \param buflen The total length of the buffer in bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the \p key + representation is larger than the available space in \p buf. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the operation for + * the group is not implemented. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_ecp_write_key( mbedtls_ecp_keypair *key, + unsigned char *buf, size_t buflen ); + +/** + * \brief This function checks that the keypair objects + * \p pub and \p prv have the same group and the + * same public point, and that the private key in + * \p prv is consistent with the public key. + * + * \param pub The keypair structure holding the public key. This + * must be initialized. If it contains a private key, that + * part is ignored. + * \param prv The keypair structure holding the full keypair. + * This must be initialized. + * + * \return \c 0 on success, meaning that the keys are valid and match. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the keys are invalid or do not match. + * \return An \c MBEDTLS_ERR_ECP_XXX or an \c MBEDTLS_ERR_MPI_XXX + * error code on calculation failure. + */ +int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, + const mbedtls_ecp_keypair *prv ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief The ECP checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_ecp_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* ecp.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ecp_internal.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ecp_internal.h new file mode 100644 index 0000000..6a47a8f --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ecp_internal.h @@ -0,0 +1,297 @@ +/** + * \file ecp_internal.h + * + * \brief Function declarations for alternative implementation of elliptic curve + * point arithmetic. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ + +/* + * References: + * + * [1] BERNSTEIN, Daniel J. Curve25519: new Diffie-Hellman speed records. + * + * + * [2] CORON, Jean-S'ebastien. Resistance against differential power analysis + * for elliptic curve cryptosystems. In : Cryptographic Hardware and + * Embedded Systems. Springer Berlin Heidelberg, 1999. p. 292-302. + * + * + * [3] HEDABOU, Mustapha, PINEL, Pierre, et B'EN'ETEAU, Lucien. A comb method to + * render ECC resistant against Side Channel Attacks. IACR Cryptology + * ePrint Archive, 2004, vol. 2004, p. 342. + * + * + * [4] Certicom Research. SEC 2: Recommended Elliptic Curve Domain Parameters. + * + * + * [5] HANKERSON, Darrel, MENEZES, Alfred J., VANSTONE, Scott. Guide to Elliptic + * Curve Cryptography. + * + * [6] Digital Signature Standard (DSS), FIPS 186-4. + * + * + * [7] Elliptic Curve Cryptography (ECC) Cipher Suites for Transport Layer + * Security (TLS), RFC 4492. + * + * + * [8] + * + * [9] COHEN, Henri. A Course in Computational Algebraic Number Theory. + * Springer Science & Business Media, 1 Aug 2000 + */ + +#ifndef MBEDTLS_ECP_INTERNAL_H +#define MBEDTLS_ECP_INTERNAL_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + +/** + * \brief Indicate if the Elliptic Curve Point module extension can + * handle the group. + * + * \param grp The pointer to the elliptic curve group that will be the + * basis of the cryptographic computations. + * + * \return Non-zero if successful. + */ +unsigned char mbedtls_internal_ecp_grp_capable( const mbedtls_ecp_group *grp ); + +/** + * \brief Initialise the Elliptic Curve Point module extension. + * + * If mbedtls_internal_ecp_grp_capable returns true for a + * group, this function has to be able to initialise the + * module for it. + * + * This module can be a driver to a crypto hardware + * accelerator, for which this could be an initialise function. + * + * \param grp The pointer to the group the module needs to be + * initialised for. + * + * \return 0 if successful. + */ +int mbedtls_internal_ecp_init( const mbedtls_ecp_group *grp ); + +/** + * \brief Frees and deallocates the Elliptic Curve Point module + * extension. + * + * \param grp The pointer to the group the module was initialised for. + */ +void mbedtls_internal_ecp_free( const mbedtls_ecp_group *grp ); + +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) + +#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) +/** + * \brief Randomize jacobian coordinates: + * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l. + * + * \param grp Pointer to the group representing the curve. + * + * \param pt The point on the curve to be randomised, given with Jacobian + * coordinates. + * + * \param f_rng A function pointer to the random number generator. + * + * \param p_rng A pointer to the random number generator state. + * + * \return 0 if successful. + */ +int mbedtls_internal_ecp_randomize_jac( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *pt, int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +#endif + +#if defined(MBEDTLS_ECP_ADD_MIXED_ALT) +/** + * \brief Addition: R = P + Q, mixed affine-Jacobian coordinates. + * + * The coordinates of Q must be normalized (= affine), + * but those of P don't need to. R is not normalized. + * + * This function is used only as a subrutine of + * ecp_mul_comb(). + * + * Special cases: (1) P or Q is zero, (2) R is zero, + * (3) P == Q. + * None of these cases can happen as intermediate step in + * ecp_mul_comb(): + * - at each step, P, Q and R are multiples of the base + * point, the factor being less than its order, so none of + * them is zero; + * - Q is an odd multiple of the base point, P an even + * multiple, due to the choice of precomputed points in the + * modified comb method. + * So branches for these cases do not leak secret information. + * + * We accept Q->Z being unset (saving memory in tables) as + * meaning 1. + * + * Cost in field operations if done by [5] 3.22: + * 1A := 8M + 3S + * + * \param grp Pointer to the group representing the curve. + * + * \param R Pointer to a point structure to hold the result. + * + * \param P Pointer to the first summand, given with Jacobian + * coordinates + * + * \param Q Pointer to the second summand, given with affine + * coordinates. + * + * \return 0 if successful. + */ +int mbedtls_internal_ecp_add_mixed( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, const mbedtls_ecp_point *P, + const mbedtls_ecp_point *Q ); +#endif + +/** + * \brief Point doubling R = 2 P, Jacobian coordinates. + * + * Cost: 1D := 3M + 4S (A == 0) + * 4M + 4S (A == -3) + * 3M + 6S + 1a otherwise + * when the implementation is based on the "dbl-1998-cmo-2" + * doubling formulas in [8] and standard optimizations are + * applied when curve parameter A is one of { 0, -3 }. + * + * \param grp Pointer to the group representing the curve. + * + * \param R Pointer to a point structure to hold the result. + * + * \param P Pointer to the point that has to be doubled, given with + * Jacobian coordinates. + * + * \return 0 if successful. + */ +#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) +int mbedtls_internal_ecp_double_jac( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, const mbedtls_ecp_point *P ); +#endif + +/** + * \brief Normalize jacobian coordinates of an array of (pointers to) + * points. + * + * Using Montgomery's trick to perform only one inversion mod P + * the cost is: + * 1N(t) := 1I + (6t - 3)M + 1S + * (See for example Algorithm 10.3.4. in [9]) + * + * This function is used only as a subrutine of + * ecp_mul_comb(). + * + * Warning: fails (returning an error) if one of the points is + * zero! + * This should never happen, see choice of w in ecp_mul_comb(). + * + * \param grp Pointer to the group representing the curve. + * + * \param T Array of pointers to the points to normalise. + * + * \param t_len Number of elements in the array. + * + * \return 0 if successful, + * an error if one of the points is zero. + */ +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) +int mbedtls_internal_ecp_normalize_jac_many( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *T[], size_t t_len ); +#endif + +/** + * \brief Normalize jacobian coordinates so that Z == 0 || Z == 1. + * + * Cost in field operations if done by [5] 3.2.1: + * 1N := 1I + 3M + 1S + * + * \param grp Pointer to the group representing the curve. + * + * \param pt pointer to the point to be normalised. This is an + * input/output parameter. + * + * \return 0 if successful. + */ +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) +int mbedtls_internal_ecp_normalize_jac( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *pt ); +#endif + +#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ + +#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) + +#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) +int mbedtls_internal_ecp_double_add_mxz( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, mbedtls_ecp_point *S, const mbedtls_ecp_point *P, + const mbedtls_ecp_point *Q, const mbedtls_mpi *d ); +#endif + +/** + * \brief Randomize projective x/z coordinates: + * (X, Z) -> (l X, l Z) for random l + * + * \param grp pointer to the group representing the curve + * + * \param P the point on the curve to be randomised given with + * projective coordinates. This is an input/output parameter. + * + * \param f_rng a function pointer to the random number generator + * + * \param p_rng a pointer to the random number generator state + * + * \return 0 if successful + */ +#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) +int mbedtls_internal_ecp_randomize_mxz( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *P, int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +#endif + +/** + * \brief Normalize Montgomery x/z coordinates: X = X/Z, Z = 1. + * + * \param grp pointer to the group representing the curve + * + * \param P pointer to the point to be normalised. This is an + * input/output parameter. + * + * \return 0 if successful + */ +#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) +int mbedtls_internal_ecp_normalize_mxz( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *P ); +#endif + +#endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */ + +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ + +#endif /* ecp_internal.h */ + diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/entropy.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/entropy.h new file mode 100644 index 0000000..5a9c11c --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/entropy.h @@ -0,0 +1,287 @@ +/** + * \file entropy.h + * + * \brief Entropy accumulator implementation + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_ENTROPY_H +#define MBEDTLS_ENTROPY_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) +#include "mbedtls/sha512.h" +#define MBEDTLS_ENTROPY_SHA512_ACCUMULATOR +#else +#if defined(MBEDTLS_SHA256_C) +#define MBEDTLS_ENTROPY_SHA256_ACCUMULATOR +#include "mbedtls/sha256.h" +#endif +#endif + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +#if defined(MBEDTLS_HAVEGE_C) +#include "mbedtls/havege.h" +#endif + +#define MBEDTLS_ERR_ENTROPY_SOURCE_FAILED -0x003C /**< Critical entropy source failure. */ +#define MBEDTLS_ERR_ENTROPY_MAX_SOURCES -0x003E /**< No more sources can be added. */ +#define MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED -0x0040 /**< No sources have been added to poll. */ +#define MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE -0x003D /**< No strong sources have been added to poll. */ +#define MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR -0x003F /**< Read/write error in file. */ + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_ENTROPY_MAX_SOURCES) +#define MBEDTLS_ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */ +#endif + +#if !defined(MBEDTLS_ENTROPY_MAX_GATHER) +#define MBEDTLS_ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */ +#endif + +/* \} name SECTION: Module settings */ + +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) +#define MBEDTLS_ENTROPY_BLOCK_SIZE 64 /**< Block size of entropy accumulator (SHA-512) */ +#else +#define MBEDTLS_ENTROPY_BLOCK_SIZE 32 /**< Block size of entropy accumulator (SHA-256) */ +#endif + +#define MBEDTLS_ENTROPY_MAX_SEED_SIZE 1024 /**< Maximum size of seed we read from seed file */ +#define MBEDTLS_ENTROPY_SOURCE_MANUAL MBEDTLS_ENTROPY_MAX_SOURCES + +#define MBEDTLS_ENTROPY_SOURCE_STRONG 1 /**< Entropy source is strong */ +#define MBEDTLS_ENTROPY_SOURCE_WEAK 0 /**< Entropy source is weak */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Entropy poll callback pointer + * + * \param data Callback-specific data pointer + * \param output Data to fill + * \param len Maximum size to provide + * \param olen The actual amount of bytes put into the buffer (Can be 0) + * + * \return 0 if no critical failures occurred, + * MBEDTLS_ERR_ENTROPY_SOURCE_FAILED otherwise + */ +typedef int (*mbedtls_entropy_f_source_ptr)(void *data, unsigned char *output, size_t len, + size_t *olen); + +/** + * \brief Entropy source state + */ +typedef struct mbedtls_entropy_source_state +{ + mbedtls_entropy_f_source_ptr f_source; /**< The entropy source callback */ + void * p_source; /**< The callback data pointer */ + size_t size; /**< Amount received in bytes */ + size_t threshold; /**< Minimum bytes required before release */ + int strong; /**< Is the source strong? */ +} +mbedtls_entropy_source_state; + +/** + * \brief Entropy context structure + */ +typedef struct mbedtls_entropy_context +{ + int accumulator_started; +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + mbedtls_sha512_context accumulator; +#else + mbedtls_sha256_context accumulator; +#endif + int source_count; + mbedtls_entropy_source_state source[MBEDTLS_ENTROPY_MAX_SOURCES]; +#if defined(MBEDTLS_HAVEGE_C) + mbedtls_havege_state havege_data; +#endif +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; /*!< mutex */ +#endif +#if defined(MBEDTLS_ENTROPY_NV_SEED) + int initial_entropy_run; +#endif +} +mbedtls_entropy_context; + +/** + * \brief Initialize the context + * + * \param ctx Entropy context to initialize + */ +void mbedtls_entropy_init( mbedtls_entropy_context *ctx ); + +/** + * \brief Free the data in the context + * + * \param ctx Entropy context to free + */ +void mbedtls_entropy_free( mbedtls_entropy_context *ctx ); + +/** + * \brief Adds an entropy source to poll + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param ctx Entropy context + * \param f_source Entropy function + * \param p_source Function data + * \param threshold Minimum required from source before entropy is released + * ( with mbedtls_entropy_func() ) (in bytes) + * \param strong MBEDTLS_ENTROPY_SOURCE_STRONG or + * MBEDTLS_ENTROPY_SOURCE_WEAK. + * At least one strong source needs to be added. + * Weaker sources (such as the cycle counter) can be used as + * a complement. + * + * \return 0 if successful or MBEDTLS_ERR_ENTROPY_MAX_SOURCES + */ +int mbedtls_entropy_add_source( mbedtls_entropy_context *ctx, + mbedtls_entropy_f_source_ptr f_source, void *p_source, + size_t threshold, int strong ); + +/** + * \brief Trigger an extra gather poll for the accumulator + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param ctx Entropy context + * + * \return 0 if successful, or MBEDTLS_ERR_ENTROPY_SOURCE_FAILED + */ +int mbedtls_entropy_gather( mbedtls_entropy_context *ctx ); + +/** + * \brief Retrieve entropy from the accumulator + * (Maximum length: MBEDTLS_ENTROPY_BLOCK_SIZE) + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param data Entropy context + * \param output Buffer to fill + * \param len Number of bytes desired, must be at most MBEDTLS_ENTROPY_BLOCK_SIZE + * + * \return 0 if successful, or MBEDTLS_ERR_ENTROPY_SOURCE_FAILED + */ +int mbedtls_entropy_func( void *data, unsigned char *output, size_t len ); + +/** + * \brief Add data to the accumulator manually + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param ctx Entropy context + * \param data Data to add + * \param len Length of data + * + * \return 0 if successful + */ +int mbedtls_entropy_update_manual( mbedtls_entropy_context *ctx, + const unsigned char *data, size_t len ); + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +/** + * \brief Trigger an update of the seed file in NV by using the + * current entropy pool. + * + * \param ctx Entropy context + * + * \return 0 if successful + */ +int mbedtls_entropy_update_nv_seed( mbedtls_entropy_context *ctx ); +#endif /* MBEDTLS_ENTROPY_NV_SEED */ + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Write a seed file + * + * \param ctx Entropy context + * \param path Name of the file + * + * \return 0 if successful, + * MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR on file error, or + * MBEDTLS_ERR_ENTROPY_SOURCE_FAILED + */ +int mbedtls_entropy_write_seed_file( mbedtls_entropy_context *ctx, const char *path ); + +/** + * \brief Read and update a seed file. Seed is added to this + * instance. No more than MBEDTLS_ENTROPY_MAX_SEED_SIZE bytes are + * read from the seed file. The rest is ignored. + * + * \param ctx Entropy context + * \param path Name of the file + * + * \return 0 if successful, + * MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR on file error, + * MBEDTLS_ERR_ENTROPY_SOURCE_FAILED + */ +int mbedtls_entropy_update_seed_file( mbedtls_entropy_context *ctx, const char *path ); +#endif /* MBEDTLS_FS_IO */ + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine + * + * This module self-test also calls the entropy self-test, + * mbedtls_entropy_source_self_test(); + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_entropy_self_test( int verbose ); + +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) +/** + * \brief Checkup routine + * + * Verifies the integrity of the hardware entropy source + * provided by the function 'mbedtls_hardware_poll()'. + * + * Note this is the only hardware entropy source that is known + * at link time, and other entropy sources configured + * dynamically at runtime by the function + * mbedtls_entropy_add_source() will not be tested. + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_entropy_source_self_test( int verbose ); +#endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* entropy.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/entropy_poll.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/entropy_poll.h new file mode 100644 index 0000000..e1d7491 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/entropy_poll.h @@ -0,0 +1,108 @@ +/** + * \file entropy_poll.h + * + * \brief Platform-specific and custom entropy polling functions + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_ENTROPY_POLL_H +#define MBEDTLS_ENTROPY_POLL_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Default thresholds for built-in sources, in bytes + */ +#define MBEDTLS_ENTROPY_MIN_PLATFORM 32 /**< Minimum for platform source */ +#define MBEDTLS_ENTROPY_MIN_HAVEGE 32 /**< Minimum for HAVEGE */ +#define MBEDTLS_ENTROPY_MIN_HARDCLOCK 4 /**< Minimum for mbedtls_timing_hardclock() */ +#if !defined(MBEDTLS_ENTROPY_MIN_HARDWARE) +#define MBEDTLS_ENTROPY_MIN_HARDWARE 32 /**< Minimum for the hardware source */ +#endif + +/** + * \brief Entropy poll callback that provides 0 entropy. + */ +#if defined(MBEDTLS_TEST_NULL_ENTROPY) + int mbedtls_null_entropy_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) +/** + * \brief Platform-specific entropy poll callback + */ +int mbedtls_platform_entropy_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#if defined(MBEDTLS_HAVEGE_C) +/** + * \brief HAVEGE based entropy poll callback + * + * Requires an HAVEGE state as its data pointer. + */ +int mbedtls_havege_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#if defined(MBEDTLS_TIMING_C) +/** + * \brief mbedtls_timing_hardclock-based entropy poll callback + */ +int mbedtls_hardclock_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) +/** + * \brief Entropy poll callback for a hardware source + * + * \warning This is not provided by mbed TLS! + * See \c MBEDTLS_ENTROPY_HARDWARE_ALT in config.h. + * + * \note This must accept NULL as its first argument. + */ +int mbedtls_hardware_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +/** + * \brief Entropy poll callback for a non-volatile seed file + * + * \note This must accept NULL as its first argument. + */ +int mbedtls_nv_seed_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* entropy_poll.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/error.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/error.h new file mode 100644 index 0000000..cd7731e --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/error.h @@ -0,0 +1,162 @@ +/** + * \file error.h + * + * \brief Error to string translation + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_ERROR_H +#define MBEDTLS_ERROR_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +/** + * Error code layout. + * + * Currently we try to keep all error codes within the negative space of 16 + * bits signed integers to support all platforms (-0x0001 - -0x7FFF). In + * addition we'd like to give two layers of information on the error if + * possible. + * + * For that purpose the error codes are segmented in the following manner: + * + * 16 bit error code bit-segmentation + * + * 1 bit - Unused (sign bit) + * 3 bits - High level module ID + * 5 bits - Module-dependent error code + * 7 bits - Low level module errors + * + * For historical reasons, low-level error codes are divided in even and odd, + * even codes were assigned first, and -1 is reserved for other errors. + * + * Low-level module errors (0x0002-0x007E, 0x0001-0x007F) + * + * Module Nr Codes assigned + * ERROR 2 0x006E 0x0001 + * MPI 7 0x0002-0x0010 + * GCM 3 0x0012-0x0014 0x0013-0x0013 + * BLOWFISH 3 0x0016-0x0018 0x0017-0x0017 + * THREADING 3 0x001A-0x001E + * AES 5 0x0020-0x0022 0x0021-0x0025 + * CAMELLIA 3 0x0024-0x0026 0x0027-0x0027 + * XTEA 2 0x0028-0x0028 0x0029-0x0029 + * BASE64 2 0x002A-0x002C + * OID 1 0x002E-0x002E 0x000B-0x000B + * PADLOCK 1 0x0030-0x0030 + * DES 2 0x0032-0x0032 0x0033-0x0033 + * CTR_DBRG 4 0x0034-0x003A + * ENTROPY 3 0x003C-0x0040 0x003D-0x003F + * NET 13 0x0042-0x0052 0x0043-0x0049 + * ARIA 4 0x0058-0x005E + * ASN1 7 0x0060-0x006C + * CMAC 1 0x007A-0x007A + * PBKDF2 1 0x007C-0x007C + * HMAC_DRBG 4 0x0003-0x0009 + * CCM 3 0x000D-0x0011 + * ARC4 1 0x0019-0x0019 + * MD2 1 0x002B-0x002B + * MD4 1 0x002D-0x002D + * MD5 1 0x002F-0x002F + * RIPEMD160 1 0x0031-0x0031 + * SHA1 1 0x0035-0x0035 0x0073-0x0073 + * SHA256 1 0x0037-0x0037 0x0074-0x0074 + * SHA512 1 0x0039-0x0039 0x0075-0x0075 + * CHACHA20 3 0x0051-0x0055 + * POLY1305 3 0x0057-0x005B + * CHACHAPOLY 2 0x0054-0x0056 + * PLATFORM 2 0x0070-0x0072 + * + * High-level module nr (3 bits - 0x0...-0x7...) + * Name ID Nr of Errors + * PEM 1 9 + * PKCS#12 1 4 (Started from top) + * X509 2 20 + * PKCS5 2 4 (Started from top) + * DHM 3 11 + * PK 3 15 (Started from top) + * RSA 4 11 + * ECP 4 10 (Started from top) + * MD 5 5 + * HKDF 5 1 (Started from top) + * SSL 5 2 (Started from 0x5F00) + * CIPHER 6 8 (Started from 0x6080) + * SSL 6 24 (Started from top, plus 0x6000) + * SSL 7 32 + * + * Module dependent error code (5 bits 0x.00.-0x.F8.) + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#define MBEDTLS_ERR_ERROR_GENERIC_ERROR -0x0001 /**< Generic error */ +#define MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED -0x006E /**< This is a bug in the library */ + +/** + * \brief Translate a mbed TLS error code into a string representation, + * Result is truncated if necessary and always includes a terminating + * null byte. + * + * \param errnum error code + * \param buffer buffer to place representation in + * \param buflen length of the buffer + */ +void mbedtls_strerror( int errnum, char *buffer, size_t buflen ); + +/** + * \brief Translate the high-level part of an Mbed TLS error code into a string + * representation. + * + * This function returns a const pointer to an un-modifiable string. The caller + * must not try to modify the string. It is intended to be used mostly for + * logging purposes. + * + * \param error_code error code + * + * \return The string representation of the error code, or \c NULL if the error + * code is unknown. + */ +const char * mbedtls_high_level_strerr( int error_code ); + +/** + * \brief Translate the low-level part of an Mbed TLS error code into a string + * representation. + * + * This function returns a const pointer to an un-modifiable string. The caller + * must not try to modify the string. It is intended to be used mostly for + * logging purposes. + * + * \param error_code error code + * + * \return The string representation of the error code, or \c NULL if the error + * code is unknown. + */ +const char * mbedtls_low_level_strerr( int error_code ); + +#ifdef __cplusplus +} +#endif + +#endif /* error.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/gcm.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/gcm.h new file mode 100644 index 0000000..6b67361 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/gcm.h @@ -0,0 +1,324 @@ +/** + * \file gcm.h + * + * \brief This file contains GCM definitions and functions. + * + * The Galois/Counter Mode (GCM) for 128-bit block ciphers is defined + * in D. McGrew, J. Viega, The Galois/Counter Mode of Operation + * (GCM), Natl. Inst. Stand. Technol. + * + * For more information on GCM, see NIST SP 800-38D: Recommendation for + * Block Cipher Modes of Operation: Galois/Counter Mode (GCM) and GMAC. + * + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_GCM_H +#define MBEDTLS_GCM_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/cipher.h" + +#include + +#define MBEDTLS_GCM_ENCRYPT 1 +#define MBEDTLS_GCM_DECRYPT 0 + +#define MBEDTLS_ERR_GCM_AUTH_FAILED -0x0012 /**< Authenticated decryption failed. */ + +/* MBEDTLS_ERR_GCM_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_GCM_HW_ACCEL_FAILED -0x0013 /**< GCM hardware accelerator failed. */ + +#define MBEDTLS_ERR_GCM_BAD_INPUT -0x0014 /**< Bad input parameters to function. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_GCM_ALT) + +/** + * \brief The GCM context structure. + */ +typedef struct mbedtls_gcm_context +{ + mbedtls_cipher_context_t cipher_ctx; /*!< The cipher context used. */ + uint64_t HL[16]; /*!< Precalculated HTable low. */ + uint64_t HH[16]; /*!< Precalculated HTable high. */ + uint64_t len; /*!< The total length of the encrypted data. */ + uint64_t add_len; /*!< The total length of the additional data. */ + unsigned char base_ectr[16]; /*!< The first ECTR for tag. */ + unsigned char y[16]; /*!< The Y working value. */ + unsigned char buf[16]; /*!< The buf working value. */ + int mode; /*!< The operation to perform: + #MBEDTLS_GCM_ENCRYPT or + #MBEDTLS_GCM_DECRYPT. */ +} +mbedtls_gcm_context; + +#else /* !MBEDTLS_GCM_ALT */ +#include "gcm_alt.h" +#endif /* !MBEDTLS_GCM_ALT */ + +/** + * \brief This function initializes the specified GCM context, + * to make references valid, and prepares the context + * for mbedtls_gcm_setkey() or mbedtls_gcm_free(). + * + * The function does not bind the GCM context to a particular + * cipher, nor set the key. For this purpose, use + * mbedtls_gcm_setkey(). + * + * \param ctx The GCM context to initialize. This must not be \c NULL. + */ +void mbedtls_gcm_init( mbedtls_gcm_context *ctx ); + +/** + * \brief This function associates a GCM context with a + * cipher algorithm and a key. + * + * \param ctx The GCM context. This must be initialized. + * \param cipher The 128-bit block cipher to use. + * \param key The encryption key. This must be a readable buffer of at + * least \p keybits bits. + * \param keybits The key size in bits. Valid options are: + *
  • 128 bits
  • + *
  • 192 bits
  • + *
  • 256 bits
+ * + * \return \c 0 on success. + * \return A cipher-specific error code on failure. + */ +int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief This function performs GCM encryption or decryption of a buffer. + * + * \note For encryption, the output buffer can be the same as the + * input buffer. For decryption, the output buffer cannot be + * the same as input buffer. If the buffers overlap, the output + * buffer must trail at least 8 Bytes behind the input buffer. + * + * \warning When this function performs a decryption, it outputs the + * authentication tag and does not verify that the data is + * authentic. You should use this function to perform encryption + * only. For decryption, use mbedtls_gcm_auth_decrypt() instead. + * + * \param ctx The GCM context to use for encryption or decryption. This + * must be initialized. + * \param mode The operation to perform: + * - #MBEDTLS_GCM_ENCRYPT to perform authenticated encryption. + * The ciphertext is written to \p output and the + * authentication tag is written to \p tag. + * - #MBEDTLS_GCM_DECRYPT to perform decryption. + * The plaintext is written to \p output and the + * authentication tag is written to \p tag. + * Note that this mode is not recommended, because it does + * not verify the authenticity of the data. For this reason, + * you should use mbedtls_gcm_auth_decrypt() instead of + * calling this function in decryption mode. + * \param length The length of the input data, which is equal to the length + * of the output data. + * \param iv The initialization vector. This must be a readable buffer of + * at least \p iv_len Bytes. + * \param iv_len The length of the IV. + * \param add The buffer holding the additional data. This must be of at + * least that size in Bytes. + * \param add_len The length of the additional data. + * \param input The buffer holding the input data. If \p length is greater + * than zero, this must be a readable buffer of at least that + * size in Bytes. + * \param output The buffer for holding the output data. If \p length is greater + * than zero, this must be a writable buffer of at least that + * size in Bytes. + * \param tag_len The length of the tag to generate. + * \param tag The buffer for holding the tag. This must be a writable + * buffer of at least \p tag_len Bytes. + * + * \return \c 0 if the encryption or decryption was performed + * successfully. Note that in #MBEDTLS_GCM_DECRYPT mode, + * this does not indicate that the data is authentic. + * \return #MBEDTLS_ERR_GCM_BAD_INPUT if the lengths or pointers are + * not valid or a cipher-specific error code if the encryption + * or decryption failed. + */ +int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx, + int mode, + size_t length, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len, + const unsigned char *input, + unsigned char *output, + size_t tag_len, + unsigned char *tag ); + +/** + * \brief This function performs a GCM authenticated decryption of a + * buffer. + * + * \note For decryption, the output buffer cannot be the same as + * input buffer. If the buffers overlap, the output buffer + * must trail at least 8 Bytes behind the input buffer. + * + * \param ctx The GCM context. This must be initialized. + * \param length The length of the ciphertext to decrypt, which is also + * the length of the decrypted plaintext. + * \param iv The initialization vector. This must be a readable buffer + * of at least \p iv_len Bytes. + * \param iv_len The length of the IV. + * \param add The buffer holding the additional data. This must be of at + * least that size in Bytes. + * \param add_len The length of the additional data. + * \param tag The buffer holding the tag to verify. This must be a + * readable buffer of at least \p tag_len Bytes. + * \param tag_len The length of the tag to verify. + * \param input The buffer holding the ciphertext. If \p length is greater + * than zero, this must be a readable buffer of at least that + * size. + * \param output The buffer for holding the decrypted plaintext. If \p length + * is greater than zero, this must be a writable buffer of at + * least that size. + * + * \return \c 0 if successful and authenticated. + * \return #MBEDTLS_ERR_GCM_AUTH_FAILED if the tag does not match. + * \return #MBEDTLS_ERR_GCM_BAD_INPUT if the lengths or pointers are + * not valid or a cipher-specific error code if the decryption + * failed. + */ +int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx, + size_t length, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len, + const unsigned char *tag, + size_t tag_len, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function starts a GCM encryption or decryption + * operation. + * + * \param ctx The GCM context. This must be initialized. + * \param mode The operation to perform: #MBEDTLS_GCM_ENCRYPT or + * #MBEDTLS_GCM_DECRYPT. + * \param iv The initialization vector. This must be a readable buffer of + * at least \p iv_len Bytes. + * \param iv_len The length of the IV. + * \param add The buffer holding the additional data, or \c NULL + * if \p add_len is \c 0. + * \param add_len The length of the additional data. If \c 0, + * \p add may be \c NULL. + * + * \return \c 0 on success. + */ +int mbedtls_gcm_starts( mbedtls_gcm_context *ctx, + int mode, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len ); + +/** + * \brief This function feeds an input buffer into an ongoing GCM + * encryption or decryption operation. + * + * ` The function expects input to be a multiple of 16 + * Bytes. Only the last call before calling + * mbedtls_gcm_finish() can be less than 16 Bytes. + * + * \note For decryption, the output buffer cannot be the same as + * input buffer. If the buffers overlap, the output buffer + * must trail at least 8 Bytes behind the input buffer. + * + * \param ctx The GCM context. This must be initialized. + * \param length The length of the input data. This must be a multiple of + * 16 except in the last call before mbedtls_gcm_finish(). + * \param input The buffer holding the input data. If \p length is greater + * than zero, this must be a readable buffer of at least that + * size in Bytes. + * \param output The buffer for holding the output data. If \p length is + * greater than zero, this must be a writable buffer of at + * least that size in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_GCM_BAD_INPUT on failure. + */ +int mbedtls_gcm_update( mbedtls_gcm_context *ctx, + size_t length, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function finishes the GCM operation and generates + * the authentication tag. + * + * It wraps up the GCM stream, and generates the + * tag. The tag can have a maximum length of 16 Bytes. + * + * \param ctx The GCM context. This must be initialized. + * \param tag The buffer for holding the tag. This must be a writable + * buffer of at least \p tag_len Bytes. + * \param tag_len The length of the tag to generate. This must be at least + * four. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_GCM_BAD_INPUT on failure. + */ +int mbedtls_gcm_finish( mbedtls_gcm_context *ctx, + unsigned char *tag, + size_t tag_len ); + +/** + * \brief This function clears a GCM context and the underlying + * cipher sub-context. + * + * \param ctx The GCM context to clear. If this is \c NULL, the call has + * no effect. Otherwise, this must be initialized. + */ +void mbedtls_gcm_free( mbedtls_gcm_context *ctx ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief The GCM checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_gcm_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + + +#endif /* gcm.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/havege.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/havege.h new file mode 100644 index 0000000..7d27039 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/havege.h @@ -0,0 +1,80 @@ +/** + * \file havege.h + * + * \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_HAVEGE_H +#define MBEDTLS_HAVEGE_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#define MBEDTLS_HAVEGE_COLLECT_SIZE 1024 + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief HAVEGE state structure + */ +typedef struct mbedtls_havege_state +{ + uint32_t PT1, PT2, offset[2]; + uint32_t pool[MBEDTLS_HAVEGE_COLLECT_SIZE]; + uint32_t WALK[8192]; +} +mbedtls_havege_state; + +/** + * \brief HAVEGE initialization + * + * \param hs HAVEGE state to be initialized + */ +void mbedtls_havege_init( mbedtls_havege_state *hs ); + +/** + * \brief Clear HAVEGE state + * + * \param hs HAVEGE state to be cleared + */ +void mbedtls_havege_free( mbedtls_havege_state *hs ); + +/** + * \brief HAVEGE rand function + * + * \param p_rng A HAVEGE state + * \param output Buffer to fill + * \param len Length of buffer + * + * \return 0 + */ +int mbedtls_havege_random( void *p_rng, unsigned char *output, size_t len ); + +#ifdef __cplusplus +} +#endif + +#endif /* havege.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/hkdf.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/hkdf.h new file mode 100644 index 0000000..2e6b363 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/hkdf.h @@ -0,0 +1,139 @@ +/** + * \file hkdf.h + * + * \brief This file contains the HKDF interface. + * + * The HMAC-based Extract-and-Expand Key Derivation Function (HKDF) is + * specified by RFC 5869. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_HKDF_H +#define MBEDTLS_HKDF_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/md.h" + +/** + * \name HKDF Error codes + * \{ + */ +#define MBEDTLS_ERR_HKDF_BAD_INPUT_DATA -0x5F80 /**< Bad input parameters to function. */ +/* \} name */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief This is the HMAC-based Extract-and-Expand Key Derivation Function + * (HKDF). + * + * \param md A hash function; md.size denotes the length of the hash + * function output in bytes. + * \param salt An optional salt value (a non-secret random value); + * if the salt is not provided, a string of all zeros of + * md.size length is used as the salt. + * \param salt_len The length in bytes of the optional \p salt. + * \param ikm The input keying material. + * \param ikm_len The length in bytes of \p ikm. + * \param info An optional context and application specific information + * string. This can be a zero-length string. + * \param info_len The length of \p info in bytes. + * \param okm The output keying material of \p okm_len bytes. + * \param okm_len The length of the output keying material in bytes. This + * must be less than or equal to 255 * md.size bytes. + * + * \return 0 on success. + * \return #MBEDTLS_ERR_HKDF_BAD_INPUT_DATA when the parameters are invalid. + * \return An MBEDTLS_ERR_MD_* error for errors returned from the underlying + * MD layer. + */ +int mbedtls_hkdf( const mbedtls_md_info_t *md, const unsigned char *salt, + size_t salt_len, const unsigned char *ikm, size_t ikm_len, + const unsigned char *info, size_t info_len, + unsigned char *okm, size_t okm_len ); + +/** + * \brief Take the input keying material \p ikm and extract from it a + * fixed-length pseudorandom key \p prk. + * + * \warning This function should only be used if the security of it has been + * studied and established in that particular context (eg. TLS 1.3 + * key schedule). For standard HKDF security guarantees use + * \c mbedtls_hkdf instead. + * + * \param md A hash function; md.size denotes the length of the + * hash function output in bytes. + * \param salt An optional salt value (a non-secret random value); + * if the salt is not provided, a string of all zeros + * of md.size length is used as the salt. + * \param salt_len The length in bytes of the optional \p salt. + * \param ikm The input keying material. + * \param ikm_len The length in bytes of \p ikm. + * \param[out] prk A pseudorandom key of at least md.size bytes. + * + * \return 0 on success. + * \return #MBEDTLS_ERR_HKDF_BAD_INPUT_DATA when the parameters are invalid. + * \return An MBEDTLS_ERR_MD_* error for errors returned from the underlying + * MD layer. + */ +int mbedtls_hkdf_extract( const mbedtls_md_info_t *md, + const unsigned char *salt, size_t salt_len, + const unsigned char *ikm, size_t ikm_len, + unsigned char *prk ); + +/** + * \brief Expand the supplied \p prk into several additional pseudorandom + * keys, which is the output of the HKDF. + * + * \warning This function should only be used if the security of it has been + * studied and established in that particular context (eg. TLS 1.3 + * key schedule). For standard HKDF security guarantees use + * \c mbedtls_hkdf instead. + * + * \param md A hash function; md.size denotes the length of the hash + * function output in bytes. + * \param prk A pseudorandom key of at least md.size bytes. \p prk is + * usually the output from the HKDF extract step. + * \param prk_len The length in bytes of \p prk. + * \param info An optional context and application specific information + * string. This can be a zero-length string. + * \param info_len The length of \p info in bytes. + * \param okm The output keying material of \p okm_len bytes. + * \param okm_len The length of the output keying material in bytes. This + * must be less than or equal to 255 * md.size bytes. + * + * \return 0 on success. + * \return #MBEDTLS_ERR_HKDF_BAD_INPUT_DATA when the parameters are invalid. + * \return An MBEDTLS_ERR_MD_* error for errors returned from the underlying + * MD layer. + */ +int mbedtls_hkdf_expand( const mbedtls_md_info_t *md, const unsigned char *prk, + size_t prk_len, const unsigned char *info, + size_t info_len, unsigned char *okm, size_t okm_len ); + +#ifdef __cplusplus +} +#endif + +#endif /* hkdf.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/hmac_drbg.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/hmac_drbg.h new file mode 100644 index 0000000..57ce9d9 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/hmac_drbg.h @@ -0,0 +1,413 @@ +/** + * \file hmac_drbg.h + * + * \brief The HMAC_DRBG pseudorandom generator. + * + * This module implements the HMAC_DRBG pseudorandom generator described + * in NIST SP 800-90A: Recommendation for Random Number Generation Using + * Deterministic Random Bit Generators. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_HMAC_DRBG_H +#define MBEDTLS_HMAC_DRBG_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/md.h" + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +/* + * Error codes + */ +#define MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG -0x0003 /**< Too many random requested in single call. */ +#define MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG -0x0005 /**< Input too large (Entropy + additional). */ +#define MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR -0x0007 /**< Read/write error in file. */ +#define MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED -0x0009 /**< The entropy source failed. */ + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_HMAC_DRBG_RESEED_INTERVAL) +#define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ +#endif + +#if !defined(MBEDTLS_HMAC_DRBG_MAX_INPUT) +#define MBEDTLS_HMAC_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +#endif + +#if !defined(MBEDTLS_HMAC_DRBG_MAX_REQUEST) +#define MBEDTLS_HMAC_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +#endif + +#if !defined(MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT) +#define MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ +#endif + +/* \} name SECTION: Module settings */ + +#define MBEDTLS_HMAC_DRBG_PR_OFF 0 /**< No prediction resistance */ +#define MBEDTLS_HMAC_DRBG_PR_ON 1 /**< Prediction resistance enabled */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * HMAC_DRBG context. + */ +typedef struct mbedtls_hmac_drbg_context +{ + /* Working state: the key K is not stored explicitly, + * but is implied by the HMAC context */ + mbedtls_md_context_t md_ctx; /*!< HMAC context (inc. K) */ + unsigned char V[MBEDTLS_MD_MAX_SIZE]; /*!< V in the spec */ + int reseed_counter; /*!< reseed counter */ + + /* Administrative state */ + size_t entropy_len; /*!< entropy bytes grabbed on each (re)seed */ + int prediction_resistance; /*!< enable prediction resistance (Automatic + reseed before every random generation) */ + int reseed_interval; /*!< reseed interval */ + + /* Callbacks */ + int (*f_entropy)(void *, unsigned char *, size_t); /*!< entropy function */ + void *p_entropy; /*!< context for the entropy function */ + +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; +#endif +} mbedtls_hmac_drbg_context; + +/** + * \brief HMAC_DRBG context initialization. + * + * This function makes the context ready for mbedtls_hmac_drbg_seed(), + * mbedtls_hmac_drbg_seed_buf() or mbedtls_hmac_drbg_free(). + * + * \param ctx HMAC_DRBG context to be initialized. + */ +void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx ); + +/** + * \brief HMAC_DRBG initial seeding. + * + * Set the initial seed and set up the entropy source for future reseeds. + * + * A typical choice for the \p f_entropy and \p p_entropy parameters is + * to use the entropy module: + * - \p f_entropy is mbedtls_entropy_func(); + * - \p p_entropy is an instance of ::mbedtls_entropy_context initialized + * with mbedtls_entropy_init() (which registers the platform's default + * entropy sources). + * + * You can provide a personalization string in addition to the + * entropy source, to make this instantiation as unique as possible. + * + * \note By default, the security strength as defined by NIST is: + * - 128 bits if \p md_info is SHA-1; + * - 192 bits if \p md_info is SHA-224; + * - 256 bits if \p md_info is SHA-256, SHA-384 or SHA-512. + * Note that SHA-256 is just as efficient as SHA-224. + * The security strength can be reduced if a smaller + * entropy length is set with + * mbedtls_hmac_drbg_set_entropy_len(). + * + * \note The default entropy length is the security strength + * (converted from bits to bytes). You can override + * it by calling mbedtls_hmac_drbg_set_entropy_len(). + * + * \note During the initial seeding, this function calls + * the entropy source to obtain a nonce + * whose length is half the entropy length. + * + * \param ctx HMAC_DRBG context to be seeded. + * \param md_info MD algorithm to use for HMAC_DRBG. + * \param f_entropy The entropy callback, taking as arguments the + * \p p_entropy context, the buffer to fill, and the + * length of the buffer. + * \p f_entropy is always called with a length that is + * less than or equal to the entropy length. + * \param p_entropy The entropy context to pass to \p f_entropy. + * \param custom The personalization string. + * This can be \c NULL, in which case the personalization + * string is empty regardless of the value of \p len. + * \param len The length of the personalization string. + * This must be at most #MBEDTLS_HMAC_DRBG_MAX_INPUT + * and also at most + * #MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT - \p entropy_len * 3 / 2 + * where \p entropy_len is the entropy length + * described above. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA if \p md_info is + * invalid. + * \return #MBEDTLS_ERR_MD_ALLOC_FAILED if there was not enough + * memory to allocate context data. + * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED + * if the call to \p f_entropy failed. + */ +int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx, + const mbedtls_md_info_t * md_info, + int (*f_entropy)(void *, unsigned char *, size_t), + void *p_entropy, + const unsigned char *custom, + size_t len ); + +/** + * \brief Initilisation of simpified HMAC_DRBG (never reseeds). + * + * This function is meant for use in algorithms that need a pseudorandom + * input such as deterministic ECDSA. + * + * \param ctx HMAC_DRBG context to be initialised. + * \param md_info MD algorithm to use for HMAC_DRBG. + * \param data Concatenation of the initial entropy string and + * the additional data. + * \param data_len Length of \p data in bytes. + * + * \return \c 0 if successful. or + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA if \p md_info is + * invalid. + * \return #MBEDTLS_ERR_MD_ALLOC_FAILED if there was not enough + * memory to allocate context data. + */ +int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx, + const mbedtls_md_info_t * md_info, + const unsigned char *data, size_t data_len ); + +/** + * \brief This function turns prediction resistance on or off. + * The default value is off. + * + * \note If enabled, entropy is gathered at the beginning of + * every call to mbedtls_hmac_drbg_random_with_add() + * or mbedtls_hmac_drbg_random(). + * Only use this if your entropy source has sufficient + * throughput. + * + * \param ctx The HMAC_DRBG context. + * \param resistance #MBEDTLS_HMAC_DRBG_PR_ON or #MBEDTLS_HMAC_DRBG_PR_OFF. + */ +void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx, + int resistance ); + +/** + * \brief This function sets the amount of entropy grabbed on each + * seed or reseed. + * + * See the documentation of mbedtls_hmac_drbg_seed() for the default value. + * + * \param ctx The HMAC_DRBG context. + * \param len The amount of entropy to grab, in bytes. + */ +void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, + size_t len ); + +/** + * \brief Set the reseed interval. + * + * The reseed interval is the number of calls to mbedtls_hmac_drbg_random() + * or mbedtls_hmac_drbg_random_with_add() after which the entropy function + * is called again. + * + * The default value is #MBEDTLS_HMAC_DRBG_RESEED_INTERVAL. + * + * \param ctx The HMAC_DRBG context. + * \param interval The reseed interval. + */ +void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, + int interval ); + +/** + * \brief This function updates the state of the HMAC_DRBG context. + * + * \param ctx The HMAC_DRBG context. + * \param additional The data to update the state with. + * If this is \c NULL, there is no additional data. + * \param add_len Length of \p additional in bytes. + * Unused if \p additional is \c NULL. + * + * \return \c 0 on success, or an error from the underlying + * hash calculation. + */ +int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, size_t add_len ); + +/** + * \brief This function reseeds the HMAC_DRBG context, that is + * extracts data from the entropy source. + * + * \param ctx The HMAC_DRBG context. + * \param additional Additional data to add to the state. + * If this is \c NULL, there is no additional data + * and \p len should be \c 0. + * \param len The length of the additional data. + * This must be at most #MBEDTLS_HMAC_DRBG_MAX_INPUT + * and also at most + * #MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT - \p entropy_len + * where \p entropy_len is the entropy length + * (see mbedtls_hmac_drbg_set_entropy_len()). + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED + * if a call to the entropy function failed. + */ +int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, size_t len ); + +/** + * \brief This function updates an HMAC_DRBG instance with additional + * data and uses it to generate random data. + * + * This function automatically reseeds if the reseed counter is exceeded + * or prediction resistance is enabled. + * + * \param p_rng The HMAC_DRBG context. This must be a pointer to a + * #mbedtls_hmac_drbg_context structure. + * \param output The buffer to fill. + * \param output_len The length of the buffer in bytes. + * This must be at most #MBEDTLS_HMAC_DRBG_MAX_REQUEST. + * \param additional Additional data to update with. + * If this is \c NULL, there is no additional data + * and \p add_len should be \c 0. + * \param add_len The length of the additional data. + * This must be at most #MBEDTLS_HMAC_DRBG_MAX_INPUT. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED + * if a call to the entropy source failed. + * \return #MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG if + * \p output_len > #MBEDTLS_HMAC_DRBG_MAX_REQUEST. + * \return #MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG if + * \p add_len > #MBEDTLS_HMAC_DRBG_MAX_INPUT. + */ +int mbedtls_hmac_drbg_random_with_add( void *p_rng, + unsigned char *output, size_t output_len, + const unsigned char *additional, + size_t add_len ); + +/** + * \brief This function uses HMAC_DRBG to generate random data. + * + * This function automatically reseeds if the reseed counter is exceeded + * or prediction resistance is enabled. + * + * \param p_rng The HMAC_DRBG context. This must be a pointer to a + * #mbedtls_hmac_drbg_context structure. + * \param output The buffer to fill. + * \param out_len The length of the buffer in bytes. + * This must be at most #MBEDTLS_HMAC_DRBG_MAX_REQUEST. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED + * if a call to the entropy source failed. + * \return #MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG if + * \p out_len > #MBEDTLS_HMAC_DRBG_MAX_REQUEST. + */ +int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len ); + +/** + * \brief Free an HMAC_DRBG context + * + * \param ctx The HMAC_DRBG context to free. + */ +void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx ); + +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function updates the state of the HMAC_DRBG context. + * + * \deprecated Superseded by mbedtls_hmac_drbg_update_ret() + * in 2.16.0. + * + * \param ctx The HMAC_DRBG context. + * \param additional The data to update the state with. + * If this is \c NULL, there is no additional data. + * \param add_len Length of \p additional in bytes. + * Unused if \p additional is \c NULL. + */ +MBEDTLS_DEPRECATED void mbedtls_hmac_drbg_update( + mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, size_t add_len ); +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_FS_IO) +/** + * \brief This function writes a seed file. + * + * \param ctx The HMAC_DRBG context. + * \param path The name of the file. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR on file error. + * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED on reseed + * failure. + */ +int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ); + +/** + * \brief This function reads and updates a seed file. The seed + * is added to this instance. + * + * \param ctx The HMAC_DRBG context. + * \param path The name of the file. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR on file error. + * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED on + * reseed failure. + * \return #MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG if the existing + * seed file is too large. + */ +int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ); +#endif /* MBEDTLS_FS_IO */ + + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief The HMAC_DRBG Checkup routine. + * + * \return \c 0 if successful. + * \return \c 1 if the test failed. + */ +int mbedtls_hmac_drbg_self_test( int verbose ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* hmac_drbg.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/md.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/md.h new file mode 100644 index 0000000..e4354ba --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/md.h @@ -0,0 +1,474 @@ + /** + * \file md.h + * + * \brief This file contains the generic message-digest wrapper. + * + * \author Adriaan de Jong + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_MD_H +#define MBEDTLS_MD_H + +#include + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#define MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE -0x5080 /**< The selected feature is not available. */ +#define MBEDTLS_ERR_MD_BAD_INPUT_DATA -0x5100 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_MD_ALLOC_FAILED -0x5180 /**< Failed to allocate memory. */ +#define MBEDTLS_ERR_MD_FILE_IO_ERROR -0x5200 /**< Opening or reading of file failed. */ + +/* MBEDTLS_ERR_MD_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_MD_HW_ACCEL_FAILED -0x5280 /**< MD hardware accelerator failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Supported message digests. + * + * \warning MD2, MD4, MD5 and SHA-1 are considered weak message digests and + * their use constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +typedef enum { + MBEDTLS_MD_NONE=0, /**< None. */ + MBEDTLS_MD_MD2, /**< The MD2 message digest. */ + MBEDTLS_MD_MD4, /**< The MD4 message digest. */ + MBEDTLS_MD_MD5, /**< The MD5 message digest. */ + MBEDTLS_MD_SHA1, /**< The SHA-1 message digest. */ + MBEDTLS_MD_SHA224, /**< The SHA-224 message digest. */ + MBEDTLS_MD_SHA256, /**< The SHA-256 message digest. */ + MBEDTLS_MD_SHA384, /**< The SHA-384 message digest. */ + MBEDTLS_MD_SHA512, /**< The SHA-512 message digest. */ + MBEDTLS_MD_RIPEMD160, /**< The RIPEMD-160 message digest. */ +} mbedtls_md_type_t; + +#if defined(MBEDTLS_SHA512_C) +#define MBEDTLS_MD_MAX_SIZE 64 /* longest known is SHA512 */ +#else +#define MBEDTLS_MD_MAX_SIZE 32 /* longest known is SHA256 or less */ +#endif + +#if defined(MBEDTLS_SHA512_C) +#define MBEDTLS_MD_MAX_BLOCK_SIZE 128 +#else +#define MBEDTLS_MD_MAX_BLOCK_SIZE 64 +#endif + +/** + * Opaque struct defined in md_internal.h. + */ +typedef struct mbedtls_md_info_t mbedtls_md_info_t; + +/** + * The generic message-digest context. + */ +typedef struct mbedtls_md_context_t +{ + /** Information about the associated message digest. */ + const mbedtls_md_info_t *md_info; + + /** The digest-specific context. */ + void *md_ctx; + + /** The HMAC part of the context. */ + void *hmac_ctx; +} mbedtls_md_context_t; + +/** + * \brief This function returns the list of digests supported by the + * generic digest module. + * + * \note The list starts with the strongest available hashes. + * + * \return A statically allocated array of digests. Each element + * in the returned list is an integer belonging to the + * message-digest enumeration #mbedtls_md_type_t. + * The last entry is 0. + */ +const int *mbedtls_md_list( void ); + +/** + * \brief This function returns the message-digest information + * associated with the given digest name. + * + * \param md_name The name of the digest to search for. + * + * \return The message-digest information associated with \p md_name. + * \return NULL if the associated message-digest information is not found. + */ +const mbedtls_md_info_t *mbedtls_md_info_from_string( const char *md_name ); + +/** + * \brief This function returns the message-digest information + * associated with the given digest type. + * + * \param md_type The type of digest to search for. + * + * \return The message-digest information associated with \p md_type. + * \return NULL if the associated message-digest information is not found. + */ +const mbedtls_md_info_t *mbedtls_md_info_from_type( mbedtls_md_type_t md_type ); + +/** + * \brief This function initializes a message-digest context without + * binding it to a particular message-digest algorithm. + * + * This function should always be called first. It prepares the + * context for mbedtls_md_setup() for binding it to a + * message-digest algorithm. + */ +void mbedtls_md_init( mbedtls_md_context_t *ctx ); + +/** + * \brief This function clears the internal structure of \p ctx and + * frees any embedded internal structure, but does not free + * \p ctx itself. + * + * If you have called mbedtls_md_setup() on \p ctx, you must + * call mbedtls_md_free() when you are no longer using the + * context. + * Calling this function if you have previously + * called mbedtls_md_init() and nothing else is optional. + * You must not call this function if you have not called + * mbedtls_md_init(). + */ +void mbedtls_md_free( mbedtls_md_context_t *ctx ); + +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function selects the message digest algorithm to use, + * and allocates internal structures. + * + * It should be called after mbedtls_md_init() or mbedtls_md_free(). + * Makes it necessary to call mbedtls_md_free() later. + * + * \deprecated Superseded by mbedtls_md_setup() in 2.0.0 + * + * \param ctx The context to set up. + * \param md_info The information structure of the message-digest algorithm + * to use. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + * \return #MBEDTLS_ERR_MD_ALLOC_FAILED on memory-allocation failure. + */ +int mbedtls_md_init_ctx( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info ) MBEDTLS_DEPRECATED; +#undef MBEDTLS_DEPRECATED +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief This function selects the message digest algorithm to use, + * and allocates internal structures. + * + * It should be called after mbedtls_md_init() or + * mbedtls_md_free(). Makes it necessary to call + * mbedtls_md_free() later. + * + * \param ctx The context to set up. + * \param md_info The information structure of the message-digest algorithm + * to use. + * \param hmac Defines if HMAC is used. 0: HMAC is not used (saves some memory), + * or non-zero: HMAC is used with this context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + * \return #MBEDTLS_ERR_MD_ALLOC_FAILED on memory-allocation failure. + */ +int mbedtls_md_setup( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac ); + +/** + * \brief This function clones the state of an message-digest + * context. + * + * \note You must call mbedtls_md_setup() on \c dst before calling + * this function. + * + * \note The two contexts must have the same type, + * for example, both are SHA-256. + * + * \warning This function clones the message-digest state, not the + * HMAC state. + * + * \param dst The destination context. + * \param src The context to be cloned. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification failure. + */ +int mbedtls_md_clone( mbedtls_md_context_t *dst, + const mbedtls_md_context_t *src ); + +/** + * \brief This function extracts the message-digest size from the + * message-digest information structure. + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * + * \return The size of the message-digest output in Bytes. + */ +unsigned char mbedtls_md_get_size( const mbedtls_md_info_t *md_info ); + +/** + * \brief This function extracts the message-digest type from the + * message-digest information structure. + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * + * \return The type of the message digest. + */ +mbedtls_md_type_t mbedtls_md_get_type( const mbedtls_md_info_t *md_info ); + +/** + * \brief This function extracts the message-digest name from the + * message-digest information structure. + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * + * \return The name of the message digest. + */ +const char *mbedtls_md_get_name( const mbedtls_md_info_t *md_info ); + +/** + * \brief This function starts a message-digest computation. + * + * You must call this function after setting up the context + * with mbedtls_md_setup(), and before passing data with + * mbedtls_md_update(). + * + * \param ctx The generic message-digest context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +int mbedtls_md_starts( mbedtls_md_context_t *ctx ); + +/** + * \brief This function feeds an input buffer into an ongoing + * message-digest computation. + * + * You must call mbedtls_md_starts() before calling this + * function. You may call this function multiple times. + * Afterwards, call mbedtls_md_finish(). + * + * \param ctx The generic message-digest context. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ); + +/** + * \brief This function finishes the digest operation, + * and writes the result to the output buffer. + * + * Call this function after a call to mbedtls_md_starts(), + * followed by any number of calls to mbedtls_md_update(). + * Afterwards, you may either clear the context with + * mbedtls_md_free(), or call mbedtls_md_starts() to reuse + * the context for another digest operation with the same + * algorithm. + * + * \param ctx The generic message-digest context. + * \param output The buffer for the generic message-digest checksum result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output ); + +/** + * \brief This function calculates the message-digest of a buffer, + * with respect to a configurable message-digest algorithm + * in a single call. + * + * The result is calculated as + * Output = message_digest(input buffer). + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * \param input The buffer holding the data. + * \param ilen The length of the input data. + * \param output The generic message-digest checksum result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen, + unsigned char *output ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief This function calculates the message-digest checksum + * result of the contents of the provided file. + * + * The result is calculated as + * Output = message_digest(file contents). + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * \param path The input file name. + * \param output The generic message-digest checksum result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_FILE_IO_ERROR on an I/O error accessing + * the file pointed by \p path. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA if \p md_info was NULL. + */ +int mbedtls_md_file( const mbedtls_md_info_t *md_info, const char *path, + unsigned char *output ); +#endif /* MBEDTLS_FS_IO */ + +/** + * \brief This function sets the HMAC key and prepares to + * authenticate a new message. + * + * Call this function after mbedtls_md_setup(), to use + * the MD context for an HMAC calculation, then call + * mbedtls_md_hmac_update() to provide the input data, and + * mbedtls_md_hmac_finish() to get the HMAC value. + * + * \param ctx The message digest context containing an embedded HMAC + * context. + * \param key The HMAC secret key. + * \param keylen The length of the HMAC key in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key, + size_t keylen ); + +/** + * \brief This function feeds an input buffer into an ongoing HMAC + * computation. + * + * Call mbedtls_md_hmac_starts() or mbedtls_md_hmac_reset() + * before calling this function. + * You may call this function multiple times to pass the + * input piecewise. + * Afterwards, call mbedtls_md_hmac_finish(). + * + * \param ctx The message digest context containing an embedded HMAC + * context. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +int mbedtls_md_hmac_update( mbedtls_md_context_t *ctx, const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the HMAC operation, and writes + * the result to the output buffer. + * + * Call this function after mbedtls_md_hmac_starts() and + * mbedtls_md_hmac_update() to get the HMAC value. Afterwards + * you may either call mbedtls_md_free() to clear the context, + * or call mbedtls_md_hmac_reset() to reuse the context with + * the same HMAC key. + * + * \param ctx The message digest context containing an embedded HMAC + * context. + * \param output The generic HMAC checksum result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output); + +/** + * \brief This function prepares to authenticate a new message with + * the same key as the previous HMAC operation. + * + * You may call this function after mbedtls_md_hmac_finish(). + * Afterwards call mbedtls_md_hmac_update() to pass the new + * input. + * + * \param ctx The message digest context containing an embedded HMAC + * context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +int mbedtls_md_hmac_reset( mbedtls_md_context_t *ctx ); + +/** + * \brief This function calculates the full generic HMAC + * on the input buffer with the provided key. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The HMAC result is calculated as + * output = generic HMAC(hmac key, input buffer). + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * \param key The HMAC secret key. + * \param keylen The length of the HMAC secret key in Bytes. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The generic HMAC result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +int mbedtls_md_hmac( const mbedtls_md_info_t *md_info, const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output ); + +/* Internal use */ +int mbedtls_md_process( mbedtls_md_context_t *ctx, const unsigned char *data ); + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_MD_H */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/md2.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/md2.h new file mode 100644 index 0000000..23c48f4 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/md2.h @@ -0,0 +1,304 @@ +/** + * \file md2.h + * + * \brief MD2 message digest algorithm (hash function) + * + * \warning MD2 is considered a weak message digest and its use constitutes a + * security risk. We recommend considering stronger message digests + * instead. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_MD2_H +#define MBEDTLS_MD2_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +/* MBEDTLS_ERR_MD2_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_MD2_HW_ACCEL_FAILED -0x002B /**< MD2 hardware accelerator failed */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_MD2_ALT) +// Regular implementation +// + +/** + * \brief MD2 context structure + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +typedef struct mbedtls_md2_context +{ + unsigned char cksum[16]; /*!< checksum of the data block */ + unsigned char state[48]; /*!< intermediate digest state */ + unsigned char buffer[16]; /*!< data block being processed */ + size_t left; /*!< amount of data in buffer */ +} +mbedtls_md2_context; + +#else /* MBEDTLS_MD2_ALT */ +#include "md2_alt.h" +#endif /* MBEDTLS_MD2_ALT */ + +/** + * \brief Initialize MD2 context + * + * \param ctx MD2 context to be initialized + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md2_init( mbedtls_md2_context *ctx ); + +/** + * \brief Clear MD2 context + * + * \param ctx MD2 context to be cleared + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md2_free( mbedtls_md2_context *ctx ); + +/** + * \brief Clone (the state of) an MD2 context + * + * \param dst The destination context + * \param src The context to be cloned + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md2_clone( mbedtls_md2_context *dst, + const mbedtls_md2_context *src ); + +/** + * \brief MD2 context setup + * + * \param ctx context to be initialized + * + * \return 0 if successful + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md2_starts_ret( mbedtls_md2_context *ctx ); + +/** + * \brief MD2 process buffer + * + * \param ctx MD2 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \return 0 if successful + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md2_update_ret( mbedtls_md2_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief MD2 final digest + * + * \param ctx MD2 context + * \param output MD2 checksum result + * + * \return 0 if successful + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md2_finish_ret( mbedtls_md2_context *ctx, + unsigned char output[16] ); + +/** + * \brief MD2 process data block (internal use only) + * + * \param ctx MD2 context + * + * \return 0 if successful + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_internal_md2_process( mbedtls_md2_context *ctx ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief MD2 context setup + * + * \deprecated Superseded by mbedtls_md2_starts_ret() in 2.7.0 + * + * \param ctx context to be initialized + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md2_starts( mbedtls_md2_context *ctx ); + +/** + * \brief MD2 process buffer + * + * \deprecated Superseded by mbedtls_md2_update_ret() in 2.7.0 + * + * \param ctx MD2 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md2_update( mbedtls_md2_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief MD2 final digest + * + * \deprecated Superseded by mbedtls_md2_finish_ret() in 2.7.0 + * + * \param ctx MD2 context + * \param output MD2 checksum result + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md2_finish( mbedtls_md2_context *ctx, + unsigned char output[16] ); + +/** + * \brief MD2 process data block (internal use only) + * + * \deprecated Superseded by mbedtls_internal_md2_process() in 2.7.0 + * + * \param ctx MD2 context + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md2_process( mbedtls_md2_context *ctx ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Output = MD2( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD2 checksum result + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md2_ret( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Output = MD2( input buffer ) + * + * \deprecated Superseded by mbedtls_md2_ret() in 2.7.0 + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD2 checksum result + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md2( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md2_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_md2.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/md4.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/md4.h new file mode 100644 index 0000000..eeb1670 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/md4.h @@ -0,0 +1,309 @@ +/** + * \file md4.h + * + * \brief MD4 message digest algorithm (hash function) + * + * \warning MD4 is considered a weak message digest and its use constitutes a + * security risk. We recommend considering stronger message digests + * instead. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_MD4_H +#define MBEDTLS_MD4_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +/* MBEDTLS_ERR_MD4_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_MD4_HW_ACCEL_FAILED -0x002D /**< MD4 hardware accelerator failed */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_MD4_ALT) +// Regular implementation +// + +/** + * \brief MD4 context structure + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +typedef struct mbedtls_md4_context +{ + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[4]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ +} +mbedtls_md4_context; + +#else /* MBEDTLS_MD4_ALT */ +#include "md4_alt.h" +#endif /* MBEDTLS_MD4_ALT */ + +/** + * \brief Initialize MD4 context + * + * \param ctx MD4 context to be initialized + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md4_init( mbedtls_md4_context *ctx ); + +/** + * \brief Clear MD4 context + * + * \param ctx MD4 context to be cleared + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md4_free( mbedtls_md4_context *ctx ); + +/** + * \brief Clone (the state of) an MD4 context + * + * \param dst The destination context + * \param src The context to be cloned + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md4_clone( mbedtls_md4_context *dst, + const mbedtls_md4_context *src ); + +/** + * \brief MD4 context setup + * + * \param ctx context to be initialized + * + * \return 0 if successful + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + */ +int mbedtls_md4_starts_ret( mbedtls_md4_context *ctx ); + +/** + * \brief MD4 process buffer + * + * \param ctx MD4 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \return 0 if successful + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md4_update_ret( mbedtls_md4_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief MD4 final digest + * + * \param ctx MD4 context + * \param output MD4 checksum result + * + * \return 0 if successful + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md4_finish_ret( mbedtls_md4_context *ctx, + unsigned char output[16] ); + +/** + * \brief MD4 process data block (internal use only) + * + * \param ctx MD4 context + * \param data buffer holding one block of data + * + * \return 0 if successful + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_internal_md4_process( mbedtls_md4_context *ctx, + const unsigned char data[64] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief MD4 context setup + * + * \deprecated Superseded by mbedtls_md4_starts_ret() in 2.7.0 + * + * \param ctx context to be initialized + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md4_starts( mbedtls_md4_context *ctx ); + +/** + * \brief MD4 process buffer + * + * \deprecated Superseded by mbedtls_md4_update_ret() in 2.7.0 + * + * \param ctx MD4 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md4_update( mbedtls_md4_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief MD4 final digest + * + * \deprecated Superseded by mbedtls_md4_finish_ret() in 2.7.0 + * + * \param ctx MD4 context + * \param output MD4 checksum result + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md4_finish( mbedtls_md4_context *ctx, + unsigned char output[16] ); + +/** + * \brief MD4 process data block (internal use only) + * + * \deprecated Superseded by mbedtls_internal_md4_process() in 2.7.0 + * + * \param ctx MD4 context + * \param data buffer holding one block of data + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md4_process( mbedtls_md4_context *ctx, + const unsigned char data[64] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Output = MD4( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD4 checksum result + * + * \return 0 if successful + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md4_ret( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Output = MD4( input buffer ) + * + * \deprecated Superseded by mbedtls_md4_ret() in 2.7.0 + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD4 checksum result + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md4( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md4_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_md4.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/md5.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/md5.h new file mode 100644 index 0000000..aaca0f2 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/md5.h @@ -0,0 +1,309 @@ +/** + * \file md5.h + * + * \brief MD5 message digest algorithm (hash function) + * + * \warning MD5 is considered a weak message digest and its use constitutes a + * security risk. We recommend considering stronger message + * digests instead. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_MD5_H +#define MBEDTLS_MD5_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +/* MBEDTLS_ERR_MD5_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_MD5_HW_ACCEL_FAILED -0x002F /**< MD5 hardware accelerator failed */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_MD5_ALT) +// Regular implementation +// + +/** + * \brief MD5 context structure + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +typedef struct mbedtls_md5_context +{ + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[4]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ +} +mbedtls_md5_context; + +#else /* MBEDTLS_MD5_ALT */ +#include "md5_alt.h" +#endif /* MBEDTLS_MD5_ALT */ + +/** + * \brief Initialize MD5 context + * + * \param ctx MD5 context to be initialized + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md5_init( mbedtls_md5_context *ctx ); + +/** + * \brief Clear MD5 context + * + * \param ctx MD5 context to be cleared + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md5_free( mbedtls_md5_context *ctx ); + +/** + * \brief Clone (the state of) an MD5 context + * + * \param dst The destination context + * \param src The context to be cloned + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md5_clone( mbedtls_md5_context *dst, + const mbedtls_md5_context *src ); + +/** + * \brief MD5 context setup + * + * \param ctx context to be initialized + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_starts_ret( mbedtls_md5_context *ctx ); + +/** + * \brief MD5 process buffer + * + * \param ctx MD5 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_update_ret( mbedtls_md5_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief MD5 final digest + * + * \param ctx MD5 context + * \param output MD5 checksum result + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_finish_ret( mbedtls_md5_context *ctx, + unsigned char output[16] ); + +/** + * \brief MD5 process data block (internal use only) + * + * \param ctx MD5 context + * \param data buffer holding one block of data + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_internal_md5_process( mbedtls_md5_context *ctx, + const unsigned char data[64] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief MD5 context setup + * + * \deprecated Superseded by mbedtls_md5_starts_ret() in 2.7.0 + * + * \param ctx context to be initialized + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5_starts( mbedtls_md5_context *ctx ); + +/** + * \brief MD5 process buffer + * + * \deprecated Superseded by mbedtls_md5_update_ret() in 2.7.0 + * + * \param ctx MD5 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5_update( mbedtls_md5_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief MD5 final digest + * + * \deprecated Superseded by mbedtls_md5_finish_ret() in 2.7.0 + * + * \param ctx MD5 context + * \param output MD5 checksum result + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5_finish( mbedtls_md5_context *ctx, + unsigned char output[16] ); + +/** + * \brief MD5 process data block (internal use only) + * + * \deprecated Superseded by mbedtls_internal_md5_process() in 2.7.0 + * + * \param ctx MD5 context + * \param data buffer holding one block of data + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5_process( mbedtls_md5_context *ctx, + const unsigned char data[64] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Output = MD5( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD5 checksum result + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_ret( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Output = MD5( input buffer ) + * + * \deprecated Superseded by mbedtls_md5_ret() in 2.7.0 + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD5 checksum result + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_md5.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/md_internal.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/md_internal.h new file mode 100644 index 0000000..f33cdf6 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/md_internal.h @@ -0,0 +1,90 @@ +/** + * \file md_internal.h + * + * \brief Message digest wrappers. + * + * \warning This in an internal header. Do not include directly. + * + * \author Adriaan de Jong + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_MD_WRAP_H +#define MBEDTLS_MD_WRAP_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/md.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Message digest information. + * Allows message digest functions to be called in a generic way. + */ +struct mbedtls_md_info_t +{ + /** Name of the message digest */ + const char * name; + + /** Digest identifier */ + mbedtls_md_type_t type; + + /** Output length of the digest function in bytes */ + unsigned char size; + + /** Block length of the digest function in bytes */ + unsigned char block_size; +}; + +#if defined(MBEDTLS_MD2_C) +extern const mbedtls_md_info_t mbedtls_md2_info; +#endif +#if defined(MBEDTLS_MD4_C) +extern const mbedtls_md_info_t mbedtls_md4_info; +#endif +#if defined(MBEDTLS_MD5_C) +extern const mbedtls_md_info_t mbedtls_md5_info; +#endif +#if defined(MBEDTLS_RIPEMD160_C) +extern const mbedtls_md_info_t mbedtls_ripemd160_info; +#endif +#if defined(MBEDTLS_SHA1_C) +extern const mbedtls_md_info_t mbedtls_sha1_info; +#endif +#if defined(MBEDTLS_SHA256_C) +extern const mbedtls_md_info_t mbedtls_sha224_info; +extern const mbedtls_md_info_t mbedtls_sha256_info; +#endif +#if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) +extern const mbedtls_md_info_t mbedtls_sha384_info; +#endif +extern const mbedtls_md_info_t mbedtls_sha512_info; +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_MD_WRAP_H */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/memory_buffer_alloc.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/memory_buffer_alloc.h new file mode 100644 index 0000000..2339772 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/memory_buffer_alloc.h @@ -0,0 +1,149 @@ +/** + * \file memory_buffer_alloc.h + * + * \brief Buffer-based memory allocator + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_MEMORY_BUFFER_ALLOC_H +#define MBEDTLS_MEMORY_BUFFER_ALLOC_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_MEMORY_ALIGN_MULTIPLE) +#define MBEDTLS_MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */ +#endif + +/* \} name SECTION: Module settings */ + +#define MBEDTLS_MEMORY_VERIFY_NONE 0 +#define MBEDTLS_MEMORY_VERIFY_ALLOC (1 << 0) +#define MBEDTLS_MEMORY_VERIFY_FREE (1 << 1) +#define MBEDTLS_MEMORY_VERIFY_ALWAYS (MBEDTLS_MEMORY_VERIFY_ALLOC | MBEDTLS_MEMORY_VERIFY_FREE) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Initialize use of stack-based memory allocator. + * The stack-based allocator does memory management inside the + * presented buffer and does not call calloc() and free(). + * It sets the global mbedtls_calloc() and mbedtls_free() pointers + * to its own functions. + * (Provided mbedtls_calloc() and mbedtls_free() are thread-safe if + * MBEDTLS_THREADING_C is defined) + * + * \note This code is not optimized and provides a straight-forward + * implementation of a stack-based memory allocator. + * + * \param buf buffer to use as heap + * \param len size of the buffer + */ +void mbedtls_memory_buffer_alloc_init( unsigned char *buf, size_t len ); + +/** + * \brief Free the mutex for thread-safety and clear remaining memory + */ +void mbedtls_memory_buffer_alloc_free( void ); + +/** + * \brief Determine when the allocator should automatically verify the state + * of the entire chain of headers / meta-data. + * (Default: MBEDTLS_MEMORY_VERIFY_NONE) + * + * \param verify One of MBEDTLS_MEMORY_VERIFY_NONE, MBEDTLS_MEMORY_VERIFY_ALLOC, + * MBEDTLS_MEMORY_VERIFY_FREE or MBEDTLS_MEMORY_VERIFY_ALWAYS + */ +void mbedtls_memory_buffer_set_verify( int verify ); + +#if defined(MBEDTLS_MEMORY_DEBUG) +/** + * \brief Print out the status of the allocated memory (primarily for use + * after a program should have de-allocated all memory) + * Prints out a list of 'still allocated' blocks and their stack + * trace if MBEDTLS_MEMORY_BACKTRACE is defined. + */ +void mbedtls_memory_buffer_alloc_status( void ); + +/** + * \brief Get the peak heap usage so far + * + * \param max_used Peak number of bytes in use or committed. This + * includes bytes in allocated blocks too small to split + * into smaller blocks but larger than the requested size. + * \param max_blocks Peak number of blocks in use, including free and used + */ +void mbedtls_memory_buffer_alloc_max_get( size_t *max_used, size_t *max_blocks ); + +/** + * \brief Reset peak statistics + */ +void mbedtls_memory_buffer_alloc_max_reset( void ); + +/** + * \brief Get the current heap usage + * + * \param cur_used Current number of bytes in use or committed. This + * includes bytes in allocated blocks too small to split + * into smaller blocks but larger than the requested size. + * \param cur_blocks Current number of blocks in use, including free and used + */ +void mbedtls_memory_buffer_alloc_cur_get( size_t *cur_used, size_t *cur_blocks ); +#endif /* MBEDTLS_MEMORY_DEBUG */ + +/** + * \brief Verifies that all headers in the memory buffer are correct + * and contain sane values. Helps debug buffer-overflow errors. + * + * Prints out first failure if MBEDTLS_MEMORY_DEBUG is defined. + * Prints out full header information if MBEDTLS_MEMORY_DEBUG + * is defined. (Includes stack trace information for each block if + * MBEDTLS_MEMORY_BACKTRACE is defined as well). + * + * \return 0 if verified, 1 otherwise + */ +int mbedtls_memory_buffer_alloc_verify( void ); + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_memory_buffer_alloc_self_test( int verbose ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* memory_buffer_alloc.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/net.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/net.h new file mode 100644 index 0000000..6692188 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/net.h @@ -0,0 +1,35 @@ +/** + * \file net.h + * + * \brief Deprecated header file that includes net_sockets.h + * + * \deprecated Superseded by mbedtls/net_sockets.h + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#include "mbedtls/net_sockets.h" +#if defined(MBEDTLS_DEPRECATED_WARNING) +#warning "Deprecated header file: Superseded by mbedtls/net_sockets.h" +#endif /* MBEDTLS_DEPRECATED_WARNING */ +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/net_sockets.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/net_sockets.h new file mode 100644 index 0000000..55fd18b --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/net_sockets.h @@ -0,0 +1,276 @@ +/** + * \file net_sockets.h + * + * \brief Network sockets abstraction layer to integrate Mbed TLS into a + * BSD-style sockets API. + * + * The network sockets module provides an example integration of the + * Mbed TLS library into a BSD sockets implementation. The module is + * intended to be an example of how Mbed TLS can be integrated into a + * networking stack, as well as to be Mbed TLS's network integration + * for its supported platforms. + * + * The module is intended only to be used with the Mbed TLS library and + * is not intended to be used by third party application software + * directly. + * + * The supported platforms are as follows: + * * Microsoft Windows and Windows CE + * * POSIX/Unix platforms including Linux, OS X + * + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_NET_SOCKETS_H +#define MBEDTLS_NET_SOCKETS_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/ssl.h" + +#include +#include + +#define MBEDTLS_ERR_NET_SOCKET_FAILED -0x0042 /**< Failed to open a socket. */ +#define MBEDTLS_ERR_NET_CONNECT_FAILED -0x0044 /**< The connection to the given server / port failed. */ +#define MBEDTLS_ERR_NET_BIND_FAILED -0x0046 /**< Binding of the socket failed. */ +#define MBEDTLS_ERR_NET_LISTEN_FAILED -0x0048 /**< Could not listen on the socket. */ +#define MBEDTLS_ERR_NET_ACCEPT_FAILED -0x004A /**< Could not accept the incoming connection. */ +#define MBEDTLS_ERR_NET_RECV_FAILED -0x004C /**< Reading information from the socket failed. */ +#define MBEDTLS_ERR_NET_SEND_FAILED -0x004E /**< Sending information through the socket failed. */ +#define MBEDTLS_ERR_NET_CONN_RESET -0x0050 /**< Connection was reset by peer. */ +#define MBEDTLS_ERR_NET_UNKNOWN_HOST -0x0052 /**< Failed to get an IP address for the given hostname. */ +#define MBEDTLS_ERR_NET_BUFFER_TOO_SMALL -0x0043 /**< Buffer is too small to hold the data. */ +#define MBEDTLS_ERR_NET_INVALID_CONTEXT -0x0045 /**< The context is invalid, eg because it was free()ed. */ +#define MBEDTLS_ERR_NET_POLL_FAILED -0x0047 /**< Polling the net context failed. */ +#define MBEDTLS_ERR_NET_BAD_INPUT_DATA -0x0049 /**< Input invalid. */ + +#define MBEDTLS_NET_LISTEN_BACKLOG 10 /**< The backlog that listen() should use. */ + +#define MBEDTLS_NET_PROTO_TCP 0 /**< The TCP transport protocol */ +#define MBEDTLS_NET_PROTO_UDP 1 /**< The UDP transport protocol */ + +#define MBEDTLS_NET_POLL_READ 1 /**< Used in \c mbedtls_net_poll to check for pending data */ +#define MBEDTLS_NET_POLL_WRITE 2 /**< Used in \c mbedtls_net_poll to check if write possible */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Wrapper type for sockets. + * + * Currently backed by just a file descriptor, but might be more in the future + * (eg two file descriptors for combined IPv4 + IPv6 support, or additional + * structures for hand-made UDP demultiplexing). + */ +typedef struct mbedtls_net_context +{ + int fd; /**< The underlying file descriptor */ +} +mbedtls_net_context; + +/** + * \brief Initialize a context + * Just makes the context ready to be used or freed safely. + * + * \param ctx Context to initialize + */ +void mbedtls_net_init( mbedtls_net_context *ctx ); + +/** + * \brief Initiate a connection with host:port in the given protocol + * + * \param ctx Socket to use + * \param host Host to connect to + * \param port Port to connect to + * \param proto Protocol: MBEDTLS_NET_PROTO_TCP or MBEDTLS_NET_PROTO_UDP + * + * \return 0 if successful, or one of: + * MBEDTLS_ERR_NET_SOCKET_FAILED, + * MBEDTLS_ERR_NET_UNKNOWN_HOST, + * MBEDTLS_ERR_NET_CONNECT_FAILED + * + * \note Sets the socket in connected mode even with UDP. + */ +int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, const char *port, int proto ); + +/** + * \brief Create a receiving socket on bind_ip:port in the chosen + * protocol. If bind_ip == NULL, all interfaces are bound. + * + * \param ctx Socket to use + * \param bind_ip IP to bind to, can be NULL + * \param port Port number to use + * \param proto Protocol: MBEDTLS_NET_PROTO_TCP or MBEDTLS_NET_PROTO_UDP + * + * \return 0 if successful, or one of: + * MBEDTLS_ERR_NET_SOCKET_FAILED, + * MBEDTLS_ERR_NET_BIND_FAILED, + * MBEDTLS_ERR_NET_LISTEN_FAILED + * + * \note Regardless of the protocol, opens the sockets and binds it. + * In addition, make the socket listening if protocol is TCP. + */ +int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto ); + +/** + * \brief Accept a connection from a remote client + * + * \param bind_ctx Relevant socket + * \param client_ctx Will contain the connected client socket + * \param client_ip Will contain the client IP address, can be NULL + * \param buf_size Size of the client_ip buffer + * \param ip_len Will receive the size of the client IP written, + * can be NULL if client_ip is null + * + * \return 0 if successful, or + * MBEDTLS_ERR_NET_ACCEPT_FAILED, or + * MBEDTLS_ERR_NET_BUFFER_TOO_SMALL if buf_size is too small, + * MBEDTLS_ERR_SSL_WANT_READ if bind_fd was set to + * non-blocking and accept() would block. + */ +int mbedtls_net_accept( mbedtls_net_context *bind_ctx, + mbedtls_net_context *client_ctx, + void *client_ip, size_t buf_size, size_t *ip_len ); + +/** + * \brief Check and wait for the context to be ready for read/write + * + * \param ctx Socket to check + * \param rw Bitflag composed of MBEDTLS_NET_POLL_READ and + * MBEDTLS_NET_POLL_WRITE specifying the events + * to wait for: + * - If MBEDTLS_NET_POLL_READ is set, the function + * will return as soon as the net context is available + * for reading. + * - If MBEDTLS_NET_POLL_WRITE is set, the function + * will return as soon as the net context is available + * for writing. + * \param timeout Maximal amount of time to wait before returning, + * in milliseconds. If \c timeout is zero, the + * function returns immediately. If \c timeout is + * -1u, the function blocks potentially indefinitely. + * + * \return Bitmask composed of MBEDTLS_NET_POLL_READ/WRITE + * on success or timeout, or a negative return code otherwise. + */ +int mbedtls_net_poll( mbedtls_net_context *ctx, uint32_t rw, uint32_t timeout ); + +/** + * \brief Set the socket blocking + * + * \param ctx Socket to set + * + * \return 0 if successful, or a non-zero error code + */ +int mbedtls_net_set_block( mbedtls_net_context *ctx ); + +/** + * \brief Set the socket non-blocking + * + * \param ctx Socket to set + * + * \return 0 if successful, or a non-zero error code + */ +int mbedtls_net_set_nonblock( mbedtls_net_context *ctx ); + +/** + * \brief Portable usleep helper + * + * \param usec Amount of microseconds to sleep + * + * \note Real amount of time slept will not be less than + * select()'s timeout granularity (typically, 10ms). + */ +void mbedtls_net_usleep( unsigned long usec ); + +/** + * \brief Read at most 'len' characters. If no error occurs, + * the actual amount read is returned. + * + * \param ctx Socket + * \param buf The buffer to write to + * \param len Maximum length of the buffer + * + * \return the number of bytes received, + * or a non-zero error code; with a non-blocking socket, + * MBEDTLS_ERR_SSL_WANT_READ indicates read() would block. + */ +int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len ); + +/** + * \brief Write at most 'len' characters. If no error occurs, + * the actual amount read is returned. + * + * \param ctx Socket + * \param buf The buffer to read from + * \param len The length of the buffer + * + * \return the number of bytes sent, + * or a non-zero error code; with a non-blocking socket, + * MBEDTLS_ERR_SSL_WANT_WRITE indicates write() would block. + */ +int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len ); + +/** + * \brief Read at most 'len' characters, blocking for at most + * 'timeout' seconds. If no error occurs, the actual amount + * read is returned. + * + * \param ctx Socket + * \param buf The buffer to write to + * \param len Maximum length of the buffer + * \param timeout Maximum number of milliseconds to wait for data + * 0 means no timeout (wait forever) + * + * \return the number of bytes received, + * or a non-zero error code: + * MBEDTLS_ERR_SSL_TIMEOUT if the operation timed out, + * MBEDTLS_ERR_SSL_WANT_READ if interrupted by a signal. + * + * \note This function will block (until data becomes available or + * timeout is reached) even if the socket is set to + * non-blocking. Handling timeouts with non-blocking reads + * requires a different strategy. + */ +int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, size_t len, + uint32_t timeout ); + +/** + * \brief Closes down the connection and free associated data + * + * \param ctx The context to close + */ +void mbedtls_net_close( mbedtls_net_context *ctx ); + +/** + * \brief Gracefully shutdown the connection and free associated data + * + * \param ctx The context to free + */ +void mbedtls_net_free( mbedtls_net_context *ctx ); + +#ifdef __cplusplus +} +#endif + +#endif /* net_sockets.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/nist_kw.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/nist_kw.h new file mode 100644 index 0000000..7f3e64a --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/nist_kw.h @@ -0,0 +1,182 @@ +/** + * \file nist_kw.h + * + * \brief This file provides an API for key wrapping (KW) and key wrapping with + * padding (KWP) as defined in NIST SP 800-38F. + * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf + * + * Key wrapping specifies a deterministic authenticated-encryption mode + * of operation, according to NIST SP 800-38F: Recommendation for + * Block Cipher Modes of Operation: Methods for Key Wrapping. Its + * purpose is to protect cryptographic keys. + * + * Its equivalent is RFC 3394 for KW, and RFC 5649 for KWP. + * https://tools.ietf.org/html/rfc3394 + * https://tools.ietf.org/html/rfc5649 + * + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_NIST_KW_H +#define MBEDTLS_NIST_KW_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/cipher.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum +{ + MBEDTLS_KW_MODE_KW = 0, + MBEDTLS_KW_MODE_KWP = 1 +} mbedtls_nist_kw_mode_t; + +#if !defined(MBEDTLS_NIST_KW_ALT) +// Regular implementation +// + +/** + * \brief The key wrapping context-type definition. The key wrapping context is passed + * to the APIs called. + * + * \note The definition of this type may change in future library versions. + * Don't make any assumptions on this context! + */ +typedef struct { + mbedtls_cipher_context_t cipher_ctx; /*!< The cipher context used. */ +} mbedtls_nist_kw_context; + +#else /* MBEDTLS_NIST_key wrapping_ALT */ +#include "nist_kw_alt.h" +#endif /* MBEDTLS_NIST_KW_ALT */ + +/** + * \brief This function initializes the specified key wrapping context + * to make references valid and prepare the context + * for mbedtls_nist_kw_setkey() or mbedtls_nist_kw_free(). + * + * \param ctx The key wrapping context to initialize. + * + */ +void mbedtls_nist_kw_init( mbedtls_nist_kw_context *ctx ); + +/** + * \brief This function initializes the key wrapping context set in the + * \p ctx parameter and sets the encryption key. + * + * \param ctx The key wrapping context. + * \param cipher The 128-bit block cipher to use. Only AES is supported. + * \param key The Key Encryption Key (KEK). + * \param keybits The KEK size in bits. This must be acceptable by the cipher. + * \param is_wrap Specify whether the operation within the context is wrapping or unwrapping + * + * \return \c 0 on success. + * \return \c MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA for any invalid input. + * \return \c MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE for 128-bit block ciphers + * which are not supported. + * \return cipher-specific error code on failure of the underlying cipher. + */ +int mbedtls_nist_kw_setkey( mbedtls_nist_kw_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits, + const int is_wrap ); + +/** + * \brief This function releases and clears the specified key wrapping context + * and underlying cipher sub-context. + * + * \param ctx The key wrapping context to clear. + */ +void mbedtls_nist_kw_free( mbedtls_nist_kw_context *ctx ); + +/** + * \brief This function encrypts a buffer using key wrapping. + * + * \param ctx The key wrapping context to use for encryption. + * \param mode The key wrapping mode to use (MBEDTLS_KW_MODE_KW or MBEDTLS_KW_MODE_KWP) + * \param input The buffer holding the input data. + * \param in_len The length of the input data in Bytes. + * The input uses units of 8 Bytes called semiblocks. + *
  • For KW mode: a multiple of 8 bytes between 16 and 2^57-8 inclusive.
  • + *
  • For KWP mode: any length between 1 and 2^32-1 inclusive.
+ * \param[out] output The buffer holding the output data. + *
  • For KW mode: Must be at least 8 bytes larger than \p in_len.
  • + *
  • For KWP mode: Must be at least 8 bytes larger rounded up to a multiple of + * 8 bytes for KWP (15 bytes at most).
+ * \param[out] out_len The number of bytes written to the output buffer. \c 0 on failure. + * \param[in] out_size The capacity of the output buffer. + * + * \return \c 0 on success. + * \return \c MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA for invalid input length. + * \return cipher-specific error code on failure of the underlying cipher. + */ +int mbedtls_nist_kw_wrap( mbedtls_nist_kw_context *ctx, mbedtls_nist_kw_mode_t mode, + const unsigned char *input, size_t in_len, + unsigned char *output, size_t* out_len, size_t out_size ); + +/** + * \brief This function decrypts a buffer using key wrapping. + * + * \param ctx The key wrapping context to use for decryption. + * \param mode The key wrapping mode to use (MBEDTLS_KW_MODE_KW or MBEDTLS_KW_MODE_KWP) + * \param input The buffer holding the input data. + * \param in_len The length of the input data in Bytes. + * The input uses units of 8 Bytes called semiblocks. + * The input must be a multiple of semiblocks. + *
  • For KW mode: a multiple of 8 bytes between 24 and 2^57 inclusive.
  • + *
  • For KWP mode: a multiple of 8 bytes between 16 and 2^32 inclusive.
+ * \param[out] output The buffer holding the output data. + * The output buffer's minimal length is 8 bytes shorter than \p in_len. + * \param[out] out_len The number of bytes written to the output buffer. \c 0 on failure. + * For KWP mode, the length could be up to 15 bytes shorter than \p in_len, + * depending on how much padding was added to the data. + * \param[in] out_size The capacity of the output buffer. + * + * \return \c 0 on success. + * \return \c MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA for invalid input length. + * \return \c MBEDTLS_ERR_CIPHER_AUTH_FAILED for verification failure of the ciphertext. + * \return cipher-specific error code on failure of the underlying cipher. + */ +int mbedtls_nist_kw_unwrap( mbedtls_nist_kw_context *ctx, mbedtls_nist_kw_mode_t mode, + const unsigned char *input, size_t in_len, + unsigned char *output, size_t* out_len, size_t out_size); + + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +/** + * \brief The key wrapping checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_nist_kw_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_NIST_KW_H */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/oid.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/oid.h new file mode 100644 index 0000000..e4c697b --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/oid.h @@ -0,0 +1,647 @@ +/** + * \file oid.h + * + * \brief Object Identifier (OID) database + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_OID_H +#define MBEDTLS_OID_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/asn1.h" +#include "mbedtls/pk.h" + +#include + +#if defined(MBEDTLS_CIPHER_C) +#include "mbedtls/cipher.h" +#endif + +#if defined(MBEDTLS_MD_C) +#include "mbedtls/md.h" +#endif + +#define MBEDTLS_ERR_OID_NOT_FOUND -0x002E /**< OID is not found. */ +#define MBEDTLS_ERR_OID_BUF_TOO_SMALL -0x000B /**< output buffer is too small */ + +/* This is for the benefit of X.509, but defined here in order to avoid + * having a "backwards" include of x.509.h here */ +/* + * X.509 extension types (internal, arbitrary values for bitsets) + */ +#define MBEDTLS_OID_X509_EXT_AUTHORITY_KEY_IDENTIFIER (1 << 0) +#define MBEDTLS_OID_X509_EXT_SUBJECT_KEY_IDENTIFIER (1 << 1) +#define MBEDTLS_OID_X509_EXT_KEY_USAGE (1 << 2) +#define MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES (1 << 3) +#define MBEDTLS_OID_X509_EXT_POLICY_MAPPINGS (1 << 4) +#define MBEDTLS_OID_X509_EXT_SUBJECT_ALT_NAME (1 << 5) +#define MBEDTLS_OID_X509_EXT_ISSUER_ALT_NAME (1 << 6) +#define MBEDTLS_OID_X509_EXT_SUBJECT_DIRECTORY_ATTRS (1 << 7) +#define MBEDTLS_OID_X509_EXT_BASIC_CONSTRAINTS (1 << 8) +#define MBEDTLS_OID_X509_EXT_NAME_CONSTRAINTS (1 << 9) +#define MBEDTLS_OID_X509_EXT_POLICY_CONSTRAINTS (1 << 10) +#define MBEDTLS_OID_X509_EXT_EXTENDED_KEY_USAGE (1 << 11) +#define MBEDTLS_OID_X509_EXT_CRL_DISTRIBUTION_POINTS (1 << 12) +#define MBEDTLS_OID_X509_EXT_INIHIBIT_ANYPOLICY (1 << 13) +#define MBEDTLS_OID_X509_EXT_FRESHEST_CRL (1 << 14) +#define MBEDTLS_OID_X509_EXT_NS_CERT_TYPE (1 << 16) + +/* + * Top level OID tuples + */ +#define MBEDTLS_OID_ISO_MEMBER_BODIES "\x2a" /* {iso(1) member-body(2)} */ +#define MBEDTLS_OID_ISO_IDENTIFIED_ORG "\x2b" /* {iso(1) identified-organization(3)} */ +#define MBEDTLS_OID_ISO_CCITT_DS "\x55" /* {joint-iso-ccitt(2) ds(5)} */ +#define MBEDTLS_OID_ISO_ITU_COUNTRY "\x60" /* {joint-iso-itu-t(2) country(16)} */ + +/* + * ISO Member bodies OID parts + */ +#define MBEDTLS_OID_COUNTRY_US "\x86\x48" /* {us(840)} */ +#define MBEDTLS_OID_ORG_RSA_DATA_SECURITY "\x86\xf7\x0d" /* {rsadsi(113549)} */ +#define MBEDTLS_OID_RSA_COMPANY MBEDTLS_OID_ISO_MEMBER_BODIES MBEDTLS_OID_COUNTRY_US \ + MBEDTLS_OID_ORG_RSA_DATA_SECURITY /* {iso(1) member-body(2) us(840) rsadsi(113549)} */ +#define MBEDTLS_OID_ORG_ANSI_X9_62 "\xce\x3d" /* ansi-X9-62(10045) */ +#define MBEDTLS_OID_ANSI_X9_62 MBEDTLS_OID_ISO_MEMBER_BODIES MBEDTLS_OID_COUNTRY_US \ + MBEDTLS_OID_ORG_ANSI_X9_62 + +/* + * ISO Identified organization OID parts + */ +#define MBEDTLS_OID_ORG_DOD "\x06" /* {dod(6)} */ +#define MBEDTLS_OID_ORG_OIW "\x0e" +#define MBEDTLS_OID_OIW_SECSIG MBEDTLS_OID_ORG_OIW "\x03" +#define MBEDTLS_OID_OIW_SECSIG_ALG MBEDTLS_OID_OIW_SECSIG "\x02" +#define MBEDTLS_OID_OIW_SECSIG_SHA1 MBEDTLS_OID_OIW_SECSIG_ALG "\x1a" +#define MBEDTLS_OID_ORG_CERTICOM "\x81\x04" /* certicom(132) */ +#define MBEDTLS_OID_CERTICOM MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_CERTICOM +#define MBEDTLS_OID_ORG_TELETRUST "\x24" /* teletrust(36) */ +#define MBEDTLS_OID_TELETRUST MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_TELETRUST + +/* + * ISO ITU OID parts + */ +#define MBEDTLS_OID_ORGANIZATION "\x01" /* {organization(1)} */ +#define MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ISO_ITU_COUNTRY MBEDTLS_OID_COUNTRY_US MBEDTLS_OID_ORGANIZATION /* {joint-iso-itu-t(2) country(16) us(840) organization(1)} */ + +#define MBEDTLS_OID_ORG_GOV "\x65" /* {gov(101)} */ +#define MBEDTLS_OID_GOV MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ORG_GOV /* {joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101)} */ + +#define MBEDTLS_OID_ORG_NETSCAPE "\x86\xF8\x42" /* {netscape(113730)} */ +#define MBEDTLS_OID_NETSCAPE MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ORG_NETSCAPE /* Netscape OID {joint-iso-itu-t(2) country(16) us(840) organization(1) netscape(113730)} */ + +/* ISO arc for standard certificate and CRL extensions */ +#define MBEDTLS_OID_ID_CE MBEDTLS_OID_ISO_CCITT_DS "\x1D" /**< id-ce OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 29} */ + +#define MBEDTLS_OID_NIST_ALG MBEDTLS_OID_GOV "\x03\x04" /** { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) */ + +/** + * Private Internet Extensions + * { iso(1) identified-organization(3) dod(6) internet(1) + * security(5) mechanisms(5) pkix(7) } + */ +#define MBEDTLS_OID_INTERNET MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_DOD "\x01" +#define MBEDTLS_OID_PKIX MBEDTLS_OID_INTERNET "\x05\x05\x07" + +/* + * Arc for standard naming attributes + */ +#define MBEDTLS_OID_AT MBEDTLS_OID_ISO_CCITT_DS "\x04" /**< id-at OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 4} */ +#define MBEDTLS_OID_AT_CN MBEDTLS_OID_AT "\x03" /**< id-at-commonName AttributeType:= {id-at 3} */ +#define MBEDTLS_OID_AT_SUR_NAME MBEDTLS_OID_AT "\x04" /**< id-at-surName AttributeType:= {id-at 4} */ +#define MBEDTLS_OID_AT_SERIAL_NUMBER MBEDTLS_OID_AT "\x05" /**< id-at-serialNumber AttributeType:= {id-at 5} */ +#define MBEDTLS_OID_AT_COUNTRY MBEDTLS_OID_AT "\x06" /**< id-at-countryName AttributeType:= {id-at 6} */ +#define MBEDTLS_OID_AT_LOCALITY MBEDTLS_OID_AT "\x07" /**< id-at-locality AttributeType:= {id-at 7} */ +#define MBEDTLS_OID_AT_STATE MBEDTLS_OID_AT "\x08" /**< id-at-state AttributeType:= {id-at 8} */ +#define MBEDTLS_OID_AT_ORGANIZATION MBEDTLS_OID_AT "\x0A" /**< id-at-organizationName AttributeType:= {id-at 10} */ +#define MBEDTLS_OID_AT_ORG_UNIT MBEDTLS_OID_AT "\x0B" /**< id-at-organizationalUnitName AttributeType:= {id-at 11} */ +#define MBEDTLS_OID_AT_TITLE MBEDTLS_OID_AT "\x0C" /**< id-at-title AttributeType:= {id-at 12} */ +#define MBEDTLS_OID_AT_POSTAL_ADDRESS MBEDTLS_OID_AT "\x10" /**< id-at-postalAddress AttributeType:= {id-at 16} */ +#define MBEDTLS_OID_AT_POSTAL_CODE MBEDTLS_OID_AT "\x11" /**< id-at-postalCode AttributeType:= {id-at 17} */ +#define MBEDTLS_OID_AT_GIVEN_NAME MBEDTLS_OID_AT "\x2A" /**< id-at-givenName AttributeType:= {id-at 42} */ +#define MBEDTLS_OID_AT_INITIALS MBEDTLS_OID_AT "\x2B" /**< id-at-initials AttributeType:= {id-at 43} */ +#define MBEDTLS_OID_AT_GENERATION_QUALIFIER MBEDTLS_OID_AT "\x2C" /**< id-at-generationQualifier AttributeType:= {id-at 44} */ +#define MBEDTLS_OID_AT_UNIQUE_IDENTIFIER MBEDTLS_OID_AT "\x2D" /**< id-at-uniqueIdentifier AttributType:= {id-at 45} */ +#define MBEDTLS_OID_AT_DN_QUALIFIER MBEDTLS_OID_AT "\x2E" /**< id-at-dnQualifier AttributeType:= {id-at 46} */ +#define MBEDTLS_OID_AT_PSEUDONYM MBEDTLS_OID_AT "\x41" /**< id-at-pseudonym AttributeType:= {id-at 65} */ + +#define MBEDTLS_OID_DOMAIN_COMPONENT "\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x19" /** id-domainComponent AttributeType:= {itu-t(0) data(9) pss(2342) ucl(19200300) pilot(100) pilotAttributeType(1) domainComponent(25)} */ + +/* + * OIDs for standard certificate extensions + */ +#define MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER MBEDTLS_OID_ID_CE "\x23" /**< id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 35 } */ +#define MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER MBEDTLS_OID_ID_CE "\x0E" /**< id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 14 } */ +#define MBEDTLS_OID_KEY_USAGE MBEDTLS_OID_ID_CE "\x0F" /**< id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 } */ +#define MBEDTLS_OID_CERTIFICATE_POLICIES MBEDTLS_OID_ID_CE "\x20" /**< id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 } */ +#define MBEDTLS_OID_POLICY_MAPPINGS MBEDTLS_OID_ID_CE "\x21" /**< id-ce-policyMappings OBJECT IDENTIFIER ::= { id-ce 33 } */ +#define MBEDTLS_OID_SUBJECT_ALT_NAME MBEDTLS_OID_ID_CE "\x11" /**< id-ce-subjectAltName OBJECT IDENTIFIER ::= { id-ce 17 } */ +#define MBEDTLS_OID_ISSUER_ALT_NAME MBEDTLS_OID_ID_CE "\x12" /**< id-ce-issuerAltName OBJECT IDENTIFIER ::= { id-ce 18 } */ +#define MBEDTLS_OID_SUBJECT_DIRECTORY_ATTRS MBEDTLS_OID_ID_CE "\x09" /**< id-ce-subjectDirectoryAttributes OBJECT IDENTIFIER ::= { id-ce 9 } */ +#define MBEDTLS_OID_BASIC_CONSTRAINTS MBEDTLS_OID_ID_CE "\x13" /**< id-ce-basicConstraints OBJECT IDENTIFIER ::= { id-ce 19 } */ +#define MBEDTLS_OID_NAME_CONSTRAINTS MBEDTLS_OID_ID_CE "\x1E" /**< id-ce-nameConstraints OBJECT IDENTIFIER ::= { id-ce 30 } */ +#define MBEDTLS_OID_POLICY_CONSTRAINTS MBEDTLS_OID_ID_CE "\x24" /**< id-ce-policyConstraints OBJECT IDENTIFIER ::= { id-ce 36 } */ +#define MBEDTLS_OID_EXTENDED_KEY_USAGE MBEDTLS_OID_ID_CE "\x25" /**< id-ce-extKeyUsage OBJECT IDENTIFIER ::= { id-ce 37 } */ +#define MBEDTLS_OID_CRL_DISTRIBUTION_POINTS MBEDTLS_OID_ID_CE "\x1F" /**< id-ce-cRLDistributionPoints OBJECT IDENTIFIER ::= { id-ce 31 } */ +#define MBEDTLS_OID_INIHIBIT_ANYPOLICY MBEDTLS_OID_ID_CE "\x36" /**< id-ce-inhibitAnyPolicy OBJECT IDENTIFIER ::= { id-ce 54 } */ +#define MBEDTLS_OID_FRESHEST_CRL MBEDTLS_OID_ID_CE "\x2E" /**< id-ce-freshestCRL OBJECT IDENTIFIER ::= { id-ce 46 } */ + +/* + * Certificate policies + */ +#define MBEDTLS_OID_ANY_POLICY MBEDTLS_OID_CERTIFICATE_POLICIES "\x00" /**< anyPolicy OBJECT IDENTIFIER ::= { id-ce-certificatePolicies 0 } */ + +/* + * Netscape certificate extensions + */ +#define MBEDTLS_OID_NS_CERT MBEDTLS_OID_NETSCAPE "\x01" +#define MBEDTLS_OID_NS_CERT_TYPE MBEDTLS_OID_NS_CERT "\x01" +#define MBEDTLS_OID_NS_BASE_URL MBEDTLS_OID_NS_CERT "\x02" +#define MBEDTLS_OID_NS_REVOCATION_URL MBEDTLS_OID_NS_CERT "\x03" +#define MBEDTLS_OID_NS_CA_REVOCATION_URL MBEDTLS_OID_NS_CERT "\x04" +#define MBEDTLS_OID_NS_RENEWAL_URL MBEDTLS_OID_NS_CERT "\x07" +#define MBEDTLS_OID_NS_CA_POLICY_URL MBEDTLS_OID_NS_CERT "\x08" +#define MBEDTLS_OID_NS_SSL_SERVER_NAME MBEDTLS_OID_NS_CERT "\x0C" +#define MBEDTLS_OID_NS_COMMENT MBEDTLS_OID_NS_CERT "\x0D" +#define MBEDTLS_OID_NS_DATA_TYPE MBEDTLS_OID_NETSCAPE "\x02" +#define MBEDTLS_OID_NS_CERT_SEQUENCE MBEDTLS_OID_NS_DATA_TYPE "\x05" + +/* + * OIDs for CRL extensions + */ +#define MBEDTLS_OID_PRIVATE_KEY_USAGE_PERIOD MBEDTLS_OID_ID_CE "\x10" +#define MBEDTLS_OID_CRL_NUMBER MBEDTLS_OID_ID_CE "\x14" /**< id-ce-cRLNumber OBJECT IDENTIFIER ::= { id-ce 20 } */ + +/* + * X.509 v3 Extended key usage OIDs + */ +#define MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE MBEDTLS_OID_EXTENDED_KEY_USAGE "\x00" /**< anyExtendedKeyUsage OBJECT IDENTIFIER ::= { id-ce-extKeyUsage 0 } */ + +#define MBEDTLS_OID_KP MBEDTLS_OID_PKIX "\x03" /**< id-kp OBJECT IDENTIFIER ::= { id-pkix 3 } */ +#define MBEDTLS_OID_SERVER_AUTH MBEDTLS_OID_KP "\x01" /**< id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 } */ +#define MBEDTLS_OID_CLIENT_AUTH MBEDTLS_OID_KP "\x02" /**< id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 } */ +#define MBEDTLS_OID_CODE_SIGNING MBEDTLS_OID_KP "\x03" /**< id-kp-codeSigning OBJECT IDENTIFIER ::= { id-kp 3 } */ +#define MBEDTLS_OID_EMAIL_PROTECTION MBEDTLS_OID_KP "\x04" /**< id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 } */ +#define MBEDTLS_OID_TIME_STAMPING MBEDTLS_OID_KP "\x08" /**< id-kp-timeStamping OBJECT IDENTIFIER ::= { id-kp 8 } */ +#define MBEDTLS_OID_OCSP_SIGNING MBEDTLS_OID_KP "\x09" /**< id-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 } */ + +/** + * Wi-SUN Alliance Field Area Network + * { iso(1) identified-organization(3) dod(6) internet(1) + * private(4) enterprise(1) WiSUN(45605) FieldAreaNetwork(1) } + */ +#define MBEDTLS_OID_WISUN_FAN MBEDTLS_OID_INTERNET "\x04\x01\x82\xe4\x25\x01" + +#define MBEDTLS_OID_ON MBEDTLS_OID_PKIX "\x08" /**< id-on OBJECT IDENTIFIER ::= { id-pkix 8 } */ +#define MBEDTLS_OID_ON_HW_MODULE_NAME MBEDTLS_OID_ON "\x04" /**< id-on-hardwareModuleName OBJECT IDENTIFIER ::= { id-on 4 } */ + +/* + * PKCS definition OIDs + */ + +#define MBEDTLS_OID_PKCS MBEDTLS_OID_RSA_COMPANY "\x01" /**< pkcs OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) 1 } */ +#define MBEDTLS_OID_PKCS1 MBEDTLS_OID_PKCS "\x01" /**< pkcs-1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 } */ +#define MBEDTLS_OID_PKCS5 MBEDTLS_OID_PKCS "\x05" /**< pkcs-5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 5 } */ +#define MBEDTLS_OID_PKCS9 MBEDTLS_OID_PKCS "\x09" /**< pkcs-9 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 } */ +#define MBEDTLS_OID_PKCS12 MBEDTLS_OID_PKCS "\x0c" /**< pkcs-12 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 12 } */ + +/* + * PKCS#1 OIDs + */ +#define MBEDTLS_OID_PKCS1_RSA MBEDTLS_OID_PKCS1 "\x01" /**< rsaEncryption OBJECT IDENTIFIER ::= { pkcs-1 1 } */ +#define MBEDTLS_OID_PKCS1_MD2 MBEDTLS_OID_PKCS1 "\x02" /**< md2WithRSAEncryption ::= { pkcs-1 2 } */ +#define MBEDTLS_OID_PKCS1_MD4 MBEDTLS_OID_PKCS1 "\x03" /**< md4WithRSAEncryption ::= { pkcs-1 3 } */ +#define MBEDTLS_OID_PKCS1_MD5 MBEDTLS_OID_PKCS1 "\x04" /**< md5WithRSAEncryption ::= { pkcs-1 4 } */ +#define MBEDTLS_OID_PKCS1_SHA1 MBEDTLS_OID_PKCS1 "\x05" /**< sha1WithRSAEncryption ::= { pkcs-1 5 } */ +#define MBEDTLS_OID_PKCS1_SHA224 MBEDTLS_OID_PKCS1 "\x0e" /**< sha224WithRSAEncryption ::= { pkcs-1 14 } */ +#define MBEDTLS_OID_PKCS1_SHA256 MBEDTLS_OID_PKCS1 "\x0b" /**< sha256WithRSAEncryption ::= { pkcs-1 11 } */ +#define MBEDTLS_OID_PKCS1_SHA384 MBEDTLS_OID_PKCS1 "\x0c" /**< sha384WithRSAEncryption ::= { pkcs-1 12 } */ +#define MBEDTLS_OID_PKCS1_SHA512 MBEDTLS_OID_PKCS1 "\x0d" /**< sha512WithRSAEncryption ::= { pkcs-1 13 } */ + +#define MBEDTLS_OID_RSA_SHA_OBS "\x2B\x0E\x03\x02\x1D" + +#define MBEDTLS_OID_PKCS9_EMAIL MBEDTLS_OID_PKCS9 "\x01" /**< emailAddress AttributeType ::= { pkcs-9 1 } */ + +/* RFC 4055 */ +#define MBEDTLS_OID_RSASSA_PSS MBEDTLS_OID_PKCS1 "\x0a" /**< id-RSASSA-PSS ::= { pkcs-1 10 } */ +#define MBEDTLS_OID_MGF1 MBEDTLS_OID_PKCS1 "\x08" /**< id-mgf1 ::= { pkcs-1 8 } */ + +/* + * Digest algorithms + */ +#define MBEDTLS_OID_DIGEST_ALG_MD2 MBEDTLS_OID_RSA_COMPANY "\x02\x02" /**< id-mbedtls_md2 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 2 } */ +#define MBEDTLS_OID_DIGEST_ALG_MD4 MBEDTLS_OID_RSA_COMPANY "\x02\x04" /**< id-mbedtls_md4 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 4 } */ +#define MBEDTLS_OID_DIGEST_ALG_MD5 MBEDTLS_OID_RSA_COMPANY "\x02\x05" /**< id-mbedtls_md5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 5 } */ +#define MBEDTLS_OID_DIGEST_ALG_SHA1 MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_OIW_SECSIG_SHA1 /**< id-mbedtls_sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 } */ +#define MBEDTLS_OID_DIGEST_ALG_SHA224 MBEDTLS_OID_NIST_ALG "\x02\x04" /**< id-sha224 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 4 } */ +#define MBEDTLS_OID_DIGEST_ALG_SHA256 MBEDTLS_OID_NIST_ALG "\x02\x01" /**< id-mbedtls_sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 1 } */ + +#define MBEDTLS_OID_DIGEST_ALG_SHA384 MBEDTLS_OID_NIST_ALG "\x02\x02" /**< id-sha384 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 2 } */ + +#define MBEDTLS_OID_DIGEST_ALG_SHA512 MBEDTLS_OID_NIST_ALG "\x02\x03" /**< id-mbedtls_sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3 } */ + +#define MBEDTLS_OID_DIGEST_ALG_RIPEMD160 MBEDTLS_OID_TELETRUST "\x03\x02\x01" /**< id-ripemd160 OBJECT IDENTIFIER :: { iso(1) identified-organization(3) teletrust(36) algorithm(3) hashAlgorithm(2) ripemd160(1) } */ + +#define MBEDTLS_OID_HMAC_SHA1 MBEDTLS_OID_RSA_COMPANY "\x02\x07" /**< id-hmacWithSHA1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 7 } */ + +#define MBEDTLS_OID_HMAC_SHA224 MBEDTLS_OID_RSA_COMPANY "\x02\x08" /**< id-hmacWithSHA224 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 8 } */ + +#define MBEDTLS_OID_HMAC_SHA256 MBEDTLS_OID_RSA_COMPANY "\x02\x09" /**< id-hmacWithSHA256 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 9 } */ + +#define MBEDTLS_OID_HMAC_SHA384 MBEDTLS_OID_RSA_COMPANY "\x02\x0A" /**< id-hmacWithSHA384 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 10 } */ + +#define MBEDTLS_OID_HMAC_SHA512 MBEDTLS_OID_RSA_COMPANY "\x02\x0B" /**< id-hmacWithSHA512 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 11 } */ + +/* + * Encryption algorithms + */ +#define MBEDTLS_OID_DES_CBC MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_OIW_SECSIG_ALG "\x07" /**< desCBC OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 7 } */ +#define MBEDTLS_OID_DES_EDE3_CBC MBEDTLS_OID_RSA_COMPANY "\x03\x07" /**< des-ede3-cbc OBJECT IDENTIFIER ::= { iso(1) member-body(2) -- us(840) rsadsi(113549) encryptionAlgorithm(3) 7 } */ +#define MBEDTLS_OID_AES MBEDTLS_OID_NIST_ALG "\x01" /** aes OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) 1 } */ + +/* + * Key Wrapping algorithms + */ +/* + * RFC 5649 + */ +#define MBEDTLS_OID_AES128_KW MBEDTLS_OID_AES "\x05" /** id-aes128-wrap OBJECT IDENTIFIER ::= { aes 5 } */ +#define MBEDTLS_OID_AES128_KWP MBEDTLS_OID_AES "\x08" /** id-aes128-wrap-pad OBJECT IDENTIFIER ::= { aes 8 } */ +#define MBEDTLS_OID_AES192_KW MBEDTLS_OID_AES "\x19" /** id-aes192-wrap OBJECT IDENTIFIER ::= { aes 25 } */ +#define MBEDTLS_OID_AES192_KWP MBEDTLS_OID_AES "\x1c" /** id-aes192-wrap-pad OBJECT IDENTIFIER ::= { aes 28 } */ +#define MBEDTLS_OID_AES256_KW MBEDTLS_OID_AES "\x2d" /** id-aes256-wrap OBJECT IDENTIFIER ::= { aes 45 } */ +#define MBEDTLS_OID_AES256_KWP MBEDTLS_OID_AES "\x30" /** id-aes256-wrap-pad OBJECT IDENTIFIER ::= { aes 48 } */ +/* + * PKCS#5 OIDs + */ +#define MBEDTLS_OID_PKCS5_PBKDF2 MBEDTLS_OID_PKCS5 "\x0c" /**< id-PBKDF2 OBJECT IDENTIFIER ::= {pkcs-5 12} */ +#define MBEDTLS_OID_PKCS5_PBES2 MBEDTLS_OID_PKCS5 "\x0d" /**< id-PBES2 OBJECT IDENTIFIER ::= {pkcs-5 13} */ +#define MBEDTLS_OID_PKCS5_PBMAC1 MBEDTLS_OID_PKCS5 "\x0e" /**< id-PBMAC1 OBJECT IDENTIFIER ::= {pkcs-5 14} */ + +/* + * PKCS#5 PBES1 algorithms + */ +#define MBEDTLS_OID_PKCS5_PBE_MD2_DES_CBC MBEDTLS_OID_PKCS5 "\x01" /**< pbeWithMD2AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 1} */ +#define MBEDTLS_OID_PKCS5_PBE_MD2_RC2_CBC MBEDTLS_OID_PKCS5 "\x04" /**< pbeWithMD2AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 4} */ +#define MBEDTLS_OID_PKCS5_PBE_MD5_DES_CBC MBEDTLS_OID_PKCS5 "\x03" /**< pbeWithMD5AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 3} */ +#define MBEDTLS_OID_PKCS5_PBE_MD5_RC2_CBC MBEDTLS_OID_PKCS5 "\x06" /**< pbeWithMD5AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 6} */ +#define MBEDTLS_OID_PKCS5_PBE_SHA1_DES_CBC MBEDTLS_OID_PKCS5 "\x0a" /**< pbeWithSHA1AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 10} */ +#define MBEDTLS_OID_PKCS5_PBE_SHA1_RC2_CBC MBEDTLS_OID_PKCS5 "\x0b" /**< pbeWithSHA1AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 11} */ + +/* + * PKCS#8 OIDs + */ +#define MBEDTLS_OID_PKCS9_CSR_EXT_REQ MBEDTLS_OID_PKCS9 "\x0e" /**< extensionRequest OBJECT IDENTIFIER ::= {pkcs-9 14} */ + +/* + * PKCS#12 PBE OIDs + */ +#define MBEDTLS_OID_PKCS12_PBE MBEDTLS_OID_PKCS12 "\x01" /**< pkcs-12PbeIds OBJECT IDENTIFIER ::= {pkcs-12 1} */ + +#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_128 MBEDTLS_OID_PKCS12_PBE "\x01" /**< pbeWithSHAAnd128BitRC4 OBJECT IDENTIFIER ::= {pkcs-12PbeIds 1} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_40 MBEDTLS_OID_PKCS12_PBE "\x02" /**< pbeWithSHAAnd40BitRC4 OBJECT IDENTIFIER ::= {pkcs-12PbeIds 2} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC MBEDTLS_OID_PKCS12_PBE "\x03" /**< pbeWithSHAAnd3-KeyTripleDES-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 3} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC MBEDTLS_OID_PKCS12_PBE "\x04" /**< pbeWithSHAAnd2-KeyTripleDES-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 4} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_128_CBC MBEDTLS_OID_PKCS12_PBE "\x05" /**< pbeWithSHAAnd128BitRC2-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 5} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_40_CBC MBEDTLS_OID_PKCS12_PBE "\x06" /**< pbeWithSHAAnd40BitRC2-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 6} */ + +/* + * EC key algorithms from RFC 5480 + */ + +/* id-ecPublicKey OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) keyType(2) 1 } */ +#define MBEDTLS_OID_EC_ALG_UNRESTRICTED MBEDTLS_OID_ANSI_X9_62 "\x02\01" + +/* id-ecDH OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) + * schemes(1) ecdh(12) } */ +#define MBEDTLS_OID_EC_ALG_ECDH MBEDTLS_OID_CERTICOM "\x01\x0c" + +/* + * ECParameters namedCurve identifiers, from RFC 5480, RFC 5639, and SEC2 + */ + +/* secp192r1 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 1 } */ +#define MBEDTLS_OID_EC_GRP_SECP192R1 MBEDTLS_OID_ANSI_X9_62 "\x03\x01\x01" + +/* secp224r1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 33 } */ +#define MBEDTLS_OID_EC_GRP_SECP224R1 MBEDTLS_OID_CERTICOM "\x00\x21" + +/* secp256r1 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 7 } */ +#define MBEDTLS_OID_EC_GRP_SECP256R1 MBEDTLS_OID_ANSI_X9_62 "\x03\x01\x07" + +/* secp384r1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 34 } */ +#define MBEDTLS_OID_EC_GRP_SECP384R1 MBEDTLS_OID_CERTICOM "\x00\x22" + +/* secp521r1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 35 } */ +#define MBEDTLS_OID_EC_GRP_SECP521R1 MBEDTLS_OID_CERTICOM "\x00\x23" + +/* secp192k1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 31 } */ +#define MBEDTLS_OID_EC_GRP_SECP192K1 MBEDTLS_OID_CERTICOM "\x00\x1f" + +/* secp224k1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 32 } */ +#define MBEDTLS_OID_EC_GRP_SECP224K1 MBEDTLS_OID_CERTICOM "\x00\x20" + +/* secp256k1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 10 } */ +#define MBEDTLS_OID_EC_GRP_SECP256K1 MBEDTLS_OID_CERTICOM "\x00\x0a" + +/* RFC 5639 4.1 + * ecStdCurvesAndGeneration OBJECT IDENTIFIER::= {iso(1) + * identified-organization(3) teletrust(36) algorithm(3) signature- + * algorithm(3) ecSign(2) 8} + * ellipticCurve OBJECT IDENTIFIER ::= {ecStdCurvesAndGeneration 1} + * versionOne OBJECT IDENTIFIER ::= {ellipticCurve 1} */ +#define MBEDTLS_OID_EC_BRAINPOOL_V1 MBEDTLS_OID_TELETRUST "\x03\x03\x02\x08\x01\x01" + +/* brainpoolP256r1 OBJECT IDENTIFIER ::= {versionOne 7} */ +#define MBEDTLS_OID_EC_GRP_BP256R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x07" + +/* brainpoolP384r1 OBJECT IDENTIFIER ::= {versionOne 11} */ +#define MBEDTLS_OID_EC_GRP_BP384R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x0B" + +/* brainpoolP512r1 OBJECT IDENTIFIER ::= {versionOne 13} */ +#define MBEDTLS_OID_EC_GRP_BP512R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x0D" + +/* + * SEC1 C.1 + * + * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 } + * id-fieldType OBJECT IDENTIFIER ::= { ansi-X9-62 fieldType(1)} + */ +#define MBEDTLS_OID_ANSI_X9_62_FIELD_TYPE MBEDTLS_OID_ANSI_X9_62 "\x01" +#define MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD MBEDTLS_OID_ANSI_X9_62_FIELD_TYPE "\x01" + +/* + * ECDSA signature identifiers, from RFC 5480 + */ +#define MBEDTLS_OID_ANSI_X9_62_SIG MBEDTLS_OID_ANSI_X9_62 "\x04" /* signatures(4) */ +#define MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 MBEDTLS_OID_ANSI_X9_62_SIG "\x03" /* ecdsa-with-SHA2(3) */ + +/* ecdsa-with-SHA1 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) 1 } */ +#define MBEDTLS_OID_ECDSA_SHA1 MBEDTLS_OID_ANSI_X9_62_SIG "\x01" + +/* ecdsa-with-SHA224 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 1 } */ +#define MBEDTLS_OID_ECDSA_SHA224 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x01" + +/* ecdsa-with-SHA256 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 2 } */ +#define MBEDTLS_OID_ECDSA_SHA256 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x02" + +/* ecdsa-with-SHA384 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 3 } */ +#define MBEDTLS_OID_ECDSA_SHA384 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x03" + +/* ecdsa-with-SHA512 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 4 } */ +#define MBEDTLS_OID_ECDSA_SHA512 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x04" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Base OID descriptor structure + */ +typedef struct mbedtls_oid_descriptor_t +{ + const char *asn1; /*!< OID ASN.1 representation */ + size_t asn1_len; /*!< length of asn1 */ + const char *name; /*!< official name (e.g. from RFC) */ + const char *description; /*!< human friendly description */ +} mbedtls_oid_descriptor_t; + +/** + * \brief Translate an ASN.1 OID into its numeric representation + * (e.g. "\x2A\x86\x48\x86\xF7\x0D" into "1.2.840.113549") + * + * \param buf buffer to put representation in + * \param size size of the buffer + * \param oid OID to translate + * + * \return Length of the string written (excluding final NULL) or + * MBEDTLS_ERR_OID_BUF_TOO_SMALL in case of error + */ +int mbedtls_oid_get_numeric_string( char *buf, size_t size, const mbedtls_asn1_buf *oid ); + +/** + * \brief Translate an X.509 extension OID into local values + * + * \param oid OID to use + * \param ext_type place to store the extension type + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_x509_ext_type( const mbedtls_asn1_buf *oid, int *ext_type ); + +/** + * \brief Translate an X.509 attribute type OID into the short name + * (e.g. the OID for an X520 Common Name into "CN") + * + * \param oid OID to use + * \param short_name place to store the string pointer + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_attr_short_name( const mbedtls_asn1_buf *oid, const char **short_name ); + +/** + * \brief Translate PublicKeyAlgorithm OID into pk_type + * + * \param oid OID to use + * \param pk_alg place to store public key algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_pk_alg( const mbedtls_asn1_buf *oid, mbedtls_pk_type_t *pk_alg ); + +/** + * \brief Translate pk_type into PublicKeyAlgorithm OID + * + * \param pk_alg Public key type to look for + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_oid_by_pk_alg( mbedtls_pk_type_t pk_alg, + const char **oid, size_t *olen ); + +#if defined(MBEDTLS_ECP_C) +/** + * \brief Translate NamedCurve OID into an EC group identifier + * + * \param oid OID to use + * \param grp_id place to store group id + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_ec_grp( const mbedtls_asn1_buf *oid, mbedtls_ecp_group_id *grp_id ); + +/** + * \brief Translate EC group identifier into NamedCurve OID + * + * \param grp_id EC group identifier + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_oid_by_ec_grp( mbedtls_ecp_group_id grp_id, + const char **oid, size_t *olen ); +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_MD_C) +/** + * \brief Translate SignatureAlgorithm OID into md_type and pk_type + * + * \param oid OID to use + * \param md_alg place to store message digest algorithm + * \param pk_alg place to store public key algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_sig_alg( const mbedtls_asn1_buf *oid, + mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg ); + +/** + * \brief Translate SignatureAlgorithm OID into description + * + * \param oid OID to use + * \param desc place to store string pointer + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_sig_alg_desc( const mbedtls_asn1_buf *oid, const char **desc ); + +/** + * \brief Translate md_type and pk_type into SignatureAlgorithm OID + * + * \param md_alg message digest algorithm + * \param pk_alg public key algorithm + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_oid_by_sig_alg( mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, + const char **oid, size_t *olen ); + +/** + * \brief Translate hash algorithm OID into md_type + * + * \param oid OID to use + * \param md_alg place to store message digest algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_md_alg( const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg ); + +/** + * \brief Translate hmac algorithm OID into md_type + * + * \param oid OID to use + * \param md_hmac place to store message hmac algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_md_hmac( const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_hmac ); +#endif /* MBEDTLS_MD_C */ + +/** + * \brief Translate Extended Key Usage OID into description + * + * \param oid OID to use + * \param desc place to store string pointer + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_extended_key_usage( const mbedtls_asn1_buf *oid, const char **desc ); + +/** + * \brief Translate certificate policies OID into description + * + * \param oid OID to use + * \param desc place to store string pointer + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_certificate_policies( const mbedtls_asn1_buf *oid, const char **desc ); + +/** + * \brief Translate md_type into hash algorithm OID + * + * \param md_alg message digest algorithm + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_oid_by_md( mbedtls_md_type_t md_alg, const char **oid, size_t *olen ); + +#if defined(MBEDTLS_CIPHER_C) +/** + * \brief Translate encryption algorithm OID into cipher_type + * + * \param oid OID to use + * \param cipher_alg place to store cipher algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_cipher_alg( const mbedtls_asn1_buf *oid, mbedtls_cipher_type_t *cipher_alg ); +#endif /* MBEDTLS_CIPHER_C */ + +#if defined(MBEDTLS_PKCS12_C) +/** + * \brief Translate PKCS#12 PBE algorithm OID into md_type and + * cipher_type + * + * \param oid OID to use + * \param md_alg place to store message digest algorithm + * \param cipher_alg place to store cipher algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_pkcs12_pbe_alg( const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg, + mbedtls_cipher_type_t *cipher_alg ); +#endif /* MBEDTLS_PKCS12_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* oid.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/padlock.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/padlock.h new file mode 100644 index 0000000..78dbeb6 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/padlock.h @@ -0,0 +1,124 @@ +/** + * \file padlock.h + * + * \brief VIA PadLock ACE for HW encryption/decryption supported by some + * processors + * + * \warning These functions are only for internal use by other library + * functions; you must not call them directly. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_PADLOCK_H +#define MBEDTLS_PADLOCK_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/aes.h" + +#define MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED -0x0030 /**< Input data should be aligned. */ + +#if defined(__has_feature) +#if __has_feature(address_sanitizer) +#define MBEDTLS_HAVE_ASAN +#endif +#endif + +/* Some versions of ASan result in errors about not enough registers */ +#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && defined(__i386__) && \ + !defined(MBEDTLS_HAVE_ASAN) + +#ifndef MBEDTLS_HAVE_X86 +#define MBEDTLS_HAVE_X86 +#endif + +#include + +#define MBEDTLS_PADLOCK_RNG 0x000C +#define MBEDTLS_PADLOCK_ACE 0x00C0 +#define MBEDTLS_PADLOCK_PHE 0x0C00 +#define MBEDTLS_PADLOCK_PMM 0x3000 + +#define MBEDTLS_PADLOCK_ALIGN16(x) (uint32_t *) (16 + ((int32_t) (x) & ~15)) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Internal PadLock detection routine + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. + * + * \param feature The feature to detect + * + * \return 1 if CPU has support for the feature, 0 otherwise + */ +int mbedtls_padlock_has_support( int feature ); + +/** + * \brief Internal PadLock AES-ECB block en(de)cryption + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. + * + * \param ctx AES context + * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT + * \param input 16-byte input block + * \param output 16-byte output block + * + * \return 0 if success, 1 if operation failed + */ +int mbedtls_padlock_xcryptecb( mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ); + +/** + * \brief Internal PadLock AES-CBC buffer en(de)cryption + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. + * + * \param ctx AES context + * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if success, 1 if operation failed + */ +int mbedtls_padlock_xcryptcbc( mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); + +#ifdef __cplusplus +} +#endif + +#endif /* HAVE_X86 */ + +#endif /* padlock.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/pem.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/pem.h new file mode 100644 index 0000000..4769bec --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/pem.h @@ -0,0 +1,144 @@ +/** + * \file pem.h + * + * \brief Privacy Enhanced Mail (PEM) decoding + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_PEM_H +#define MBEDTLS_PEM_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +/** + * \name PEM Error codes + * These error codes are returned in case of errors reading the + * PEM data. + * \{ + */ +#define MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT -0x1080 /**< No PEM header or footer found. */ +#define MBEDTLS_ERR_PEM_INVALID_DATA -0x1100 /**< PEM string is not as expected. */ +#define MBEDTLS_ERR_PEM_ALLOC_FAILED -0x1180 /**< Failed to allocate memory. */ +#define MBEDTLS_ERR_PEM_INVALID_ENC_IV -0x1200 /**< RSA IV is not in hex-format. */ +#define MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG -0x1280 /**< Unsupported key encryption algorithm. */ +#define MBEDTLS_ERR_PEM_PASSWORD_REQUIRED -0x1300 /**< Private key password can't be empty. */ +#define MBEDTLS_ERR_PEM_PASSWORD_MISMATCH -0x1380 /**< Given private key password does not allow for correct decryption. */ +#define MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE -0x1400 /**< Unavailable feature, e.g. hashing/encryption combination. */ +#define MBEDTLS_ERR_PEM_BAD_INPUT_DATA -0x1480 /**< Bad input parameters to function. */ +/* \} name */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) +/** + * \brief PEM context structure + */ +typedef struct mbedtls_pem_context +{ + unsigned char *buf; /*!< buffer for decoded data */ + size_t buflen; /*!< length of the buffer */ + unsigned char *info; /*!< buffer for extra header information */ +} +mbedtls_pem_context; + +/** + * \brief PEM context setup + * + * \param ctx context to be initialized + */ +void mbedtls_pem_init( mbedtls_pem_context *ctx ); + +/** + * \brief Read a buffer for PEM information and store the resulting + * data into the specified context buffers. + * + * \param ctx context to use + * \param header header string to seek and expect + * \param footer footer string to seek and expect + * \param data source data to look in (must be nul-terminated) + * \param pwd password for decryption (can be NULL) + * \param pwdlen length of password + * \param use_len destination for total length used (set after header is + * correctly read, so unless you get + * MBEDTLS_ERR_PEM_BAD_INPUT_DATA or + * MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT, use_len is + * the length to skip) + * + * \note Attempts to check password correctness by verifying if + * the decrypted text starts with an ASN.1 sequence of + * appropriate length + * + * \return 0 on success, or a specific PEM error code + */ +int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const char *footer, + const unsigned char *data, + const unsigned char *pwd, + size_t pwdlen, size_t *use_len ); + +/** + * \brief PEM context memory freeing + * + * \param ctx context to be freed + */ +void mbedtls_pem_free( mbedtls_pem_context *ctx ); +#endif /* MBEDTLS_PEM_PARSE_C */ + +#if defined(MBEDTLS_PEM_WRITE_C) +/** + * \brief Write a buffer of PEM information from a DER encoded + * buffer. + * + * \param header The header string to write. + * \param footer The footer string to write. + * \param der_data The DER data to encode. + * \param der_len The length of the DER data \p der_data in Bytes. + * \param buf The buffer to write to. + * \param buf_len The length of the output buffer \p buf in Bytes. + * \param olen The address at which to store the total length written + * or required (if \p buf_len is not enough). + * + * \note You may pass \c NULL for \p buf and \c 0 for \p buf_len + * to request the length of the resulting PEM buffer in + * `*olen`. + * + * \note This function may be called with overlapping \p der_data + * and \p buf buffers. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL if \p buf isn't large + * enough to hold the PEM buffer. In this case, `*olen` holds + * the required minimum size of \p buf. + * \return Another PEM or BASE64 error code on other kinds of failure. + */ +int mbedtls_pem_write_buffer( const char *header, const char *footer, + const unsigned char *der_data, size_t der_len, + unsigned char *buf, size_t buf_len, size_t *olen ); +#endif /* MBEDTLS_PEM_WRITE_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* pem.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/pk.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/pk.h new file mode 100644 index 0000000..22fab13 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/pk.h @@ -0,0 +1,879 @@ +/** + * \file pk.h + * + * \brief Public Key abstraction layer + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_PK_H +#define MBEDTLS_PK_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/md.h" + +#if defined(MBEDTLS_RSA_C) +#include "mbedtls/rsa.h" +#endif + +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/ecp.h" +#endif + +#if defined(MBEDTLS_ECDSA_C) +#include "mbedtls/ecdsa.h" +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#endif + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#define MBEDTLS_ERR_PK_ALLOC_FAILED -0x3F80 /**< Memory allocation failed. */ +#define MBEDTLS_ERR_PK_TYPE_MISMATCH -0x3F00 /**< Type mismatch, eg attempt to encrypt with an ECDSA key */ +#define MBEDTLS_ERR_PK_BAD_INPUT_DATA -0x3E80 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_PK_FILE_IO_ERROR -0x3E00 /**< Read/write of file failed. */ +#define MBEDTLS_ERR_PK_KEY_INVALID_VERSION -0x3D80 /**< Unsupported key version */ +#define MBEDTLS_ERR_PK_KEY_INVALID_FORMAT -0x3D00 /**< Invalid key tag or value. */ +#define MBEDTLS_ERR_PK_UNKNOWN_PK_ALG -0x3C80 /**< Key algorithm is unsupported (only RSA and EC are supported). */ +#define MBEDTLS_ERR_PK_PASSWORD_REQUIRED -0x3C00 /**< Private key password can't be empty. */ +#define MBEDTLS_ERR_PK_PASSWORD_MISMATCH -0x3B80 /**< Given private key password does not allow for correct decryption. */ +#define MBEDTLS_ERR_PK_INVALID_PUBKEY -0x3B00 /**< The pubkey tag or value is invalid (only RSA and EC are supported). */ +#define MBEDTLS_ERR_PK_INVALID_ALG -0x3A80 /**< The algorithm tag or value is invalid. */ +#define MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE -0x3A00 /**< Elliptic curve is unsupported (only NIST curves are supported). */ +#define MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE -0x3980 /**< Unavailable feature, e.g. RSA disabled for RSA key. */ +#define MBEDTLS_ERR_PK_SIG_LEN_MISMATCH -0x3900 /**< The buffer contains a valid signature followed by more data. */ + +/* MBEDTLS_ERR_PK_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_PK_HW_ACCEL_FAILED -0x3880 /**< PK hardware accelerator failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Public key types + */ +typedef enum { + MBEDTLS_PK_NONE=0, + MBEDTLS_PK_RSA, + MBEDTLS_PK_ECKEY, + MBEDTLS_PK_ECKEY_DH, + MBEDTLS_PK_ECDSA, + MBEDTLS_PK_RSA_ALT, + MBEDTLS_PK_RSASSA_PSS, + MBEDTLS_PK_OPAQUE, +} mbedtls_pk_type_t; + +/** + * \brief Options for RSASSA-PSS signature verification. + * See \c mbedtls_rsa_rsassa_pss_verify_ext() + */ +typedef struct mbedtls_pk_rsassa_pss_options +{ + mbedtls_md_type_t mgf1_hash_id; + int expected_salt_len; + +} mbedtls_pk_rsassa_pss_options; + +/** + * \brief Maximum size of a signature made by mbedtls_pk_sign(). + */ +/* We need to set MBEDTLS_PK_SIGNATURE_MAX_SIZE to the maximum signature + * size among the supported signature types. Do it by starting at 0, + * then incrementally increasing to be large enough for each supported + * signature mechanism. + * + * The resulting value can be 0, for example if MBEDTLS_ECDH_C is enabled + * (which allows the pk module to be included) but neither MBEDTLS_ECDSA_C + * nor MBEDTLS_RSA_C nor any opaque signature mechanism (PSA or RSA_ALT). + */ +#define MBEDTLS_PK_SIGNATURE_MAX_SIZE 0 + +#if ( defined(MBEDTLS_RSA_C) || defined(MBEDTLS_PK_RSA_ALT_SUPPORT) ) && \ + MBEDTLS_MPI_MAX_SIZE > MBEDTLS_PK_SIGNATURE_MAX_SIZE +/* For RSA, the signature can be as large as the bignum module allows. + * For RSA_ALT, the signature size is not necessarily tied to what the + * bignum module can do, but in the absence of any specific setting, + * we use that (rsa_alt_sign_wrap in pk_wrap will check). */ +#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE +#define MBEDTLS_PK_SIGNATURE_MAX_SIZE MBEDTLS_MPI_MAX_SIZE +#endif + +#if defined(MBEDTLS_ECDSA_C) && \ + MBEDTLS_ECDSA_MAX_LEN > MBEDTLS_PK_SIGNATURE_MAX_SIZE +/* For ECDSA, the ecdsa module exports a constant for the maximum + * signature size. */ +#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE +#define MBEDTLS_PK_SIGNATURE_MAX_SIZE MBEDTLS_ECDSA_MAX_LEN +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#if PSA_SIGNATURE_MAX_SIZE > MBEDTLS_PK_SIGNATURE_MAX_SIZE +/* PSA_SIGNATURE_MAX_SIZE is the maximum size of a signature made + * through the PSA API in the PSA representation. */ +#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE +#define MBEDTLS_PK_SIGNATURE_MAX_SIZE PSA_SIGNATURE_MAX_SIZE +#endif + +#if PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE + 11 > MBEDTLS_PK_SIGNATURE_MAX_SIZE +/* The Mbed TLS representation is different for ECDSA signatures: + * PSA uses the raw concatenation of r and s, + * whereas Mbed TLS uses the ASN.1 representation (SEQUENCE of two INTEGERs). + * Add the overhead of ASN.1: up to (1+2) + 2 * (1+2+1) for the + * types, lengths (represented by up to 2 bytes), and potential leading + * zeros of the INTEGERs and the SEQUENCE. */ +#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE +#define MBEDTLS_PK_SIGNATURE_MAX_SIZE ( PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE + 11 ) +#endif +#endif /* defined(MBEDTLS_USE_PSA_CRYPTO) */ + +/** + * \brief Types for interfacing with the debug module + */ +typedef enum +{ + MBEDTLS_PK_DEBUG_NONE = 0, + MBEDTLS_PK_DEBUG_MPI, + MBEDTLS_PK_DEBUG_ECP, +} mbedtls_pk_debug_type; + +/** + * \brief Item to send to the debug module + */ +typedef struct mbedtls_pk_debug_item +{ + mbedtls_pk_debug_type type; + const char *name; + void *value; +} mbedtls_pk_debug_item; + +/** Maximum number of item send for debugging, plus 1 */ +#define MBEDTLS_PK_DEBUG_MAX_ITEMS 3 + +/** + * \brief Public key information and operations + */ +typedef struct mbedtls_pk_info_t mbedtls_pk_info_t; + +/** + * \brief Public key container + */ +typedef struct mbedtls_pk_context +{ + const mbedtls_pk_info_t * pk_info; /**< Public key information */ + void * pk_ctx; /**< Underlying public key context */ +} mbedtls_pk_context; + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Context for resuming operations + */ +typedef struct +{ + const mbedtls_pk_info_t * pk_info; /**< Public key information */ + void * rs_ctx; /**< Underlying restart context */ +} mbedtls_pk_restart_ctx; +#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ +/* Now we can declare functions that take a pointer to that */ +typedef void mbedtls_pk_restart_ctx; +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + +#if defined(MBEDTLS_RSA_C) +/** + * Quick access to an RSA context inside a PK context. + * + * \warning You must make sure the PK context actually holds an RSA context + * before using this function! + */ +static inline mbedtls_rsa_context *mbedtls_pk_rsa( const mbedtls_pk_context pk ) +{ + return( (mbedtls_rsa_context *) (pk).pk_ctx ); +} +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) +/** + * Quick access to an EC context inside a PK context. + * + * \warning You must make sure the PK context actually holds an EC context + * before using this function! + */ +static inline mbedtls_ecp_keypair *mbedtls_pk_ec( const mbedtls_pk_context pk ) +{ + return( (mbedtls_ecp_keypair *) (pk).pk_ctx ); +} +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/** + * \brief Types for RSA-alt abstraction + */ +typedef int (*mbedtls_pk_rsa_alt_decrypt_func)( void *ctx, int mode, size_t *olen, + const unsigned char *input, unsigned char *output, + size_t output_max_len ); +typedef int (*mbedtls_pk_rsa_alt_sign_func)( void *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + int mode, mbedtls_md_type_t md_alg, unsigned int hashlen, + const unsigned char *hash, unsigned char *sig ); +typedef size_t (*mbedtls_pk_rsa_alt_key_len_func)( void *ctx ); +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ + +/** + * \brief Return information associated with the given PK type + * + * \param pk_type PK type to search for. + * + * \return The PK info associated with the type or NULL if not found. + */ +const mbedtls_pk_info_t *mbedtls_pk_info_from_type( mbedtls_pk_type_t pk_type ); + +/** + * \brief Initialize a #mbedtls_pk_context (as NONE). + * + * \param ctx The context to initialize. + * This must not be \c NULL. + */ +void mbedtls_pk_init( mbedtls_pk_context *ctx ); + +/** + * \brief Free the components of a #mbedtls_pk_context. + * + * \param ctx The context to clear. It must have been initialized. + * If this is \c NULL, this function does nothing. + * + * \note For contexts that have been set up with + * mbedtls_pk_setup_opaque(), this does not free the underlying + * PSA key and you still need to call psa_destroy_key() + * independently if you want to destroy that key. + */ +void mbedtls_pk_free( mbedtls_pk_context *ctx ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Initialize a restart context + * + * \param ctx The context to initialize. + * This must not be \c NULL. + */ +void mbedtls_pk_restart_init( mbedtls_pk_restart_ctx *ctx ); + +/** + * \brief Free the components of a restart context + * + * \param ctx The context to clear. It must have been initialized. + * If this is \c NULL, this function does nothing. + */ +void mbedtls_pk_restart_free( mbedtls_pk_restart_ctx *ctx ); +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + +/** + * \brief Initialize a PK context with the information given + * and allocates the type-specific PK subcontext. + * + * \param ctx Context to initialize. It must not have been set + * up yet (type #MBEDTLS_PK_NONE). + * \param info Information to use + * + * \return 0 on success, + * MBEDTLS_ERR_PK_BAD_INPUT_DATA on invalid input, + * MBEDTLS_ERR_PK_ALLOC_FAILED on allocation failure. + * + * \note For contexts holding an RSA-alt key, use + * \c mbedtls_pk_setup_rsa_alt() instead. + */ +int mbedtls_pk_setup( mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/** + * \brief Initialize a PK context to wrap a PSA key. + * + * \note This function replaces mbedtls_pk_setup() for contexts + * that wrap a (possibly opaque) PSA key instead of + * storing and manipulating the key material directly. + * + * \param ctx The context to initialize. It must be empty (type NONE). + * \param key The PSA key to wrap, which must hold an ECC key pair + * (see notes below). + * + * \note The wrapped key must remain valid as long as the + * wrapping PK context is in use, that is at least between + * the point this function is called and the point + * mbedtls_pk_free() is called on this context. The wrapped + * key might then be independently used or destroyed. + * + * \note This function is currently only available for ECC key + * pairs (that is, ECC keys containing private key material). + * Support for other key types may be added later. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_PK_BAD_INPUT_DATA on invalid input + * (context already used, invalid key handle). + * \return #MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE if the key is not an + * ECC key pair. + * \return #MBEDTLS_ERR_PK_ALLOC_FAILED on allocation failure. + */ +int mbedtls_pk_setup_opaque( mbedtls_pk_context *ctx, const psa_key_handle_t key ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/** + * \brief Initialize an RSA-alt context + * + * \param ctx Context to initialize. It must not have been set + * up yet (type #MBEDTLS_PK_NONE). + * \param key RSA key pointer + * \param decrypt_func Decryption function + * \param sign_func Signing function + * \param key_len_func Function returning key length in bytes + * + * \return 0 on success, or MBEDTLS_ERR_PK_BAD_INPUT_DATA if the + * context wasn't already initialized as RSA_ALT. + * + * \note This function replaces \c mbedtls_pk_setup() for RSA-alt. + */ +int mbedtls_pk_setup_rsa_alt( mbedtls_pk_context *ctx, void * key, + mbedtls_pk_rsa_alt_decrypt_func decrypt_func, + mbedtls_pk_rsa_alt_sign_func sign_func, + mbedtls_pk_rsa_alt_key_len_func key_len_func ); +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ + +/** + * \brief Get the size in bits of the underlying key + * + * \param ctx The context to query. It must have been initialized. + * + * \return Key size in bits, or 0 on error + */ +size_t mbedtls_pk_get_bitlen( const mbedtls_pk_context *ctx ); + +/** + * \brief Get the length in bytes of the underlying key + * + * \param ctx The context to query. It must have been initialized. + * + * \return Key length in bytes, or 0 on error + */ +static inline size_t mbedtls_pk_get_len( const mbedtls_pk_context *ctx ) +{ + return( ( mbedtls_pk_get_bitlen( ctx ) + 7 ) / 8 ); +} + +/** + * \brief Tell if a context can do the operation given by type + * + * \param ctx The context to query. It must have been initialized. + * \param type The desired type. + * + * \return 1 if the context can do operations on the given type. + * \return 0 if the context cannot do the operations on the given + * type. This is always the case for a context that has + * been initialized but not set up, or that has been + * cleared with mbedtls_pk_free(). + */ +int mbedtls_pk_can_do( const mbedtls_pk_context *ctx, mbedtls_pk_type_t type ); + +/** + * \brief Verify signature (including padding if relevant). + * + * \param ctx The PK context to use. It must have been set up. + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Signature to verify + * \param sig_len Signature length + * + * \return 0 on success (signature is valid), + * #MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if there is a valid + * signature in sig but its length is less than \p siglen, + * or a specific error code. + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * Use \c mbedtls_pk_verify_ext( MBEDTLS_PK_RSASSA_PSS, ... ) + * to verify RSASSA_PSS signatures. + * + * \note If hash_len is 0, then the length associated with md_alg + * is used instead, or an error returned if it is invalid. + * + * \note md_alg may be MBEDTLS_MD_NONE, only if hash_len != 0 + */ +int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ); + +/** + * \brief Restartable version of \c mbedtls_pk_verify() + * + * \note Performs the same job as \c mbedtls_pk_verify(), but can + * return early and restart according to the limit set with + * \c mbedtls_ecp_set_max_ops() to reduce blocking for ECC + * operations. For RSA, same as \c mbedtls_pk_verify(). + * + * \param ctx The PK context to use. It must have been set up. + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Signature to verify + * \param sig_len Signature length + * \param rs_ctx Restart context (NULL to disable restart) + * + * \return See \c mbedtls_pk_verify(), or + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + */ +int mbedtls_pk_verify_restartable( mbedtls_pk_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + mbedtls_pk_restart_ctx *rs_ctx ); + +/** + * \brief Verify signature, with options. + * (Includes verification of the padding depending on type.) + * + * \param type Signature type (inc. possible padding type) to verify + * \param options Pointer to type-specific options, or NULL + * \param ctx The PK context to use. It must have been set up. + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Signature to verify + * \param sig_len Signature length + * + * \return 0 on success (signature is valid), + * #MBEDTLS_ERR_PK_TYPE_MISMATCH if the PK context can't be + * used for this type of signatures, + * #MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if there is a valid + * signature in sig but its length is less than \p siglen, + * or a specific error code. + * + * \note If hash_len is 0, then the length associated with md_alg + * is used instead, or an error returned if it is invalid. + * + * \note md_alg may be MBEDTLS_MD_NONE, only if hash_len != 0 + * + * \note If type is MBEDTLS_PK_RSASSA_PSS, then options must point + * to a mbedtls_pk_rsassa_pss_options structure, + * otherwise it must be NULL. + */ +int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options, + mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ); + +/** + * \brief Make signature, including padding if relevant. + * + * \param ctx The PK context to use. It must have been set up + * with a private key. + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Place to write the signature. + * It must have enough room for the signature. + * #MBEDTLS_PK_SIGNATURE_MAX_SIZE is always enough. + * You may use a smaller buffer if it is large enough + * given the key type. + * \param sig_len On successful return, + * the number of bytes written to \p sig. + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 on success, or a specific error code. + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * There is no interface in the PK module to make RSASSA-PSS + * signatures yet. + * + * \note If hash_len is 0, then the length associated with md_alg + * is used instead, or an error returned if it is invalid. + * + * \note For RSA, md_alg may be MBEDTLS_MD_NONE if hash_len != 0. + * For ECDSA, md_alg may never be MBEDTLS_MD_NONE. + */ +int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief Restartable version of \c mbedtls_pk_sign() + * + * \note Performs the same job as \c mbedtls_pk_sign(), but can + * return early and restart according to the limit set with + * \c mbedtls_ecp_set_max_ops() to reduce blocking for ECC + * operations. For RSA, same as \c mbedtls_pk_sign(). + * + * \param ctx The PK context to use. It must have been set up + * with a private key. + * \param md_alg Hash algorithm used (see notes for mbedtls_pk_sign()) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes for mbedtls_pk_sign()) + * \param sig Place to write the signature. + * It must have enough room for the signature. + * #MBEDTLS_PK_SIGNATURE_MAX_SIZE is always enough. + * You may use a smaller buffer if it is large enough + * given the key type. + * \param sig_len On successful return, + * the number of bytes written to \p sig. + * \param f_rng RNG function + * \param p_rng RNG parameter + * \param rs_ctx Restart context (NULL to disable restart) + * + * \return See \c mbedtls_pk_sign(). + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + */ +int mbedtls_pk_sign_restartable( mbedtls_pk_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_pk_restart_ctx *rs_ctx ); + +/** + * \brief Decrypt message (including padding if relevant). + * + * \param ctx The PK context to use. It must have been set up + * with a private key. + * \param input Input to decrypt + * \param ilen Input size + * \param output Decrypted output + * \param olen Decrypted message length + * \param osize Size of the output buffer + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * + * \return 0 on success, or a specific error code. + */ +int mbedtls_pk_decrypt( mbedtls_pk_context *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief Encrypt message (including padding if relevant). + * + * \param ctx The PK context to use. It must have been set up. + * \param input Message to encrypt + * \param ilen Message size + * \param output Encrypted output + * \param olen Encrypted output length + * \param osize Size of the output buffer + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * + * \return 0 on success, or a specific error code. + */ +int mbedtls_pk_encrypt( mbedtls_pk_context *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief Check if a public-private pair of keys matches. + * + * \param pub Context holding a public key. + * \param prv Context holding a private (and public) key. + * + * \return \c 0 on success (keys were checked and match each other). + * \return #MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE if the keys could not + * be checked - in that case they may or may not match. + * \return #MBEDTLS_ERR_PK_BAD_INPUT_DATA if a context is invalid. + * \return Another non-zero value if the keys do not match. + */ +int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, const mbedtls_pk_context *prv ); + +/** + * \brief Export debug information + * + * \param ctx The PK context to use. It must have been initialized. + * \param items Place to write debug items + * + * \return 0 on success or MBEDTLS_ERR_PK_BAD_INPUT_DATA + */ +int mbedtls_pk_debug( const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items ); + +/** + * \brief Access the type name + * + * \param ctx The PK context to use. It must have been initialized. + * + * \return Type name on success, or "invalid PK" + */ +const char * mbedtls_pk_get_name( const mbedtls_pk_context *ctx ); + +/** + * \brief Get the key type + * + * \param ctx The PK context to use. It must have been initialized. + * + * \return Type on success. + * \return #MBEDTLS_PK_NONE for a context that has not been set up. + */ +mbedtls_pk_type_t mbedtls_pk_get_type( const mbedtls_pk_context *ctx ); + +#if defined(MBEDTLS_PK_PARSE_C) +/** \ingroup pk_module */ +/** + * \brief Parse a private key in PEM or DER format + * + * \param ctx The PK context to fill. It must have been initialized + * but not set up. + * \param key Input buffer to parse. + * The buffer must contain the input exactly, with no + * extra trailing material. For PEM, the buffer must + * contain a null-terminated string. + * \param keylen Size of \b key in bytes. + * For PEM data, this includes the terminating null byte, + * so \p keylen must be equal to `strlen(key) + 1`. + * \param pwd Optional password for decryption. + * Pass \c NULL if expecting a non-encrypted key. + * Pass a string of \p pwdlen bytes if expecting an encrypted + * key; a non-encrypted key will also be accepted. + * The empty password is not supported. + * \param pwdlen Size of the password in bytes. + * Ignored if \p pwd is \c NULL. + * + * \note On entry, ctx must be empty, either freshly initialised + * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a + * specific key type, check the result with mbedtls_pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int mbedtls_pk_parse_key( mbedtls_pk_context *ctx, + const unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen ); + +/** \ingroup pk_module */ +/** + * \brief Parse a public key in PEM or DER format + * + * \param ctx The PK context to fill. It must have been initialized + * but not set up. + * \param key Input buffer to parse. + * The buffer must contain the input exactly, with no + * extra trailing material. For PEM, the buffer must + * contain a null-terminated string. + * \param keylen Size of \b key in bytes. + * For PEM data, this includes the terminating null byte, + * so \p keylen must be equal to `strlen(key) + 1`. + * + * \note On entry, ctx must be empty, either freshly initialised + * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a + * specific key type, check the result with mbedtls_pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int mbedtls_pk_parse_public_key( mbedtls_pk_context *ctx, + const unsigned char *key, size_t keylen ); + +#if defined(MBEDTLS_FS_IO) +/** \ingroup pk_module */ +/** + * \brief Load and parse a private key + * + * \param ctx The PK context to fill. It must have been initialized + * but not set up. + * \param path filename to read the private key from + * \param password Optional password to decrypt the file. + * Pass \c NULL if expecting a non-encrypted key. + * Pass a null-terminated string if expecting an encrypted + * key; a non-encrypted key will also be accepted. + * The empty password is not supported. + * + * \note On entry, ctx must be empty, either freshly initialised + * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a + * specific key type, check the result with mbedtls_pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int mbedtls_pk_parse_keyfile( mbedtls_pk_context *ctx, + const char *path, const char *password ); + +/** \ingroup pk_module */ +/** + * \brief Load and parse a public key + * + * \param ctx The PK context to fill. It must have been initialized + * but not set up. + * \param path filename to read the public key from + * + * \note On entry, ctx must be empty, either freshly initialised + * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If + * you need a specific key type, check the result with + * mbedtls_pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int mbedtls_pk_parse_public_keyfile( mbedtls_pk_context *ctx, const char *path ); +#endif /* MBEDTLS_FS_IO */ +#endif /* MBEDTLS_PK_PARSE_C */ + +#if defined(MBEDTLS_PK_WRITE_C) +/** + * \brief Write a private key to a PKCS#1 or SEC1 DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param ctx PK context which must contain a valid private key. + * \param buf buffer to write to + * \param size size of the buffer + * + * \return length of data written if successful, or a specific + * error code + */ +int mbedtls_pk_write_key_der( mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); + +/** + * \brief Write a public key to a SubjectPublicKeyInfo DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param ctx PK context which must contain a valid public or private key. + * \param buf buffer to write to + * \param size size of the buffer + * + * \return length of data written if successful, or a specific + * error code + */ +int mbedtls_pk_write_pubkey_der( mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); + +#if defined(MBEDTLS_PEM_WRITE_C) +/** + * \brief Write a public key to a PEM string + * + * \param ctx PK context which must contain a valid public or private key. + * \param buf Buffer to write to. The output includes a + * terminating null byte. + * \param size Size of the buffer in bytes. + * + * \return 0 if successful, or a specific error code + */ +int mbedtls_pk_write_pubkey_pem( mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); + +/** + * \brief Write a private key to a PKCS#1 or SEC1 PEM string + * + * \param ctx PK context which must contain a valid private key. + * \param buf Buffer to write to. The output includes a + * terminating null byte. + * \param size Size of the buffer in bytes. + * + * \return 0 if successful, or a specific error code + */ +int mbedtls_pk_write_key_pem( mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); +#endif /* MBEDTLS_PEM_WRITE_C */ +#endif /* MBEDTLS_PK_WRITE_C */ + +/* + * WARNING: Low-level functions. You probably do not want to use these unless + * you are certain you do ;) + */ + +#if defined(MBEDTLS_PK_PARSE_C) +/** + * \brief Parse a SubjectPublicKeyInfo DER structure + * + * \param p the position in the ASN.1 data + * \param end end of the buffer + * \param pk The PK context to fill. It must have been initialized + * but not set up. + * + * \return 0 if successful, or a specific PK error code + */ +int mbedtls_pk_parse_subpubkey( unsigned char **p, const unsigned char *end, + mbedtls_pk_context *pk ); +#endif /* MBEDTLS_PK_PARSE_C */ + +#if defined(MBEDTLS_PK_WRITE_C) +/** + * \brief Write a subjectPublicKey to ASN.1 data + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param key PK context which must contain a valid public or private key. + * + * \return the length written or a negative error code + */ +int mbedtls_pk_write_pubkey( unsigned char **p, unsigned char *start, + const mbedtls_pk_context *key ); +#endif /* MBEDTLS_PK_WRITE_C */ + +/* + * Internal module functions. You probably do not want to use these unless you + * know you do. + */ +#if defined(MBEDTLS_FS_IO) +int mbedtls_pk_load_file( const char *path, unsigned char **buf, size_t *n ); +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/** + * \brief Turn an EC key into an opaque one. + * + * \warning This is a temporary utility function for tests. It might + * change or be removed at any time without notice. + * + * \note Only ECDSA keys are supported so far. Signing with the + * specified hash is the only allowed use of that key. + * + * \param pk Input: the EC key to import to a PSA key. + * Output: a PK context wrapping that PSA key. + * \param handle Output: a PSA key handle. + * It's the caller's responsibility to call + * psa_destroy_key() on that handle after calling + * mbedtls_pk_free() on the PK context. + * \param hash_alg The hash algorithm to allow for use with that key. + * + * \return \c 0 if successful. + * \return An Mbed TLS error code otherwise. + */ +int mbedtls_pk_wrap_as_opaque( mbedtls_pk_context *pk, + psa_key_handle_t *handle, + psa_algorithm_t hash_alg ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_PK_H */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/pk_internal.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/pk_internal.h new file mode 100644 index 0000000..47f7767 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/pk_internal.h @@ -0,0 +1,140 @@ +/** + * \file pk_internal.h + * + * \brief Public Key abstraction layer: wrapper functions + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_PK_WRAP_H +#define MBEDTLS_PK_WRAP_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/pk.h" + +struct mbedtls_pk_info_t +{ + /** Public key type */ + mbedtls_pk_type_t type; + + /** Type name */ + const char *name; + + /** Get key size in bits */ + size_t (*get_bitlen)( const void * ); + + /** Tell if the context implements this type (e.g. ECKEY can do ECDSA) */ + int (*can_do)( mbedtls_pk_type_t type ); + + /** Verify signature */ + int (*verify_func)( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ); + + /** Make signature */ + int (*sign_func)( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /** Verify signature (restartable) */ + int (*verify_rs_func)( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + void *rs_ctx ); + + /** Make signature (restartable) */ + int (*sign_rs_func)( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, void *rs_ctx ); +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + + /** Decrypt message */ + int (*decrypt_func)( void *ctx, const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + + /** Encrypt message */ + int (*encrypt_func)( void *ctx, const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + + /** Check public-private key pair */ + int (*check_pair_func)( const void *pub, const void *prv ); + + /** Allocate a new context */ + void * (*ctx_alloc_func)( void ); + + /** Free the given context */ + void (*ctx_free_func)( void *ctx ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /** Allocate the restart context */ + void * (*rs_alloc_func)( void ); + + /** Free the restart context */ + void (*rs_free_func)( void *rs_ctx ); +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + + /** Interface with the debug module */ + void (*debug_func)( const void *ctx, mbedtls_pk_debug_item *items ); + +}; +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/* Container for RSA-alt */ +typedef struct +{ + void *key; + mbedtls_pk_rsa_alt_decrypt_func decrypt_func; + mbedtls_pk_rsa_alt_sign_func sign_func; + mbedtls_pk_rsa_alt_key_len_func key_len_func; +} mbedtls_rsa_alt_context; +#endif + +#if defined(MBEDTLS_RSA_C) +extern const mbedtls_pk_info_t mbedtls_rsa_info; +#endif + +#if defined(MBEDTLS_ECP_C) +extern const mbedtls_pk_info_t mbedtls_eckey_info; +extern const mbedtls_pk_info_t mbedtls_eckeydh_info; +#endif + +#if defined(MBEDTLS_ECDSA_C) +extern const mbedtls_pk_info_t mbedtls_ecdsa_info; +#endif + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +extern const mbedtls_pk_info_t mbedtls_rsa_alt_info; +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +extern const mbedtls_pk_info_t mbedtls_pk_opaque_info; +#endif + +#endif /* MBEDTLS_PK_WRAP_H */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/pkcs11.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/pkcs11.h new file mode 100644 index 0000000..3530ee1 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/pkcs11.h @@ -0,0 +1,246 @@ +/** + * \file pkcs11.h + * + * \brief Wrapper for PKCS#11 library libpkcs11-helper + * + * \author Adriaan de Jong + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_PKCS11_H +#define MBEDTLS_PKCS11_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PKCS11_C) + +#include "mbedtls/x509_crt.h" + +#include + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_DEPRECATED_REMOVED) + +/** + * Context for PKCS #11 private keys. + */ +typedef struct mbedtls_pkcs11_context +{ + pkcs11h_certificate_t pkcs11h_cert; + int len; +} mbedtls_pkcs11_context; + +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif + +/** + * Initialize a mbedtls_pkcs11_context. + * (Just making memory references valid.) + * + * \deprecated This function is deprecated and will be removed in a + * future version of the library. + */ +MBEDTLS_DEPRECATED void mbedtls_pkcs11_init( mbedtls_pkcs11_context *ctx ); + +/** + * Fill in a mbed TLS certificate, based on the given PKCS11 helper certificate. + * + * \deprecated This function is deprecated and will be removed in a + * future version of the library. + * + * \param cert X.509 certificate to fill + * \param pkcs11h_cert PKCS #11 helper certificate + * + * \return 0 on success. + */ +MBEDTLS_DEPRECATED int mbedtls_pkcs11_x509_cert_bind( mbedtls_x509_crt *cert, + pkcs11h_certificate_t pkcs11h_cert ); + +/** + * Set up a mbedtls_pkcs11_context storing the given certificate. Note that the + * mbedtls_pkcs11_context will take over control of the certificate, freeing it when + * done. + * + * \deprecated This function is deprecated and will be removed in a + * future version of the library. + * + * \param priv_key Private key structure to fill. + * \param pkcs11_cert PKCS #11 helper certificate + * + * \return 0 on success + */ +MBEDTLS_DEPRECATED int mbedtls_pkcs11_priv_key_bind( + mbedtls_pkcs11_context *priv_key, + pkcs11h_certificate_t pkcs11_cert ); + +/** + * Free the contents of the given private key context. Note that the structure + * itself is not freed. + * + * \deprecated This function is deprecated and will be removed in a + * future version of the library. + * + * \param priv_key Private key structure to cleanup + */ +MBEDTLS_DEPRECATED void mbedtls_pkcs11_priv_key_free( + mbedtls_pkcs11_context *priv_key ); + +/** + * \brief Do an RSA private key decrypt, then remove the message + * padding + * + * \deprecated This function is deprecated and will be removed in a future + * version of the library. + * + * \param ctx PKCS #11 context + * \param mode must be MBEDTLS_RSA_PRIVATE, for compatibility with rsa.c's signature + * \param input buffer holding the encrypted data + * \param output buffer that will hold the plaintext + * \param olen will contain the plaintext length + * \param output_max_len maximum length of the output buffer + * + * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code + * + * \note The output buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise + * an error is thrown. + */ +MBEDTLS_DEPRECATED int mbedtls_pkcs11_decrypt( mbedtls_pkcs11_context *ctx, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ); + +/** + * \brief Do a private RSA to sign a message digest + * + * \deprecated This function is deprecated and will be removed in a future + * version of the library. + * + * \param ctx PKCS #11 context + * \param mode must be MBEDTLS_RSA_PRIVATE, for compatibility with rsa.c's signature + * \param md_alg a MBEDTLS_MD_XXX (use MBEDTLS_MD_NONE for signing raw data) + * \param hashlen message digest length (for MBEDTLS_MD_NONE only) + * \param hash buffer holding the message digest + * \param sig buffer that will hold the ciphertext + * + * \return 0 if the signing operation was successful, + * or an MBEDTLS_ERR_RSA_XXX error code + * + * \note The "sig" buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + */ +MBEDTLS_DEPRECATED int mbedtls_pkcs11_sign( mbedtls_pkcs11_context *ctx, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); + +/** + * SSL/TLS wrappers for PKCS#11 functions + * + * \deprecated This function is deprecated and will be removed in a future + * version of the library. + */ +MBEDTLS_DEPRECATED static inline int mbedtls_ssl_pkcs11_decrypt( void *ctx, + int mode, size_t *olen, + const unsigned char *input, unsigned char *output, + size_t output_max_len ) +{ + return mbedtls_pkcs11_decrypt( (mbedtls_pkcs11_context *) ctx, mode, olen, input, output, + output_max_len ); +} + +/** + * \brief This function signs a message digest using RSA. + * + * \deprecated This function is deprecated and will be removed in a future + * version of the library. + * + * \param ctx The PKCS #11 context. + * \param f_rng The RNG function. This parameter is unused. + * \param p_rng The RNG context. This parameter is unused. + * \param mode The operation to run. This must be set to + * MBEDTLS_RSA_PRIVATE, for compatibility with rsa.c's + * signature. + * \param md_alg The message digest algorithm. One of the MBEDTLS_MD_XXX + * must be passed to this function and MBEDTLS_MD_NONE can be + * used for signing raw data. + * \param hashlen The message digest length (for MBEDTLS_MD_NONE only). + * \param hash The buffer holding the message digest. + * \param sig The buffer that will hold the ciphertext. + * + * \return \c 0 if the signing operation was successful. + * \return A non-zero error code on failure. + * + * \note The \p sig buffer must be as large as the size of + * ctx->N. For example, 128 bytes if RSA-1024 is + * used. + */ +MBEDTLS_DEPRECATED static inline int mbedtls_ssl_pkcs11_sign( void *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + int mode, mbedtls_md_type_t md_alg, unsigned int hashlen, + const unsigned char *hash, unsigned char *sig ) +{ + ((void) f_rng); + ((void) p_rng); + return mbedtls_pkcs11_sign( (mbedtls_pkcs11_context *) ctx, mode, md_alg, + hashlen, hash, sig ); +} + +/** + * This function gets the length of the private key. + * + * \deprecated This function is deprecated and will be removed in a future + * version of the library. + * + * \param ctx The PKCS #11 context. + * + * \return The length of the private key. + */ +MBEDTLS_DEPRECATED static inline size_t mbedtls_ssl_pkcs11_key_len( void *ctx ) +{ + return ( (mbedtls_pkcs11_context *) ctx )->len; +} + +#undef MBEDTLS_DEPRECATED + +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_PKCS11_C */ + +#endif /* MBEDTLS_PKCS11_H */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/pkcs12.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/pkcs12.h new file mode 100644 index 0000000..4b8ce7e --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/pkcs12.h @@ -0,0 +1,128 @@ +/** + * \file pkcs12.h + * + * \brief PKCS#12 Personal Information Exchange Syntax + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_PKCS12_H +#define MBEDTLS_PKCS12_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/md.h" +#include "mbedtls/cipher.h" +#include "mbedtls/asn1.h" + +#include + +#define MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA -0x1F80 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE -0x1F00 /**< Feature not available, e.g. unsupported encryption scheme. */ +#define MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT -0x1E80 /**< PBE ASN.1 data not as expected. */ +#define MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH -0x1E00 /**< Given private key password does not allow for correct decryption. */ + +#define MBEDTLS_PKCS12_DERIVE_KEY 1 /**< encryption/decryption key */ +#define MBEDTLS_PKCS12_DERIVE_IV 2 /**< initialization vector */ +#define MBEDTLS_PKCS12_DERIVE_MAC_KEY 3 /**< integrity / MAC key */ + +#define MBEDTLS_PKCS12_PBE_DECRYPT 0 +#define MBEDTLS_PKCS12_PBE_ENCRYPT 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_ASN1_PARSE_C) + +/** + * \brief PKCS12 Password Based function (encryption / decryption) + * for pbeWithSHAAnd128BitRC4 + * + * \param pbe_params an ASN1 buffer containing the pkcs-12PbeParams structure + * \param mode either MBEDTLS_PKCS12_PBE_ENCRYPT or MBEDTLS_PKCS12_PBE_DECRYPT + * \param pwd the password used (may be NULL if no password is used) + * \param pwdlen length of the password (may be 0) + * \param input the input data + * \param len data length + * \param output the output buffer + * + * \return 0 if successful, or a MBEDTLS_ERR_XXX code + */ +int mbedtls_pkcs12_pbe_sha1_rc4_128( mbedtls_asn1_buf *pbe_params, int mode, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *input, size_t len, + unsigned char *output ); + +/** + * \brief PKCS12 Password Based function (encryption / decryption) + * for cipher-based and mbedtls_md-based PBE's + * + * \param pbe_params an ASN1 buffer containing the pkcs-12PbeParams structure + * \param mode either MBEDTLS_PKCS12_PBE_ENCRYPT or MBEDTLS_PKCS12_PBE_DECRYPT + * \param cipher_type the cipher used + * \param md_type the mbedtls_md used + * \param pwd the password used (may be NULL if no password is used) + * \param pwdlen length of the password (may be 0) + * \param input the input data + * \param len data length + * \param output the output buffer + * + * \return 0 if successful, or a MBEDTLS_ERR_XXX code + */ +int mbedtls_pkcs12_pbe( mbedtls_asn1_buf *pbe_params, int mode, + mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *input, size_t len, + unsigned char *output ); + +#endif /* MBEDTLS_ASN1_PARSE_C */ + +/** + * \brief The PKCS#12 derivation function uses a password and a salt + * to produce pseudo-random bits for a particular "purpose". + * + * Depending on the given id, this function can produce an + * encryption/decryption key, an nitialization vector or an + * integrity key. + * + * \param data buffer to store the derived data in + * \param datalen length to fill + * \param pwd password to use (may be NULL if no password is used) + * \param pwdlen length of the password (may be 0) + * \param salt salt buffer to use + * \param saltlen length of the salt + * \param mbedtls_md mbedtls_md type to use during the derivation + * \param id id that describes the purpose (can be MBEDTLS_PKCS12_DERIVE_KEY, + * MBEDTLS_PKCS12_DERIVE_IV or MBEDTLS_PKCS12_DERIVE_MAC_KEY) + * \param iterations number of iterations + * + * \return 0 if successful, or a MD, BIGNUM type error. + */ +int mbedtls_pkcs12_derivation( unsigned char *data, size_t datalen, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *salt, size_t saltlen, + mbedtls_md_type_t mbedtls_md, int id, int iterations ); + +#ifdef __cplusplus +} +#endif + +#endif /* pkcs12.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/pkcs5.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/pkcs5.h new file mode 100644 index 0000000..8f348ce --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/pkcs5.h @@ -0,0 +1,107 @@ +/** + * \file pkcs5.h + * + * \brief PKCS#5 functions + * + * \author Mathias Olsson + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_PKCS5_H +#define MBEDTLS_PKCS5_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/asn1.h" +#include "mbedtls/md.h" + +#include +#include + +#define MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA -0x2f80 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_PKCS5_INVALID_FORMAT -0x2f00 /**< Unexpected ASN.1 data. */ +#define MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE -0x2e80 /**< Requested encryption or digest alg not available. */ +#define MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH -0x2e00 /**< Given private key password does not allow for correct decryption. */ + +#define MBEDTLS_PKCS5_DECRYPT 0 +#define MBEDTLS_PKCS5_ENCRYPT 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_ASN1_PARSE_C) + +/** + * \brief PKCS#5 PBES2 function + * + * \param pbe_params the ASN.1 algorithm parameters + * \param mode either MBEDTLS_PKCS5_DECRYPT or MBEDTLS_PKCS5_ENCRYPT + * \param pwd password to use when generating key + * \param pwdlen length of password + * \param data data to process + * \param datalen length of data + * \param output output buffer + * + * \returns 0 on success, or a MBEDTLS_ERR_XXX code if verification fails. + */ +int mbedtls_pkcs5_pbes2( const mbedtls_asn1_buf *pbe_params, int mode, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *data, size_t datalen, + unsigned char *output ); + +#endif /* MBEDTLS_ASN1_PARSE_C */ + +/** + * \brief PKCS#5 PBKDF2 using HMAC + * + * \param ctx Generic HMAC context + * \param password Password to use when generating key + * \param plen Length of password + * \param salt Salt to use when generating key + * \param slen Length of salt + * \param iteration_count Iteration count + * \param key_length Length of generated key in bytes + * \param output Generated key. Must be at least as big as key_length + * + * \returns 0 on success, or a MBEDTLS_ERR_XXX code if verification fails. + */ +int mbedtls_pkcs5_pbkdf2_hmac( mbedtls_md_context_t *ctx, const unsigned char *password, + size_t plen, const unsigned char *salt, size_t slen, + unsigned int iteration_count, + uint32_t key_length, unsigned char *output ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_pkcs5_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* pkcs5.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/platform.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/platform.h new file mode 100644 index 0000000..fde5ee8 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/platform.h @@ -0,0 +1,417 @@ +/** + * \file platform.h + * + * \brief This file contains the definitions and functions of the + * Mbed TLS platform abstraction layer. + * + * The platform abstraction layer removes the need for the library + * to directly link to standard C library functions or operating + * system services, making the library easier to port and embed. + * Application developers and users of the library can provide their own + * implementations of these functions, or implementations specific to + * their platform, which can be statically linked to the library or + * dynamically configured at runtime. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_PLATFORM_H +#define MBEDTLS_PLATFORM_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_HAVE_TIME) +#include "mbedtls/platform_time.h" +#endif + +#define MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED -0x0070 /**< Hardware accelerator failed */ +#define MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED -0x0072 /**< The requested feature is not supported by the platform */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +/* The older Microsoft Windows common runtime provides non-conforming + * implementations of some standard library functions, including snprintf + * and vsnprintf. This affects MSVC and MinGW builds. + */ +#if defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER <= 1900) +#define MBEDTLS_PLATFORM_HAS_NON_CONFORMING_SNPRINTF +#define MBEDTLS_PLATFORM_HAS_NON_CONFORMING_VSNPRINTF +#endif + +#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) +#include +#include +#include +#if !defined(MBEDTLS_PLATFORM_STD_SNPRINTF) +#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_SNPRINTF) +#define MBEDTLS_PLATFORM_STD_SNPRINTF mbedtls_platform_win32_snprintf /**< The default \c snprintf function to use. */ +#else +#define MBEDTLS_PLATFORM_STD_SNPRINTF snprintf /**< The default \c snprintf function to use. */ +#endif +#endif +#if !defined(MBEDTLS_PLATFORM_STD_VSNPRINTF) +#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_VSNPRINTF) +#define MBEDTLS_PLATFORM_STD_VSNPRINTF mbedtls_platform_win32_vsnprintf /**< The default \c vsnprintf function to use. */ +#else +#define MBEDTLS_PLATFORM_STD_VSNPRINTF vsnprintf /**< The default \c vsnprintf function to use. */ +#endif +#endif +#if !defined(MBEDTLS_PLATFORM_STD_PRINTF) +#define MBEDTLS_PLATFORM_STD_PRINTF printf /**< The default \c printf function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_FPRINTF) +#define MBEDTLS_PLATFORM_STD_FPRINTF fprintf /**< The default \c fprintf function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_CALLOC) +#define MBEDTLS_PLATFORM_STD_CALLOC calloc /**< The default \c calloc function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_FREE) +#define MBEDTLS_PLATFORM_STD_FREE free /**< The default \c free function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_EXIT) +#define MBEDTLS_PLATFORM_STD_EXIT exit /**< The default \c exit function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_TIME) +#define MBEDTLS_PLATFORM_STD_TIME time /**< The default \c time function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_EXIT_SUCCESS) +#define MBEDTLS_PLATFORM_STD_EXIT_SUCCESS EXIT_SUCCESS /**< The default exit value to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_EXIT_FAILURE) +#define MBEDTLS_PLATFORM_STD_EXIT_FAILURE EXIT_FAILURE /**< The default exit value to use. */ +#endif +#if defined(MBEDTLS_FS_IO) +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) +#define MBEDTLS_PLATFORM_STD_NV_SEED_READ mbedtls_platform_std_nv_seed_read +#endif +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) +#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE mbedtls_platform_std_nv_seed_write +#endif +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_FILE) +#define MBEDTLS_PLATFORM_STD_NV_SEED_FILE "seedfile" +#endif +#endif /* MBEDTLS_FS_IO */ +#else /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ +#if defined(MBEDTLS_PLATFORM_STD_MEM_HDR) +#include MBEDTLS_PLATFORM_STD_MEM_HDR +#endif +#endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ + + +/* \} name SECTION: Module settings */ + +/* + * The function pointers for calloc and free. + */ +#if defined(MBEDTLS_PLATFORM_MEMORY) +#if defined(MBEDTLS_PLATFORM_FREE_MACRO) && \ + defined(MBEDTLS_PLATFORM_CALLOC_MACRO) +#define mbedtls_free MBEDTLS_PLATFORM_FREE_MACRO +#define mbedtls_calloc MBEDTLS_PLATFORM_CALLOC_MACRO +#else +/* For size_t */ +#include +extern void *mbedtls_calloc( size_t n, size_t size ); +extern void mbedtls_free( void *ptr ); + +/** + * \brief This function dynamically sets the memory-management + * functions used by the library, during runtime. + * + * \param calloc_func The \c calloc function implementation. + * \param free_func The \c free function implementation. + * + * \return \c 0. + */ +int mbedtls_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ), + void (*free_func)( void * ) ); +#endif /* MBEDTLS_PLATFORM_FREE_MACRO && MBEDTLS_PLATFORM_CALLOC_MACRO */ +#else /* !MBEDTLS_PLATFORM_MEMORY */ +#define mbedtls_free free +#define mbedtls_calloc calloc +#endif /* MBEDTLS_PLATFORM_MEMORY && !MBEDTLS_PLATFORM_{FREE,CALLOC}_MACRO */ + +/* + * The function pointers for fprintf + */ +#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) +/* We need FILE * */ +#include +extern int (*mbedtls_fprintf)( FILE *stream, const char *format, ... ); + +/** + * \brief This function dynamically configures the fprintf + * function that is called when the + * mbedtls_fprintf() function is invoked by the library. + * + * \param fprintf_func The \c fprintf function implementation. + * + * \return \c 0. + */ +int mbedtls_platform_set_fprintf( int (*fprintf_func)( FILE *stream, const char *, + ... ) ); +#else +#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) +#define mbedtls_fprintf MBEDTLS_PLATFORM_FPRINTF_MACRO +#else +#define mbedtls_fprintf fprintf +#endif /* MBEDTLS_PLATFORM_FPRINTF_MACRO */ +#endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */ + +/* + * The function pointers for printf + */ +#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) +extern int (*mbedtls_printf)( const char *format, ... ); + +/** + * \brief This function dynamically configures the snprintf + * function that is called when the mbedtls_snprintf() + * function is invoked by the library. + * + * \param printf_func The \c printf function implementation. + * + * \return \c 0 on success. + */ +int mbedtls_platform_set_printf( int (*printf_func)( const char *, ... ) ); +#else /* !MBEDTLS_PLATFORM_PRINTF_ALT */ +#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) +#define mbedtls_printf MBEDTLS_PLATFORM_PRINTF_MACRO +#else +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_PRINTF_MACRO */ +#endif /* MBEDTLS_PLATFORM_PRINTF_ALT */ + +/* + * The function pointers for snprintf + * + * The snprintf implementation should conform to C99: + * - it *must* always correctly zero-terminate the buffer + * (except when n == 0, then it must leave the buffer untouched) + * - however it is acceptable to return -1 instead of the required length when + * the destination buffer is too short. + */ +#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_SNPRINTF) +/* For Windows (inc. MSYS2), we provide our own fixed implementation */ +int mbedtls_platform_win32_snprintf( char *s, size_t n, const char *fmt, ... ); +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) +extern int (*mbedtls_snprintf)( char * s, size_t n, const char * format, ... ); + +/** + * \brief This function allows configuring a custom + * \c snprintf function pointer. + * + * \param snprintf_func The \c snprintf function implementation. + * + * \return \c 0 on success. + */ +int mbedtls_platform_set_snprintf( int (*snprintf_func)( char * s, size_t n, + const char * format, ... ) ); +#else /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ +#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) +#define mbedtls_snprintf MBEDTLS_PLATFORM_SNPRINTF_MACRO +#else +#define mbedtls_snprintf MBEDTLS_PLATFORM_STD_SNPRINTF +#endif /* MBEDTLS_PLATFORM_SNPRINTF_MACRO */ +#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ + +/* + * The function pointers for vsnprintf + * + * The vsnprintf implementation should conform to C99: + * - it *must* always correctly zero-terminate the buffer + * (except when n == 0, then it must leave the buffer untouched) + * - however it is acceptable to return -1 instead of the required length when + * the destination buffer is too short. + */ +#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_VSNPRINTF) +#include +/* For Older Windows (inc. MSYS2), we provide our own fixed implementation */ +int mbedtls_platform_win32_vsnprintf( char *s, size_t n, const char *fmt, va_list arg ); +#endif + +#if defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT) +#include +extern int (*mbedtls_vsnprintf)( char * s, size_t n, const char * format, va_list arg ); + +/** + * \brief Set your own snprintf function pointer + * + * \param vsnprintf_func The \c vsnprintf function implementation + * + * \return \c 0 + */ +int mbedtls_platform_set_vsnprintf( int (*vsnprintf_func)( char * s, size_t n, + const char * format, va_list arg ) ); +#else /* MBEDTLS_PLATFORM_VSNPRINTF_ALT */ +#if defined(MBEDTLS_PLATFORM_VSNPRINTF_MACRO) +#define mbedtls_vsnprintf MBEDTLS_PLATFORM_VSNPRINTF_MACRO +#else +#define mbedtls_vsnprintf vsnprintf +#endif /* MBEDTLS_PLATFORM_VSNPRINTF_MACRO */ +#endif /* MBEDTLS_PLATFORM_VSNPRINTF_ALT */ + +/* + * The function pointers for exit + */ +#if defined(MBEDTLS_PLATFORM_EXIT_ALT) +extern void (*mbedtls_exit)( int status ); + +/** + * \brief This function dynamically configures the exit + * function that is called when the mbedtls_exit() + * function is invoked by the library. + * + * \param exit_func The \c exit function implementation. + * + * \return \c 0 on success. + */ +int mbedtls_platform_set_exit( void (*exit_func)( int status ) ); +#else +#if defined(MBEDTLS_PLATFORM_EXIT_MACRO) +#define mbedtls_exit MBEDTLS_PLATFORM_EXIT_MACRO +#else +#define mbedtls_exit exit +#endif /* MBEDTLS_PLATFORM_EXIT_MACRO */ +#endif /* MBEDTLS_PLATFORM_EXIT_ALT */ + +/* + * The default exit values + */ +#if defined(MBEDTLS_PLATFORM_STD_EXIT_SUCCESS) +#define MBEDTLS_EXIT_SUCCESS MBEDTLS_PLATFORM_STD_EXIT_SUCCESS +#else +#define MBEDTLS_EXIT_SUCCESS 0 +#endif +#if defined(MBEDTLS_PLATFORM_STD_EXIT_FAILURE) +#define MBEDTLS_EXIT_FAILURE MBEDTLS_PLATFORM_STD_EXIT_FAILURE +#else +#define MBEDTLS_EXIT_FAILURE 1 +#endif + +/* + * The function pointers for reading from and writing a seed file to + * Non-Volatile storage (NV) in a platform-independent way + * + * Only enabled when the NV seed entropy source is enabled + */ +#if defined(MBEDTLS_ENTROPY_NV_SEED) +#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) && defined(MBEDTLS_FS_IO) +/* Internal standard platform definitions */ +int mbedtls_platform_std_nv_seed_read( unsigned char *buf, size_t buf_len ); +int mbedtls_platform_std_nv_seed_write( unsigned char *buf, size_t buf_len ); +#endif + +#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) +extern int (*mbedtls_nv_seed_read)( unsigned char *buf, size_t buf_len ); +extern int (*mbedtls_nv_seed_write)( unsigned char *buf, size_t buf_len ); + +/** + * \brief This function allows configuring custom seed file writing and + * reading functions. + * + * \param nv_seed_read_func The seed reading function implementation. + * \param nv_seed_write_func The seed writing function implementation. + * + * \return \c 0 on success. + */ +int mbedtls_platform_set_nv_seed( + int (*nv_seed_read_func)( unsigned char *buf, size_t buf_len ), + int (*nv_seed_write_func)( unsigned char *buf, size_t buf_len ) + ); +#else +#if defined(MBEDTLS_PLATFORM_NV_SEED_READ_MACRO) && \ + defined(MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO) +#define mbedtls_nv_seed_read MBEDTLS_PLATFORM_NV_SEED_READ_MACRO +#define mbedtls_nv_seed_write MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO +#else +#define mbedtls_nv_seed_read mbedtls_platform_std_nv_seed_read +#define mbedtls_nv_seed_write mbedtls_platform_std_nv_seed_write +#endif +#endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */ +#endif /* MBEDTLS_ENTROPY_NV_SEED */ + +#if !defined(MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT) + +/** + * \brief The platform context structure. + * + * \note This structure may be used to assist platform-specific + * setup or teardown operations. + */ +typedef struct mbedtls_platform_context +{ + char dummy; /**< A placeholder member, as empty structs are not portable. */ +} +mbedtls_platform_context; + +#else +#include "platform_alt.h" +#endif /* !MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT */ + +/** + * \brief This function performs any platform-specific initialization + * operations. + * + * \note This function should be called before any other library functions. + * + * Its implementation is platform-specific, and unless + * platform-specific code is provided, it does nothing. + * + * \note The usage and necessity of this function is dependent on the platform. + * + * \param ctx The platform context. + * + * \return \c 0 on success. + */ +int mbedtls_platform_setup( mbedtls_platform_context *ctx ); +/** + * \brief This function performs any platform teardown operations. + * + * \note This function should be called after every other Mbed TLS module + * has been correctly freed using the appropriate free function. + * + * Its implementation is platform-specific, and unless + * platform-specific code is provided, it does nothing. + * + * \note The usage and necessity of this function is dependent on the platform. + * + * \param ctx The platform context. + * + */ +void mbedtls_platform_teardown( mbedtls_platform_context *ctx ); + +#ifdef __cplusplus +} +#endif + +#endif /* platform.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/platform_time.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/platform_time.h new file mode 100644 index 0000000..7e7daab --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/platform_time.h @@ -0,0 +1,80 @@ +/** + * \file platform_time.h + * + * \brief mbed TLS Platform time abstraction + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_PLATFORM_TIME_H +#define MBEDTLS_PLATFORM_TIME_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +/* + * The time_t datatype + */ +#if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) +typedef MBEDTLS_PLATFORM_TIME_TYPE_MACRO mbedtls_time_t; +#else +/* For time_t */ +#include +typedef time_t mbedtls_time_t; +#endif /* MBEDTLS_PLATFORM_TIME_TYPE_MACRO */ + +/* + * The function pointers for time + */ +#if defined(MBEDTLS_PLATFORM_TIME_ALT) +extern mbedtls_time_t (*mbedtls_time)( mbedtls_time_t* time ); + +/** + * \brief Set your own time function pointer + * + * \param time_func the time function implementation + * + * \return 0 + */ +int mbedtls_platform_set_time( mbedtls_time_t (*time_func)( mbedtls_time_t* time ) ); +#else +#if defined(MBEDTLS_PLATFORM_TIME_MACRO) +#define mbedtls_time MBEDTLS_PLATFORM_TIME_MACRO +#else +#define mbedtls_time time +#endif /* MBEDTLS_PLATFORM_TIME_MACRO */ +#endif /* MBEDTLS_PLATFORM_TIME_ALT */ + +#ifdef __cplusplus +} +#endif + +#endif /* platform_time.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/platform_util.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/platform_util.h new file mode 100644 index 0000000..fbc2a0d --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/platform_util.h @@ -0,0 +1,194 @@ +/** + * \file platform_util.h + * + * \brief Common and shared functions used by multiple modules in the Mbed TLS + * library. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_PLATFORM_UTIL_H +#define MBEDTLS_PLATFORM_UTIL_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#if defined(MBEDTLS_HAVE_TIME_DATE) +#include "mbedtls/platform_time.h" +#include +#endif /* MBEDTLS_HAVE_TIME_DATE */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_CHECK_PARAMS) + +#if defined(MBEDTLS_CHECK_PARAMS_ASSERT) +/* Allow the user to define MBEDTLS_PARAM_FAILED to something like assert + * (which is what our config.h suggests). */ +#include +#endif /* MBEDTLS_CHECK_PARAMS_ASSERT */ + +#if defined(MBEDTLS_PARAM_FAILED) +/** An alternative definition of MBEDTLS_PARAM_FAILED has been set in config.h. + * + * This flag can be used to check whether it is safe to assume that + * MBEDTLS_PARAM_FAILED() will expand to a call to mbedtls_param_failed(). + */ +#define MBEDTLS_PARAM_FAILED_ALT + +#elif defined(MBEDTLS_CHECK_PARAMS_ASSERT) +#define MBEDTLS_PARAM_FAILED( cond ) assert( cond ) +#define MBEDTLS_PARAM_FAILED_ALT + +#else /* MBEDTLS_PARAM_FAILED */ +#define MBEDTLS_PARAM_FAILED( cond ) \ + mbedtls_param_failed( #cond, __FILE__, __LINE__ ) + +/** + * \brief User supplied callback function for parameter validation failure. + * See #MBEDTLS_CHECK_PARAMS for context. + * + * This function will be called unless an alternative treatement + * is defined through the #MBEDTLS_PARAM_FAILED macro. + * + * This function can return, and the operation will be aborted, or + * alternatively, through use of setjmp()/longjmp() can resume + * execution in the application code. + * + * \param failure_condition The assertion that didn't hold. + * \param file The file where the assertion failed. + * \param line The line in the file where the assertion failed. + */ +void mbedtls_param_failed( const char *failure_condition, + const char *file, + int line ); +#endif /* MBEDTLS_PARAM_FAILED */ + +/* Internal macro meant to be called only from within the library. */ +#define MBEDTLS_INTERNAL_VALIDATE_RET( cond, ret ) \ + do { \ + if( !(cond) ) \ + { \ + MBEDTLS_PARAM_FAILED( cond ); \ + return( ret ); \ + } \ + } while( 0 ) + +/* Internal macro meant to be called only from within the library. */ +#define MBEDTLS_INTERNAL_VALIDATE( cond ) \ + do { \ + if( !(cond) ) \ + { \ + MBEDTLS_PARAM_FAILED( cond ); \ + return; \ + } \ + } while( 0 ) + +#else /* MBEDTLS_CHECK_PARAMS */ + +/* Internal macros meant to be called only from within the library. */ +#define MBEDTLS_INTERNAL_VALIDATE_RET( cond, ret ) do { } while( 0 ) +#define MBEDTLS_INTERNAL_VALIDATE( cond ) do { } while( 0 ) + +#endif /* MBEDTLS_CHECK_PARAMS */ + +/* Internal helper macros for deprecating API constants. */ +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +/* Deliberately don't (yet) export MBEDTLS_DEPRECATED here + * to avoid conflict with other headers which define and use + * it, too. We might want to move all these definitions here at + * some point for uniformity. */ +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +MBEDTLS_DEPRECATED typedef char const * mbedtls_deprecated_string_constant_t; +#define MBEDTLS_DEPRECATED_STRING_CONSTANT( VAL ) \ + ( (mbedtls_deprecated_string_constant_t) ( VAL ) ) +MBEDTLS_DEPRECATED typedef int mbedtls_deprecated_numeric_constant_t; +#define MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( VAL ) \ + ( (mbedtls_deprecated_numeric_constant_t) ( VAL ) ) +#undef MBEDTLS_DEPRECATED +#else /* MBEDTLS_DEPRECATED_WARNING */ +#define MBEDTLS_DEPRECATED_STRING_CONSTANT( VAL ) VAL +#define MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( VAL ) VAL +#endif /* MBEDTLS_DEPRECATED_WARNING */ +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Securely zeroize a buffer + * + * The function is meant to wipe the data contained in a buffer so + * that it can no longer be recovered even if the program memory + * is later compromised. Call this function on sensitive data + * stored on the stack before returning from a function, and on + * sensitive data stored on the heap before freeing the heap + * object. + * + * It is extremely difficult to guarantee that calls to + * mbedtls_platform_zeroize() are not removed by aggressive + * compiler optimizations in a portable way. For this reason, Mbed + * TLS provides the configuration option + * MBEDTLS_PLATFORM_ZEROIZE_ALT, which allows users to configure + * mbedtls_platform_zeroize() to use a suitable implementation for + * their platform and needs + * + * \param buf Buffer to be zeroized + * \param len Length of the buffer in bytes + * + */ +void mbedtls_platform_zeroize( void *buf, size_t len ); + +#if defined(MBEDTLS_HAVE_TIME_DATE) +/** + * \brief Platform-specific implementation of gmtime_r() + * + * The function is a thread-safe abstraction that behaves + * similarly to the gmtime_r() function from Unix/POSIX. + * + * Mbed TLS will try to identify the underlying platform and + * make use of an appropriate underlying implementation (e.g. + * gmtime_r() for POSIX and gmtime_s() for Windows). If this is + * not possible, then gmtime() will be used. In this case, calls + * from the library to gmtime() will be guarded by the mutex + * mbedtls_threading_gmtime_mutex if MBEDTLS_THREADING_C is + * enabled. It is recommended that calls from outside the library + * are also guarded by this mutex. + * + * If MBEDTLS_PLATFORM_GMTIME_R_ALT is defined, then Mbed TLS will + * unconditionally use the alternative implementation for + * mbedtls_platform_gmtime_r() supplied by the user at compile time. + * + * \param tt Pointer to an object containing time (in seconds) since the + * epoch to be converted + * \param tm_buf Pointer to an object where the results will be stored + * + * \return Pointer to an object of type struct tm on success, otherwise + * NULL + */ +struct tm *mbedtls_platform_gmtime_r( const mbedtls_time_t *tt, + struct tm *tm_buf ); +#endif /* MBEDTLS_HAVE_TIME_DATE */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_PLATFORM_UTIL_H */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/poly1305.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/poly1305.h new file mode 100644 index 0000000..905c145 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/poly1305.h @@ -0,0 +1,191 @@ +/** + * \file poly1305.h + * + * \brief This file contains Poly1305 definitions and functions. + * + * Poly1305 is a one-time message authenticator that can be used to + * authenticate messages. Poly1305-AES was created by Daniel + * Bernstein https://cr.yp.to/mac/poly1305-20050329.pdf The generic + * Poly1305 algorithm (not tied to AES) was also standardized in RFC + * 7539. + * + * \author Daniel King + */ + +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_POLY1305_H +#define MBEDTLS_POLY1305_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#define MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA -0x0057 /**< Invalid input parameter(s). */ + +/* MBEDTLS_ERR_POLY1305_FEATURE_UNAVAILABLE is deprecated and should not be + * used. */ +#define MBEDTLS_ERR_POLY1305_FEATURE_UNAVAILABLE -0x0059 /**< Feature not available. For example, s part of the API is not implemented. */ + +/* MBEDTLS_ERR_POLY1305_HW_ACCEL_FAILED is deprecated and should not be used. + */ +#define MBEDTLS_ERR_POLY1305_HW_ACCEL_FAILED -0x005B /**< Poly1305 hardware accelerator failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_POLY1305_ALT) + +typedef struct mbedtls_poly1305_context +{ + uint32_t r[4]; /** The value for 'r' (low 128 bits of the key). */ + uint32_t s[4]; /** The value for 's' (high 128 bits of the key). */ + uint32_t acc[5]; /** The accumulator number. */ + uint8_t queue[16]; /** The current partial block of data. */ + size_t queue_len; /** The number of bytes stored in 'queue'. */ +} +mbedtls_poly1305_context; + +#else /* MBEDTLS_POLY1305_ALT */ +#include "poly1305_alt.h" +#endif /* MBEDTLS_POLY1305_ALT */ + +/** + * \brief This function initializes the specified Poly1305 context. + * + * It must be the first API called before using + * the context. + * + * It is usually followed by a call to + * \c mbedtls_poly1305_starts(), then one or more calls to + * \c mbedtls_poly1305_update(), then one call to + * \c mbedtls_poly1305_finish(), then finally + * \c mbedtls_poly1305_free(). + * + * \param ctx The Poly1305 context to initialize. This must + * not be \c NULL. + */ +void mbedtls_poly1305_init( mbedtls_poly1305_context *ctx ); + +/** + * \brief This function releases and clears the specified + * Poly1305 context. + * + * \param ctx The Poly1305 context to clear. This may be \c NULL, in which + * case this function is a no-op. If it is not \c NULL, it must + * point to an initialized Poly1305 context. + */ +void mbedtls_poly1305_free( mbedtls_poly1305_context *ctx ); + +/** + * \brief This function sets the one-time authentication key. + * + * \warning The key must be unique and unpredictable for each + * invocation of Poly1305. + * + * \param ctx The Poly1305 context to which the key should be bound. + * This must be initialized. + * \param key The buffer containing the \c 32 Byte (\c 256 Bit) key. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_poly1305_starts( mbedtls_poly1305_context *ctx, + const unsigned char key[32] ); + +/** + * \brief This functions feeds an input buffer into an ongoing + * Poly1305 computation. + * + * It is called between \c mbedtls_cipher_poly1305_starts() and + * \c mbedtls_cipher_poly1305_finish(). + * It can be called repeatedly to process a stream of data. + * + * \param ctx The Poly1305 context to use for the Poly1305 operation. + * This must be initialized and bound to a key. + * \param ilen The length of the input data in Bytes. + * Any value is accepted. + * \param input The buffer holding the input data. + * This pointer can be \c NULL if `ilen == 0`. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_poly1305_update( mbedtls_poly1305_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function generates the Poly1305 Message + * Authentication Code (MAC). + * + * \param ctx The Poly1305 context to use for the Poly1305 operation. + * This must be initialized and bound to a key. + * \param mac The buffer to where the MAC is written. This must + * be a writable buffer of length \c 16 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_poly1305_finish( mbedtls_poly1305_context *ctx, + unsigned char mac[16] ); + +/** + * \brief This function calculates the Poly1305 MAC of the input + * buffer with the provided key. + * + * \warning The key must be unique and unpredictable for each + * invocation of Poly1305. + * + * \param key The buffer containing the \c 32 Byte (\c 256 Bit) key. + * \param ilen The length of the input data in Bytes. + * Any value is accepted. + * \param input The buffer holding the input data. + * This pointer can be \c NULL if `ilen == 0`. + * \param mac The buffer to where the MAC is written. This must be + * a writable buffer of length \c 16 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_poly1305_mac( const unsigned char key[32], + const unsigned char *input, + size_t ilen, + unsigned char mac[16] ); + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief The Poly1305 checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_poly1305_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_POLY1305_H */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/psa_util.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/psa_util.h new file mode 100644 index 0000000..d8a32c5 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/psa_util.h @@ -0,0 +1,422 @@ +/** + * \file psa_util.h + * + * \brief Utility functions for the use of the PSA Crypto library. + * + * \warning This function is not part of the public API and may + * change at any time. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_PSA_UTIL_H +#define MBEDTLS_PSA_UTIL_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + +#include "psa/crypto.h" + +#include "mbedtls/ecp.h" +#include "mbedtls/md.h" +#include "mbedtls/pk.h" +#include "mbedtls/oid.h" + +#include + +/* Translations for symmetric crypto. */ + +static inline psa_key_type_t mbedtls_psa_translate_cipher_type( + mbedtls_cipher_type_t cipher ) +{ + switch( cipher ) + { + case MBEDTLS_CIPHER_AES_128_CCM: + case MBEDTLS_CIPHER_AES_192_CCM: + case MBEDTLS_CIPHER_AES_256_CCM: + case MBEDTLS_CIPHER_AES_128_GCM: + case MBEDTLS_CIPHER_AES_192_GCM: + case MBEDTLS_CIPHER_AES_256_GCM: + case MBEDTLS_CIPHER_AES_128_CBC: + case MBEDTLS_CIPHER_AES_192_CBC: + case MBEDTLS_CIPHER_AES_256_CBC: + return( PSA_KEY_TYPE_AES ); + + /* ARIA not yet supported in PSA. */ + /* case MBEDTLS_CIPHER_ARIA_128_CCM: + case MBEDTLS_CIPHER_ARIA_192_CCM: + case MBEDTLS_CIPHER_ARIA_256_CCM: + case MBEDTLS_CIPHER_ARIA_128_GCM: + case MBEDTLS_CIPHER_ARIA_192_GCM: + case MBEDTLS_CIPHER_ARIA_256_GCM: + case MBEDTLS_CIPHER_ARIA_128_CBC: + case MBEDTLS_CIPHER_ARIA_192_CBC: + case MBEDTLS_CIPHER_ARIA_256_CBC: + return( PSA_KEY_TYPE_ARIA ); */ + + default: + return( 0 ); + } +} + +static inline psa_algorithm_t mbedtls_psa_translate_cipher_mode( + mbedtls_cipher_mode_t mode, size_t taglen ) +{ + switch( mode ) + { + case MBEDTLS_MODE_ECB: + return( PSA_ALG_ECB_NO_PADDING ); + case MBEDTLS_MODE_GCM: + return( PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_GCM, taglen ) ); + case MBEDTLS_MODE_CCM: + return( PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_CCM, taglen ) ); + case MBEDTLS_MODE_CBC: + if( taglen == 0 ) + return( PSA_ALG_CBC_NO_PADDING ); + /* Intentional fallthrough for taglen != 0 */ + /* fallthrough */ + default: + return( 0 ); + } +} + +static inline psa_key_usage_t mbedtls_psa_translate_cipher_operation( + mbedtls_operation_t op ) +{ + switch( op ) + { + case MBEDTLS_ENCRYPT: + return( PSA_KEY_USAGE_ENCRYPT ); + case MBEDTLS_DECRYPT: + return( PSA_KEY_USAGE_DECRYPT ); + default: + return( 0 ); + } +} + +/* Translations for hashing. */ + +static inline psa_algorithm_t mbedtls_psa_translate_md( mbedtls_md_type_t md_alg ) +{ + switch( md_alg ) + { +#if defined(MBEDTLS_MD2_C) + case MBEDTLS_MD_MD2: + return( PSA_ALG_MD2 ); +#endif +#if defined(MBEDTLS_MD4_C) + case MBEDTLS_MD_MD4: + return( PSA_ALG_MD4 ); +#endif +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return( PSA_ALG_MD5 ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return( PSA_ALG_SHA_1 ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA224: + return( PSA_ALG_SHA_224 ); + case MBEDTLS_MD_SHA256: + return( PSA_ALG_SHA_256 ); +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_MD_SHA384: + return( PSA_ALG_SHA_384 ); + case MBEDTLS_MD_SHA512: + return( PSA_ALG_SHA_512 ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + return( PSA_ALG_RIPEMD160 ); +#endif + case MBEDTLS_MD_NONE: /* Intentional fallthrough */ + default: + return( 0 ); + } +} + +/* Translations for ECC. */ + +static inline int mbedtls_psa_get_ecc_oid_from_id( + psa_ecc_family_t curve, size_t bits, + char const **oid, size_t *oid_len ) +{ + switch( curve ) + { + case PSA_ECC_FAMILY_SECP_R1: + switch( bits ) + { +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + case 192: + *oid = MBEDTLS_OID_EC_GRP_SECP192R1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP192R1 ); + return( 0 ); +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) + case 224: + *oid = MBEDTLS_OID_EC_GRP_SECP224R1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP224R1 ); + return( 0 ); +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + case 256: + *oid = MBEDTLS_OID_EC_GRP_SECP256R1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP256R1 ); + return( 0 ); +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + case 384: + *oid = MBEDTLS_OID_EC_GRP_SECP384R1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP384R1 ); + return( 0 ); +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) + case 521: + *oid = MBEDTLS_OID_EC_GRP_SECP521R1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP521R1 ); + return( 0 ); +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ + } + break; + case PSA_ECC_FAMILY_SECP_K1: + switch( bits ) + { +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) + case 192: + *oid = MBEDTLS_OID_EC_GRP_SECP192K1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP192K1 ); + return( 0 ); +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) + case 224: + *oid = MBEDTLS_OID_EC_GRP_SECP224K1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP224K1 ); + return( 0 ); +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) + case 256: + *oid = MBEDTLS_OID_EC_GRP_SECP256K1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP256K1 ); + return( 0 ); +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ + } + break; + case PSA_ECC_FAMILY_BRAINPOOL_P_R1: + switch( bits ) + { +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) + case 256: + *oid = MBEDTLS_OID_EC_GRP_BP256R1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_BP256R1 ); + return( 0 ); +#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) + case 384: + *oid = MBEDTLS_OID_EC_GRP_BP384R1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_BP384R1 ); + return( 0 ); +#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) + case 512: + *oid = MBEDTLS_OID_EC_GRP_BP512R1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_BP512R1 ); + return( 0 ); +#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ + } + break; + } + (void) oid; + (void) oid_len; + return( -1 ); +} + +#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH 1 + +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) +#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 192 + 7 ) / 8 ) + 1 ) +#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH +#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 192 + 7 ) / 8 ) + 1 ) +#endif +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) +#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 224 + 7 ) / 8 ) + 1 ) +#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH +#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 224 + 7 ) / 8 ) + 1 ) +#endif +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) +#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 256 + 7 ) / 8 ) + 1 ) +#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH +#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 256 + 7 ) / 8 ) + 1 ) +#endif +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 384 + 7 ) / 8 ) + 1 ) +#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH +#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 384 + 7 ) / 8 ) + 1 ) +#endif +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) +#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 521 + 7 ) / 8 ) + 1 ) +#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH +#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 521 + 7 ) / 8 ) + 1 ) +#endif +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) +#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 192 + 7 ) / 8 ) + 1 ) +#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH +#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 192 + 7 ) / 8 ) + 1 ) +#endif +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) +#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 224 + 7 ) / 8 ) + 1 ) +#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH +#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 224 + 7 ) / 8 ) + 1 ) +#endif +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 256 + 7 ) / 8 ) + 1 ) +#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH +#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 256 + 7 ) / 8 ) + 1 ) +#endif +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) +#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 256 + 7 ) / 8 ) + 1 ) +#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH +#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 256 + 7 ) / 8 ) + 1 ) +#endif +#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) +#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 384 + 7 ) / 8 ) + 1 ) +#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH +#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 384 + 7 ) / 8 ) + 1 ) +#endif +#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) +#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 512 + 7 ) / 8 ) + 1 ) +#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH +#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 512 + 7 ) / 8 ) + 1 ) +#endif +#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ + + +/* Translations for PK layer */ + +static inline int mbedtls_psa_err_translate_pk( psa_status_t status ) +{ + switch( status ) + { + case PSA_SUCCESS: + return( 0 ); + case PSA_ERROR_NOT_SUPPORTED: + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + case PSA_ERROR_INSUFFICIENT_MEMORY: + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + case PSA_ERROR_INSUFFICIENT_ENTROPY: + return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); + case PSA_ERROR_BAD_STATE: + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + /* All other failures */ + case PSA_ERROR_COMMUNICATION_FAILURE: + case PSA_ERROR_HARDWARE_FAILURE: + case PSA_ERROR_CORRUPTION_DETECTED: + return( MBEDTLS_ERR_PK_HW_ACCEL_FAILED ); + default: /* We return the same as for the 'other failures', + * but list them separately nonetheless to indicate + * which failure conditions we have considered. */ + return( MBEDTLS_ERR_PK_HW_ACCEL_FAILED ); + } +} + +/* Translations for ECC */ + +/* This function transforms an ECC group identifier from + * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 + * into a PSA ECC group identifier. */ +#if defined(MBEDTLS_ECP_C) +static inline psa_key_type_t mbedtls_psa_parse_tls_ecc_group( + uint16_t tls_ecc_grp_reg_id, size_t *bits ) +{ + const mbedtls_ecp_curve_info *curve_info = + mbedtls_ecp_curve_info_from_tls_id( tls_ecc_grp_reg_id ); + if( curve_info == NULL ) + return( 0 ); + return( PSA_KEY_TYPE_ECC_KEY_PAIR( + mbedtls_ecc_group_to_psa( curve_info->grp_id, bits ) ) ); +} +#endif /* MBEDTLS_ECP_C */ + +/* This function takes a buffer holding an EC public key + * exported through psa_export_public_key(), and converts + * it into an ECPoint structure to be put into a ClientKeyExchange + * message in an ECDHE exchange. + * + * Both the present and the foreseeable future format of EC public keys + * used by PSA have the ECPoint structure contained in the exported key + * as a subbuffer, and the function merely selects this subbuffer instead + * of making a copy. + */ +static inline int mbedtls_psa_tls_psa_ec_to_ecpoint( unsigned char *src, + size_t srclen, + unsigned char **dst, + size_t *dstlen ) +{ + *dst = src; + *dstlen = srclen; + return( 0 ); +} + +/* This function takes a buffer holding an ECPoint structure + * (as contained in a TLS ServerKeyExchange message for ECDHE + * exchanges) and converts it into a format that the PSA key + * agreement API understands. + */ +static inline int mbedtls_psa_tls_ecpoint_to_psa_ec( unsigned char const *src, + size_t srclen, + unsigned char *dst, + size_t dstlen, + size_t *olen ) +{ + if( srclen > dstlen ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + memcpy( dst, src, srclen ); + *olen = srclen; + return( 0 ); +} + +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#endif /* MBEDTLS_PSA_UTIL_H */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ripemd160.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ripemd160.h new file mode 100644 index 0000000..381c725 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ripemd160.h @@ -0,0 +1,235 @@ +/** + * \file ripemd160.h + * + * \brief RIPE MD-160 message digest + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_RIPEMD160_H +#define MBEDTLS_RIPEMD160_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +/* MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED is deprecated and should not be used. + */ +#define MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED -0x0031 /**< RIPEMD160 hardware accelerator failed */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_RIPEMD160_ALT) +// Regular implementation +// + +/** + * \brief RIPEMD-160 context structure + */ +typedef struct mbedtls_ripemd160_context +{ + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[5]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ +} +mbedtls_ripemd160_context; + +#else /* MBEDTLS_RIPEMD160_ALT */ +#include "ripemd160_alt.h" +#endif /* MBEDTLS_RIPEMD160_ALT */ + +/** + * \brief Initialize RIPEMD-160 context + * + * \param ctx RIPEMD-160 context to be initialized + */ +void mbedtls_ripemd160_init( mbedtls_ripemd160_context *ctx ); + +/** + * \brief Clear RIPEMD-160 context + * + * \param ctx RIPEMD-160 context to be cleared + */ +void mbedtls_ripemd160_free( mbedtls_ripemd160_context *ctx ); + +/** + * \brief Clone (the state of) an RIPEMD-160 context + * + * \param dst The destination context + * \param src The context to be cloned + */ +void mbedtls_ripemd160_clone( mbedtls_ripemd160_context *dst, + const mbedtls_ripemd160_context *src ); + +/** + * \brief RIPEMD-160 context setup + * + * \param ctx context to be initialized + * + * \return 0 if successful + */ +int mbedtls_ripemd160_starts_ret( mbedtls_ripemd160_context *ctx ); + +/** + * \brief RIPEMD-160 process buffer + * + * \param ctx RIPEMD-160 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \return 0 if successful + */ +int mbedtls_ripemd160_update_ret( mbedtls_ripemd160_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief RIPEMD-160 final digest + * + * \param ctx RIPEMD-160 context + * \param output RIPEMD-160 checksum result + * + * \return 0 if successful + */ +int mbedtls_ripemd160_finish_ret( mbedtls_ripemd160_context *ctx, + unsigned char output[20] ); + +/** + * \brief RIPEMD-160 process data block (internal use only) + * + * \param ctx RIPEMD-160 context + * \param data buffer holding one block of data + * + * \return 0 if successful + */ +int mbedtls_internal_ripemd160_process( mbedtls_ripemd160_context *ctx, + const unsigned char data[64] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief RIPEMD-160 context setup + * + * \deprecated Superseded by mbedtls_ripemd160_starts_ret() in 2.7.0 + * + * \param ctx context to be initialized + */ +MBEDTLS_DEPRECATED void mbedtls_ripemd160_starts( + mbedtls_ripemd160_context *ctx ); + +/** + * \brief RIPEMD-160 process buffer + * + * \deprecated Superseded by mbedtls_ripemd160_update_ret() in 2.7.0 + * + * \param ctx RIPEMD-160 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +MBEDTLS_DEPRECATED void mbedtls_ripemd160_update( + mbedtls_ripemd160_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief RIPEMD-160 final digest + * + * \deprecated Superseded by mbedtls_ripemd160_finish_ret() in 2.7.0 + * + * \param ctx RIPEMD-160 context + * \param output RIPEMD-160 checksum result + */ +MBEDTLS_DEPRECATED void mbedtls_ripemd160_finish( + mbedtls_ripemd160_context *ctx, + unsigned char output[20] ); + +/** + * \brief RIPEMD-160 process data block (internal use only) + * + * \deprecated Superseded by mbedtls_internal_ripemd160_process() in 2.7.0 + * + * \param ctx RIPEMD-160 context + * \param data buffer holding one block of data + */ +MBEDTLS_DEPRECATED void mbedtls_ripemd160_process( + mbedtls_ripemd160_context *ctx, + const unsigned char data[64] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Output = RIPEMD-160( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output RIPEMD-160 checksum result + * + * \return 0 if successful + */ +int mbedtls_ripemd160_ret( const unsigned char *input, + size_t ilen, + unsigned char output[20] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Output = RIPEMD-160( input buffer ) + * + * \deprecated Superseded by mbedtls_ripemd160_ret() in 2.7.0 + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output RIPEMD-160 checksum result + */ +MBEDTLS_DEPRECATED void mbedtls_ripemd160( const unsigned char *input, + size_t ilen, + unsigned char output[20] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_ripemd160_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_ripemd160.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/rsa.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/rsa.h new file mode 100644 index 0000000..6a31514 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/rsa.h @@ -0,0 +1,1275 @@ +/** + * \file rsa.h + * + * \brief This file provides an API for the RSA public-key cryptosystem. + * + * The RSA public-key cryptosystem is defined in Public-Key + * Cryptography Standards (PKCS) #1 v1.5: RSA Encryption + * and Public-Key Cryptography Standards (PKCS) #1 v2.1: + * RSA Cryptography Specifications. + * + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_RSA_H +#define MBEDTLS_RSA_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/bignum.h" +#include "mbedtls/md.h" + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +/* + * RSA Error codes + */ +#define MBEDTLS_ERR_RSA_BAD_INPUT_DATA -0x4080 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_RSA_INVALID_PADDING -0x4100 /**< Input data contains invalid padding and is rejected. */ +#define MBEDTLS_ERR_RSA_KEY_GEN_FAILED -0x4180 /**< Something failed during generation of a key. */ +#define MBEDTLS_ERR_RSA_KEY_CHECK_FAILED -0x4200 /**< Key failed to pass the validity check of the library. */ +#define MBEDTLS_ERR_RSA_PUBLIC_FAILED -0x4280 /**< The public key operation failed. */ +#define MBEDTLS_ERR_RSA_PRIVATE_FAILED -0x4300 /**< The private key operation failed. */ +#define MBEDTLS_ERR_RSA_VERIFY_FAILED -0x4380 /**< The PKCS#1 verification failed. */ +#define MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE -0x4400 /**< The output buffer for decryption is not large enough. */ +#define MBEDTLS_ERR_RSA_RNG_FAILED -0x4480 /**< The random generator failed to generate non-zeros. */ + +/* MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION is deprecated and should not be used. + */ +#define MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION -0x4500 /**< The implementation does not offer the requested operation, for example, because of security violations or lack of functionality. */ + +/* MBEDTLS_ERR_RSA_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_RSA_HW_ACCEL_FAILED -0x4580 /**< RSA hardware accelerator failed. */ + +/* + * RSA constants + */ +#define MBEDTLS_RSA_PUBLIC 0 /**< Request private key operation. */ +#define MBEDTLS_RSA_PRIVATE 1 /**< Request public key operation. */ + +#define MBEDTLS_RSA_PKCS_V15 0 /**< Use PKCS#1 v1.5 encoding. */ +#define MBEDTLS_RSA_PKCS_V21 1 /**< Use PKCS#1 v2.1 encoding. */ + +#define MBEDTLS_RSA_SIGN 1 /**< Identifier for RSA signature operations. */ +#define MBEDTLS_RSA_CRYPT 2 /**< Identifier for RSA encryption and decryption operations. */ + +#define MBEDTLS_RSA_SALT_LEN_ANY -1 + +/* + * The above constants may be used even if the RSA module is compile out, + * eg for alternative (PKCS#11) RSA implemenations in the PK layers. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_RSA_ALT) +// Regular implementation +// + +/** + * \brief The RSA context structure. + * + * \note Direct manipulation of the members of this structure + * is deprecated. All manipulation should instead be done through + * the public interface functions. + */ +typedef struct mbedtls_rsa_context +{ + int ver; /*!< Always 0.*/ + size_t len; /*!< The size of \p N in Bytes. */ + + mbedtls_mpi N; /*!< The public modulus. */ + mbedtls_mpi E; /*!< The public exponent. */ + + mbedtls_mpi D; /*!< The private exponent. */ + mbedtls_mpi P; /*!< The first prime factor. */ + mbedtls_mpi Q; /*!< The second prime factor. */ + + mbedtls_mpi DP; /*!< D % (P - 1). */ + mbedtls_mpi DQ; /*!< D % (Q - 1). */ + mbedtls_mpi QP; /*!< 1 / (Q % P). */ + + mbedtls_mpi RN; /*!< cached R^2 mod N. */ + + mbedtls_mpi RP; /*!< cached R^2 mod P. */ + mbedtls_mpi RQ; /*!< cached R^2 mod Q. */ + + mbedtls_mpi Vi; /*!< The cached blinding value. */ + mbedtls_mpi Vf; /*!< The cached un-blinding value. */ + + int padding; /*!< Selects padding mode: + #MBEDTLS_RSA_PKCS_V15 for 1.5 padding and + #MBEDTLS_RSA_PKCS_V21 for OAEP or PSS. */ + int hash_id; /*!< Hash identifier of mbedtls_md_type_t type, + as specified in md.h for use in the MGF + mask generating function used in the + EME-OAEP and EMSA-PSS encodings. */ +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; /*!< Thread-safety mutex. */ +#endif +} +mbedtls_rsa_context; + +#else /* MBEDTLS_RSA_ALT */ +#include "rsa_alt.h" +#endif /* MBEDTLS_RSA_ALT */ + +/** + * \brief This function initializes an RSA context. + * + * \note Set padding to #MBEDTLS_RSA_PKCS_V21 for the RSAES-OAEP + * encryption scheme and the RSASSA-PSS signature scheme. + * + * \note The \p hash_id parameter is ignored when using + * #MBEDTLS_RSA_PKCS_V15 padding. + * + * \note The choice of padding mode is strictly enforced for private key + * operations, since there might be security concerns in + * mixing padding modes. For public key operations it is + * a default value, which can be overridden by calling specific + * \c rsa_rsaes_xxx or \c rsa_rsassa_xxx functions. + * + * \note The hash selected in \p hash_id is always used for OEAP + * encryption. For PSS signatures, it is always used for + * making signatures, but can be overridden for verifying them. + * If set to #MBEDTLS_MD_NONE, it is always overridden. + * + * \param ctx The RSA context to initialize. This must not be \c NULL. + * \param padding The padding mode to use. This must be either + * #MBEDTLS_RSA_PKCS_V15 or #MBEDTLS_RSA_PKCS_V21. + * \param hash_id The hash identifier of ::mbedtls_md_type_t type, if + * \p padding is #MBEDTLS_RSA_PKCS_V21. It is unused + * otherwise. + */ +void mbedtls_rsa_init( mbedtls_rsa_context *ctx, + int padding, + int hash_id ); + +/** + * \brief This function imports a set of core parameters into an + * RSA context. + * + * \note This function can be called multiple times for successive + * imports, if the parameters are not simultaneously present. + * + * Any sequence of calls to this function should be followed + * by a call to mbedtls_rsa_complete(), which checks and + * completes the provided information to a ready-for-use + * public or private RSA key. + * + * \note See mbedtls_rsa_complete() for more information on which + * parameters are necessary to set up a private or public + * RSA key. + * + * \note The imported parameters are copied and need not be preserved + * for the lifetime of the RSA context being set up. + * + * \param ctx The initialized RSA context to store the parameters in. + * \param N The RSA modulus. This may be \c NULL. + * \param P The first prime factor of \p N. This may be \c NULL. + * \param Q The second prime factor of \p N. This may be \c NULL. + * \param D The private exponent. This may be \c NULL. + * \param E The public exponent. This may be \c NULL. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_rsa_import( mbedtls_rsa_context *ctx, + const mbedtls_mpi *N, + const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, const mbedtls_mpi *E ); + +/** + * \brief This function imports core RSA parameters, in raw big-endian + * binary format, into an RSA context. + * + * \note This function can be called multiple times for successive + * imports, if the parameters are not simultaneously present. + * + * Any sequence of calls to this function should be followed + * by a call to mbedtls_rsa_complete(), which checks and + * completes the provided information to a ready-for-use + * public or private RSA key. + * + * \note See mbedtls_rsa_complete() for more information on which + * parameters are necessary to set up a private or public + * RSA key. + * + * \note The imported parameters are copied and need not be preserved + * for the lifetime of the RSA context being set up. + * + * \param ctx The initialized RSA context to store the parameters in. + * \param N The RSA modulus. This may be \c NULL. + * \param N_len The Byte length of \p N; it is ignored if \p N == NULL. + * \param P The first prime factor of \p N. This may be \c NULL. + * \param P_len The Byte length of \p P; it ns ignored if \p P == NULL. + * \param Q The second prime factor of \p N. This may be \c NULL. + * \param Q_len The Byte length of \p Q; it is ignored if \p Q == NULL. + * \param D The private exponent. This may be \c NULL. + * \param D_len The Byte length of \p D; it is ignored if \p D == NULL. + * \param E The public exponent. This may be \c NULL. + * \param E_len The Byte length of \p E; it is ignored if \p E == NULL. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_rsa_import_raw( mbedtls_rsa_context *ctx, + unsigned char const *N, size_t N_len, + unsigned char const *P, size_t P_len, + unsigned char const *Q, size_t Q_len, + unsigned char const *D, size_t D_len, + unsigned char const *E, size_t E_len ); + +/** + * \brief This function completes an RSA context from + * a set of imported core parameters. + * + * To setup an RSA public key, precisely \p N and \p E + * must have been imported. + * + * To setup an RSA private key, sufficient information must + * be present for the other parameters to be derivable. + * + * The default implementation supports the following: + *
  • Derive \p P, \p Q from \p N, \p D, \p E.
  • + *
  • Derive \p N, \p D from \p P, \p Q, \p E.
+ * Alternative implementations need not support these. + * + * If this function runs successfully, it guarantees that + * the RSA context can be used for RSA operations without + * the risk of failure or crash. + * + * \warning This function need not perform consistency checks + * for the imported parameters. In particular, parameters that + * are not needed by the implementation might be silently + * discarded and left unchecked. To check the consistency + * of the key material, see mbedtls_rsa_check_privkey(). + * + * \param ctx The initialized RSA context holding imported parameters. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_RSA_BAD_INPUT_DATA if the attempted derivations + * failed. + * + */ +int mbedtls_rsa_complete( mbedtls_rsa_context *ctx ); + +/** + * \brief This function exports the core parameters of an RSA key. + * + * If this function runs successfully, the non-NULL buffers + * pointed to by \p N, \p P, \p Q, \p D, and \p E are fully + * written, with additional unused space filled leading by + * zero Bytes. + * + * Possible reasons for returning + * #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED:
    + *
  • An alternative RSA implementation is in use, which + * stores the key externally, and either cannot or should + * not export it into RAM.
  • + *
  • A SW or HW implementation might not support a certain + * deduction. For example, \p P, \p Q from \p N, \p D, + * and \p E if the former are not part of the + * implementation.
+ * + * If the function fails due to an unsupported operation, + * the RSA context stays intact and remains usable. + * + * \param ctx The initialized RSA context. + * \param N The MPI to hold the RSA modulus. + * This may be \c NULL if this field need not be exported. + * \param P The MPI to hold the first prime factor of \p N. + * This may be \c NULL if this field need not be exported. + * \param Q The MPI to hold the second prime factor of \p N. + * This may be \c NULL if this field need not be exported. + * \param D The MPI to hold the private exponent. + * This may be \c NULL if this field need not be exported. + * \param E The MPI to hold the public exponent. + * This may be \c NULL if this field need not be exported. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED if exporting the + * requested parameters cannot be done due to missing + * functionality or because of security policies. + * \return A non-zero return code on any other failure. + * + */ +int mbedtls_rsa_export( const mbedtls_rsa_context *ctx, + mbedtls_mpi *N, mbedtls_mpi *P, mbedtls_mpi *Q, + mbedtls_mpi *D, mbedtls_mpi *E ); + +/** + * \brief This function exports core parameters of an RSA key + * in raw big-endian binary format. + * + * If this function runs successfully, the non-NULL buffers + * pointed to by \p N, \p P, \p Q, \p D, and \p E are fully + * written, with additional unused space filled leading by + * zero Bytes. + * + * Possible reasons for returning + * #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED:
    + *
  • An alternative RSA implementation is in use, which + * stores the key externally, and either cannot or should + * not export it into RAM.
  • + *
  • A SW or HW implementation might not support a certain + * deduction. For example, \p P, \p Q from \p N, \p D, + * and \p E if the former are not part of the + * implementation.
+ * If the function fails due to an unsupported operation, + * the RSA context stays intact and remains usable. + * + * \note The length parameters are ignored if the corresponding + * buffer pointers are NULL. + * + * \param ctx The initialized RSA context. + * \param N The Byte array to store the RSA modulus, + * or \c NULL if this field need not be exported. + * \param N_len The size of the buffer for the modulus. + * \param P The Byte array to hold the first prime factor of \p N, + * or \c NULL if this field need not be exported. + * \param P_len The size of the buffer for the first prime factor. + * \param Q The Byte array to hold the second prime factor of \p N, + * or \c NULL if this field need not be exported. + * \param Q_len The size of the buffer for the second prime factor. + * \param D The Byte array to hold the private exponent, + * or \c NULL if this field need not be exported. + * \param D_len The size of the buffer for the private exponent. + * \param E The Byte array to hold the public exponent, + * or \c NULL if this field need not be exported. + * \param E_len The size of the buffer for the public exponent. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED if exporting the + * requested parameters cannot be done due to missing + * functionality or because of security policies. + * \return A non-zero return code on any other failure. + */ +int mbedtls_rsa_export_raw( const mbedtls_rsa_context *ctx, + unsigned char *N, size_t N_len, + unsigned char *P, size_t P_len, + unsigned char *Q, size_t Q_len, + unsigned char *D, size_t D_len, + unsigned char *E, size_t E_len ); + +/** + * \brief This function exports CRT parameters of a private RSA key. + * + * \note Alternative RSA implementations not using CRT-parameters + * internally can implement this function based on + * mbedtls_rsa_deduce_opt(). + * + * \param ctx The initialized RSA context. + * \param DP The MPI to hold \c D modulo `P-1`, + * or \c NULL if it need not be exported. + * \param DQ The MPI to hold \c D modulo `Q-1`, + * or \c NULL if it need not be exported. + * \param QP The MPI to hold modular inverse of \c Q modulo \c P, + * or \c NULL if it need not be exported. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + * + */ +int mbedtls_rsa_export_crt( const mbedtls_rsa_context *ctx, + mbedtls_mpi *DP, mbedtls_mpi *DQ, mbedtls_mpi *QP ); + +/** + * \brief This function sets padding for an already initialized RSA + * context. See mbedtls_rsa_init() for details. + * + * \param ctx The initialized RSA context to be configured. + * \param padding The padding mode to use. This must be either + * #MBEDTLS_RSA_PKCS_V15 or #MBEDTLS_RSA_PKCS_V21. + * \param hash_id The #MBEDTLS_RSA_PKCS_V21 hash identifier. + */ +void mbedtls_rsa_set_padding( mbedtls_rsa_context *ctx, int padding, + int hash_id ); + +/** + * \brief This function retrieves the length of RSA modulus in Bytes. + * + * \param ctx The initialized RSA context. + * + * \return The length of the RSA modulus in Bytes. + * + */ +size_t mbedtls_rsa_get_len( const mbedtls_rsa_context *ctx ); + +/** + * \brief This function generates an RSA keypair. + * + * \note mbedtls_rsa_init() must be called before this function, + * to set up the RSA context. + * + * \param ctx The initialized RSA context used to hold the key. + * \param f_rng The RNG function to be used for key generation. + * This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. + * This may be \c NULL if \p f_rng doesn't need a context. + * \param nbits The size of the public key in bits. + * \param exponent The public exponent to use. For example, \c 65537. + * This must be odd and greater than \c 1. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + unsigned int nbits, int exponent ); + +/** + * \brief This function checks if a context contains at least an RSA + * public key. + * + * If the function runs successfully, it is guaranteed that + * enough information is present to perform an RSA public key + * operation using mbedtls_rsa_public(). + * + * \param ctx The initialized RSA context to check. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + * + */ +int mbedtls_rsa_check_pubkey( const mbedtls_rsa_context *ctx ); + +/** + * \brief This function checks if a context contains an RSA private key + * and perform basic consistency checks. + * + * \note The consistency checks performed by this function not only + * ensure that mbedtls_rsa_private() can be called successfully + * on the given context, but that the various parameters are + * mutually consistent with high probability, in the sense that + * mbedtls_rsa_public() and mbedtls_rsa_private() are inverses. + * + * \warning This function should catch accidental misconfigurations + * like swapping of parameters, but it cannot establish full + * trust in neither the quality nor the consistency of the key + * material that was used to setup the given RSA context: + *
  • Consistency: Imported parameters that are irrelevant + * for the implementation might be silently dropped. If dropped, + * the current function does not have access to them, + * and therefore cannot check them. See mbedtls_rsa_complete(). + * If you want to check the consistency of the entire + * content of an PKCS1-encoded RSA private key, for example, you + * should use mbedtls_rsa_validate_params() before setting + * up the RSA context. + * Additionally, if the implementation performs empirical checks, + * these checks substantiate but do not guarantee consistency.
  • + *
  • Quality: This function is not expected to perform + * extended quality assessments like checking that the prime + * factors are safe. Additionally, it is the responsibility of the + * user to ensure the trustworthiness of the source of his RSA + * parameters, which goes beyond what is effectively checkable + * by the library.
+ * + * \param ctx The initialized RSA context to check. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx ); + +/** + * \brief This function checks a public-private RSA key pair. + * + * It checks each of the contexts, and makes sure they match. + * + * \param pub The initialized RSA context holding the public key. + * \param prv The initialized RSA context holding the private key. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_check_pub_priv( const mbedtls_rsa_context *pub, + const mbedtls_rsa_context *prv ); + +/** + * \brief This function performs an RSA public key operation. + * + * \param ctx The initialized RSA context to use. + * \param input The input buffer. This must be a readable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * \param output The output buffer. This must be a writable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \note This function does not handle message padding. + * + * \note Make sure to set \p input[0] = 0 or ensure that + * input is smaller than \p N. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_public( mbedtls_rsa_context *ctx, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function performs an RSA private key operation. + * + * \note Blinding is used if and only if a PRNG is provided. + * + * \note If blinding is used, both the base of exponentation + * and the exponent are blinded, providing protection + * against some side-channel attacks. + * + * \warning It is deprecated and a security risk to not provide + * a PRNG here and thereby prevent the use of blinding. + * Future versions of the library may enforce the presence + * of a PRNG. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function, used for blinding. It is discouraged + * and deprecated to pass \c NULL here, in which case + * blinding will be omitted. + * \param p_rng The RNG context to pass to \p f_rng. This may be \c NULL + * if \p f_rng is \c NULL or if \p f_rng doesn't need a context. + * \param input The input buffer. This must be a readable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * \param output The output buffer. This must be a writable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + * + */ +int mbedtls_rsa_private( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function adds the message padding, then performs an RSA + * operation. + * + * It is the generic wrapper for performing a PKCS#1 encryption + * operation using the \p mode from the context. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PUBLIC. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG to use. It is mandatory for PKCS#1 v2.1 padding + * encoding, and for PKCS#1 v1.5 padding encoding when used + * with \p mode set to #MBEDTLS_RSA_PUBLIC. For PKCS#1 v1.5 + * padding encoding and \p mode set to #MBEDTLS_RSA_PRIVATE, + * it is used for blinding and should be provided in this + * case; see mbedtls_rsa_private() for more. + * \param p_rng The RNG context to be passed to \p f_rng. May be + * \c NULL if \p f_rng is \c NULL or if \p f_rng doesn't + * need a context argument. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated). + * \param ilen The length of the plaintext in Bytes. + * \param input The input data to encrypt. This must be a readable + * buffer of size \p ilen Bytes. It may be \c NULL if + * `ilen == 0`. + * \param output The output buffer. This must be a writable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_pkcs1_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t ilen, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function performs a PKCS#1 v1.5 encryption operation + * (RSAES-PKCS1-v1_5-ENCRYPT). + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PUBLIC. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function to use. It is needed for padding generation + * if \p mode is #MBEDTLS_RSA_PUBLIC. If \p mode is + * #MBEDTLS_RSA_PRIVATE (discouraged), it is used for + * blinding and should be provided; see mbedtls_rsa_private(). + * \param p_rng The RNG context to be passed to \p f_rng. This may + * be \c NULL if \p f_rng is \c NULL or if \p f_rng + * doesn't need a context argument. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated). + * \param ilen The length of the plaintext in Bytes. + * \param input The input data to encrypt. This must be a readable + * buffer of size \p ilen Bytes. It may be \c NULL if + * `ilen == 0`. + * \param output The output buffer. This must be a writable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t ilen, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function performs a PKCS#1 v2.1 OAEP encryption + * operation (RSAES-OAEP-ENCRYPT). + * + * \note The output buffer must be as large as the size + * of ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PUBLIC. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initnialized RSA context to use. + * \param f_rng The RNG function to use. This is needed for padding + * generation and must be provided. + * \param p_rng The RNG context to be passed to \p f_rng. This may + * be \c NULL if \p f_rng doesn't need a context argument. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated). + * \param label The buffer holding the custom label to use. + * This must be a readable buffer of length \p label_len + * Bytes. It may be \c NULL if \p label_len is \c 0. + * \param label_len The length of the label in Bytes. + * \param ilen The length of the plaintext buffer \p input in Bytes. + * \param input The input data to encrypt. This must be a readable + * buffer of size \p ilen Bytes. It may be \c NULL if + * `ilen == 0`. + * \param output The output buffer. This must be a writable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + const unsigned char *label, size_t label_len, + size_t ilen, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function performs an RSA operation, then removes the + * message padding. + * + * It is the generic wrapper for performing a PKCS#1 decryption + * operation using the \p mode from the context. + * + * \note The output buffer length \c output_max_len should be + * as large as the size \p ctx->len of \p ctx->N (for example, + * 128 Bytes if RSA-1024 is used) to be able to hold an + * arbitrary decrypted message. If it is not large enough to + * hold the decryption of the particular ciphertext provided, + * the function returns \c MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function. If \p mode is #MBEDTLS_RSA_PRIVATE, + * this is used for blinding and should be provided; see + * mbedtls_rsa_private() for more. If \p mode is + * #MBEDTLS_RSA_PUBLIC, it is ignored. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't need a context. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated). + * \param olen The address at which to store the length of + * the plaintext. This must not be \c NULL. + * \param input The ciphertext buffer. This must be a readable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * \param output The buffer used to hold the plaintext. This must + * be a writable buffer of length \p output_max_len Bytes. + * \param output_max_len The length in Bytes of the output buffer \p output. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_pkcs1_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ); + +/** + * \brief This function performs a PKCS#1 v1.5 decryption + * operation (RSAES-PKCS1-v1_5-DECRYPT). + * + * \note The output buffer length \c output_max_len should be + * as large as the size \p ctx->len of \p ctx->N, for example, + * 128 Bytes if RSA-1024 is used, to be able to hold an + * arbitrary decrypted message. If it is not large enough to + * hold the decryption of the particular ciphertext provided, + * the function returns #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function. If \p mode is #MBEDTLS_RSA_PRIVATE, + * this is used for blinding and should be provided; see + * mbedtls_rsa_private() for more. If \p mode is + * #MBEDTLS_RSA_PUBLIC, it is ignored. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't need a context. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated). + * \param olen The address at which to store the length of + * the plaintext. This must not be \c NULL. + * \param input The ciphertext buffer. This must be a readable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * \param output The buffer used to hold the plaintext. This must + * be a writable buffer of length \p output_max_len Bytes. + * \param output_max_len The length in Bytes of the output buffer \p output. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + * + */ +int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ); + +/** + * \brief This function performs a PKCS#1 v2.1 OAEP decryption + * operation (RSAES-OAEP-DECRYPT). + * + * \note The output buffer length \c output_max_len should be + * as large as the size \p ctx->len of \p ctx->N, for + * example, 128 Bytes if RSA-1024 is used, to be able to + * hold an arbitrary decrypted message. If it is not + * large enough to hold the decryption of the particular + * ciphertext provided, the function returns + * #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function. If \p mode is #MBEDTLS_RSA_PRIVATE, + * this is used for blinding and should be provided; see + * mbedtls_rsa_private() for more. If \p mode is + * #MBEDTLS_RSA_PUBLIC, it is ignored. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't need a context. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated). + * \param label The buffer holding the custom label to use. + * This must be a readable buffer of length \p label_len + * Bytes. It may be \c NULL if \p label_len is \c 0. + * \param label_len The length of the label in Bytes. + * \param olen The address at which to store the length of + * the plaintext. This must not be \c NULL. + * \param input The ciphertext buffer. This must be a readable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * \param output The buffer used to hold the plaintext. This must + * be a writable buffer of length \p output_max_len Bytes. + * \param output_max_len The length in Bytes of the output buffer \p output. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + const unsigned char *label, size_t label_len, + size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ); + +/** + * \brief This function performs a private RSA operation to sign + * a message digest using PKCS#1. + * + * It is the generic wrapper for performing a PKCS#1 + * signature using the \p mode from the context. + * + * \note The \p sig buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \note For PKCS#1 v2.1 encoding, see comments on + * mbedtls_rsa_rsassa_pss_sign() for details on + * \p md_alg and \p hash_id. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function to use. If the padding mode is PKCS#1 v2.1, + * this must be provided. If the padding mode is PKCS#1 v1.5 and + * \p mode is #MBEDTLS_RSA_PRIVATE, it is used for blinding + * and should be provided; see mbedtls_rsa_private() for more + * more. It is ignored otherwise. + * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL + * if \p f_rng is \c NULL or doesn't need a context argument. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated). + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. + * Ths is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest or raw data. + * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable + * buffer of length \p hashlen Bytes. If \p md_alg is not + * #MBEDTLS_MD_NONE, it must be a readable buffer of length + * the size of the hash corresponding to \p md_alg. + * \param sig The buffer to hold the signature. This must be a writable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. A buffer length of + * #MBEDTLS_MPI_MAX_SIZE is always safe. + * + * \return \c 0 if the signing operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_pkcs1_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); + +/** + * \brief This function performs a PKCS#1 v1.5 signature + * operation (RSASSA-PKCS1-v1_5-SIGN). + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function. If \p mode is #MBEDTLS_RSA_PRIVATE, + * this is used for blinding and should be provided; see + * mbedtls_rsa_private() for more. If \p mode is + * #MBEDTLS_RSA_PUBLIC, it is ignored. + * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL + * if \p f_rng is \c NULL or doesn't need a context argument. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated). + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. + * Ths is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest or raw data. + * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable + * buffer of length \p hashlen Bytes. If \p md_alg is not + * #MBEDTLS_MD_NONE, it must be a readable buffer of length + * the size of the hash corresponding to \p md_alg. + * \param sig The buffer to hold the signature. This must be a writable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. A buffer length of + * #MBEDTLS_MPI_MAX_SIZE is always safe. + * + * \return \c 0 if the signing operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); + +/** + * \brief This function performs a PKCS#1 v2.1 PSS signature + * operation (RSASSA-PSS-SIGN). + * + * \note The \p hash_id in the RSA context is the one used for the + * encoding. \p md_alg in the function call is the type of hash + * that is encoded. According to RFC-3447: Public-Key + * Cryptography Standards (PKCS) #1 v2.1: RSA Cryptography + * Specifications it is advised to keep both hashes the + * same. + * + * \note This function always uses the maximum possible salt size, + * up to the length of the payload hash. This choice of salt + * size complies with FIPS 186-4 §5.5 (e) and RFC 8017 (PKCS#1 + * v2.2) §9.1.1 step 3. Furthermore this function enforces a + * minimum salt size which is the hash size minus 2 bytes. If + * this minimum size is too large given the key size (the salt + * size, plus the hash size, plus 2 bytes must be no more than + * the key size in bytes), this function returns + * #MBEDTLS_ERR_RSA_BAD_INPUT_DATA. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function. It must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL + * if \p f_rng doesn't need a context argument. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated). + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. + * Ths is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest or raw data. + * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable + * buffer of length \p hashlen Bytes. If \p md_alg is not + * #MBEDTLS_MD_NONE, it must be a readable buffer of length + * the size of the hash corresponding to \p md_alg. + * \param sig The buffer to hold the signature. This must be a writable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. A buffer length of + * #MBEDTLS_MPI_MAX_SIZE is always safe. + * + * \return \c 0 if the signing operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); + +/** + * \brief This function performs a public RSA operation and checks + * the message digest. + * + * This is the generic wrapper for performing a PKCS#1 + * verification using the mode from the context. + * + * \note For PKCS#1 v2.1 encoding, see comments on + * mbedtls_rsa_rsassa_pss_verify() about \p md_alg and + * \p hash_id. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * set to #MBEDTLS_RSA_PUBLIC. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA public key context to use. + * \param f_rng The RNG function to use. If \p mode is #MBEDTLS_RSA_PRIVATE, + * this is used for blinding and should be provided; see + * mbedtls_rsa_private() for more. Otherwise, it is ignored. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't need a context. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated). + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. + * This is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest or raw data. + * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable + * buffer of length \p hashlen Bytes. If \p md_alg is not + * #MBEDTLS_MD_NONE, it must be a readable buffer of length + * the size of the hash corresponding to \p md_alg. + * \param sig The buffer holding the signature. This must be a readable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 if the verify operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_pkcs1_verify( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ); + +/** + * \brief This function performs a PKCS#1 v1.5 verification + * operation (RSASSA-PKCS1-v1_5-VERIFY). + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * set to #MBEDTLS_RSA_PUBLIC. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA public key context to use. + * \param f_rng The RNG function to use. If \p mode is #MBEDTLS_RSA_PRIVATE, + * this is used for blinding and should be provided; see + * mbedtls_rsa_private() for more. Otherwise, it is ignored. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't need a context. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated). + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. + * This is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest or raw data. + * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable + * buffer of length \p hashlen Bytes. If \p md_alg is not + * #MBEDTLS_MD_NONE, it must be a readable buffer of length + * the size of the hash corresponding to \p md_alg. + * \param sig The buffer holding the signature. This must be a readable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 if the verify operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsassa_pkcs1_v15_verify( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ); + +/** + * \brief This function performs a PKCS#1 v2.1 PSS verification + * operation (RSASSA-PSS-VERIFY). + * + * The hash function for the MGF mask generating function + * is that specified in the RSA context. + * + * \note The \p hash_id in the RSA context is the one used for the + * verification. \p md_alg in the function call is the type of + * hash that is verified. According to RFC-3447: Public-Key + * Cryptography Standards (PKCS) #1 v2.1: RSA Cryptography + * Specifications it is advised to keep both hashes the + * same. If \p hash_id in the RSA context is unset, + * the \p md_alg from the function call is used. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PUBLIC. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA public key context to use. + * \param f_rng The RNG function to use. If \p mode is #MBEDTLS_RSA_PRIVATE, + * this is used for blinding and should be provided; see + * mbedtls_rsa_private() for more. Otherwise, it is ignored. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't need a context. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated). + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. + * This is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest or raw data. + * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable + * buffer of length \p hashlen Bytes. If \p md_alg is not + * #MBEDTLS_MD_NONE, it must be a readable buffer of length + * the size of the hash corresponding to \p md_alg. + * \param sig The buffer holding the signature. This must be a readable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 if the verify operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsassa_pss_verify( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ); + +/** + * \brief This function performs a PKCS#1 v2.1 PSS verification + * operation (RSASSA-PSS-VERIFY). + * + * The hash function for the MGF mask generating function + * is that specified in \p mgf1_hash_id. + * + * \note The \p sig buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \note The \p hash_id in the RSA context is ignored. + * + * \param ctx The initialized RSA public key context to use. + * \param f_rng The RNG function to use. If \p mode is #MBEDTLS_RSA_PRIVATE, + * this is used for blinding and should be provided; see + * mbedtls_rsa_private() for more. Otherwise, it is ignored. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't need a context. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. + * This is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest or raw data. + * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable + * buffer of length \p hashlen Bytes. If \p md_alg is not + * #MBEDTLS_MD_NONE, it must be a readable buffer of length + * the size of the hash corresponding to \p md_alg. + * \param mgf1_hash_id The message digest used for mask generation. + * \param expected_salt_len The length of the salt used in padding. Use + * #MBEDTLS_RSA_SALT_LEN_ANY to accept any salt length. + * \param sig The buffer holding the signature. This must be a readable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 if the verify operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + mbedtls_md_type_t mgf1_hash_id, + int expected_salt_len, + const unsigned char *sig ); + +/** + * \brief This function copies the components of an RSA context. + * + * \param dst The destination context. This must be initialized. + * \param src The source context. This must be initialized. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory allocation failure. + */ +int mbedtls_rsa_copy( mbedtls_rsa_context *dst, const mbedtls_rsa_context *src ); + +/** + * \brief This function frees the components of an RSA key. + * + * \param ctx The RSA context to free. May be \c NULL, in which case + * this function is a no-op. If it is not \c NULL, it must + * point to an initialized RSA context. + */ +void mbedtls_rsa_free( mbedtls_rsa_context *ctx ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief The RSA checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_rsa_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* rsa.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/rsa_internal.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/rsa_internal.h new file mode 100644 index 0000000..d55492b --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/rsa_internal.h @@ -0,0 +1,224 @@ +/** + * \file rsa_internal.h + * + * \brief Context-independent RSA helper functions + * + * This module declares some RSA-related helper functions useful when + * implementing the RSA interface. These functions are provided in a separate + * compilation unit in order to make it easy for designers of alternative RSA + * implementations to use them in their own code, as it is conceived that the + * functionality they provide will be necessary for most complete + * implementations. + * + * End-users of Mbed TLS who are not providing their own alternative RSA + * implementations should not use these functions directly, and should instead + * use only the functions declared in rsa.h. + * + * The interface provided by this module will be maintained through LTS (Long + * Term Support) branches of Mbed TLS, but may otherwise be subject to change, + * and must be considered an internal interface of the library. + * + * There are two classes of helper functions: + * + * (1) Parameter-generating helpers. These are: + * - mbedtls_rsa_deduce_primes + * - mbedtls_rsa_deduce_private_exponent + * - mbedtls_rsa_deduce_crt + * Each of these functions takes a set of core RSA parameters and + * generates some other, or CRT related parameters. + * + * (2) Parameter-checking helpers. These are: + * - mbedtls_rsa_validate_params + * - mbedtls_rsa_validate_crt + * They take a set of core or CRT related RSA parameters and check their + * validity. + * + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_RSA_INTERNAL_H +#define MBEDTLS_RSA_INTERNAL_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/bignum.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * \brief Compute RSA prime moduli P, Q from public modulus N=PQ + * and a pair of private and public key. + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param N RSA modulus N = PQ, with P, Q to be found + * \param E RSA public exponent + * \param D RSA private exponent + * \param P Pointer to MPI holding first prime factor of N on success + * \param Q Pointer to MPI holding second prime factor of N on success + * + * \return + * - 0 if successful. In this case, P and Q constitute a + * factorization of N. + * - A non-zero error code otherwise. + * + * \note It is neither checked that P, Q are prime nor that + * D, E are modular inverses wrt. P-1 and Q-1. For that, + * use the helper function \c mbedtls_rsa_validate_params. + * + */ +int mbedtls_rsa_deduce_primes( mbedtls_mpi const *N, mbedtls_mpi const *E, + mbedtls_mpi const *D, + mbedtls_mpi *P, mbedtls_mpi *Q ); + +/** + * \brief Compute RSA private exponent from + * prime moduli and public key. + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param P First prime factor of RSA modulus + * \param Q Second prime factor of RSA modulus + * \param E RSA public exponent + * \param D Pointer to MPI holding the private exponent on success. + * + * \return + * - 0 if successful. In this case, D is set to a simultaneous + * modular inverse of E modulo both P-1 and Q-1. + * - A non-zero error code otherwise. + * + * \note This function does not check whether P and Q are primes. + * + */ +int mbedtls_rsa_deduce_private_exponent( mbedtls_mpi const *P, + mbedtls_mpi const *Q, + mbedtls_mpi const *E, + mbedtls_mpi *D ); + + +/** + * \brief Generate RSA-CRT parameters + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param P First prime factor of N + * \param Q Second prime factor of N + * \param D RSA private exponent + * \param DP Output variable for D modulo P-1 + * \param DQ Output variable for D modulo Q-1 + * \param QP Output variable for the modular inverse of Q modulo P. + * + * \return 0 on success, non-zero error code otherwise. + * + * \note This function does not check whether P, Q are + * prime and whether D is a valid private exponent. + * + */ +int mbedtls_rsa_deduce_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, mbedtls_mpi *DP, + mbedtls_mpi *DQ, mbedtls_mpi *QP ); + + +/** + * \brief Check validity of core RSA parameters + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param N RSA modulus N = PQ + * \param P First prime factor of N + * \param Q Second prime factor of N + * \param D RSA private exponent + * \param E RSA public exponent + * \param f_rng PRNG to be used for primality check, or NULL + * \param p_rng PRNG context for f_rng, or NULL + * + * \return + * - 0 if the following conditions are satisfied + * if all relevant parameters are provided: + * - P prime if f_rng != NULL (%) + * - Q prime if f_rng != NULL (%) + * - 1 < N = P * Q + * - 1 < D, E < N + * - D and E are modular inverses modulo P-1 and Q-1 + * (%) This is only done if MBEDTLS_GENPRIME is defined. + * - A non-zero error code otherwise. + * + * \note The function can be used with a restricted set of arguments + * to perform specific checks only. E.g., calling it with + * (-,P,-,-,-) and a PRNG amounts to a primality check for P. + */ +int mbedtls_rsa_validate_params( const mbedtls_mpi *N, const mbedtls_mpi *P, + const mbedtls_mpi *Q, const mbedtls_mpi *D, + const mbedtls_mpi *E, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Check validity of RSA CRT parameters + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param P First prime factor of RSA modulus + * \param Q Second prime factor of RSA modulus + * \param D RSA private exponent + * \param DP MPI to check for D modulo P-1 + * \param DQ MPI to check for D modulo P-1 + * \param QP MPI to check for the modular inverse of Q modulo P. + * + * \return + * - 0 if the following conditions are satisfied: + * - D = DP mod P-1 if P, D, DP != NULL + * - Q = DQ mod P-1 if P, D, DQ != NULL + * - QP = Q^-1 mod P if P, Q, QP != NULL + * - \c MBEDTLS_ERR_RSA_KEY_CHECK_FAILED if check failed, + * potentially including \c MBEDTLS_ERR_MPI_XXX if some + * MPI calculations failed. + * - \c MBEDTLS_ERR_RSA_BAD_INPUT_DATA if insufficient + * data was provided to check DP, DQ or QP. + * + * \note The function can be used with a restricted set of arguments + * to perform specific checks only. E.g., calling it with the + * parameters (P, -, D, DP, -, -) will check DP = D mod P-1. + */ +int mbedtls_rsa_validate_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, const mbedtls_mpi *DP, + const mbedtls_mpi *DQ, const mbedtls_mpi *QP ); + +#ifdef __cplusplus +} +#endif + +#endif /* rsa_internal.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/sha1.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/sha1.h new file mode 100644 index 0000000..86a3d06 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/sha1.h @@ -0,0 +1,350 @@ +/** + * \file sha1.h + * + * \brief This file contains SHA-1 definitions and functions. + * + * The Secure Hash Algorithm 1 (SHA-1) cryptographic hash function is defined in + * FIPS 180-4: Secure Hash Standard (SHS). + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. We recommend considering stronger message + * digests instead. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_SHA1_H +#define MBEDTLS_SHA1_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +/* MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED -0x0035 /**< SHA-1 hardware accelerator failed */ +#define MBEDTLS_ERR_SHA1_BAD_INPUT_DATA -0x0073 /**< SHA-1 input data was malformed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_SHA1_ALT) +// Regular implementation +// + +/** + * \brief The SHA-1 context structure. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +typedef struct mbedtls_sha1_context +{ + uint32_t total[2]; /*!< The number of Bytes processed. */ + uint32_t state[5]; /*!< The intermediate digest state. */ + unsigned char buffer[64]; /*!< The data block being processed. */ +} +mbedtls_sha1_context; + +#else /* MBEDTLS_SHA1_ALT */ +#include "sha1_alt.h" +#endif /* MBEDTLS_SHA1_ALT */ + +/** + * \brief This function initializes a SHA-1 context. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context to initialize. + * This must not be \c NULL. + * + */ +void mbedtls_sha1_init( mbedtls_sha1_context *ctx ); + +/** + * \brief This function clears a SHA-1 context. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context to clear. This may be \c NULL, + * in which case this function does nothing. If it is + * not \c NULL, it must point to an initialized + * SHA-1 context. + * + */ +void mbedtls_sha1_free( mbedtls_sha1_context *ctx ); + +/** + * \brief This function clones the state of a SHA-1 context. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param dst The SHA-1 context to clone to. This must be initialized. + * \param src The SHA-1 context to clone from. This must be initialized. + * + */ +void mbedtls_sha1_clone( mbedtls_sha1_context *dst, + const mbedtls_sha1_context *src ); + +/** + * \brief This function starts a SHA-1 checksum calculation. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context to initialize. This must be initialized. + * + * \return \c 0 on success. + * \return A negative error code on failure. + * + */ +int mbedtls_sha1_starts_ret( mbedtls_sha1_context *ctx ); + +/** + * \brief This function feeds an input buffer into an ongoing SHA-1 + * checksum calculation. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context. This must be initialized + * and have a hash operation started. + * \param input The buffer holding the input data. + * This must be a readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data \p input in Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha1_update_ret( mbedtls_sha1_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-1 operation, and writes + * the result to the output buffer. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context to use. This must be initialized and + * have a hash operation started. + * \param output The SHA-1 checksum result. This must be a writable + * buffer of length \c 20 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha1_finish_ret( mbedtls_sha1_context *ctx, + unsigned char output[20] ); + +/** + * \brief SHA-1 process data block (internal use only). + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context to use. This must be initialized. + * \param data The data block being processed. This must be a + * readable buffer of length \c 64 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + * + */ +int mbedtls_internal_sha1_process( mbedtls_sha1_context *ctx, + const unsigned char data[64] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function starts a SHA-1 checksum calculation. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \deprecated Superseded by mbedtls_sha1_starts_ret() in 2.7.0. + * + * \param ctx The SHA-1 context to initialize. This must be initialized. + * + */ +MBEDTLS_DEPRECATED void mbedtls_sha1_starts( mbedtls_sha1_context *ctx ); + +/** + * \brief This function feeds an input buffer into an ongoing SHA-1 + * checksum calculation. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \deprecated Superseded by mbedtls_sha1_update_ret() in 2.7.0. + * + * \param ctx The SHA-1 context. This must be initialized and + * have a hash operation started. + * \param input The buffer holding the input data. + * This must be a readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data \p input in Bytes. + * + */ +MBEDTLS_DEPRECATED void mbedtls_sha1_update( mbedtls_sha1_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-1 operation, and writes + * the result to the output buffer. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \deprecated Superseded by mbedtls_sha1_finish_ret() in 2.7.0. + * + * \param ctx The SHA-1 context. This must be initialized and + * have a hash operation started. + * \param output The SHA-1 checksum result. + * This must be a writable buffer of length \c 20 Bytes. + */ +MBEDTLS_DEPRECATED void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, + unsigned char output[20] ); + +/** + * \brief SHA-1 process data block (internal use only). + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \deprecated Superseded by mbedtls_internal_sha1_process() in 2.7.0. + * + * \param ctx The SHA-1 context. This must be initialized. + * \param data The data block being processed. + * This must be a readable buffer of length \c 64 bytes. + * + */ +MBEDTLS_DEPRECATED void mbedtls_sha1_process( mbedtls_sha1_context *ctx, + const unsigned char data[64] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief This function calculates the SHA-1 checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-1 result is calculated as + * output = SHA-1(input buffer). + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param input The buffer holding the input data. + * This must be a readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data \p input in Bytes. + * \param output The SHA-1 checksum result. + * This must be a writable buffer of length \c 20 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + * + */ +int mbedtls_sha1_ret( const unsigned char *input, + size_t ilen, + unsigned char output[20] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function calculates the SHA-1 checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-1 result is calculated as + * output = SHA-1(input buffer). + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \deprecated Superseded by mbedtls_sha1_ret() in 2.7.0 + * + * \param input The buffer holding the input data. + * This must be a readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data \p input in Bytes. + * \param output The SHA-1 checksum result. This must be a writable + * buffer of size \c 20 Bytes. + * + */ +MBEDTLS_DEPRECATED void mbedtls_sha1( const unsigned char *input, + size_t ilen, + unsigned char output[20] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief The SHA-1 checkup routine. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \return \c 0 on success. + * \return \c 1 on failure. + * + */ +int mbedtls_sha1_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_sha1.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/sha256.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/sha256.h new file mode 100644 index 0000000..73d9544 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/sha256.h @@ -0,0 +1,295 @@ +/** + * \file sha256.h + * + * \brief This file contains SHA-224 and SHA-256 definitions and functions. + * + * The Secure Hash Algorithms 224 and 256 (SHA-224 and SHA-256) cryptographic + * hash functions are defined in FIPS 180-4: Secure Hash Standard (SHS). + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_SHA256_H +#define MBEDTLS_SHA256_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +/* MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED -0x0037 /**< SHA-256 hardware accelerator failed */ +#define MBEDTLS_ERR_SHA256_BAD_INPUT_DATA -0x0074 /**< SHA-256 input data was malformed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_SHA256_ALT) +// Regular implementation +// + +/** + * \brief The SHA-256 context structure. + * + * The structure is used both for SHA-256 and for SHA-224 + * checksum calculations. The choice between these two is + * made in the call to mbedtls_sha256_starts_ret(). + */ +typedef struct mbedtls_sha256_context +{ + uint32_t total[2]; /*!< The number of Bytes processed. */ + uint32_t state[8]; /*!< The intermediate digest state. */ + unsigned char buffer[64]; /*!< The data block being processed. */ + int is224; /*!< Determines which function to use: + 0: Use SHA-256, or 1: Use SHA-224. */ +} +mbedtls_sha256_context; + +#else /* MBEDTLS_SHA256_ALT */ +#include "sha256_alt.h" +#endif /* MBEDTLS_SHA256_ALT */ + +/** + * \brief This function initializes a SHA-256 context. + * + * \param ctx The SHA-256 context to initialize. This must not be \c NULL. + */ +void mbedtls_sha256_init( mbedtls_sha256_context *ctx ); + +/** + * \brief This function clears a SHA-256 context. + * + * \param ctx The SHA-256 context to clear. This may be \c NULL, in which + * case this function returns immediately. If it is not \c NULL, + * it must point to an initialized SHA-256 context. + */ +void mbedtls_sha256_free( mbedtls_sha256_context *ctx ); + +/** + * \brief This function clones the state of a SHA-256 context. + * + * \param dst The destination context. This must be initialized. + * \param src The context to clone. This must be initialized. + */ +void mbedtls_sha256_clone( mbedtls_sha256_context *dst, + const mbedtls_sha256_context *src ); + +/** + * \brief This function starts a SHA-224 or SHA-256 checksum + * calculation. + * + * \param ctx The context to use. This must be initialized. + * \param is224 This determines which function to use. This must be + * either \c 0 for SHA-256, or \c 1 for SHA-224. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha256_starts_ret( mbedtls_sha256_context *ctx, int is224 ); + +/** + * \brief This function feeds an input buffer into an ongoing + * SHA-256 checksum calculation. + * + * \param ctx The SHA-256 context. This must be initialized + * and have a hash operation started. + * \param input The buffer holding the data. This must be a readable + * buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha256_update_ret( mbedtls_sha256_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-256 operation, and writes + * the result to the output buffer. + * + * \param ctx The SHA-256 context. This must be initialized + * and have a hash operation started. + * \param output The SHA-224 or SHA-256 checksum result. + * This must be a writable buffer of length \c 32 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha256_finish_ret( mbedtls_sha256_context *ctx, + unsigned char output[32] ); + +/** + * \brief This function processes a single data block within + * the ongoing SHA-256 computation. This function is for + * internal use only. + * + * \param ctx The SHA-256 context. This must be initialized. + * \param data The buffer holding one block of data. This must + * be a readable buffer of length \c 64 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_internal_sha256_process( mbedtls_sha256_context *ctx, + const unsigned char data[64] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function starts a SHA-224 or SHA-256 checksum + * calculation. + * + * \deprecated Superseded by mbedtls_sha256_starts_ret() in 2.7.0. + * + * \param ctx The context to use. This must be initialized. + * \param is224 Determines which function to use. This must be + * either \c 0 for SHA-256, or \c 1 for SHA-224. + */ +MBEDTLS_DEPRECATED void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, + int is224 ); + +/** + * \brief This function feeds an input buffer into an ongoing + * SHA-256 checksum calculation. + * + * \deprecated Superseded by mbedtls_sha256_update_ret() in 2.7.0. + * + * \param ctx The SHA-256 context to use. This must be + * initialized and have a hash operation started. + * \param input The buffer holding the data. This must be a readable + * buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + */ +MBEDTLS_DEPRECATED void mbedtls_sha256_update( mbedtls_sha256_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-256 operation, and writes + * the result to the output buffer. + * + * \deprecated Superseded by mbedtls_sha256_finish_ret() in 2.7.0. + * + * \param ctx The SHA-256 context. This must be initialized and + * have a hash operation started. + * \param output The SHA-224 or SHA-256 checksum result. This must be + * a writable buffer of length \c 32 Bytes. + */ +MBEDTLS_DEPRECATED void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, + unsigned char output[32] ); + +/** + * \brief This function processes a single data block within + * the ongoing SHA-256 computation. This function is for + * internal use only. + * + * \deprecated Superseded by mbedtls_internal_sha256_process() in 2.7.0. + * + * \param ctx The SHA-256 context. This must be initialized. + * \param data The buffer holding one block of data. This must be + * a readable buffer of size \c 64 Bytes. + */ +MBEDTLS_DEPRECATED void mbedtls_sha256_process( mbedtls_sha256_context *ctx, + const unsigned char data[64] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief This function calculates the SHA-224 or SHA-256 + * checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-256 result is calculated as + * output = SHA-256(input buffer). + * + * \param input The buffer holding the data. This must be a readable + * buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * \param output The SHA-224 or SHA-256 checksum result. This must + * be a writable buffer of length \c 32 Bytes. + * \param is224 Determines which function to use. This must be + * either \c 0 for SHA-256, or \c 1 for SHA-224. + */ +int mbedtls_sha256_ret( const unsigned char *input, + size_t ilen, + unsigned char output[32], + int is224 ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif + +/** + * \brief This function calculates the SHA-224 or SHA-256 checksum + * of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-256 result is calculated as + * output = SHA-256(input buffer). + * + * \deprecated Superseded by mbedtls_sha256_ret() in 2.7.0. + * + * \param input The buffer holding the data. This must be a readable + * buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * \param output The SHA-224 or SHA-256 checksum result. This must be + * a writable buffer of length \c 32 Bytes. + * \param is224 Determines which function to use. This must be either + * \c 0 for SHA-256, or \c 1 for SHA-224. + */ +MBEDTLS_DEPRECATED void mbedtls_sha256( const unsigned char *input, + size_t ilen, + unsigned char output[32], + int is224 ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief The SHA-224 and SHA-256 checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_sha256_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_sha256.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/sha512.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/sha512.h new file mode 100644 index 0000000..9036ed4 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/sha512.h @@ -0,0 +1,314 @@ +/** + * \file sha512.h + * \brief This file contains SHA-384 and SHA-512 definitions and functions. + * + * The Secure Hash Algorithms 384 and 512 (SHA-384 and SHA-512) cryptographic + * hash functions are defined in FIPS 180-4: Secure Hash Standard (SHS). + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_SHA512_H +#define MBEDTLS_SHA512_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +/* MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED -0x0039 /**< SHA-512 hardware accelerator failed */ +#define MBEDTLS_ERR_SHA512_BAD_INPUT_DATA -0x0075 /**< SHA-512 input data was malformed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_SHA512_ALT) +// Regular implementation +// + +/** + * \brief The SHA-512 context structure. + * + * The structure is used both for SHA-384 and for SHA-512 + * checksum calculations. The choice between these two is + * made in the call to mbedtls_sha512_starts_ret(). + */ +typedef struct mbedtls_sha512_context +{ + uint64_t total[2]; /*!< The number of Bytes processed. */ + uint64_t state[8]; /*!< The intermediate digest state. */ + unsigned char buffer[128]; /*!< The data block being processed. */ +#if !defined(MBEDTLS_SHA512_NO_SHA384) + int is384; /*!< Determines which function to use: + 0: Use SHA-512, or 1: Use SHA-384. */ +#endif +} +mbedtls_sha512_context; + +#else /* MBEDTLS_SHA512_ALT */ +#include "sha512_alt.h" +#endif /* MBEDTLS_SHA512_ALT */ + +/** + * \brief This function initializes a SHA-512 context. + * + * \param ctx The SHA-512 context to initialize. This must + * not be \c NULL. + */ +void mbedtls_sha512_init( mbedtls_sha512_context *ctx ); + +/** + * \brief This function clears a SHA-512 context. + * + * \param ctx The SHA-512 context to clear. This may be \c NULL, + * in which case this function does nothing. If it + * is not \c NULL, it must point to an initialized + * SHA-512 context. + */ +void mbedtls_sha512_free( mbedtls_sha512_context *ctx ); + +/** + * \brief This function clones the state of a SHA-512 context. + * + * \param dst The destination context. This must be initialized. + * \param src The context to clone. This must be initialized. + */ +void mbedtls_sha512_clone( mbedtls_sha512_context *dst, + const mbedtls_sha512_context *src ); + +/** + * \brief This function starts a SHA-384 or SHA-512 checksum + * calculation. + * + * \param ctx The SHA-512 context to use. This must be initialized. + * \param is384 Determines which function to use. This must be + * either \c 0 for SHA-512, or \c 1 for SHA-384. + * + * \note When \c MBEDTLS_SHA512_NO_SHA384 is defined, \p is384 must + * be \c 0, or the function will return + * #MBEDTLS_ERR_SHA512_BAD_INPUT_DATA. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha512_starts_ret( mbedtls_sha512_context *ctx, int is384 ); + +/** + * \brief This function feeds an input buffer into an ongoing + * SHA-512 checksum calculation. + * + * \param ctx The SHA-512 context. This must be initialized + * and have a hash operation started. + * \param input The buffer holding the input data. This must + * be a readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha512_update_ret( mbedtls_sha512_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-512 operation, and writes + * the result to the output buffer. This function is for + * internal use only. + * + * \param ctx The SHA-512 context. This must be initialized + * and have a hash operation started. + * \param output The SHA-384 or SHA-512 checksum result. + * This must be a writable buffer of length \c 64 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha512_finish_ret( mbedtls_sha512_context *ctx, + unsigned char output[64] ); + +/** + * \brief This function processes a single data block within + * the ongoing SHA-512 computation. + * + * \param ctx The SHA-512 context. This must be initialized. + * \param data The buffer holding one block of data. This + * must be a readable buffer of length \c 128 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx, + const unsigned char data[128] ); +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function starts a SHA-384 or SHA-512 checksum + * calculation. + * + * \deprecated Superseded by mbedtls_sha512_starts_ret() in 2.7.0 + * + * \param ctx The SHA-512 context to use. This must be initialized. + * \param is384 Determines which function to use. This must be either + * \c 0 for SHA-512 or \c 1 for SHA-384. + * + * \note When \c MBEDTLS_SHA512_NO_SHA384 is defined, \p is384 must + * be \c 0, or the function will fail to work. + */ +MBEDTLS_DEPRECATED void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, + int is384 ); + +/** + * \brief This function feeds an input buffer into an ongoing + * SHA-512 checksum calculation. + * + * \deprecated Superseded by mbedtls_sha512_update_ret() in 2.7.0. + * + * \param ctx The SHA-512 context. This must be initialized + * and have a hash operation started. + * \param input The buffer holding the data. This must be a readable + * buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + */ +MBEDTLS_DEPRECATED void mbedtls_sha512_update( mbedtls_sha512_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-512 operation, and writes + * the result to the output buffer. + * + * \deprecated Superseded by mbedtls_sha512_finish_ret() in 2.7.0. + * + * \param ctx The SHA-512 context. This must be initialized + * and have a hash operation started. + * \param output The SHA-384 or SHA-512 checksum result. This must + * be a writable buffer of size \c 64 Bytes. + */ +MBEDTLS_DEPRECATED void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, + unsigned char output[64] ); + +/** + * \brief This function processes a single data block within + * the ongoing SHA-512 computation. This function is for + * internal use only. + * + * \deprecated Superseded by mbedtls_internal_sha512_process() in 2.7.0. + * + * \param ctx The SHA-512 context. This must be initialized. + * \param data The buffer holding one block of data. This must be + * a readable buffer of length \c 128 Bytes. + */ +MBEDTLS_DEPRECATED void mbedtls_sha512_process( + mbedtls_sha512_context *ctx, + const unsigned char data[128] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief This function calculates the SHA-512 or SHA-384 + * checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-512 result is calculated as + * output = SHA-512(input buffer). + * + * \param input The buffer holding the input data. This must be + * a readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * \param output The SHA-384 or SHA-512 checksum result. + * This must be a writable buffer of length \c 64 Bytes. + * \param is384 Determines which function to use. This must be either + * \c 0 for SHA-512, or \c 1 for SHA-384. + * + * \note When \c MBEDTLS_SHA512_NO_SHA384 is defined, \p is384 must + * be \c 0, or the function will return + * #MBEDTLS_ERR_SHA512_BAD_INPUT_DATA. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha512_ret( const unsigned char *input, + size_t ilen, + unsigned char output[64], + int is384 ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif + +/** + * \brief This function calculates the SHA-512 or SHA-384 + * checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-512 result is calculated as + * output = SHA-512(input buffer). + * + * \deprecated Superseded by mbedtls_sha512_ret() in 2.7.0 + * + * \param input The buffer holding the data. This must be a + * readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * \param output The SHA-384 or SHA-512 checksum result. This must + * be a writable buffer of length \c 64 Bytes. + * \param is384 Determines which function to use. This must be either + * \c 0 for SHA-512, or \c 1 for SHA-384. + * + * \note When \c MBEDTLS_SHA512_NO_SHA384 is defined, \p is384 must + * be \c 0, or the function will fail to work. + */ +MBEDTLS_DEPRECATED void mbedtls_sha512( const unsigned char *input, + size_t ilen, + unsigned char output[64], + int is384 ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_SELF_TEST) + + /** + * \brief The SHA-384 or SHA-512 checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_sha512_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_sha512.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ssl.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ssl.h new file mode 100644 index 0000000..1b4e163 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ssl.h @@ -0,0 +1,4346 @@ +/** + * \file ssl.h + * + * \brief SSL/TLS functions. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_SSL_H +#define MBEDTLS_SSL_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/bignum.h" +#include "mbedtls/ecp.h" + +#include "mbedtls/ssl_ciphersuites.h" + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#include "mbedtls/x509_crt.h" +#include "mbedtls/x509_crl.h" +#endif + +#if defined(MBEDTLS_DHM_C) +#include "mbedtls/dhm.h" +#endif + +#if defined(MBEDTLS_ECDH_C) +#include "mbedtls/ecdh.h" +#endif + +#if defined(MBEDTLS_ZLIB_SUPPORT) + +#if defined(MBEDTLS_DEPRECATED_WARNING) +#warning "Record compression support via MBEDTLS_ZLIB_SUPPORT is deprecated and will be removed in the next major revision of the library" +#endif + +#if defined(MBEDTLS_DEPRECATED_REMOVED) +#error "Record compression support via MBEDTLS_ZLIB_SUPPORT is deprecated and cannot be used if MBEDTLS_DEPRECATED_REMOVED is set" +#endif + +#include "zlib.h" +#endif + +#if defined(MBEDTLS_HAVE_TIME) +#include "mbedtls/platform_time.h" +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +/* + * SSL Error codes + */ +#define MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE -0x7080 /**< The requested feature is not available. */ +#define MBEDTLS_ERR_SSL_BAD_INPUT_DATA -0x7100 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_SSL_INVALID_MAC -0x7180 /**< Verification of the message MAC failed. */ +#define MBEDTLS_ERR_SSL_INVALID_RECORD -0x7200 /**< An invalid SSL record was received. */ +#define MBEDTLS_ERR_SSL_CONN_EOF -0x7280 /**< The connection indicated an EOF. */ +#define MBEDTLS_ERR_SSL_UNKNOWN_CIPHER -0x7300 /**< An unknown cipher was received. */ +#define MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN -0x7380 /**< The server has no ciphersuites in common with the client. */ +#define MBEDTLS_ERR_SSL_NO_RNG -0x7400 /**< No RNG was provided to the SSL module. */ +#define MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE -0x7480 /**< No client certification received from the client, but required by the authentication mode. */ +#define MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE -0x7500 /**< Our own certificate(s) is/are too large to send in an SSL message. */ +#define MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED -0x7580 /**< The own certificate is not set, but needed by the server. */ +#define MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED -0x7600 /**< The own private key or pre-shared key is not set, but needed. */ +#define MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED -0x7680 /**< No CA Chain is set, but required to operate. */ +#define MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE -0x7700 /**< An unexpected message was received from our peer. */ +#define MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE -0x7780 /**< A fatal alert message was received from our peer. */ +#define MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED -0x7800 /**< Verification of our peer failed. */ +#define MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY -0x7880 /**< The peer notified us that the connection is going to be closed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO -0x7900 /**< Processing of the ClientHello handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO -0x7980 /**< Processing of the ServerHello handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE -0x7A00 /**< Processing of the Certificate handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST -0x7A80 /**< Processing of the CertificateRequest handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE -0x7B00 /**< Processing of the ServerKeyExchange handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE -0x7B80 /**< Processing of the ServerHelloDone handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE -0x7C00 /**< Processing of the ClientKeyExchange handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP -0x7C80 /**< Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Read Public. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS -0x7D00 /**< Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Calculate Secret. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY -0x7D80 /**< Processing of the CertificateVerify handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC -0x7E00 /**< Processing of the ChangeCipherSpec handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_FINISHED -0x7E80 /**< Processing of the Finished handshake message failed. */ +#define MBEDTLS_ERR_SSL_ALLOC_FAILED -0x7F00 /**< Memory allocation failed */ +#define MBEDTLS_ERR_SSL_HW_ACCEL_FAILED -0x7F80 /**< Hardware acceleration function returned with error */ +#define MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH -0x6F80 /**< Hardware acceleration function skipped / left alone data */ +#define MBEDTLS_ERR_SSL_COMPRESSION_FAILED -0x6F00 /**< Processing of the compression / decompression failed */ +#define MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION -0x6E80 /**< Handshake protocol not within min/max boundaries */ +#define MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET -0x6E00 /**< Processing of the NewSessionTicket handshake message failed. */ +#define MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED -0x6D80 /**< Session ticket has expired. */ +#define MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH -0x6D00 /**< Public key type mismatch (eg, asked for RSA key exchange and presented EC key) */ +#define MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY -0x6C80 /**< Unknown identity received (eg, PSK identity) */ +#define MBEDTLS_ERR_SSL_INTERNAL_ERROR -0x6C00 /**< Internal error (eg, unexpected failure in lower-level module) */ +#define MBEDTLS_ERR_SSL_COUNTER_WRAPPING -0x6B80 /**< A counter would wrap (eg, too many messages exchanged). */ +#define MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO -0x6B00 /**< Unexpected message at ServerHello in renegotiation. */ +#define MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED -0x6A80 /**< DTLS client must retry for hello verification */ +#define MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL -0x6A00 /**< A buffer is too small to receive or write a message */ +#define MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE -0x6980 /**< None of the common ciphersuites is usable (eg, no suitable certificate, see debug messages). */ +#define MBEDTLS_ERR_SSL_WANT_READ -0x6900 /**< No data of requested type currently available on underlying transport. */ +#define MBEDTLS_ERR_SSL_WANT_WRITE -0x6880 /**< Connection requires a write call. */ +#define MBEDTLS_ERR_SSL_TIMEOUT -0x6800 /**< The operation timed out. */ +#define MBEDTLS_ERR_SSL_CLIENT_RECONNECT -0x6780 /**< The client initiated a reconnect from the same port. */ +#define MBEDTLS_ERR_SSL_UNEXPECTED_RECORD -0x6700 /**< Record header looks valid but is not expected. */ +#define MBEDTLS_ERR_SSL_NON_FATAL -0x6680 /**< The alert message received indicates a non-fatal error. */ +#define MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH -0x6600 /**< Couldn't set the hash for verifying CertificateVerify */ +#define MBEDTLS_ERR_SSL_CONTINUE_PROCESSING -0x6580 /**< Internal-only message signaling that further message-processing should be done */ +#define MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS -0x6500 /**< The asynchronous operation is not completed yet. */ +#define MBEDTLS_ERR_SSL_EARLY_MESSAGE -0x6480 /**< Internal-only message signaling that a message arrived early. */ +#define MBEDTLS_ERR_SSL_UNEXPECTED_CID -0x6000 /**< An encrypted DTLS-frame with an unexpected CID was received. */ +#define MBEDTLS_ERR_SSL_VERSION_MISMATCH -0x5F00 /**< An operation failed due to an unexpected version or configuration. */ +#define MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS -0x7000 /**< A cryptographic operation is in progress. Try again later. */ +#define MBEDTLS_ERR_SSL_BAD_CONFIG -0x5E80 /**< Invalid value in SSL config */ + +/* + * Various constants + */ +#define MBEDTLS_SSL_MAJOR_VERSION_3 3 +#define MBEDTLS_SSL_MINOR_VERSION_0 0 /*!< SSL v3.0 */ +#define MBEDTLS_SSL_MINOR_VERSION_1 1 /*!< TLS v1.0 */ +#define MBEDTLS_SSL_MINOR_VERSION_2 2 /*!< TLS v1.1 */ +#define MBEDTLS_SSL_MINOR_VERSION_3 3 /*!< TLS v1.2 */ +#define MBEDTLS_SSL_MINOR_VERSION_4 4 /*!< TLS v1.3 (experimental) */ + +#define MBEDTLS_SSL_TRANSPORT_STREAM 0 /*!< TLS */ +#define MBEDTLS_SSL_TRANSPORT_DATAGRAM 1 /*!< DTLS */ + +#define MBEDTLS_SSL_MAX_HOST_NAME_LEN 255 /*!< Maximum host name defined in RFC 1035 */ +#define MBEDTLS_SSL_MAX_ALPN_NAME_LEN 255 /*!< Maximum size in bytes of a protocol name in alpn ext., RFC 7301 */ + +#define MBEDTLS_SSL_MAX_ALPN_LIST_LEN 65535 /*!< Maximum size in bytes of list in alpn ext., RFC 7301 */ + +/* RFC 6066 section 4, see also mfl_code_to_length in ssl_tls.c + * NONE must be zero so that memset()ing structure to zero works */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_NONE 0 /*!< don't use this extension */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_512 1 /*!< MaxFragmentLength 2^9 */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_1024 2 /*!< MaxFragmentLength 2^10 */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_2048 3 /*!< MaxFragmentLength 2^11 */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_4096 4 /*!< MaxFragmentLength 2^12 */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_INVALID 5 /*!< first invalid value */ + +#define MBEDTLS_SSL_IS_CLIENT 0 +#define MBEDTLS_SSL_IS_SERVER 1 + +#define MBEDTLS_SSL_IS_NOT_FALLBACK 0 +#define MBEDTLS_SSL_IS_FALLBACK 1 + +#define MBEDTLS_SSL_EXTENDED_MS_DISABLED 0 +#define MBEDTLS_SSL_EXTENDED_MS_ENABLED 1 + +#define MBEDTLS_SSL_CID_DISABLED 0 +#define MBEDTLS_SSL_CID_ENABLED 1 + +#define MBEDTLS_SSL_ETM_DISABLED 0 +#define MBEDTLS_SSL_ETM_ENABLED 1 + +#define MBEDTLS_SSL_COMPRESS_NULL 0 +#define MBEDTLS_SSL_COMPRESS_DEFLATE 1 + +#define MBEDTLS_SSL_VERIFY_NONE 0 +#define MBEDTLS_SSL_VERIFY_OPTIONAL 1 +#define MBEDTLS_SSL_VERIFY_REQUIRED 2 +#define MBEDTLS_SSL_VERIFY_UNSET 3 /* Used only for sni_authmode */ + +#define MBEDTLS_SSL_LEGACY_RENEGOTIATION 0 +#define MBEDTLS_SSL_SECURE_RENEGOTIATION 1 + +#define MBEDTLS_SSL_RENEGOTIATION_DISABLED 0 +#define MBEDTLS_SSL_RENEGOTIATION_ENABLED 1 + +#define MBEDTLS_SSL_ANTI_REPLAY_DISABLED 0 +#define MBEDTLS_SSL_ANTI_REPLAY_ENABLED 1 + +#define MBEDTLS_SSL_RENEGOTIATION_NOT_ENFORCED -1 +#define MBEDTLS_SSL_RENEGO_MAX_RECORDS_DEFAULT 16 + +#define MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION 0 +#define MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION 1 +#define MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE 2 + +#define MBEDTLS_SSL_TRUNC_HMAC_DISABLED 0 +#define MBEDTLS_SSL_TRUNC_HMAC_ENABLED 1 +#define MBEDTLS_SSL_TRUNCATED_HMAC_LEN 10 /* 80 bits, rfc 6066 section 7 */ + +#define MBEDTLS_SSL_SESSION_TICKETS_DISABLED 0 +#define MBEDTLS_SSL_SESSION_TICKETS_ENABLED 1 + +#define MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED 0 +#define MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED 1 + +#define MBEDTLS_SSL_ARC4_ENABLED 0 +#define MBEDTLS_SSL_ARC4_DISABLED 1 + +#define MBEDTLS_SSL_PRESET_DEFAULT 0 +#define MBEDTLS_SSL_PRESET_SUITEB 2 + +#define MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED 1 +#define MBEDTLS_SSL_CERT_REQ_CA_LIST_DISABLED 0 + +#define MBEDTLS_SSL_DTLS_SRTP_MKI_UNSUPPORTED 0 +#define MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED 1 + +/* + * Default range for DTLS retransmission timer value, in milliseconds. + * RFC 6347 4.2.4.1 says from 1 second to 60 seconds. + */ +#define MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN 1000 +#define MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX 60000 + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME) +#define MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME 86400 /**< Lifetime of session tickets (if enabled) */ +#endif + +/* + * Maximum fragment length in bytes, + * determines the size of each of the two internal I/O buffers. + * + * Note: the RFC defines the default size of SSL / TLS messages. If you + * change the value here, other clients / servers may not be able to + * communicate with you anymore. Only change this value if you control + * both sides of the connection and have it reduced at both sides, or + * if you're using the Max Fragment Length extension and you know all your + * peers are using it too! + */ +#if !defined(MBEDTLS_SSL_MAX_CONTENT_LEN) +#define MBEDTLS_SSL_MAX_CONTENT_LEN 16384 /**< Size of the input / output buffer */ +#endif + +#if !defined(MBEDTLS_SSL_IN_CONTENT_LEN) +#define MBEDTLS_SSL_IN_CONTENT_LEN MBEDTLS_SSL_MAX_CONTENT_LEN +#endif + +#if !defined(MBEDTLS_SSL_OUT_CONTENT_LEN) +#define MBEDTLS_SSL_OUT_CONTENT_LEN MBEDTLS_SSL_MAX_CONTENT_LEN +#endif + +/* + * Maximum number of heap-allocated bytes for the purpose of + * DTLS handshake message reassembly and future message buffering. + */ +#if !defined(MBEDTLS_SSL_DTLS_MAX_BUFFERING) +#define MBEDTLS_SSL_DTLS_MAX_BUFFERING 32768 +#endif + +/* + * Maximum length of CIDs for incoming and outgoing messages. + */ +#if !defined(MBEDTLS_SSL_CID_IN_LEN_MAX) +#define MBEDTLS_SSL_CID_IN_LEN_MAX 32 +#endif + +#if !defined(MBEDTLS_SSL_CID_OUT_LEN_MAX) +#define MBEDTLS_SSL_CID_OUT_LEN_MAX 32 +#endif + +#if !defined(MBEDTLS_SSL_CID_PADDING_GRANULARITY) +#define MBEDTLS_SSL_CID_PADDING_GRANULARITY 16 +#endif + +#if !defined(MBEDTLS_SSL_TLS1_3_PADDING_GRANULARITY) +#define MBEDTLS_SSL_TLS1_3_PADDING_GRANULARITY 1 +#endif + +/* \} name SECTION: Module settings */ + +/* + * Length of the verify data for secure renegotiation + */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) +#define MBEDTLS_SSL_VERIFY_DATA_MAX_LEN 36 +#else +#define MBEDTLS_SSL_VERIFY_DATA_MAX_LEN 12 +#endif + +/* + * Signaling ciphersuite values (SCSV) + */ +#define MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO 0xFF /**< renegotiation info ext */ +#define MBEDTLS_SSL_FALLBACK_SCSV_VALUE 0x5600 /**< RFC 7507 section 2 */ + +/* + * Supported Signature and Hash algorithms (For TLS 1.2) + * RFC 5246 section 7.4.1.4.1 + */ +#define MBEDTLS_SSL_HASH_NONE 0 +#define MBEDTLS_SSL_HASH_MD5 1 +#define MBEDTLS_SSL_HASH_SHA1 2 +#define MBEDTLS_SSL_HASH_SHA224 3 +#define MBEDTLS_SSL_HASH_SHA256 4 +#define MBEDTLS_SSL_HASH_SHA384 5 +#define MBEDTLS_SSL_HASH_SHA512 6 + +#define MBEDTLS_SSL_SIG_ANON 0 +#define MBEDTLS_SSL_SIG_RSA 1 +#define MBEDTLS_SSL_SIG_ECDSA 3 + +/* + * Client Certificate Types + * RFC 5246 section 7.4.4 plus RFC 4492 section 5.5 + */ +#define MBEDTLS_SSL_CERT_TYPE_RSA_SIGN 1 +#define MBEDTLS_SSL_CERT_TYPE_ECDSA_SIGN 64 + +/* + * Message, alert and handshake types + */ +#define MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC 20 +#define MBEDTLS_SSL_MSG_ALERT 21 +#define MBEDTLS_SSL_MSG_HANDSHAKE 22 +#define MBEDTLS_SSL_MSG_APPLICATION_DATA 23 +#define MBEDTLS_SSL_MSG_CID 25 + +#define MBEDTLS_SSL_ALERT_LEVEL_WARNING 1 +#define MBEDTLS_SSL_ALERT_LEVEL_FATAL 2 + +#define MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY 0 /* 0x00 */ +#define MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE 10 /* 0x0A */ +#define MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC 20 /* 0x14 */ +#define MBEDTLS_SSL_ALERT_MSG_DECRYPTION_FAILED 21 /* 0x15 */ +#define MBEDTLS_SSL_ALERT_MSG_RECORD_OVERFLOW 22 /* 0x16 */ +#define MBEDTLS_SSL_ALERT_MSG_DECOMPRESSION_FAILURE 30 /* 0x1E */ +#define MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE 40 /* 0x28 */ +#define MBEDTLS_SSL_ALERT_MSG_NO_CERT 41 /* 0x29 */ +#define MBEDTLS_SSL_ALERT_MSG_BAD_CERT 42 /* 0x2A */ +#define MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT 43 /* 0x2B */ +#define MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED 44 /* 0x2C */ +#define MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED 45 /* 0x2D */ +#define MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN 46 /* 0x2E */ +#define MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER 47 /* 0x2F */ +#define MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA 48 /* 0x30 */ +#define MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED 49 /* 0x31 */ +#define MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR 50 /* 0x32 */ +#define MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR 51 /* 0x33 */ +#define MBEDTLS_SSL_ALERT_MSG_EXPORT_RESTRICTION 60 /* 0x3C */ +#define MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION 70 /* 0x46 */ +#define MBEDTLS_SSL_ALERT_MSG_INSUFFICIENT_SECURITY 71 /* 0x47 */ +#define MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR 80 /* 0x50 */ +#define MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK 86 /* 0x56 */ +#define MBEDTLS_SSL_ALERT_MSG_USER_CANCELED 90 /* 0x5A */ +#define MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION 100 /* 0x64 */ +#define MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT 110 /* 0x6E */ +#define MBEDTLS_SSL_ALERT_MSG_UNRECOGNIZED_NAME 112 /* 0x70 */ +#define MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY 115 /* 0x73 */ +#define MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL 120 /* 0x78 */ + +#define MBEDTLS_SSL_HS_HELLO_REQUEST 0 +#define MBEDTLS_SSL_HS_CLIENT_HELLO 1 +#define MBEDTLS_SSL_HS_SERVER_HELLO 2 +#define MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST 3 +#define MBEDTLS_SSL_HS_NEW_SESSION_TICKET 4 +#define MBEDTLS_SSL_HS_CERTIFICATE 11 +#define MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE 12 +#define MBEDTLS_SSL_HS_CERTIFICATE_REQUEST 13 +#define MBEDTLS_SSL_HS_SERVER_HELLO_DONE 14 +#define MBEDTLS_SSL_HS_CERTIFICATE_VERIFY 15 +#define MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE 16 +#define MBEDTLS_SSL_HS_FINISHED 20 + +/* + * TLS extensions + */ +#define MBEDTLS_TLS_EXT_SERVERNAME 0 +#define MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME 0 + +#define MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH 1 + +#define MBEDTLS_TLS_EXT_TRUNCATED_HMAC 4 + +#define MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES 10 +#define MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS 11 + +#define MBEDTLS_TLS_EXT_SIG_ALG 13 + +#define MBEDTLS_TLS_EXT_USE_SRTP 14 + +#define MBEDTLS_TLS_EXT_ALPN 16 + +#define MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC 22 /* 0x16 */ +#define MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET 0x0017 /* 23 */ + +#define MBEDTLS_TLS_EXT_SESSION_TICKET 35 + +/* The value of the CID extension is still TBD as of + * draft-ietf-tls-dtls-connection-id-05 + * (https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05) */ +#define MBEDTLS_TLS_EXT_CID 254 /* TBD */ + +#define MBEDTLS_TLS_EXT_ECJPAKE_KKPP 256 /* experimental */ + +#define MBEDTLS_TLS_EXT_RENEGOTIATION_INFO 0xFF01 + +/* + * Size defines + */ +#if !defined(MBEDTLS_PSK_MAX_LEN) +#define MBEDTLS_PSK_MAX_LEN 32 /* 256 bits */ +#endif + +/* Dummy type used only for its size */ +union mbedtls_ssl_premaster_secret +{ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) + unsigned char _pms_rsa[48]; /* RFC 5246 8.1.1 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) + unsigned char _pms_dhm[MBEDTLS_MPI_MAX_SIZE]; /* RFC 5246 8.1.2 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + unsigned char _pms_ecdh[MBEDTLS_ECP_MAX_BYTES]; /* RFC 4492 5.10 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + unsigned char _pms_psk[4 + 2 * MBEDTLS_PSK_MAX_LEN]; /* RFC 4279 2 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + unsigned char _pms_dhe_psk[4 + MBEDTLS_MPI_MAX_SIZE + + MBEDTLS_PSK_MAX_LEN]; /* RFC 4279 3 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + unsigned char _pms_rsa_psk[52 + MBEDTLS_PSK_MAX_LEN]; /* RFC 4279 4 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + unsigned char _pms_ecdhe_psk[4 + MBEDTLS_ECP_MAX_BYTES + + MBEDTLS_PSK_MAX_LEN]; /* RFC 5489 2 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + unsigned char _pms_ecjpake[32]; /* Thread spec: SHA-256 output */ +#endif +}; + +#define MBEDTLS_PREMASTER_SIZE sizeof( union mbedtls_ssl_premaster_secret ) + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * SSL state machine + */ +typedef enum +{ + MBEDTLS_SSL_HELLO_REQUEST, + MBEDTLS_SSL_CLIENT_HELLO, + MBEDTLS_SSL_SERVER_HELLO, + MBEDTLS_SSL_SERVER_CERTIFICATE, + MBEDTLS_SSL_SERVER_KEY_EXCHANGE, + MBEDTLS_SSL_CERTIFICATE_REQUEST, + MBEDTLS_SSL_SERVER_HELLO_DONE, + MBEDTLS_SSL_CLIENT_CERTIFICATE, + MBEDTLS_SSL_CLIENT_KEY_EXCHANGE, + MBEDTLS_SSL_CERTIFICATE_VERIFY, + MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC, + MBEDTLS_SSL_CLIENT_FINISHED, + MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC, + MBEDTLS_SSL_SERVER_FINISHED, + MBEDTLS_SSL_FLUSH_BUFFERS, + MBEDTLS_SSL_HANDSHAKE_WRAPUP, + MBEDTLS_SSL_HANDSHAKE_OVER, + MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET, + MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT, +} +mbedtls_ssl_states; + +/* + * The tls_prf function types. + */ +typedef enum +{ + MBEDTLS_SSL_TLS_PRF_NONE, + MBEDTLS_SSL_TLS_PRF_SSL3, + MBEDTLS_SSL_TLS_PRF_TLS1, + MBEDTLS_SSL_TLS_PRF_SHA384, + MBEDTLS_SSL_TLS_PRF_SHA256 +} +mbedtls_tls_prf_types; +/** + * \brief Callback type: send data on the network. + * + * \note That callback may be either blocking or non-blocking. + * + * \param ctx Context for the send callback (typically a file descriptor) + * \param buf Buffer holding the data to send + * \param len Length of the data to send + * + * \return The callback must return the number of bytes sent if any, + * or a non-zero error code. + * If performing non-blocking I/O, \c MBEDTLS_ERR_SSL_WANT_WRITE + * must be returned when the operation would block. + * + * \note The callback is allowed to send fewer bytes than requested. + * It must always return the number of bytes actually sent. + */ +typedef int mbedtls_ssl_send_t( void *ctx, + const unsigned char *buf, + size_t len ); + +/** + * \brief Callback type: receive data from the network. + * + * \note That callback may be either blocking or non-blocking. + * + * \param ctx Context for the receive callback (typically a file + * descriptor) + * \param buf Buffer to write the received data to + * \param len Length of the receive buffer + * + * \return The callback must return the number of bytes received, + * or a non-zero error code. + * If performing non-blocking I/O, \c MBEDTLS_ERR_SSL_WANT_READ + * must be returned when the operation would block. + * + * \note The callback may receive fewer bytes than the length of the + * buffer. It must always return the number of bytes actually + * received and written to the buffer. + */ +typedef int mbedtls_ssl_recv_t( void *ctx, + unsigned char *buf, + size_t len ); + +/** + * \brief Callback type: receive data from the network, with timeout + * + * \note That callback must block until data is received, or the + * timeout delay expires, or the operation is interrupted by a + * signal. + * + * \param ctx Context for the receive callback (typically a file descriptor) + * \param buf Buffer to write the received data to + * \param len Length of the receive buffer + * \param timeout Maximum nomber of millisecondes to wait for data + * 0 means no timeout (potentially waiting forever) + * + * \return The callback must return the number of bytes received, + * or a non-zero error code: + * \c MBEDTLS_ERR_SSL_TIMEOUT if the operation timed out, + * \c MBEDTLS_ERR_SSL_WANT_READ if interrupted by a signal. + * + * \note The callback may receive fewer bytes than the length of the + * buffer. It must always return the number of bytes actually + * received and written to the buffer. + */ +typedef int mbedtls_ssl_recv_timeout_t( void *ctx, + unsigned char *buf, + size_t len, + uint32_t timeout ); +/** + * \brief Callback type: set a pair of timers/delays to watch + * + * \param ctx Context pointer + * \param int_ms Intermediate delay in milliseconds + * \param fin_ms Final delay in milliseconds + * 0 cancels the current timer. + * + * \note This callback must at least store the necessary information + * for the associated \c mbedtls_ssl_get_timer_t callback to + * return correct information. + * + * \note If using a event-driven style of programming, an event must + * be generated when the final delay is passed. The event must + * cause a call to \c mbedtls_ssl_handshake() with the proper + * SSL context to be scheduled. Care must be taken to ensure + * that at most one such call happens at a time. + * + * \note Only one timer at a time must be running. Calling this + * function while a timer is running must cancel it. Cancelled + * timers must not generate any event. + */ +typedef void mbedtls_ssl_set_timer_t( void * ctx, + uint32_t int_ms, + uint32_t fin_ms ); + +/** + * \brief Callback type: get status of timers/delays + * + * \param ctx Context pointer + * + * \return This callback must return: + * -1 if cancelled (fin_ms == 0), + * 0 if none of the delays have passed, + * 1 if only the intermediate delay has passed, + * 2 if the final delay has passed. + */ +typedef int mbedtls_ssl_get_timer_t( void * ctx ); + +/* Defined below */ +typedef struct mbedtls_ssl_session mbedtls_ssl_session; +typedef struct mbedtls_ssl_context mbedtls_ssl_context; +typedef struct mbedtls_ssl_config mbedtls_ssl_config; + +/* Defined in ssl_internal.h */ +typedef struct mbedtls_ssl_transform mbedtls_ssl_transform; +typedef struct mbedtls_ssl_handshake_params mbedtls_ssl_handshake_params; +typedef struct mbedtls_ssl_sig_hash_set_t mbedtls_ssl_sig_hash_set_t; +#if defined(MBEDTLS_X509_CRT_PARSE_C) +typedef struct mbedtls_ssl_key_cert mbedtls_ssl_key_cert; +#endif +#if defined(MBEDTLS_SSL_PROTO_DTLS) +typedef struct mbedtls_ssl_flight_item mbedtls_ssl_flight_item; +#endif + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * \brief Callback type: start external signature operation. + * + * This callback is called during an SSL handshake to start + * a signature decryption operation using an + * external processor. The parameter \p cert contains + * the public key; it is up to the callback function to + * determine how to access the associated private key. + * + * This function typically sends or enqueues a request, and + * does not wait for the operation to complete. This allows + * the handshake step to be non-blocking. + * + * The parameters \p ssl and \p cert are guaranteed to remain + * valid throughout the handshake. On the other hand, this + * function must save the contents of \p hash if the value + * is needed for later processing, because the \p hash buffer + * is no longer valid after this function returns. + * + * This function may call mbedtls_ssl_set_async_operation_data() + * to store an operation context for later retrieval + * by the resume or cancel callback. + * + * \note For RSA signatures, this function must produce output + * that is consistent with PKCS#1 v1.5 in the same way as + * mbedtls_rsa_pkcs1_sign(). Before the private key operation, + * apply the padding steps described in RFC 8017, section 9.2 + * "EMSA-PKCS1-v1_5" as follows. + * - If \p md_alg is #MBEDTLS_MD_NONE, apply the PKCS#1 v1.5 + * encoding, treating \p hash as the DigestInfo to be + * padded. In other words, apply EMSA-PKCS1-v1_5 starting + * from step 3, with `T = hash` and `tLen = hash_len`. + * - If `md_alg != MBEDTLS_MD_NONE`, apply the PKCS#1 v1.5 + * encoding, treating \p hash as the hash to be encoded and + * padded. In other words, apply EMSA-PKCS1-v1_5 starting + * from step 2, with `digestAlgorithm` obtained by calling + * mbedtls_oid_get_oid_by_md() on \p md_alg. + * + * \note For ECDSA signatures, the output format is the DER encoding + * `Ecdsa-Sig-Value` defined in + * [RFC 4492 section 5.4](https://tools.ietf.org/html/rfc4492#section-5.4). + * + * \param ssl The SSL connection instance. It should not be + * modified other than via + * mbedtls_ssl_set_async_operation_data(). + * \param cert Certificate containing the public key. + * In simple cases, this is one of the pointers passed to + * mbedtls_ssl_conf_own_cert() when configuring the SSL + * connection. However, if other callbacks are used, this + * property may not hold. For example, if an SNI callback + * is registered with mbedtls_ssl_conf_sni(), then + * this callback determines what certificate is used. + * \param md_alg Hash algorithm. + * \param hash Buffer containing the hash. This buffer is + * no longer valid when the function returns. + * \param hash_len Size of the \c hash buffer in bytes. + * + * \return 0 if the operation was started successfully and the SSL + * stack should call the resume callback immediately. + * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if the operation + * was started successfully and the SSL stack should return + * immediately without calling the resume callback yet. + * \return #MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH if the external + * processor does not support this key. The SSL stack will + * use the private key object instead. + * \return Any other error indicates a fatal failure and is + * propagated up the call chain. The callback should + * use \c MBEDTLS_ERR_PK_xxx error codes, and must not + * use \c MBEDTLS_ERR_SSL_xxx error codes except as + * directed in the documentation of this callback. + */ +typedef int mbedtls_ssl_async_sign_t( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *cert, + mbedtls_md_type_t md_alg, + const unsigned char *hash, + size_t hash_len ); + +/** + * \brief Callback type: start external decryption operation. + * + * This callback is called during an SSL handshake to start + * an RSA decryption operation using an + * external processor. The parameter \p cert contains + * the public key; it is up to the callback function to + * determine how to access the associated private key. + * + * This function typically sends or enqueues a request, and + * does not wait for the operation to complete. This allows + * the handshake step to be non-blocking. + * + * The parameters \p ssl and \p cert are guaranteed to remain + * valid throughout the handshake. On the other hand, this + * function must save the contents of \p input if the value + * is needed for later processing, because the \p input buffer + * is no longer valid after this function returns. + * + * This function may call mbedtls_ssl_set_async_operation_data() + * to store an operation context for later retrieval + * by the resume or cancel callback. + * + * \warning RSA decryption as used in TLS is subject to a potential + * timing side channel attack first discovered by Bleichenbacher + * in 1998. This attack can be remotely exploitable + * in practice. To avoid this attack, you must ensure that + * if the callback performs an RSA decryption, the time it + * takes to execute and return the result does not depend + * on whether the RSA decryption succeeded or reported + * invalid padding. + * + * \param ssl The SSL connection instance. It should not be + * modified other than via + * mbedtls_ssl_set_async_operation_data(). + * \param cert Certificate containing the public key. + * In simple cases, this is one of the pointers passed to + * mbedtls_ssl_conf_own_cert() when configuring the SSL + * connection. However, if other callbacks are used, this + * property may not hold. For example, if an SNI callback + * is registered with mbedtls_ssl_conf_sni(), then + * this callback determines what certificate is used. + * \param input Buffer containing the input ciphertext. This buffer + * is no longer valid when the function returns. + * \param input_len Size of the \p input buffer in bytes. + * + * \return 0 if the operation was started successfully and the SSL + * stack should call the resume callback immediately. + * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if the operation + * was started successfully and the SSL stack should return + * immediately without calling the resume callback yet. + * \return #MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH if the external + * processor does not support this key. The SSL stack will + * use the private key object instead. + * \return Any other error indicates a fatal failure and is + * propagated up the call chain. The callback should + * use \c MBEDTLS_ERR_PK_xxx error codes, and must not + * use \c MBEDTLS_ERR_SSL_xxx error codes except as + * directed in the documentation of this callback. + */ +typedef int mbedtls_ssl_async_decrypt_t( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *cert, + const unsigned char *input, + size_t input_len ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +/** + * \brief Callback type: resume external operation. + * + * This callback is called during an SSL handshake to resume + * an external operation started by the + * ::mbedtls_ssl_async_sign_t or + * ::mbedtls_ssl_async_decrypt_t callback. + * + * This function typically checks the status of a pending + * request or causes the request queue to make progress, and + * does not wait for the operation to complete. This allows + * the handshake step to be non-blocking. + * + * This function may call mbedtls_ssl_get_async_operation_data() + * to retrieve an operation context set by the start callback. + * It may call mbedtls_ssl_set_async_operation_data() to modify + * this context. + * + * Note that when this function returns a status other than + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS, it must free any + * resources associated with the operation. + * + * \param ssl The SSL connection instance. It should not be + * modified other than via + * mbedtls_ssl_set_async_operation_data(). + * \param output Buffer containing the output (signature or decrypted + * data) on success. + * \param output_len On success, number of bytes written to \p output. + * \param output_size Size of the \p output buffer in bytes. + * + * \return 0 if output of the operation is available in the + * \p output buffer. + * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if the operation + * is still in progress. Subsequent requests for progress + * on the SSL connection will call the resume callback + * again. + * \return Any other error means that the operation is aborted. + * The SSL handshake is aborted. The callback should + * use \c MBEDTLS_ERR_PK_xxx error codes, and must not + * use \c MBEDTLS_ERR_SSL_xxx error codes except as + * directed in the documentation of this callback. + */ +typedef int mbedtls_ssl_async_resume_t( mbedtls_ssl_context *ssl, + unsigned char *output, + size_t *output_len, + size_t output_size ); + +/** + * \brief Callback type: cancel external operation. + * + * This callback is called if an SSL connection is closed + * while an asynchronous operation is in progress. Note that + * this callback is not called if the + * ::mbedtls_ssl_async_resume_t callback has run and has + * returned a value other than + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS, since in that case + * the asynchronous operation has already completed. + * + * This function may call mbedtls_ssl_get_async_operation_data() + * to retrieve an operation context set by the start callback. + * + * \param ssl The SSL connection instance. It should not be + * modified. + */ +typedef void mbedtls_ssl_async_cancel_t( mbedtls_ssl_context *ssl ); +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) && \ + !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) +#define MBEDTLS_SSL_PEER_CERT_DIGEST_MAX_LEN 48 +#if defined(MBEDTLS_SHA256_C) +#define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE MBEDTLS_MD_SHA256 +#define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN 32 +#elif defined(MBEDTLS_SHA512_C) +#define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE MBEDTLS_MD_SHA384 +#define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN 48 +#elif defined(MBEDTLS_SHA1_C) +#define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE MBEDTLS_MD_SHA1 +#define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN 20 +#else +/* This is already checked in check_config.h, but be sure. */ +#error "Bad configuration - need SHA-1, SHA-256 or SHA-512 enabled to compute digest of peer CRT." +#endif +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED && + !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + +#if defined(MBEDTLS_SSL_DTLS_SRTP) + +#define MBEDTLS_TLS_SRTP_MAX_MKI_LENGTH 255 +#define MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH 4 +/* + * For code readability use a typedef for DTLS-SRTP profiles + * + * Use_srtp extension protection profiles values as defined in + * http://www.iana.org/assignments/srtp-protection/srtp-protection.xhtml + * + * Reminder: if this list is expanded mbedtls_ssl_check_srtp_profile_value + * must be updated too. + */ +#define MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_80 ( (uint16_t) 0x0001) +#define MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_32 ( (uint16_t) 0x0002) +#define MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_80 ( (uint16_t) 0x0005) +#define MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_32 ( (uint16_t) 0x0006) +/* This one is not iana defined, but for code readability. */ +#define MBEDTLS_TLS_SRTP_UNSET ( (uint16_t) 0x0000) + +typedef uint16_t mbedtls_ssl_srtp_profile; + +typedef struct mbedtls_dtls_srtp_info_t +{ + /*! The SRTP profile that was negotiated. */ + mbedtls_ssl_srtp_profile chosen_dtls_srtp_profile; + /*! The length of mki_value. */ + uint16_t mki_len; + /*! The mki_value used, with max size of 256 bytes. */ + unsigned char mki_value[MBEDTLS_TLS_SRTP_MAX_MKI_LENGTH]; +} +mbedtls_dtls_srtp_info; + +#endif /* MBEDTLS_SSL_DTLS_SRTP */ + +/* + * This structure is used for storing current session data. + * + * Note: when changing this definition, we need to check and update: + * - in tests/suites/test_suite_ssl.function: + * ssl_populate_session() and ssl_serialize_session_save_load() + * - in library/ssl_tls.c: + * mbedtls_ssl_session_init() and mbedtls_ssl_session_free() + * mbedtls_ssl_session_save() and ssl_session_load() + * ssl_session_copy() + */ +struct mbedtls_ssl_session +{ +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t start; /*!< starting time */ +#endif + int ciphersuite; /*!< chosen ciphersuite */ + int compression; /*!< chosen compression */ + size_t id_len; /*!< session id length */ + unsigned char id[32]; /*!< session identifier */ + unsigned char master[48]; /*!< the master secret */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + mbedtls_x509_crt *peer_cert; /*!< peer X.509 cert chain */ +#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + /*! The digest of the peer's end-CRT. This must be kept to detect CRT + * changes during renegotiation, mitigating the triple handshake attack. */ + unsigned char *peer_cert_digest; + size_t peer_cert_digest_len; + mbedtls_md_type_t peer_cert_digest_type; +#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + uint32_t verify_result; /*!< verification result */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) + unsigned char *ticket; /*!< RFC 5077 session ticket */ + size_t ticket_len; /*!< session ticket length */ + uint32_t ticket_lifetime; /*!< ticket lifetime hint */ +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + unsigned char mfl_code; /*!< MaxFragmentLength negotiated by peer */ +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + int trunc_hmac; /*!< flag for truncated hmac activation */ +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + int encrypt_then_mac; /*!< flag for EtM activation */ +#endif +}; + +/** + * SSL/TLS configuration to be shared between mbedtls_ssl_context structures. + */ +struct mbedtls_ssl_config +{ + /* Group items by size (largest first) to minimize padding overhead */ + + /* + * Pointers + */ + + const int *ciphersuite_list[4]; /*!< allowed ciphersuites per version */ + + /** Callback for printing debug output */ + void (*f_dbg)(void *, int, const char *, int, const char *); + void *p_dbg; /*!< context for the debug function */ + + /** Callback for getting (pseudo-)random numbers */ + int (*f_rng)(void *, unsigned char *, size_t); + void *p_rng; /*!< context for the RNG function */ + + /** Callback to retrieve a session from the cache */ + int (*f_get_cache)(void *, mbedtls_ssl_session *); + /** Callback to store a session into the cache */ + int (*f_set_cache)(void *, const mbedtls_ssl_session *); + void *p_cache; /*!< context for cache callbacks */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + /** Callback for setting cert according to SNI extension */ + int (*f_sni)(void *, mbedtls_ssl_context *, const unsigned char *, size_t); + void *p_sni; /*!< context for SNI callback */ +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + /** Callback to customize X.509 certificate chain verification */ + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *); + void *p_vrfy; /*!< context for X.509 verify calllback */ +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) + /** Callback to retrieve PSK key from identity */ + int (*f_psk)(void *, mbedtls_ssl_context *, const unsigned char *, size_t); + void *p_psk; /*!< context for PSK callback */ +#endif + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) + /** Callback to create & write a cookie for ClientHello veirifcation */ + int (*f_cookie_write)( void *, unsigned char **, unsigned char *, + const unsigned char *, size_t ); + /** Callback to verify validity of a ClientHello cookie */ + int (*f_cookie_check)( void *, const unsigned char *, size_t, + const unsigned char *, size_t ); + void *p_cookie; /*!< context for the cookie callbacks */ +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_SRV_C) + /** Callback to create & write a session ticket */ + int (*f_ticket_write)( void *, const mbedtls_ssl_session *, + unsigned char *, const unsigned char *, size_t *, uint32_t * ); + /** Callback to parse a session ticket into a session structure */ + int (*f_ticket_parse)( void *, mbedtls_ssl_session *, unsigned char *, size_t); + void *p_ticket; /*!< context for the ticket callbacks */ +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_EXPORT_KEYS) + /** Callback to export key block and master secret */ + int (*f_export_keys)( void *, const unsigned char *, + const unsigned char *, size_t, size_t, size_t ); + /** Callback to export key block, master secret, + * tls_prf and random bytes. Should replace f_export_keys */ + int (*f_export_keys_ext)( void *, const unsigned char *, + const unsigned char *, size_t, size_t, size_t, + const unsigned char[32], const unsigned char[32], + mbedtls_tls_prf_types ); + void *p_export_keys; /*!< context for key export callback */ +#endif + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + size_t cid_len; /*!< The length of CIDs for incoming DTLS records. */ +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + const mbedtls_x509_crt_profile *cert_profile; /*!< verification profile */ + mbedtls_ssl_key_cert *key_cert; /*!< own certificate/key pair(s) */ + mbedtls_x509_crt *ca_chain; /*!< trusted CAs */ + mbedtls_x509_crl *ca_crl; /*!< trusted CAs CRLs */ +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + mbedtls_x509_crt_ca_cb_t f_ca_cb; + void *p_ca_cb; +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_ssl_async_sign_t *f_async_sign_start; /*!< start asynchronous signature operation */ + mbedtls_ssl_async_decrypt_t *f_async_decrypt_start; /*!< start asynchronous decryption operation */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + mbedtls_ssl_async_resume_t *f_async_resume; /*!< resume asynchronous operation */ + mbedtls_ssl_async_cancel_t *f_async_cancel; /*!< cancel asynchronous operation */ + void *p_async_config_data; /*!< Configuration data set by mbedtls_ssl_conf_async_private_cb(). */ +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + const int *sig_hashes; /*!< allowed signature hashes */ +#endif + +#if defined(MBEDTLS_ECP_C) + const mbedtls_ecp_group_id *curve_list; /*!< allowed curves */ +#endif + +#if defined(MBEDTLS_DHM_C) + mbedtls_mpi dhm_P; /*!< prime modulus for DHM */ + mbedtls_mpi dhm_G; /*!< generator for DHM */ +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_key_handle_t psk_opaque; /*!< PSA key slot holding opaque PSK. + * This field should only be set via + * mbedtls_ssl_conf_psk_opaque(). + * If either no PSK or a raw PSK have + * been configured, this has value \c 0. */ +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + unsigned char *psk; /*!< The raw pre-shared key. This field should + * only be set via mbedtls_ssl_conf_psk(). + * If either no PSK or an opaque PSK + * have been configured, this has value NULL. */ + size_t psk_len; /*!< The length of the raw pre-shared key. + * This field should only be set via + * mbedtls_ssl_conf_psk(). + * Its value is non-zero if and only if + * \c psk is not \c NULL. */ + + unsigned char *psk_identity; /*!< The PSK identity for PSK negotiation. + * This field should only be set via + * mbedtls_ssl_conf_psk(). + * This is set if and only if either + * \c psk or \c psk_opaque are set. */ + size_t psk_identity_len;/*!< The length of PSK identity. + * This field should only be set via + * mbedtls_ssl_conf_psk(). + * Its value is non-zero if and only if + * \c psk is not \c NULL or \c psk_opaque + * is not \c 0. */ +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ + +#if defined(MBEDTLS_SSL_ALPN) + const char **alpn_list; /*!< ordered list of protocols */ +#endif + +#if defined(MBEDTLS_SSL_DTLS_SRTP) + /*! ordered list of supported srtp profile */ + const mbedtls_ssl_srtp_profile *dtls_srtp_profile_list; + /*! number of supported profiles */ + size_t dtls_srtp_profile_list_len; +#endif /* MBEDTLS_SSL_DTLS_SRTP */ + + /* + * Numerical settings (int then char) + */ + + uint32_t read_timeout; /*!< timeout for mbedtls_ssl_read (ms) */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + uint32_t hs_timeout_min; /*!< initial value of the handshake + retransmission timeout (ms) */ + uint32_t hs_timeout_max; /*!< maximum value of the handshake + retransmission timeout (ms) */ +#endif + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + int renego_max_records; /*!< grace period for renegotiation */ + unsigned char renego_period[8]; /*!< value of the record counters + that triggers renegotiation */ +#endif + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) + unsigned int badmac_limit; /*!< limit of records with a bad MAC */ +#endif + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) + unsigned int dhm_min_bitlen; /*!< min. bit length of the DHM prime */ +#endif + + unsigned char max_major_ver; /*!< max. major version used */ + unsigned char max_minor_ver; /*!< max. minor version used */ + unsigned char min_major_ver; /*!< min. major version used */ + unsigned char min_minor_ver; /*!< min. minor version used */ + + /* + * Flags (bitfields) + */ + + unsigned int endpoint : 1; /*!< 0: client, 1: server */ + unsigned int transport : 1; /*!< stream (TLS) or datagram (DTLS) */ + unsigned int authmode : 2; /*!< MBEDTLS_SSL_VERIFY_XXX */ + /* needed even with renego disabled for LEGACY_BREAK_HANDSHAKE */ + unsigned int allow_legacy_renegotiation : 2 ; /*!< MBEDTLS_LEGACY_XXX */ +#if defined(MBEDTLS_ARC4_C) + unsigned int arc4_disabled : 1; /*!< blacklist RC4 ciphersuites? */ +#endif +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + unsigned int mfl_code : 3; /*!< desired fragment length */ +#endif +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + unsigned int encrypt_then_mac : 1 ; /*!< negotiate encrypt-then-mac? */ +#endif +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + unsigned int extended_ms : 1; /*!< negotiate extended master secret? */ +#endif +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + unsigned int anti_replay : 1; /*!< detect and prevent replay? */ +#endif +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) + unsigned int cbc_record_splitting : 1; /*!< do cbc record splitting */ +#endif +#if defined(MBEDTLS_SSL_RENEGOTIATION) + unsigned int disable_renegotiation : 1; /*!< disable renegotiation? */ +#endif +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + unsigned int trunc_hmac : 1; /*!< negotiate truncated hmac? */ +#endif +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + unsigned int session_tickets : 1; /*!< use session tickets? */ +#endif +#if defined(MBEDTLS_SSL_FALLBACK_SCSV) && defined(MBEDTLS_SSL_CLI_C) + unsigned int fallback : 1; /*!< is this a fallback? */ +#endif +#if defined(MBEDTLS_SSL_SRV_C) + unsigned int cert_req_ca_list : 1; /*!< enable sending CA list in + Certificate Request messages? */ +#endif +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + unsigned int ignore_unexpected_cid : 1; /*!< Determines whether DTLS + * record with unexpected CID + * should lead to failure. */ +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ +#if defined(MBEDTLS_SSL_DTLS_SRTP) + unsigned int dtls_srtp_mki_support : 1; /* support having mki_value + in the use_srtp extension */ +#endif +}; + +struct mbedtls_ssl_context +{ + const mbedtls_ssl_config *conf; /*!< configuration information */ + + /* + * Miscellaneous + */ + int state; /*!< SSL handshake: current state */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + int renego_status; /*!< Initial, in progress, pending? */ + int renego_records_seen; /*!< Records since renego request, or with DTLS, + number of retransmissions of request if + renego_max_records is < 0 */ +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + int major_ver; /*!< equal to MBEDTLS_SSL_MAJOR_VERSION_3 */ + int minor_ver; /*!< either 0 (SSL3) or 1 (TLS1.0) */ + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) + unsigned badmac_seen; /*!< records with a bad MAC received */ +#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + /** Callback to customize X.509 certificate chain verification */ + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *); + void *p_vrfy; /*!< context for X.509 verify callback */ +#endif + + mbedtls_ssl_send_t *f_send; /*!< Callback for network send */ + mbedtls_ssl_recv_t *f_recv; /*!< Callback for network receive */ + mbedtls_ssl_recv_timeout_t *f_recv_timeout; + /*!< Callback for network receive with timeout */ + + void *p_bio; /*!< context for I/O operations */ + + /* + * Session layer + */ + mbedtls_ssl_session *session_in; /*!< current session data (in) */ + mbedtls_ssl_session *session_out; /*!< current session data (out) */ + mbedtls_ssl_session *session; /*!< negotiated session data */ + mbedtls_ssl_session *session_negotiate; /*!< session data in negotiation */ + + mbedtls_ssl_handshake_params *handshake; /*!< params required only during + the handshake process */ + + /* + * Record layer transformations + */ + mbedtls_ssl_transform *transform_in; /*!< current transform params (in) */ + mbedtls_ssl_transform *transform_out; /*!< current transform params (in) */ + mbedtls_ssl_transform *transform; /*!< negotiated transform params */ + mbedtls_ssl_transform *transform_negotiate; /*!< transform params in negotiation */ + + /* + * Timers + */ + void *p_timer; /*!< context for the timer callbacks */ + + mbedtls_ssl_set_timer_t *f_set_timer; /*!< set timer callback */ + mbedtls_ssl_get_timer_t *f_get_timer; /*!< get timer callback */ + + /* + * Record layer (incoming data) + */ + unsigned char *in_buf; /*!< input buffer */ + unsigned char *in_ctr; /*!< 64-bit incoming message counter + TLS: maintained by us + DTLS: read from peer */ + unsigned char *in_hdr; /*!< start of record header */ +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + unsigned char *in_cid; /*!< The start of the CID; + * (the end is marked by in_len). */ +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + unsigned char *in_len; /*!< two-bytes message length field */ + unsigned char *in_iv; /*!< ivlen-byte IV */ + unsigned char *in_msg; /*!< message contents (in_iv+ivlen) */ + unsigned char *in_offt; /*!< read offset in application data */ + + int in_msgtype; /*!< record header: message type */ + size_t in_msglen; /*!< record header: message length */ + size_t in_left; /*!< amount of data read so far */ +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t in_buf_len; /*!< length of input buffer */ +#endif +#if defined(MBEDTLS_SSL_PROTO_DTLS) + uint16_t in_epoch; /*!< DTLS epoch for incoming records */ + size_t next_record_offset; /*!< offset of the next record in datagram + (equal to in_left if none) */ +#endif /* MBEDTLS_SSL_PROTO_DTLS */ +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + uint64_t in_window_top; /*!< last validated record seq_num */ + uint64_t in_window; /*!< bitmask for replay detection */ +#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ + + size_t in_hslen; /*!< current handshake message length, + including the handshake header */ + int nb_zero; /*!< # of 0-length encrypted messages */ + + int keep_current_message; /*!< drop or reuse current message + on next call to record layer? */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + uint8_t disable_datagram_packing; /*!< Disable packing multiple records + * within a single datagram. */ +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + /* + * Record layer (outgoing data) + */ + unsigned char *out_buf; /*!< output buffer */ + unsigned char *out_ctr; /*!< 64-bit outgoing message counter */ + unsigned char *out_hdr; /*!< start of record header */ +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + unsigned char *out_cid; /*!< The start of the CID; + * (the end is marked by in_len). */ +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + unsigned char *out_len; /*!< two-bytes message length field */ + unsigned char *out_iv; /*!< ivlen-byte IV */ + unsigned char *out_msg; /*!< message contents (out_iv+ivlen) */ + + int out_msgtype; /*!< record header: message type */ + size_t out_msglen; /*!< record header: message length */ + size_t out_left; /*!< amount of data not yet written */ +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t out_buf_len; /*!< length of output buffer */ +#endif + + unsigned char cur_out_ctr[8]; /*!< Outgoing record sequence number. */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + uint16_t mtu; /*!< path mtu, used to fragment outgoing messages */ +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_ZLIB_SUPPORT) + unsigned char *compress_buf; /*!< zlib data buffer */ +#endif /* MBEDTLS_ZLIB_SUPPORT */ +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) + signed char split_done; /*!< current record already splitted? */ +#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */ + + /* + * PKI layer + */ + int client_auth; /*!< flag for client auth. */ + + /* + * User settings + */ +#if defined(MBEDTLS_X509_CRT_PARSE_C) + char *hostname; /*!< expected peer CN for verification + (and SNI if available) */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_ALPN) + const char *alpn_chosen; /*!< negotiated protocol */ +#endif /* MBEDTLS_SSL_ALPN */ + +#if defined(MBEDTLS_SSL_DTLS_SRTP) + /* + * use_srtp extension + */ + mbedtls_dtls_srtp_info dtls_srtp_info; +#endif /* MBEDTLS_SSL_DTLS_SRTP */ + + /* + * Information for DTLS hello verify + */ +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) + unsigned char *cli_id; /*!< transport-level ID of the client */ + size_t cli_id_len; /*!< length of cli_id */ +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */ + + /* + * Secure renegotiation + */ + /* needed to know when to send extension on server */ + int secure_renegotiation; /*!< does peer support legacy or + secure renegotiation */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + size_t verify_data_len; /*!< length of verify data stored */ + char own_verify_data[MBEDTLS_SSL_VERIFY_DATA_MAX_LEN]; /*!< previous handshake verify data */ + char peer_verify_data[MBEDTLS_SSL_VERIFY_DATA_MAX_LEN]; /*!< previous handshake verify data */ +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + /* CID configuration to use in subsequent handshakes. */ + + /*! The next incoming CID, chosen by the user and applying to + * all subsequent handshakes. This may be different from the + * CID currently used in case the user has re-configured the CID + * after an initial handshake. */ + unsigned char own_cid[ MBEDTLS_SSL_CID_IN_LEN_MAX ]; + uint8_t own_cid_len; /*!< The length of \c own_cid. */ + uint8_t negotiate_cid; /*!< This indicates whether the CID extension should + * be negotiated in the next handshake or not. + * Possible values are #MBEDTLS_SSL_CID_ENABLED + * and #MBEDTLS_SSL_CID_DISABLED. */ +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ +}; + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + +#define MBEDTLS_SSL_CHANNEL_OUTBOUND MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( 0 ) +#define MBEDTLS_SSL_CHANNEL_INBOUND MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( 1 ) + +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif /* MBEDTLS_DEPRECATED_WARNING */ + +MBEDTLS_DEPRECATED extern int (*mbedtls_ssl_hw_record_init)( + mbedtls_ssl_context *ssl, + const unsigned char *key_enc, const unsigned char *key_dec, + size_t keylen, + const unsigned char *iv_enc, const unsigned char *iv_dec, + size_t ivlen, + const unsigned char *mac_enc, const unsigned char *mac_dec, + size_t maclen); +MBEDTLS_DEPRECATED extern int (*mbedtls_ssl_hw_record_activate)( + mbedtls_ssl_context *ssl, + int direction ); +MBEDTLS_DEPRECATED extern int (*mbedtls_ssl_hw_record_reset)( + mbedtls_ssl_context *ssl ); +MBEDTLS_DEPRECATED extern int (*mbedtls_ssl_hw_record_write)( + mbedtls_ssl_context *ssl ); +MBEDTLS_DEPRECATED extern int (*mbedtls_ssl_hw_record_read)( + mbedtls_ssl_context *ssl ); +MBEDTLS_DEPRECATED extern int (*mbedtls_ssl_hw_record_finish)( + mbedtls_ssl_context *ssl ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ + +/** + * \brief Return the name of the ciphersuite associated with the + * given ID + * + * \param ciphersuite_id SSL ciphersuite ID + * + * \return a string containing the ciphersuite name + */ +const char *mbedtls_ssl_get_ciphersuite_name( const int ciphersuite_id ); + +/** + * \brief Return the ID of the ciphersuite associated with the + * given name + * + * \param ciphersuite_name SSL ciphersuite name + * + * \return the ID with the ciphersuite or 0 if not found + */ +int mbedtls_ssl_get_ciphersuite_id( const char *ciphersuite_name ); + +/** + * \brief Initialize an SSL context + * Just makes the context ready for mbedtls_ssl_setup() or + * mbedtls_ssl_free() + * + * \param ssl SSL context + */ +void mbedtls_ssl_init( mbedtls_ssl_context *ssl ); + +/** + * \brief Set up an SSL context for use + * + * \note No copy of the configuration context is made, it can be + * shared by many mbedtls_ssl_context structures. + * + * \warning The conf structure will be accessed during the session. + * It must not be modified or freed as long as the session + * is active. + * + * \warning This function must be called exactly once per context. + * Calling mbedtls_ssl_setup again is not supported, even + * if no session is active. + * + * \param ssl SSL context + * \param conf SSL configuration to use + * + * \return 0 if successful, or MBEDTLS_ERR_SSL_ALLOC_FAILED if + * memory allocation failed + */ +int mbedtls_ssl_setup( mbedtls_ssl_context *ssl, + const mbedtls_ssl_config *conf ); + +/** + * \brief Reset an already initialized SSL context for re-use + * while retaining application-set variables, function + * pointers and data. + * + * \param ssl SSL context + * \return 0 if successful, or MBEDTLS_ERR_SSL_ALLOC_FAILED, + MBEDTLS_ERR_SSL_HW_ACCEL_FAILED or + * MBEDTLS_ERR_SSL_COMPRESSION_FAILED + */ +int mbedtls_ssl_session_reset( mbedtls_ssl_context *ssl ); + +/** + * \brief Set the current endpoint type + * + * \param conf SSL configuration + * \param endpoint must be MBEDTLS_SSL_IS_CLIENT or MBEDTLS_SSL_IS_SERVER + */ +void mbedtls_ssl_conf_endpoint( mbedtls_ssl_config *conf, int endpoint ); + +/** + * \brief Set the transport type (TLS or DTLS). + * Default: TLS + * + * \note For DTLS, you must either provide a recv callback that + * doesn't block, or one that handles timeouts, see + * \c mbedtls_ssl_set_bio(). You also need to provide timer + * callbacks with \c mbedtls_ssl_set_timer_cb(). + * + * \param conf SSL configuration + * \param transport transport type: + * MBEDTLS_SSL_TRANSPORT_STREAM for TLS, + * MBEDTLS_SSL_TRANSPORT_DATAGRAM for DTLS. + */ +void mbedtls_ssl_conf_transport( mbedtls_ssl_config *conf, int transport ); + +/** + * \brief Set the certificate verification mode + * Default: NONE on server, REQUIRED on client + * + * \param conf SSL configuration + * \param authmode can be: + * + * MBEDTLS_SSL_VERIFY_NONE: peer certificate is not checked + * (default on server) + * (insecure on client) + * + * MBEDTLS_SSL_VERIFY_OPTIONAL: peer certificate is checked, however the + * handshake continues even if verification failed; + * mbedtls_ssl_get_verify_result() can be called after the + * handshake is complete. + * + * MBEDTLS_SSL_VERIFY_REQUIRED: peer *must* present a valid certificate, + * handshake is aborted if verification failed. + * (default on client) + * + * \note On client, MBEDTLS_SSL_VERIFY_REQUIRED is the recommended mode. + * With MBEDTLS_SSL_VERIFY_OPTIONAL, the user needs to call mbedtls_ssl_get_verify_result() at + * the right time(s), which may not be obvious, while REQUIRED always perform + * the verification as soon as possible. For example, REQUIRED was protecting + * against the "triple handshake" attack even before it was found. + */ +void mbedtls_ssl_conf_authmode( mbedtls_ssl_config *conf, int authmode ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * \brief Set the verification callback (Optional). + * + * If set, the provided verify callback is called for each + * certificate in the peer's CRT chain, including the trusted + * root. For more information, please see the documentation of + * \c mbedtls_x509_crt_verify(). + * + * \note For per context callbacks and contexts, please use + * mbedtls_ssl_set_verify() instead. + * + * \param conf The SSL configuration to use. + * \param f_vrfy The verification callback to use during CRT verification. + * \param p_vrfy The opaque context to be passed to the callback. + */ +void mbedtls_ssl_conf_verify( mbedtls_ssl_config *conf, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +/** + * \brief Set the random number generator callback + * + * \param conf SSL configuration + * \param f_rng RNG function + * \param p_rng RNG parameter + */ +void mbedtls_ssl_conf_rng( mbedtls_ssl_config *conf, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Set the debug callback + * + * The callback has the following argument: + * void * opaque context for the callback + * int debug level + * const char * file name + * int line number + * const char * message + * + * \param conf SSL configuration + * \param f_dbg debug function + * \param p_dbg debug parameter + */ +void mbedtls_ssl_conf_dbg( mbedtls_ssl_config *conf, + void (*f_dbg)(void *, int, const char *, int, const char *), + void *p_dbg ); + +/** + * \brief Set the underlying BIO callbacks for write, read and + * read-with-timeout. + * + * \param ssl SSL context + * \param p_bio parameter (context) shared by BIO callbacks + * \param f_send write callback + * \param f_recv read callback + * \param f_recv_timeout blocking read callback with timeout. + * + * \note One of f_recv or f_recv_timeout can be NULL, in which case + * the other is used. If both are non-NULL, f_recv_timeout is + * used and f_recv is ignored (as if it were NULL). + * + * \note The two most common use cases are: + * - non-blocking I/O, f_recv != NULL, f_recv_timeout == NULL + * - blocking I/O, f_recv == NULL, f_recv_timout != NULL + * + * \note For DTLS, you need to provide either a non-NULL + * f_recv_timeout callback, or a f_recv that doesn't block. + * + * \note See the documentations of \c mbedtls_ssl_send_t, + * \c mbedtls_ssl_recv_t and \c mbedtls_ssl_recv_timeout_t for + * the conventions those callbacks must follow. + * + * \note On some platforms, net_sockets.c provides + * \c mbedtls_net_send(), \c mbedtls_net_recv() and + * \c mbedtls_net_recv_timeout() that are suitable to be used + * here. + */ +void mbedtls_ssl_set_bio( mbedtls_ssl_context *ssl, + void *p_bio, + mbedtls_ssl_send_t *f_send, + mbedtls_ssl_recv_t *f_recv, + mbedtls_ssl_recv_timeout_t *f_recv_timeout ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + + +/** + * \brief Configure the use of the Connection ID (CID) + * extension in the next handshake. + * + * Reference: draft-ietf-tls-dtls-connection-id-05 + * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05 + * + * The DTLS CID extension allows the reliable association of + * DTLS records to DTLS connections across changes in the + * underlying transport (changed IP and Port metadata) by + * adding explicit connection identifiers (CIDs) to the + * headers of encrypted DTLS records. The desired CIDs are + * configured by the application layer and are exchanged in + * new `ClientHello` / `ServerHello` extensions during the + * handshake, where each side indicates the CID it wants the + * peer to use when writing encrypted messages. The CIDs are + * put to use once records get encrypted: the stack discards + * any incoming records that don't include the configured CID + * in their header, and adds the peer's requested CID to the + * headers of outgoing messages. + * + * This API enables or disables the use of the CID extension + * in the next handshake and sets the value of the CID to + * be used for incoming messages. + * + * \param ssl The SSL context to configure. This must be initialized. + * \param enable This value determines whether the CID extension should + * be used or not. Possible values are: + * - MBEDTLS_SSL_CID_ENABLED to enable the use of the CID. + * - MBEDTLS_SSL_CID_DISABLED (default) to disable the use + * of the CID. + * \param own_cid The address of the readable buffer holding the CID we want + * the peer to use when sending encrypted messages to us. + * This may be \c NULL if \p own_cid_len is \c 0. + * This parameter is unused if \p enabled is set to + * MBEDTLS_SSL_CID_DISABLED. + * \param own_cid_len The length of \p own_cid. + * This parameter is unused if \p enabled is set to + * MBEDTLS_SSL_CID_DISABLED. + * + * \note The value of \p own_cid_len must match the value of the + * \c len parameter passed to mbedtls_ssl_conf_cid() + * when configuring the ::mbedtls_ssl_config that \p ssl + * is bound to. + * + * \note This CID configuration applies to subsequent handshakes + * performed on the SSL context \p ssl, but does not trigger + * one. You still have to call `mbedtls_ssl_handshake()` + * (for the initial handshake) or `mbedtls_ssl_renegotiate()` + * (for a renegotiation handshake) explicitly after a + * successful call to this function to run the handshake. + * + * \note This call cannot guarantee that the use of the CID + * will be successfully negotiated in the next handshake, + * because the peer might not support it. Specifically: + * - On the Client, enabling the use of the CID through + * this call implies that the `ClientHello` in the next + * handshake will include the CID extension, thereby + * offering the use of the CID to the server. Only if + * the `ServerHello` contains the CID extension, too, + * the CID extension will actually be put to use. + * - On the Server, enabling the use of the CID through + * this call implies that that the server will look for + * the CID extension in a `ClientHello` from the client, + * and, if present, reply with a CID extension in its + * `ServerHello`. + * + * \note To check whether the use of the CID was negotiated + * after the subsequent handshake has completed, please + * use the API mbedtls_ssl_get_peer_cid(). + * + * \warning If the use of the CID extension is enabled in this call + * and the subsequent handshake negotiates its use, Mbed TLS + * will silently drop every packet whose CID does not match + * the CID configured in \p own_cid. It is the responsibility + * of the user to adapt the underlying transport to take care + * of CID-based demultiplexing before handing datagrams to + * Mbed TLS. + * + * \return \c 0 on success. In this case, the CID configuration + * applies to the next handshake. + * \return A negative error code on failure. + */ +int mbedtls_ssl_set_cid( mbedtls_ssl_context *ssl, + int enable, + unsigned char const *own_cid, + size_t own_cid_len ); + +/** + * \brief Get information about the use of the CID extension + * in the current connection. + * + * \param ssl The SSL context to query. + * \param enabled The address at which to store whether the CID extension + * is currently in use or not. If the CID is in use, + * `*enabled` is set to MBEDTLS_SSL_CID_ENABLED; + * otherwise, it is set to MBEDTLS_SSL_CID_DISABLED. + * \param peer_cid The address of the buffer in which to store the CID + * chosen by the peer (if the CID extension is used). + * This may be \c NULL in case the value of peer CID + * isn't needed. If it is not \c NULL, \p peer_cid_len + * must not be \c NULL. + * \param peer_cid_len The address at which to store the size of the CID + * chosen by the peer (if the CID extension is used). + * This is also the number of Bytes in \p peer_cid that + * have been written. + * This may be \c NULL in case the length of the peer CID + * isn't needed. If it is \c NULL, \p peer_cid must be + * \c NULL, too. + * + * \note This applies to the state of the CID negotiated in + * the last complete handshake. If a handshake is in + * progress, this function will attempt to complete + * the handshake first. + * + * \note If CID extensions have been exchanged but both client + * and server chose to use an empty CID, this function + * sets `*enabled` to #MBEDTLS_SSL_CID_DISABLED + * (the rationale for this is that the resulting + * communication is the same as if the CID extensions + * hadn't been used). + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_ssl_get_peer_cid( mbedtls_ssl_context *ssl, + int *enabled, + unsigned char peer_cid[ MBEDTLS_SSL_CID_OUT_LEN_MAX ], + size_t *peer_cid_len ); + +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + +/** + * \brief Set the Maximum Tranport Unit (MTU). + * Special value: 0 means unset (no limit). + * This represents the maximum size of a datagram payload + * handled by the transport layer (usually UDP) as determined + * by the network link and stack. In practice, this controls + * the maximum size datagram the DTLS layer will pass to the + * \c f_send() callback set using \c mbedtls_ssl_set_bio(). + * + * \note The limit on datagram size is converted to a limit on + * record payload by subtracting the current overhead of + * encapsulation and encryption/authentication if any. + * + * \note This can be called at any point during the connection, for + * example when a Path Maximum Transfer Unit (PMTU) + * estimate becomes available from other sources, + * such as lower (or higher) protocol layers. + * + * \note This setting only controls the size of the packets we send, + * and does not restrict the size of the datagrams we're + * willing to receive. Client-side, you can request the + * server to use smaller records with \c + * mbedtls_ssl_conf_max_frag_len(). + * + * \note If both a MTU and a maximum fragment length have been + * configured (or negotiated with the peer), the resulting + * lower limit on record payload (see first note) is used. + * + * \note This can only be used to decrease the maximum size + * of datagrams (hence records, see first note) sent. It + * cannot be used to increase the maximum size of records over + * the limit set by #MBEDTLS_SSL_OUT_CONTENT_LEN. + * + * \note Values lower than the current record layer expansion will + * result in an error when trying to send data. + * + * \note Using record compression together with a non-zero MTU value + * will result in an error when trying to send data. + * + * \param ssl SSL context + * \param mtu Value of the path MTU in bytes + */ +void mbedtls_ssl_set_mtu( mbedtls_ssl_context *ssl, uint16_t mtu ); +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * \brief Set a connection-specific verification callback (optional). + * + * If set, the provided verify callback is called for each + * certificate in the peer's CRT chain, including the trusted + * root. For more information, please see the documentation of + * \c mbedtls_x509_crt_verify(). + * + * \note This call is analogous to mbedtls_ssl_conf_verify() but + * binds the verification callback and context to an SSL context + * as opposed to an SSL configuration. + * If mbedtls_ssl_conf_verify() and mbedtls_ssl_set_verify() + * are both used, mbedtls_ssl_set_verify() takes precedence. + * + * \param ssl The SSL context to use. + * \param f_vrfy The verification callback to use during CRT verification. + * \param p_vrfy The opaque context to be passed to the callback. + */ +void mbedtls_ssl_set_verify( mbedtls_ssl_context *ssl, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +/** + * \brief Set the timeout period for mbedtls_ssl_read() + * (Default: no timeout.) + * + * \param conf SSL configuration context + * \param timeout Timeout value in milliseconds. + * Use 0 for no timeout (default). + * + * \note With blocking I/O, this will only work if a non-NULL + * \c f_recv_timeout was set with \c mbedtls_ssl_set_bio(). + * With non-blocking I/O, this will only work if timer + * callbacks were set with \c mbedtls_ssl_set_timer_cb(). + * + * \note With non-blocking I/O, you may also skip this function + * altogether and handle timeouts at the application layer. + */ +void mbedtls_ssl_conf_read_timeout( mbedtls_ssl_config *conf, uint32_t timeout ); + +#if defined(MBEDTLS_SSL_RECORD_CHECKING) +/** + * \brief Check whether a buffer contains a valid and authentic record + * that has not been seen before. (DTLS only). + * + * This function does not change the user-visible state + * of the SSL context. Its sole purpose is to provide + * an indication of the legitimacy of an incoming record. + * + * This can be useful e.g. in distributed server environments + * using the DTLS Connection ID feature, in which connections + * might need to be passed between service instances on a change + * of peer address, but where such disruptive operations should + * only happen after the validity of incoming records has been + * confirmed. + * + * \param ssl The SSL context to use. + * \param buf The address of the buffer holding the record to be checked. + * This must be a read/write buffer of length \p buflen Bytes. + * \param buflen The length of \p buf in Bytes. + * + * \note This routine only checks whether the provided buffer begins + * with a valid and authentic record that has not been seen + * before, but does not check potential data following the + * initial record. In particular, it is possible to pass DTLS + * datagrams containing multiple records, in which case only + * the first record is checked. + * + * \note This function modifies the input buffer \p buf. If you need + * to preserve the original record, you have to maintain a copy. + * + * \return \c 0 if the record is valid and authentic and has not been + * seen before. + * \return MBEDTLS_ERR_SSL_INVALID_MAC if the check completed + * successfully but the record was found to be not authentic. + * \return MBEDTLS_ERR_SSL_INVALID_RECORD if the check completed + * successfully but the record was found to be invalid for + * a reason different from authenticity checking. + * \return MBEDTLS_ERR_SSL_UNEXPECTED_RECORD if the check completed + * successfully but the record was found to be unexpected + * in the state of the SSL context, including replayed records. + * \return Another negative error code on different kinds of failure. + * In this case, the SSL context becomes unusable and needs + * to be freed or reset before reuse. + */ +int mbedtls_ssl_check_record( mbedtls_ssl_context const *ssl, + unsigned char *buf, + size_t buflen ); +#endif /* MBEDTLS_SSL_RECORD_CHECKING */ + +/** + * \brief Set the timer callbacks (Mandatory for DTLS.) + * + * \param ssl SSL context + * \param p_timer parameter (context) shared by timer callbacks + * \param f_set_timer set timer callback + * \param f_get_timer get timer callback. Must return: + * + * \note See the documentation of \c mbedtls_ssl_set_timer_t and + * \c mbedtls_ssl_get_timer_t for the conventions this pair of + * callbacks must follow. + * + * \note On some platforms, timing.c provides + * \c mbedtls_timing_set_delay() and + * \c mbedtls_timing_get_delay() that are suitable for using + * here, except if using an event-driven style. + * + * \note See also the "DTLS tutorial" article in our knowledge base. + * https://tls.mbed.org/kb/how-to/dtls-tutorial + */ +void mbedtls_ssl_set_timer_cb( mbedtls_ssl_context *ssl, + void *p_timer, + mbedtls_ssl_set_timer_t *f_set_timer, + mbedtls_ssl_get_timer_t *f_get_timer ); + +/** + * \brief Callback type: generate and write session ticket + * + * \note This describes what a callback implementation should do. + * This callback should generate an encrypted and + * authenticated ticket for the session and write it to the + * output buffer. Here, ticket means the opaque ticket part + * of the NewSessionTicket structure of RFC 5077. + * + * \param p_ticket Context for the callback + * \param session SSL session to be written in the ticket + * \param start Start of the output buffer + * \param end End of the output buffer + * \param tlen On exit, holds the length written + * \param lifetime On exit, holds the lifetime of the ticket in seconds + * + * \return 0 if successful, or + * a specific MBEDTLS_ERR_XXX code. + */ +typedef int mbedtls_ssl_ticket_write_t( void *p_ticket, + const mbedtls_ssl_session *session, + unsigned char *start, + const unsigned char *end, + size_t *tlen, + uint32_t *lifetime ); + +#if defined(MBEDTLS_SSL_EXPORT_KEYS) +/** + * \brief Callback type: Export key block and master secret + * + * \note This is required for certain uses of TLS, e.g. EAP-TLS + * (RFC 5216) and Thread. The key pointers are ephemeral and + * therefore must not be stored. The master secret and keys + * should not be used directly except as an input to a key + * derivation function. + * + * \param p_expkey Context for the callback + * \param ms Pointer to master secret (fixed length: 48 bytes) + * \param kb Pointer to key block, see RFC 5246 section 6.3 + * (variable length: 2 * maclen + 2 * keylen + 2 * ivlen). + * \param maclen MAC length + * \param keylen Key length + * \param ivlen IV length + * + * \return 0 if successful, or + * a specific MBEDTLS_ERR_XXX code. + */ +typedef int mbedtls_ssl_export_keys_t( void *p_expkey, + const unsigned char *ms, + const unsigned char *kb, + size_t maclen, + size_t keylen, + size_t ivlen ); + +/** + * \brief Callback type: Export key block, master secret, + * handshake randbytes and the tls_prf function + * used to derive keys. + * + * \note This is required for certain uses of TLS, e.g. EAP-TLS + * (RFC 5216) and Thread. The key pointers are ephemeral and + * therefore must not be stored. The master secret and keys + * should not be used directly except as an input to a key + * derivation function. + * + * \param p_expkey Context for the callback. + * \param ms Pointer to master secret (fixed length: 48 bytes). + * \param kb Pointer to key block, see RFC 5246 section 6.3. + * (variable length: 2 * maclen + 2 * keylen + 2 * ivlen). + * \param maclen MAC length. + * \param keylen Key length. + * \param ivlen IV length. + * \param client_random The client random bytes. + * \param server_random The server random bytes. + * \param tls_prf_type The tls_prf enum type. + * + * \return 0 if successful, or + * a specific MBEDTLS_ERR_XXX code. + */ +typedef int mbedtls_ssl_export_keys_ext_t( void *p_expkey, + const unsigned char *ms, + const unsigned char *kb, + size_t maclen, + size_t keylen, + size_t ivlen, + const unsigned char client_random[32], + const unsigned char server_random[32], + mbedtls_tls_prf_types tls_prf_type ); +#endif /* MBEDTLS_SSL_EXPORT_KEYS */ + +/** + * \brief Callback type: parse and load session ticket + * + * \note This describes what a callback implementation should do. + * This callback should parse a session ticket as generated + * by the corresponding mbedtls_ssl_ticket_write_t function, + * and, if the ticket is authentic and valid, load the + * session. + * + * \note The implementation is allowed to modify the first len + * bytes of the input buffer, eg to use it as a temporary + * area for the decrypted ticket contents. + * + * \param p_ticket Context for the callback + * \param session SSL session to be loaded + * \param buf Start of the buffer containing the ticket + * \param len Length of the ticket. + * + * \return 0 if successful, or + * MBEDTLS_ERR_SSL_INVALID_MAC if not authentic, or + * MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED if expired, or + * any other non-zero code for other failures. + */ +typedef int mbedtls_ssl_ticket_parse_t( void *p_ticket, + mbedtls_ssl_session *session, + unsigned char *buf, + size_t len ); + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_SRV_C) +/** + * \brief Configure SSL session ticket callbacks (server only). + * (Default: none.) + * + * \note On server, session tickets are enabled by providing + * non-NULL callbacks. + * + * \note On client, use \c mbedtls_ssl_conf_session_tickets(). + * + * \param conf SSL configuration context + * \param f_ticket_write Callback for writing a ticket + * \param f_ticket_parse Callback for parsing a ticket + * \param p_ticket Context shared by the two callbacks + */ +void mbedtls_ssl_conf_session_tickets_cb( mbedtls_ssl_config *conf, + mbedtls_ssl_ticket_write_t *f_ticket_write, + mbedtls_ssl_ticket_parse_t *f_ticket_parse, + void *p_ticket ); +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_EXPORT_KEYS) +/** + * \brief Configure key export callback. + * (Default: none.) + * + * \note See \c mbedtls_ssl_export_keys_t. + * + * \param conf SSL configuration context + * \param f_export_keys Callback for exporting keys + * \param p_export_keys Context for the callback + */ +void mbedtls_ssl_conf_export_keys_cb( mbedtls_ssl_config *conf, + mbedtls_ssl_export_keys_t *f_export_keys, + void *p_export_keys ); + +/** + * \brief Configure extended key export callback. + * (Default: none.) + * + * \note See \c mbedtls_ssl_export_keys_ext_t. + * \warning Exported key material must not be used for any purpose + * before the (D)TLS handshake is completed + * + * \param conf SSL configuration context + * \param f_export_keys_ext Callback for exporting keys + * \param p_export_keys Context for the callback + */ +void mbedtls_ssl_conf_export_keys_ext_cb( mbedtls_ssl_config *conf, + mbedtls_ssl_export_keys_ext_t *f_export_keys_ext, + void *p_export_keys ); +#endif /* MBEDTLS_SSL_EXPORT_KEYS */ + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) +/** + * \brief Configure asynchronous private key operation callbacks. + * + * \param conf SSL configuration context + * \param f_async_sign Callback to start a signature operation. See + * the description of ::mbedtls_ssl_async_sign_t + * for more information. This may be \c NULL if the + * external processor does not support any signature + * operation; in this case the private key object + * associated with the certificate will be used. + * \param f_async_decrypt Callback to start a decryption operation. See + * the description of ::mbedtls_ssl_async_decrypt_t + * for more information. This may be \c NULL if the + * external processor does not support any decryption + * operation; in this case the private key object + * associated with the certificate will be used. + * \param f_async_resume Callback to resume an asynchronous operation. See + * the description of ::mbedtls_ssl_async_resume_t + * for more information. This may not be \c NULL unless + * \p f_async_sign and \p f_async_decrypt are both + * \c NULL. + * \param f_async_cancel Callback to cancel an asynchronous operation. See + * the description of ::mbedtls_ssl_async_cancel_t + * for more information. This may be \c NULL if + * no cleanup is needed. + * \param config_data A pointer to configuration data which can be + * retrieved with + * mbedtls_ssl_conf_get_async_config_data(). The + * library stores this value without dereferencing it. + */ +void mbedtls_ssl_conf_async_private_cb( mbedtls_ssl_config *conf, + mbedtls_ssl_async_sign_t *f_async_sign, + mbedtls_ssl_async_decrypt_t *f_async_decrypt, + mbedtls_ssl_async_resume_t *f_async_resume, + mbedtls_ssl_async_cancel_t *f_async_cancel, + void *config_data ); + +/** + * \brief Retrieve the configuration data set by + * mbedtls_ssl_conf_async_private_cb(). + * + * \param conf SSL configuration context + * \return The configuration data set by + * mbedtls_ssl_conf_async_private_cb(). + */ +void *mbedtls_ssl_conf_get_async_config_data( const mbedtls_ssl_config *conf ); + +/** + * \brief Retrieve the asynchronous operation user context. + * + * \note This function may only be called while a handshake + * is in progress. + * + * \param ssl The SSL context to access. + * + * \return The asynchronous operation user context that was last + * set during the current handshake. If + * mbedtls_ssl_set_async_operation_data() has not yet been + * called during the current handshake, this function returns + * \c NULL. + */ +void *mbedtls_ssl_get_async_operation_data( const mbedtls_ssl_context *ssl ); + +/** + * \brief Retrieve the asynchronous operation user context. + * + * \note This function may only be called while a handshake + * is in progress. + * + * \param ssl The SSL context to access. + * \param ctx The new value of the asynchronous operation user context. + * Call mbedtls_ssl_get_async_operation_data() later during the + * same handshake to retrieve this value. + */ +void mbedtls_ssl_set_async_operation_data( mbedtls_ssl_context *ssl, + void *ctx ); +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + +/** + * \brief Callback type: generate a cookie + * + * \param ctx Context for the callback + * \param p Buffer to write to, + * must be updated to point right after the cookie + * \param end Pointer to one past the end of the output buffer + * \param info Client ID info that was passed to + * \c mbedtls_ssl_set_client_transport_id() + * \param ilen Length of info in bytes + * + * \return The callback must return 0 on success, + * or a negative error code. + */ +typedef int mbedtls_ssl_cookie_write_t( void *ctx, + unsigned char **p, unsigned char *end, + const unsigned char *info, size_t ilen ); + +/** + * \brief Callback type: verify a cookie + * + * \param ctx Context for the callback + * \param cookie Cookie to verify + * \param clen Length of cookie + * \param info Client ID info that was passed to + * \c mbedtls_ssl_set_client_transport_id() + * \param ilen Length of info in bytes + * + * \return The callback must return 0 if cookie is valid, + * or a negative error code. + */ +typedef int mbedtls_ssl_cookie_check_t( void *ctx, + const unsigned char *cookie, size_t clen, + const unsigned char *info, size_t ilen ); + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) +/** + * \brief Register callbacks for DTLS cookies + * (Server only. DTLS only.) + * + * Default: dummy callbacks that fail, in order to force you to + * register working callbacks (and initialize their context). + * + * To disable HelloVerifyRequest, register NULL callbacks. + * + * \warning Disabling hello verification allows your server to be used + * for amplification in DoS attacks against other hosts. + * Only disable if you known this can't happen in your + * particular environment. + * + * \note See comments on \c mbedtls_ssl_handshake() about handling + * the MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED that is expected + * on the first handshake attempt when this is enabled. + * + * \note This is also necessary to handle client reconnection from + * the same port as described in RFC 6347 section 4.2.8 (only + * the variant with cookies is supported currently). See + * comments on \c mbedtls_ssl_read() for details. + * + * \param conf SSL configuration + * \param f_cookie_write Cookie write callback + * \param f_cookie_check Cookie check callback + * \param p_cookie Context for both callbacks + */ +void mbedtls_ssl_conf_dtls_cookies( mbedtls_ssl_config *conf, + mbedtls_ssl_cookie_write_t *f_cookie_write, + mbedtls_ssl_cookie_check_t *f_cookie_check, + void *p_cookie ); + +/** + * \brief Set client's transport-level identification info. + * (Server only. DTLS only.) + * + * This is usually the IP address (and port), but could be + * anything identify the client depending on the underlying + * network stack. Used for HelloVerifyRequest with DTLS. + * This is *not* used to route the actual packets. + * + * \param ssl SSL context + * \param info Transport-level info identifying the client (eg IP + port) + * \param ilen Length of info in bytes + * + * \note An internal copy is made, so the info buffer can be reused. + * + * \return 0 on success, + * MBEDTLS_ERR_SSL_BAD_INPUT_DATA if used on client, + * MBEDTLS_ERR_SSL_ALLOC_FAILED if out of memory. + */ +int mbedtls_ssl_set_client_transport_id( mbedtls_ssl_context *ssl, + const unsigned char *info, + size_t ilen ); + +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +/** + * \brief Enable or disable anti-replay protection for DTLS. + * (DTLS only, no effect on TLS.) + * Default: enabled. + * + * \param conf SSL configuration + * \param mode MBEDTLS_SSL_ANTI_REPLAY_ENABLED or MBEDTLS_SSL_ANTI_REPLAY_DISABLED. + * + * \warning Disabling this is a security risk unless the application + * protocol handles duplicated packets in a safe way. You + * should not disable this without careful consideration. + * However, if your application already detects duplicated + * packets and needs information about them to adjust its + * transmission strategy, then you'll want to disable this. + */ +void mbedtls_ssl_conf_dtls_anti_replay( mbedtls_ssl_config *conf, char mode ); +#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) +/** + * \brief Set a limit on the number of records with a bad MAC + * before terminating the connection. + * (DTLS only, no effect on TLS.) + * Default: 0 (disabled). + * + * \param conf SSL configuration + * \param limit Limit, or 0 to disable. + * + * \note If the limit is N, then the connection is terminated when + * the Nth non-authentic record is seen. + * + * \note Records with an invalid header are not counted, only the + * ones going through the authentication-decryption phase. + * + * \note This is a security trade-off related to the fact that it's + * often relatively easy for an active attacker ot inject UDP + * datagrams. On one hand, setting a low limit here makes it + * easier for such an attacker to forcibly terminated a + * connection. On the other hand, a high limit or no limit + * might make us waste resources checking authentication on + * many bogus packets. + */ +void mbedtls_ssl_conf_dtls_badmac_limit( mbedtls_ssl_config *conf, unsigned limit ); +#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + +/** + * \brief Allow or disallow packing of multiple handshake records + * within a single datagram. + * + * \param ssl The SSL context to configure. + * \param allow_packing This determines whether datagram packing may + * be used or not. A value of \c 0 means that every + * record will be sent in a separate datagram; a + * value of \c 1 means that, if space permits, + * multiple handshake messages (including CCS) belonging to + * a single flight may be packed within a single datagram. + * + * \note This is enabled by default and should only be disabled + * for test purposes, or if datagram packing causes + * interoperability issues with peers that don't support it. + * + * \note Allowing datagram packing reduces the network load since + * there's less overhead if multiple messages share the same + * datagram. Also, it increases the handshake efficiency + * since messages belonging to a single datagram will not + * be reordered in transit, and so future message buffering + * or flight retransmission (if no buffering is used) as + * means to deal with reordering are needed less frequently. + * + * \note Application records are not affected by this option and + * are currently always sent in separate datagrams. + * + */ +void mbedtls_ssl_set_datagram_packing( mbedtls_ssl_context *ssl, + unsigned allow_packing ); + +/** + * \brief Set retransmit timeout values for the DTLS handshake. + * (DTLS only, no effect on TLS.) + * + * \param conf SSL configuration + * \param min Initial timeout value in milliseconds. + * Default: 1000 (1 second). + * \param max Maximum timeout value in milliseconds. + * Default: 60000 (60 seconds). + * + * \note Default values are from RFC 6347 section 4.2.4.1. + * + * \note The 'min' value should typically be slightly above the + * expected round-trip time to your peer, plus whatever time + * it takes for the peer to process the message. For example, + * if your RTT is about 600ms and you peer needs up to 1s to + * do the cryptographic operations in the handshake, then you + * should set 'min' slightly above 1600. Lower values of 'min' + * might cause spurious resends which waste network resources, + * while larger value of 'min' will increase overall latency + * on unreliable network links. + * + * \note The more unreliable your network connection is, the larger + * your max / min ratio needs to be in order to achieve + * reliable handshakes. + * + * \note Messages are retransmitted up to log2(ceil(max/min)) times. + * For example, if min = 1s and max = 5s, the retransmit plan + * goes: send ... 1s -> resend ... 2s -> resend ... 4s -> + * resend ... 5s -> give up and return a timeout error. + */ +void mbedtls_ssl_conf_handshake_timeout( mbedtls_ssl_config *conf, uint32_t min, uint32_t max ); +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_SSL_SRV_C) +/** + * \brief Set the session cache callbacks (server-side only) + * If not set, no session resuming is done (except if session + * tickets are enabled too). + * + * The session cache has the responsibility to check for stale + * entries based on timeout. See RFC 5246 for recommendations. + * + * Warning: session.peer_cert is cleared by the SSL/TLS layer on + * connection shutdown, so do not cache the pointer! Either set + * it to NULL or make a full copy of the certificate. + * + * The get callback is called once during the initial handshake + * to enable session resuming. The get function has the + * following parameters: (void *parameter, mbedtls_ssl_session *session) + * If a valid entry is found, it should fill the master of + * the session object with the cached values and return 0, + * return 1 otherwise. Optionally peer_cert can be set as well + * if it is properly present in cache entry. + * + * The set callback is called once during the initial handshake + * to enable session resuming after the entire handshake has + * been finished. The set function has the following parameters: + * (void *parameter, const mbedtls_ssl_session *session). The function + * should create a cache entry for future retrieval based on + * the data in the session structure and should keep in mind + * that the mbedtls_ssl_session object presented (and all its referenced + * data) is cleared by the SSL/TLS layer when the connection is + * terminated. It is recommended to add metadata to determine if + * an entry is still valid in the future. Return 0 if + * successfully cached, return 1 otherwise. + * + * \param conf SSL configuration + * \param p_cache parmater (context) for both callbacks + * \param f_get_cache session get callback + * \param f_set_cache session set callback + */ +void mbedtls_ssl_conf_session_cache( mbedtls_ssl_config *conf, + void *p_cache, + int (*f_get_cache)(void *, mbedtls_ssl_session *), + int (*f_set_cache)(void *, const mbedtls_ssl_session *) ); +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_CLI_C) +/** + * \brief Request resumption of session (client-side only) + * Session data is copied from presented session structure. + * + * \param ssl SSL context + * \param session session context + * + * \return 0 if successful, + * MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_SSL_BAD_INPUT_DATA if used server-side or + * arguments are otherwise invalid + * + * \sa mbedtls_ssl_get_session() + */ +int mbedtls_ssl_set_session( mbedtls_ssl_context *ssl, const mbedtls_ssl_session *session ); +#endif /* MBEDTLS_SSL_CLI_C */ + +/** + * \brief Load serialized session data into a session structure. + * On client, this can be used for loading saved sessions + * before resuming them with mbedstls_ssl_set_session(). + * On server, this can be used for alternative implementations + * of session cache or session tickets. + * + * \warning If a peer certificate chain is associated with the session, + * the serialized state will only contain the peer's + * end-entity certificate and the result of the chain + * verification (unless verification was disabled), but not + * the rest of the chain. + * + * \see mbedtls_ssl_session_save() + * \see mbedtls_ssl_set_session() + * + * \param session The session structure to be populated. It must have been + * initialised with mbedtls_ssl_session_init() but not + * populated yet. + * \param buf The buffer holding the serialized session data. It must be a + * readable buffer of at least \p len bytes. + * \param len The size of the serialized data in bytes. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed. + * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if input data is invalid. + * \return #MBEDTLS_ERR_SSL_VERSION_MISMATCH if the serialized data + * was generated in a different version or configuration of + * Mbed TLS. + * \return Another negative value for other kinds of errors (for + * example, unsupported features in the embedded certificate). + */ +int mbedtls_ssl_session_load( mbedtls_ssl_session *session, + const unsigned char *buf, + size_t len ); + +/** + * \brief Save session structure as serialized data in a buffer. + * On client, this can be used for saving session data, + * potentially in non-volatile storage, for resuming later. + * On server, this can be used for alternative implementations + * of session cache or session tickets. + * + * \see mbedtls_ssl_session_load() + * \see mbedtls_ssl_get_session_pointer() + * + * \param session The session structure to be saved. + * \param buf The buffer to write the serialized data to. It must be a + * writeable buffer of at least \p len bytes, or may be \c + * NULL if \p len is \c 0. + * \param buf_len The number of bytes available for writing in \p buf. + * \param olen The size in bytes of the data that has been or would have + * been written. It must point to a valid \c size_t. + * + * \note \p olen is updated to the correct value regardless of + * whether \p buf_len was large enough. This makes it possible + * to determine the necessary size by calling this function + * with \p buf set to \c NULL and \p buf_len to \c 0. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL if \p buf is too small. + */ +int mbedtls_ssl_session_save( const mbedtls_ssl_session *session, + unsigned char *buf, + size_t buf_len, + size_t *olen ); + +/** + * \brief Get a pointer to the current session structure, for example + * to serialize it. + * + * \warning Ownership of the session remains with the SSL context, and + * the returned pointer is only guaranteed to be valid until + * the next API call operating on the same \p ssl context. + * + * \see mbedtls_ssl_session_save() + * + * \param ssl The SSL context. + * + * \return A pointer to the current session if successful. + * \return \c NULL if no session is active. + */ +const mbedtls_ssl_session *mbedtls_ssl_get_session_pointer( const mbedtls_ssl_context *ssl ); + +/** + * \brief Set the list of allowed ciphersuites and the preference + * order. First in the list has the highest preference. + * (Overrides all version-specific lists) + * + * The ciphersuites array is not copied, and must remain + * valid for the lifetime of the ssl_config. + * + * Note: The server uses its own preferences + * over the preference of the client unless + * MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE is defined! + * + * \param conf SSL configuration + * \param ciphersuites 0-terminated list of allowed ciphersuites + */ +void mbedtls_ssl_conf_ciphersuites( mbedtls_ssl_config *conf, + const int *ciphersuites ); + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) +#define MBEDTLS_SSL_UNEXPECTED_CID_IGNORE 0 +#define MBEDTLS_SSL_UNEXPECTED_CID_FAIL 1 +/** + * \brief Specify the length of Connection IDs for incoming + * encrypted DTLS records, as well as the behaviour + * on unexpected CIDs. + * + * By default, the CID length is set to \c 0, + * and unexpected CIDs are silently ignored. + * + * \param conf The SSL configuration to modify. + * \param len The length in Bytes of the CID fields in encrypted + * DTLS records using the CID mechanism. This must + * not be larger than #MBEDTLS_SSL_CID_OUT_LEN_MAX. + * \param ignore_other_cids This determines the stack's behaviour when + * receiving a record with an unexpected CID. + * Possible values are: + * - #MBEDTLS_SSL_UNEXPECTED_CID_IGNORE + * In this case, the record is silently ignored. + * - #MBEDTLS_SSL_UNEXPECTED_CID_FAIL + * In this case, the stack fails with the specific + * error code #MBEDTLS_ERR_SSL_UNEXPECTED_CID. + * + * \note The CID specification allows implementations to either + * use a common length for all incoming connection IDs or + * allow variable-length incoming IDs. Mbed TLS currently + * requires a common length for all connections sharing the + * same SSL configuration; this allows simpler parsing of + * record headers. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if \p own_cid_len + * is too large. + */ +int mbedtls_ssl_conf_cid( mbedtls_ssl_config *conf, size_t len, + int ignore_other_cids ); +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + +/** + * \brief Set the list of allowed ciphersuites and the + * preference order for a specific version of the protocol. + * (Only useful on the server side) + * + * The ciphersuites array is not copied, and must remain + * valid for the lifetime of the ssl_config. + * + * \param conf SSL configuration + * \param ciphersuites 0-terminated list of allowed ciphersuites + * \param major Major version number (only MBEDTLS_SSL_MAJOR_VERSION_3 + * supported) + * \param minor Minor version number (MBEDTLS_SSL_MINOR_VERSION_0, + * MBEDTLS_SSL_MINOR_VERSION_1 and MBEDTLS_SSL_MINOR_VERSION_2, + * MBEDTLS_SSL_MINOR_VERSION_3 supported) + * + * \note With DTLS, use MBEDTLS_SSL_MINOR_VERSION_2 for DTLS 1.0 + * and MBEDTLS_SSL_MINOR_VERSION_3 for DTLS 1.2 + */ +void mbedtls_ssl_conf_ciphersuites_for_version( mbedtls_ssl_config *conf, + const int *ciphersuites, + int major, int minor ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * \brief Set the X.509 security profile used for verification + * + * \note The restrictions are enforced for all certificates in the + * chain. However, signatures in the handshake are not covered + * by this setting but by \b mbedtls_ssl_conf_sig_hashes(). + * + * \param conf SSL configuration + * \param profile Profile to use + */ +void mbedtls_ssl_conf_cert_profile( mbedtls_ssl_config *conf, + const mbedtls_x509_crt_profile *profile ); + +/** + * \brief Set the data required to verify peer certificate + * + * \note See \c mbedtls_x509_crt_verify() for notes regarding the + * parameters ca_chain (maps to trust_ca for that function) + * and ca_crl. + * + * \param conf SSL configuration + * \param ca_chain trusted CA chain (meaning all fully trusted top-level CAs) + * \param ca_crl trusted CA CRLs + */ +void mbedtls_ssl_conf_ca_chain( mbedtls_ssl_config *conf, + mbedtls_x509_crt *ca_chain, + mbedtls_x509_crl *ca_crl ); + +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) +/** + * \brief Set the trusted certificate callback. + * + * This API allows to register the set of trusted certificates + * through a callback, instead of a linked list as configured + * by mbedtls_ssl_conf_ca_chain(). + * + * This is useful for example in contexts where a large number + * of CAs are used, and the inefficiency of maintaining them + * in a linked list cannot be tolerated. It is also useful when + * the set of trusted CAs needs to be modified frequently. + * + * See the documentation of `mbedtls_x509_crt_ca_cb_t` for + * more information. + * + * \param conf The SSL configuration to register the callback with. + * \param f_ca_cb The trusted certificate callback to use when verifying + * certificate chains. + * \param p_ca_cb The context to be passed to \p f_ca_cb (for example, + * a reference to a trusted CA database). + * + * \note This API is incompatible with mbedtls_ssl_conf_ca_chain(): + * Any call to this function overwrites the values set through + * earlier calls to mbedtls_ssl_conf_ca_chain() or + * mbedtls_ssl_conf_ca_cb(). + * + * \note This API is incompatible with CA indication in + * CertificateRequest messages: A server-side SSL context which + * is bound to an SSL configuration that uses a CA callback + * configured via mbedtls_ssl_conf_ca_cb(), and which requires + * client authentication, will send an empty CA list in the + * corresponding CertificateRequest message. + * + * \note This API is incompatible with mbedtls_ssl_set_hs_ca_chain(): + * If an SSL context is bound to an SSL configuration which uses + * CA callbacks configured via mbedtls_ssl_conf_ca_cb(), then + * calls to mbedtls_ssl_set_hs_ca_chain() have no effect. + * + * \note The use of this API disables the use of restartable ECC + * during X.509 CRT signature verification (but doesn't affect + * other uses). + * + * \warning This API is incompatible with the use of CRLs. Any call to + * mbedtls_ssl_conf_ca_cb() unsets CRLs configured through + * earlier calls to mbedtls_ssl_conf_ca_chain(). + * + * \warning In multi-threaded environments, the callback \p f_ca_cb + * must be thread-safe, and it is the user's responsibility + * to guarantee this (for example through a mutex + * contained in the callback context pointed to by \p p_ca_cb). + */ +void mbedtls_ssl_conf_ca_cb( mbedtls_ssl_config *conf, + mbedtls_x509_crt_ca_cb_t f_ca_cb, + void *p_ca_cb ); +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ + +/** + * \brief Set own certificate chain and private key + * + * \note own_cert should contain in order from the bottom up your + * certificate chain. The top certificate (self-signed) + * can be omitted. + * + * \note On server, this function can be called multiple times to + * provision more than one cert/key pair (eg one ECDSA, one + * RSA with SHA-256, one RSA with SHA-1). An adequate + * certificate will be selected according to the client's + * advertised capabilities. In case multiple certificates are + * adequate, preference is given to the one set by the first + * call to this function, then second, etc. + * + * \note On client, only the first call has any effect. That is, + * only one client certificate can be provisioned. The + * server's preferences in its CertficateRequest message will + * be ignored and our only cert will be sent regardless of + * whether it matches those preferences - the server can then + * decide what it wants to do with it. + * + * \note The provided \p pk_key needs to match the public key in the + * first certificate in \p own_cert, or all handshakes using + * that certificate will fail. It is your responsibility + * to ensure that; this function will not perform any check. + * You may use mbedtls_pk_check_pair() in order to perform + * this check yourself, but be aware that this function can + * be computationally expensive on some key types. + * + * \param conf SSL configuration + * \param own_cert own public certificate chain + * \param pk_key own private key + * + * \return 0 on success or MBEDTLS_ERR_SSL_ALLOC_FAILED + */ +int mbedtls_ssl_conf_own_cert( mbedtls_ssl_config *conf, + mbedtls_x509_crt *own_cert, + mbedtls_pk_context *pk_key ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) +/** + * \brief Configure a pre-shared key (PSK) and identity + * to be used in PSK-based ciphersuites. + * + * \note This is mainly useful for clients. Servers will usually + * want to use \c mbedtls_ssl_conf_psk_cb() instead. + * + * \note A PSK set by \c mbedtls_ssl_set_hs_psk() in the PSK callback + * takes precedence over a PSK configured by this function. + * + * \warning Currently, clients can only register a single pre-shared key. + * Calling this function or mbedtls_ssl_conf_psk_opaque() more + * than once will overwrite values configured in previous calls. + * Support for setting multiple PSKs on clients and selecting + * one based on the identity hint is not a planned feature, + * but feedback is welcomed. + * + * \param conf The SSL configuration to register the PSK with. + * \param psk The pointer to the pre-shared key to use. + * \param psk_len The length of the pre-shared key in bytes. + * \param psk_identity The pointer to the pre-shared key identity. + * \param psk_identity_len The length of the pre-shared key identity + * in bytes. + * + * \note The PSK and its identity are copied internally and + * hence need not be preserved by the caller for the lifetime + * of the SSL configuration. + * + * \return \c 0 if successful. + * \return An \c MBEDTLS_ERR_SSL_XXX error code on failure. + */ +int mbedtls_ssl_conf_psk( mbedtls_ssl_config *conf, + const unsigned char *psk, size_t psk_len, + const unsigned char *psk_identity, size_t psk_identity_len ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/** + * \brief Configure an opaque pre-shared key (PSK) and identity + * to be used in PSK-based ciphersuites. + * + * \note This is mainly useful for clients. Servers will usually + * want to use \c mbedtls_ssl_conf_psk_cb() instead. + * + * \note An opaque PSK set by \c mbedtls_ssl_set_hs_psk_opaque() in + * the PSK callback takes precedence over an opaque PSK + * configured by this function. + * + * \warning Currently, clients can only register a single pre-shared key. + * Calling this function or mbedtls_ssl_conf_psk() more than + * once will overwrite values configured in previous calls. + * Support for setting multiple PSKs on clients and selecting + * one based on the identity hint is not a planned feature, + * but feedback is welcomed. + * + * \param conf The SSL configuration to register the PSK with. + * \param psk The identifier of the key slot holding the PSK. + * Until \p conf is destroyed or this function is successfully + * called again, the key slot \p psk must be populated with a + * key of type PSA_ALG_CATEGORY_KEY_DERIVATION whose policy + * allows its use for the key derivation algorithm applied + * in the handshake. + * \param psk_identity The pointer to the pre-shared key identity. + * \param psk_identity_len The length of the pre-shared key identity + * in bytes. + * + * \note The PSK identity hint is copied internally and hence need + * not be preserved by the caller for the lifetime of the + * SSL configuration. + * + * \return \c 0 if successful. + * \return An \c MBEDTLS_ERR_SSL_XXX error code on failure. + */ +int mbedtls_ssl_conf_psk_opaque( mbedtls_ssl_config *conf, + psa_key_handle_t psk, + const unsigned char *psk_identity, + size_t psk_identity_len ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +/** + * \brief Set the pre-shared Key (PSK) for the current handshake. + * + * \note This should only be called inside the PSK callback, + * i.e. the function passed to \c mbedtls_ssl_conf_psk_cb(). + * + * \note A PSK set by this function takes precedence over a PSK + * configured by \c mbedtls_ssl_conf_psk(). + * + * \param ssl The SSL context to configure a PSK for. + * \param psk The pointer to the pre-shared key. + * \param psk_len The length of the pre-shared key in bytes. + * + * \return \c 0 if successful. + * \return An \c MBEDTLS_ERR_SSL_XXX error code on failure. + */ +int mbedtls_ssl_set_hs_psk( mbedtls_ssl_context *ssl, + const unsigned char *psk, size_t psk_len ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/** + * \brief Set an opaque pre-shared Key (PSK) for the current handshake. + * + * \note This should only be called inside the PSK callback, + * i.e. the function passed to \c mbedtls_ssl_conf_psk_cb(). + * + * \note An opaque PSK set by this function takes precedence over an + * opaque PSK configured by \c mbedtls_ssl_conf_psk_opaque(). + * + * \param ssl The SSL context to configure a PSK for. + * \param psk The identifier of the key slot holding the PSK. + * For the duration of the current handshake, the key slot + * must be populated with a key of type + * PSA_ALG_CATEGORY_KEY_DERIVATION whose policy allows its + * use for the key derivation algorithm + * applied in the handshake. + * + * \return \c 0 if successful. + * \return An \c MBEDTLS_ERR_SSL_XXX error code on failure. + */ +int mbedtls_ssl_set_hs_psk_opaque( mbedtls_ssl_context *ssl, + psa_key_handle_t psk ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +/** + * \brief Set the PSK callback (server-side only). + * + * If set, the PSK callback is called for each + * handshake where a PSK-based ciphersuite was negotiated. + * The caller provides the identity received and wants to + * receive the actual PSK data and length. + * + * The callback has the following parameters: + * - \c void*: The opaque pointer \p p_psk. + * - \c mbedtls_ssl_context*: The SSL context to which + * the operation applies. + * - \c const unsigned char*: The PSK identity + * selected by the client. + * - \c size_t: The length of the PSK identity + * selected by the client. + * + * If a valid PSK identity is found, the callback should use + * \c mbedtls_ssl_set_hs_psk() or + * \c mbedtls_ssl_set_hs_psk_opaque() + * on the SSL context to set the correct PSK and return \c 0. + * Any other return value will result in a denied PSK identity. + * + * \note A dynamic PSK (i.e. set by the PSK callback) takes + * precedence over a static PSK (i.e. set by + * \c mbedtls_ssl_conf_psk() or + * \c mbedtls_ssl_conf_psk_opaque()). + * This means that if you set a PSK callback using this + * function, you don't need to set a PSK using + * \c mbedtls_ssl_conf_psk() or + * \c mbedtls_ssl_conf_psk_opaque()). + * + * \param conf The SSL configuration to register the callback with. + * \param f_psk The callback for selecting and setting the PSK based + * in the PSK identity chosen by the client. + * \param p_psk A pointer to an opaque structure to be passed to + * the callback, for example a PSK store. + */ +void mbedtls_ssl_conf_psk_cb( mbedtls_ssl_config *conf, + int (*f_psk)(void *, mbedtls_ssl_context *, const unsigned char *, + size_t), + void *p_psk ); +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif + +/** + * \brief Set the Diffie-Hellman public P and G values, + * read as hexadecimal strings (server-side only) + * (Default values: MBEDTLS_DHM_RFC3526_MODP_2048_[PG]) + * + * \param conf SSL configuration + * \param dhm_P Diffie-Hellman-Merkle modulus + * \param dhm_G Diffie-Hellman-Merkle generator + * + * \deprecated Superseded by \c mbedtls_ssl_conf_dh_param_bin. + * + * \return 0 if successful + */ +MBEDTLS_DEPRECATED int mbedtls_ssl_conf_dh_param( mbedtls_ssl_config *conf, + const char *dhm_P, + const char *dhm_G ); + +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Set the Diffie-Hellman public P and G values + * from big-endian binary presentations. + * (Default values: MBEDTLS_DHM_RFC3526_MODP_2048_[PG]_BIN) + * + * \param conf SSL configuration + * \param dhm_P Diffie-Hellman-Merkle modulus in big-endian binary form + * \param P_len Length of DHM modulus + * \param dhm_G Diffie-Hellman-Merkle generator in big-endian binary form + * \param G_len Length of DHM generator + * + * \return 0 if successful + */ +int mbedtls_ssl_conf_dh_param_bin( mbedtls_ssl_config *conf, + const unsigned char *dhm_P, size_t P_len, + const unsigned char *dhm_G, size_t G_len ); + +/** + * \brief Set the Diffie-Hellman public P and G values, + * read from existing context (server-side only) + * + * \param conf SSL configuration + * \param dhm_ctx Diffie-Hellman-Merkle context + * + * \return 0 if successful + */ +int mbedtls_ssl_conf_dh_param_ctx( mbedtls_ssl_config *conf, mbedtls_dhm_context *dhm_ctx ); +#endif /* MBEDTLS_DHM_C && defined(MBEDTLS_SSL_SRV_C) */ + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) +/** + * \brief Set the minimum length for Diffie-Hellman parameters. + * (Client-side only.) + * (Default: 1024 bits.) + * + * \param conf SSL configuration + * \param bitlen Minimum bit length of the DHM prime + */ +void mbedtls_ssl_conf_dhm_min_bitlen( mbedtls_ssl_config *conf, + unsigned int bitlen ); +#endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_ECP_C) +/** + * \brief Set the allowed curves in order of preference. + * (Default: all defined curves.) + * + * On server: this only affects selection of the ECDHE curve; + * the curves used for ECDH and ECDSA are determined by the + * list of available certificates instead. + * + * On client: this affects the list of curves offered for any + * use. The server can override our preference order. + * + * Both sides: limits the set of curves accepted for use in + * ECDHE and in the peer's end-entity certificate. + * + * \note This has no influence on which curves are allowed inside the + * certificate chains, see \c mbedtls_ssl_conf_cert_profile() + * for that. For the end-entity certificate however, the key + * will be accepted only if it is allowed both by this list + * and by the cert profile. + * + * \note This list should be ordered by decreasing preference + * (preferred curve first). + * + * \param conf SSL configuration + * \param curves Ordered list of allowed curves, + * terminated by MBEDTLS_ECP_DP_NONE. + */ +void mbedtls_ssl_conf_curves( mbedtls_ssl_config *conf, + const mbedtls_ecp_group_id *curves ); +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) +/** + * \brief Set the allowed hashes for signatures during the handshake. + * (Default: all available hashes except MD5.) + * + * \note This only affects which hashes are offered and can be used + * for signatures during the handshake. Hashes for message + * authentication and the TLS PRF are controlled by the + * ciphersuite, see \c mbedtls_ssl_conf_ciphersuites(). Hashes + * used for certificate signature are controlled by the + * verification profile, see \c mbedtls_ssl_conf_cert_profile(). + * + * \note This list should be ordered by decreasing preference + * (preferred hash first). + * + * \param conf SSL configuration + * \param hashes Ordered list of allowed signature hashes, + * terminated by \c MBEDTLS_MD_NONE. + */ +void mbedtls_ssl_conf_sig_hashes( mbedtls_ssl_config *conf, + const int *hashes ); +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * \brief Set or reset the hostname to check against the received + * server certificate. It sets the ServerName TLS extension, + * too, if that extension is enabled. (client-side only) + * + * \param ssl SSL context + * \param hostname the server hostname, may be NULL to clear hostname + + * \note Maximum hostname length MBEDTLS_SSL_MAX_HOST_NAME_LEN. + * + * \return 0 if successful, MBEDTLS_ERR_SSL_ALLOC_FAILED on + * allocation failure, MBEDTLS_ERR_SSL_BAD_INPUT_DATA on + * too long input hostname. + * + * Hostname set to the one provided on success (cleared + * when NULL). On allocation failure hostname is cleared. + * On too long input failure, old hostname is unchanged. + */ +int mbedtls_ssl_set_hostname( mbedtls_ssl_context *ssl, const char *hostname ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +/** + * \brief Set own certificate and key for the current handshake + * + * \note Same as \c mbedtls_ssl_conf_own_cert() but for use within + * the SNI callback. + * + * \param ssl SSL context + * \param own_cert own public certificate chain + * \param pk_key own private key + * + * \return 0 on success or MBEDTLS_ERR_SSL_ALLOC_FAILED + */ +int mbedtls_ssl_set_hs_own_cert( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *own_cert, + mbedtls_pk_context *pk_key ); + +/** + * \brief Set the data required to verify peer certificate for the + * current handshake + * + * \note Same as \c mbedtls_ssl_conf_ca_chain() but for use within + * the SNI callback. + * + * \param ssl SSL context + * \param ca_chain trusted CA chain (meaning all fully trusted top-level CAs) + * \param ca_crl trusted CA CRLs + */ +void mbedtls_ssl_set_hs_ca_chain( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *ca_chain, + mbedtls_x509_crl *ca_crl ); + +/** + * \brief Set authmode for the current handshake. + * + * \note Same as \c mbedtls_ssl_conf_authmode() but for use within + * the SNI callback. + * + * \param ssl SSL context + * \param authmode MBEDTLS_SSL_VERIFY_NONE, MBEDTLS_SSL_VERIFY_OPTIONAL or + * MBEDTLS_SSL_VERIFY_REQUIRED + */ +void mbedtls_ssl_set_hs_authmode( mbedtls_ssl_context *ssl, + int authmode ); + +/** + * \brief Set server side ServerName TLS extension callback + * (optional, server-side only). + * + * If set, the ServerName callback is called whenever the + * server receives a ServerName TLS extension from the client + * during a handshake. The ServerName callback has the + * following parameters: (void *parameter, mbedtls_ssl_context *ssl, + * const unsigned char *hostname, size_t len). If a suitable + * certificate is found, the callback must set the + * certificate(s) and key(s) to use with \c + * mbedtls_ssl_set_hs_own_cert() (can be called repeatedly), + * and may optionally adjust the CA and associated CRL with \c + * mbedtls_ssl_set_hs_ca_chain() as well as the client + * authentication mode with \c mbedtls_ssl_set_hs_authmode(), + * then must return 0. If no matching name is found, the + * callback must either set a default cert, or + * return non-zero to abort the handshake at this point. + * + * \param conf SSL configuration + * \param f_sni verification function + * \param p_sni verification parameter + */ +void mbedtls_ssl_conf_sni( mbedtls_ssl_config *conf, + int (*f_sni)(void *, mbedtls_ssl_context *, const unsigned char *, + size_t), + void *p_sni ); +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +/** + * \brief Set the EC J-PAKE password for current handshake. + * + * \note An internal copy is made, and destroyed as soon as the + * handshake is completed, or when the SSL context is reset or + * freed. + * + * \note The SSL context needs to be already set up. The right place + * to call this function is between \c mbedtls_ssl_setup() or + * \c mbedtls_ssl_reset() and \c mbedtls_ssl_handshake(). + * + * \param ssl SSL context + * \param pw EC J-PAKE password (pre-shared secret) + * \param pw_len length of pw in bytes + * + * \return 0 on success, or a negative error code. + */ +int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl, + const unsigned char *pw, + size_t pw_len ); +#endif /*MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_ALPN) +/** + * \brief Set the supported Application Layer Protocols. + * + * \param conf SSL configuration + * \param protos Pointer to a NULL-terminated list of supported protocols, + * in decreasing preference order. The pointer to the list is + * recorded by the library for later reference as required, so + * the lifetime of the table must be atleast as long as the + * lifetime of the SSL configuration structure. + * + * \return 0 on success, or MBEDTLS_ERR_SSL_BAD_INPUT_DATA. + */ +int mbedtls_ssl_conf_alpn_protocols( mbedtls_ssl_config *conf, const char **protos ); + +/** + * \brief Get the name of the negotiated Application Layer Protocol. + * This function should be called after the handshake is + * completed. + * + * \param ssl SSL context + * + * \return Protcol name, or NULL if no protocol was negotiated. + */ +const char *mbedtls_ssl_get_alpn_protocol( const mbedtls_ssl_context *ssl ); +#endif /* MBEDTLS_SSL_ALPN */ + +#if defined(MBEDTLS_SSL_DTLS_SRTP) +#if defined(MBEDTLS_DEBUG_C) +static inline const char *mbedtls_ssl_get_srtp_profile_as_string( mbedtls_ssl_srtp_profile profile ) +{ + switch( profile ) + { + case MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_80: + return( "MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_80" ); + case MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_32: + return( "MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_32" ); + case MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_80: + return( "MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_80" ); + case MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_32: + return( "MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_32" ); + default: break; + } + return( "" ); +} +#endif /* MBEDTLS_DEBUG_C */ +/** + * \brief Manage support for mki(master key id) value + * in use_srtp extension. + * MKI is an optional part of SRTP used for key management + * and re-keying. See RFC3711 section 3.1 for details. + * The default value is + * #MBEDTLS_SSL_DTLS_SRTP_MKI_UNSUPPORTED. + * + * \param conf The SSL configuration to manage mki support. + * \param support_mki_value Enable or disable mki usage. Values are + * #MBEDTLS_SSL_DTLS_SRTP_MKI_UNSUPPORTED + * or #MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED. + */ +void mbedtls_ssl_conf_srtp_mki_value_supported( mbedtls_ssl_config *conf, + int support_mki_value ); + +/** + * \brief Set the supported DTLS-SRTP protection profiles. + * + * \param conf SSL configuration + * \param profiles Pointer to a List of MBEDTLS_TLS_SRTP_UNSET terminated + * supported protection profiles + * in decreasing preference order. + * The pointer to the list is recorded by the library + * for later reference as required, so the lifetime + * of the table must be at least as long as the lifetime + * of the SSL configuration structure. + * The list must not hold more than + * MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH elements + * (excluding the terminating MBEDTLS_TLS_SRTP_UNSET). + * + * \return 0 on success + * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA when the list of + * protection profiles is incorrect. + */ +int mbedtls_ssl_conf_dtls_srtp_protection_profiles + ( mbedtls_ssl_config *conf, + const mbedtls_ssl_srtp_profile *profiles ); + +/** + * \brief Set the mki_value for the current DTLS-SRTP session. + * + * \param ssl SSL context to use. + * \param mki_value The MKI value to set. + * \param mki_len The length of the MKI value. + * + * \note This function is relevant on client side only. + * The server discovers the mki value during handshake. + * A mki value set on server side using this function + * is ignored. + * + * \return 0 on success + * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA + * \return #MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE + */ +int mbedtls_ssl_dtls_srtp_set_mki_value( mbedtls_ssl_context *ssl, + unsigned char *mki_value, + uint16_t mki_len ); +/** + * \brief Get the negotiated DTLS-SRTP informations: + * Protection profile and MKI value. + * + * \warning This function must be called after the handshake is + * completed. The value returned by this function must + * not be trusted or acted upon before the handshake completes. + * + * \param ssl The SSL context to query. + * \param dtls_srtp_info The negotiated DTLS-SRTP informations: + * - Protection profile in use. + * A direct mapping of the iana defined value for protection + * profile on an uint16_t. + http://www.iana.org/assignments/srtp-protection/srtp-protection.xhtml + * #MBEDTLS_TLS_SRTP_UNSET if the use of SRTP was not negotiated + * or peer's Hello packet was not parsed yet. + * - mki size and value( if size is > 0 ). + */ +void mbedtls_ssl_get_dtls_srtp_negotiation_result( const mbedtls_ssl_context *ssl, + mbedtls_dtls_srtp_info *dtls_srtp_info ); +#endif /* MBEDTLS_SSL_DTLS_SRTP */ + +/** + * \brief Set the maximum supported version sent from the client side + * and/or accepted at the server side + * (Default: MBEDTLS_SSL_MAX_MAJOR_VERSION, MBEDTLS_SSL_MAX_MINOR_VERSION) + * + * \note This ignores ciphersuites from higher versions. + * + * \note With DTLS, use MBEDTLS_SSL_MINOR_VERSION_2 for DTLS 1.0 and + * MBEDTLS_SSL_MINOR_VERSION_3 for DTLS 1.2 + * + * \param conf SSL configuration + * \param major Major version number (only MBEDTLS_SSL_MAJOR_VERSION_3 supported) + * \param minor Minor version number (MBEDTLS_SSL_MINOR_VERSION_0, + * MBEDTLS_SSL_MINOR_VERSION_1 and MBEDTLS_SSL_MINOR_VERSION_2, + * MBEDTLS_SSL_MINOR_VERSION_3 supported) + */ +void mbedtls_ssl_conf_max_version( mbedtls_ssl_config *conf, int major, int minor ); + +/** + * \brief Set the minimum accepted SSL/TLS protocol version + * (Default: TLS 1.0) + * + * \note Input outside of the SSL_MAX_XXXXX_VERSION and + * SSL_MIN_XXXXX_VERSION range is ignored. + * + * \note MBEDTLS_SSL_MINOR_VERSION_0 (SSL v3) should be avoided. + * + * \note With DTLS, use MBEDTLS_SSL_MINOR_VERSION_2 for DTLS 1.0 and + * MBEDTLS_SSL_MINOR_VERSION_3 for DTLS 1.2 + * + * \param conf SSL configuration + * \param major Major version number (only MBEDTLS_SSL_MAJOR_VERSION_3 supported) + * \param minor Minor version number (MBEDTLS_SSL_MINOR_VERSION_0, + * MBEDTLS_SSL_MINOR_VERSION_1 and MBEDTLS_SSL_MINOR_VERSION_2, + * MBEDTLS_SSL_MINOR_VERSION_3 supported) + */ +void mbedtls_ssl_conf_min_version( mbedtls_ssl_config *conf, int major, int minor ); + +#if defined(MBEDTLS_SSL_FALLBACK_SCSV) && defined(MBEDTLS_SSL_CLI_C) +/** + * \brief Set the fallback flag (client-side only). + * (Default: MBEDTLS_SSL_IS_NOT_FALLBACK). + * + * \note Set to MBEDTLS_SSL_IS_FALLBACK when preparing a fallback + * connection, that is a connection with max_version set to a + * lower value than the value you're willing to use. Such + * fallback connections are not recommended but are sometimes + * necessary to interoperate with buggy (version-intolerant) + * servers. + * + * \warning You should NOT set this to MBEDTLS_SSL_IS_FALLBACK for + * non-fallback connections! This would appear to work for a + * while, then cause failures when the server is upgraded to + * support a newer TLS version. + * + * \param conf SSL configuration + * \param fallback MBEDTLS_SSL_IS_NOT_FALLBACK or MBEDTLS_SSL_IS_FALLBACK + */ +void mbedtls_ssl_conf_fallback( mbedtls_ssl_config *conf, char fallback ); +#endif /* MBEDTLS_SSL_FALLBACK_SCSV && MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +/** + * \brief Enable or disable Encrypt-then-MAC + * (Default: MBEDTLS_SSL_ETM_ENABLED) + * + * \note This should always be enabled, it is a security + * improvement, and should not cause any interoperability + * issue (used only if the peer supports it too). + * + * \param conf SSL configuration + * \param etm MBEDTLS_SSL_ETM_ENABLED or MBEDTLS_SSL_ETM_DISABLED + */ +void mbedtls_ssl_conf_encrypt_then_mac( mbedtls_ssl_config *conf, char etm ); +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +/** + * \brief Enable or disable Extended Master Secret negotiation. + * (Default: MBEDTLS_SSL_EXTENDED_MS_ENABLED) + * + * \note This should always be enabled, it is a security fix to the + * protocol, and should not cause any interoperability issue + * (used only if the peer supports it too). + * + * \param conf SSL configuration + * \param ems MBEDTLS_SSL_EXTENDED_MS_ENABLED or MBEDTLS_SSL_EXTENDED_MS_DISABLED + */ +void mbedtls_ssl_conf_extended_master_secret( mbedtls_ssl_config *conf, char ems ); +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_ARC4_C) +/** + * \brief Disable or enable support for RC4 + * (Default: MBEDTLS_SSL_ARC4_DISABLED) + * + * \warning Use of RC4 in DTLS/TLS has been prohibited by RFC 7465 + * for security reasons. Use at your own risk. + * + * \note This function is deprecated and will be removed in + * a future version of the library. + * RC4 is disabled by default at compile time and needs to be + * actively enabled for use with legacy systems. + * + * \param conf SSL configuration + * \param arc4 MBEDTLS_SSL_ARC4_ENABLED or MBEDTLS_SSL_ARC4_DISABLED + */ +void mbedtls_ssl_conf_arc4_support( mbedtls_ssl_config *conf, char arc4 ); +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_SSL_SRV_C) +/** + * \brief Whether to send a list of acceptable CAs in + * CertificateRequest messages. + * (Default: do send) + * + * \param conf SSL configuration + * \param cert_req_ca_list MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED or + * MBEDTLS_SSL_CERT_REQ_CA_LIST_DISABLED + */ +void mbedtls_ssl_conf_cert_req_ca_list( mbedtls_ssl_config *conf, + char cert_req_ca_list ); +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +/** + * \brief Set the maximum fragment length to emit and/or negotiate. + * (Typical: the smaller of #MBEDTLS_SSL_IN_CONTENT_LEN and + * #MBEDTLS_SSL_OUT_CONTENT_LEN, usually `2^14` bytes) + * (Server: set maximum fragment length to emit, + * usually negotiated by the client during handshake) + * (Client: set maximum fragment length to emit *and* + * negotiate with the server during handshake) + * (Default: #MBEDTLS_SSL_MAX_FRAG_LEN_NONE) + * + * \note On the client side, the maximum fragment length extension + * *will not* be used, unless the maximum fragment length has + * been set via this function to a value different than + * #MBEDTLS_SSL_MAX_FRAG_LEN_NONE. + * + * \note With TLS, this currently only affects ApplicationData (sent + * with \c mbedtls_ssl_read()), not handshake messages. + * With DTLS, this affects both ApplicationData and handshake. + * + * \note This sets the maximum length for a record's payload, + * excluding record overhead that will be added to it, see + * \c mbedtls_ssl_get_record_expansion(). + * + * \note For DTLS, it is also possible to set a limit for the total + * size of daragrams passed to the transport layer, including + * record overhead, see \c mbedtls_ssl_set_mtu(). + * + * \param conf SSL configuration + * \param mfl_code Code for maximum fragment length (allowed values: + * MBEDTLS_SSL_MAX_FRAG_LEN_512, MBEDTLS_SSL_MAX_FRAG_LEN_1024, + * MBEDTLS_SSL_MAX_FRAG_LEN_2048, MBEDTLS_SSL_MAX_FRAG_LEN_4096) + * + * \return 0 if successful or MBEDTLS_ERR_SSL_BAD_INPUT_DATA + */ +int mbedtls_ssl_conf_max_frag_len( mbedtls_ssl_config *conf, unsigned char mfl_code ); +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) +/** + * \brief Activate negotiation of truncated HMAC + * (Default: MBEDTLS_SSL_TRUNC_HMAC_DISABLED) + * + * \param conf SSL configuration + * \param truncate Enable or disable (MBEDTLS_SSL_TRUNC_HMAC_ENABLED or + * MBEDTLS_SSL_TRUNC_HMAC_DISABLED) + */ +void mbedtls_ssl_conf_truncated_hmac( mbedtls_ssl_config *conf, int truncate ); +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) +/** + * \brief Enable / Disable 1/n-1 record splitting + * (Default: MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED) + * + * \note Only affects SSLv3 and TLS 1.0, not higher versions. + * Does not affect non-CBC ciphersuites in any version. + * + * \param conf SSL configuration + * \param split MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED or + * MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED + */ +void mbedtls_ssl_conf_cbc_record_splitting( mbedtls_ssl_config *conf, char split ); +#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) +/** + * \brief Enable / Disable session tickets (client only). + * (Default: MBEDTLS_SSL_SESSION_TICKETS_ENABLED.) + * + * \note On server, use \c mbedtls_ssl_conf_session_tickets_cb(). + * + * \param conf SSL configuration + * \param use_tickets Enable or disable (MBEDTLS_SSL_SESSION_TICKETS_ENABLED or + * MBEDTLS_SSL_SESSION_TICKETS_DISABLED) + */ +void mbedtls_ssl_conf_session_tickets( mbedtls_ssl_config *conf, int use_tickets ); +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +/** + * \brief Enable / Disable renegotiation support for connection when + * initiated by peer + * (Default: MBEDTLS_SSL_RENEGOTIATION_DISABLED) + * + * \warning It is recommended to always disable renegotation unless you + * know you need it and you know what you're doing. In the + * past, there have been several issues associated with + * renegotiation or a poor understanding of its properties. + * + * \note Server-side, enabling renegotiation also makes the server + * susceptible to a resource DoS by a malicious client. + * + * \param conf SSL configuration + * \param renegotiation Enable or disable (MBEDTLS_SSL_RENEGOTIATION_ENABLED or + * MBEDTLS_SSL_RENEGOTIATION_DISABLED) + */ +void mbedtls_ssl_conf_renegotiation( mbedtls_ssl_config *conf, int renegotiation ); +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +/** + * \brief Prevent or allow legacy renegotiation. + * (Default: MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION) + * + * MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION allows connections to + * be established even if the peer does not support + * secure renegotiation, but does not allow renegotiation + * to take place if not secure. + * (Interoperable and secure option) + * + * MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION allows renegotiations + * with non-upgraded peers. Allowing legacy renegotiation + * makes the connection vulnerable to specific man in the + * middle attacks. (See RFC 5746) + * (Most interoperable and least secure option) + * + * MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE breaks off connections + * if peer does not support secure renegotiation. Results + * in interoperability issues with non-upgraded peers + * that do not support renegotiation altogether. + * (Most secure option, interoperability issues) + * + * \param conf SSL configuration + * \param allow_legacy Prevent or allow (SSL_NO_LEGACY_RENEGOTIATION, + * SSL_ALLOW_LEGACY_RENEGOTIATION or + * MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE) + */ +void mbedtls_ssl_conf_legacy_renegotiation( mbedtls_ssl_config *conf, int allow_legacy ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +/** + * \brief Enforce renegotiation requests. + * (Default: enforced, max_records = 16) + * + * When we request a renegotiation, the peer can comply or + * ignore the request. This function allows us to decide + * whether to enforce our renegotiation requests by closing + * the connection if the peer doesn't comply. + * + * However, records could already be in transit from the peer + * when the request is emitted. In order to increase + * reliability, we can accept a number of records before the + * expected handshake records. + * + * The optimal value is highly dependent on the specific usage + * scenario. + * + * \note With DTLS and server-initiated renegotiation, the + * HelloRequest is retransmited every time mbedtls_ssl_read() times + * out or receives Application Data, until: + * - max_records records have beens seen, if it is >= 0, or + * - the number of retransmits that would happen during an + * actual handshake has been reached. + * Please remember the request might be lost a few times + * if you consider setting max_records to a really low value. + * + * \warning On client, the grace period can only happen during + * mbedtls_ssl_read(), as opposed to mbedtls_ssl_write() and mbedtls_ssl_renegotiate() + * which always behave as if max_record was 0. The reason is, + * if we receive application data from the server, we need a + * place to write it, which only happens during mbedtls_ssl_read(). + * + * \param conf SSL configuration + * \param max_records Use MBEDTLS_SSL_RENEGOTIATION_NOT_ENFORCED if you don't want to + * enforce renegotiation, or a non-negative value to enforce + * it but allow for a grace period of max_records records. + */ +void mbedtls_ssl_conf_renegotiation_enforced( mbedtls_ssl_config *conf, int max_records ); + +/** + * \brief Set record counter threshold for periodic renegotiation. + * (Default: 2^48 - 1) + * + * Renegotiation is automatically triggered when a record + * counter (outgoing or incoming) crosses the defined + * threshold. The default value is meant to prevent the + * connection from being closed when the counter is about to + * reached its maximal value (it is not allowed to wrap). + * + * Lower values can be used to enforce policies such as "keys + * must be refreshed every N packets with cipher X". + * + * The renegotiation period can be disabled by setting + * conf->disable_renegotiation to + * MBEDTLS_SSL_RENEGOTIATION_DISABLED. + * + * \note When the configured transport is + * MBEDTLS_SSL_TRANSPORT_DATAGRAM the maximum renegotiation + * period is 2^48 - 1, and for MBEDTLS_SSL_TRANSPORT_STREAM, + * the maximum renegotiation period is 2^64 - 1. + * + * \param conf SSL configuration + * \param period The threshold value: a big-endian 64-bit number. + */ +void mbedtls_ssl_conf_renegotiation_period( mbedtls_ssl_config *conf, + const unsigned char period[8] ); +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +/** + * \brief Check if there is data already read from the + * underlying transport but not yet processed. + * + * \param ssl SSL context + * + * \return 0 if nothing's pending, 1 otherwise. + * + * \note This is different in purpose and behaviour from + * \c mbedtls_ssl_get_bytes_avail in that it considers + * any kind of unprocessed data, not only unread + * application data. If \c mbedtls_ssl_get_bytes + * returns a non-zero value, this function will + * also signal pending data, but the converse does + * not hold. For example, in DTLS there might be + * further records waiting to be processed from + * the current underlying transport's datagram. + * + * \note If this function returns 1 (data pending), this + * does not imply that a subsequent call to + * \c mbedtls_ssl_read will provide any data; + * e.g., the unprocessed data might turn out + * to be an alert or a handshake message. + * + * \note This function is useful in the following situation: + * If the SSL/TLS module successfully returns from an + * operation - e.g. a handshake or an application record + * read - and you're awaiting incoming data next, you + * must not immediately idle on the underlying transport + * to have data ready, but you need to check the value + * of this function first. The reason is that the desired + * data might already be read but not yet processed. + * If, in contrast, a previous call to the SSL/TLS module + * returned MBEDTLS_ERR_SSL_WANT_READ, it is not necessary + * to call this function, as the latter error code entails + * that all internal data has been processed. + * + */ +int mbedtls_ssl_check_pending( const mbedtls_ssl_context *ssl ); + +/** + * \brief Return the number of application data bytes + * remaining to be read from the current record. + * + * \param ssl SSL context + * + * \return How many bytes are available in the application + * data record read buffer. + * + * \note When working over a datagram transport, this is + * useful to detect the current datagram's boundary + * in case \c mbedtls_ssl_read has written the maximal + * amount of data fitting into the input buffer. + * + */ +size_t mbedtls_ssl_get_bytes_avail( const mbedtls_ssl_context *ssl ); + +/** + * \brief Return the result of the certificate verification + * + * \param ssl The SSL context to use. + * + * \return \c 0 if the certificate verification was successful. + * \return \c -1u if the result is not available. This may happen + * e.g. if the handshake aborts early, or a verification + * callback returned a fatal error. + * \return A bitwise combination of \c MBEDTLS_X509_BADCERT_XXX + * and \c MBEDTLS_X509_BADCRL_XXX failure flags; see x509.h. + */ +uint32_t mbedtls_ssl_get_verify_result( const mbedtls_ssl_context *ssl ); + +/** + * \brief Return the name of the current ciphersuite + * + * \param ssl SSL context + * + * \return a string containing the ciphersuite name + */ +const char *mbedtls_ssl_get_ciphersuite( const mbedtls_ssl_context *ssl ); + +/** + * \brief Return the current SSL version (SSLv3/TLSv1/etc) + * + * \param ssl SSL context + * + * \return a string containing the SSL version + */ +const char *mbedtls_ssl_get_version( const mbedtls_ssl_context *ssl ); + +/** + * \brief Return the (maximum) number of bytes added by the record + * layer: header + encryption/MAC overhead (inc. padding) + * + * \note This function is not available (always returns an error) + * when record compression is enabled. + * + * \param ssl SSL context + * + * \return Current maximum record expansion in bytes, or + * MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE if compression is + * enabled, which makes expansion much less predictable + */ +int mbedtls_ssl_get_record_expansion( const mbedtls_ssl_context *ssl ); + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +/** + * \brief Return the maximum fragment length (payload, in bytes) for + * the output buffer. For the client, this is the configured + * value. For the server, it is the minimum of two - the + * configured value and the negotiated one. + * + * \sa mbedtls_ssl_conf_max_frag_len() + * \sa mbedtls_ssl_get_max_record_payload() + * + * \param ssl SSL context + * + * \return Current maximum fragment length for the output buffer. + */ +size_t mbedtls_ssl_get_output_max_frag_len( const mbedtls_ssl_context *ssl ); + +/** + * \brief Return the maximum fragment length (payload, in bytes) for + * the input buffer. This is the negotiated maximum fragment + * length, or, if there is none, MBEDTLS_SSL_MAX_CONTENT_LEN. + * If it is not defined either, the value is 2^14. This function + * works as its predecessor, \c mbedtls_ssl_get_max_frag_len(). + * + * \sa mbedtls_ssl_conf_max_frag_len() + * \sa mbedtls_ssl_get_max_record_payload() + * + * \param ssl SSL context + * + * \return Current maximum fragment length for the output buffer. + */ +size_t mbedtls_ssl_get_input_max_frag_len( const mbedtls_ssl_context *ssl ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif + +/** + * \brief This function is a deprecated approach to getting the max + * fragment length. Its an alias for + * \c mbedtls_ssl_get_output_max_frag_len(), as the behaviour + * is the same. See \c mbedtls_ssl_get_output_max_frag_len() for + * more detail. + * + * \sa mbedtls_ssl_get_input_max_frag_len() + * \sa mbedtls_ssl_get_output_max_frag_len() + * + * \param ssl SSL context + * + * \return Current maximum fragment length for the output buffer. + */ +MBEDTLS_DEPRECATED size_t mbedtls_ssl_get_max_frag_len( + const mbedtls_ssl_context *ssl ); +#endif /* MBEDTLS_DEPRECATED_REMOVED */ +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +/** + * \brief Return the current maximum outgoing record payload in bytes. + * This takes into account the config.h setting \c + * MBEDTLS_SSL_OUT_CONTENT_LEN, the configured and negotiated + * max fragment length extension if used, and for DTLS the + * path MTU as configured and current record expansion. + * + * \note With DTLS, \c mbedtls_ssl_write() will return an error if + * called with a larger length value. + * With TLS, \c mbedtls_ssl_write() will fragment the input if + * necessary and return the number of bytes written; it is up + * to the caller to call \c mbedtls_ssl_write() again in + * order to send the remaining bytes if any. + * + * \note This function is not available (always returns an error) + * when record compression is enabled. + * + * \sa mbedtls_ssl_set_mtu() + * \sa mbedtls_ssl_get_output_max_frag_len() + * \sa mbedtls_ssl_get_input_max_frag_len() + * \sa mbedtls_ssl_get_record_expansion() + * + * \param ssl SSL context + * + * \return Current maximum payload for an outgoing record, + * or a negative error code. + */ +int mbedtls_ssl_get_max_out_record_payload( const mbedtls_ssl_context *ssl ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * \brief Return the peer certificate from the current connection. + * + * \param ssl The SSL context to use. This must be initialized and setup. + * + * \return The current peer certificate, if available. + * The returned certificate is owned by the SSL context and + * is valid only until the next call to the SSL API. + * \return \c NULL if no peer certificate is available. This might + * be because the chosen ciphersuite doesn't use CRTs + * (PSK-based ciphersuites, for example), or because + * #MBEDTLS_SSL_KEEP_PEER_CERTIFICATE has been disabled, + * allowing the stack to free the peer's CRT to save memory. + * + * \note For one-time inspection of the peer's certificate during + * the handshake, consider registering an X.509 CRT verification + * callback through mbedtls_ssl_conf_verify() instead of calling + * this function. Using mbedtls_ssl_conf_verify() also comes at + * the benefit of allowing you to influence the verification + * process, for example by masking expected and tolerated + * verification failures. + * + * \warning You must not use the pointer returned by this function + * after any further call to the SSL API, including + * mbedtls_ssl_read() and mbedtls_ssl_write(); this is + * because the pointer might change during renegotiation, + * which happens transparently to the user. + * If you want to use the certificate across API calls, + * you must make a copy. + */ +const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert( const mbedtls_ssl_context *ssl ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_CLI_C) +/** + * \brief Save session in order to resume it later (client-side only) + * Session data is copied to presented session structure. + * + * + * \param ssl SSL context + * \param session session context + * + * \return 0 if successful, + * MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_SSL_BAD_INPUT_DATA if used server-side or + * arguments are otherwise invalid. + * + * \note Only the server certificate is copied, and not the full chain, + * so you should not attempt to validate the certificate again + * by calling \c mbedtls_x509_crt_verify() on it. + * Instead, you should use the results from the verification + * in the original handshake by calling \c mbedtls_ssl_get_verify_result() + * after loading the session again into a new SSL context + * using \c mbedtls_ssl_set_session(). + * + * \note Once the session object is not needed anymore, you should + * free it by calling \c mbedtls_ssl_session_free(). + * + * \sa mbedtls_ssl_set_session() + */ +int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl, mbedtls_ssl_session *session ); +#endif /* MBEDTLS_SSL_CLI_C */ + +/** + * \brief Perform the SSL handshake + * + * \param ssl SSL context + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_SSL_WANT_READ or #MBEDTLS_ERR_SSL_WANT_WRITE + * if the handshake is incomplete and waiting for data to + * be available for reading from or writing to the underlying + * transport - in this case you must call this function again + * when the underlying transport is ready for the operation. + * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if an asynchronous + * operation is in progress (see + * mbedtls_ssl_conf_async_private_cb()) - in this case you + * must call this function again when the operation is ready. + * \return #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS if a cryptographic + * operation is in progress (see mbedtls_ecp_set_max_ops()) - + * in this case you must call this function again to complete + * the handshake when you're done attending other tasks. + * \return #MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED if DTLS is in use + * and the client did not demonstrate reachability yet - in + * this case you must stop using the context (see below). + * \return Another SSL error code - in this case you must stop using + * the context (see below). + * + * \warning If this function returns something other than + * \c 0, + * #MBEDTLS_ERR_SSL_WANT_READ, + * #MBEDTLS_ERR_SSL_WANT_WRITE, + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS, + * you must stop using the SSL context for reading or writing, + * and either free it or call \c mbedtls_ssl_session_reset() + * on it before re-using it for a new connection; the current + * connection must be closed. + * + * \note If DTLS is in use, then you may choose to handle + * #MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED specially for logging + * purposes, as it is an expected return value rather than an + * actual error, but you still need to reset/free the context. + * + * \note Remarks regarding event-driven DTLS: + * If the function returns #MBEDTLS_ERR_SSL_WANT_READ, no datagram + * from the underlying transport layer is currently being processed, + * and it is safe to idle until the timer or the underlying transport + * signal a new event. This is not true for a successful handshake, + * in which case the datagram of the underlying transport that is + * currently being processed might or might not contain further + * DTLS records. + */ +int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl ); + +/** + * \brief Perform a single step of the SSL handshake + * + * \note The state of the context (ssl->state) will be at + * the next state after this function returns \c 0. Do not + * call this function if state is MBEDTLS_SSL_HANDSHAKE_OVER. + * + * \param ssl SSL context + * + * \return See mbedtls_ssl_handshake(). + * + * \warning If this function returns something other than \c 0, + * #MBEDTLS_ERR_SSL_WANT_READ, #MBEDTLS_ERR_SSL_WANT_WRITE, + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS, you must stop using + * the SSL context for reading or writing, and either free it + * or call \c mbedtls_ssl_session_reset() on it before + * re-using it for a new connection; the current connection + * must be closed. + */ +int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +/** + * \brief Initiate an SSL renegotiation on the running connection. + * Client: perform the renegotiation right now. + * Server: request renegotiation, which will be performed + * during the next call to mbedtls_ssl_read() if honored by + * client. + * + * \param ssl SSL context + * + * \return 0 if successful, or any mbedtls_ssl_handshake() return + * value except #MBEDTLS_ERR_SSL_CLIENT_RECONNECT that can't + * happen during a renegotiation. + * + * \warning If this function returns something other than \c 0, + * #MBEDTLS_ERR_SSL_WANT_READ, #MBEDTLS_ERR_SSL_WANT_WRITE, + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS, you must stop using + * the SSL context for reading or writing, and either free it + * or call \c mbedtls_ssl_session_reset() on it before + * re-using it for a new connection; the current connection + * must be closed. + * + */ +int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl ); +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +/** + * \brief Read at most 'len' application data bytes + * + * \param ssl SSL context + * \param buf buffer that will hold the data + * \param len maximum number of bytes to read + * + * \return The (positive) number of bytes read if successful. + * \return \c 0 if the read end of the underlying transport was closed + * without sending a CloseNotify beforehand, which might happen + * because of various reasons (internal error of an underlying + * stack, non-conformant peer not sending a CloseNotify and + * such) - in this case you must stop using the context + * (see below). + * \return #MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY if the underlying + * transport is still functional, but the peer has + * acknowledged to not send anything anymore. + * \return #MBEDTLS_ERR_SSL_WANT_READ or #MBEDTLS_ERR_SSL_WANT_WRITE + * if the handshake is incomplete and waiting for data to + * be available for reading from or writing to the underlying + * transport - in this case you must call this function again + * when the underlying transport is ready for the operation. + * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if an asynchronous + * operation is in progress (see + * mbedtls_ssl_conf_async_private_cb()) - in this case you + * must call this function again when the operation is ready. + * \return #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS if a cryptographic + * operation is in progress (see mbedtls_ecp_set_max_ops()) - + * in this case you must call this function again to complete + * the handshake when you're done attending other tasks. + * \return #MBEDTLS_ERR_SSL_CLIENT_RECONNECT if we're at the server + * side of a DTLS connection and the client is initiating a + * new connection using the same source port. See below. + * \return Another SSL error code - in this case you must stop using + * the context (see below). + * + * \warning If this function returns something other than + * a positive value, + * #MBEDTLS_ERR_SSL_WANT_READ, + * #MBEDTLS_ERR_SSL_WANT_WRITE, + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS, + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS or + * #MBEDTLS_ERR_SSL_CLIENT_RECONNECT, + * you must stop using the SSL context for reading or writing, + * and either free it or call \c mbedtls_ssl_session_reset() + * on it before re-using it for a new connection; the current + * connection must be closed. + * + * \note When this function returns #MBEDTLS_ERR_SSL_CLIENT_RECONNECT + * (which can only happen server-side), it means that a client + * is initiating a new connection using the same source port. + * You can either treat that as a connection close and wait + * for the client to resend a ClientHello, or directly + * continue with \c mbedtls_ssl_handshake() with the same + * context (as it has been reset internally). Either way, you + * must make sure this is seen by the application as a new + * connection: application state, if any, should be reset, and + * most importantly the identity of the client must be checked + * again. WARNING: not validating the identity of the client + * again, or not transmitting the new identity to the + * application layer, would allow authentication bypass! + * + * \note Remarks regarding event-driven DTLS: + * - If the function returns #MBEDTLS_ERR_SSL_WANT_READ, no datagram + * from the underlying transport layer is currently being processed, + * and it is safe to idle until the timer or the underlying transport + * signal a new event. + * - This function may return MBEDTLS_ERR_SSL_WANT_READ even if data was + * initially available on the underlying transport, as this data may have + * been only e.g. duplicated messages or a renegotiation request. + * Therefore, you must be prepared to receive MBEDTLS_ERR_SSL_WANT_READ even + * when reacting to an incoming-data event from the underlying transport. + * - On success, the datagram of the underlying transport that is currently + * being processed may contain further DTLS records. You should call + * \c mbedtls_ssl_check_pending to check for remaining records. + * + */ +int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ); + +/** + * \brief Try to write exactly 'len' application data bytes + * + * \warning This function will do partial writes in some cases. If the + * return value is non-negative but less than length, the + * function must be called again with updated arguments: + * buf + ret, len - ret (if ret is the return value) until + * it returns a value equal to the last 'len' argument. + * + * \param ssl SSL context + * \param buf buffer holding the data + * \param len how many bytes must be written + * + * \return The (non-negative) number of bytes actually written if + * successful (may be less than \p len). + * \return #MBEDTLS_ERR_SSL_WANT_READ or #MBEDTLS_ERR_SSL_WANT_WRITE + * if the handshake is incomplete and waiting for data to + * be available for reading from or writing to the underlying + * transport - in this case you must call this function again + * when the underlying transport is ready for the operation. + * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if an asynchronous + * operation is in progress (see + * mbedtls_ssl_conf_async_private_cb()) - in this case you + * must call this function again when the operation is ready. + * \return #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS if a cryptographic + * operation is in progress (see mbedtls_ecp_set_max_ops()) - + * in this case you must call this function again to complete + * the handshake when you're done attending other tasks. + * \return Another SSL error code - in this case you must stop using + * the context (see below). + * + * \warning If this function returns something other than + * a non-negative value, + * #MBEDTLS_ERR_SSL_WANT_READ, + * #MBEDTLS_ERR_SSL_WANT_WRITE, + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS, + * you must stop using the SSL context for reading or writing, + * and either free it or call \c mbedtls_ssl_session_reset() + * on it before re-using it for a new connection; the current + * connection must be closed. + * + * \note When this function returns #MBEDTLS_ERR_SSL_WANT_WRITE/READ, + * it must be called later with the *same* arguments, + * until it returns a value greater that or equal to 0. When + * the function returns #MBEDTLS_ERR_SSL_WANT_WRITE there may be + * some partial data in the output buffer, however this is not + * yet sent. + * + * \note If the requested length is greater than the maximum + * fragment length (either the built-in limit or the one set + * or negotiated with the peer), then: + * - with TLS, less bytes than requested are written. + * - with DTLS, MBEDTLS_ERR_SSL_BAD_INPUT_DATA is returned. + * \c mbedtls_ssl_get_output_max_frag_len() may be used to + * query the active maximum fragment length. + * + * \note Attempting to write 0 bytes will result in an empty TLS + * application record being sent. + */ +int mbedtls_ssl_write( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ); + +/** + * \brief Send an alert message + * + * \param ssl SSL context + * \param level The alert level of the message + * (MBEDTLS_SSL_ALERT_LEVEL_WARNING or MBEDTLS_SSL_ALERT_LEVEL_FATAL) + * \param message The alert message (SSL_ALERT_MSG_*) + * + * \return 0 if successful, or a specific SSL error code. + * + * \note If this function returns something other than 0 or + * MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using + * the SSL context for reading or writing, and either free it or + * call \c mbedtls_ssl_session_reset() on it before re-using it + * for a new connection; the current connection must be closed. + */ +int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl, + unsigned char level, + unsigned char message ); +/** + * \brief Notify the peer that the connection is being closed + * + * \param ssl SSL context + * + * \return 0 if successful, or a specific SSL error code. + * + * \note If this function returns something other than 0 or + * MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using + * the SSL context for reading or writing, and either free it or + * call \c mbedtls_ssl_session_reset() on it before re-using it + * for a new connection; the current connection must be closed. + */ +int mbedtls_ssl_close_notify( mbedtls_ssl_context *ssl ); + +/** + * \brief Free referenced items in an SSL context and clear memory + * + * \param ssl SSL context + */ +void mbedtls_ssl_free( mbedtls_ssl_context *ssl ); + +#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) +/** + * \brief Save an active connection as serialized data in a buffer. + * This allows the freeing or re-using of the SSL context + * while still picking up the connection later in a way that + * it entirely transparent to the peer. + * + * \see mbedtls_ssl_context_load() + * + * \note This feature is currently only available under certain + * conditions, see the documentation of the return value + * #MBEDTLS_ERR_SSL_BAD_INPUT_DATA for details. + * + * \note When this function succeeds, it calls + * mbedtls_ssl_session_reset() on \p ssl which as a result is + * no longer associated with the connection that has been + * serialized. This avoids creating copies of the connection + * state. You're then free to either re-use the context + * structure for a different connection, or call + * mbedtls_ssl_free() on it. See the documentation of + * mbedtls_ssl_session_reset() for more details. + * + * \param ssl The SSL context to save. On success, it is no longer + * associated with the connection that has been serialized. + * \param buf The buffer to write the serialized data to. It must be a + * writeable buffer of at least \p buf_len bytes, or may be \c + * NULL if \p buf_len is \c 0. + * \param buf_len The number of bytes available for writing in \p buf. + * \param olen The size in bytes of the data that has been or would have + * been written. It must point to a valid \c size_t. + * + * \note \p olen is updated to the correct value regardless of + * whether \p buf_len was large enough. This makes it possible + * to determine the necessary size by calling this function + * with \p buf set to \c NULL and \p buf_len to \c 0. However, + * the value of \p olen is only guaranteed to be correct when + * the function returns #MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL or + * \c 0. If the return value is different, then the value of + * \p olen is undefined. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL if \p buf is too small. + * \return #MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed + * while reseting the context. + * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if a handshake is in + * progress, or there is pending data for reading or sending, + * or the connection does not use DTLS 1.2 with an AEAD + * ciphersuite, or renegotiation is enabled. + */ +int mbedtls_ssl_context_save( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t buf_len, + size_t *olen ); + +/** + * \brief Load serialized connection data to an SSL context. + * + * \see mbedtls_ssl_context_save() + * + * \warning The same serialized data must never be loaded into more + * that one context. In order to ensure that, after + * successfully loading serialized data to an SSL context, you + * should immediately destroy or invalidate all copies of the + * serialized data that was loaded. Loading the same data in + * more than one context would cause severe security failures + * including but not limited to loss of confidentiality. + * + * \note Before calling this function, the SSL context must be + * prepared in one of the two following ways. The first way is + * to take a context freshly initialised with + * mbedtls_ssl_init() and call mbedtls_ssl_setup() on it with + * the same ::mbedtls_ssl_config structure that was used in + * the original connection. The second way is to + * call mbedtls_ssl_session_reset() on a context that was + * previously prepared as above but used in the meantime. + * Either way, you must not use the context to perform a + * handshake between calling mbedtls_ssl_setup() or + * mbedtls_ssl_session_reset() and calling this function. You + * may however call other setter functions in that time frame + * as indicated in the note below. + * + * \note Before or after calling this function successfully, you + * also need to configure some connection-specific callbacks + * and settings before you can use the connection again + * (unless they were already set before calling + * mbedtls_ssl_session_reset() and the values are suitable for + * the present connection). Specifically, you want to call + * at least mbedtls_ssl_set_bio() and + * mbedtls_ssl_set_timer_cb(). All other SSL setter functions + * are not necessary to call, either because they're only used + * in handshakes, or because the setting is already saved. You + * might choose to call them anyway, for example in order to + * share code between the cases of establishing a new + * connection and the case of loading an already-established + * connection. + * + * \note If you have new information about the path MTU, you want to + * call mbedtls_ssl_set_mtu() after calling this function, as + * otherwise this function would overwrite your + * newly-configured value with the value that was active when + * the context was saved. + * + * \note When this function returns an error code, it calls + * mbedtls_ssl_free() on \p ssl. In this case, you need to + * prepare the context with the usual sequence starting with a + * call to mbedtls_ssl_init() if you want to use it again. + * + * \param ssl The SSL context structure to be populated. It must have + * been prepared as described in the note above. + * \param buf The buffer holding the serialized connection data. It must + * be a readable buffer of at least \p len bytes. + * \param len The size of the serialized data in bytes. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed. + * \return #MBEDTLS_ERR_SSL_VERSION_MISMATCH if the serialized data + * comes from a different Mbed TLS version or build. + * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if input data is invalid. + */ +int mbedtls_ssl_context_load( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ); +#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */ + +/** + * \brief Initialize an SSL configuration context + * Just makes the context ready for + * mbedtls_ssl_config_defaults() or mbedtls_ssl_config_free(). + * + * \note You need to call mbedtls_ssl_config_defaults() unless you + * manually set all of the relevant fields yourself. + * + * \param conf SSL configuration context + */ +void mbedtls_ssl_config_init( mbedtls_ssl_config *conf ); + +/** + * \brief Load reasonnable default SSL configuration values. + * (You need to call mbedtls_ssl_config_init() first.) + * + * \param conf SSL configuration context + * \param endpoint MBEDTLS_SSL_IS_CLIENT or MBEDTLS_SSL_IS_SERVER + * \param transport MBEDTLS_SSL_TRANSPORT_STREAM for TLS, or + * MBEDTLS_SSL_TRANSPORT_DATAGRAM for DTLS + * \param preset a MBEDTLS_SSL_PRESET_XXX value + * + * \note See \c mbedtls_ssl_conf_transport() for notes on DTLS. + * + * \return 0 if successful, or + * MBEDTLS_ERR_XXX_ALLOC_FAILED on memory allocation error. + */ +int mbedtls_ssl_config_defaults( mbedtls_ssl_config *conf, + int endpoint, int transport, int preset ); + +/** + * \brief Free an SSL configuration context + * + * \param conf SSL configuration context + */ +void mbedtls_ssl_config_free( mbedtls_ssl_config *conf ); + +/** + * \brief Initialize SSL session structure + * + * \param session SSL session + */ +void mbedtls_ssl_session_init( mbedtls_ssl_session *session ); + +/** + * \brief Free referenced items in an SSL session including the + * peer certificate and clear memory + * + * \note A session object can be freed even if the SSL context + * that was used to retrieve the session is still in use. + * + * \param session SSL session + */ +void mbedtls_ssl_session_free( mbedtls_ssl_session *session ); + +/** + * \brief TLS-PRF function for key derivation. + * + * \param prf The tls_prf type funtion type to be used. + * \param secret Secret for the key derivation function. + * \param slen Length of the secret. + * \param label String label for the key derivation function, + * terminated with null character. + * \param random Random bytes. + * \param rlen Length of the random bytes buffer. + * \param dstbuf The buffer holding the derived key. + * \param dlen Length of the output buffer. + * + * \return 0 on sucess. An SSL specific error on failure. + */ +int mbedtls_ssl_tls_prf( const mbedtls_tls_prf_types prf, + const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ); + +#ifdef __cplusplus +} +#endif + +#endif /* ssl.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ssl_cache.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ssl_cache.h new file mode 100644 index 0000000..c6ef296 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ssl_cache.h @@ -0,0 +1,149 @@ +/** + * \file ssl_cache.h + * + * \brief SSL session cache implementation + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_SSL_CACHE_H +#define MBEDTLS_SSL_CACHE_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/ssl.h" + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT) +#define MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT 86400 /*!< 1 day */ +#endif + +#if !defined(MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES) +#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /*!< Maximum entries in cache */ +#endif + +/* \} name SECTION: Module settings */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct mbedtls_ssl_cache_context mbedtls_ssl_cache_context; +typedef struct mbedtls_ssl_cache_entry mbedtls_ssl_cache_entry; + +/** + * \brief This structure is used for storing cache entries + */ +struct mbedtls_ssl_cache_entry +{ +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t timestamp; /*!< entry timestamp */ +#endif + mbedtls_ssl_session session; /*!< entry session */ +#if defined(MBEDTLS_X509_CRT_PARSE_C) && \ + defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + mbedtls_x509_buf peer_cert; /*!< entry peer_cert */ +#endif + mbedtls_ssl_cache_entry *next; /*!< chain pointer */ +}; + +/** + * \brief Cache context + */ +struct mbedtls_ssl_cache_context +{ + mbedtls_ssl_cache_entry *chain; /*!< start of the chain */ + int timeout; /*!< cache entry timeout */ + int max_entries; /*!< maximum entries */ +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; /*!< mutex */ +#endif +}; + +/** + * \brief Initialize an SSL cache context + * + * \param cache SSL cache context + */ +void mbedtls_ssl_cache_init( mbedtls_ssl_cache_context *cache ); + +/** + * \brief Cache get callback implementation + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param data SSL cache context + * \param session session to retrieve entry for + */ +int mbedtls_ssl_cache_get( void *data, mbedtls_ssl_session *session ); + +/** + * \brief Cache set callback implementation + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param data SSL cache context + * \param session session to store entry for + */ +int mbedtls_ssl_cache_set( void *data, const mbedtls_ssl_session *session ); + +#if defined(MBEDTLS_HAVE_TIME) +/** + * \brief Set the cache timeout + * (Default: MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT (1 day)) + * + * A timeout of 0 indicates no timeout. + * + * \param cache SSL cache context + * \param timeout cache entry timeout in seconds + */ +void mbedtls_ssl_cache_set_timeout( mbedtls_ssl_cache_context *cache, int timeout ); +#endif /* MBEDTLS_HAVE_TIME */ + +/** + * \brief Set the maximum number of cache entries + * (Default: MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES (50)) + * + * \param cache SSL cache context + * \param max cache entry maximum + */ +void mbedtls_ssl_cache_set_max_entries( mbedtls_ssl_cache_context *cache, int max ); + +/** + * \brief Free referenced items in a cache context and clear memory + * + * \param cache SSL cache context + */ +void mbedtls_ssl_cache_free( mbedtls_ssl_cache_context *cache ); + +#ifdef __cplusplus +} +#endif + +#endif /* ssl_cache.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ssl_ciphersuites.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ssl_ciphersuites.h new file mode 100644 index 0000000..93c32a5 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ssl_ciphersuites.h @@ -0,0 +1,556 @@ +/** + * \file ssl_ciphersuites.h + * + * \brief SSL Ciphersuites for mbed TLS + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_SSL_CIPHERSUITES_H +#define MBEDTLS_SSL_CIPHERSUITES_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/pk.h" +#include "mbedtls/cipher.h" +#include "mbedtls/md.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Supported ciphersuites (Official IANA names) + */ +#define MBEDTLS_TLS_RSA_WITH_NULL_MD5 0x01 /**< Weak! */ +#define MBEDTLS_TLS_RSA_WITH_NULL_SHA 0x02 /**< Weak! */ + +#define MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 0x04 +#define MBEDTLS_TLS_RSA_WITH_RC4_128_SHA 0x05 +#define MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA 0x09 /**< Weak! Not in TLS 1.2 */ + +#define MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA 0x0A + +#define MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA 0x15 /**< Weak! Not in TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA 0x16 + +#define MBEDTLS_TLS_PSK_WITH_NULL_SHA 0x2C /**< Weak! */ +#define MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA 0x2D /**< Weak! */ +#define MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA 0x2E /**< Weak! */ +#define MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA 0x2F + +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA 0x33 +#define MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA 0x35 +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x39 + +#define MBEDTLS_TLS_RSA_WITH_NULL_SHA256 0x3B /**< Weak! */ +#define MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 0x3C /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 0x3D /**< TLS 1.2 */ + +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA 0x41 +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA 0x45 + +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 0x67 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 0x6B /**< TLS 1.2 */ + +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA 0x84 +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA 0x88 + +#define MBEDTLS_TLS_PSK_WITH_RC4_128_SHA 0x8A +#define MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA 0x8B +#define MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA 0x8C +#define MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA 0x8D + +#define MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA 0x8E +#define MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA 0x8F +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA 0x90 +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA 0x91 + +#define MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA 0x92 +#define MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA 0x93 +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA 0x94 +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA 0x95 + +#define MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 0x9C /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 0x9D /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 0x9E /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 0x9F /**< TLS 1.2 */ + +#define MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 0xA8 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 0xA9 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 0xAA /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 0xAB /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 0xAC /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 0xAD /**< TLS 1.2 */ + +#define MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 0xAE +#define MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 0xAF +#define MBEDTLS_TLS_PSK_WITH_NULL_SHA256 0xB0 /**< Weak! */ +#define MBEDTLS_TLS_PSK_WITH_NULL_SHA384 0xB1 /**< Weak! */ + +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 0xB2 +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 0xB3 +#define MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256 0xB4 /**< Weak! */ +#define MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384 0xB5 /**< Weak! */ + +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 0xB6 +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 0xB7 +#define MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256 0xB8 /**< Weak! */ +#define MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384 0xB9 /**< Weak! */ + +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xBA /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xBE /**< TLS 1.2 */ + +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 0xC0 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 0xC4 /**< TLS 1.2 */ + +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA 0xC001 /**< Weak! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA 0xC002 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA 0xC003 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA 0xC004 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA 0xC005 /**< Not in SSL3! */ + +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA 0xC006 /**< Weak! */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA 0xC007 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA 0xC008 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0xC009 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0xC00A /**< Not in SSL3! */ + +#define MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA 0xC00B /**< Weak! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA 0xC00C /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA 0xC00D /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA 0xC00E /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA 0xC00F /**< Not in SSL3! */ + +#define MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA 0xC010 /**< Weak! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA 0xC011 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA 0xC012 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 0xC013 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 0xC014 /**< Not in SSL3! */ + +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 0xC023 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 0xC024 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 0xC025 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 0xC026 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 0xC027 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 0xC028 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 0xC029 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 0xC02A /**< TLS 1.2 */ + +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xC02B /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0xC02C /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 0xC02D /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 0xC02E /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0xC02F /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0xC030 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 0xC031 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 0xC032 /**< TLS 1.2 */ + +#define MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA 0xC033 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA 0xC034 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA 0xC035 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA 0xC036 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 0xC037 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 0xC038 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA 0xC039 /**< Weak! No SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256 0xC03A /**< Weak! No SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384 0xC03B /**< Weak! No SSL3! */ + +#define MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256 0xC03C /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384 0xC03D /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 0xC044 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 0xC045 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 0xC048 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 0xC049 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256 0xC04A /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384 0xC04B /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 0xC04C /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 0xC04D /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256 0xC04E /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384 0xC04F /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256 0xC050 /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384 0xC051 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 0xC052 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 0xC053 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 0xC05C /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 0xC05D /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256 0xC05E /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384 0xC05F /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 0xC060 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 0xC061 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256 0xC062 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384 0xC063 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256 0xC064 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384 0xC065 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256 0xC066 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384 0xC067 /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256 0xC068 /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384 0xC069 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256 0xC06A /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384 0xC06B /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256 0xC06C /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384 0xC06D /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256 0xC06E /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384 0xC06F /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256 0xC070 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 0xC071 /**< TLS 1.2 */ + +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0xC072 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0xC073 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0xC074 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0xC075 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xC076 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 0xC077 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xC078 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 0xC079 /**< Not in SSL3! */ + +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC07A /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC07B /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC07C /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC07D /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 0xC086 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 0xC087 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 0xC088 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 0xC089 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC08A /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC08B /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC08C /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC08D /**< TLS 1.2 */ + +#define MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 0xC08E /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 0xC08F /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 0xC090 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 0xC091 /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 0xC092 /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 0xC093 /**< TLS 1.2 */ + +#define MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC094 +#define MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC095 +#define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC096 +#define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC097 +#define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC098 +#define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC099 +#define MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC09A /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC09B /**< Not in SSL3! */ + +#define MBEDTLS_TLS_RSA_WITH_AES_128_CCM 0xC09C /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_AES_256_CCM 0xC09D /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM 0xC09E /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM 0xC09F /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8 0xC0A0 /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8 0xC0A1 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8 0xC0A2 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8 0xC0A3 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_AES_128_CCM 0xC0A4 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_AES_256_CCM 0xC0A5 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM 0xC0A6 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM 0xC0A7 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8 0xC0A8 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8 0xC0A9 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8 0xC0AA /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8 0xC0AB /**< TLS 1.2 */ +/* The last two are named with PSK_DHE in the RFC, which looks like a typo */ + +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM 0xC0AC /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM 0xC0AD /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 0xC0AE /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 0xC0AF /**< TLS 1.2 */ + +#define MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8 0xC0FF /**< experimental */ + +/* RFC 7905 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA8 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA9 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCAA /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAB /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAC /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAD /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAE /**< TLS 1.2 */ + +/* Reminder: update mbedtls_ssl_premaster_secret when adding a new key exchange. + * Reminder: update MBEDTLS_KEY_EXCHANGE__xxx below + */ +typedef enum { + MBEDTLS_KEY_EXCHANGE_NONE = 0, + MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_KEY_EXCHANGE_ECJPAKE, +} mbedtls_key_exchange_type_t; + +/* Key exchanges using a certificate */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +#define MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED +#endif + +/* Key exchanges allowing client certificate requests */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +#define MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED +#endif + +/* Key exchanges involving server signature in ServerKeyExchange */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +#define MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED +#endif + +/* Key exchanges using ECDH */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +#define MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED +#endif + +/* Key exchanges that don't involve ephemeral keys */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED) +#define MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED +#endif + +/* Key exchanges that involve ephemeral keys */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +#define MBEDTLS_KEY_EXCHANGE_SOME_PFS_ENABLED +#endif + +/* Key exchanges using a PSK */ +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +#define MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED +#endif + +/* Key exchanges using DHE */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) +#define MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED +#endif + +/* Key exchanges using ECDHE */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +#define MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED +#endif + +typedef struct mbedtls_ssl_ciphersuite_t mbedtls_ssl_ciphersuite_t; + +#define MBEDTLS_CIPHERSUITE_WEAK 0x01 /**< Weak ciphersuite flag */ +#define MBEDTLS_CIPHERSUITE_SHORT_TAG 0x02 /**< Short authentication tag, + eg for CCM_8 */ +#define MBEDTLS_CIPHERSUITE_NODTLS 0x04 /**< Can't be used with DTLS */ + +/** + * \brief This structure is used for storing ciphersuite information + */ +struct mbedtls_ssl_ciphersuite_t +{ + int id; + const char * name; + + mbedtls_cipher_type_t cipher; + mbedtls_md_type_t mac; + mbedtls_key_exchange_type_t key_exchange; + + int min_major_ver; + int min_minor_ver; + int max_major_ver; + int max_minor_ver; + + unsigned char flags; +}; + +const int *mbedtls_ssl_list_ciphersuites( void ); + +const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_string( const char *ciphersuite_name ); +const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_id( int ciphersuite_id ); + +#if defined(MBEDTLS_PK_C) +mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_pk_alg( const mbedtls_ssl_ciphersuite_t *info ); +mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_alg( const mbedtls_ssl_ciphersuite_t *info ); +#endif + +int mbedtls_ssl_ciphersuite_uses_ec( const mbedtls_ssl_ciphersuite_t *info ); +int mbedtls_ssl_ciphersuite_uses_psk( const mbedtls_ssl_ciphersuite_t *info ); + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PFS_ENABLED) +static inline int mbedtls_ssl_ciphersuite_has_pfs( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_DHE_PSK: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + case MBEDTLS_KEY_EXCHANGE_ECJPAKE: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PFS_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED) +static inline int mbedtls_ssl_ciphersuite_no_pfs( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + case MBEDTLS_KEY_EXCHANGE_RSA: + case MBEDTLS_KEY_EXCHANGE_PSK: + case MBEDTLS_KEY_EXCHANGE_RSA_PSK: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED) +static inline int mbedtls_ssl_ciphersuite_uses_ecdh( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED */ + +static inline int mbedtls_ssl_ciphersuite_cert_req_allowed( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_RSA: + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + return( 1 ); + + default: + return( 0 ); + } +} + +static inline int mbedtls_ssl_ciphersuite_uses_srv_cert( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_RSA: + case MBEDTLS_KEY_EXCHANGE_RSA_PSK: + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + return( 1 ); + + default: + return( 0 ); + } +} + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED) +static inline int mbedtls_ssl_ciphersuite_uses_dhe( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_DHE_PSK: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED) */ + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED) +static inline int mbedtls_ssl_ciphersuite_uses_ecdhe( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED) */ + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) +static inline int mbedtls_ssl_ciphersuite_uses_server_signature( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */ + +#ifdef __cplusplus +} +#endif + +#endif /* ssl_ciphersuites.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ssl_cookie.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ssl_cookie.h new file mode 100644 index 0000000..0a23870 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ssl_cookie.h @@ -0,0 +1,113 @@ +/** + * \file ssl_cookie.h + * + * \brief DTLS cookie callbacks implementation + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_SSL_COOKIE_H +#define MBEDTLS_SSL_COOKIE_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/ssl.h" + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ +#ifndef MBEDTLS_SSL_COOKIE_TIMEOUT +#define MBEDTLS_SSL_COOKIE_TIMEOUT 60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */ +#endif + +/* \} name SECTION: Module settings */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Context for the default cookie functions. + */ +typedef struct mbedtls_ssl_cookie_ctx +{ + mbedtls_md_context_t hmac_ctx; /*!< context for the HMAC portion */ +#if !defined(MBEDTLS_HAVE_TIME) + unsigned long serial; /*!< serial number for expiration */ +#endif + unsigned long timeout; /*!< timeout delay, in seconds if HAVE_TIME, + or in number of tickets issued */ + +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; +#endif +} mbedtls_ssl_cookie_ctx; + +/** + * \brief Initialize cookie context + */ +void mbedtls_ssl_cookie_init( mbedtls_ssl_cookie_ctx *ctx ); + +/** + * \brief Setup cookie context (generate keys) + */ +int mbedtls_ssl_cookie_setup( mbedtls_ssl_cookie_ctx *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Set expiration delay for cookies + * (Default MBEDTLS_SSL_COOKIE_TIMEOUT) + * + * \param ctx Cookie contex + * \param delay Delay, in seconds if HAVE_TIME, or in number of cookies + * issued in the meantime. + * 0 to disable expiration (NOT recommended) + */ +void mbedtls_ssl_cookie_set_timeout( mbedtls_ssl_cookie_ctx *ctx, unsigned long delay ); + +/** + * \brief Free cookie context + */ +void mbedtls_ssl_cookie_free( mbedtls_ssl_cookie_ctx *ctx ); + +/** + * \brief Generate cookie, see \c mbedtls_ssl_cookie_write_t + */ +mbedtls_ssl_cookie_write_t mbedtls_ssl_cookie_write; + +/** + * \brief Verify cookie, see \c mbedtls_ssl_cookie_write_t + */ +mbedtls_ssl_cookie_check_t mbedtls_ssl_cookie_check; + +#ifdef __cplusplus +} +#endif + +#endif /* ssl_cookie.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ssl_internal.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ssl_internal.h new file mode 100644 index 0000000..1dc9648 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ssl_internal.h @@ -0,0 +1,1304 @@ +/** + * \file ssl_internal.h + * + * \brief Internal functions shared by the SSL modules + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_SSL_INTERNAL_H +#define MBEDTLS_SSL_INTERNAL_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/ssl.h" +#include "mbedtls/cipher.h" + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#endif + +#if defined(MBEDTLS_MD5_C) +#include "mbedtls/md5.h" +#endif + +#if defined(MBEDTLS_SHA1_C) +#include "mbedtls/sha1.h" +#endif + +#if defined(MBEDTLS_SHA256_C) +#include "mbedtls/sha256.h" +#endif + +#if defined(MBEDTLS_SHA512_C) +#include "mbedtls/sha512.h" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +#include "mbedtls/ecjpake.h" +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#include "mbedtls/psa_util.h" +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +/* Determine minimum supported version */ +#define MBEDTLS_SSL_MIN_MAJOR_VERSION MBEDTLS_SSL_MAJOR_VERSION_3 + +#if defined(MBEDTLS_SSL_PROTO_SSL3) +#define MBEDTLS_SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_0 +#else +#if defined(MBEDTLS_SSL_PROTO_TLS1) +#define MBEDTLS_SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_1 +#else +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) +#define MBEDTLS_SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_2 +#else +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#define MBEDTLS_SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_3 +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_1 */ +#endif /* MBEDTLS_SSL_PROTO_TLS1 */ +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + +#define MBEDTLS_SSL_MIN_VALID_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_1 +#define MBEDTLS_SSL_MIN_VALID_MAJOR_VERSION MBEDTLS_SSL_MAJOR_VERSION_3 + +/* Determine maximum supported version */ +#define MBEDTLS_SSL_MAX_MAJOR_VERSION MBEDTLS_SSL_MAJOR_VERSION_3 + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#define MBEDTLS_SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_3 +#else +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) +#define MBEDTLS_SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_2 +#else +#if defined(MBEDTLS_SSL_PROTO_TLS1) +#define MBEDTLS_SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_1 +#else +#if defined(MBEDTLS_SSL_PROTO_SSL3) +#define MBEDTLS_SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_0 +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ +#endif /* MBEDTLS_SSL_PROTO_TLS1 */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_1 */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +/* Shorthand for restartable ECC */ +#if defined(MBEDTLS_ECP_RESTARTABLE) && \ + defined(MBEDTLS_SSL_CLI_C) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +#define MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED +#endif + +#define MBEDTLS_SSL_INITIAL_HANDSHAKE 0 +#define MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS 1 /* In progress */ +#define MBEDTLS_SSL_RENEGOTIATION_DONE 2 /* Done or aborted */ +#define MBEDTLS_SSL_RENEGOTIATION_PENDING 3 /* Requested (server only) */ + +/* + * DTLS retransmission states, see RFC 6347 4.2.4 + * + * The SENDING state is merged in PREPARING for initial sends, + * but is distinct for resends. + * + * Note: initial state is wrong for server, but is not used anyway. + */ +#define MBEDTLS_SSL_RETRANS_PREPARING 0 +#define MBEDTLS_SSL_RETRANS_SENDING 1 +#define MBEDTLS_SSL_RETRANS_WAITING 2 +#define MBEDTLS_SSL_RETRANS_FINISHED 3 + +/* + * Allow extra bytes for record, authentication and encryption overhead: + * counter (8) + header (5) + IV(16) + MAC (16-48) + padding (0-256) + * and allow for a maximum of 1024 of compression expansion if + * enabled. + */ +#if defined(MBEDTLS_ZLIB_SUPPORT) +#define MBEDTLS_SSL_COMPRESSION_ADD 1024 +#else +#define MBEDTLS_SSL_COMPRESSION_ADD 0 +#endif + +/* This macro determines whether CBC is supported. */ +#if defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_AES_C) || \ + defined(MBEDTLS_CAMELLIA_C) || \ + defined(MBEDTLS_ARIA_C) || \ + defined(MBEDTLS_DES_C) ) +#define MBEDTLS_SSL_SOME_SUITES_USE_CBC +#endif + +/* This macro determines whether the CBC construct used in TLS 1.0-1.2 (as + * opposed to the very different CBC construct used in SSLv3) is supported. */ +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) && \ + ( defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) ) +#define MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC +#endif + +#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) || \ + defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) +#define MBEDTLS_SSL_SOME_MODES_USE_MAC +#endif + +#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) +/* Ciphersuites using HMAC */ +#if defined(MBEDTLS_SHA512_C) +#define MBEDTLS_SSL_MAC_ADD 48 /* SHA-384 used for HMAC */ +#elif defined(MBEDTLS_SHA256_C) +#define MBEDTLS_SSL_MAC_ADD 32 /* SHA-256 used for HMAC */ +#else +#define MBEDTLS_SSL_MAC_ADD 20 /* SHA-1 used for HMAC */ +#endif +#else /* MBEDTLS_SSL_SOME_MODES_USE_MAC */ +/* AEAD ciphersuites: GCM and CCM use a 128 bits tag */ +#define MBEDTLS_SSL_MAC_ADD 16 +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#define MBEDTLS_SSL_PADDING_ADD 256 +#else +#define MBEDTLS_SSL_PADDING_ADD 0 +#endif + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) +#define MBEDTLS_SSL_MAX_CID_EXPANSION MBEDTLS_SSL_CID_PADDING_GRANULARITY +#else +#define MBEDTLS_SSL_MAX_CID_EXPANSION 0 +#endif + +#define MBEDTLS_SSL_PAYLOAD_OVERHEAD ( MBEDTLS_SSL_COMPRESSION_ADD + \ + MBEDTLS_MAX_IV_LENGTH + \ + MBEDTLS_SSL_MAC_ADD + \ + MBEDTLS_SSL_PADDING_ADD + \ + MBEDTLS_SSL_MAX_CID_EXPANSION \ + ) + +#define MBEDTLS_SSL_IN_PAYLOAD_LEN ( MBEDTLS_SSL_PAYLOAD_OVERHEAD + \ + ( MBEDTLS_SSL_IN_CONTENT_LEN ) ) + +#define MBEDTLS_SSL_OUT_PAYLOAD_LEN ( MBEDTLS_SSL_PAYLOAD_OVERHEAD + \ + ( MBEDTLS_SSL_OUT_CONTENT_LEN ) ) + +/* The maximum number of buffered handshake messages. */ +#define MBEDTLS_SSL_MAX_BUFFERED_HS 4 + +/* Maximum length we can advertise as our max content length for + RFC 6066 max_fragment_length extension negotiation purposes + (the lesser of both sizes, if they are unequal.) + */ +#define MBEDTLS_TLS_EXT_ADV_CONTENT_LEN ( \ + (MBEDTLS_SSL_IN_CONTENT_LEN > MBEDTLS_SSL_OUT_CONTENT_LEN) \ + ? ( MBEDTLS_SSL_OUT_CONTENT_LEN ) \ + : ( MBEDTLS_SSL_IN_CONTENT_LEN ) \ + ) + +/* Maximum size in bytes of list in sig-hash algorithm ext., RFC 5246 */ +#define MBEDTLS_SSL_MAX_SIG_HASH_ALG_LIST_LEN 65534 + +/* Maximum size in bytes of list in supported elliptic curve ext., RFC 4492 */ +#define MBEDTLS_SSL_MAX_CURVE_LIST_LEN 65535 + +/* + * Check that we obey the standard's message size bounds + */ + +#if MBEDTLS_SSL_MAX_CONTENT_LEN > 16384 +#error "Bad configuration - record content too large." +#endif + +#if MBEDTLS_SSL_IN_CONTENT_LEN > MBEDTLS_SSL_MAX_CONTENT_LEN +#error "Bad configuration - incoming record content should not be larger than MBEDTLS_SSL_MAX_CONTENT_LEN." +#endif + +#if MBEDTLS_SSL_OUT_CONTENT_LEN > MBEDTLS_SSL_MAX_CONTENT_LEN +#error "Bad configuration - outgoing record content should not be larger than MBEDTLS_SSL_MAX_CONTENT_LEN." +#endif + +#if MBEDTLS_SSL_IN_PAYLOAD_LEN > MBEDTLS_SSL_MAX_CONTENT_LEN + 2048 +#error "Bad configuration - incoming protected record payload too large." +#endif + +#if MBEDTLS_SSL_OUT_PAYLOAD_LEN > MBEDTLS_SSL_MAX_CONTENT_LEN + 2048 +#error "Bad configuration - outgoing protected record payload too large." +#endif + +/* Calculate buffer sizes */ + +/* Note: Even though the TLS record header is only 5 bytes + long, we're internally using 8 bytes to store the + implicit sequence number. */ +#define MBEDTLS_SSL_HEADER_LEN 13 + +#if !defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) +#define MBEDTLS_SSL_IN_BUFFER_LEN \ + ( ( MBEDTLS_SSL_HEADER_LEN ) + ( MBEDTLS_SSL_IN_PAYLOAD_LEN ) ) +#else +#define MBEDTLS_SSL_IN_BUFFER_LEN \ + ( ( MBEDTLS_SSL_HEADER_LEN ) + ( MBEDTLS_SSL_IN_PAYLOAD_LEN ) \ + + ( MBEDTLS_SSL_CID_IN_LEN_MAX ) ) +#endif + +#if !defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) +#define MBEDTLS_SSL_OUT_BUFFER_LEN \ + ( ( MBEDTLS_SSL_HEADER_LEN ) + ( MBEDTLS_SSL_OUT_PAYLOAD_LEN ) ) +#else +#define MBEDTLS_SSL_OUT_BUFFER_LEN \ + ( ( MBEDTLS_SSL_HEADER_LEN ) + ( MBEDTLS_SSL_OUT_PAYLOAD_LEN ) \ + + ( MBEDTLS_SSL_CID_OUT_LEN_MAX ) ) +#endif + +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) +static inline uint32_t mbedtls_ssl_get_output_buflen( const mbedtls_ssl_context *ctx ) +{ +#if defined (MBEDTLS_SSL_DTLS_CONNECTION_ID) + return (uint32_t) mbedtls_ssl_get_output_max_frag_len( ctx ) + + MBEDTLS_SSL_HEADER_LEN + MBEDTLS_SSL_PAYLOAD_OVERHEAD + + MBEDTLS_SSL_CID_OUT_LEN_MAX; +#else + return (uint32_t) mbedtls_ssl_get_output_max_frag_len( ctx ) + + MBEDTLS_SSL_HEADER_LEN + MBEDTLS_SSL_PAYLOAD_OVERHEAD; +#endif +} + +static inline uint32_t mbedtls_ssl_get_input_buflen( const mbedtls_ssl_context *ctx ) +{ +#if defined (MBEDTLS_SSL_DTLS_CONNECTION_ID) + return (uint32_t) mbedtls_ssl_get_input_max_frag_len( ctx ) + + MBEDTLS_SSL_HEADER_LEN + MBEDTLS_SSL_PAYLOAD_OVERHEAD + + MBEDTLS_SSL_CID_IN_LEN_MAX; +#else + return (uint32_t) mbedtls_ssl_get_input_max_frag_len( ctx ) + + MBEDTLS_SSL_HEADER_LEN + MBEDTLS_SSL_PAYLOAD_OVERHEAD; +#endif +} +#endif + +#ifdef MBEDTLS_ZLIB_SUPPORT +/* Compression buffer holds both IN and OUT buffers, so should be size of the larger */ +#define MBEDTLS_SSL_COMPRESS_BUFFER_LEN ( \ + ( MBEDTLS_SSL_IN_BUFFER_LEN > MBEDTLS_SSL_OUT_BUFFER_LEN ) \ + ? MBEDTLS_SSL_IN_BUFFER_LEN \ + : MBEDTLS_SSL_OUT_BUFFER_LEN \ + ) +#endif + +/* + * TLS extension flags (for extensions with outgoing ServerHello content + * that need it (e.g. for RENEGOTIATION_INFO the server already knows because + * of state of the renegotiation flag, so no indicator is required) + */ +#define MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT (1 << 0) +#define MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK (1 << 1) + +/** + * \brief This function checks if the remaining size in a buffer is + * greater or equal than a needed space. + * + * \param cur Pointer to the current position in the buffer. + * \param end Pointer to one past the end of the buffer. + * \param need Needed space in bytes. + * + * \return Zero if the needed space is available in the buffer, non-zero + * otherwise. + */ +static inline int mbedtls_ssl_chk_buf_ptr( const uint8_t *cur, + const uint8_t *end, size_t need ) +{ + return( ( cur > end ) || ( need > (size_t)( end - cur ) ) ); +} + +/** + * \brief This macro checks if the remaining size in a buffer is + * greater or equal than a needed space. If it is not the case, + * it returns an SSL_BUFFER_TOO_SMALL error. + * + * \param cur Pointer to the current position in the buffer. + * \param end Pointer to one past the end of the buffer. + * \param need Needed space in bytes. + * + */ +#define MBEDTLS_SSL_CHK_BUF_PTR( cur, end, need ) \ + do { \ + if( mbedtls_ssl_chk_buf_ptr( ( cur ), ( end ), ( need ) ) != 0 ) \ + { \ + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); \ + } \ + } while( 0 ) + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) +/* + * Abstraction for a grid of allowed signature-hash-algorithm pairs. + */ +struct mbedtls_ssl_sig_hash_set_t +{ + /* At the moment, we only need to remember a single suitable + * hash algorithm per signature algorithm. As long as that's + * the case - and we don't need a general lookup function - + * we can implement the sig-hash-set as a map from signatures + * to hash algorithms. */ + mbedtls_md_type_t rsa; + mbedtls_md_type_t ecdsa; +}; +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + +typedef int mbedtls_ssl_tls_prf_cb( const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ); + +/* cipher.h exports the maximum IV, key and block length from + * all ciphers enabled in the config, regardless of whether those + * ciphers are actually usable in SSL/TLS. Notably, XTS is enabled + * in the default configuration and uses 64 Byte keys, but it is + * not used for record protection in SSL/TLS. + * + * In order to prevent unnecessary inflation of key structures, + * we introduce SSL-specific variants of the max-{key,block,IV} + * macros here which are meant to only take those ciphers into + * account which can be negotiated in SSL/TLS. + * + * Since the current definitions of MBEDTLS_MAX_{KEY|BLOCK|IV}_LENGTH + * in cipher.h are rough overapproximations of the real maxima, here + * we content ourselves with replicating those overapproximations + * for the maximum block and IV length, and excluding XTS from the + * computation of the maximum key length. */ +#define MBEDTLS_SSL_MAX_BLOCK_LENGTH 16 +#define MBEDTLS_SSL_MAX_IV_LENGTH 16 +#define MBEDTLS_SSL_MAX_KEY_LENGTH 32 + +/** + * \brief The data structure holding the cryptographic material (key and IV) + * used for record protection in TLS 1.3. + */ +struct mbedtls_ssl_key_set +{ + /*! The key for client->server records. */ + unsigned char client_write_key[ MBEDTLS_SSL_MAX_KEY_LENGTH ]; + /*! The key for server->client records. */ + unsigned char server_write_key[ MBEDTLS_SSL_MAX_KEY_LENGTH ]; + /*! The IV for client->server records. */ + unsigned char client_write_iv[ MBEDTLS_SSL_MAX_IV_LENGTH ]; + /*! The IV for server->client records. */ + unsigned char server_write_iv[ MBEDTLS_SSL_MAX_IV_LENGTH ]; + + size_t key_len; /*!< The length of client_write_key and + * server_write_key, in Bytes. */ + size_t iv_len; /*!< The length of client_write_iv and + * server_write_iv, in Bytes. */ +}; +typedef struct mbedtls_ssl_key_set mbedtls_ssl_key_set; + +/* + * This structure contains the parameters only needed during handshake. + */ +struct mbedtls_ssl_handshake_params +{ + /* + * Handshake specific crypto variables + */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + mbedtls_ssl_sig_hash_set_t hash_algs; /*!< Set of suitable sig-hash pairs */ +#endif +#if defined(MBEDTLS_DHM_C) + mbedtls_dhm_context dhm_ctx; /*!< DHM key exchange */ +#endif +#if defined(MBEDTLS_ECDH_C) + mbedtls_ecdh_context ecdh_ctx; /*!< ECDH key exchange */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_key_type_t ecdh_psa_type; + uint16_t ecdh_bits; + psa_key_handle_t ecdh_psa_privkey; + unsigned char ecdh_psa_peerkey[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH]; + size_t ecdh_psa_peerkey_len; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#endif /* MBEDTLS_ECDH_C */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + mbedtls_ecjpake_context ecjpake_ctx; /*!< EC J-PAKE key exchange */ +#if defined(MBEDTLS_SSL_CLI_C) + unsigned char *ecjpake_cache; /*!< Cache for ClientHello ext */ + size_t ecjpake_cache_len; /*!< Length of cached data */ +#endif +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + const mbedtls_ecp_curve_info **curves; /*!< Supported elliptic curves */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_key_handle_t psk_opaque; /*!< Opaque PSK from the callback */ +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + unsigned char *psk; /*!< PSK from the callback */ + size_t psk_len; /*!< Length of PSK from callback */ +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_ssl_key_cert *key_cert; /*!< chosen key/cert pair (server) */ +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + int sni_authmode; /*!< authmode from SNI callback */ + mbedtls_ssl_key_cert *sni_key_cert; /*!< key/cert list from SNI */ + mbedtls_x509_crt *sni_ca_chain; /*!< trusted CAs from SNI callback */ + mbedtls_x509_crl *sni_ca_crl; /*!< trusted CAs CRLs from SNI */ +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + int ecrs_enabled; /*!< Handshake supports EC restart? */ + mbedtls_x509_crt_restart_ctx ecrs_ctx; /*!< restart context */ + enum { /* this complements ssl->state with info on intra-state operations */ + ssl_ecrs_none = 0, /*!< nothing going on (yet) */ + ssl_ecrs_crt_verify, /*!< Certificate: crt_verify() */ + ssl_ecrs_ske_start_processing, /*!< ServerKeyExchange: pk_verify() */ + ssl_ecrs_cke_ecdh_calc_secret, /*!< ClientKeyExchange: ECDH step 2 */ + ssl_ecrs_crt_vrfy_sign, /*!< CertificateVerify: pk_sign() */ + } ecrs_state; /*!< current (or last) operation */ + mbedtls_x509_crt *ecrs_peer_cert; /*!< The peer's CRT chain. */ + size_t ecrs_n; /*!< place for saving a length */ +#endif +#if defined(MBEDTLS_X509_CRT_PARSE_C) && \ + !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + mbedtls_pk_context peer_pubkey; /*!< The public key from the peer. */ +#endif /* MBEDTLS_X509_CRT_PARSE_C && !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + unsigned int out_msg_seq; /*!< Outgoing handshake sequence number */ + unsigned int in_msg_seq; /*!< Incoming handshake sequence number */ + + unsigned char *verify_cookie; /*!< Cli: HelloVerifyRequest cookie + Srv: unused */ + unsigned char verify_cookie_len; /*!< Cli: cookie length + Srv: flag for sending a cookie */ + + uint32_t retransmit_timeout; /*!< Current value of timeout */ + unsigned char retransmit_state; /*!< Retransmission state */ + mbedtls_ssl_flight_item *flight; /*!< Current outgoing flight */ + mbedtls_ssl_flight_item *cur_msg; /*!< Current message in flight */ + unsigned char *cur_msg_p; /*!< Position in current message */ + unsigned int in_flight_start_seq; /*!< Minimum message sequence in the + flight being received */ + mbedtls_ssl_transform *alt_transform_out; /*!< Alternative transform for + resending messages */ + unsigned char alt_out_ctr[8]; /*!< Alternative record epoch/counter + for resending messages */ + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + /* The state of CID configuration in this handshake. */ + + uint8_t cid_in_use; /*!< This indicates whether the use of the CID extension + * has been negotiated. Possible values are + * #MBEDTLS_SSL_CID_ENABLED and + * #MBEDTLS_SSL_CID_DISABLED. */ + unsigned char peer_cid[ MBEDTLS_SSL_CID_OUT_LEN_MAX ]; /*! The peer's CID */ + uint8_t peer_cid_len; /*!< The length of + * \c peer_cid. */ +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + + struct + { + size_t total_bytes_buffered; /*!< Cumulative size of heap allocated + * buffers used for message buffering. */ + + uint8_t seen_ccs; /*!< Indicates if a CCS message has + * been seen in the current flight. */ + + struct mbedtls_ssl_hs_buffer + { + unsigned is_valid : 1; + unsigned is_fragmented : 1; + unsigned is_complete : 1; + unsigned char *data; + size_t data_len; + } hs[MBEDTLS_SSL_MAX_BUFFERED_HS]; + + struct + { + unsigned char *data; + size_t len; + unsigned epoch; + } future_record; + + } buffering; + + uint16_t mtu; /*!< Handshake mtu, used to fragment outgoing messages */ +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + /* + * Checksum contexts + */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + mbedtls_md5_context fin_md5; + mbedtls_sha1_context fin_sha1; +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_hash_operation_t fin_sha256_psa; +#else + mbedtls_sha256_context fin_sha256; +#endif +#endif +#if defined(MBEDTLS_SHA512_C) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_hash_operation_t fin_sha384_psa; +#else + mbedtls_sha512_context fin_sha512; +#endif +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + void (*update_checksum)(mbedtls_ssl_context *, const unsigned char *, size_t); + void (*calc_verify)(const mbedtls_ssl_context *, unsigned char *, size_t *); + void (*calc_finished)(mbedtls_ssl_context *, unsigned char *, int); + mbedtls_ssl_tls_prf_cb *tls_prf; + + mbedtls_ssl_ciphersuite_t const *ciphersuite_info; + + size_t pmslen; /*!< premaster length */ + + unsigned char randbytes[64]; /*!< random bytes */ + unsigned char premaster[MBEDTLS_PREMASTER_SIZE]; + /*!< premaster secret */ + + int resume; /*!< session resume indicator*/ + int max_major_ver; /*!< max. major version client*/ + int max_minor_ver; /*!< max. minor version client*/ + int cli_exts; /*!< client extension presence*/ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + int new_session_ticket; /*!< use NewSessionTicket? */ +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + int extended_ms; /*!< use Extended Master Secret? */ +#endif + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + unsigned int async_in_progress : 1; /*!< an asynchronous operation is in progress */ +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + /** Asynchronous operation context. This field is meant for use by the + * asynchronous operation callbacks (mbedtls_ssl_config::f_async_sign_start, + * mbedtls_ssl_config::f_async_decrypt_start, + * mbedtls_ssl_config::f_async_resume, mbedtls_ssl_config::f_async_cancel). + * The library does not use it internally. */ + void *user_async_ctx; +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ +}; + +typedef struct mbedtls_ssl_hs_buffer mbedtls_ssl_hs_buffer; + +/* + * Representation of decryption/encryption transformations on records + * + * There are the following general types of record transformations: + * - Stream transformations (TLS versions <= 1.2 only) + * Transformation adding a MAC and applying a stream-cipher + * to the authenticated message. + * - CBC block cipher transformations ([D]TLS versions <= 1.2 only) + * In addition to the distinction of the order of encryption and + * authentication, there's a fundamental difference between the + * handling in SSL3 & TLS 1.0 and TLS 1.1 and TLS 1.2: For SSL3 + * and TLS 1.0, the final IV after processing a record is used + * as the IV for the next record. No explicit IV is contained + * in an encrypted record. The IV for the first record is extracted + * at key extraction time. In contrast, for TLS 1.1 and 1.2, no + * IV is generated at key extraction time, but every encrypted + * record is explicitly prefixed by the IV with which it was encrypted. + * - AEAD transformations ([D]TLS versions >= 1.2 only) + * These come in two fundamentally different versions, the first one + * used in TLS 1.2, excluding ChaChaPoly ciphersuites, and the second + * one used for ChaChaPoly ciphersuites in TLS 1.2 as well as for TLS 1.3. + * In the first transformation, the IV to be used for a record is obtained + * as the concatenation of an explicit, static 4-byte IV and the 8-byte + * record sequence number, and explicitly prepending this sequence number + * to the encrypted record. In contrast, in the second transformation + * the IV is obtained by XOR'ing a static IV obtained at key extraction + * time with the 8-byte record sequence number, without prepending the + * latter to the encrypted record. + * + * Additionally, DTLS 1.2 + CID as well as TLS 1.3 use an inner plaintext + * which allows to add flexible length padding and to hide a record's true + * content type. + * + * In addition to type and version, the following parameters are relevant: + * - The symmetric cipher algorithm to be used. + * - The (static) encryption/decryption keys for the cipher. + * - For stream/CBC, the type of message digest to be used. + * - For stream/CBC, (static) encryption/decryption keys for the digest. + * - For AEAD transformations, the size (potentially 0) of an explicit, + * random initialization vector placed in encrypted records. + * - For some transformations (currently AEAD and CBC in SSL3 and TLS 1.0) + * an implicit IV. It may be static (e.g. AEAD) or dynamic (e.g. CBC) + * and (if present) is combined with the explicit IV in a transformation- + * dependent way (e.g. appending in TLS 1.2 and XOR'ing in TLS 1.3). + * - For stream/CBC, a flag determining the order of encryption and MAC. + * - The details of the transformation depend on the SSL/TLS version. + * - The length of the authentication tag. + * + * Note: Except for CBC in SSL3 and TLS 1.0, these parameters are + * constant across multiple encryption/decryption operations. + * For CBC, the implicit IV needs to be updated after each + * operation. + * + * The struct below refines this abstract view as follows: + * - The cipher underlying the transformation is managed in + * cipher contexts cipher_ctx_{enc/dec}, which must have the + * same cipher type. The mode of these cipher contexts determines + * the type of the transformation in the sense above: e.g., if + * the type is MBEDTLS_CIPHER_AES_256_CBC resp. MBEDTLS_CIPHER_AES_192_GCM + * then the transformation has type CBC resp. AEAD. + * - The cipher keys are never stored explicitly but + * are maintained within cipher_ctx_{enc/dec}. + * - For stream/CBC transformations, the message digest contexts + * used for the MAC's are stored in md_ctx_{enc/dec}. These contexts + * are unused for AEAD transformations. + * - For stream/CBC transformations and versions > SSL3, the + * MAC keys are not stored explicitly but maintained within + * md_ctx_{enc/dec}. + * - For stream/CBC transformations and version SSL3, the MAC + * keys are stored explicitly in mac_enc, mac_dec and have + * a fixed size of 20 bytes. These fields are unused for + * AEAD transformations or transformations >= TLS 1.0. + * - For transformations using an implicit IV maintained within + * the transformation context, its contents are stored within + * iv_{enc/dec}. + * - The value of ivlen indicates the length of the IV. + * This is redundant in case of stream/CBC transformations + * which always use 0 resp. the cipher's block length as the + * IV length, but is needed for AEAD ciphers and may be + * different from the underlying cipher's block length + * in this case. + * - The field fixed_ivlen is nonzero for AEAD transformations only + * and indicates the length of the static part of the IV which is + * constant throughout the communication, and which is stored in + * the first fixed_ivlen bytes of the iv_{enc/dec} arrays. + * Note: For CBC in SSL3 and TLS 1.0, the fields iv_{enc/dec} + * still store IV's for continued use across multiple transformations, + * so it is not true that fixed_ivlen == 0 means that iv_{enc/dec} are + * not being used! + * - minor_ver denotes the SSL/TLS version + * - For stream/CBC transformations, maclen denotes the length of the + * authentication tag, while taglen is unused and 0. + * - For AEAD transformations, taglen denotes the length of the + * authentication tag, while maclen is unused and 0. + * - For CBC transformations, encrypt_then_mac determines the + * order of encryption and authentication. This field is unused + * in other transformations. + * + */ +struct mbedtls_ssl_transform +{ + /* + * Session specific crypto layer + */ + size_t minlen; /*!< min. ciphertext length */ + size_t ivlen; /*!< IV length */ + size_t fixed_ivlen; /*!< Fixed part of IV (AEAD) */ + size_t maclen; /*!< MAC(CBC) len */ + size_t taglen; /*!< TAG(AEAD) len */ + + unsigned char iv_enc[16]; /*!< IV (encryption) */ + unsigned char iv_dec[16]; /*!< IV (decryption) */ + +#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + /* Needed only for SSL v3.0 secret */ + unsigned char mac_enc[20]; /*!< SSL v3.0 secret (enc) */ + unsigned char mac_dec[20]; /*!< SSL v3.0 secret (dec) */ +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + + mbedtls_md_context_t md_ctx_enc; /*!< MAC (encryption) */ + mbedtls_md_context_t md_ctx_dec; /*!< MAC (decryption) */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + int encrypt_then_mac; /*!< flag for EtM activation */ +#endif + +#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */ + + mbedtls_cipher_context_t cipher_ctx_enc; /*!< encryption context */ + mbedtls_cipher_context_t cipher_ctx_dec; /*!< decryption context */ + int minor_ver; + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + uint8_t in_cid_len; + uint8_t out_cid_len; + unsigned char in_cid [ MBEDTLS_SSL_CID_OUT_LEN_MAX ]; + unsigned char out_cid[ MBEDTLS_SSL_CID_OUT_LEN_MAX ]; +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + + /* + * Session specific compression layer + */ +#if defined(MBEDTLS_ZLIB_SUPPORT) + z_stream ctx_deflate; /*!< compression context */ + z_stream ctx_inflate; /*!< decompression context */ +#endif + +#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) + /* We need the Hello random bytes in order to re-derive keys from the + * Master Secret and other session info, see ssl_populate_transform() */ + unsigned char randbytes[64]; /*!< ServerHello.random+ClientHello.random */ +#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */ +}; + +/* + * Return 1 if the transform uses an AEAD cipher, 0 otherwise. + * Equivalently, return 0 if a separate MAC is used, 1 otherwise. + */ +static inline int mbedtls_ssl_transform_uses_aead( + const mbedtls_ssl_transform *transform ) +{ +#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) + return( transform->maclen == 0 && transform->taglen != 0 ); +#else + (void) transform; + return( 1 ); +#endif +} + +/* + * Internal representation of record frames + * + * Instances come in two flavors: + * (1) Encrypted + * These always have data_offset = 0 + * (2) Unencrypted + * These have data_offset set to the amount of + * pre-expansion during record protection. Concretely, + * this is the length of the fixed part of the explicit IV + * used for encryption, or 0 if no explicit IV is used + * (e.g. for CBC in TLS 1.0, or stream ciphers). + * + * The reason for the data_offset in the unencrypted case + * is to allow for in-place conversion of an unencrypted to + * an encrypted record. If the offset wasn't included, the + * encrypted content would need to be shifted afterwards to + * make space for the fixed IV. + * + */ +#if MBEDTLS_SSL_CID_OUT_LEN_MAX > MBEDTLS_SSL_CID_IN_LEN_MAX +#define MBEDTLS_SSL_CID_LEN_MAX MBEDTLS_SSL_CID_OUT_LEN_MAX +#else +#define MBEDTLS_SSL_CID_LEN_MAX MBEDTLS_SSL_CID_IN_LEN_MAX +#endif + +typedef struct +{ + uint8_t ctr[8]; /* In TLS: The implicit record sequence number. + * In DTLS: The 2-byte epoch followed by + * the 6-byte sequence number. + * This is stored as a raw big endian byte array + * as opposed to a uint64_t because we rarely + * need to perform arithmetic on this, but do + * need it as a Byte array for the purpose of + * MAC computations. */ + uint8_t type; /* The record content type. */ + uint8_t ver[2]; /* SSL/TLS version as present on the wire. + * Convert to internal presentation of versions + * using mbedtls_ssl_read_version() and + * mbedtls_ssl_write_version(). + * Keep wire-format for MAC computations. */ + + unsigned char *buf; /* Memory buffer enclosing the record content */ + size_t buf_len; /* Buffer length */ + size_t data_offset; /* Offset of record content */ + size_t data_len; /* Length of record content */ + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + uint8_t cid_len; /* Length of the CID (0 if not present) */ + unsigned char cid[ MBEDTLS_SSL_CID_LEN_MAX ]; /* The CID */ +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ +} mbedtls_record; + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/* + * List of certificate + private key pairs + */ +struct mbedtls_ssl_key_cert +{ + mbedtls_x509_crt *cert; /*!< cert */ + mbedtls_pk_context *key; /*!< private key */ + mbedtls_ssl_key_cert *next; /*!< next key/cert pair */ +}; +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +/* + * List of handshake messages kept around for resending + */ +struct mbedtls_ssl_flight_item +{ + unsigned char *p; /*!< message, including handshake headers */ + size_t len; /*!< length of p */ + unsigned char type; /*!< type of the message: handshake or CCS */ + mbedtls_ssl_flight_item *next; /*!< next handshake message(s) */ +}; +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + +/* Find an entry in a signature-hash set matching a given hash algorithm. */ +mbedtls_md_type_t mbedtls_ssl_sig_hash_set_find( mbedtls_ssl_sig_hash_set_t *set, + mbedtls_pk_type_t sig_alg ); +/* Add a signature-hash-pair to a signature-hash set */ +void mbedtls_ssl_sig_hash_set_add( mbedtls_ssl_sig_hash_set_t *set, + mbedtls_pk_type_t sig_alg, + mbedtls_md_type_t md_alg ); +/* Allow exactly one hash algorithm for each signature. */ +void mbedtls_ssl_sig_hash_set_const_hash( mbedtls_ssl_sig_hash_set_t *set, + mbedtls_md_type_t md_alg ); + +/* Setup an empty signature-hash set */ +static inline void mbedtls_ssl_sig_hash_set_init( mbedtls_ssl_sig_hash_set_t *set ) +{ + mbedtls_ssl_sig_hash_set_const_hash( set, MBEDTLS_MD_NONE ); +} + +#endif /* MBEDTLS_SSL_PROTO_TLS1_2) && + MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + +/** + * \brief Free referenced items in an SSL transform context and clear + * memory + * + * \param transform SSL transform context + */ +void mbedtls_ssl_transform_free( mbedtls_ssl_transform *transform ); + +/** + * \brief Free referenced items in an SSL handshake context and clear + * memory + * + * \param ssl SSL context + */ +void mbedtls_ssl_handshake_free( mbedtls_ssl_context *ssl ); + +int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_handshake_server_step( mbedtls_ssl_context *ssl ); +void mbedtls_ssl_handshake_wrapup( mbedtls_ssl_context *ssl ); + +int mbedtls_ssl_send_fatal_handshake_failure( mbedtls_ssl_context *ssl ); + +void mbedtls_ssl_reset_checksum( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ); + +int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl ); +void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl ); + +/** + * \brief Update record layer + * + * This function roughly separates the implementation + * of the logic of (D)TLS from the implementation + * of the secure transport. + * + * \param ssl The SSL context to use. + * \param update_hs_digest This indicates if the handshake digest + * should be automatically updated in case + * a handshake message is found. + * + * \return 0 or non-zero error code. + * + * \note A clarification on what is called 'record layer' here + * is in order, as many sensible definitions are possible: + * + * The record layer takes as input an untrusted underlying + * transport (stream or datagram) and transforms it into + * a serially multiplexed, secure transport, which + * conceptually provides the following: + * + * (1) Three datagram based, content-agnostic transports + * for handshake, alert and CCS messages. + * (2) One stream- or datagram-based transport + * for application data. + * (3) Functionality for changing the underlying transform + * securing the contents. + * + * The interface to this functionality is given as follows: + * + * a Updating + * [Currently implemented by mbedtls_ssl_read_record] + * + * Check if and on which of the four 'ports' data is pending: + * Nothing, a controlling datagram of type (1), or application + * data (2). In any case data is present, internal buffers + * provide access to the data for the user to process it. + * Consumption of type (1) datagrams is done automatically + * on the next update, invalidating that the internal buffers + * for previous datagrams, while consumption of application + * data (2) is user-controlled. + * + * b Reading of application data + * [Currently manual adaption of ssl->in_offt pointer] + * + * As mentioned in the last paragraph, consumption of data + * is different from the automatic consumption of control + * datagrams (1) because application data is treated as a stream. + * + * c Tracking availability of application data + * [Currently manually through decreasing ssl->in_msglen] + * + * For efficiency and to retain datagram semantics for + * application data in case of DTLS, the record layer + * provides functionality for checking how much application + * data is still available in the internal buffer. + * + * d Changing the transformation securing the communication. + * + * Given an opaque implementation of the record layer in the + * above sense, it should be possible to implement the logic + * of (D)TLS on top of it without the need to know anything + * about the record layer's internals. This is done e.g. + * in all the handshake handling functions, and in the + * application data reading function mbedtls_ssl_read. + * + * \note The above tries to give a conceptual picture of the + * record layer, but the current implementation deviates + * from it in some places. For example, our implementation of + * the update functionality through mbedtls_ssl_read_record + * discards datagrams depending on the current state, which + * wouldn't fall under the record layer's responsibility + * following the above definition. + * + */ +int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl, + unsigned update_hs_digest ); +int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want ); + +int mbedtls_ssl_write_handshake_msg( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl, uint8_t force_flush ); +int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl ); + +int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl ); + +int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_write_change_cipher_spec( mbedtls_ssl_context *ssl ); + +int mbedtls_ssl_parse_finished( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl ); + +void mbedtls_ssl_optimize_checksum( mbedtls_ssl_context *ssl, + const mbedtls_ssl_ciphersuite_t *ciphersuite_info ); + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) +int mbedtls_ssl_psk_derive_premaster( mbedtls_ssl_context *ssl, mbedtls_key_exchange_type_t key_ex ); + +/** + * Get the first defined PSK by order of precedence: + * 1. handshake PSK set by \c mbedtls_ssl_set_hs_psk() in the PSK callback + * 2. static PSK configured by \c mbedtls_ssl_conf_psk() + * Return a code and update the pair (PSK, PSK length) passed to this function + */ +static inline int mbedtls_ssl_get_psk( const mbedtls_ssl_context *ssl, + const unsigned char **psk, size_t *psk_len ) +{ + if( ssl->handshake->psk != NULL && ssl->handshake->psk_len > 0 ) + { + *psk = ssl->handshake->psk; + *psk_len = ssl->handshake->psk_len; + } + + else if( ssl->conf->psk != NULL && ssl->conf->psk_len > 0 ) + { + *psk = ssl->conf->psk; + *psk_len = ssl->conf->psk_len; + } + + else + { + *psk = NULL; + *psk_len = 0; + return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); + } + + return( 0 ); +} + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/** + * Get the first defined opaque PSK by order of precedence: + * 1. handshake PSK set by \c mbedtls_ssl_set_hs_psk_opaque() in the PSK + * callback + * 2. static PSK configured by \c mbedtls_ssl_conf_psk_opaque() + * Return an opaque PSK + */ +static inline psa_key_handle_t mbedtls_ssl_get_opaque_psk( + const mbedtls_ssl_context *ssl ) +{ + if( ssl->handshake->psk_opaque != 0 ) + return( ssl->handshake->psk_opaque ); + + if( ssl->conf->psk_opaque != 0 ) + return( ssl->conf->psk_opaque ); + + return( 0 ); +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ + +#if defined(MBEDTLS_PK_C) +unsigned char mbedtls_ssl_sig_from_pk( mbedtls_pk_context *pk ); +unsigned char mbedtls_ssl_sig_from_pk_alg( mbedtls_pk_type_t type ); +mbedtls_pk_type_t mbedtls_ssl_pk_alg_from_sig( unsigned char sig ); +#endif + +mbedtls_md_type_t mbedtls_ssl_md_alg_from_hash( unsigned char hash ); +unsigned char mbedtls_ssl_hash_from_md_alg( int md ); +int mbedtls_ssl_set_calc_verify_md( mbedtls_ssl_context *ssl, int md ); + +#if defined(MBEDTLS_ECP_C) +int mbedtls_ssl_check_curve( const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id ); +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) +int mbedtls_ssl_check_sig_hash( const mbedtls_ssl_context *ssl, + mbedtls_md_type_t md ); +#endif + +#if defined(MBEDTLS_SSL_DTLS_SRTP) +static inline mbedtls_ssl_srtp_profile mbedtls_ssl_check_srtp_profile_value + ( const uint16_t srtp_profile_value ) +{ + switch( srtp_profile_value ) + { + case MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_80: + case MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_32: + case MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_80: + case MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_32: + return srtp_profile_value; + default: break; + } + return( MBEDTLS_TLS_SRTP_UNSET ); +} +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +static inline mbedtls_pk_context *mbedtls_ssl_own_key( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_key_cert *key_cert; + + if( ssl->handshake != NULL && ssl->handshake->key_cert != NULL ) + key_cert = ssl->handshake->key_cert; + else + key_cert = ssl->conf->key_cert; + + return( key_cert == NULL ? NULL : key_cert->key ); +} + +static inline mbedtls_x509_crt *mbedtls_ssl_own_cert( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_key_cert *key_cert; + + if( ssl->handshake != NULL && ssl->handshake->key_cert != NULL ) + key_cert = ssl->handshake->key_cert; + else + key_cert = ssl->conf->key_cert; + + return( key_cert == NULL ? NULL : key_cert->cert ); +} + +/* + * Check usage of a certificate wrt extensions: + * keyUsage, extendedKeyUsage (later), and nSCertType (later). + * + * Warning: cert_endpoint is the endpoint of the cert (ie, of our peer when we + * check a cert we received from them)! + * + * Return 0 if everything is OK, -1 if not. + */ +int mbedtls_ssl_check_cert_usage( const mbedtls_x509_crt *cert, + const mbedtls_ssl_ciphersuite_t *ciphersuite, + int cert_endpoint, + uint32_t *flags ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +void mbedtls_ssl_write_version( int major, int minor, int transport, + unsigned char ver[2] ); +void mbedtls_ssl_read_version( int *major, int *minor, int transport, + const unsigned char ver[2] ); + +static inline size_t mbedtls_ssl_in_hdr_len( const mbedtls_ssl_context *ssl ) +{ +#if !defined(MBEDTLS_SSL_PROTO_DTLS) + ((void) ssl); +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + return( 13 ); + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + { + return( 5 ); + } +} + +static inline size_t mbedtls_ssl_out_hdr_len( const mbedtls_ssl_context *ssl ) +{ + return( (size_t) ( ssl->out_iv - ssl->out_hdr ) ); +} + +static inline size_t mbedtls_ssl_hs_hdr_len( const mbedtls_ssl_context *ssl ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + return( 12 ); +#else + ((void) ssl); +#endif + return( 4 ); +} + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +void mbedtls_ssl_send_flight_completed( mbedtls_ssl_context *ssl ); +void mbedtls_ssl_recv_flight_completed( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_resend( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_flight_transmit( mbedtls_ssl_context *ssl ); +#endif + +/* Visible for testing purposes only */ +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +int mbedtls_ssl_dtls_replay_check( mbedtls_ssl_context const *ssl ); +void mbedtls_ssl_dtls_replay_update( mbedtls_ssl_context *ssl ); +#endif + +int mbedtls_ssl_session_copy( mbedtls_ssl_session *dst, + const mbedtls_ssl_session *src ); + +/* constant-time buffer comparison */ +static inline int mbedtls_ssl_safer_memcmp( const void *a, const void *b, size_t n ) +{ + size_t i; + volatile const unsigned char *A = (volatile const unsigned char *) a; + volatile const unsigned char *B = (volatile const unsigned char *) b; + volatile unsigned char diff = 0; + + for( i = 0; i < n; i++ ) + { + /* Read volatile data in order before computing diff. + * This avoids IAR compiler warning: + * 'the order of volatile accesses is undefined ..' */ + unsigned char x = A[i], y = B[i]; + diff |= x ^ y; + } + + return( diff ); +} + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) +int mbedtls_ssl_get_key_exchange_md_ssl_tls( mbedtls_ssl_context *ssl, + unsigned char *output, + unsigned char *data, size_t data_len ); +#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ + MBEDTLS_SSL_PROTO_TLS1_1 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) +/* The hash buffer must have at least MBEDTLS_MD_MAX_SIZE bytes of length. */ +int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl, + unsigned char *hash, size_t *hashlen, + unsigned char *data, size_t data_len, + mbedtls_md_type_t md_alg ); +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ + MBEDTLS_SSL_PROTO_TLS1_2 */ + +#ifdef __cplusplus +} +#endif + +void mbedtls_ssl_transform_init( mbedtls_ssl_transform *transform ); +int mbedtls_ssl_encrypt_buf( mbedtls_ssl_context *ssl, + mbedtls_ssl_transform *transform, + mbedtls_record *rec, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context const *ssl, + mbedtls_ssl_transform *transform, + mbedtls_record *rec ); + +/* Length of the "epoch" field in the record header */ +static inline size_t mbedtls_ssl_ep_len( const mbedtls_ssl_context *ssl ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + return( 2 ); +#else + ((void) ssl); +#endif + return( 0 ); +} + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +int mbedtls_ssl_resend_hello_request( mbedtls_ssl_context *ssl ); +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +void mbedtls_ssl_set_timer( mbedtls_ssl_context *ssl, uint32_t millisecs ); +int mbedtls_ssl_check_timer( mbedtls_ssl_context *ssl ); + +void mbedtls_ssl_reset_in_out_pointers( mbedtls_ssl_context *ssl ); +void mbedtls_ssl_update_out_pointers( mbedtls_ssl_context *ssl, + mbedtls_ssl_transform *transform ); +void mbedtls_ssl_update_in_pointers( mbedtls_ssl_context *ssl ); + +int mbedtls_ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ); + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +void mbedtls_ssl_dtls_replay_reset( mbedtls_ssl_context *ssl ); +#endif + +void mbedtls_ssl_handshake_wrapup_free_hs_transform( mbedtls_ssl_context *ssl ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +int mbedtls_ssl_start_renegotiation( mbedtls_ssl_context *ssl ); +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +size_t mbedtls_ssl_get_current_mtu( const mbedtls_ssl_context *ssl ); +void mbedtls_ssl_buffering_free( mbedtls_ssl_context *ssl ); +void mbedtls_ssl_flight_free( mbedtls_ssl_flight_item *flight ); +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#endif /* ssl_internal.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ssl_ticket.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ssl_ticket.h new file mode 100644 index 0000000..bf5fc97 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/ssl_ticket.h @@ -0,0 +1,140 @@ +/** + * \file ssl_ticket.h + * + * \brief TLS server ticket callbacks implementation + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_SSL_TICKET_H +#define MBEDTLS_SSL_TICKET_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +/* + * This implementation of the session ticket callbacks includes key + * management, rotating the keys periodically in order to preserve forward + * secrecy, when MBEDTLS_HAVE_TIME is defined. + */ + +#include "mbedtls/ssl.h" +#include "mbedtls/cipher.h" + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Information for session ticket protection + */ +typedef struct mbedtls_ssl_ticket_key +{ + unsigned char name[4]; /*!< random key identifier */ + uint32_t generation_time; /*!< key generation timestamp (seconds) */ + mbedtls_cipher_context_t ctx; /*!< context for auth enc/decryption */ +} +mbedtls_ssl_ticket_key; + +/** + * \brief Context for session ticket handling functions + */ +typedef struct mbedtls_ssl_ticket_context +{ + mbedtls_ssl_ticket_key keys[2]; /*!< ticket protection keys */ + unsigned char active; /*!< index of the currently active key */ + + uint32_t ticket_lifetime; /*!< lifetime of tickets in seconds */ + + /** Callback for getting (pseudo-)random numbers */ + int (*f_rng)(void *, unsigned char *, size_t); + void *p_rng; /*!< context for the RNG function */ + +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; +#endif +} +mbedtls_ssl_ticket_context; + +/** + * \brief Initialize a ticket context. + * (Just make it ready for mbedtls_ssl_ticket_setup() + * or mbedtls_ssl_ticket_free().) + * + * \param ctx Context to be initialized + */ +void mbedtls_ssl_ticket_init( mbedtls_ssl_ticket_context *ctx ); + +/** + * \brief Prepare context to be actually used + * + * \param ctx Context to be set up + * \param f_rng RNG callback function + * \param p_rng RNG callback context + * \param cipher AEAD cipher to use for ticket protection. + * Recommended value: MBEDTLS_CIPHER_AES_256_GCM. + * \param lifetime Tickets lifetime in seconds + * Recommended value: 86400 (one day). + * + * \note It is highly recommended to select a cipher that is at + * least as strong as the the strongest ciphersuite + * supported. Usually that means a 256-bit key. + * + * \note The lifetime of the keys is twice the lifetime of tickets. + * It is recommended to pick a reasonnable lifetime so as not + * to negate the benefits of forward secrecy. + * + * \return 0 if successful, + * or a specific MBEDTLS_ERR_XXX error code + */ +int mbedtls_ssl_ticket_setup( mbedtls_ssl_ticket_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_cipher_type_t cipher, + uint32_t lifetime ); + +/** + * \brief Implementation of the ticket write callback + * + * \note See \c mbedtls_ssl_ticket_write_t for description + */ +mbedtls_ssl_ticket_write_t mbedtls_ssl_ticket_write; + +/** + * \brief Implementation of the ticket parse callback + * + * \note See \c mbedtls_ssl_ticket_parse_t for description + */ +mbedtls_ssl_ticket_parse_t mbedtls_ssl_ticket_parse; + +/** + * \brief Free a context's content and zeroize it. + * + * \param ctx Context to be cleaned up + */ +void mbedtls_ssl_ticket_free( mbedtls_ssl_ticket_context *ctx ); + +#ifdef __cplusplus +} +#endif + +#endif /* ssl_ticket.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/threading.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/threading.h new file mode 100644 index 0000000..8baf15a --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/threading.h @@ -0,0 +1,120 @@ +/** + * \file threading.h + * + * \brief Threading abstraction layer + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_THREADING_H +#define MBEDTLS_THREADING_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE is deprecated and should not be + * used. */ +#define MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE -0x001A /**< The selected feature is not available. */ + +#define MBEDTLS_ERR_THREADING_BAD_INPUT_DATA -0x001C /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_THREADING_MUTEX_ERROR -0x001E /**< Locking / unlocking / free failed with error code. */ + +#if defined(MBEDTLS_THREADING_PTHREAD) +#include +typedef struct mbedtls_threading_mutex_t +{ + pthread_mutex_t mutex; + char is_valid; +} mbedtls_threading_mutex_t; +#endif + +#if defined(MBEDTLS_THREADING_ALT) +/* You should define the mbedtls_threading_mutex_t type in your header */ +#include "threading_alt.h" + +/** + * \brief Set your alternate threading implementation function + * pointers and initialize global mutexes. If used, this + * function must be called once in the main thread before any + * other mbed TLS function is called, and + * mbedtls_threading_free_alt() must be called once in the main + * thread after all other mbed TLS functions. + * + * \note mutex_init() and mutex_free() don't return a status code. + * If mutex_init() fails, it should leave its argument (the + * mutex) in a state such that mutex_lock() will fail when + * called with this argument. + * + * \param mutex_init the init function implementation + * \param mutex_free the free function implementation + * \param mutex_lock the lock function implementation + * \param mutex_unlock the unlock function implementation + */ +void mbedtls_threading_set_alt( void (*mutex_init)( mbedtls_threading_mutex_t * ), + void (*mutex_free)( mbedtls_threading_mutex_t * ), + int (*mutex_lock)( mbedtls_threading_mutex_t * ), + int (*mutex_unlock)( mbedtls_threading_mutex_t * ) ); + +/** + * \brief Free global mutexes. + */ +void mbedtls_threading_free_alt( void ); +#endif /* MBEDTLS_THREADING_ALT */ + +#if defined(MBEDTLS_THREADING_C) +/* + * The function pointers for mutex_init, mutex_free, mutex_ and mutex_unlock + * + * All these functions are expected to work or the result will be undefined. + */ +extern void (*mbedtls_mutex_init)( mbedtls_threading_mutex_t *mutex ); +extern void (*mbedtls_mutex_free)( mbedtls_threading_mutex_t *mutex ); +extern int (*mbedtls_mutex_lock)( mbedtls_threading_mutex_t *mutex ); +extern int (*mbedtls_mutex_unlock)( mbedtls_threading_mutex_t *mutex ); + +/* + * Global mutexes + */ +#if defined(MBEDTLS_FS_IO) +extern mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex; +#endif + +#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT) +/* This mutex may or may not be used in the default definition of + * mbedtls_platform_gmtime_r(), but in order to determine that, + * we need to check POSIX features, hence modify _POSIX_C_SOURCE. + * With the current approach, this declaration is orphaned, lacking + * an accompanying definition, in case mbedtls_platform_gmtime_r() + * doesn't need it, but that's not a problem. */ +extern mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex; +#endif /* MBEDTLS_HAVE_TIME_DATE && !MBEDTLS_PLATFORM_GMTIME_R_ALT */ + +#endif /* MBEDTLS_THREADING_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* threading.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/timing.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/timing.h new file mode 100644 index 0000000..b7290cf --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/timing.h @@ -0,0 +1,151 @@ +/** + * \file timing.h + * + * \brief Portable interface to timeouts and to the CPU cycle counter + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_TIMING_H +#define MBEDTLS_TIMING_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_TIMING_ALT) +// Regular implementation +// + +/** + * \brief timer structure + */ +struct mbedtls_timing_hr_time +{ + unsigned char opaque[32]; +}; + +/** + * \brief Context for mbedtls_timing_set/get_delay() + */ +typedef struct mbedtls_timing_delay_context +{ + struct mbedtls_timing_hr_time timer; + uint32_t int_ms; + uint32_t fin_ms; +} mbedtls_timing_delay_context; + +#else /* MBEDTLS_TIMING_ALT */ +#include "timing_alt.h" +#endif /* MBEDTLS_TIMING_ALT */ + +extern volatile int mbedtls_timing_alarmed; + +/** + * \brief Return the CPU cycle counter value + * + * \warning This is only a best effort! Do not rely on this! + * In particular, it is known to be unreliable on virtual + * machines. + * + * \note This value starts at an unspecified origin and + * may wrap around. + */ +unsigned long mbedtls_timing_hardclock( void ); + +/** + * \brief Return the elapsed time in milliseconds + * + * \param val points to a timer structure + * \param reset If 0, query the elapsed time. Otherwise (re)start the timer. + * + * \return Elapsed time since the previous reset in ms. When + * restarting, this is always 0. + * + * \note To initialize a timer, call this function with reset=1. + * + * Determining the elapsed time and resetting the timer is not + * atomic on all platforms, so after the sequence + * `{ get_timer(1); ...; time1 = get_timer(1); ...; time2 = + * get_timer(0) }` the value time1+time2 is only approximately + * the delay since the first reset. + */ +unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset ); + +/** + * \brief Setup an alarm clock + * + * \param seconds delay before the "mbedtls_timing_alarmed" flag is set + * (must be >=0) + * + * \warning Only one alarm at a time is supported. In a threaded + * context, this means one for the whole process, not one per + * thread. + */ +void mbedtls_set_alarm( int seconds ); + +/** + * \brief Set a pair of delays to watch + * (See \c mbedtls_timing_get_delay().) + * + * \param data Pointer to timing data. + * Must point to a valid \c mbedtls_timing_delay_context struct. + * \param int_ms First (intermediate) delay in milliseconds. + * The effect if int_ms > fin_ms is unspecified. + * \param fin_ms Second (final) delay in milliseconds. + * Pass 0 to cancel the current delay. + * + * \note To set a single delay, either use \c mbedtls_timing_set_timer + * directly or use this function with int_ms == fin_ms. + */ +void mbedtls_timing_set_delay( void *data, uint32_t int_ms, uint32_t fin_ms ); + +/** + * \brief Get the status of delays + * (Memory helper: number of delays passed.) + * + * \param data Pointer to timing data + * Must point to a valid \c mbedtls_timing_delay_context struct. + * + * \return -1 if cancelled (fin_ms = 0), + * 0 if none of the delays are passed, + * 1 if only the intermediate delay is passed, + * 2 if the final delay is passed. + */ +int mbedtls_timing_get_delay( void *data ); + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_timing_self_test( int verbose ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* timing.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/version.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/version.h new file mode 100644 index 0000000..665a283 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/version.h @@ -0,0 +1,110 @@ +/** + * \file version.h + * + * \brief Run-time version information + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 set of compile-time defines and run-time variables can be used to + * determine the version number of the mbed TLS library used. + */ +#ifndef MBEDTLS_VERSION_H +#define MBEDTLS_VERSION_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +/** + * The version number x.y.z is split into three parts. + * Major, Minor, Patchlevel + */ +#define MBEDTLS_VERSION_MAJOR 2 +#define MBEDTLS_VERSION_MINOR 24 +#define MBEDTLS_VERSION_PATCH 0 + +/** + * The single version number has the following structure: + * MMNNPP00 + * Major version | Minor version | Patch version + */ +#define MBEDTLS_VERSION_NUMBER 0x02180000 +#define MBEDTLS_VERSION_STRING "2.24.0" +#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.24.0" + +#if defined(MBEDTLS_VERSION_C) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Get the version number. + * + * \return The constructed version number in the format + * MMNNPP00 (Major, Minor, Patch). + */ +unsigned int mbedtls_version_get_number( void ); + +/** + * Get the version string ("x.y.z"). + * + * \param string The string that will receive the value. + * (Should be at least 9 bytes in size) + */ +void mbedtls_version_get_string( char *string ); + +/** + * Get the full version string ("mbed TLS x.y.z"). + * + * \param string The string that will receive the value. The mbed TLS version + * string will use 18 bytes AT MOST including a terminating + * null byte. + * (So the buffer should be at least 18 bytes to receive this + * version string). + */ +void mbedtls_version_get_string_full( char *string ); + +/** + * \brief Check if support for a feature was compiled into this + * mbed TLS binary. This allows you to see at runtime if the + * library was for instance compiled with or without + * Multi-threading support. + * + * \note only checks against defines in the sections "System + * support", "mbed TLS modules" and "mbed TLS feature + * support" in config.h + * + * \param feature The string for the define to check (e.g. "MBEDTLS_AES_C") + * + * \return 0 if the feature is present, + * -1 if the feature is not present and + * -2 if support for feature checking as a whole was not + * compiled in. + */ +int mbedtls_version_check_feature( const char *feature ); + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_VERSION_C */ + +#endif /* version.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/x509.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/x509.h new file mode 100644 index 0000000..08525e2 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/x509.h @@ -0,0 +1,359 @@ +/** + * \file x509.h + * + * \brief X.509 generic defines and structures + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_X509_H +#define MBEDTLS_X509_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/asn1.h" +#include "mbedtls/pk.h" + +#if defined(MBEDTLS_RSA_C) +#include "mbedtls/rsa.h" +#endif + +/** + * \addtogroup x509_module + * \{ + */ + +#if !defined(MBEDTLS_X509_MAX_INTERMEDIATE_CA) +/** + * Maximum number of intermediate CAs in a verification chain. + * That is, maximum length of the chain, excluding the end-entity certificate + * and the trusted root certificate. + * + * Set this to a low value to prevent an adversary from making you waste + * resources verifying an overlong certificate chain. + */ +#define MBEDTLS_X509_MAX_INTERMEDIATE_CA 8 +#endif + +/** + * \name X509 Error codes + * \{ + */ +#define MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE -0x2080 /**< Unavailable feature, e.g. RSA hashing/encryption combination. */ +#define MBEDTLS_ERR_X509_UNKNOWN_OID -0x2100 /**< Requested OID is unknown. */ +#define MBEDTLS_ERR_X509_INVALID_FORMAT -0x2180 /**< The CRT/CRL/CSR format is invalid, e.g. different type expected. */ +#define MBEDTLS_ERR_X509_INVALID_VERSION -0x2200 /**< The CRT/CRL/CSR version element is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_SERIAL -0x2280 /**< The serial tag or value is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_ALG -0x2300 /**< The algorithm tag or value is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_NAME -0x2380 /**< The name tag or value is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_DATE -0x2400 /**< The date tag or value is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_SIGNATURE -0x2480 /**< The signature tag or value invalid. */ +#define MBEDTLS_ERR_X509_INVALID_EXTENSIONS -0x2500 /**< The extension tag or value is invalid. */ +#define MBEDTLS_ERR_X509_UNKNOWN_VERSION -0x2580 /**< CRT/CRL/CSR has an unsupported version number. */ +#define MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG -0x2600 /**< Signature algorithm (oid) is unsupported. */ +#define MBEDTLS_ERR_X509_SIG_MISMATCH -0x2680 /**< Signature algorithms do not match. (see \c ::mbedtls_x509_crt sig_oid) */ +#define MBEDTLS_ERR_X509_CERT_VERIFY_FAILED -0x2700 /**< Certificate verification failed, e.g. CRL, CA or signature check failed. */ +#define MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT -0x2780 /**< Format not recognized as DER or PEM. */ +#define MBEDTLS_ERR_X509_BAD_INPUT_DATA -0x2800 /**< Input invalid. */ +#define MBEDTLS_ERR_X509_ALLOC_FAILED -0x2880 /**< Allocation of memory failed. */ +#define MBEDTLS_ERR_X509_FILE_IO_ERROR -0x2900 /**< Read/write of file failed. */ +#define MBEDTLS_ERR_X509_BUFFER_TOO_SMALL -0x2980 /**< Destination buffer is too small. */ +#define MBEDTLS_ERR_X509_FATAL_ERROR -0x3000 /**< A fatal error occurred, eg the chain is too long or the vrfy callback failed. */ +/* \} name */ + +/** + * \name X509 Verify codes + * \{ + */ +/* Reminder: update x509_crt_verify_strings[] in library/x509_crt.c */ +#define MBEDTLS_X509_BADCERT_EXPIRED 0x01 /**< The certificate validity has expired. */ +#define MBEDTLS_X509_BADCERT_REVOKED 0x02 /**< The certificate has been revoked (is on a CRL). */ +#define MBEDTLS_X509_BADCERT_CN_MISMATCH 0x04 /**< The certificate Common Name (CN) does not match with the expected CN. */ +#define MBEDTLS_X509_BADCERT_NOT_TRUSTED 0x08 /**< The certificate is not correctly signed by the trusted CA. */ +#define MBEDTLS_X509_BADCRL_NOT_TRUSTED 0x10 /**< The CRL is not correctly signed by the trusted CA. */ +#define MBEDTLS_X509_BADCRL_EXPIRED 0x20 /**< The CRL is expired. */ +#define MBEDTLS_X509_BADCERT_MISSING 0x40 /**< Certificate was missing. */ +#define MBEDTLS_X509_BADCERT_SKIP_VERIFY 0x80 /**< Certificate verification was skipped. */ +#define MBEDTLS_X509_BADCERT_OTHER 0x0100 /**< Other reason (can be used by verify callback) */ +#define MBEDTLS_X509_BADCERT_FUTURE 0x0200 /**< The certificate validity starts in the future. */ +#define MBEDTLS_X509_BADCRL_FUTURE 0x0400 /**< The CRL is from the future */ +#define MBEDTLS_X509_BADCERT_KEY_USAGE 0x0800 /**< Usage does not match the keyUsage extension. */ +#define MBEDTLS_X509_BADCERT_EXT_KEY_USAGE 0x1000 /**< Usage does not match the extendedKeyUsage extension. */ +#define MBEDTLS_X509_BADCERT_NS_CERT_TYPE 0x2000 /**< Usage does not match the nsCertType extension. */ +#define MBEDTLS_X509_BADCERT_BAD_MD 0x4000 /**< The certificate is signed with an unacceptable hash. */ +#define MBEDTLS_X509_BADCERT_BAD_PK 0x8000 /**< The certificate is signed with an unacceptable PK alg (eg RSA vs ECDSA). */ +#define MBEDTLS_X509_BADCERT_BAD_KEY 0x010000 /**< The certificate is signed with an unacceptable key (eg bad curve, RSA too short). */ +#define MBEDTLS_X509_BADCRL_BAD_MD 0x020000 /**< The CRL is signed with an unacceptable hash. */ +#define MBEDTLS_X509_BADCRL_BAD_PK 0x040000 /**< The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA). */ +#define MBEDTLS_X509_BADCRL_BAD_KEY 0x080000 /**< The CRL is signed with an unacceptable key (eg bad curve, RSA too short). */ + +/* \} name */ +/* \} addtogroup x509_module */ + +/* + * X.509 v3 Subject Alternative Name types. + * otherName [0] OtherName, + * rfc822Name [1] IA5String, + * dNSName [2] IA5String, + * x400Address [3] ORAddress, + * directoryName [4] Name, + * ediPartyName [5] EDIPartyName, + * uniformResourceIdentifier [6] IA5String, + * iPAddress [7] OCTET STRING, + * registeredID [8] OBJECT IDENTIFIER + */ +#define MBEDTLS_X509_SAN_OTHER_NAME 0 +#define MBEDTLS_X509_SAN_RFC822_NAME 1 +#define MBEDTLS_X509_SAN_DNS_NAME 2 +#define MBEDTLS_X509_SAN_X400_ADDRESS_NAME 3 +#define MBEDTLS_X509_SAN_DIRECTORY_NAME 4 +#define MBEDTLS_X509_SAN_EDI_PARTY_NAME 5 +#define MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER 6 +#define MBEDTLS_X509_SAN_IP_ADDRESS 7 +#define MBEDTLS_X509_SAN_REGISTERED_ID 8 + +/* + * X.509 v3 Key Usage Extension flags + * Reminder: update x509_info_key_usage() when adding new flags. + */ +#define MBEDTLS_X509_KU_DIGITAL_SIGNATURE (0x80) /* bit 0 */ +#define MBEDTLS_X509_KU_NON_REPUDIATION (0x40) /* bit 1 */ +#define MBEDTLS_X509_KU_KEY_ENCIPHERMENT (0x20) /* bit 2 */ +#define MBEDTLS_X509_KU_DATA_ENCIPHERMENT (0x10) /* bit 3 */ +#define MBEDTLS_X509_KU_KEY_AGREEMENT (0x08) /* bit 4 */ +#define MBEDTLS_X509_KU_KEY_CERT_SIGN (0x04) /* bit 5 */ +#define MBEDTLS_X509_KU_CRL_SIGN (0x02) /* bit 6 */ +#define MBEDTLS_X509_KU_ENCIPHER_ONLY (0x01) /* bit 7 */ +#define MBEDTLS_X509_KU_DECIPHER_ONLY (0x8000) /* bit 8 */ + +/* + * Netscape certificate types + * (http://www.mozilla.org/projects/security/pki/nss/tech-notes/tn3.html) + */ + +#define MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT (0x80) /* bit 0 */ +#define MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER (0x40) /* bit 1 */ +#define MBEDTLS_X509_NS_CERT_TYPE_EMAIL (0x20) /* bit 2 */ +#define MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING (0x10) /* bit 3 */ +#define MBEDTLS_X509_NS_CERT_TYPE_RESERVED (0x08) /* bit 4 */ +#define MBEDTLS_X509_NS_CERT_TYPE_SSL_CA (0x04) /* bit 5 */ +#define MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA (0x02) /* bit 6 */ +#define MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA (0x01) /* bit 7 */ + +/* + * X.509 extension types + * + * Comments refer to the status for using certificates. Status can be + * different for writing certificates or reading CRLs or CSRs. + * + * Those are defined in oid.h as oid.c needs them in a data structure. Since + * these were previously defined here, let's have aliases for compatibility. + */ +#define MBEDTLS_X509_EXT_AUTHORITY_KEY_IDENTIFIER MBEDTLS_OID_X509_EXT_AUTHORITY_KEY_IDENTIFIER +#define MBEDTLS_X509_EXT_SUBJECT_KEY_IDENTIFIER MBEDTLS_OID_X509_EXT_SUBJECT_KEY_IDENTIFIER +#define MBEDTLS_X509_EXT_KEY_USAGE MBEDTLS_OID_X509_EXT_KEY_USAGE +#define MBEDTLS_X509_EXT_CERTIFICATE_POLICIES MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES +#define MBEDTLS_X509_EXT_POLICY_MAPPINGS MBEDTLS_OID_X509_EXT_POLICY_MAPPINGS +#define MBEDTLS_X509_EXT_SUBJECT_ALT_NAME MBEDTLS_OID_X509_EXT_SUBJECT_ALT_NAME /* Supported (DNS) */ +#define MBEDTLS_X509_EXT_ISSUER_ALT_NAME MBEDTLS_OID_X509_EXT_ISSUER_ALT_NAME +#define MBEDTLS_X509_EXT_SUBJECT_DIRECTORY_ATTRS MBEDTLS_OID_X509_EXT_SUBJECT_DIRECTORY_ATTRS +#define MBEDTLS_X509_EXT_BASIC_CONSTRAINTS MBEDTLS_OID_X509_EXT_BASIC_CONSTRAINTS /* Supported */ +#define MBEDTLS_X509_EXT_NAME_CONSTRAINTS MBEDTLS_OID_X509_EXT_NAME_CONSTRAINTS +#define MBEDTLS_X509_EXT_POLICY_CONSTRAINTS MBEDTLS_OID_X509_EXT_POLICY_CONSTRAINTS +#define MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE MBEDTLS_OID_X509_EXT_EXTENDED_KEY_USAGE +#define MBEDTLS_X509_EXT_CRL_DISTRIBUTION_POINTS MBEDTLS_OID_X509_EXT_CRL_DISTRIBUTION_POINTS +#define MBEDTLS_X509_EXT_INIHIBIT_ANYPOLICY MBEDTLS_OID_X509_EXT_INIHIBIT_ANYPOLICY +#define MBEDTLS_X509_EXT_FRESHEST_CRL MBEDTLS_OID_X509_EXT_FRESHEST_CRL +#define MBEDTLS_X509_EXT_NS_CERT_TYPE MBEDTLS_OID_X509_EXT_NS_CERT_TYPE + +/* + * Storage format identifiers + * Recognized formats: PEM and DER + */ +#define MBEDTLS_X509_FORMAT_DER 1 +#define MBEDTLS_X509_FORMAT_PEM 2 + +#define MBEDTLS_X509_MAX_DN_NAME_SIZE 256 /**< Maximum value size of a DN entry */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup x509_module + * \{ */ + +/** + * \name Structures for parsing X.509 certificates, CRLs and CSRs + * \{ + */ + +/** + * Type-length-value structure that allows for ASN1 using DER. + */ +typedef mbedtls_asn1_buf mbedtls_x509_buf; + +/** + * Container for ASN1 bit strings. + */ +typedef mbedtls_asn1_bitstring mbedtls_x509_bitstring; + +/** + * Container for ASN1 named information objects. + * It allows for Relative Distinguished Names (e.g. cn=localhost,ou=code,etc.). + */ +typedef mbedtls_asn1_named_data mbedtls_x509_name; + +/** + * Container for a sequence of ASN.1 items + */ +typedef mbedtls_asn1_sequence mbedtls_x509_sequence; + +/** Container for date and time (precision in seconds). */ +typedef struct mbedtls_x509_time +{ + int year, mon, day; /**< Date. */ + int hour, min, sec; /**< Time. */ +} +mbedtls_x509_time; + +/** \} name Structures for parsing X.509 certificates, CRLs and CSRs */ +/** \} addtogroup x509_module */ + +/** + * \brief Store the certificate DN in printable form into buf; + * no more than size characters will be written. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param dn The X509 name to represent + * + * \return The length of the string written (not including the + * terminated nul byte), or a negative error code. + */ +int mbedtls_x509_dn_gets( char *buf, size_t size, const mbedtls_x509_name *dn ); + +/** + * \brief Store the certificate serial in printable form into buf; + * no more than size characters will be written. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param serial The X509 serial to represent + * + * \return The length of the string written (not including the + * terminated nul byte), or a negative error code. + */ +int mbedtls_x509_serial_gets( char *buf, size_t size, const mbedtls_x509_buf *serial ); + +/** + * \brief Check a given mbedtls_x509_time against the system time + * and tell if it's in the past. + * + * \note Intended usage is "if( is_past( valid_to ) ) ERROR". + * Hence the return value of 1 if on internal errors. + * + * \param to mbedtls_x509_time to check + * + * \return 1 if the given time is in the past or an error occurred, + * 0 otherwise. + */ +int mbedtls_x509_time_is_past( const mbedtls_x509_time *to ); + +/** + * \brief Check a given mbedtls_x509_time against the system time + * and tell if it's in the future. + * + * \note Intended usage is "if( is_future( valid_from ) ) ERROR". + * Hence the return value of 1 if on internal errors. + * + * \param from mbedtls_x509_time to check + * + * \return 1 if the given time is in the future or an error occurred, + * 0 otherwise. + */ +int mbedtls_x509_time_is_future( const mbedtls_x509_time *from ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_x509_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +/* + * Internal module functions. You probably do not want to use these unless you + * know you do. + */ +int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end, + mbedtls_x509_name *cur ); +int mbedtls_x509_get_alg_null( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *alg ); +int mbedtls_x509_get_alg( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *alg, mbedtls_x509_buf *params ); +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) +int mbedtls_x509_get_rsassa_pss_params( const mbedtls_x509_buf *params, + mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md, + int *salt_len ); +#endif +int mbedtls_x509_get_sig( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig ); +int mbedtls_x509_get_sig_alg( const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params, + mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg, + void **sig_opts ); +int mbedtls_x509_get_time( unsigned char **p, const unsigned char *end, + mbedtls_x509_time *t ); +int mbedtls_x509_get_serial( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *serial ); +int mbedtls_x509_get_ext( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *ext, int tag ); +int mbedtls_x509_sig_alg_gets( char *buf, size_t size, const mbedtls_x509_buf *sig_oid, + mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, + const void *sig_opts ); +int mbedtls_x509_key_size_helper( char *buf, size_t buf_size, const char *name ); +int mbedtls_x509_string_to_names( mbedtls_asn1_named_data **head, const char *name ); +int mbedtls_x509_set_extension( mbedtls_asn1_named_data **head, const char *oid, size_t oid_len, + int critical, const unsigned char *val, + size_t val_len ); +int mbedtls_x509_write_extensions( unsigned char **p, unsigned char *start, + mbedtls_asn1_named_data *first ); +int mbedtls_x509_write_names( unsigned char **p, unsigned char *start, + mbedtls_asn1_named_data *first ); +int mbedtls_x509_write_sig( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len, + unsigned char *sig, size_t size ); + +#define MBEDTLS_X509_SAFE_SNPRINTF \ + do { \ + if( ret < 0 || (size_t) ret >= n ) \ + return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL ); \ + \ + n -= (size_t) ret; \ + p += (size_t) ret; \ + } while( 0 ) + +#ifdef __cplusplus +} +#endif + +#endif /* x509.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/x509_crl.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/x509_crl.h new file mode 100644 index 0000000..7e9e888 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/x509_crl.h @@ -0,0 +1,172 @@ +/** + * \file x509_crl.h + * + * \brief X.509 certificate revocation list parsing + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_X509_CRL_H +#define MBEDTLS_X509_CRL_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/x509.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup x509_module + * \{ */ + +/** + * \name Structures and functions for parsing CRLs + * \{ + */ + +/** + * Certificate revocation list entry. + * Contains the CA-specific serial numbers and revocation dates. + */ +typedef struct mbedtls_x509_crl_entry +{ + mbedtls_x509_buf raw; + + mbedtls_x509_buf serial; + + mbedtls_x509_time revocation_date; + + mbedtls_x509_buf entry_ext; + + struct mbedtls_x509_crl_entry *next; +} +mbedtls_x509_crl_entry; + +/** + * Certificate revocation list structure. + * Every CRL may have multiple entries. + */ +typedef struct mbedtls_x509_crl +{ + mbedtls_x509_buf raw; /**< The raw certificate data (DER). */ + mbedtls_x509_buf tbs; /**< The raw certificate body (DER). The part that is To Be Signed. */ + + int version; /**< CRL version (1=v1, 2=v2) */ + mbedtls_x509_buf sig_oid; /**< CRL signature type identifier */ + + mbedtls_x509_buf issuer_raw; /**< The raw issuer data (DER). */ + + mbedtls_x509_name issuer; /**< The parsed issuer data (named information object). */ + + mbedtls_x509_time this_update; + mbedtls_x509_time next_update; + + mbedtls_x509_crl_entry entry; /**< The CRL entries containing the certificate revocation times for this CA. */ + + mbedtls_x509_buf crl_ext; + + mbedtls_x509_buf sig_oid2; + mbedtls_x509_buf sig; + mbedtls_md_type_t sig_md; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ + mbedtls_pk_type_t sig_pk; /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ + void *sig_opts; /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ + + struct mbedtls_x509_crl *next; +} +mbedtls_x509_crl; + +/** + * \brief Parse a DER-encoded CRL and append it to the chained list + * + * \param chain points to the start of the chain + * \param buf buffer holding the CRL data in DER format + * \param buflen size of the buffer + * (including the terminating null byte for PEM data) + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int mbedtls_x509_crl_parse_der( mbedtls_x509_crl *chain, + const unsigned char *buf, size_t buflen ); +/** + * \brief Parse one or more CRLs and append them to the chained list + * + * \note Multiple CRLs are accepted only if using PEM format + * + * \param chain points to the start of the chain + * \param buf buffer holding the CRL data in PEM or DER format + * \param buflen size of the buffer + * (including the terminating null byte for PEM data) + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int mbedtls_x509_crl_parse( mbedtls_x509_crl *chain, const unsigned char *buf, size_t buflen ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Load one or more CRLs and append them to the chained list + * + * \note Multiple CRLs are accepted only if using PEM format + * + * \param chain points to the start of the chain + * \param path filename to read the CRLs from (in PEM or DER encoding) + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int mbedtls_x509_crl_parse_file( mbedtls_x509_crl *chain, const char *path ); +#endif /* MBEDTLS_FS_IO */ + +/** + * \brief Returns an informational string about the CRL. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param prefix A line prefix + * \param crl The X509 CRL to represent + * + * \return The length of the string written (not including the + * terminated nul byte), or a negative error code. + */ +int mbedtls_x509_crl_info( char *buf, size_t size, const char *prefix, + const mbedtls_x509_crl *crl ); + +/** + * \brief Initialize a CRL (chain) + * + * \param crl CRL chain to initialize + */ +void mbedtls_x509_crl_init( mbedtls_x509_crl *crl ); + +/** + * \brief Unallocate all CRL data + * + * \param crl CRL chain to free + */ +void mbedtls_x509_crl_free( mbedtls_x509_crl *crl ); + +/* \} name */ +/* \} addtogroup x509_module */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_x509_crl.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/x509_crt.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/x509_crt.h new file mode 100644 index 0000000..8e389f8 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/x509_crt.h @@ -0,0 +1,1085 @@ +/** + * \file x509_crt.h + * + * \brief X.509 certificate parsing and writing + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_X509_CRT_H +#define MBEDTLS_X509_CRT_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/x509.h" +#include "mbedtls/x509_crl.h" +#include "mbedtls/bignum.h" + +/** + * \addtogroup x509_module + * \{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \name Structures and functions for parsing and writing X.509 certificates + * \{ + */ + +/** + * Container for an X.509 certificate. The certificate may be chained. + */ +typedef struct mbedtls_x509_crt +{ + int own_buffer; /**< Indicates if \c raw is owned + * by the structure or not. */ + mbedtls_x509_buf raw; /**< The raw certificate data (DER). */ + mbedtls_x509_buf tbs; /**< The raw certificate body (DER). The part that is To Be Signed. */ + + int version; /**< The X.509 version. (1=v1, 2=v2, 3=v3) */ + mbedtls_x509_buf serial; /**< Unique id for certificate issued by a specific CA. */ + mbedtls_x509_buf sig_oid; /**< Signature algorithm, e.g. sha1RSA */ + + mbedtls_x509_buf issuer_raw; /**< The raw issuer data (DER). Used for quick comparison. */ + mbedtls_x509_buf subject_raw; /**< The raw subject data (DER). Used for quick comparison. */ + + mbedtls_x509_name issuer; /**< The parsed issuer data (named information object). */ + mbedtls_x509_name subject; /**< The parsed subject data (named information object). */ + + mbedtls_x509_time valid_from; /**< Start time of certificate validity. */ + mbedtls_x509_time valid_to; /**< End time of certificate validity. */ + + mbedtls_x509_buf pk_raw; + mbedtls_pk_context pk; /**< Container for the public key context. */ + + mbedtls_x509_buf issuer_id; /**< Optional X.509 v2/v3 issuer unique identifier. */ + mbedtls_x509_buf subject_id; /**< Optional X.509 v2/v3 subject unique identifier. */ + mbedtls_x509_buf v3_ext; /**< Optional X.509 v3 extensions. */ + mbedtls_x509_sequence subject_alt_names; /**< Optional list of raw entries of Subject Alternative Names extension (currently only dNSName and OtherName are listed). */ + + mbedtls_x509_sequence certificate_policies; /**< Optional list of certificate policies (Only anyPolicy is printed and enforced, however the rest of the policies are still listed). */ + + int ext_types; /**< Bit string containing detected and parsed extensions */ + int ca_istrue; /**< Optional Basic Constraint extension value: 1 if this certificate belongs to a CA, 0 otherwise. */ + int max_pathlen; /**< Optional Basic Constraint extension value: The maximum path length to the root certificate. Path length is 1 higher than RFC 5280 'meaning', so 1+ */ + + unsigned int key_usage; /**< Optional key usage extension value: See the values in x509.h */ + + mbedtls_x509_sequence ext_key_usage; /**< Optional list of extended key usage OIDs. */ + + unsigned char ns_cert_type; /**< Optional Netscape certificate type extension value: See the values in x509.h */ + + mbedtls_x509_buf sig; /**< Signature: hash of the tbs part signed with the private key. */ + mbedtls_md_type_t sig_md; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ + mbedtls_pk_type_t sig_pk; /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ + void *sig_opts; /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ + + struct mbedtls_x509_crt *next; /**< Next certificate in the CA-chain. */ +} +mbedtls_x509_crt; + +/** + * From RFC 5280 section 4.2.1.6: + * OtherName ::= SEQUENCE { + * type-id OBJECT IDENTIFIER, + * value [0] EXPLICIT ANY DEFINED BY type-id } + */ +typedef struct mbedtls_x509_san_other_name +{ + /** + * The type_id is an OID as deifned in RFC 5280. + * To check the value of the type id, you should use + * \p MBEDTLS_OID_CMP with a known OID mbedtls_x509_buf. + */ + mbedtls_x509_buf type_id; /**< The type id. */ + union + { + /** + * From RFC 4108 section 5: + * HardwareModuleName ::= SEQUENCE { + * hwType OBJECT IDENTIFIER, + * hwSerialNum OCTET STRING } + */ + struct + { + mbedtls_x509_buf oid; /**< The object identifier. */ + mbedtls_x509_buf val; /**< The named value. */ + } + hardware_module_name; + } + value; +} +mbedtls_x509_san_other_name; + +/** + * A structure for holding the parsed Subject Alternative Name, according to type + */ +typedef struct mbedtls_x509_subject_alternative_name +{ + int type; /**< The SAN type, value of MBEDTLS_X509_SAN_XXX. */ + union { + mbedtls_x509_san_other_name other_name; /**< The otherName supported type. */ + mbedtls_x509_buf unstructured_name; /**< The buffer for the un constructed types. Only dnsName currently supported */ + } + san; /**< A union of the supported SAN types */ +} +mbedtls_x509_subject_alternative_name; + +/** + * Build flag from an algorithm/curve identifier (pk, md, ecp) + * Since 0 is always XXX_NONE, ignore it. + */ +#define MBEDTLS_X509_ID_FLAG( id ) ( 1 << ( (id) - 1 ) ) + +/** + * Security profile for certificate verification. + * + * All lists are bitfields, built by ORing flags from MBEDTLS_X509_ID_FLAG(). + */ +typedef struct mbedtls_x509_crt_profile +{ + uint32_t allowed_mds; /**< MDs for signatures */ + uint32_t allowed_pks; /**< PK algs for signatures */ + uint32_t allowed_curves; /**< Elliptic curves for ECDSA */ + uint32_t rsa_min_bitlen; /**< Minimum size for RSA keys */ +} +mbedtls_x509_crt_profile; + +#define MBEDTLS_X509_CRT_VERSION_1 0 +#define MBEDTLS_X509_CRT_VERSION_2 1 +#define MBEDTLS_X509_CRT_VERSION_3 2 + +#define MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN 32 +#define MBEDTLS_X509_RFC5280_UTC_TIME_LEN 15 + +#if !defined( MBEDTLS_X509_MAX_FILE_PATH_LEN ) +#define MBEDTLS_X509_MAX_FILE_PATH_LEN 512 +#endif + +/** + * Container for writing a certificate (CRT) + */ +typedef struct mbedtls_x509write_cert +{ + int version; + mbedtls_mpi serial; + mbedtls_pk_context *subject_key; + mbedtls_pk_context *issuer_key; + mbedtls_asn1_named_data *subject; + mbedtls_asn1_named_data *issuer; + mbedtls_md_type_t md_alg; + char not_before[MBEDTLS_X509_RFC5280_UTC_TIME_LEN + 1]; + char not_after[MBEDTLS_X509_RFC5280_UTC_TIME_LEN + 1]; + mbedtls_asn1_named_data *extensions; +} +mbedtls_x509write_cert; + +/** + * Item in a verification chain: cert and flags for it + */ +typedef struct { + mbedtls_x509_crt *crt; + uint32_t flags; +} mbedtls_x509_crt_verify_chain_item; + +/** + * Max size of verification chain: end-entity + intermediates + trusted root + */ +#define MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE ( MBEDTLS_X509_MAX_INTERMEDIATE_CA + 2 ) + +/** + * Verification chain as built by \c mbedtls_crt_verify_chain() + */ +typedef struct +{ + mbedtls_x509_crt_verify_chain_item items[MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE]; + unsigned len; + +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + /* This stores the list of potential trusted signers obtained from + * the CA callback used for the CRT verification, if configured. + * We must track it somewhere because the callback passes its + * ownership to the caller. */ + mbedtls_x509_crt *trust_ca_cb_result; +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ +} mbedtls_x509_crt_verify_chain; + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + +/** + * \brief Context for resuming X.509 verify operations + */ +typedef struct +{ + /* for check_signature() */ + mbedtls_pk_restart_ctx pk; + + /* for find_parent_in() */ + mbedtls_x509_crt *parent; /* non-null iff parent_in in progress */ + mbedtls_x509_crt *fallback_parent; + int fallback_signature_is_good; + + /* for find_parent() */ + int parent_is_trusted; /* -1 if find_parent is not in progress */ + + /* for verify_chain() */ + enum { + x509_crt_rs_none, + x509_crt_rs_find_parent, + } in_progress; /* none if no operation is in progress */ + int self_cnt; + mbedtls_x509_crt_verify_chain ver_chain; + +} mbedtls_x509_crt_restart_ctx; + +#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + +/* Now we can declare functions that take a pointer to that */ +typedef void mbedtls_x509_crt_restart_ctx; + +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * Default security profile. Should provide a good balance between security + * and compatibility with current deployments. + */ +extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default; + +/** + * Expected next default profile. Recommended for new deployments. + * Currently targets a 128-bit security level, except for RSA-2048. + */ +extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next; + +/** + * NSA Suite B profile. + */ +extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb; + +/** + * \brief Parse a single DER formatted certificate and add it + * to the end of the provided chained list. + * + * \param chain The pointer to the start of the CRT chain to attach to. + * When parsing the first CRT in a chain, this should point + * to an instance of ::mbedtls_x509_crt initialized through + * mbedtls_x509_crt_init(). + * \param buf The buffer holding the DER encoded certificate. + * \param buflen The size in Bytes of \p buf. + * + * \note This function makes an internal copy of the CRT buffer + * \p buf. In particular, \p buf may be destroyed or reused + * after this call returns. To avoid duplicating the CRT + * buffer (at the cost of stricter lifetime constraints), + * use mbedtls_x509_crt_parse_der_nocopy() instead. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain, + const unsigned char *buf, + size_t buflen ); + +/** + * \brief The type of certificate extension callbacks. + * + * Callbacks of this type are passed to and used by the + * mbedtls_x509_crt_parse_der_with_ext_cb() routine when + * it encounters either an unsupported extension or a + * "certificate policies" extension containing any + * unsupported certificate policies. + * Future versions of the library may invoke the callback + * in other cases, if and when the need arises. + * + * \param p_ctx An opaque context passed to the callback. + * \param crt The certificate being parsed. + * \param oid The OID of the extension. + * \param critical Whether the extension is critical. + * \param p Pointer to the start of the extension value + * (the content of the OCTET STRING). + * \param end End of extension value. + * + * \note The callback must fail and return a negative error code + * if it can not parse or does not support the extension. + * When the callback fails to parse a critical extension + * mbedtls_x509_crt_parse_der_with_ext_cb() also fails. + * When the callback fails to parse a non critical extension + * mbedtls_x509_crt_parse_der_with_ext_cb() simply skips + * the extension and continues parsing. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +typedef int (*mbedtls_x509_crt_ext_cb_t)( void *p_ctx, + mbedtls_x509_crt const *crt, + mbedtls_x509_buf const *oid, + int critical, + const unsigned char *p, + const unsigned char *end ); + +/** + * \brief Parse a single DER formatted certificate and add it + * to the end of the provided chained list. + * + * \param chain The pointer to the start of the CRT chain to attach to. + * When parsing the first CRT in a chain, this should point + * to an instance of ::mbedtls_x509_crt initialized through + * mbedtls_x509_crt_init(). + * \param buf The buffer holding the DER encoded certificate. + * \param buflen The size in Bytes of \p buf. + * \param make_copy When not zero this function makes an internal copy of the + * CRT buffer \p buf. In particular, \p buf may be destroyed + * or reused after this call returns. + * When zero this function avoids duplicating the CRT buffer + * by taking temporary ownership thereof until the CRT + * is destroyed (like mbedtls_x509_crt_parse_der_nocopy()) + * \param cb A callback invoked for every unsupported certificate + * extension. + * \param p_ctx An opaque context passed to the callback. + * + * \note This call is functionally equivalent to + * mbedtls_x509_crt_parse_der(), and/or + * mbedtls_x509_crt_parse_der_nocopy() + * but it calls the callback with every unsupported + * certificate extension and additionally the + * "certificate policies" extension if it contains any + * unsupported certificate policies. + * The callback must return a negative error code if it + * does not know how to handle such an extension. + * When the callback fails to parse a critical extension + * mbedtls_x509_crt_parse_der_with_ext_cb() also fails. + * When the callback fails to parse a non critical extension + * mbedtls_x509_crt_parse_der_with_ext_cb() simply skips + * the extension and continues parsing. + * Future versions of the library may invoke the callback + * in other cases, if and when the need arises. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_x509_crt_parse_der_with_ext_cb( mbedtls_x509_crt *chain, + const unsigned char *buf, + size_t buflen, + int make_copy, + mbedtls_x509_crt_ext_cb_t cb, + void *p_ctx ); + +/** + * \brief Parse a single DER formatted certificate and add it + * to the end of the provided chained list. This is a + * variant of mbedtls_x509_crt_parse_der() which takes + * temporary ownership of the CRT buffer until the CRT + * is destroyed. + * + * \param chain The pointer to the start of the CRT chain to attach to. + * When parsing the first CRT in a chain, this should point + * to an instance of ::mbedtls_x509_crt initialized through + * mbedtls_x509_crt_init(). + * \param buf The address of the readable buffer holding the DER encoded + * certificate to use. On success, this buffer must be + * retained and not be changed for the liftetime of the + * CRT chain \p chain, that is, until \p chain is destroyed + * through a call to mbedtls_x509_crt_free(). + * \param buflen The size in Bytes of \p buf. + * + * \note This call is functionally equivalent to + * mbedtls_x509_crt_parse_der(), but it avoids creating a + * copy of the input buffer at the cost of stronger lifetime + * constraints. This is useful in constrained environments + * where duplication of the CRT cannot be tolerated. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_x509_crt_parse_der_nocopy( mbedtls_x509_crt *chain, + const unsigned char *buf, + size_t buflen ); + +/** + * \brief Parse one DER-encoded or one or more concatenated PEM-encoded + * certificates and add them to the chained list. + * + * For CRTs in PEM encoding, the function parses permissively: + * if at least one certificate can be parsed, the function + * returns the number of certificates for which parsing failed + * (hence \c 0 if all certificates were parsed successfully). + * If no certificate could be parsed, the function returns + * the first (negative) error encountered during parsing. + * + * PEM encoded certificates may be interleaved by other data + * such as human readable descriptions of their content, as + * long as the certificates are enclosed in the PEM specific + * '-----{BEGIN/END} CERTIFICATE-----' delimiters. + * + * \param chain The chain to which to add the parsed certificates. + * \param buf The buffer holding the certificate data in PEM or DER format. + * For certificates in PEM encoding, this may be a concatenation + * of multiple certificates; for DER encoding, the buffer must + * comprise exactly one certificate. + * \param buflen The size of \p buf, including the terminating \c NULL byte + * in case of PEM encoded data. + * + * \return \c 0 if all certificates were parsed successfully. + * \return The (positive) number of certificates that couldn't + * be parsed if parsing was partly successful (see above). + * \return A negative X509 or PEM error code otherwise. + * + */ +int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Load one or more certificates and add them + * to the chained list. Parses permissively. If some + * certificates can be parsed, the result is the number + * of failed certificates it encountered. If none complete + * correctly, the first error is returned. + * + * \param chain points to the start of the chain + * \param path filename to read the certificates from + * + * \return 0 if all certificates parsed successfully, a positive number + * if partly successful or a specific X509 or PEM error code + */ +int mbedtls_x509_crt_parse_file( mbedtls_x509_crt *chain, const char *path ); + +/** + * \brief Load one or more certificate files from a path and add them + * to the chained list. Parses permissively. If some + * certificates can be parsed, the result is the number + * of failed certificates it encountered. If none complete + * correctly, the first error is returned. + * + * \param chain points to the start of the chain + * \param path directory / folder to read the certificate files from + * + * \return 0 if all certificates parsed successfully, a positive number + * if partly successful or a specific X509 or PEM error code + */ +int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ); + +#endif /* MBEDTLS_FS_IO */ +/** + * \brief This function parses an item in the SubjectAlternativeNames + * extension. + * + * \param san_buf The buffer holding the raw data item of the subject + * alternative name. + * \param san The target structure to populate with the parsed presentation + * of the subject alternative name encoded in \p san_raw. + * + * \note Only "dnsName" and "otherName" of type hardware_module_name + * as defined in RFC 4180 is supported. + * + * \note This function should be called on a single raw data of + * subject alternative name. For example, after successful + * certificate parsing, one must iterate on every item in the + * \p crt->subject_alt_names sequence, and pass it to + * this function. + * + * \warning The target structure contains pointers to the raw data of the + * parsed certificate, and its lifetime is restricted by the + * lifetime of the certificate. + * + * \return \c 0 on success + * \return #MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE for an unsupported + * SAN type. + * \return Another negative value for any other failure. + */ +int mbedtls_x509_parse_subject_alt_name( const mbedtls_x509_buf *san_buf, + mbedtls_x509_subject_alternative_name *san ); +/** + * \brief Returns an informational string about the + * certificate. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param prefix A line prefix + * \param crt The X509 certificate to represent + * + * \return The length of the string written (not including the + * terminated nul byte), or a negative error code. + */ +int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix, + const mbedtls_x509_crt *crt ); + +/** + * \brief Returns an informational string about the + * verification status of a certificate. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param prefix A line prefix + * \param flags Verification flags created by mbedtls_x509_crt_verify() + * + * \return The length of the string written (not including the + * terminated nul byte), or a negative error code. + */ +int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix, + uint32_t flags ); + +/** + * \brief Verify a chain of certificates. + * + * The verify callback is a user-supplied callback that + * can clear / modify / add flags for a certificate. If set, + * the verification callback is called for each + * certificate in the chain (from the trust-ca down to the + * presented crt). The parameters for the callback are: + * (void *parameter, mbedtls_x509_crt *crt, int certificate_depth, + * int *flags). With the flags representing current flags for + * that specific certificate and the certificate depth from + * the bottom (Peer cert depth = 0). + * + * All flags left after returning from the callback + * are also returned to the application. The function should + * return 0 for anything (including invalid certificates) + * other than fatal error, as a non-zero return code + * immediately aborts the verification process. For fatal + * errors, a specific error code should be used (different + * from MBEDTLS_ERR_X509_CERT_VERIFY_FAILED which should not + * be returned at this point), or MBEDTLS_ERR_X509_FATAL_ERROR + * can be used if no better code is available. + * + * \note In case verification failed, the results can be displayed + * using \c mbedtls_x509_crt_verify_info() + * + * \note Same as \c mbedtls_x509_crt_verify_with_profile() with the + * default security profile. + * + * \note It is your responsibility to provide up-to-date CRLs for + * all trusted CAs. If no CRL is provided for the CA that was + * used to sign the certificate, CRL verification is skipped + * silently, that is *without* setting any flag. + * + * \note The \c trust_ca list can contain two types of certificates: + * (1) those of trusted root CAs, so that certificates + * chaining up to those CAs will be trusted, and (2) + * self-signed end-entity certificates to be trusted (for + * specific peers you know) - in that case, the self-signed + * certificate doesn't need to have the CA bit set. + * + * \param crt The certificate chain to be verified. + * \param trust_ca The list of trusted CAs. + * \param ca_crl The list of CRLs for trusted CAs. + * \param cn The expected Common Name. This will be checked to be + * present in the certificate's subjectAltNames extension or, + * if this extension is absent, as a CN component in its + * Subject name. Currently only DNS names are supported. This + * may be \c NULL if the CN need not be verified. + * \param flags The address at which to store the result of the verification. + * If the verification couldn't be completed, the flag value is + * set to (uint32_t) -1. + * \param f_vrfy The verification callback to use. See the documentation + * of mbedtls_x509_crt_verify() for more information. + * \param p_vrfy The context to be passed to \p f_vrfy. + * + * \return \c 0 if the chain is valid with respect to the + * passed CN, CAs, CRLs and security profile. + * \return #MBEDTLS_ERR_X509_CERT_VERIFY_FAILED in case the + * certificate chain verification failed. In this case, + * \c *flags will have one or more + * \c MBEDTLS_X509_BADCERT_XXX or \c MBEDTLS_X509_BADCRL_XXX + * flags set. + * \return Another negative error code in case of a fatal error + * encountered during the verification process. + */ +int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ); + +/** + * \brief Verify a chain of certificates with respect to + * a configurable security profile. + * + * \note Same as \c mbedtls_x509_crt_verify(), but with explicit + * security profile. + * + * \note The restrictions on keys (RSA minimum size, allowed curves + * for ECDSA) apply to all certificates: trusted root, + * intermediate CAs if any, and end entity certificate. + * + * \param crt The certificate chain to be verified. + * \param trust_ca The list of trusted CAs. + * \param ca_crl The list of CRLs for trusted CAs. + * \param profile The security profile to use for the verification. + * \param cn The expected Common Name. This may be \c NULL if the + * CN need not be verified. + * \param flags The address at which to store the result of the verification. + * If the verification couldn't be completed, the flag value is + * set to (uint32_t) -1. + * \param f_vrfy The verification callback to use. See the documentation + * of mbedtls_x509_crt_verify() for more information. + * \param p_vrfy The context to be passed to \p f_vrfy. + * + * \return \c 0 if the chain is valid with respect to the + * passed CN, CAs, CRLs and security profile. + * \return #MBEDTLS_ERR_X509_CERT_VERIFY_FAILED in case the + * certificate chain verification failed. In this case, + * \c *flags will have one or more + * \c MBEDTLS_X509_BADCERT_XXX or \c MBEDTLS_X509_BADCRL_XXX + * flags set. + * \return Another negative error code in case of a fatal error + * encountered during the verification process. + */ +int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const mbedtls_x509_crt_profile *profile, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ); + +/** + * \brief Restartable version of \c mbedtls_crt_verify_with_profile() + * + * \note Performs the same job as \c mbedtls_crt_verify_with_profile() + * but can return early and restart according to the limit + * set with \c mbedtls_ecp_set_max_ops() to reduce blocking. + * + * \param crt The certificate chain to be verified. + * \param trust_ca The list of trusted CAs. + * \param ca_crl The list of CRLs for trusted CAs. + * \param profile The security profile to use for the verification. + * \param cn The expected Common Name. This may be \c NULL if the + * CN need not be verified. + * \param flags The address at which to store the result of the verification. + * If the verification couldn't be completed, the flag value is + * set to (uint32_t) -1. + * \param f_vrfy The verification callback to use. See the documentation + * of mbedtls_x509_crt_verify() for more information. + * \param p_vrfy The context to be passed to \p f_vrfy. + * \param rs_ctx The restart context to use. This may be set to \c NULL + * to disable restartable ECC. + * + * \return See \c mbedtls_crt_verify_with_profile(), or + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + */ +int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const mbedtls_x509_crt_profile *profile, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy, + mbedtls_x509_crt_restart_ctx *rs_ctx ); + +/** + * \brief The type of trusted certificate callbacks. + * + * Callbacks of this type are passed to and used by the CRT + * verification routine mbedtls_x509_crt_verify_with_ca_cb() + * when looking for trusted signers of a given certificate. + * + * On success, the callback returns a list of trusted + * certificates to be considered as potential signers + * for the input certificate. + * + * \param p_ctx An opaque context passed to the callback. + * \param child The certificate for which to search a potential signer. + * This will point to a readable certificate. + * \param candidate_cas The address at which to store the address of the first + * entry in the generated linked list of candidate signers. + * This will not be \c NULL. + * + * \note The callback must only return a non-zero value on a + * fatal error. If, in contrast, the search for a potential + * signer completes without a single candidate, the + * callback must return \c 0 and set \c *candidate_cas + * to \c NULL. + * + * \return \c 0 on success. In this case, \c *candidate_cas points + * to a heap-allocated linked list of instances of + * ::mbedtls_x509_crt, and ownership of this list is passed + * to the caller. + * \return A negative error code on failure. + */ +typedef int (*mbedtls_x509_crt_ca_cb_t)( void *p_ctx, + mbedtls_x509_crt const *child, + mbedtls_x509_crt **candidate_cas ); + +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) +/** + * \brief Version of \c mbedtls_x509_crt_verify_with_profile() which + * uses a callback to acquire the list of trusted CA + * certificates. + * + * \param crt The certificate chain to be verified. + * \param f_ca_cb The callback to be used to query for potential signers + * of a given child certificate. See the documentation of + * ::mbedtls_x509_crt_ca_cb_t for more information. + * \param p_ca_cb The opaque context to be passed to \p f_ca_cb. + * \param profile The security profile for the verification. + * \param cn The expected Common Name. This may be \c NULL if the + * CN need not be verified. + * \param flags The address at which to store the result of the verification. + * If the verification couldn't be completed, the flag value is + * set to (uint32_t) -1. + * \param f_vrfy The verification callback to use. See the documentation + * of mbedtls_x509_crt_verify() for more information. + * \param p_vrfy The context to be passed to \p f_vrfy. + * + * \return See \c mbedtls_crt_verify_with_profile(). + */ +int mbedtls_x509_crt_verify_with_ca_cb( mbedtls_x509_crt *crt, + mbedtls_x509_crt_ca_cb_t f_ca_cb, + void *p_ca_cb, + const mbedtls_x509_crt_profile *profile, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ); + +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ + +#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) +/** + * \brief Check usage of certificate against keyUsage extension. + * + * \param crt Leaf certificate used. + * \param usage Intended usage(s) (eg MBEDTLS_X509_KU_KEY_ENCIPHERMENT + * before using the certificate to perform an RSA key + * exchange). + * + * \note Except for decipherOnly and encipherOnly, a bit set in the + * usage argument means this bit MUST be set in the + * certificate. For decipherOnly and encipherOnly, it means + * that bit MAY be set. + * + * \return 0 is these uses of the certificate are allowed, + * MBEDTLS_ERR_X509_BAD_INPUT_DATA if the keyUsage extension + * is present but does not match the usage argument. + * + * \note You should only call this function on leaf certificates, on + * (intermediate) CAs the keyUsage extension is automatically + * checked by \c mbedtls_x509_crt_verify(). + */ +int mbedtls_x509_crt_check_key_usage( const mbedtls_x509_crt *crt, + unsigned int usage ); +#endif /* MBEDTLS_X509_CHECK_KEY_USAGE) */ + +#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) +/** + * \brief Check usage of certificate against extendedKeyUsage. + * + * \param crt Leaf certificate used. + * \param usage_oid Intended usage (eg MBEDTLS_OID_SERVER_AUTH or + * MBEDTLS_OID_CLIENT_AUTH). + * \param usage_len Length of usage_oid (eg given by MBEDTLS_OID_SIZE()). + * + * \return 0 if this use of the certificate is allowed, + * MBEDTLS_ERR_X509_BAD_INPUT_DATA if not. + * + * \note Usually only makes sense on leaf certificates. + */ +int mbedtls_x509_crt_check_extended_key_usage( const mbedtls_x509_crt *crt, + const char *usage_oid, + size_t usage_len ); +#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */ + +#if defined(MBEDTLS_X509_CRL_PARSE_C) +/** + * \brief Verify the certificate revocation status + * + * \param crt a certificate to be verified + * \param crl the CRL to verify against + * + * \return 1 if the certificate is revoked, 0 otherwise + * + */ +int mbedtls_x509_crt_is_revoked( const mbedtls_x509_crt *crt, const mbedtls_x509_crl *crl ); +#endif /* MBEDTLS_X509_CRL_PARSE_C */ + +/** + * \brief Initialize a certificate (chain) + * + * \param crt Certificate chain to initialize + */ +void mbedtls_x509_crt_init( mbedtls_x509_crt *crt ); + +/** + * \brief Unallocate all certificate data + * + * \param crt Certificate chain to free + */ +void mbedtls_x509_crt_free( mbedtls_x509_crt *crt ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Initialize a restart context + */ +void mbedtls_x509_crt_restart_init( mbedtls_x509_crt_restart_ctx *ctx ); + +/** + * \brief Free the components of a restart context + */ +void mbedtls_x509_crt_restart_free( mbedtls_x509_crt_restart_ctx *ctx ); +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +/* \} name */ +/* \} addtogroup x509_module */ + +#if defined(MBEDTLS_X509_CRT_WRITE_C) +/** + * \brief Initialize a CRT writing context + * + * \param ctx CRT context to initialize + */ +void mbedtls_x509write_crt_init( mbedtls_x509write_cert *ctx ); + +/** + * \brief Set the verion for a Certificate + * Default: MBEDTLS_X509_CRT_VERSION_3 + * + * \param ctx CRT context to use + * \param version version to set (MBEDTLS_X509_CRT_VERSION_1, MBEDTLS_X509_CRT_VERSION_2 or + * MBEDTLS_X509_CRT_VERSION_3) + */ +void mbedtls_x509write_crt_set_version( mbedtls_x509write_cert *ctx, int version ); + +/** + * \brief Set the serial number for a Certificate. + * + * \param ctx CRT context to use + * \param serial serial number to set + * + * \return 0 if successful + */ +int mbedtls_x509write_crt_set_serial( mbedtls_x509write_cert *ctx, const mbedtls_mpi *serial ); + +/** + * \brief Set the validity period for a Certificate + * Timestamps should be in string format for UTC timezone + * i.e. "YYYYMMDDhhmmss" + * e.g. "20131231235959" for December 31st 2013 + * at 23:59:59 + * + * \param ctx CRT context to use + * \param not_before not_before timestamp + * \param not_after not_after timestamp + * + * \return 0 if timestamp was parsed successfully, or + * a specific error code + */ +int mbedtls_x509write_crt_set_validity( mbedtls_x509write_cert *ctx, const char *not_before, + const char *not_after ); + +/** + * \brief Set the issuer name for a Certificate + * Issuer names should contain a comma-separated list + * of OID types and values: + * e.g. "C=UK,O=ARM,CN=mbed TLS CA" + * + * \param ctx CRT context to use + * \param issuer_name issuer name to set + * + * \return 0 if issuer name was parsed successfully, or + * a specific error code + */ +int mbedtls_x509write_crt_set_issuer_name( mbedtls_x509write_cert *ctx, + const char *issuer_name ); + +/** + * \brief Set the subject name for a Certificate + * Subject names should contain a comma-separated list + * of OID types and values: + * e.g. "C=UK,O=ARM,CN=mbed TLS Server 1" + * + * \param ctx CRT context to use + * \param subject_name subject name to set + * + * \return 0 if subject name was parsed successfully, or + * a specific error code + */ +int mbedtls_x509write_crt_set_subject_name( mbedtls_x509write_cert *ctx, + const char *subject_name ); + +/** + * \brief Set the subject public key for the certificate + * + * \param ctx CRT context to use + * \param key public key to include + */ +void mbedtls_x509write_crt_set_subject_key( mbedtls_x509write_cert *ctx, mbedtls_pk_context *key ); + +/** + * \brief Set the issuer key used for signing the certificate + * + * \param ctx CRT context to use + * \param key private key to sign with + */ +void mbedtls_x509write_crt_set_issuer_key( mbedtls_x509write_cert *ctx, mbedtls_pk_context *key ); + +/** + * \brief Set the MD algorithm to use for the signature + * (e.g. MBEDTLS_MD_SHA1) + * + * \param ctx CRT context to use + * \param md_alg MD algorithm to use + */ +void mbedtls_x509write_crt_set_md_alg( mbedtls_x509write_cert *ctx, mbedtls_md_type_t md_alg ); + +/** + * \brief Generic function to add to or replace an extension in the + * CRT + * + * \param ctx CRT context to use + * \param oid OID of the extension + * \param oid_len length of the OID + * \param critical if the extension is critical (per the RFC's definition) + * \param val value of the extension OCTET STRING + * \param val_len length of the value data + * + * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_crt_set_extension( mbedtls_x509write_cert *ctx, + const char *oid, size_t oid_len, + int critical, + const unsigned char *val, size_t val_len ); + +/** + * \brief Set the basicConstraints extension for a CRT + * + * \param ctx CRT context to use + * \param is_ca is this a CA certificate + * \param max_pathlen maximum length of certificate chains below this + * certificate (only for CA certificates, -1 is + * inlimited) + * + * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_crt_set_basic_constraints( mbedtls_x509write_cert *ctx, + int is_ca, int max_pathlen ); + +#if defined(MBEDTLS_SHA1_C) +/** + * \brief Set the subjectKeyIdentifier extension for a CRT + * Requires that mbedtls_x509write_crt_set_subject_key() has been + * called before + * + * \param ctx CRT context to use + * + * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_crt_set_subject_key_identifier( mbedtls_x509write_cert *ctx ); + +/** + * \brief Set the authorityKeyIdentifier extension for a CRT + * Requires that mbedtls_x509write_crt_set_issuer_key() has been + * called before + * + * \param ctx CRT context to use + * + * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_crt_set_authority_key_identifier( mbedtls_x509write_cert *ctx ); +#endif /* MBEDTLS_SHA1_C */ + +/** + * \brief Set the Key Usage Extension flags + * (e.g. MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_KEY_CERT_SIGN) + * + * \param ctx CRT context to use + * \param key_usage key usage flags to set + * + * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_crt_set_key_usage( mbedtls_x509write_cert *ctx, + unsigned int key_usage ); + +/** + * \brief Set the Netscape Cert Type flags + * (e.g. MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT | MBEDTLS_X509_NS_CERT_TYPE_EMAIL) + * + * \param ctx CRT context to use + * \param ns_cert_type Netscape Cert Type flags to set + * + * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_crt_set_ns_cert_type( mbedtls_x509write_cert *ctx, + unsigned char ns_cert_type ); + +/** + * \brief Free the contents of a CRT write context + * + * \param ctx CRT context to free + */ +void mbedtls_x509write_crt_free( mbedtls_x509write_cert *ctx ); + +/** + * \brief Write a built up certificate to a X509 DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param ctx certificate to write away + * \param buf buffer to write to + * \param size size of the buffer + * \param f_rng RNG function (for signature, see note) + * \param p_rng RNG parameter + * + * \return length of data written if successful, or a specific + * error code + * + * \note f_rng may be NULL if RSA is used for signature and the + * signature is made offline (otherwise f_rng is desirable + * for countermeasures against timing attacks). + * ECDSA signatures always require a non-NULL f_rng. + */ +int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +#if defined(MBEDTLS_PEM_WRITE_C) +/** + * \brief Write a built up certificate to a X509 PEM string + * + * \param ctx certificate to write away + * \param buf buffer to write to + * \param size size of the buffer + * \param f_rng RNG function (for signature, see note) + * \param p_rng RNG parameter + * + * \return 0 if successful, or a specific error code + * + * \note f_rng may be NULL if RSA is used for signature and the + * signature is made offline (otherwise f_rng is desirable + * for countermeasures against timing attacks). + * ECDSA signatures always require a non-NULL f_rng. + */ +int mbedtls_x509write_crt_pem( mbedtls_x509write_cert *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +#endif /* MBEDTLS_PEM_WRITE_C */ +#endif /* MBEDTLS_X509_CRT_WRITE_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_x509_crt.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/x509_csr.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/x509_csr.h new file mode 100644 index 0000000..b1dfc21 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/x509_csr.h @@ -0,0 +1,305 @@ +/** + * \file x509_csr.h + * + * \brief X.509 certificate signing request parsing and writing + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_X509_CSR_H +#define MBEDTLS_X509_CSR_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/x509.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup x509_module + * \{ */ + +/** + * \name Structures and functions for X.509 Certificate Signing Requests (CSR) + * \{ + */ + +/** + * Certificate Signing Request (CSR) structure. + */ +typedef struct mbedtls_x509_csr +{ + mbedtls_x509_buf raw; /**< The raw CSR data (DER). */ + mbedtls_x509_buf cri; /**< The raw CertificateRequestInfo body (DER). */ + + int version; /**< CSR version (1=v1). */ + + mbedtls_x509_buf subject_raw; /**< The raw subject data (DER). */ + mbedtls_x509_name subject; /**< The parsed subject data (named information object). */ + + mbedtls_pk_context pk; /**< Container for the public key context. */ + + mbedtls_x509_buf sig_oid; + mbedtls_x509_buf sig; + mbedtls_md_type_t sig_md; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ + mbedtls_pk_type_t sig_pk; /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ + void *sig_opts; /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ +} +mbedtls_x509_csr; + +/** + * Container for writing a CSR + */ +typedef struct mbedtls_x509write_csr +{ + mbedtls_pk_context *key; + mbedtls_asn1_named_data *subject; + mbedtls_md_type_t md_alg; + mbedtls_asn1_named_data *extensions; +} +mbedtls_x509write_csr; + +#if defined(MBEDTLS_X509_CSR_PARSE_C) +/** + * \brief Load a Certificate Signing Request (CSR) in DER format + * + * \note CSR attributes (if any) are currently silently ignored. + * + * \param csr CSR context to fill + * \param buf buffer holding the CRL data + * \param buflen size of the buffer + * + * \return 0 if successful, or a specific X509 error code + */ +int mbedtls_x509_csr_parse_der( mbedtls_x509_csr *csr, + const unsigned char *buf, size_t buflen ); + +/** + * \brief Load a Certificate Signing Request (CSR), DER or PEM format + * + * \note See notes for \c mbedtls_x509_csr_parse_der() + * + * \param csr CSR context to fill + * \param buf buffer holding the CRL data + * \param buflen size of the buffer + * (including the terminating null byte for PEM data) + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int mbedtls_x509_csr_parse( mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Load a Certificate Signing Request (CSR) + * + * \note See notes for \c mbedtls_x509_csr_parse() + * + * \param csr CSR context to fill + * \param path filename to read the CSR from + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int mbedtls_x509_csr_parse_file( mbedtls_x509_csr *csr, const char *path ); +#endif /* MBEDTLS_FS_IO */ + +/** + * \brief Returns an informational string about the + * CSR. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param prefix A line prefix + * \param csr The X509 CSR to represent + * + * \return The length of the string written (not including the + * terminated nul byte), or a negative error code. + */ +int mbedtls_x509_csr_info( char *buf, size_t size, const char *prefix, + const mbedtls_x509_csr *csr ); + +/** + * \brief Initialize a CSR + * + * \param csr CSR to initialize + */ +void mbedtls_x509_csr_init( mbedtls_x509_csr *csr ); + +/** + * \brief Unallocate all CSR data + * + * \param csr CSR to free + */ +void mbedtls_x509_csr_free( mbedtls_x509_csr *csr ); +#endif /* MBEDTLS_X509_CSR_PARSE_C */ + +/* \} name */ +/* \} addtogroup x509_module */ + +#if defined(MBEDTLS_X509_CSR_WRITE_C) +/** + * \brief Initialize a CSR context + * + * \param ctx CSR context to initialize + */ +void mbedtls_x509write_csr_init( mbedtls_x509write_csr *ctx ); + +/** + * \brief Set the subject name for a CSR + * Subject names should contain a comma-separated list + * of OID types and values: + * e.g. "C=UK,O=ARM,CN=mbed TLS Server 1" + * + * \param ctx CSR context to use + * \param subject_name subject name to set + * + * \return 0 if subject name was parsed successfully, or + * a specific error code + */ +int mbedtls_x509write_csr_set_subject_name( mbedtls_x509write_csr *ctx, + const char *subject_name ); + +/** + * \brief Set the key for a CSR (public key will be included, + * private key used to sign the CSR when writing it) + * + * \param ctx CSR context to use + * \param key Asymetric key to include + */ +void mbedtls_x509write_csr_set_key( mbedtls_x509write_csr *ctx, mbedtls_pk_context *key ); + +/** + * \brief Set the MD algorithm to use for the signature + * (e.g. MBEDTLS_MD_SHA1) + * + * \param ctx CSR context to use + * \param md_alg MD algorithm to use + */ +void mbedtls_x509write_csr_set_md_alg( mbedtls_x509write_csr *ctx, mbedtls_md_type_t md_alg ); + +/** + * \brief Set the Key Usage Extension flags + * (e.g. MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_KEY_CERT_SIGN) + * + * \param ctx CSR context to use + * \param key_usage key usage flags to set + * + * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED + * + * \note The decipherOnly flag from the Key Usage + * extension is represented by bit 8 (i.e. + * 0x8000), which cannot typically be represented + * in an unsigned char. Therefore, the flag + * decipherOnly (i.e. + * #MBEDTLS_X509_KU_DECIPHER_ONLY) cannot be set using this + * function. + */ +int mbedtls_x509write_csr_set_key_usage( mbedtls_x509write_csr *ctx, unsigned char key_usage ); + +/** + * \brief Set the Netscape Cert Type flags + * (e.g. MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT | MBEDTLS_X509_NS_CERT_TYPE_EMAIL) + * + * \param ctx CSR context to use + * \param ns_cert_type Netscape Cert Type flags to set + * + * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_csr_set_ns_cert_type( mbedtls_x509write_csr *ctx, + unsigned char ns_cert_type ); + +/** + * \brief Generic function to add to or replace an extension in the + * CSR + * + * \param ctx CSR context to use + * \param oid OID of the extension + * \param oid_len length of the OID + * \param val value of the extension OCTET STRING + * \param val_len length of the value data + * + * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_csr_set_extension( mbedtls_x509write_csr *ctx, + const char *oid, size_t oid_len, + const unsigned char *val, size_t val_len ); + +/** + * \brief Free the contents of a CSR context + * + * \param ctx CSR context to free + */ +void mbedtls_x509write_csr_free( mbedtls_x509write_csr *ctx ); + +/** + * \brief Write a CSR (Certificate Signing Request) to a + * DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param ctx CSR to write away + * \param buf buffer to write to + * \param size size of the buffer + * \param f_rng RNG function (for signature, see note) + * \param p_rng RNG parameter + * + * \return length of data written if successful, or a specific + * error code + * + * \note f_rng may be NULL if RSA is used for signature and the + * signature is made offline (otherwise f_rng is desirable + * for countermeasures against timing attacks). + * ECDSA signatures always require a non-NULL f_rng. + */ +int mbedtls_x509write_csr_der( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +#if defined(MBEDTLS_PEM_WRITE_C) +/** + * \brief Write a CSR (Certificate Signing Request) to a + * PEM string + * + * \param ctx CSR to write away + * \param buf buffer to write to + * \param size size of the buffer + * \param f_rng RNG function (for signature, see note) + * \param p_rng RNG parameter + * + * \return 0 if successful, or a specific error code + * + * \note f_rng may be NULL if RSA is used for signature and the + * signature is made offline (otherwise f_rng is desirable + * for countermeasures against timing attacks). + * ECDSA signatures always require a non-NULL f_rng. + */ +int mbedtls_x509write_csr_pem( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +#endif /* MBEDTLS_PEM_WRITE_C */ +#endif /* MBEDTLS_X509_CSR_WRITE_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_x509_csr.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/xtea.h b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/xtea.h new file mode 100644 index 0000000..473dd4b --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/mbedtls/xtea.h @@ -0,0 +1,137 @@ +/** + * \file xtea.h + * + * \brief XTEA block cipher (32-bit) + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_XTEA_H +#define MBEDTLS_XTEA_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#define MBEDTLS_XTEA_ENCRYPT 1 +#define MBEDTLS_XTEA_DECRYPT 0 + +#define MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH -0x0028 /**< The data input has an invalid length. */ + +/* MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED -0x0029 /**< XTEA hardware accelerator failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_XTEA_ALT) +// Regular implementation +// + +/** + * \brief XTEA context structure + */ +typedef struct mbedtls_xtea_context +{ + uint32_t k[4]; /*!< key */ +} +mbedtls_xtea_context; + +#else /* MBEDTLS_XTEA_ALT */ +#include "xtea_alt.h" +#endif /* MBEDTLS_XTEA_ALT */ + +/** + * \brief Initialize XTEA context + * + * \param ctx XTEA context to be initialized + */ +void mbedtls_xtea_init( mbedtls_xtea_context *ctx ); + +/** + * \brief Clear XTEA context + * + * \param ctx XTEA context to be cleared + */ +void mbedtls_xtea_free( mbedtls_xtea_context *ctx ); + +/** + * \brief XTEA key schedule + * + * \param ctx XTEA context to be initialized + * \param key the secret key + */ +void mbedtls_xtea_setup( mbedtls_xtea_context *ctx, const unsigned char key[16] ); + +/** + * \brief XTEA cipher function + * + * \param ctx XTEA context + * \param mode MBEDTLS_XTEA_ENCRYPT or MBEDTLS_XTEA_DECRYPT + * \param input 8-byte input block + * \param output 8-byte output block + * + * \return 0 if successful + */ +int mbedtls_xtea_crypt_ecb( mbedtls_xtea_context *ctx, + int mode, + const unsigned char input[8], + unsigned char output[8] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief XTEA CBC cipher function + * + * \param ctx XTEA context + * \param mode MBEDTLS_XTEA_ENCRYPT or MBEDTLS_XTEA_DECRYPT + * \param length the length of input, multiple of 8 + * \param iv initialization vector for CBC mode + * \param input input block + * \param output output block + * + * \return 0 if successful, + * MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH if the length % 8 != 0 + */ +int mbedtls_xtea_crypt_cbc( mbedtls_xtea_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_xtea_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* xtea.h */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/psa/crypto.h b/Android/Level4/app/src/main/c/mbedtls/include/psa/crypto.h new file mode 100644 index 0000000..5ba16b9 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/psa/crypto.h @@ -0,0 +1,3782 @@ +/** + * \file psa/crypto.h + * \brief Platform Security Architecture cryptography module + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 PSA_CRYPTO_H +#define PSA_CRYPTO_H + +#include "crypto_platform.h" + +#include + +#ifdef __DOXYGEN_ONLY__ +/* This __DOXYGEN_ONLY__ block contains mock definitions for things that + * must be defined in the crypto_platform.h header. These mock definitions + * are present in this file as a convenience to generate pretty-printed + * documentation that includes those definitions. */ + +/** \defgroup platform Implementation-specific definitions + * @{ + */ + +/** \brief Key handle. + * + * This type represents open handles to keys. It must be an unsigned integral + * type. The choice of type is implementation-dependent. + * + * 0 is not a valid key handle. How other handle values are assigned is + * implementation-dependent. + */ +typedef _unsigned_integral_type_ psa_key_handle_t; + +/**@}*/ +#endif /* __DOXYGEN_ONLY__ */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* The file "crypto_types.h" declares types that encode errors, + * algorithms, key types, policies, etc. */ +#include "crypto_types.h" + +/** \defgroup version API version + * @{ + */ + +/** + * The major version of this implementation of the PSA Crypto API + */ +#define PSA_CRYPTO_API_VERSION_MAJOR 1 + +/** + * The minor version of this implementation of the PSA Crypto API + */ +#define PSA_CRYPTO_API_VERSION_MINOR 0 + +/**@}*/ + +/* The file "crypto_values.h" declares macros to build and analyze values + * of integral types defined in "crypto_types.h". */ +#include "crypto_values.h" + +/** \defgroup initialization Library initialization + * @{ + */ + +/** + * \brief Library initialization. + * + * Applications must call this function before calling any other + * function in this module. + * + * Applications may call this function more than once. Once a call + * succeeds, subsequent calls are guaranteed to succeed. + * + * If the application calls other functions before calling psa_crypto_init(), + * the behavior is undefined. Implementations are encouraged to either perform + * the operation as if the library had been initialized or to return + * #PSA_ERROR_BAD_STATE or some other applicable error. In particular, + * implementations should not return a success status if the lack of + * initialization may have security implications, for example due to improper + * seeding of the random number generator. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY + */ +psa_status_t psa_crypto_init(void); + +/**@}*/ + +/** \addtogroup attributes + * @{ + */ + +/** \def PSA_KEY_ATTRIBUTES_INIT + * + * This macro returns a suitable initializer for a key attribute structure + * of type #psa_key_attributes_t. + */ +#ifdef __DOXYGEN_ONLY__ +/* This is an example definition for documentation purposes. + * Implementations should define a suitable value in `crypto_struct.h`. + */ +#define PSA_KEY_ATTRIBUTES_INIT {0} +#endif + +/** Return an initial value for a key attributes structure. + */ +static psa_key_attributes_t psa_key_attributes_init(void); + +/** Declare a key as persistent and set its key identifier. + * + * If the attribute structure currently declares the key as volatile (which + * is the default content of an attribute structure), this function sets + * the lifetime attribute to #PSA_KEY_LIFETIME_PERSISTENT. + * + * This function does not access storage, it merely stores the given + * value in the structure. + * The persistent key will be written to storage when the attribute + * structure is passed to a key creation function such as + * psa_import_key(), psa_generate_key(), + * psa_key_derivation_output_key() or psa_copy_key(). + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] attributes The attribute structure to write to. + * \param key The persistent identifier for the key. + */ +static void psa_set_key_id( psa_key_attributes_t *attributes, + mbedtls_svc_key_id_t key ); + +/** Set the location of a persistent key. + * + * To make a key persistent, you must give it a persistent key identifier + * with psa_set_key_id(). By default, a key that has a persistent identifier + * is stored in the default storage area identifier by + * #PSA_KEY_LIFETIME_PERSISTENT. Call this function to choose a storage + * area, or to explicitly declare the key as volatile. + * + * This function does not access storage, it merely stores the given + * value in the structure. + * The persistent key will be written to storage when the attribute + * structure is passed to a key creation function such as + * psa_import_key(), psa_generate_key(), + * psa_key_derivation_output_key() or psa_copy_key(). + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] attributes The attribute structure to write to. + * \param lifetime The lifetime for the key. + * If this is #PSA_KEY_LIFETIME_VOLATILE, the + * key will be volatile, and the key identifier + * attribute is reset to 0. + */ +static void psa_set_key_lifetime(psa_key_attributes_t *attributes, + psa_key_lifetime_t lifetime); + +/** Retrieve the key identifier from key attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The persistent identifier stored in the attribute structure. + * This value is unspecified if the attribute structure declares + * the key as volatile. + */ +static mbedtls_svc_key_id_t psa_get_key_id( + const psa_key_attributes_t *attributes); + +/** Retrieve the lifetime from key attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The lifetime value stored in the attribute structure. + */ +static psa_key_lifetime_t psa_get_key_lifetime( + const psa_key_attributes_t *attributes); + +/** Declare usage flags for a key. + * + * Usage flags are part of a key's usage policy. They encode what + * kind of operations are permitted on the key. For more details, + * refer to the documentation of the type #psa_key_usage_t. + * + * This function overwrites any usage flags + * previously set in \p attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] attributes The attribute structure to write to. + * \param usage_flags The usage flags to write. + */ +static void psa_set_key_usage_flags(psa_key_attributes_t *attributes, + psa_key_usage_t usage_flags); + +/** Retrieve the usage flags from key attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The usage flags stored in the attribute structure. + */ +static psa_key_usage_t psa_get_key_usage_flags( + const psa_key_attributes_t *attributes); + +/** Declare the permitted algorithm policy for a key. + * + * The permitted algorithm policy of a key encodes which algorithm or + * algorithms are permitted to be used with this key. The following + * algorithm policies are supported: + * - 0 does not allow any cryptographic operation with the key. The key + * may be used for non-cryptographic actions such as exporting (if + * permitted by the usage flags). + * - An algorithm value permits this particular algorithm. + * - An algorithm wildcard built from #PSA_ALG_ANY_HASH allows the specified + * signature scheme with any hash algorithm. + * + * This function overwrites any algorithm policy + * previously set in \p attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] attributes The attribute structure to write to. + * \param alg The permitted algorithm policy to write. + */ +static void psa_set_key_algorithm(psa_key_attributes_t *attributes, + psa_algorithm_t alg); + + +/** Retrieve the algorithm policy from key attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The algorithm stored in the attribute structure. + */ +static psa_algorithm_t psa_get_key_algorithm( + const psa_key_attributes_t *attributes); + +/** Declare the type of a key. + * + * This function overwrites any key type + * previously set in \p attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] attributes The attribute structure to write to. + * \param type The key type to write. + * If this is 0, the key type in \p attributes + * becomes unspecified. + */ +static void psa_set_key_type(psa_key_attributes_t *attributes, + psa_key_type_t type); + + +/** Declare the size of a key. + * + * This function overwrites any key size previously set in \p attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] attributes The attribute structure to write to. + * \param bits The key size in bits. + * If this is 0, the key size in \p attributes + * becomes unspecified. Keys of size 0 are + * not supported. + */ +static void psa_set_key_bits(psa_key_attributes_t *attributes, + size_t bits); + +/** Retrieve the key type from key attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The key type stored in the attribute structure. + */ +static psa_key_type_t psa_get_key_type(const psa_key_attributes_t *attributes); + +/** Retrieve the key size from key attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The key size stored in the attribute structure, in bits. + */ +static size_t psa_get_key_bits(const psa_key_attributes_t *attributes); + +/** Retrieve the attributes of a key. + * + * This function first resets the attribute structure as with + * psa_reset_key_attributes(). It then copies the attributes of + * the given key into the given attribute structure. + * + * \note This function may allocate memory or other resources. + * Once you have called this function on an attribute structure, + * you must call psa_reset_key_attributes() to free these resources. + * + * \param[in] handle Handle to the key to query. + * \param[in,out] attributes On success, the attributes of the key. + * On failure, equivalent to a + * freshly-initialized structure. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_get_key_attributes(psa_key_handle_t handle, + psa_key_attributes_t *attributes); + +/** Reset a key attribute structure to a freshly initialized state. + * + * You must initialize the attribute structure as described in the + * documentation of the type #psa_key_attributes_t before calling this + * function. Once the structure has been initialized, you may call this + * function at any time. + * + * This function frees any auxiliary resources that the structure + * may contain. + * + * \param[in,out] attributes The attribute structure to reset. + */ +void psa_reset_key_attributes(psa_key_attributes_t *attributes); + +/**@}*/ + +/** \defgroup key_management Key management + * @{ + */ + +/** Open a handle to an existing persistent key. + * + * Open a handle to a persistent key. A key is persistent if it was created + * with a lifetime other than #PSA_KEY_LIFETIME_VOLATILE. A persistent key + * always has a nonzero key identifier, set with psa_set_key_id() when + * creating the key. Implementations may provide additional pre-provisioned + * keys that can be opened with psa_open_key(). Such keys have an application + * key identifier in the vendor range, as documented in the description of + * #psa_key_id_t. + * + * The application must eventually close the handle with psa_close_key() or + * psa_destroy_key() to release associated resources. If the application dies + * without calling one of these functions, the implementation should perform + * the equivalent of a call to psa_close_key(). + * + * Some implementations permit an application to open the same key multiple + * times. If this is successful, each call to psa_open_key() will return a + * different key handle. + * + * \note Applications that rely on opening a key multiple times will not be + * portable to implementations that only permit a single key handle to be + * opened. See also :ref:\`key-handles\`. + * + * \param key The persistent identifier of the key. + * \param[out] handle On success, a handle to the key. + * + * \retval #PSA_SUCCESS + * Success. The application can now use the value of `*handle` + * to access the key. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * The implementation does not have sufficient resources to open the + * key. This can be due to reaching an implementation limit on the + * number of open keys, the number of open key handles, or available + * memory. + * \retval #PSA_ERROR_DOES_NOT_EXIST + * There is no persistent key with key identifier \p id. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p id is not a valid persistent key identifier. + * \retval #PSA_ERROR_NOT_PERMITTED + * The specified key exists, but the application does not have the + * permission to access it. Note that this specification does not + * define any way to create such a key, but it may be possible + * through implementation-specific means. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_open_key( mbedtls_svc_key_id_t key, + psa_key_handle_t *handle ); + +/** Close a key handle. + * + * If the handle designates a volatile key, this will destroy the key material + * and free all associated resources, just like psa_destroy_key(). + * + * If this is the last open handle to a persistent key, then closing the handle + * will free all resources associated with the key in volatile memory. The key + * data in persistent storage is not affected and can be opened again later + * with a call to psa_open_key(). + * + * Closing the key handle makes the handle invalid, and the key handle + * must not be used again by the application. + * + * \note If the key handle was used to set up an active + * :ref:\`multipart operation \`, then closing the + * key handle can cause the multipart operation to fail. Applications should + * maintain the key handle until after the multipart operation has finished. + * + * \param handle The key handle to close. + * If this is \c 0, do nothing and return \c PSA_SUCCESS. + * + * \retval #PSA_SUCCESS + * \p handle was a valid handle or \c 0. It is now closed. + * \retval #PSA_ERROR_INVALID_HANDLE + * \p handle is not a valid handle nor \c 0. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_close_key(psa_key_handle_t handle); + +/** Make a copy of a key. + * + * Copy key material from one location to another. + * + * This function is primarily useful to copy a key from one location + * to another, since it populates a key using the material from + * another key which may have a different lifetime. + * + * This function may be used to share a key with a different party, + * subject to implementation-defined restrictions on key sharing. + * + * The policy on the source key must have the usage flag + * #PSA_KEY_USAGE_COPY set. + * This flag is sufficient to permit the copy if the key has the lifetime + * #PSA_KEY_LIFETIME_VOLATILE or #PSA_KEY_LIFETIME_PERSISTENT. + * Some secure elements do not provide a way to copy a key without + * making it extractable from the secure element. If a key is located + * in such a secure element, then the key must have both usage flags + * #PSA_KEY_USAGE_COPY and #PSA_KEY_USAGE_EXPORT in order to make + * a copy of the key outside the secure element. + * + * The resulting key may only be used in a way that conforms to + * both the policy of the original key and the policy specified in + * the \p attributes parameter: + * - The usage flags on the resulting key are the bitwise-and of the + * usage flags on the source policy and the usage flags in \p attributes. + * - If both allow the same algorithm or wildcard-based + * algorithm policy, the resulting key has the same algorithm policy. + * - If either of the policies allows an algorithm and the other policy + * allows a wildcard-based algorithm policy that includes this algorithm, + * the resulting key allows the same algorithm. + * - If the policies do not allow any algorithm in common, this function + * fails with the status #PSA_ERROR_INVALID_ARGUMENT. + * + * The effect of this function on implementation-defined attributes is + * implementation-defined. + * + * \param source_handle The key to copy. It must be a valid key handle. + * \param[in] attributes The attributes for the new key. + * They are used as follows: + * - The key type and size may be 0. If either is + * nonzero, it must match the corresponding + * attribute of the source key. + * - The key location (the lifetime and, for + * persistent keys, the key identifier) is + * used directly. + * - The policy constraints (usage flags and + * algorithm policy) are combined from + * the source key and \p attributes so that + * both sets of restrictions apply, as + * described in the documentation of this function. + * \param[out] target_handle On success, a handle to the newly created key. + * \c 0 on failure. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \p source_handle is invalid. + * \retval #PSA_ERROR_ALREADY_EXISTS + * This is an attempt to create a persistent key, and there is + * already a persistent key with the given identifier. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The lifetime or identifier in \p attributes are invalid. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The policy constraints on the source and specified in + * \p attributes are incompatible. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p attributes specifies a key type or key size + * which does not match the attributes of the source key. + * \retval #PSA_ERROR_NOT_PERMITTED + * The source key does not have the #PSA_KEY_USAGE_COPY usage flag. + * \retval #PSA_ERROR_NOT_PERMITTED + * The source key is not exportable and its lifetime does not + * allow copying it to the target's lifetime. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_copy_key(psa_key_handle_t source_handle, + const psa_key_attributes_t *attributes, + psa_key_handle_t *target_handle); + + +/** + * \brief Destroy a key. + * + * This function destroys a key from both volatile + * memory and, if applicable, non-volatile storage. Implementations shall + * make a best effort to ensure that that the key material cannot be recovered. + * + * This function also erases any metadata such as policies and frees + * resources associated with the key. To free all resources associated with + * the key, all handles to the key must be closed or destroyed. + * + * Destroying the key makes the handle invalid, and the key handle + * must not be used again by the application. Using other open handles to the + * destroyed key in a cryptographic operation will result in an error. + * + * If a key is currently in use in a multipart operation, then destroying the + * key will cause the multipart operation to fail. + * + * \param handle Handle to the key to erase. + * If this is \c 0, do nothing and return \c PSA_SUCCESS. + * + * \retval #PSA_SUCCESS + * \p handle was a valid handle and the key material that it + * referred to has been erased. + * Alternatively, \p handle is \c 0. + * \retval #PSA_ERROR_NOT_PERMITTED + * The key cannot be erased because it is + * read-only, either due to a policy or due to physical restrictions. + * \retval #PSA_ERROR_INVALID_HANDLE + * \p handle is not a valid handle nor \c 0. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * There was an failure in communication with the cryptoprocessor. + * The key material may still be present in the cryptoprocessor. + * \retval #PSA_ERROR_STORAGE_FAILURE + * The storage is corrupted. Implementations shall make a best effort + * to erase key material even in this stage, however applications + * should be aware that it may be impossible to guarantee that the + * key material is not recoverable in such cases. + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * An unexpected condition which is not a storage corruption or + * a communication failure occurred. The cryptoprocessor may have + * been compromised. + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_destroy_key(psa_key_handle_t handle); + +/**@}*/ + +/** \defgroup import_export Key import and export + * @{ + */ + +/** + * \brief Import a key in binary format. + * + * This function supports any output from psa_export_key(). Refer to the + * documentation of psa_export_public_key() for the format of public keys + * and to the documentation of psa_export_key() for the format for + * other key types. + * + * The key data determines the key size. The attributes may optionally + * specify a key size; in this case it must match the size determined + * from the key data. A key size of 0 in \p attributes indicates that + * the key size is solely determined by the key data. + * + * Implementations must reject an attempt to import a key of size 0. + * + * This specification supports a single format for each key type. + * Implementations may support other formats as long as the standard + * format is supported. Implementations that support other formats + * should ensure that the formats are clearly unambiguous so as to + * minimize the risk that an invalid input is accidentally interpreted + * according to a different format. + * + * \param[in] attributes The attributes for the new key. + * The key size is always determined from the + * \p data buffer. + * If the key size in \p attributes is nonzero, + * it must be equal to the size from \p data. + * \param[out] handle On success, a handle to the newly created key. + * \c 0 on failure. + * \param[in] data Buffer containing the key data. The content of this + * buffer is interpreted according to the type declared + * in \p attributes. + * All implementations must support at least the format + * described in the documentation + * of psa_export_key() or psa_export_public_key() for + * the chosen type. Implementations may allow other + * formats, but should be conservative: implementations + * should err on the side of rejecting content if it + * may be erroneous (e.g. wrong type or truncated data). + * \param data_length Size of the \p data buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * If the key is persistent, the key material and the key's metadata + * have been saved to persistent storage. + * \retval #PSA_ERROR_ALREADY_EXISTS + * This is an attempt to create a persistent key, and there is + * already a persistent key with the given identifier. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The key type or key size is not supported, either by the + * implementation in general or in this particular persistent location. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The key attributes, as a whole, are invalid. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The key data is not correctly formatted. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The size in \p attributes is nonzero and does not match the size + * of the key data. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_import_key(const psa_key_attributes_t *attributes, + const uint8_t *data, + size_t data_length, + psa_key_handle_t *handle); + + + +/** + * \brief Export a key in binary format. + * + * The output of this function can be passed to psa_import_key() to + * create an equivalent object. + * + * If the implementation of psa_import_key() supports other formats + * beyond the format specified here, the output from psa_export_key() + * must use the representation specified here, not the original + * representation. + * + * For standard key types, the output format is as follows: + * + * - For symmetric keys (including MAC keys), the format is the + * raw bytes of the key. + * - For DES, the key data consists of 8 bytes. The parity bits must be + * correct. + * - For Triple-DES, the format is the concatenation of the + * two or three DES keys. + * - For RSA key pairs (#PSA_KEY_TYPE_RSA_KEY_PAIR), the format + * is the non-encrypted DER encoding of the representation defined by + * PKCS\#1 (RFC 8017) as `RSAPrivateKey`, version 0. + * ``` + * RSAPrivateKey ::= SEQUENCE { + * version INTEGER, -- must be 0 + * modulus INTEGER, -- n + * publicExponent INTEGER, -- e + * privateExponent INTEGER, -- d + * prime1 INTEGER, -- p + * prime2 INTEGER, -- q + * exponent1 INTEGER, -- d mod (p-1) + * exponent2 INTEGER, -- d mod (q-1) + * coefficient INTEGER, -- (inverse of q) mod p + * } + * ``` + * - For elliptic curve key pairs (key types for which + * #PSA_KEY_TYPE_IS_ECC_KEY_PAIR is true), the format is + * a representation of the private value as a `ceiling(m/8)`-byte string + * where `m` is the bit size associated with the curve, i.e. the bit size + * of the order of the curve's coordinate field. This byte string is + * in little-endian order for Montgomery curves (curve types + * `PSA_ECC_FAMILY_CURVEXXX`), and in big-endian order for Weierstrass + * curves (curve types `PSA_ECC_FAMILY_SECTXXX`, `PSA_ECC_FAMILY_SECPXXX` + * and `PSA_ECC_FAMILY_BRAINPOOL_PXXX`). + * For Weierstrass curves, this is the content of the `privateKey` field of + * the `ECPrivateKey` format defined by RFC 5915. For Montgomery curves, + * the format is defined by RFC 7748, and output is masked according to §5. + * - For Diffie-Hellman key exchange key pairs (key types for which + * #PSA_KEY_TYPE_IS_DH_KEY_PAIR is true), the + * format is the representation of the private key `x` as a big-endian byte + * string. The length of the byte string is the private key size in bytes + * (leading zeroes are not stripped). + * - For public keys (key types for which #PSA_KEY_TYPE_IS_PUBLIC_KEY is + * true), the format is the same as for psa_export_public_key(). + * + * The policy on the key must have the usage flag #PSA_KEY_USAGE_EXPORT set. + * + * \param handle Handle to the key to export. + * \param[out] data Buffer where the key data is to be written. + * \param data_size Size of the \p data buffer in bytes. + * \param[out] data_length On success, the number of bytes + * that make up the key data. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * The key does not have the #PSA_KEY_USAGE_EXPORT flag. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p data buffer is too small. You can determine a + * sufficient buffer size by calling + * #PSA_KEY_EXPORT_MAX_SIZE(\c type, \c bits) + * where \c type is the key type + * and \c bits is the key size in bits. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_export_key(psa_key_handle_t handle, + uint8_t *data, + size_t data_size, + size_t *data_length); + +/** + * \brief Export a public key or the public part of a key pair in binary format. + * + * The output of this function can be passed to psa_import_key() to + * create an object that is equivalent to the public key. + * + * This specification supports a single format for each key type. + * Implementations may support other formats as long as the standard + * format is supported. Implementations that support other formats + * should ensure that the formats are clearly unambiguous so as to + * minimize the risk that an invalid input is accidentally interpreted + * according to a different format. + * + * For standard key types, the output format is as follows: + * - For RSA public keys (#PSA_KEY_TYPE_RSA_PUBLIC_KEY), the DER encoding of + * the representation defined by RFC 3279 §2.3.1 as `RSAPublicKey`. + * ``` + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER } -- e + * ``` + * - For elliptic curve public keys (key types for which + * #PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY is true), the format is the uncompressed + * representation defined by SEC1 §2.3.3 as the content of an ECPoint. + * Let `m` be the bit size associated with the curve, i.e. the bit size of + * `q` for a curve over `F_q`. The representation consists of: + * - The byte 0x04; + * - `x_P` as a `ceiling(m/8)`-byte string, big-endian; + * - `y_P` as a `ceiling(m/8)`-byte string, big-endian. + * - For Diffie-Hellman key exchange public keys (key types for which + * #PSA_KEY_TYPE_IS_DH_PUBLIC_KEY is true), + * the format is the representation of the public key `y = g^x mod p` as a + * big-endian byte string. The length of the byte string is the length of the + * base prime `p` in bytes. + * + * Exporting a public key object or the public part of a key pair is + * always permitted, regardless of the key's usage flags. + * + * \param handle Handle to the key to export. + * \param[out] data Buffer where the key data is to be written. + * \param data_size Size of the \p data buffer in bytes. + * \param[out] data_length On success, the number of bytes + * that make up the key data. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The key is neither a public key nor a key pair. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p data buffer is too small. You can determine a + * sufficient buffer size by calling + * #PSA_KEY_EXPORT_MAX_SIZE(#PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(\c type), \c bits) + * where \c type is the key type + * and \c bits is the key size in bits. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_export_public_key(psa_key_handle_t handle, + uint8_t *data, + size_t data_size, + size_t *data_length); + + + +/**@}*/ + +/** \defgroup hash Message digests + * @{ + */ + +/** Calculate the hash (digest) of a message. + * + * \note To verify the hash of a message against an + * expected value, use psa_hash_compare() instead. + * + * \param alg The hash algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_HASH(\p alg) is true). + * \param[in] input Buffer containing the message to hash. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] hash Buffer where the hash is to be written. + * \param hash_size Size of the \p hash buffer in bytes. + * \param[out] hash_length On success, the number of bytes + * that make up the hash value. This is always + * #PSA_HASH_SIZE(\p alg). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a hash algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \p hash_size is too small + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_hash_compute(psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *hash, + size_t hash_size, + size_t *hash_length); + +/** Calculate the hash (digest) of a message and compare it with a + * reference value. + * + * \param alg The hash algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_HASH(\p alg) is true). + * \param[in] input Buffer containing the message to hash. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] hash Buffer containing the expected hash value. + * \param hash_length Size of the \p hash buffer in bytes. + * + * \retval #PSA_SUCCESS + * The expected hash is identical to the actual hash of the input. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The hash of the message was calculated successfully, but it + * differs from the expected hash. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a hash algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p input_length or \p hash_length do not match the hash size for \p alg + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_hash_compare(psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *hash, + size_t hash_length); + +/** The type of the state data structure for multipart hash operations. + * + * Before calling any function on a hash operation object, the application must + * initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_hash_operation_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_hash_operation_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_HASH_OPERATION_INIT, + * for example: + * \code + * psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT; + * \endcode + * - Assign the result of the function psa_hash_operation_init() + * to the structure, for example: + * \code + * psa_hash_operation_t operation; + * operation = psa_hash_operation_init(); + * \endcode + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure except + * as directed by the documentation of a specific implementation. */ +typedef struct psa_hash_operation_s psa_hash_operation_t; + +/** \def PSA_HASH_OPERATION_INIT + * + * This macro returns a suitable initializer for a hash operation object + * of type #psa_hash_operation_t. + */ +#ifdef __DOXYGEN_ONLY__ +/* This is an example definition for documentation purposes. + * Implementations should define a suitable value in `crypto_struct.h`. + */ +#define PSA_HASH_OPERATION_INIT {0} +#endif + +/** Return an initial value for a hash operation object. + */ +static psa_hash_operation_t psa_hash_operation_init(void); + +/** Set up a multipart hash operation. + * + * The sequence of operations to calculate a hash (message digest) + * is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_hash_operation_t, e.g. #PSA_HASH_OPERATION_INIT. + * -# Call psa_hash_setup() to specify the algorithm. + * -# Call psa_hash_update() zero, one or more times, passing a fragment + * of the message each time. The hash that is calculated is the hash + * of the concatenation of these messages in order. + * -# To calculate the hash, call psa_hash_finish(). + * To compare the hash with an expected value, call psa_hash_verify(). + * + * If an error occurs at any step after a call to psa_hash_setup(), the + * operation will need to be reset by a call to psa_hash_abort(). The + * application may call psa_hash_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_hash_setup(), the application must + * eventually terminate the operation. The following events terminate an + * operation: + * - A successful call to psa_hash_finish() or psa_hash_verify(). + * - A call to psa_hash_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_hash_operation_t and not yet in use. + * \param alg The hash algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_HASH(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not a supported hash algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p alg is not a hash algorithm. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_hash_setup(psa_hash_operation_t *operation, + psa_algorithm_t alg); + +/** Add a message fragment to a multipart hash operation. + * + * The application must call psa_hash_setup() before calling this function. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_hash_abort(). + * + * \param[in,out] operation Active hash operation. + * \param[in] input Buffer containing the message fragment to hash. + * \param input_length Size of the \p input buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it muct be active). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_hash_update(psa_hash_operation_t *operation, + const uint8_t *input, + size_t input_length); + +/** Finish the calculation of the hash of a message. + * + * The application must call psa_hash_setup() before calling this function. + * This function calculates the hash of the message formed by concatenating + * the inputs passed to preceding calls to psa_hash_update(). + * + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_hash_abort(). + * + * \warning Applications should not call this function if they expect + * a specific value for the hash. Call psa_hash_verify() instead. + * Beware that comparing integrity or authenticity data such as + * hash values with a function such as \c memcmp is risky + * because the time taken by the comparison may leak information + * about the hashed data which could allow an attacker to guess + * a valid hash and thereby bypass security controls. + * + * \param[in,out] operation Active hash operation. + * \param[out] hash Buffer where the hash is to be written. + * \param hash_size Size of the \p hash buffer in bytes. + * \param[out] hash_length On success, the number of bytes + * that make up the hash value. This is always + * #PSA_HASH_SIZE(\c alg) where \c alg is the + * hash algorithm that is calculated. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p hash buffer is too small. You can determine a + * sufficient buffer size by calling #PSA_HASH_SIZE(\c alg) + * where \c alg is the hash algorithm that is calculated. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_hash_finish(psa_hash_operation_t *operation, + uint8_t *hash, + size_t hash_size, + size_t *hash_length); + +/** Finish the calculation of the hash of a message and compare it with + * an expected value. + * + * The application must call psa_hash_setup() before calling this function. + * This function calculates the hash of the message formed by concatenating + * the inputs passed to preceding calls to psa_hash_update(). It then + * compares the calculated hash with the expected hash passed as a + * parameter to this function. + * + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_hash_abort(). + * + * \note Implementations shall make the best effort to ensure that the + * comparison between the actual hash and the expected hash is performed + * in constant time. + * + * \param[in,out] operation Active hash operation. + * \param[in] hash Buffer containing the expected hash value. + * \param hash_length Size of the \p hash buffer in bytes. + * + * \retval #PSA_SUCCESS + * The expected hash is identical to the actual hash of the message. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The hash of the message was calculated successfully, but it + * differs from the expected hash. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_hash_verify(psa_hash_operation_t *operation, + const uint8_t *hash, + size_t hash_length); + +/** Abort a hash operation. + * + * Aborting an operation frees all associated resources except for the + * \p operation structure itself. Once aborted, the operation object + * can be reused for another operation by calling + * psa_hash_setup() again. + * + * You may call this function any time after the operation object has + * been initialized by one of the methods described in #psa_hash_operation_t. + * + * In particular, calling psa_hash_abort() after the operation has been + * terminated by a call to psa_hash_abort(), psa_hash_finish() or + * psa_hash_verify() is safe and has no effect. + * + * \param[in,out] operation Initialized hash operation. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_hash_abort(psa_hash_operation_t *operation); + +/** Clone a hash operation. + * + * This function copies the state of an ongoing hash operation to + * a new operation object. In other words, this function is equivalent + * to calling psa_hash_setup() on \p target_operation with the same + * algorithm that \p source_operation was set up for, then + * psa_hash_update() on \p target_operation with the same input that + * that was passed to \p source_operation. After this function returns, the + * two objects are independent, i.e. subsequent calls involving one of + * the objects do not affect the other object. + * + * \param[in] source_operation The active hash operation to clone. + * \param[in,out] target_operation The operation object to set up. + * It must be initialized but not active. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_BAD_STATE + * The \p source_operation state is not valid (it must be active). + * \retval #PSA_ERROR_BAD_STATE + * The \p target_operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_hash_clone(const psa_hash_operation_t *source_operation, + psa_hash_operation_t *target_operation); + +/**@}*/ + +/** \defgroup MAC Message authentication codes + * @{ + */ + +/** Calculate the MAC (message authentication code) of a message. + * + * \note To verify the MAC of a message against an + * expected value, use psa_mac_verify() instead. + * Beware that comparing integrity or authenticity data such as + * MAC values with a function such as \c memcmp is risky + * because the time taken by the comparison may leak information + * about the MAC value which could allow an attacker to guess + * a valid MAC and thereby bypass security controls. + * + * \param handle Handle to the key to use for the operation. + * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_MAC(\p alg) is true). + * \param[in] input Buffer containing the input message. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] mac Buffer where the MAC value is to be written. + * \param mac_size Size of the \p mac buffer in bytes. + * \param[out] mac_length On success, the number of bytes + * that make up the MAC value. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a MAC algorithm. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \p mac_size is too small + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * The key could not be retrieved from storage. + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_compute(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *mac, + size_t mac_size, + size_t *mac_length); + +/** Calculate the MAC of a message and compare it with a reference value. + * + * \param handle Handle to the key to use for the operation. + * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_MAC(\p alg) is true). + * \param[in] input Buffer containing the input message. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] mac Buffer containing the expected MAC value. + * \param mac_length Size of the \p mac buffer in bytes. + * + * \retval #PSA_SUCCESS + * The expected MAC is identical to the actual MAC of the input. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The MAC of the message was calculated successfully, but it + * differs from the expected value. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a MAC algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * The key could not be retrieved from storage. + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_verify(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *mac, + size_t mac_length); + +/** The type of the state data structure for multipart MAC operations. + * + * Before calling any function on a MAC operation object, the application must + * initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_mac_operation_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_mac_operation_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_MAC_OPERATION_INIT, + * for example: + * \code + * psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT; + * \endcode + * - Assign the result of the function psa_mac_operation_init() + * to the structure, for example: + * \code + * psa_mac_operation_t operation; + * operation = psa_mac_operation_init(); + * \endcode + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure except + * as directed by the documentation of a specific implementation. */ +typedef struct psa_mac_operation_s psa_mac_operation_t; + +/** \def PSA_MAC_OPERATION_INIT + * + * This macro returns a suitable initializer for a MAC operation object of type + * #psa_mac_operation_t. + */ +#ifdef __DOXYGEN_ONLY__ +/* This is an example definition for documentation purposes. + * Implementations should define a suitable value in `crypto_struct.h`. + */ +#define PSA_MAC_OPERATION_INIT {0} +#endif + +/** Return an initial value for a MAC operation object. + */ +static psa_mac_operation_t psa_mac_operation_init(void); + +/** Set up a multipart MAC calculation operation. + * + * This function sets up the calculation of the MAC + * (message authentication code) of a byte string. + * To verify the MAC of a message against an + * expected value, use psa_mac_verify_setup() instead. + * + * The sequence of operations to calculate a MAC is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_mac_operation_t, e.g. #PSA_MAC_OPERATION_INIT. + * -# Call psa_mac_sign_setup() to specify the algorithm and key. + * -# Call psa_mac_update() zero, one or more times, passing a fragment + * of the message each time. The MAC that is calculated is the MAC + * of the concatenation of these messages in order. + * -# At the end of the message, call psa_mac_sign_finish() to finish + * calculating the MAC value and retrieve it. + * + * If an error occurs at any step after a call to psa_mac_sign_setup(), the + * operation will need to be reset by a call to psa_mac_abort(). The + * application may call psa_mac_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_mac_sign_setup(), the application must + * eventually terminate the operation through one of the following methods: + * - A successful call to psa_mac_sign_finish(). + * - A call to psa_mac_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_mac_operation_t and not yet in use. + * \param handle Handle to the key to use for the operation. + * It must remain valid until the operation + * terminates. + * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_MAC(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a MAC algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * The key could not be retrieved from storage. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg); + +/** Set up a multipart MAC verification operation. + * + * This function sets up the verification of the MAC + * (message authentication code) of a byte string against an expected value. + * + * The sequence of operations to verify a MAC is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_mac_operation_t, e.g. #PSA_MAC_OPERATION_INIT. + * -# Call psa_mac_verify_setup() to specify the algorithm and key. + * -# Call psa_mac_update() zero, one or more times, passing a fragment + * of the message each time. The MAC that is calculated is the MAC + * of the concatenation of these messages in order. + * -# At the end of the message, call psa_mac_verify_finish() to finish + * calculating the actual MAC of the message and verify it against + * the expected value. + * + * If an error occurs at any step after a call to psa_mac_verify_setup(), the + * operation will need to be reset by a call to psa_mac_abort(). The + * application may call psa_mac_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_mac_verify_setup(), the application must + * eventually terminate the operation through one of the following methods: + * - A successful call to psa_mac_verify_finish(). + * - A call to psa_mac_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_mac_operation_t and not yet in use. + * \param handle Handle to the key to use for the operation. + * It must remain valid until the operation + * terminates. + * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_MAC(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c key is not compatible with \c alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \c alg is not supported or is not a MAC algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * The key could not be retrieved from storage + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_verify_setup(psa_mac_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg); + +/** Add a message fragment to a multipart MAC operation. + * + * The application must call psa_mac_sign_setup() or psa_mac_verify_setup() + * before calling this function. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_mac_abort(). + * + * \param[in,out] operation Active MAC operation. + * \param[in] input Buffer containing the message fragment to add to + * the MAC calculation. + * \param input_length Size of the \p input buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_update(psa_mac_operation_t *operation, + const uint8_t *input, + size_t input_length); + +/** Finish the calculation of the MAC of a message. + * + * The application must call psa_mac_sign_setup() before calling this function. + * This function calculates the MAC of the message formed by concatenating + * the inputs passed to preceding calls to psa_mac_update(). + * + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_mac_abort(). + * + * \warning Applications should not call this function if they expect + * a specific value for the MAC. Call psa_mac_verify_finish() instead. + * Beware that comparing integrity or authenticity data such as + * MAC values with a function such as \c memcmp is risky + * because the time taken by the comparison may leak information + * about the MAC value which could allow an attacker to guess + * a valid MAC and thereby bypass security controls. + * + * \param[in,out] operation Active MAC operation. + * \param[out] mac Buffer where the MAC value is to be written. + * \param mac_size Size of the \p mac buffer in bytes. + * \param[out] mac_length On success, the number of bytes + * that make up the MAC value. This is always + * #PSA_MAC_FINAL_SIZE(\c key_type, \c key_bits, \c alg) + * where \c key_type and \c key_bits are the type and + * bit-size respectively of the key and \c alg is the + * MAC algorithm that is calculated. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active mac sign + * operation). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p mac buffer is too small. You can determine a + * sufficient buffer size by calling PSA_MAC_FINAL_SIZE(). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_sign_finish(psa_mac_operation_t *operation, + uint8_t *mac, + size_t mac_size, + size_t *mac_length); + +/** Finish the calculation of the MAC of a message and compare it with + * an expected value. + * + * The application must call psa_mac_verify_setup() before calling this function. + * This function calculates the MAC of the message formed by concatenating + * the inputs passed to preceding calls to psa_mac_update(). It then + * compares the calculated MAC with the expected MAC passed as a + * parameter to this function. + * + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_mac_abort(). + * + * \note Implementations shall make the best effort to ensure that the + * comparison between the actual MAC and the expected MAC is performed + * in constant time. + * + * \param[in,out] operation Active MAC operation. + * \param[in] mac Buffer containing the expected MAC value. + * \param mac_length Size of the \p mac buffer in bytes. + * + * \retval #PSA_SUCCESS + * The expected MAC is identical to the actual MAC of the message. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The MAC of the message was calculated successfully, but it + * differs from the expected MAC. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active mac verify + * operation). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_verify_finish(psa_mac_operation_t *operation, + const uint8_t *mac, + size_t mac_length); + +/** Abort a MAC operation. + * + * Aborting an operation frees all associated resources except for the + * \p operation structure itself. Once aborted, the operation object + * can be reused for another operation by calling + * psa_mac_sign_setup() or psa_mac_verify_setup() again. + * + * You may call this function any time after the operation object has + * been initialized by one of the methods described in #psa_mac_operation_t. + * + * In particular, calling psa_mac_abort() after the operation has been + * terminated by a call to psa_mac_abort(), psa_mac_sign_finish() or + * psa_mac_verify_finish() is safe and has no effect. + * + * \param[in,out] operation Initialized MAC operation. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_abort(psa_mac_operation_t *operation); + +/**@}*/ + +/** \defgroup cipher Symmetric ciphers + * @{ + */ + +/** Encrypt a message using a symmetric cipher. + * + * This function encrypts a message with a random IV (initialization + * vector). Use the multipart operation interface with a + * #psa_cipher_operation_t object to provide other forms of IV. + * + * \param handle Handle to the key to use for the operation. + * It must remain valid until the operation + * terminates. + * \param alg The cipher algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_CIPHER(\p alg) is true). + * \param[in] input Buffer containing the message to encrypt. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] output Buffer where the output is to be written. + * The output contains the IV followed by + * the ciphertext proper. + * \param output_size Size of the \p output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a cipher algorithm. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_encrypt(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** Decrypt a message using a symmetric cipher. + * + * This function decrypts a message encrypted with a symmetric cipher. + * + * \param handle Handle to the key to use for the operation. + * It must remain valid until the operation + * terminates. + * \param alg The cipher algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_CIPHER(\p alg) is true). + * \param[in] input Buffer containing the message to decrypt. + * This consists of the IV followed by the + * ciphertext proper. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] output Buffer where the plaintext is to be written. + * \param output_size Size of the \p output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a cipher algorithm. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_decrypt(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** The type of the state data structure for multipart cipher operations. + * + * Before calling any function on a cipher operation object, the application + * must initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_cipher_operation_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_cipher_operation_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_CIPHER_OPERATION_INIT, + * for example: + * \code + * psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT; + * \endcode + * - Assign the result of the function psa_cipher_operation_init() + * to the structure, for example: + * \code + * psa_cipher_operation_t operation; + * operation = psa_cipher_operation_init(); + * \endcode + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure except + * as directed by the documentation of a specific implementation. */ +typedef struct psa_cipher_operation_s psa_cipher_operation_t; + +/** \def PSA_CIPHER_OPERATION_INIT + * + * This macro returns a suitable initializer for a cipher operation object of + * type #psa_cipher_operation_t. + */ +#ifdef __DOXYGEN_ONLY__ +/* This is an example definition for documentation purposes. + * Implementations should define a suitable value in `crypto_struct.h`. + */ +#define PSA_CIPHER_OPERATION_INIT {0} +#endif + +/** Return an initial value for a cipher operation object. + */ +static psa_cipher_operation_t psa_cipher_operation_init(void); + +/** Set the key for a multipart symmetric encryption operation. + * + * The sequence of operations to encrypt a message with a symmetric cipher + * is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_cipher_operation_t, e.g. + * #PSA_CIPHER_OPERATION_INIT. + * -# Call psa_cipher_encrypt_setup() to specify the algorithm and key. + * -# Call either psa_cipher_generate_iv() or psa_cipher_set_iv() to + * generate or set the IV (initialization vector). You should use + * psa_cipher_generate_iv() unless the protocol you are implementing + * requires a specific IV value. + * -# Call psa_cipher_update() zero, one or more times, passing a fragment + * of the message each time. + * -# Call psa_cipher_finish(). + * + * If an error occurs at any step after a call to psa_cipher_encrypt_setup(), + * the operation will need to be reset by a call to psa_cipher_abort(). The + * application may call psa_cipher_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_cipher_encrypt_setup(), the application must + * eventually terminate the operation. The following events terminate an + * operation: + * - A successful call to psa_cipher_finish(). + * - A call to psa_cipher_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_cipher_operation_t and not yet in use. + * \param handle Handle to the key to use for the operation. + * It must remain valid until the operation + * terminates. + * \param alg The cipher algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_CIPHER(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a cipher algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg); + +/** Set the key for a multipart symmetric decryption operation. + * + * The sequence of operations to decrypt a message with a symmetric cipher + * is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_cipher_operation_t, e.g. + * #PSA_CIPHER_OPERATION_INIT. + * -# Call psa_cipher_decrypt_setup() to specify the algorithm and key. + * -# Call psa_cipher_set_iv() with the IV (initialization vector) for the + * decryption. If the IV is prepended to the ciphertext, you can call + * psa_cipher_update() on a buffer containing the IV followed by the + * beginning of the message. + * -# Call psa_cipher_update() zero, one or more times, passing a fragment + * of the message each time. + * -# Call psa_cipher_finish(). + * + * If an error occurs at any step after a call to psa_cipher_decrypt_setup(), + * the operation will need to be reset by a call to psa_cipher_abort(). The + * application may call psa_cipher_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_cipher_decrypt_setup(), the application must + * eventually terminate the operation. The following events terminate an + * operation: + * - A successful call to psa_cipher_finish(). + * - A call to psa_cipher_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_cipher_operation_t and not yet in use. + * \param handle Handle to the key to use for the operation. + * It must remain valid until the operation + * terminates. + * \param alg The cipher algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_CIPHER(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a cipher algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg); + +/** Generate an IV for a symmetric encryption operation. + * + * This function generates a random IV (initialization vector), nonce + * or initial counter value for the encryption operation as appropriate + * for the chosen algorithm, key type and key size. + * + * The application must call psa_cipher_encrypt_setup() before + * calling this function. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_cipher_abort(). + * + * \param[in,out] operation Active cipher operation. + * \param[out] iv Buffer where the generated IV is to be written. + * \param iv_size Size of the \p iv buffer in bytes. + * \param[out] iv_length On success, the number of bytes of the + * generated IV. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, with no IV set). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p iv buffer is too small. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_generate_iv(psa_cipher_operation_t *operation, + uint8_t *iv, + size_t iv_size, + size_t *iv_length); + +/** Set the IV for a symmetric encryption or decryption operation. + * + * This function sets the IV (initialization vector), nonce + * or initial counter value for the encryption or decryption operation. + * + * The application must call psa_cipher_encrypt_setup() before + * calling this function. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_cipher_abort(). + * + * \note When encrypting, applications should use psa_cipher_generate_iv() + * instead of this function, unless implementing a protocol that requires + * a non-random IV. + * + * \param[in,out] operation Active cipher operation. + * \param[in] iv Buffer containing the IV to use. + * \param iv_length Size of the IV in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active cipher + * encrypt operation, with no IV set). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The size of \p iv is not acceptable for the chosen algorithm, + * or the chosen algorithm does not use an IV. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_set_iv(psa_cipher_operation_t *operation, + const uint8_t *iv, + size_t iv_length); + +/** Encrypt or decrypt a message fragment in an active cipher operation. + * + * Before calling this function, you must: + * 1. Call either psa_cipher_encrypt_setup() or psa_cipher_decrypt_setup(). + * The choice of setup function determines whether this function + * encrypts or decrypts its input. + * 2. If the algorithm requires an IV, call psa_cipher_generate_iv() + * (recommended when encrypting) or psa_cipher_set_iv(). + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_cipher_abort(). + * + * \param[in,out] operation Active cipher operation. + * \param[in] input Buffer containing the message fragment to + * encrypt or decrypt. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] output Buffer where the output is to be written. + * \param output_size Size of the \p output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, with an IV set + * if required for the algorithm). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_update(psa_cipher_operation_t *operation, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** Finish encrypting or decrypting a message in a cipher operation. + * + * The application must call psa_cipher_encrypt_setup() or + * psa_cipher_decrypt_setup() before calling this function. The choice + * of setup function determines whether this function encrypts or + * decrypts its input. + * + * This function finishes the encryption or decryption of the message + * formed by concatenating the inputs passed to preceding calls to + * psa_cipher_update(). + * + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_cipher_abort(). + * + * \param[in,out] operation Active cipher operation. + * \param[out] output Buffer where the output is to be written. + * \param output_size Size of the \p output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total input size passed to this operation is not valid for + * this particular algorithm. For example, the algorithm is a based + * on block cipher and requires a whole number of blocks, but the + * total input size is not a multiple of the block size. + * \retval #PSA_ERROR_INVALID_PADDING + * This is a decryption operation for an algorithm that includes + * padding, and the ciphertext does not contain valid padding. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, with an IV set + * if required for the algorithm). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_finish(psa_cipher_operation_t *operation, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** Abort a cipher operation. + * + * Aborting an operation frees all associated resources except for the + * \p operation structure itself. Once aborted, the operation object + * can be reused for another operation by calling + * psa_cipher_encrypt_setup() or psa_cipher_decrypt_setup() again. + * + * You may call this function any time after the operation object has + * been initialized as described in #psa_cipher_operation_t. + * + * In particular, calling psa_cipher_abort() after the operation has been + * terminated by a call to psa_cipher_abort() or psa_cipher_finish() + * is safe and has no effect. + * + * \param[in,out] operation Initialized cipher operation. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation); + +/**@}*/ + +/** \defgroup aead Authenticated encryption with associated data (AEAD) + * @{ + */ + +/** Process an authenticated encryption operation. + * + * \param handle Handle to the key to use for the operation. + * \param alg The AEAD algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * \param[in] nonce Nonce or IV to use. + * \param nonce_length Size of the \p nonce buffer in bytes. + * \param[in] additional_data Additional data that will be authenticated + * but not encrypted. + * \param additional_data_length Size of \p additional_data in bytes. + * \param[in] plaintext Data that will be authenticated and + * encrypted. + * \param plaintext_length Size of \p plaintext in bytes. + * \param[out] ciphertext Output buffer for the authenticated and + * encrypted data. The additional data is not + * part of this output. For algorithms where the + * encrypted data and the authentication tag + * are defined as separate outputs, the + * authentication tag is appended to the + * encrypted data. + * \param ciphertext_size Size of the \p ciphertext buffer in bytes. + * This must be at least + * #PSA_AEAD_ENCRYPT_OUTPUT_SIZE(\p alg, + * \p plaintext_length). + * \param[out] ciphertext_length On success, the size of the output + * in the \p ciphertext buffer. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not an AEAD algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \p ciphertext_size is too small + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_encrypt(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *nonce, + size_t nonce_length, + const uint8_t *additional_data, + size_t additional_data_length, + const uint8_t *plaintext, + size_t plaintext_length, + uint8_t *ciphertext, + size_t ciphertext_size, + size_t *ciphertext_length); + +/** Process an authenticated decryption operation. + * + * \param handle Handle to the key to use for the operation. + * \param alg The AEAD algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * \param[in] nonce Nonce or IV to use. + * \param nonce_length Size of the \p nonce buffer in bytes. + * \param[in] additional_data Additional data that has been authenticated + * but not encrypted. + * \param additional_data_length Size of \p additional_data in bytes. + * \param[in] ciphertext Data that has been authenticated and + * encrypted. For algorithms where the + * encrypted data and the authentication tag + * are defined as separate inputs, the buffer + * must contain the encrypted data followed + * by the authentication tag. + * \param ciphertext_length Size of \p ciphertext in bytes. + * \param[out] plaintext Output buffer for the decrypted data. + * \param plaintext_size Size of the \p plaintext buffer in bytes. + * This must be at least + * #PSA_AEAD_DECRYPT_OUTPUT_SIZE(\p alg, + * \p ciphertext_length). + * \param[out] plaintext_length On success, the size of the output + * in the \p plaintext buffer. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The ciphertext is not authentic. + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not an AEAD algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \p plaintext_size or \p nonce_length is too small + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_decrypt(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *nonce, + size_t nonce_length, + const uint8_t *additional_data, + size_t additional_data_length, + const uint8_t *ciphertext, + size_t ciphertext_length, + uint8_t *plaintext, + size_t plaintext_size, + size_t *plaintext_length); + +/** The type of the state data structure for multipart AEAD operations. + * + * Before calling any function on an AEAD operation object, the application + * must initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_aead_operation_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_aead_operation_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_AEAD_OPERATION_INIT, + * for example: + * \code + * psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT; + * \endcode + * - Assign the result of the function psa_aead_operation_init() + * to the structure, for example: + * \code + * psa_aead_operation_t operation; + * operation = psa_aead_operation_init(); + * \endcode + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure except + * as directed by the documentation of a specific implementation. */ +typedef struct psa_aead_operation_s psa_aead_operation_t; + +/** \def PSA_AEAD_OPERATION_INIT + * + * This macro returns a suitable initializer for an AEAD operation object of + * type #psa_aead_operation_t. + */ +#ifdef __DOXYGEN_ONLY__ +/* This is an example definition for documentation purposes. + * Implementations should define a suitable value in `crypto_struct.h`. + */ +#define PSA_AEAD_OPERATION_INIT {0} +#endif + +/** Return an initial value for an AEAD operation object. + */ +static psa_aead_operation_t psa_aead_operation_init(void); + +/** Set the key for a multipart authenticated encryption operation. + * + * The sequence of operations to encrypt a message with authentication + * is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_aead_operation_t, e.g. + * #PSA_AEAD_OPERATION_INIT. + * -# Call psa_aead_encrypt_setup() to specify the algorithm and key. + * -# If needed, call psa_aead_set_lengths() to specify the length of the + * inputs to the subsequent calls to psa_aead_update_ad() and + * psa_aead_update(). See the documentation of psa_aead_set_lengths() + * for details. + * -# Call either psa_aead_generate_nonce() or psa_aead_set_nonce() to + * generate or set the nonce. You should use + * psa_aead_generate_nonce() unless the protocol you are implementing + * requires a specific nonce value. + * -# Call psa_aead_update_ad() zero, one or more times, passing a fragment + * of the non-encrypted additional authenticated data each time. + * -# Call psa_aead_update() zero, one or more times, passing a fragment + * of the message to encrypt each time. + * -# Call psa_aead_finish(). + * + * If an error occurs at any step after a call to psa_aead_encrypt_setup(), + * the operation will need to be reset by a call to psa_aead_abort(). The + * application may call psa_aead_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_aead_encrypt_setup(), the application must + * eventually terminate the operation. The following events terminate an + * operation: + * - A successful call to psa_aead_finish(). + * - A call to psa_aead_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_aead_operation_t and not yet in use. + * \param handle Handle to the key to use for the operation. + * It must remain valid until the operation + * terminates. + * \param alg The AEAD algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not an AEAD algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_encrypt_setup(psa_aead_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg); + +/** Set the key for a multipart authenticated decryption operation. + * + * The sequence of operations to decrypt a message with authentication + * is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_aead_operation_t, e.g. + * #PSA_AEAD_OPERATION_INIT. + * -# Call psa_aead_decrypt_setup() to specify the algorithm and key. + * -# If needed, call psa_aead_set_lengths() to specify the length of the + * inputs to the subsequent calls to psa_aead_update_ad() and + * psa_aead_update(). See the documentation of psa_aead_set_lengths() + * for details. + * -# Call psa_aead_set_nonce() with the nonce for the decryption. + * -# Call psa_aead_update_ad() zero, one or more times, passing a fragment + * of the non-encrypted additional authenticated data each time. + * -# Call psa_aead_update() zero, one or more times, passing a fragment + * of the ciphertext to decrypt each time. + * -# Call psa_aead_verify(). + * + * If an error occurs at any step after a call to psa_aead_decrypt_setup(), + * the operation will need to be reset by a call to psa_aead_abort(). The + * application may call psa_aead_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_aead_decrypt_setup(), the application must + * eventually terminate the operation. The following events terminate an + * operation: + * - A successful call to psa_aead_verify(). + * - A call to psa_aead_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_aead_operation_t and not yet in use. + * \param handle Handle to the key to use for the operation. + * It must remain valid until the operation + * terminates. + * \param alg The AEAD algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not an AEAD algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_decrypt_setup(psa_aead_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg); + +/** Generate a random nonce for an authenticated encryption operation. + * + * This function generates a random nonce for the authenticated encryption + * operation with an appropriate size for the chosen algorithm, key type + * and key size. + * + * The application must call psa_aead_encrypt_setup() before + * calling this function. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \param[in,out] operation Active AEAD operation. + * \param[out] nonce Buffer where the generated nonce is to be + * written. + * \param nonce_size Size of the \p nonce buffer in bytes. + * \param[out] nonce_length On success, the number of bytes of the + * generated nonce. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active aead encrypt + operation, with no nonce set). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p nonce buffer is too small. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_generate_nonce(psa_aead_operation_t *operation, + uint8_t *nonce, + size_t nonce_size, + size_t *nonce_length); + +/** Set the nonce for an authenticated encryption or decryption operation. + * + * This function sets the nonce for the authenticated + * encryption or decryption operation. + * + * The application must call psa_aead_encrypt_setup() or + * psa_aead_decrypt_setup() before calling this function. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \note When encrypting, applications should use psa_aead_generate_nonce() + * instead of this function, unless implementing a protocol that requires + * a non-random IV. + * + * \param[in,out] operation Active AEAD operation. + * \param[in] nonce Buffer containing the nonce to use. + * \param nonce_length Size of the nonce in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, with no nonce + * set). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The size of \p nonce is not acceptable for the chosen algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_set_nonce(psa_aead_operation_t *operation, + const uint8_t *nonce, + size_t nonce_length); + +/** Declare the lengths of the message and additional data for AEAD. + * + * The application must call this function before calling + * psa_aead_update_ad() or psa_aead_update() if the algorithm for + * the operation requires it. If the algorithm does not require it, + * calling this function is optional, but if this function is called + * then the implementation must enforce the lengths. + * + * You may call this function before or after setting the nonce with + * psa_aead_set_nonce() or psa_aead_generate_nonce(). + * + * - For #PSA_ALG_CCM, calling this function is required. + * - For the other AEAD algorithms defined in this specification, calling + * this function is not required. + * - For vendor-defined algorithm, refer to the vendor documentation. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \param[in,out] operation Active AEAD operation. + * \param ad_length Size of the non-encrypted additional + * authenticated data in bytes. + * \param plaintext_length Size of the plaintext to encrypt in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, and + * psa_aead_update_ad() and psa_aead_update() must not have been + * called yet). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * At least one of the lengths is not acceptable for the chosen + * algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_set_lengths(psa_aead_operation_t *operation, + size_t ad_length, + size_t plaintext_length); + +/** Pass additional data to an active AEAD operation. + * + * Additional data is authenticated, but not encrypted. + * + * You may call this function multiple times to pass successive fragments + * of the additional data. You may not call this function after passing + * data to encrypt or decrypt with psa_aead_update(). + * + * Before calling this function, you must: + * 1. Call either psa_aead_encrypt_setup() or psa_aead_decrypt_setup(). + * 2. Set the nonce with psa_aead_generate_nonce() or psa_aead_set_nonce(). + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \warning When decrypting, until psa_aead_verify() has returned #PSA_SUCCESS, + * there is no guarantee that the input is valid. Therefore, until + * you have called psa_aead_verify() and it has returned #PSA_SUCCESS, + * treat the input as untrusted and prepare to undo any action that + * depends on the input if psa_aead_verify() returns an error status. + * + * \param[in,out] operation Active AEAD operation. + * \param[in] input Buffer containing the fragment of + * additional data. + * \param input_length Size of the \p input buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, have a nonce + * set, have lengths set if required by the algorithm, and + * psa_aead_update() must not have been called yet). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total input length overflows the additional data length that + * was previously specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_update_ad(psa_aead_operation_t *operation, + const uint8_t *input, + size_t input_length); + +/** Encrypt or decrypt a message fragment in an active AEAD operation. + * + * Before calling this function, you must: + * 1. Call either psa_aead_encrypt_setup() or psa_aead_decrypt_setup(). + * The choice of setup function determines whether this function + * encrypts or decrypts its input. + * 2. Set the nonce with psa_aead_generate_nonce() or psa_aead_set_nonce(). + * 3. Call psa_aead_update_ad() to pass all the additional data. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \warning When decrypting, until psa_aead_verify() has returned #PSA_SUCCESS, + * there is no guarantee that the input is valid. Therefore, until + * you have called psa_aead_verify() and it has returned #PSA_SUCCESS: + * - Do not use the output in any way other than storing it in a + * confidential location. If you take any action that depends + * on the tentative decrypted data, this action will need to be + * undone if the input turns out not to be valid. Furthermore, + * if an adversary can observe that this action took place + * (for example through timing), they may be able to use this + * fact as an oracle to decrypt any message encrypted with the + * same key. + * - In particular, do not copy the output anywhere but to a + * memory or storage space that you have exclusive access to. + * + * This function does not require the input to be aligned to any + * particular block boundary. If the implementation can only process + * a whole block at a time, it must consume all the input provided, but + * it may delay the end of the corresponding output until a subsequent + * call to psa_aead_update(), psa_aead_finish() or psa_aead_verify() + * provides sufficient input. The amount of data that can be delayed + * in this way is bounded by #PSA_AEAD_UPDATE_OUTPUT_SIZE. + * + * \param[in,out] operation Active AEAD operation. + * \param[in] input Buffer containing the message fragment to + * encrypt or decrypt. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] output Buffer where the output is to be written. + * \param output_size Size of the \p output buffer in bytes. + * This must be at least + * #PSA_AEAD_UPDATE_OUTPUT_SIZE(\c alg, + * \p input_length) where \c alg is the + * algorithm that is being calculated. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, have a nonce + * set, and have lengths set if required by the algorithm). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. + * You can determine a sufficient buffer size by calling + * #PSA_AEAD_UPDATE_OUTPUT_SIZE(\c alg, \p input_length) + * where \c alg is the algorithm that is being calculated. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total length of input to psa_aead_update_ad() so far is + * less than the additional data length that was previously + * specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total input length overflows the plaintext length that + * was previously specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_update(psa_aead_operation_t *operation, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** Finish encrypting a message in an AEAD operation. + * + * The operation must have been set up with psa_aead_encrypt_setup(). + * + * This function finishes the authentication of the additional data + * formed by concatenating the inputs passed to preceding calls to + * psa_aead_update_ad() with the plaintext formed by concatenating the + * inputs passed to preceding calls to psa_aead_update(). + * + * This function has two output buffers: + * - \p ciphertext contains trailing ciphertext that was buffered from + * preceding calls to psa_aead_update(). + * - \p tag contains the authentication tag. Its length is always + * #PSA_AEAD_TAG_LENGTH(\c alg) where \c alg is the AEAD algorithm + * that the operation performs. + * + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \param[in,out] operation Active AEAD operation. + * \param[out] ciphertext Buffer where the last part of the ciphertext + * is to be written. + * \param ciphertext_size Size of the \p ciphertext buffer in bytes. + * This must be at least + * #PSA_AEAD_FINISH_OUTPUT_SIZE(\c alg) where + * \c alg is the algorithm that is being + * calculated. + * \param[out] ciphertext_length On success, the number of bytes of + * returned ciphertext. + * \param[out] tag Buffer where the authentication tag is + * to be written. + * \param tag_size Size of the \p tag buffer in bytes. + * This must be at least + * #PSA_AEAD_TAG_LENGTH(\c alg) where \c alg is + * the algorithm that is being calculated. + * \param[out] tag_length On success, the number of bytes + * that make up the returned tag. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active encryption + * operation with a nonce set). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p ciphertext or \p tag buffer is too small. + * You can determine a sufficient buffer size for \p ciphertext by + * calling #PSA_AEAD_FINISH_OUTPUT_SIZE(\c alg) + * where \c alg is the algorithm that is being calculated. + * You can determine a sufficient buffer size for \p tag by + * calling #PSA_AEAD_TAG_LENGTH(\c alg). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total length of input to psa_aead_update_ad() so far is + * less than the additional data length that was previously + * specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total length of input to psa_aead_update() so far is + * less than the plaintext length that was previously + * specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_finish(psa_aead_operation_t *operation, + uint8_t *ciphertext, + size_t ciphertext_size, + size_t *ciphertext_length, + uint8_t *tag, + size_t tag_size, + size_t *tag_length); + +/** Finish authenticating and decrypting a message in an AEAD operation. + * + * The operation must have been set up with psa_aead_decrypt_setup(). + * + * This function finishes the authenticated decryption of the message + * components: + * + * - The additional data consisting of the concatenation of the inputs + * passed to preceding calls to psa_aead_update_ad(). + * - The ciphertext consisting of the concatenation of the inputs passed to + * preceding calls to psa_aead_update(). + * - The tag passed to this function call. + * + * If the authentication tag is correct, this function outputs any remaining + * plaintext and reports success. If the authentication tag is not correct, + * this function returns #PSA_ERROR_INVALID_SIGNATURE. + * + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \note Implementations shall make the best effort to ensure that the + * comparison between the actual tag and the expected tag is performed + * in constant time. + * + * \param[in,out] operation Active AEAD operation. + * \param[out] plaintext Buffer where the last part of the plaintext + * is to be written. This is the remaining data + * from previous calls to psa_aead_update() + * that could not be processed until the end + * of the input. + * \param plaintext_size Size of the \p plaintext buffer in bytes. + * This must be at least + * #PSA_AEAD_VERIFY_OUTPUT_SIZE(\c alg) where + * \c alg is the algorithm that is being + * calculated. + * \param[out] plaintext_length On success, the number of bytes of + * returned plaintext. + * \param[in] tag Buffer containing the authentication tag. + * \param tag_length Size of the \p tag buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The calculations were successful, but the authentication tag is + * not correct. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active decryption + * operation with a nonce set). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p plaintext buffer is too small. + * You can determine a sufficient buffer size for \p plaintext by + * calling #PSA_AEAD_VERIFY_OUTPUT_SIZE(\c alg) + * where \c alg is the algorithm that is being calculated. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total length of input to psa_aead_update_ad() so far is + * less than the additional data length that was previously + * specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total length of input to psa_aead_update() so far is + * less than the plaintext length that was previously + * specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_verify(psa_aead_operation_t *operation, + uint8_t *plaintext, + size_t plaintext_size, + size_t *plaintext_length, + const uint8_t *tag, + size_t tag_length); + +/** Abort an AEAD operation. + * + * Aborting an operation frees all associated resources except for the + * \p operation structure itself. Once aborted, the operation object + * can be reused for another operation by calling + * psa_aead_encrypt_setup() or psa_aead_decrypt_setup() again. + * + * You may call this function any time after the operation object has + * been initialized as described in #psa_aead_operation_t. + * + * In particular, calling psa_aead_abort() after the operation has been + * terminated by a call to psa_aead_abort(), psa_aead_finish() or + * psa_aead_verify() is safe and has no effect. + * + * \param[in,out] operation Initialized AEAD operation. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_abort(psa_aead_operation_t *operation); + +/**@}*/ + +/** \defgroup asymmetric Asymmetric cryptography + * @{ + */ + +/** + * \brief Sign a hash or short message with a private key. + * + * Note that to perform a hash-and-sign signature algorithm, you must + * first calculate the hash by calling psa_hash_setup(), psa_hash_update() + * and psa_hash_finish(). Then pass the resulting hash as the \p hash + * parameter to this function. You can use #PSA_ALG_SIGN_GET_HASH(\p alg) + * to determine the hash algorithm to use. + * + * \param handle Handle to the key to use for the operation. + * It must be an asymmetric key pair. + * \param alg A signature algorithm that is compatible with + * the type of \p handle. + * \param[in] hash The hash or message to sign. + * \param hash_length Size of the \p hash buffer in bytes. + * \param[out] signature Buffer where the signature is to be written. + * \param signature_size Size of the \p signature buffer in bytes. + * \param[out] signature_length On success, the number of bytes + * that make up the returned signature value. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p signature buffer is too small. You can + * determine a sufficient buffer size by calling + * #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) + * where \c key_type and \c key_bits are the type and bit-size + * respectively of \p handle. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_sign_hash(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + uint8_t *signature, + size_t signature_size, + size_t *signature_length); + +/** + * \brief Verify the signature a hash or short message using a public key. + * + * Note that to perform a hash-and-sign signature algorithm, you must + * first calculate the hash by calling psa_hash_setup(), psa_hash_update() + * and psa_hash_finish(). Then pass the resulting hash as the \p hash + * parameter to this function. You can use #PSA_ALG_SIGN_GET_HASH(\p alg) + * to determine the hash algorithm to use. + * + * \param handle Handle to the key to use for the operation. + * It must be a public key or an asymmetric key pair. + * \param alg A signature algorithm that is compatible with + * the type of \p handle. + * \param[in] hash The hash or message whose signature is to be + * verified. + * \param hash_length Size of the \p hash buffer in bytes. + * \param[in] signature Buffer containing the signature to verify. + * \param signature_length Size of the \p signature buffer in bytes. + * + * \retval #PSA_SUCCESS + * The signature is valid. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The calculation was perfomed successfully, but the passed + * signature is not a valid signature. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_verify_hash(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + const uint8_t *signature, + size_t signature_length); + +/** + * \brief Encrypt a short message with a public key. + * + * \param handle Handle to the key to use for the operation. + * It must be a public key or an asymmetric + * key pair. + * \param alg An asymmetric encryption algorithm that is + * compatible with the type of \p handle. + * \param[in] input The message to encrypt. + * \param input_length Size of the \p input buffer in bytes. + * \param[in] salt A salt or label, if supported by the + * encryption algorithm. + * If the algorithm does not support a + * salt, pass \c NULL. + * If the algorithm supports an optional + * salt and you do not want to pass a salt, + * pass \c NULL. + * + * - For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is + * supported. + * \param salt_length Size of the \p salt buffer in bytes. + * If \p salt is \c NULL, pass 0. + * \param[out] output Buffer where the encrypted message is to + * be written. + * \param output_size Size of the \p output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. You can + * determine a sufficient buffer size by calling + * #PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) + * where \c key_type and \c key_bits are the type and bit-size + * respectively of \p handle. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_asymmetric_encrypt(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *salt, + size_t salt_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** + * \brief Decrypt a short message with a private key. + * + * \param handle Handle to the key to use for the operation. + * It must be an asymmetric key pair. + * \param alg An asymmetric encryption algorithm that is + * compatible with the type of \p handle. + * \param[in] input The message to decrypt. + * \param input_length Size of the \p input buffer in bytes. + * \param[in] salt A salt or label, if supported by the + * encryption algorithm. + * If the algorithm does not support a + * salt, pass \c NULL. + * If the algorithm supports an optional + * salt and you do not want to pass a salt, + * pass \c NULL. + * + * - For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is + * supported. + * \param salt_length Size of the \p salt buffer in bytes. + * If \p salt is \c NULL, pass 0. + * \param[out] output Buffer where the decrypted message is to + * be written. + * \param output_size Size of the \c output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. You can + * determine a sufficient buffer size by calling + * #PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) + * where \c key_type and \c key_bits are the type and bit-size + * respectively of \p handle. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY + * \retval #PSA_ERROR_INVALID_PADDING + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_asymmetric_decrypt(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *salt, + size_t salt_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/**@}*/ + +/** \defgroup key_derivation Key derivation and pseudorandom generation + * @{ + */ + +/** The type of the state data structure for key derivation operations. + * + * Before calling any function on a key derivation operation object, the + * application must initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_key_derivation_operation_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_key_derivation_operation_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_KEY_DERIVATION_OPERATION_INIT, + * for example: + * \code + * psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT; + * \endcode + * - Assign the result of the function psa_key_derivation_operation_init() + * to the structure, for example: + * \code + * psa_key_derivation_operation_t operation; + * operation = psa_key_derivation_operation_init(); + * \endcode + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure except + * as directed by the documentation of a specific implementation. + */ +typedef struct psa_key_derivation_s psa_key_derivation_operation_t; + +/** \def PSA_KEY_DERIVATION_OPERATION_INIT + * + * This macro returns a suitable initializer for a key derivation operation + * object of type #psa_key_derivation_operation_t. + */ +#ifdef __DOXYGEN_ONLY__ +/* This is an example definition for documentation purposes. + * Implementations should define a suitable value in `crypto_struct.h`. + */ +#define PSA_KEY_DERIVATION_OPERATION_INIT {0} +#endif + +/** Return an initial value for a key derivation operation object. + */ +static psa_key_derivation_operation_t psa_key_derivation_operation_init(void); + +/** Set up a key derivation operation. + * + * A key derivation algorithm takes some inputs and uses them to generate + * a byte stream in a deterministic way. + * This byte stream can be used to produce keys and other + * cryptographic material. + * + * To derive a key: + * -# Start with an initialized object of type #psa_key_derivation_operation_t. + * -# Call psa_key_derivation_setup() to select the algorithm. + * -# Provide the inputs for the key derivation by calling + * psa_key_derivation_input_bytes() or psa_key_derivation_input_key() + * as appropriate. Which inputs are needed, in what order, and whether + * they may be keys and if so of what type depends on the algorithm. + * -# Optionally set the operation's maximum capacity with + * psa_key_derivation_set_capacity(). You may do this before, in the middle + * of or after providing inputs. For some algorithms, this step is mandatory + * because the output depends on the maximum capacity. + * -# To derive a key, call psa_key_derivation_output_key(). + * To derive a byte string for a different purpose, call + * psa_key_derivation_output_bytes(). + * Successive calls to these functions use successive output bytes + * calculated by the key derivation algorithm. + * -# Clean up the key derivation operation object with + * psa_key_derivation_abort(). + * + * If this function returns an error, the key derivation operation object is + * not changed. + * + * If an error occurs at any step after a call to psa_key_derivation_setup(), + * the operation will need to be reset by a call to psa_key_derivation_abort(). + * + * Implementations must reject an attempt to derive a key of size 0. + * + * \param[in,out] operation The key derivation operation object + * to set up. It must + * have been initialized but not set up yet. + * \param alg The key derivation algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_KEY_DERIVATION(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c alg is not a key derivation algorithm. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \c alg is not supported or is not a key derivation algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_setup( + psa_key_derivation_operation_t *operation, + psa_algorithm_t alg); + +/** Retrieve the current capacity of a key derivation operation. + * + * The capacity of a key derivation is the maximum number of bytes that it can + * return. When you get *N* bytes of output from a key derivation operation, + * this reduces its capacity by *N*. + * + * \param[in] operation The operation to query. + * \param[out] capacity On success, the capacity of the operation. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active). + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_get_capacity( + const psa_key_derivation_operation_t *operation, + size_t *capacity); + +/** Set the maximum capacity of a key derivation operation. + * + * The capacity of a key derivation operation is the maximum number of bytes + * that the key derivation operation can return from this point onwards. + * + * \param[in,out] operation The key derivation operation object to modify. + * \param capacity The new capacity of the operation. + * It must be less or equal to the operation's + * current capacity. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p capacity is larger than the operation's current capacity. + * In this case, the operation object remains valid and its capacity + * remains unchanged. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active). + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_set_capacity( + psa_key_derivation_operation_t *operation, + size_t capacity); + +/** Use the maximum possible capacity for a key derivation operation. + * + * Use this value as the capacity argument when setting up a key derivation + * to indicate that the operation should have the maximum possible capacity. + * The value of the maximum possible capacity depends on the key derivation + * algorithm. + */ +#define PSA_KEY_DERIVATION_UNLIMITED_CAPACITY ((size_t)(-1)) + +/** Provide an input for key derivation or key agreement. + * + * Which inputs are required and in what order depends on the algorithm. + * Refer to the documentation of each key derivation or key agreement + * algorithm for information. + * + * This function passes direct inputs, which is usually correct for + * non-secret inputs. To pass a secret input, which should be in a key + * object, call psa_key_derivation_input_key() instead of this function. + * Refer to the documentation of individual step types + * (`PSA_KEY_DERIVATION_INPUT_xxx` values of type ::psa_key_derivation_step_t) + * for more information. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_key_derivation_abort(). + * + * \param[in,out] operation The key derivation operation object to use. + * It must have been set up with + * psa_key_derivation_setup() and must not + * have produced any output yet. + * \param step Which step the input data is for. + * \param[in] data Input data to use. + * \param data_length Size of the \p data buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c step is not compatible with the operation's algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c step does not allow direct inputs. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid for this input \p step. + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_input_bytes( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + const uint8_t *data, + size_t data_length); + +/** Provide an input for key derivation in the form of a key. + * + * Which inputs are required and in what order depends on the algorithm. + * Refer to the documentation of each key derivation or key agreement + * algorithm for information. + * + * This function obtains input from a key object, which is usually correct for + * secret inputs or for non-secret personalization strings kept in the key + * store. To pass a non-secret parameter which is not in the key store, + * call psa_key_derivation_input_bytes() instead of this function. + * Refer to the documentation of individual step types + * (`PSA_KEY_DERIVATION_INPUT_xxx` values of type ::psa_key_derivation_step_t) + * for more information. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_key_derivation_abort(). + * + * \param[in,out] operation The key derivation operation object to use. + * It must have been set up with + * psa_key_derivation_setup() and must not + * have produced any output yet. + * \param step Which step the input data is for. + * \param handle Handle to the key. It must have an + * appropriate type for \p step and must + * allow the usage #PSA_KEY_USAGE_DERIVE. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c step is not compatible with the operation's algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c step does not allow key inputs of the given type + * or does not allow key inputs at all. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid for this input \p step. + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_input_key( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + psa_key_handle_t handle); + +/** Perform a key agreement and use the shared secret as input to a key + * derivation. + * + * A key agreement algorithm takes two inputs: a private key \p private_key + * a public key \p peer_key. + * The result of this function is passed as input to a key derivation. + * The output of this key derivation can be extracted by reading from the + * resulting operation to produce keys and other cryptographic material. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_key_derivation_abort(). + * + * \param[in,out] operation The key derivation operation object to use. + * It must have been set up with + * psa_key_derivation_setup() with a + * key agreement and derivation algorithm + * \c alg (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_KEY_AGREEMENT(\c alg) is true + * and #PSA_ALG_IS_RAW_KEY_AGREEMENT(\c alg) + * is false). + * The operation must be ready for an + * input of the type given by \p step. + * \param step Which step the input data is for. + * \param private_key Handle to the private key to use. + * \param[in] peer_key Public key of the peer. The peer key must be in the + * same format that psa_import_key() accepts for the + * public key type corresponding to the type of + * private_key. That is, this function performs the + * equivalent of + * #psa_import_key(..., + * `peer_key`, `peer_key_length`) where + * with key attributes indicating the public key + * type corresponding to the type of `private_key`. + * For example, for EC keys, this means that peer_key + * is interpreted as a point on the curve that the + * private key is on. The standard formats for public + * keys are documented in the documentation of + * psa_export_public_key(). + * \param peer_key_length Size of \p peer_key in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid for this key agreement \p step. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c private_key is not compatible with \c alg, + * or \p peer_key is not valid for \c alg or not compatible with + * \c private_key. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \c alg is not supported or is not a key derivation algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c step does not allow an input resulting from a key agreement. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_key_agreement( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + psa_key_handle_t private_key, + const uint8_t *peer_key, + size_t peer_key_length); + +/** Read some data from a key derivation operation. + * + * This function calculates output bytes from a key derivation algorithm and + * return those bytes. + * If you view the key derivation's output as a stream of bytes, this + * function destructively reads the requested number of bytes from the + * stream. + * The operation's capacity decreases by the number of bytes read. + * + * If this function returns an error status other than + * #PSA_ERROR_INSUFFICIENT_DATA, the operation enters an error + * state and must be aborted by calling psa_key_derivation_abort(). + * + * \param[in,out] operation The key derivation operation object to read from. + * \param[out] output Buffer where the output will be written. + * \param output_length Number of bytes to output. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INSUFFICIENT_DATA + * The operation's capacity was less than + * \p output_length bytes. Note that in this case, + * no output is written to the output buffer. + * The operation's capacity is set to 0, thus + * subsequent calls to this function will not + * succeed, even with a smaller output buffer. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active and completed + * all required input steps). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_output_bytes( + psa_key_derivation_operation_t *operation, + uint8_t *output, + size_t output_length); + +/** Derive a key from an ongoing key derivation operation. + * + * This function calculates output bytes from a key derivation algorithm + * and uses those bytes to generate a key deterministically. + * The key's location, usage policy, type and size are taken from + * \p attributes. + * + * If you view the key derivation's output as a stream of bytes, this + * function destructively reads as many bytes as required from the + * stream. + * The operation's capacity decreases by the number of bytes read. + * + * If this function returns an error status other than + * #PSA_ERROR_INSUFFICIENT_DATA, the operation enters an error + * state and must be aborted by calling psa_key_derivation_abort(). + * + * How much output is produced and consumed from the operation, and how + * the key is derived, depends on the key type: + * + * - For key types for which the key is an arbitrary sequence of bytes + * of a given size, this function is functionally equivalent to + * calling #psa_key_derivation_output_bytes + * and passing the resulting output to #psa_import_key. + * However, this function has a security benefit: + * if the implementation provides an isolation boundary then + * the key material is not exposed outside the isolation boundary. + * As a consequence, for these key types, this function always consumes + * exactly (\p bits / 8) bytes from the operation. + * The following key types defined in this specification follow this scheme: + * + * - #PSA_KEY_TYPE_AES; + * - #PSA_KEY_TYPE_ARC4; + * - #PSA_KEY_TYPE_CAMELLIA; + * - #PSA_KEY_TYPE_DERIVE; + * - #PSA_KEY_TYPE_HMAC. + * + * - For ECC keys on a Montgomery elliptic curve + * (#PSA_KEY_TYPE_ECC_KEY_PAIR(\c curve) where \c curve designates a + * Montgomery curve), this function always draws a byte string whose + * length is determined by the curve, and sets the mandatory bits + * accordingly. That is: + * + * - Curve25519 (#PSA_ECC_FAMILY_MONTGOMERY, 255 bits): draw a 32-byte + * string and process it as specified in RFC 7748 §5. + * - Curve448 (#PSA_ECC_FAMILY_MONTGOMERY, 448 bits): draw a 56-byte + * string and process it as specified in RFC 7748 §5. + * + * - For key types for which the key is represented by a single sequence of + * \p bits bits with constraints as to which bit sequences are acceptable, + * this function draws a byte string of length (\p bits / 8) bytes rounded + * up to the nearest whole number of bytes. If the resulting byte string + * is acceptable, it becomes the key, otherwise the drawn bytes are discarded. + * This process is repeated until an acceptable byte string is drawn. + * The byte string drawn from the operation is interpreted as specified + * for the output produced by psa_export_key(). + * The following key types defined in this specification follow this scheme: + * + * - #PSA_KEY_TYPE_DES. + * Force-set the parity bits, but discard forbidden weak keys. + * For 2-key and 3-key triple-DES, the three keys are generated + * successively (for example, for 3-key triple-DES, + * if the first 8 bytes specify a weak key and the next 8 bytes do not, + * discard the first 8 bytes, use the next 8 bytes as the first key, + * and continue reading output from the operation to derive the other + * two keys). + * - Finite-field Diffie-Hellman keys (#PSA_KEY_TYPE_DH_KEY_PAIR(\c group) + * where \c group designates any Diffie-Hellman group) and + * ECC keys on a Weierstrass elliptic curve + * (#PSA_KEY_TYPE_ECC_KEY_PAIR(\c curve) where \c curve designates a + * Weierstrass curve). + * For these key types, interpret the byte string as integer + * in big-endian order. Discard it if it is not in the range + * [0, *N* - 2] where *N* is the boundary of the private key domain + * (the prime *p* for Diffie-Hellman, the subprime *q* for DSA, + * or the order of the curve's base point for ECC). + * Add 1 to the resulting integer and use this as the private key *x*. + * This method allows compliance to NIST standards, specifically + * the methods titled "key-pair generation by testing candidates" + * in NIST SP 800-56A §5.6.1.1.4 for Diffie-Hellman, + * in FIPS 186-4 §B.1.2 for DSA, and + * in NIST SP 800-56A §5.6.1.2.2 or + * FIPS 186-4 §B.4.2 for elliptic curve keys. + * + * - For other key types, including #PSA_KEY_TYPE_RSA_KEY_PAIR, + * the way in which the operation output is consumed is + * implementation-defined. + * + * In all cases, the data that is read is discarded from the operation. + * The operation's capacity is decreased by the number of bytes read. + * + * For algorithms that take an input step #PSA_KEY_DERIVATION_INPUT_SECRET, + * the input to that step must be provided with psa_key_derivation_input_key(). + * Future versions of this specification may include additional restrictions + * on the derived key based on the attributes and strength of the secret key. + * + * \param[in] attributes The attributes for the new key. + * \param[in,out] operation The key derivation operation object to read from. + * \param[out] handle On success, a handle to the newly created key. + * \c 0 on failure. + * + * \retval #PSA_SUCCESS + * Success. + * If the key is persistent, the key material and the key's metadata + * have been saved to persistent storage. + * \retval #PSA_ERROR_ALREADY_EXISTS + * This is an attempt to create a persistent key, and there is + * already a persistent key with the given identifier. + * \retval #PSA_ERROR_INSUFFICIENT_DATA + * There was not enough data to create the desired key. + * Note that in this case, no output is written to the output buffer. + * The operation's capacity is set to 0, thus subsequent calls to + * this function will not succeed, even with a smaller output buffer. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The key type or key size is not supported, either by the + * implementation in general or in this particular location. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The provided key attributes are not valid for the operation. + * \retval #PSA_ERROR_NOT_PERMITTED + * The #PSA_KEY_DERIVATION_INPUT_SECRET input was not provided through + * a key. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active and completed + * all required input steps). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_output_key( + const psa_key_attributes_t *attributes, + psa_key_derivation_operation_t *operation, + psa_key_handle_t *handle); + +/** Abort a key derivation operation. + * + * Aborting an operation frees all associated resources except for the \c + * operation structure itself. Once aborted, the operation object can be reused + * for another operation by calling psa_key_derivation_setup() again. + * + * This function may be called at any time after the operation + * object has been initialized as described in #psa_key_derivation_operation_t. + * + * In particular, it is valid to call psa_key_derivation_abort() twice, or to + * call psa_key_derivation_abort() on an operation that has not been set up. + * + * \param[in,out] operation The operation to abort. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_abort( + psa_key_derivation_operation_t *operation); + +/** Perform a key agreement and return the raw shared secret. + * + * \warning The raw result of a key agreement algorithm such as finite-field + * Diffie-Hellman or elliptic curve Diffie-Hellman has biases and should + * not be used directly as key material. It should instead be passed as + * input to a key derivation algorithm. To chain a key agreement with + * a key derivation, use psa_key_derivation_key_agreement() and other + * functions from the key derivation interface. + * + * \param alg The key agreement algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_RAW_KEY_AGREEMENT(\p alg) + * is true). + * \param private_key Handle to the private key to use. + * \param[in] peer_key Public key of the peer. It must be + * in the same format that psa_import_key() + * accepts. The standard formats for public + * keys are documented in the documentation + * of psa_export_public_key(). + * \param peer_key_length Size of \p peer_key in bytes. + * \param[out] output Buffer where the decrypted message is to + * be written. + * \param output_size Size of the \c output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p alg is not a key agreement algorithm + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p private_key is not compatible with \p alg, + * or \p peer_key is not valid for \p alg or not compatible with + * \p private_key. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \p output_size is too small + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not a supported key agreement algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_raw_key_agreement(psa_algorithm_t alg, + psa_key_handle_t private_key, + const uint8_t *peer_key, + size_t peer_key_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/**@}*/ + +/** \defgroup random Random generation + * @{ + */ + +/** + * \brief Generate random bytes. + * + * \warning This function **can** fail! Callers MUST check the return status + * and MUST NOT use the content of the output buffer if the return + * status is not #PSA_SUCCESS. + * + * \note To generate a key, use psa_generate_key() instead. + * + * \param[out] output Output buffer for the generated data. + * \param output_size Number of bytes to generate and output. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_generate_random(uint8_t *output, + size_t output_size); + +/** + * \brief Generate a key or key pair. + * + * The key is generated randomly. + * Its location, usage policy, type and size are taken from \p attributes. + * + * Implementations must reject an attempt to generate a key of size 0. + * + * The following type-specific considerations apply: + * - For RSA keys (#PSA_KEY_TYPE_RSA_KEY_PAIR), + * the public exponent is 65537. + * The modulus is a product of two probabilistic primes + * between 2^{n-1} and 2^n where n is the bit size specified in the + * attributes. + * + * \param[in] attributes The attributes for the new key. + * \param[out] handle On success, a handle to the newly created key. + * \c 0 on failure. + * + * \retval #PSA_SUCCESS + * Success. + * If the key is persistent, the key material and the key's metadata + * have been saved to persistent storage. + * \retval #PSA_ERROR_ALREADY_EXISTS + * This is an attempt to create a persistent key, and there is + * already a persistent key with the given identifier. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_generate_key(const psa_key_attributes_t *attributes, + psa_key_handle_t *handle); + +/**@}*/ + +#ifdef __cplusplus +} +#endif + +/* The file "crypto_sizes.h" contains definitions for size calculation + * macros whose definitions are implementation-specific. */ +#include "crypto_sizes.h" + +/* The file "crypto_struct.h" contains definitions for + * implementation-specific structs that are declared above. */ +#include "crypto_struct.h" + +/* The file "crypto_extra.h" contains vendor-specific definitions. This + * can include vendor-defined algorithms, extra functions, etc. */ +#include "crypto_extra.h" + +#endif /* PSA_CRYPTO_H */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/psa/crypto_accel_driver.h b/Android/Level4/app/src/main/c/mbedtls/include/psa/crypto_accel_driver.h new file mode 100644 index 0000000..1a193c5 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/psa/crypto_accel_driver.h @@ -0,0 +1,823 @@ +/** + * \file psa/crypto_accel_driver.h + * \brief PSA cryptography accelerator driver module + * + * This header declares types and function signatures for cryptography + * drivers that access key material directly. This is meant for + * on-chip cryptography accelerators. + * + * This file is part of the PSA Crypto Driver Model, containing functions for + * driver developers to implement to enable hardware to be called in a + * standardized way by a PSA Cryptographic API implementation. The functions + * comprising the driver model, which driver authors implement, are not + * intended to be called by application developers. + */ + +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 PSA_CRYPTO_ACCEL_DRIVER_H +#define PSA_CRYPTO_ACCEL_DRIVER_H + +#include "crypto_driver_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup driver_digest Hardware-Accelerated Message Digests + * + * Generation and authentication of Message Digests (aka hashes) must be done + * in parts using the following sequence: + * - `psa_drv_hash_setup_t` + * - `psa_drv_hash_update_t` + * - `psa_drv_hash_update_t` + * - ... + * - `psa_drv_hash_finish_t` + * + * If a previously started Message Digest operation needs to be terminated + * before the `psa_drv_hash_finish_t` operation is complete, it should be aborted + * by the `psa_drv_hash_abort_t`. Failure to do so may result in allocated + * resources not being freed or in other undefined behavior. + */ +/**@{*/ + +/** \brief The hardware-specific hash context structure + * + * The contents of this structure are implementation dependent and are + * therefore not described here + */ +typedef struct psa_drv_hash_context_s psa_drv_hash_context_t; + +/** \brief The function prototype for the start operation of a hash (message + * digest) operation + * + * Functions that implement this prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_hash__setup + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the underlying hash function + * + * \param[in,out] p_context A structure that will contain the + * hardware-specific hash context + * + * \retval PSA_SUCCESS Success. + */ +typedef psa_status_t (*psa_drv_hash_setup_t)(psa_drv_hash_context_t *p_context); + +/** \brief The function prototype for the update operation of a hash (message + * digest) operation + * + * Functions that implement this prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_hash__update + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the underlying algorithm + * + * \param[in,out] p_context A hardware-specific structure for the + * previously-established hash operation to be + * continued + * \param[in] p_input A buffer containing the message to be appended + * to the hash operation + * \param[in] input_length The size in bytes of the input message buffer + */ +typedef psa_status_t (*psa_drv_hash_update_t)(psa_drv_hash_context_t *p_context, + const uint8_t *p_input, + size_t input_length); + +/** \brief The function prototype for the finish operation of a hash (message + * digest) operation + * + * Functions that implement this prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_hash__finish + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the underlying algorithm + * + * \param[in,out] p_context A hardware-specific structure for the + * previously started hash operation to be + * fiinished + * \param[out] p_output A buffer where the generated digest will be + * placed + * \param[in] output_size The size in bytes of the buffer that has been + * allocated for the `p_output` buffer + * \param[out] p_output_length The number of bytes placed in `p_output` after + * success + * + * \retval PSA_SUCCESS + * Success. + */ +typedef psa_status_t (*psa_drv_hash_finish_t)(psa_drv_hash_context_t *p_context, + uint8_t *p_output, + size_t output_size, + size_t *p_output_length); + +/** \brief The function prototype for the abort operation of a hash (message + * digest) operation + * + * Functions that implement this prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_hash__abort + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the underlying algorithm + * + * \param[in,out] p_context A hardware-specific structure for the previously + * started hash operation to be aborted + */ +typedef void (*psa_drv_hash_abort_t)(psa_drv_hash_context_t *p_context); + +/**@}*/ + +/** \defgroup accel_mac Hardware-Accelerated Message Authentication Code + * Generation and authentication of Message Authentication Codes (MACs) using + * cryptographic accelerators can be done either as a single function call (via the + * `psa_drv_accel_mac_generate_t` or `psa_drv_accel_mac_verify_t` + * functions), or in parts using the following sequence: + * - `psa_drv_accel_mac_setup_t` + * - `psa_drv_accel_mac_update_t` + * - `psa_drv_accel_mac_update_t` + * - ... + * - `psa_drv_accel_mac_finish_t` or `psa_drv_accel_mac_finish_verify_t` + * + * If a previously started MAC operation needs to be terminated, it + * should be done so by the `psa_drv_accel_mac_abort_t`. Failure to do so may + * result in allocated resources not being freed or in other undefined + * behavior. + * + */ +/**@{*/ + +/** \brief The hardware-accelerator-specific MAC context structure + * + * The contents of this structure are implementation dependent and are + * therefore not described here. + */ +typedef struct psa_drv_accel_mac_context_s psa_drv_accel_mac_context_t; + +/** \brief The function prototype for the setup operation of a + * hardware-accelerated MAC operation + * + * Functions that implement this prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_accel_mac___setup + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the underlying primitive, and `MAC_VARIANT` + * is the specific variant of a MAC operation (such as HMAC or CMAC) + * + * \param[in,out] p_context A structure that will contain the + * hardware-specific MAC context + * \param[in] p_key A buffer containing the cleartext key material + * to be used in the operation + * \param[in] key_length The size in bytes of the key material + * + * \retval PSA_SUCCESS + * Success. + */ +typedef psa_status_t (*psa_drv_accel_mac_setup_t)(psa_drv_accel_mac_context_t *p_context, + const uint8_t *p_key, + size_t key_length); + +/** \brief The function prototype for the update operation of a + * hardware-accelerated MAC operation + * + * Functions that implement this prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_accel_mac___update + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the underlying algorithm, and `MAC_VARIANT` + * is the specific variant of a MAC operation (such as HMAC or CMAC) + * + * \param[in,out] p_context A hardware-specific structure for the + * previously-established MAC operation to be + * continued + * \param[in] p_input A buffer containing the message to be appended + * to the MAC operation + * \param[in] input_length The size in bytes of the input message buffer + */ +typedef psa_status_t (*psa_drv_accel_mac_update_t)(psa_drv_accel_mac_context_t *p_context, + const uint8_t *p_input, + size_t input_length); + +/** \brief The function prototype for the finish operation of a + * hardware-accelerated MAC operation + * + * Functions that implement this prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_accel_mac___finish + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the underlying algorithm, and `MAC_VARIANT` is + * the specific variant of a MAC operation (such as HMAC or CMAC) + * + * \param[in,out] p_context A hardware-specific structure for the + * previously started MAC operation to be + * finished + * \param[out] p_mac A buffer where the generated MAC will be placed + * \param[in] mac_length The size in bytes of the buffer that has been + * allocated for the `p_mac` buffer + * + * \retval PSA_SUCCESS + * Success. + */ +typedef psa_status_t (*psa_drv_accel_mac_finish_t)(psa_drv_accel_mac_context_t *p_context, + uint8_t *p_mac, + size_t mac_length); + +/** \brief The function prototype for the finish and verify operation of a + * hardware-accelerated MAC operation + * + * Functions that implement this prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_accel_mac___finish_verify + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the underlying algorithm, and `MAC_VARIANT` is + * the specific variant of a MAC operation (such as HMAC or CMAC) + * + * \param[in,out] p_context A hardware-specific structure for the + * previously started MAC operation to be + * verified and finished + * \param[in] p_mac A buffer containing the MAC that will be used + * for verification + * \param[in] mac_length The size in bytes of the data in the `p_mac` + * buffer + * + * \retval PSA_SUCCESS + * The operation completed successfully and the comparison matched + */ +typedef psa_status_t (*psa_drv_accel_mac_finish_verify_t)(psa_drv_accel_mac_context_t *p_context, + const uint8_t *p_mac, + size_t mac_length); + +/** \brief The function prototype for the abort operation for a previously + * started hardware-accelerated MAC operation + * + * Functions that implement this prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_accel_mac___abort + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the underlying algorithm, and `MAC_VARIANT` is + * the specific variant of a MAC operation (such as HMAC or CMAC) + * + * \param[in,out] p_context A hardware-specific structure for the + * previously started MAC operation to be + * aborted + * + */ +typedef psa_status_t (*psa_drv_accel_mac_abort_t)(psa_drv_accel_mac_context_t *p_context); + +/** \brief The function prototype for the one-shot operation of a + * hardware-accelerated MAC operation + * + * Functions that implement this prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_accel_mac__ + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the underlying algorithm, and `MAC_VARIANT` is + * the specific variant of a MAC operation (such as HMAC or CMAC) + * + * \param[in] p_input A buffer containing the data to be MACed + * \param[in] input_length The length in bytes of the `p_input` data + * \param[in] p_key A buffer containing the key material to be used + * for the MAC operation + * \param[in] key_length The length in bytes of the `p_key` data + * \param[in] alg The algorithm to be performed + * \param[out] p_mac The buffer where the resulting MAC will be placed + * upon success + * \param[in] mac_length The length in bytes of the `p_mac` buffer + */ +typedef psa_status_t (*psa_drv_accel_mac_t)(const uint8_t *p_input, + size_t input_length, + const uint8_t *p_key, + size_t key_length, + psa_algorithm_t alg, + uint8_t *p_mac, + size_t mac_length); + +/** \brief The function prototype for the one-shot hardware-accelerated MAC + * Verify operation + * + * Functions that implement this prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_accel_mac___verify + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the underlying algorithm, and `MAC_VARIANT` is + * the specific variant of a MAC operation (such as HMAC or CMAC) + * + * \param[in] p_input A buffer containing the data to be MACed + * \param[in] input_length The length in bytes of the `p_input` data + * \param[in] p_key A buffer containing the key material to be used + * for the MAC operation + * \param[in] key_length The length in bytes of the `p_key` data + * \param[in] alg The algorithm to be performed + * \param[in] p_mac The MAC data to be compared + * \param[in] mac_length The length in bytes of the `p_mac` buffer + * + * \retval PSA_SUCCESS + * The operation completed successfully and the comparison matched + */ +typedef psa_status_t (*psa_drv_accel_mac_verify_t)(const uint8_t *p_input, + size_t input_length, + const uint8_t *p_key, + size_t key_length, + psa_algorithm_t alg, + const uint8_t *p_mac, + size_t mac_length); +/**@}*/ + +/** \defgroup accel_cipher Hardware-Accelerated Block Ciphers + * Encryption and Decryption using hardware-acceleration in block modes other + * than ECB must be done in multiple parts, using the following flow: + * - `psa_drv_accel_ciphersetup_t` + * - `psa_drv_accel_cipher_set_iv_t` (optional depending upon block mode) + * - `psa_drv_accel_cipher_update_t` + * - `psa_drv_accel_cipher_update_t` + * - ... + * - `psa_drv_accel_cipher_finish_t` + * + * If a previously started hardware-accelerated Cipher operation needs to be + * terminated, it should be done so by the `psa_drv_accel_cipher_abort_t`. + * Failure to do so may result in allocated resources not being freed or in + * other undefined behavior. + */ +/**@{*/ + +/** \brief The hardware-accelerator-specific cipher context structure + * + * The contents of this structure are implementation dependent and are + * therefore not described here. + */ +typedef struct psa_drv_accel_cipher_context_s psa_drv_accel_cipher_context_t; + +/** \brief The function prototype for the setup operation of + * hardware-accelerated block cipher operations. + * Functions that implement this prototype should be named in the following + * conventions: + * ~~~~~~~~~~~~~{.c} + * psa_drv_accel_cipher_setup__ + * ~~~~~~~~~~~~~ + * Where + * - `CIPHER_NAME` is the name of the underlying block cipher (i.e. AES or DES) + * - `MODE` is the block mode of the cipher operation (i.e. CBC or CTR) + * + * For stream ciphers: + * ~~~~~~~~~~~~~{.c} + * psa_drv_accel_cipher_setup_ + * ~~~~~~~~~~~~~ + * Where `CIPHER_NAME` is the name of a stream cipher (i.e. RC4) + * + * \param[in,out] p_context A structure that will contain the + * hardware-specific cipher context + * \param[in] direction Indicates if the operation is an encrypt or a + * decrypt + * \param[in] p_key_data A buffer containing the cleartext key material + * to be used in the operation + * \param[in] key_data_size The size in bytes of the key material + * + * \retval PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_accel_cipher_setup_t)(psa_drv_accel_cipher_context_t *p_context, + psa_encrypt_or_decrypt_t direction, + const uint8_t *p_key_data, + size_t key_data_size); + +/** \brief The function prototype for the set initialization vector operation + * of hardware-accelerated block cipher operations + * Functions that implement this prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_accel_cipher_set_iv__ + * ~~~~~~~~~~~~~ + * Where + * - `CIPHER_NAME` is the name of the underlying block cipher (i.e. AES or DES) + * - `MODE` is the block mode of the cipher operation (i.e. CBC or CTR) + * + * \param[in,out] p_context A structure that contains the previously setup + * hardware-specific cipher context + * \param[in] p_iv A buffer containing the initialization vecotr + * \param[in] iv_length The size in bytes of the contents of `p_iv` + * + * \retval PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_accel_cipher_set_iv_t)(psa_drv_accel_cipher_context_t *p_context, + const uint8_t *p_iv, + size_t iv_length); + +/** \brief The function prototype for the update operation of + * hardware-accelerated block cipher operations. + * + * Functions that implement this prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_accel_cipher_update__ + * ~~~~~~~~~~~~~ + * Where + * - `CIPHER_NAME` is the name of the underlying block cipher (i.e. AES or DES) + * - `MODE` is the block mode of the cipher operation (i.e. CBC or CTR) + * + * \param[in,out] p_context A hardware-specific structure for the + * previously started cipher operation + * \param[in] p_input A buffer containing the data to be + * encrypted or decrypted + * \param[in] input_size The size in bytes of the `p_input` buffer + * \param[out] p_output A caller-allocated buffer where the + * generated output will be placed + * \param[in] output_size The size in bytes of the `p_output` buffer + * \param[out] p_output_length After completion, will contain the number + * of bytes placed in the `p_output` buffer + * + * \retval PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_accel_cipher_update_t)(psa_drv_accel_cipher_context_t *p_context, + const uint8_t *p_input, + size_t input_size, + uint8_t *p_output, + size_t output_size, + size_t *p_output_length); + +/** \brief The function prototype for the finish operation of + * hardware-accelerated block cipher operations. + * + * Functions that implement this prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_accel_cipher_finish__ + * ~~~~~~~~~~~~~ + * Where + * - `CIPHER_NAME` is the name of the underlying block cipher (i.e. AES or DES) + * - `MODE` is the block mode of the cipher operation (i.e. CBC or CTR) + * + * \param[in,out] p_context A hardware-specific structure for the + * previously started cipher operation + * \param[out] p_output A caller-allocated buffer where the generated + * output will be placed + * \param[in] output_size The size in bytes of the `p_output` buffer + * \param[out] p_output_length After completion, will contain the number of + * bytes placed in the `p_output` buffer + * + * \retval PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_accel_cipher_finish_t)(psa_drv_accel_cipher_context_t *p_context, + uint8_t *p_output, + size_t output_size, + size_t *p_output_length); + +/** \brief The function prototype for the abort operation of + * hardware-accelerated block cipher operations. + * + * Functions that implement the following prototype should be named in the + * following convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_accel_cipher_abort__ + * ~~~~~~~~~~~~~ + * Where + * - `CIPHER_NAME` is the name of the underlying block cipher (i.e. AES or DES) + * - `MODE` is the block mode of the cipher operation (i.e. CBC or CTR) + * + * \param[in,out] p_context A hardware-specific structure for the + * previously started cipher operation + * + * \retval PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_accel_cipher_abort_t)(psa_drv_accel_cipher_context_t *p_context); + +/**@}*/ + +/** \defgroup accel_aead Hardware-Accelerated Authenticated Encryption with Additional Data + * + * Hardware-accelerated Authenticated Encryption with Additional Data (AEAD) + * operations must be done in one function call. While this creates a burden + * for implementers as there must be sufficient space in memory for the entire + * message, it prevents decrypted data from being made available before the + * authentication operation is complete and the data is known to be authentic. + */ +/**@{*/ + +/** \brief The function prototype for the hardware-accelerated authenticated + * encryption operation. + * + * Functions that implement this prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_accel_aead__encrypt + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the AEAD algorithm + * + * \param[in] p_key A pointer to the key material + * \param[in] key_length The size in bytes of the key material + * \param[in] alg The AEAD algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(`alg`) is true) + * \param[in] nonce Nonce or IV to use + * \param[in] nonce_length Size of the `nonce` buffer in bytes + * \param[in] additional_data Additional data that will be MACed + * but not encrypted. + * \param[in] additional_data_length Size of `additional_data` in bytes + * \param[in] plaintext Data that will be MACed and + * encrypted. + * \param[in] plaintext_length Size of `plaintext` in bytes + * \param[out] ciphertext Output buffer for the authenticated and + * encrypted data. The additional data is + * not part of this output. For algorithms + * where the encrypted data and the + * authentication tag are defined as + * separate outputs, the authentication + * tag is appended to the encrypted data. + * \param[in] ciphertext_size Size of the `ciphertext` buffer in + * bytes + * This must be at least + * #PSA_AEAD_ENCRYPT_OUTPUT_SIZE(`alg`, + * `plaintext_length`). + * \param[out] ciphertext_length On success, the size of the output in + * the `ciphertext` buffer + * + * \retval #PSA_SUCCESS + * + */ +typedef psa_status_t (*psa_drv_accel_aead_encrypt_t)(const uint8_t *p_key, + size_t key_length, + psa_algorithm_t alg, + const uint8_t *nonce, + size_t nonce_length, + const uint8_t *additional_data, + size_t additional_data_length, + const uint8_t *plaintext, + size_t plaintext_length, + uint8_t *ciphertext, + size_t ciphertext_size, + size_t *ciphertext_length); + +/** \brief The function prototype for the hardware-accelerated authenticated + * decryption operation. + * + * Functions that implement this prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_accel_aead__decrypt + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the AEAD algorithm + * \param[in] p_key A pointer to the key material + * \param[in] key_length The size in bytes of the key material + * \param[in] alg The AEAD algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(`alg`) is true) + * \param[in] nonce Nonce or IV to use + * \param[in] nonce_length Size of the `nonce` buffer in bytes + * \param[in] additional_data Additional data that has been MACed + * but not encrypted + * \param[in] additional_data_length Size of `additional_data` in bytes + * \param[in] ciphertext Data that has been MACed and + * encrypted + * For algorithms where the encrypted data + * and the authentication tag are defined + * as separate inputs, the buffer must + * contain the encrypted data followed by + * the authentication tag. + * \param[in] ciphertext_length Size of `ciphertext` in bytes + * \param[out] plaintext Output buffer for the decrypted data + * \param[in] plaintext_size Size of the `plaintext` buffer in + * bytes + * This must be at least + * #PSA_AEAD_DECRYPT_OUTPUT_SIZE(`alg`, + * `ciphertext_length`). + * \param[out] plaintext_length On success, the size of the output + * in the \b plaintext buffer + * + * \retval #PSA_SUCCESS + * Success. + */ +typedef psa_status_t (*psa_drv_accel_aead_decrypt_t)(const uint8_t *p_key, + size_t key_length, + psa_algorithm_t alg, + const uint8_t *nonce, + size_t nonce_length, + const uint8_t *additional_data, + size_t additional_data_length, + const uint8_t *ciphertext, + size_t ciphertext_length, + uint8_t *plaintext, + size_t plaintext_size, + size_t *plaintext_length); + +/**@}*/ + +/** \defgroup accel_asymmetric Hardware-Accelerated Asymmetric Cryptography + * + * Since the amount of data that can (or should) be encrypted or signed using + * asymmetric keys is limited by the key size, hardware-accelerated asymmetric + * key operations must be done in single function calls. + */ +/**@{*/ + + +/** + * \brief The function prototype for the hardware-accelerated asymmetric sign + * operation. + * + * Functions that implement this prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_accel_asymmetric__sign + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the signing algorithm + * + * This function supports any asymmetric-key output from psa_export_key() as + * the buffer in \p p_key. Refer to the documentation of \ref + * psa_export_key() for the formats. + * + * \param[in] p_key A buffer containing the private key + * material + * \param[in] key_size The size in bytes of the `p_key` data + * \param[in] alg A signature algorithm that is compatible + * with the type of `p_key` + * \param[in] p_hash The hash or message to sign + * \param[in] hash_length Size of the `p_hash` buffer in bytes + * \param[out] p_signature Buffer where the signature is to be written + * \param[in] signature_size Size of the `p_signature` buffer in bytes + * \param[out] p_signature_length On success, the number of bytes + * that make up the returned signature value + * + * \retval PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_accel_asymmetric_sign_t)(const uint8_t *p_key, + size_t key_size, + psa_algorithm_t alg, + psa_key_type_t key_type, + const uint8_t *p_hash, + size_t hash_length, + uint8_t *p_signature, + size_t signature_size, + size_t *p_signature_length); + +/** + * \brief The function prototype for the hardware-accelerated signature verify + * operation + * + * Functions that implement this prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_accel_asymmetric__verify + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the signing algorithm + * + * This function supports any output from \ref psa_export_public_key() as the + * buffer in \p p_key. Refer to the documentation of \ref + * psa_export_public_key() for the format of public keys and to the + * documentation of \ref psa_export_key() for the format for other key types. + * + * \param[in] p_key A buffer containing the public key material + * \param[in] key_size The size in bytes of the `p_key` data + * \param[in] alg A signature algorithm that is compatible with + * the type of `key` + * \param[in] p_hash The hash or message whose signature is to be + * verified + * \param[in] hash_length Size of the `p_hash` buffer in bytes + * \param[in] p_signature Buffer containing the signature to verify + * \param[in] signature_length Size of the `p_signature` buffer in bytes + * + * \retval PSA_SUCCESS + * The signature is valid. + */ +typedef psa_status_t (*psa_drv_accel_asymmetric_verify_t)(const uint8_t *p_key, + size_t key_size, + psa_algorithm_t alg, + psa_key_type_t key_type, + const uint8_t *p_hash, + size_t hash_length, + const uint8_t *p_signature, + size_t signature_length); + +/** + * \brief The function prototype for the hardware-accelerated asymmetric + * encrypt operation + * + * Functions that implement this prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_accel_asymmetric__encrypt + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the encryption algorithm + * + * This function supports any output from \ref psa_export_public_key() as the + * buffer in \p p_key. Refer to the documentation of \ref + * psa_export_public_key() for the format of public keys and to the + * documentation of \ref psa_export_key() for the format for other key types. + * + * \param[in] p_key A buffer containing the public key material + * \param[in] key_size The size in bytes of the `p_key` data + * \param[in] alg An asymmetric encryption algorithm that is + * compatible with the type of `key` + * \param[in] p_input The message to encrypt + * \param[in] input_length Size of the `p_input` buffer in bytes + * \param[in] p_salt A salt or label, if supported by the + * encryption algorithm + * If the algorithm does not support a + * salt, pass `NULL` + * If the algorithm supports an optional + * salt and you do not want to pass a salt, + * pass `NULL`. + * For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is + * supported. + * \param[in] salt_length Size of the `p_salt` buffer in bytes + * If `p_salt` is `NULL`, pass 0. + * \param[out] p_output Buffer where the encrypted message is to + * be written + * \param[in] output_size Size of the `p_output` buffer in bytes + * \param[out] p_output_length On success, the number of bytes + * that make up the returned output + * + * \retval PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_accel_asymmetric_encrypt_t)(const uint8_t *p_key, + size_t key_size, + psa_algorithm_t alg, + psa_key_type_t key_type, + const uint8_t *p_input, + size_t input_length, + const uint8_t *p_salt, + size_t salt_length, + uint8_t *p_output, + size_t output_size, + size_t *p_output_length); + +/** + * \brief The function prototype for the hardware=acce;erated asymmetric + * decrypt operation + * + * Functions that implement this prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_accel_asymmetric__decrypt + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the encryption algorithm + * + * This function supports any asymmetric-key output from psa_export_key() as + * the buffer in \p p_key. Refer to the documentation of \ref + * psa_export_key() for the formats. + * + * \param[in] p_key A buffer containing the private key material + * \param[in] key_size The size in bytes of the `p_key` data + * \param[in] alg An asymmetric encryption algorithm that is + * compatible with the type of `key` + * \param[in] p_input The message to decrypt + * \param[in] input_length Size of the `p_input` buffer in bytes + * \param[in] p_salt A salt or label, if supported by the + * encryption algorithm + * If the algorithm does not support a + * salt, pass `NULL`. + * If the algorithm supports an optional + * salt and you do not want to pass a salt, + * pass `NULL`. + * For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is + * supported + * \param[in] salt_length Size of the `p_salt` buffer in bytes + * If `p_salt` is `NULL`, pass 0 + * \param[out] p_output Buffer where the decrypted message is to + * be written + * \param[in] output_size Size of the `p_output` buffer in bytes + * \param[out] p_output_length On success, the number of bytes + * that make up the returned output + * + * \retval PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_accel_asymmetric_decrypt_t)(const uint8_t *p_key, + size_t key_size, + psa_algorithm_t alg, + psa_key_type_t key_type, + const uint8_t *p_input, + size_t input_length, + const uint8_t *p_salt, + size_t salt_length, + uint8_t *p_output, + size_t output_size, + size_t *p_output_length); + +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* PSA_CRYPTO_ACCEL_DRIVER_H */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/psa/crypto_compat.h b/Android/Level4/app/src/main/c/mbedtls/include/psa/crypto_compat.h new file mode 100644 index 0000000..4b607b6 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/psa/crypto_compat.h @@ -0,0 +1,230 @@ +/** + * \file psa/crypto_compat.h + * + * \brief PSA cryptography module: Backward compatibility aliases + * + * This header declares alternative names for macro and functions. + * New application code should not use these names. + * These names may be removed in a future version of Mbed Crypto. + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 PSA_CRYPTO_COMPAT_H +#define PSA_CRYPTO_COMPAT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + +/* + * Mechanism for declaring deprecated values + */ +#if defined(MBEDTLS_DEPRECATED_WARNING) && !defined(MBEDTLS_PSA_DEPRECATED) +#define MBEDTLS_PSA_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_PSA_DEPRECATED +#endif + +typedef MBEDTLS_PSA_DEPRECATED size_t mbedtls_deprecated_size_t; +typedef MBEDTLS_PSA_DEPRECATED psa_status_t mbedtls_deprecated_psa_status_t; +typedef MBEDTLS_PSA_DEPRECATED psa_key_usage_t mbedtls_deprecated_psa_key_usage_t; +typedef MBEDTLS_PSA_DEPRECATED psa_ecc_family_t mbedtls_deprecated_psa_ecc_family_t; +typedef MBEDTLS_PSA_DEPRECATED psa_dh_family_t mbedtls_deprecated_psa_dh_family_t; +typedef MBEDTLS_PSA_DEPRECATED psa_ecc_family_t psa_ecc_curve_t; +typedef MBEDTLS_PSA_DEPRECATED psa_dh_family_t psa_dh_group_t; + +#define PSA_KEY_TYPE_GET_CURVE PSA_KEY_TYPE_ECC_GET_FAMILY +#define PSA_KEY_TYPE_GET_GROUP PSA_KEY_TYPE_DH_GET_FAMILY + +#define MBEDTLS_DEPRECATED_CONSTANT( type, value ) \ + ( (mbedtls_deprecated_##type) ( value ) ) + +/* + * Deprecated PSA Crypto error code definitions (PSA Crypto API <= 1.0 beta2) + */ +#define PSA_ERROR_UNKNOWN_ERROR \ + MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_GENERIC_ERROR ) +#define PSA_ERROR_OCCUPIED_SLOT \ + MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_ALREADY_EXISTS ) +#define PSA_ERROR_EMPTY_SLOT \ + MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_DOES_NOT_EXIST ) +#define PSA_ERROR_INSUFFICIENT_CAPACITY \ + MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_INSUFFICIENT_DATA ) +#define PSA_ERROR_TAMPERING_DETECTED \ + MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_CORRUPTION_DETECTED ) + +/* + * Deprecated PSA Crypto numerical encodings (PSA Crypto API <= 1.0 beta3) + */ +#define PSA_KEY_USAGE_SIGN \ + MBEDTLS_DEPRECATED_CONSTANT( psa_key_usage_t, PSA_KEY_USAGE_SIGN_HASH ) +#define PSA_KEY_USAGE_VERIFY \ + MBEDTLS_DEPRECATED_CONSTANT( psa_key_usage_t, PSA_KEY_USAGE_VERIFY_HASH ) + +/* + * Deprecated PSA Crypto size calculation macros (PSA Crypto API <= 1.0 beta3) + */ +#define PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE \ + MBEDTLS_DEPRECATED_CONSTANT( size_t, PSA_SIGNATURE_MAX_SIZE ) +#define PSA_ASYMMETRIC_SIGN_OUTPUT_SIZE( key_type, key_bits, alg ) \ + MBEDTLS_DEPRECATED_CONSTANT( size_t, PSA_SIGN_OUTPUT_SIZE( key_type, key_bits, alg ) ) + +/* + * Deprecated PSA Crypto function names (PSA Crypto API <= 1.0 beta3) + */ +MBEDTLS_PSA_DEPRECATED static inline psa_status_t psa_asymmetric_sign( psa_key_handle_t key, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + uint8_t *signature, + size_t signature_size, + size_t *signature_length ) +{ + return psa_sign_hash( key, alg, hash, hash_length, signature, signature_size, signature_length ); +} + +MBEDTLS_PSA_DEPRECATED static inline psa_status_t psa_asymmetric_verify( psa_key_handle_t key, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + const uint8_t *signature, + size_t signature_length ) +{ + return psa_verify_hash( key, alg, hash, hash_length, signature, signature_length ); +} + + + +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/* + * Size-specific elliptic curve families. + */ +#define PSA_ECC_CURVE_SECP160K1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECP_K1 ) +#define PSA_ECC_CURVE_SECP192K1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECP_K1 ) +#define PSA_ECC_CURVE_SECP224K1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECP_K1 ) +#define PSA_ECC_CURVE_SECP256K1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECP_K1 ) +#define PSA_ECC_CURVE_SECP160R1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECP_R1 ) +#define PSA_ECC_CURVE_SECP192R1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECP_R1 ) +#define PSA_ECC_CURVE_SECP224R1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECP_R1 ) +#define PSA_ECC_CURVE_SECP256R1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECP_R1 ) +#define PSA_ECC_CURVE_SECP384R1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECP_R1 ) +#define PSA_ECC_CURVE_SECP521R1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECP_R1 ) +#define PSA_ECC_CURVE_SECP160R2 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECP_R2 ) +#define PSA_ECC_CURVE_SECT163K1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECT_K1 ) +#define PSA_ECC_CURVE_SECT233K1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECT_K1 ) +#define PSA_ECC_CURVE_SECT239K1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECT_K1 ) +#define PSA_ECC_CURVE_SECT283K1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECT_K1 ) +#define PSA_ECC_CURVE_SECT409K1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECT_K1 ) +#define PSA_ECC_CURVE_SECT571K1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECT_K1 ) +#define PSA_ECC_CURVE_SECT163R1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECT_R1 ) +#define PSA_ECC_CURVE_SECT193R1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECT_R1 ) +#define PSA_ECC_CURVE_SECT233R1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECT_R1 ) +#define PSA_ECC_CURVE_SECT283R1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECT_R1 ) +#define PSA_ECC_CURVE_SECT409R1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECT_R1 ) +#define PSA_ECC_CURVE_SECT571R1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECT_R1 ) +#define PSA_ECC_CURVE_SECT163R2 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECT_R2 ) +#define PSA_ECC_CURVE_SECT193R2 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECT_R2 ) +#define PSA_ECC_CURVE_BRAINPOOL_P256R1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_BRAINPOOL_P_R1 ) +#define PSA_ECC_CURVE_BRAINPOOL_P384R1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_BRAINPOOL_P_R1 ) +#define PSA_ECC_CURVE_BRAINPOOL_P512R1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_BRAINPOOL_P_R1 ) +#define PSA_ECC_CURVE_CURVE25519 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_MONTGOMERY ) +#define PSA_ECC_CURVE_CURVE448 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_MONTGOMERY ) + +/* + * Curves that changed name due to PSA specification. + */ +#define PSA_ECC_CURVE_SECP_K1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECP_K1 ) +#define PSA_ECC_CURVE_SECP_R1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECP_R1 ) +#define PSA_ECC_CURVE_SECP_R2 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECP_R2 ) +#define PSA_ECC_CURVE_SECT_K1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECT_K1 ) +#define PSA_ECC_CURVE_SECT_R1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECT_R1 ) +#define PSA_ECC_CURVE_SECT_R2 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_SECT_R2 ) +#define PSA_ECC_CURVE_BRAINPOOL_P_R1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_BRAINPOOL_P_R1 ) +#define PSA_ECC_CURVE_MONTGOMERY \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_family_t, PSA_ECC_FAMILY_MONTGOMERY ) + +/* + * Finite-field Diffie-Hellman families. + */ +#define PSA_DH_GROUP_FFDHE2048 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_dh_family_t, PSA_DH_FAMILY_RFC7919 ) +#define PSA_DH_GROUP_FFDHE3072 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_dh_family_t, PSA_DH_FAMILY_RFC7919 ) +#define PSA_DH_GROUP_FFDHE4096 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_dh_family_t, PSA_DH_FAMILY_RFC7919 ) +#define PSA_DH_GROUP_FFDHE6144 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_dh_family_t, PSA_DH_FAMILY_RFC7919 ) +#define PSA_DH_GROUP_FFDHE8192 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_dh_family_t, PSA_DH_FAMILY_RFC7919 ) + +/* + * Diffie-Hellman families that changed name due to PSA specification. + */ +#define PSA_DH_GROUP_RFC7919 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_dh_family_t, PSA_DH_FAMILY_RFC7919 ) +#define PSA_DH_GROUP_CUSTOM \ + MBEDTLS_DEPRECATED_CONSTANT( psa_dh_family_t, PSA_DH_FAMILY_CUSTOM ) + +#ifdef __cplusplus +} +#endif + +#endif /* PSA_CRYPTO_COMPAT_H */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/psa/crypto_config.h b/Android/Level4/app/src/main/c/mbedtls/include/psa/crypto_config.h new file mode 100644 index 0000000..8dbb18d --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/psa/crypto_config.h @@ -0,0 +1,56 @@ +/** + * \file psa/crypto_config.h + * \brief PSA crypto configuration options (set of defines) + * + */ +#if defined(MBEDTLS_PSA_CRYPTO_CONFIG) +/** + * When #MBEDTLS_PSA_CRYPTO_CONFIG is enabled in config.h, + * this file determines which cryptographic mechanisms are enabled + * through the PSA Cryptography API (\c psa_xxx() functions). + * + * To enable a cryptographic mechanism, uncomment the definition of + * the corresponding \c PSA_WANT_xxx preprocessor symbol. + * To disable a cryptographic mechanism, comment out the definition of + * the corresponding \c PSA_WANT_xxx preprocessor symbol. + * The names of cryptographic mechanisms correspond to values + * defined in psa/crypto_values.h, with the prefix \c PSA_WANT_ instead + * of \c PSA_. + * + * Note that many cryptographic mechanisms involve two symbols: one for + * the key type (\c PSA_WANT_KEY_TYPE_xxx) and one for the algorithm + * (\c PSA_WANT_ALG_xxx). Mechanisms with additional parameters may involve + * additional symbols. + */ +#else +/** + * When \c MBEDTLS_PSA_CRYPTO_CONFIG is disabled in config.h, + * this file is not used, and cryptographic mechanisms are supported + * through the PSA API if and only if they are supported through the + * mbedtls_xxx API. + */ +#endif +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 PSA_CRYPTO_CONFIG_H +#define PSA_CRYPTO_CONFIG_H + +#define PSA_WANT_ALG_ECDSA 1 +#define PSA_WANT_ALG_DETERMINISTIC_ECDSA 1 + +#endif /* PSA_CRYPTO_CONFIG_H */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/psa/crypto_driver_common.h b/Android/Level4/app/src/main/c/mbedtls/include/psa/crypto_driver_common.h new file mode 100644 index 0000000..2ce75d2 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/psa/crypto_driver_common.h @@ -0,0 +1,54 @@ +/** + * \file psa/crypto_driver_common.h + * \brief Definitions for all PSA crypto drivers + * + * This file contains common definitions shared by all PSA crypto drivers. + * Do not include it directly: instead, include the header file(s) for + * the type(s) of driver that you are implementing. For example, if + * you are writing a driver for a chip that provides both a hardware + * random generator and an accelerator for some cryptographic algorithms, + * include `psa/crypto_entropy_driver.h` and `psa/crypto_accel_driver.h`. + * + * This file is part of the PSA Crypto Driver Model, containing functions for + * driver developers to implement to enable hardware to be called in a + * standardized way by a PSA Cryptographic API implementation. The functions + * comprising the driver model, which driver authors implement, are not + * intended to be called by application developers. + */ + +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 PSA_CRYPTO_DRIVER_COMMON_H +#define PSA_CRYPTO_DRIVER_COMMON_H + +#include +#include + +/* Include type definitions (psa_status_t, psa_algorithm_t, + * psa_key_type_t, etc.) and macros to build and analyze values + * of these types. */ +#include "crypto_types.h" +#include "crypto_values.h" + +/** For encrypt-decrypt functions, whether the operation is an encryption + * or a decryption. */ +typedef enum { + PSA_CRYPTO_DRIVER_DECRYPT, + PSA_CRYPTO_DRIVER_ENCRYPT +} psa_encrypt_or_decrypt_t; + +#endif /* PSA_CRYPTO_DRIVER_COMMON_H */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/psa/crypto_entropy_driver.h b/Android/Level4/app/src/main/c/mbedtls/include/psa/crypto_entropy_driver.h new file mode 100644 index 0000000..6175044 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/psa/crypto_entropy_driver.h @@ -0,0 +1,108 @@ +/** + * \file psa/crypto_entropy_driver.h + * \brief PSA entropy source driver module + * + * This header declares types and function signatures for entropy sources. + * + * This file is part of the PSA Crypto Driver Model, containing functions for + * driver developers to implement to enable hardware to be called in a + * standardized way by a PSA Cryptographic API implementation. The functions + * comprising the driver model, which driver authors implement, are not + * intended to be called by application developers. + */ + +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 PSA_CRYPTO_ENTROPY_DRIVER_H +#define PSA_CRYPTO_ENTROPY_DRIVER_H + +#include "crypto_driver_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup driver_rng Entropy Generation + */ +/**@{*/ + +/** \brief Initialize an entropy driver + * + * + * \param[in,out] p_context A hardware-specific structure + * containing any context information for + * the implementation + * + * \retval PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_entropy_init_t)(void *p_context); + +/** \brief Get a specified number of bits from the entropy source + * + * It retrives `buffer_size` bytes of data from the entropy source. The entropy + * source will always fill the provided buffer to its full size, however, most + * entropy sources have biases, and the actual amount of entropy contained in + * the buffer will be less than the number of bytes. + * The driver will return the actual number of bytes of entropy placed in the + * buffer in `p_received_entropy_bytes`. + * A PSA Crypto API implementation will likely feed the output of this function + * into a Digital Random Bit Generator (DRBG), and typically has a minimum + * amount of entropy that it needs. + * To accomplish this, the PSA Crypto implementation should be designed to call + * this function multiple times until it has received the required amount of + * entropy from the entropy source. + * + * \param[in,out] p_context A hardware-specific structure + * containing any context information + * for the implementation + * \param[out] p_buffer A caller-allocated buffer for the + * retrieved entropy to be placed in + * \param[in] buffer_size The allocated size of `p_buffer` + * \param[out] p_received_entropy_bits The amount of entropy (in bits) + * actually provided in `p_buffer` + * + * \retval PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_entropy_get_bits_t)(void *p_context, + uint8_t *p_buffer, + uint32_t buffer_size, + uint32_t *p_received_entropy_bits); + +/** + * \brief A struct containing all of the function pointers needed to interface + * to an entropy source + * + * PSA Crypto API implementations should populate instances of the table as + * appropriate upon startup. + * + * If one of the functions is not implemented, it should be set to NULL. + */ +typedef struct { + /** The driver-specific size of the entropy context */ + const size_t context_size; + /** Function that performs initialization for the entropy source */ + psa_drv_entropy_init_t p_init; + /** Function that performs the get_bits operation for the entropy source */ + psa_drv_entropy_get_bits_t p_get_bits; +} psa_drv_entropy_t; +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* PSA_CRYPTO_ENTROPY_DRIVER_H */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/psa/crypto_extra.h b/Android/Level4/app/src/main/c/mbedtls/include/psa/crypto_extra.h new file mode 100644 index 0000000..71adb93 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/psa/crypto_extra.h @@ -0,0 +1,654 @@ +/** + * \file psa/crypto_extra.h + * + * \brief PSA cryptography module: Mbed TLS vendor extensions + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. + * + * This file is reserved for vendor-specific definitions. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 PSA_CRYPTO_EXTRA_H +#define PSA_CRYPTO_EXTRA_H + +#include "mbedtls/platform_util.h" + +#include "crypto_compat.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* UID for secure storage seed */ +#define PSA_CRYPTO_ITS_RANDOM_SEED_UID 0xFFFFFF52 + + +/** \addtogroup attributes + * @{ + */ + +/** \brief Declare the enrollment algorithm for a key. + * + * An operation on a key may indifferently use the algorithm set with + * psa_set_key_algorithm() or with this function. + * + * \param[out] attributes The attribute structure to write to. + * \param alg2 A second algorithm that the key may be used + * for, in addition to the algorithm set with + * psa_set_key_algorithm(). + * + * \warning Setting an enrollment algorithm is not recommended, because + * using the same key with different algorithms can allow some + * attacks based on arithmetic relations between different + * computations made with the same key, or can escalate harmless + * side channels into exploitable ones. Use this function only + * if it is necessary to support a protocol for which it has been + * verified that the usage of the key with multiple algorithms + * is safe. + */ +static inline void psa_set_key_enrollment_algorithm( + psa_key_attributes_t *attributes, + psa_algorithm_t alg2) +{ + attributes->core.policy.alg2 = alg2; +} + +/** Retrieve the enrollment algorithm policy from key attributes. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The enrollment algorithm stored in the attribute structure. + */ +static inline psa_algorithm_t psa_get_key_enrollment_algorithm( + const psa_key_attributes_t *attributes) +{ + return( attributes->core.policy.alg2 ); +} + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + +/** Retrieve the slot number where a key is stored. + * + * A slot number is only defined for keys that are stored in a secure + * element. + * + * This information is only useful if the secure element is not entirely + * managed through the PSA Cryptography API. It is up to the secure + * element driver to decide how PSA slot numbers map to any other interface + * that the secure element may have. + * + * \param[in] attributes The key attribute structure to query. + * \param[out] slot_number On success, the slot number containing the key. + * + * \retval #PSA_SUCCESS + * The key is located in a secure element, and \p *slot_number + * indicates the slot number that contains it. + * \retval #PSA_ERROR_NOT_PERMITTED + * The caller is not permitted to query the slot number. + * Mbed Crypto currently does not return this error. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The key is not located in a secure element. + */ +psa_status_t psa_get_key_slot_number( + const psa_key_attributes_t *attributes, + psa_key_slot_number_t *slot_number ); + +/** Choose the slot number where a key is stored. + * + * This function declares a slot number in the specified attribute + * structure. + * + * A slot number is only meaningful for keys that are stored in a secure + * element. It is up to the secure element driver to decide how PSA slot + * numbers map to any other interface that the secure element may have. + * + * \note Setting a slot number in key attributes for a key creation can + * cause the following errors when creating the key: + * - #PSA_ERROR_NOT_SUPPORTED if the selected secure element does + * not support choosing a specific slot number. + * - #PSA_ERROR_NOT_PERMITTED if the caller is not permitted to + * choose slot numbers in general or to choose this specific slot. + * - #PSA_ERROR_INVALID_ARGUMENT if the chosen slot number is not + * valid in general or not valid for this specific key. + * - #PSA_ERROR_ALREADY_EXISTS if there is already a key in the + * selected slot. + * + * \param[out] attributes The attribute structure to write to. + * \param slot_number The slot number to set. + */ +static inline void psa_set_key_slot_number( + psa_key_attributes_t *attributes, + psa_key_slot_number_t slot_number ) +{ + attributes->core.flags |= MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER; + attributes->slot_number = slot_number; +} + +/** Remove the slot number attribute from a key attribute structure. + * + * This function undoes the action of psa_set_key_slot_number(). + * + * \param[out] attributes The attribute structure to write to. + */ +static inline void psa_clear_key_slot_number( + psa_key_attributes_t *attributes ) +{ + attributes->core.flags &= ~MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER; +} + +/** Register a key that is already present in a secure element. + * + * The key must be located in a secure element designated by the + * lifetime field in \p attributes, in the slot set with + * psa_set_key_slot_number() in the attribute structure. + * This function makes the key available through the key identifier + * specified in \p attributes. + * + * \param[in] attributes The attributes of the existing key. + * + * \retval #PSA_SUCCESS + * The key was successfully registered. + * Note that depending on the design of the driver, this may or may + * not guarantee that a key actually exists in the designated slot + * and is compatible with the specified attributes. + * \retval #PSA_ERROR_ALREADY_EXISTS + * There is already a key with the identifier specified in + * \p attributes. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The secure element driver for the specified lifetime does not + * support registering a key. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p attributes specifies a lifetime which is not located + * in a secure element. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * No slot number is specified in \p attributes, + * or the specified slot number is not valid. + * \retval #PSA_ERROR_NOT_PERMITTED + * The caller is not authorized to register the specified key slot. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t mbedtls_psa_register_se_key( + const psa_key_attributes_t *attributes); + +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + +/**@}*/ + +/** + * \brief Library deinitialization. + * + * This function clears all data associated with the PSA layer, + * including the whole key store. + * + * This is an Mbed TLS extension. + */ +void mbedtls_psa_crypto_free( void ); + +/** \brief Statistics about + * resource consumption related to the PSA keystore. + * + * \note The content of this structure is not part of the stable API and ABI + * of Mbed Crypto and may change arbitrarily from version to version. + */ +typedef struct mbedtls_psa_stats_s +{ + /** Number of slots containing key material for a volatile key. */ + size_t volatile_slots; + /** Number of slots containing key material for a key which is in + * internal persistent storage. */ + size_t persistent_slots; + /** Number of slots containing a reference to a key in a + * secure element. */ + size_t external_slots; + /** Number of slots which are occupied, but do not contain + * key material yet. */ + size_t half_filled_slots; + /** Number of slots that contain cache data. */ + size_t cache_slots; + /** Number of slots that are not used for anything. */ + size_t empty_slots; + /** Largest key id value among open keys in internal persistent storage. */ + psa_key_id_t max_open_internal_key_id; + /** Largest key id value among open keys in secure elements. */ + psa_key_id_t max_open_external_key_id; +} mbedtls_psa_stats_t; + +/** \brief Get statistics about + * resource consumption related to the PSA keystore. + * + * \note When Mbed Crypto is built as part of a service, with isolation + * between the application and the keystore, the service may or + * may not expose this function. + */ +void mbedtls_psa_get_stats( mbedtls_psa_stats_t *stats ); + +/** + * \brief Inject an initial entropy seed for the random generator into + * secure storage. + * + * This function injects data to be used as a seed for the random generator + * used by the PSA Crypto implementation. On devices that lack a trusted + * entropy source (preferably a hardware random number generator), + * the Mbed PSA Crypto implementation uses this value to seed its + * random generator. + * + * On devices without a trusted entropy source, this function must be + * called exactly once in the lifetime of the device. On devices with + * a trusted entropy source, calling this function is optional. + * In all cases, this function may only be called before calling any + * other function in the PSA Crypto API, including psa_crypto_init(). + * + * When this function returns successfully, it populates a file in + * persistent storage. Once the file has been created, this function + * can no longer succeed. + * + * If any error occurs, this function does not change the system state. + * You can call this function again after correcting the reason for the + * error if possible. + * + * \warning This function **can** fail! Callers MUST check the return status. + * + * \warning If you use this function, you should use it as part of a + * factory provisioning process. The value of the injected seed + * is critical to the security of the device. It must be + * *secret*, *unpredictable* and (statistically) *unique per device*. + * You should be generate it randomly using a cryptographically + * secure random generator seeded from trusted entropy sources. + * You should transmit it securely to the device and ensure + * that its value is not leaked or stored anywhere beyond the + * needs of transmitting it from the point of generation to + * the call of this function, and erase all copies of the value + * once this function returns. + * + * This is an Mbed TLS extension. + * + * \note This function is only available on the following platforms: + * * If the compile-time option MBEDTLS_PSA_INJECT_ENTROPY is enabled. + * Note that you must provide compatible implementations of + * mbedtls_nv_seed_read and mbedtls_nv_seed_write. + * * In a client-server integration of PSA Cryptography, on the client side, + * if the server supports this feature. + * \param[in] seed Buffer containing the seed value to inject. + * \param[in] seed_size Size of the \p seed buffer. + * The size of the seed in bytes must be greater + * or equal to both #MBEDTLS_ENTROPY_MIN_PLATFORM + * and #MBEDTLS_ENTROPY_BLOCK_SIZE. + * It must be less or equal to + * #MBEDTLS_ENTROPY_MAX_SEED_SIZE. + * + * \retval #PSA_SUCCESS + * The seed value was injected successfully. The random generator + * of the PSA Crypto implementation is now ready for use. + * You may now call psa_crypto_init() and use the PSA Crypto + * implementation. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p seed_size is out of range. + * \retval #PSA_ERROR_STORAGE_FAILURE + * There was a failure reading or writing from storage. + * \retval #PSA_ERROR_NOT_PERMITTED + * The library has already been initialized. It is no longer + * possible to call this function. + */ +psa_status_t mbedtls_psa_inject_entropy(const uint8_t *seed, + size_t seed_size); + +/** \addtogroup crypto_types + * @{ + */ + +/** DSA public key. + * + * The import and export format is the + * representation of the public key `y = g^x mod p` as a big-endian byte + * string. The length of the byte string is the length of the base prime `p` + * in bytes. + */ +#define PSA_KEY_TYPE_DSA_PUBLIC_KEY ((psa_key_type_t)0x4002) + +/** DSA key pair (private and public key). + * + * The import and export format is the + * representation of the private key `x` as a big-endian byte string. The + * length of the byte string is the private key size in bytes (leading zeroes + * are not stripped). + * + * Determinstic DSA key derivation with psa_generate_derived_key follows + * FIPS 186-4 §B.1.2: interpret the byte string as integer + * in big-endian order. Discard it if it is not in the range + * [0, *N* - 2] where *N* is the boundary of the private key domain + * (the prime *p* for Diffie-Hellman, the subprime *q* for DSA, + * or the order of the curve's base point for ECC). + * Add 1 to the resulting integer and use this as the private key *x*. + * + */ +#define PSA_KEY_TYPE_DSA_KEY_PAIR ((psa_key_type_t)0x7002) + +/** Whether a key type is an DSA key (pair or public-only). */ +#define PSA_KEY_TYPE_IS_DSA(type) \ + (PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) == PSA_KEY_TYPE_DSA_PUBLIC_KEY) + +#define PSA_ALG_DSA_BASE ((psa_algorithm_t)0x10040000) +/** DSA signature with hashing. + * + * This is the signature scheme defined by FIPS 186-4, + * with a random per-message secret number (*k*). + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * This includes #PSA_ALG_ANY_HASH + * when specifying the algorithm in a usage policy. + * + * \return The corresponding DSA signature algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_DSA(hash_alg) \ + (PSA_ALG_DSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +#define PSA_ALG_DETERMINISTIC_DSA_BASE ((psa_algorithm_t)0x10050000) +#define PSA_ALG_DSA_DETERMINISTIC_FLAG PSA_ALG_ECDSA_DETERMINISTIC_FLAG +/** Deterministic DSA signature with hashing. + * + * This is the deterministic variant defined by RFC 6979 of + * the signature scheme defined by FIPS 186-4. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * This includes #PSA_ALG_ANY_HASH + * when specifying the algorithm in a usage policy. + * + * \return The corresponding DSA signature algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_DETERMINISTIC_DSA(hash_alg) \ + (PSA_ALG_DETERMINISTIC_DSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +#define PSA_ALG_IS_DSA(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK & ~PSA_ALG_DSA_DETERMINISTIC_FLAG) == \ + PSA_ALG_DSA_BASE) +#define PSA_ALG_DSA_IS_DETERMINISTIC(alg) \ + (((alg) & PSA_ALG_DSA_DETERMINISTIC_FLAG) != 0) +#define PSA_ALG_IS_DETERMINISTIC_DSA(alg) \ + (PSA_ALG_IS_DSA(alg) && PSA_ALG_DSA_IS_DETERMINISTIC(alg)) +#define PSA_ALG_IS_RANDOMIZED_DSA(alg) \ + (PSA_ALG_IS_DSA(alg) && !PSA_ALG_DSA_IS_DETERMINISTIC(alg)) + + +/* We need to expand the sample definition of this macro from + * the API definition. */ +#undef PSA_ALG_IS_HASH_AND_SIGN +#define PSA_ALG_IS_HASH_AND_SIGN(alg) \ + (PSA_ALG_IS_RSA_PSS(alg) || PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) || \ + PSA_ALG_IS_DSA(alg) || PSA_ALG_IS_ECDSA(alg)) + +/**@}*/ + +/** \addtogroup attributes + * @{ + */ + +/** Custom Diffie-Hellman group. + * + * For keys of type #PSA_KEY_TYPE_DH_PUBLIC_KEY(#PSA_DH_FAMILY_CUSTOM) or + * #PSA_KEY_TYPE_DH_KEY_PAIR(#PSA_DH_FAMILY_CUSTOM), the group data comes + * from domain parameters set by psa_set_key_domain_parameters(). + */ +#define PSA_DH_FAMILY_CUSTOM ((psa_dh_family_t) 0x7e) + + +/** + * \brief Set domain parameters for a key. + * + * Some key types require additional domain parameters in addition to + * the key type identifier and the key size. Use this function instead + * of psa_set_key_type() when you need to specify domain parameters. + * + * The format for the required domain parameters varies based on the key type. + * + * - For RSA keys (#PSA_KEY_TYPE_RSA_PUBLIC_KEY or #PSA_KEY_TYPE_RSA_KEY_PAIR), + * the domain parameter data consists of the public exponent, + * represented as a big-endian integer with no leading zeros. + * This information is used when generating an RSA key pair. + * When importing a key, the public exponent is read from the imported + * key data and the exponent recorded in the attribute structure is ignored. + * As an exception, the public exponent 65537 is represented by an empty + * byte string. + * - For DSA keys (#PSA_KEY_TYPE_DSA_PUBLIC_KEY or #PSA_KEY_TYPE_DSA_KEY_PAIR), + * the `Dss-Parms` format as defined by RFC 3279 §2.3.2. + * ``` + * Dss-Parms ::= SEQUENCE { + * p INTEGER, + * q INTEGER, + * g INTEGER + * } + * ``` + * - For Diffie-Hellman key exchange keys + * (#PSA_KEY_TYPE_DH_PUBLIC_KEY(#PSA_DH_FAMILY_CUSTOM) or + * #PSA_KEY_TYPE_DH_KEY_PAIR(#PSA_DH_FAMILY_CUSTOM)), the + * `DomainParameters` format as defined by RFC 3279 §2.3.3. + * ``` + * DomainParameters ::= SEQUENCE { + * p INTEGER, -- odd prime, p=jq +1 + * g INTEGER, -- generator, g + * q INTEGER, -- factor of p-1 + * j INTEGER OPTIONAL, -- subgroup factor + * validationParms ValidationParms OPTIONAL + * } + * ValidationParms ::= SEQUENCE { + * seed BIT STRING, + * pgenCounter INTEGER + * } + * ``` + * + * \note This function may allocate memory or other resources. + * Once you have called this function on an attribute structure, + * you must call psa_reset_key_attributes() to free these resources. + * + * \note This is an experimental extension to the interface. It may change + * in future versions of the library. + * + * \param[in,out] attributes Attribute structure where the specified domain + * parameters will be stored. + * If this function fails, the content of + * \p attributes is not modified. + * \param type Key type (a \c PSA_KEY_TYPE_XXX value). + * \param[in] data Buffer containing the key domain parameters. + * The content of this buffer is interpreted + * according to \p type as described above. + * \param data_length Size of the \p data buffer in bytes. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + */ +psa_status_t psa_set_key_domain_parameters(psa_key_attributes_t *attributes, + psa_key_type_t type, + const uint8_t *data, + size_t data_length); + +/** + * \brief Get domain parameters for a key. + * + * Get the domain parameters for a key with this function, if any. The format + * of the domain parameters written to \p data is specified in the + * documentation for psa_set_key_domain_parameters(). + * + * \note This is an experimental extension to the interface. It may change + * in future versions of the library. + * + * \param[in] attributes The key attribute structure to query. + * \param[out] data On success, the key domain parameters. + * \param data_size Size of the \p data buffer in bytes. + * The buffer is guaranteed to be large + * enough if its size in bytes is at least + * the value given by + * PSA_KEY_DOMAIN_PARAMETERS_SIZE(). + * \param[out] data_length On success, the number of bytes + * that make up the key domain parameters data. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + */ +psa_status_t psa_get_key_domain_parameters( + const psa_key_attributes_t *attributes, + uint8_t *data, + size_t data_size, + size_t *data_length); + +/** Safe output buffer size for psa_get_key_domain_parameters(). + * + * This macro returns a compile-time constant if its arguments are + * compile-time constants. + * + * \warning This function may call its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * \note This is an experimental extension to the interface. It may change + * in future versions of the library. + * + * \param key_type A supported key type. + * \param key_bits The size of the key in bits. + * + * \return If the parameters are valid and supported, return + * a buffer size in bytes that guarantees that + * psa_get_key_domain_parameters() will not fail with + * #PSA_ERROR_BUFFER_TOO_SMALL. + * If the parameters are a valid combination that is not supported + * by the implementation, this macro shall return either a + * sensible size or 0. + * If the parameters are not valid, the + * return value is unspecified. + */ +#define PSA_KEY_DOMAIN_PARAMETERS_SIZE(key_type, key_bits) \ + (PSA_KEY_TYPE_IS_RSA(key_type) ? sizeof(int) : \ + PSA_KEY_TYPE_IS_DH(key_type) ? PSA_DH_KEY_DOMAIN_PARAMETERS_SIZE(key_bits) : \ + PSA_KEY_TYPE_IS_DSA(key_type) ? PSA_DSA_KEY_DOMAIN_PARAMETERS_SIZE(key_bits) : \ + 0) +#define PSA_DH_KEY_DOMAIN_PARAMETERS_SIZE(key_bits) \ + (4 + (PSA_BITS_TO_BYTES(key_bits) + 5) * 3 /*without optional parts*/) +#define PSA_DSA_KEY_DOMAIN_PARAMETERS_SIZE(key_bits) \ + (4 + (PSA_BITS_TO_BYTES(key_bits) + 5) * 2 /*p, g*/ + 34 /*q*/) + +/**@}*/ + +/** \defgroup psa_tls_helpers TLS helper functions + * @{ + */ + +#if defined(MBEDTLS_ECP_C) +#include + +/** Convert an ECC curve identifier from the Mbed TLS encoding to PSA. + * + * \note This function is provided solely for the convenience of + * Mbed TLS and may be removed at any time without notice. + * + * \param grpid An Mbed TLS elliptic curve identifier + * (`MBEDTLS_ECP_DP_xxx`). + * \param[out] bits On success, the bit size of the curve. + * + * \return The corresponding PSA elliptic curve identifier + * (`PSA_ECC_FAMILY_xxx`). + * \return \c 0 on failure (\p grpid is not recognized). + */ +static inline psa_ecc_family_t mbedtls_ecc_group_to_psa( mbedtls_ecp_group_id grpid, + size_t *bits ) +{ + switch( grpid ) + { + case MBEDTLS_ECP_DP_SECP192R1: + *bits = 192; + return( PSA_ECC_FAMILY_SECP_R1 ); + case MBEDTLS_ECP_DP_SECP224R1: + *bits = 224; + return( PSA_ECC_FAMILY_SECP_R1 ); + case MBEDTLS_ECP_DP_SECP256R1: + *bits = 256; + return( PSA_ECC_FAMILY_SECP_R1 ); + case MBEDTLS_ECP_DP_SECP384R1: + *bits = 384; + return( PSA_ECC_FAMILY_SECP_R1 ); + case MBEDTLS_ECP_DP_SECP521R1: + *bits = 521; + return( PSA_ECC_FAMILY_SECP_R1 ); + case MBEDTLS_ECP_DP_BP256R1: + *bits = 256; + return( PSA_ECC_FAMILY_BRAINPOOL_P_R1 ); + case MBEDTLS_ECP_DP_BP384R1: + *bits = 384; + return( PSA_ECC_FAMILY_BRAINPOOL_P_R1 ); + case MBEDTLS_ECP_DP_BP512R1: + *bits = 512; + return( PSA_ECC_FAMILY_BRAINPOOL_P_R1 ); + case MBEDTLS_ECP_DP_CURVE25519: + *bits = 255; + return( PSA_ECC_FAMILY_MONTGOMERY ); + case MBEDTLS_ECP_DP_SECP192K1: + *bits = 192; + return( PSA_ECC_FAMILY_SECP_K1 ); + case MBEDTLS_ECP_DP_SECP224K1: + *bits = 224; + return( PSA_ECC_FAMILY_SECP_K1 ); + case MBEDTLS_ECP_DP_SECP256K1: + *bits = 256; + return( PSA_ECC_FAMILY_SECP_K1 ); + case MBEDTLS_ECP_DP_CURVE448: + *bits = 448; + return( PSA_ECC_FAMILY_MONTGOMERY ); + default: + *bits = 0; + return( 0 ); + } +} + +/** Convert an ECC curve identifier from the PSA encoding to Mbed TLS. + * + * \note This function is provided solely for the convenience of + * Mbed TLS and may be removed at any time without notice. + * + * \param curve A PSA elliptic curve identifier + * (`PSA_ECC_FAMILY_xxx`). + * \param byte_length The byte-length of a private key on \p curve. + * + * \return The corresponding Mbed TLS elliptic curve identifier + * (`MBEDTLS_ECP_DP_xxx`). + * \return #MBEDTLS_ECP_DP_NONE if \c curve is not recognized. + * \return #MBEDTLS_ECP_DP_NONE if \p byte_length is not + * correct for \p curve. + */ +mbedtls_ecp_group_id mbedtls_ecc_group_of_psa( psa_ecc_family_t curve, + size_t byte_length ); +#endif /* MBEDTLS_ECP_C */ + +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* PSA_CRYPTO_EXTRA_H */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/psa/crypto_platform.h b/Android/Level4/app/src/main/c/mbedtls/include/psa/crypto_platform.h new file mode 100644 index 0000000..c64f61d --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/psa/crypto_platform.h @@ -0,0 +1,83 @@ +/** + * \file psa/crypto_platform.h + * + * \brief PSA cryptography module: Mbed TLS platform definitions + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. + * + * This file contains platform-dependent type definitions. + * + * In implementations with isolation between the application and the + * cryptography module, implementers should take care to ensure that + * the definitions that are exposed to applications match what the + * module implements. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 PSA_CRYPTO_PLATFORM_H +#define PSA_CRYPTO_PLATFORM_H + +/* Include the Mbed TLS configuration file, the way Mbed TLS does it + * in each of its header files. */ +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +/* PSA requires several types which C99 provides in stdint.h. */ +#include + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +/* Integral type representing a key handle. */ +typedef uint16_t psa_key_handle_t; + +#if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) + +/* Building for the PSA Crypto service on a PSA platform, a key owner is a PSA + * partition identifier. + * + * The function psa_its_identifier_of_slot() in psa_crypto_storage.c that + * translates a key identifier to a key storage file name assumes that + * mbedtls_key_owner_id_t is an 32 bits integer. This function thus needs + * reworking if mbedtls_key_owner_id_t is not defined as a 32 bits integer + * here anymore. + */ +typedef int32_t mbedtls_key_owner_id_t; + +/** Compare two key owner identifiers. + * + * \param id1 First key owner identifier. + * \param id2 Second key owner identifier. + * + * \return Non-zero if the two key owner identifiers are equal, zero otherwise. + */ +static inline int mbedtls_key_owner_id_equal( mbedtls_key_owner_id_t id1, + mbedtls_key_owner_id_t id2 ) +{ + return( id1 == id2 ); +} + +#endif /* MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */ + +#endif /* PSA_CRYPTO_PLATFORM_H */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/psa/crypto_se_driver.h b/Android/Level4/app/src/main/c/mbedtls/include/psa/crypto_se_driver.h new file mode 100644 index 0000000..46b2d64 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/psa/crypto_se_driver.h @@ -0,0 +1,1392 @@ +/** + * \file psa/crypto_se_driver.h + * \brief PSA external cryptoprocessor driver module + * + * This header declares types and function signatures for cryptography + * drivers that access key material via opaque references. + * This is meant for cryptoprocessors that have a separate key storage from the + * space in which the PSA Crypto implementation runs, typically secure + * elements (SEs). + * + * This file is part of the PSA Crypto Driver HAL (hardware abstraction layer), + * containing functions for driver developers to implement to enable hardware + * to be called in a standardized way by a PSA Cryptography API + * implementation. The functions comprising the driver HAL, which driver + * authors implement, are not intended to be called by application developers. + */ + +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 PSA_CRYPTO_SE_DRIVER_H +#define PSA_CRYPTO_SE_DRIVER_H + +#include "crypto_driver_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup se_init Secure element driver initialization + */ +/**@{*/ + +/** \brief Driver context structure + * + * Driver functions receive a pointer to this structure. + * Each registered driver has one instance of this structure. + * + * Implementations must include the fields specified here and + * may include other fields. + */ +typedef struct { + /** A read-only pointer to the driver's persistent data. + * + * Drivers typically use this persistent data to keep track of + * which slot numbers are available. This is only a guideline: + * drivers may use the persistent data for any purpose, keeping + * in mind the restrictions on when the persistent data is saved + * to storage: the persistent data is only saved after calling + * certain functions that receive a writable pointer to the + * persistent data. + * + * The core allocates a memory buffer for the persistent data. + * The pointer is guaranteed to be suitably aligned for any data type, + * like a pointer returned by `malloc` (but the core can use any + * method to allocate the buffer, not necessarily `malloc`). + * + * The size of this buffer is in the \c persistent_data_size field of + * this structure. + * + * Before the driver is initialized for the first time, the content of + * the persistent data is all-bits-zero. After a driver upgrade, if the + * size of the persistent data has increased, the original data is padded + * on the right with zeros; if the size has decreased, the original data + * is truncated to the new size. + * + * This pointer is to read-only data. Only a few driver functions are + * allowed to modify the persistent data. These functions receive a + * writable pointer. These functions are: + * - psa_drv_se_t::p_init + * - psa_drv_se_key_management_t::p_allocate + * - psa_drv_se_key_management_t::p_destroy + * + * The PSA Cryptography core saves the persistent data from one + * session to the next. It does this before returning from API functions + * that call a driver method that is allowed to modify the persistent + * data, specifically: + * - psa_crypto_init() causes a call to psa_drv_se_t::p_init, and may call + * psa_drv_se_key_management_t::p_destroy to complete an action + * that was interrupted by a power failure. + * - Key creation functions cause a call to + * psa_drv_se_key_management_t::p_allocate, and may cause a call to + * psa_drv_se_key_management_t::p_destroy in case an error occurs. + * - psa_destroy_key() causes a call to + * psa_drv_se_key_management_t::p_destroy. + */ + const void *const persistent_data; + + /** The size of \c persistent_data in bytes. + * + * This is always equal to the value of the `persistent_data_size` field + * of the ::psa_drv_se_t structure when the driver is registered. + */ + const size_t persistent_data_size; + + /** Driver transient data. + * + * The core initializes this value to 0 and does not read or modify it + * afterwards. The driver may store whatever it wants in this field. + */ + uintptr_t transient_data; +} psa_drv_se_context_t; + +/** \brief A driver initialization function. + * + * \param[in,out] drv_context The driver context structure. + * \param[in,out] persistent_data A pointer to the persistent data + * that allows writing. + * \param location The location value for which this driver + * is registered. The driver will be invoked + * for all keys whose lifetime is in this + * location. + * + * \retval #PSA_SUCCESS + * The driver is operational. + * The core will update the persistent data in storage. + * \return + * Any other return value prevents the driver from being used in + * this session. + * The core will NOT update the persistent data in storage. + */ +typedef psa_status_t (*psa_drv_se_init_t)(psa_drv_se_context_t *drv_context, + void *persistent_data, + psa_key_location_t location); + +#if defined(__DOXYGEN_ONLY__) || !defined(MBEDTLS_PSA_CRYPTO_SE_C) +/* Mbed Crypto with secure element support enabled defines this type in + * crypto_types.h because it is also visible to applications through an + * implementation-specific extension. + * For the PSA Cryptography specification, this type is only visible + * via crypto_se_driver.h. */ +/** An internal designation of a key slot between the core part of the + * PSA Crypto implementation and the driver. The meaning of this value + * is driver-dependent. */ +typedef uint64_t psa_key_slot_number_t; +#endif /* __DOXYGEN_ONLY__ || !MBEDTLS_PSA_CRYPTO_SE_C */ + +/**@}*/ + +/** \defgroup se_mac Secure Element Message Authentication Codes + * Generation and authentication of Message Authentication Codes (MACs) using + * a secure element can be done either as a single function call (via the + * `psa_drv_se_mac_generate_t` or `psa_drv_se_mac_verify_t` functions), or in + * parts using the following sequence: + * - `psa_drv_se_mac_setup_t` + * - `psa_drv_se_mac_update_t` + * - `psa_drv_se_mac_update_t` + * - ... + * - `psa_drv_se_mac_finish_t` or `psa_drv_se_mac_finish_verify_t` + * + * If a previously started secure element MAC operation needs to be terminated, + * it should be done so by the `psa_drv_se_mac_abort_t`. Failure to do so may + * result in allocated resources not being freed or in other undefined + * behavior. + */ +/**@{*/ +/** \brief A function that starts a secure element MAC operation for a PSA + * Crypto Driver implementation + * + * \param[in,out] drv_context The driver context structure. + * \param[in,out] op_context A structure that will contain the + * hardware-specific MAC context + * \param[in] key_slot The slot of the key to be used for the + * operation + * \param[in] algorithm The algorithm to be used to underly the MAC + * operation + * + * \retval PSA_SUCCESS + * Success. + */ +typedef psa_status_t (*psa_drv_se_mac_setup_t)(psa_drv_se_context_t *drv_context, + void *op_context, + psa_key_slot_number_t key_slot, + psa_algorithm_t algorithm); + +/** \brief A function that continues a previously started secure element MAC + * operation + * + * \param[in,out] op_context A hardware-specific structure for the + * previously-established MAC operation to be + * updated + * \param[in] p_input A buffer containing the message to be appended + * to the MAC operation + * \param[in] input_length The size in bytes of the input message buffer + */ +typedef psa_status_t (*psa_drv_se_mac_update_t)(void *op_context, + const uint8_t *p_input, + size_t input_length); + +/** \brief a function that completes a previously started secure element MAC + * operation by returning the resulting MAC. + * + * \param[in,out] op_context A hardware-specific structure for the + * previously started MAC operation to be + * finished + * \param[out] p_mac A buffer where the generated MAC will be + * placed + * \param[in] mac_size The size in bytes of the buffer that has been + * allocated for the `output` buffer + * \param[out] p_mac_length After completion, will contain the number of + * bytes placed in the `p_mac` buffer + * + * \retval PSA_SUCCESS + * Success. + */ +typedef psa_status_t (*psa_drv_se_mac_finish_t)(void *op_context, + uint8_t *p_mac, + size_t mac_size, + size_t *p_mac_length); + +/** \brief A function that completes a previously started secure element MAC + * operation by comparing the resulting MAC against a provided value + * + * \param[in,out] op_context A hardware-specific structure for the previously + * started MAC operation to be fiinished + * \param[in] p_mac The MAC value against which the resulting MAC + * will be compared against + * \param[in] mac_length The size in bytes of the value stored in `p_mac` + * + * \retval PSA_SUCCESS + * The operation completed successfully and the MACs matched each + * other + * \retval PSA_ERROR_INVALID_SIGNATURE + * The operation completed successfully, but the calculated MAC did + * not match the provided MAC + */ +typedef psa_status_t (*psa_drv_se_mac_finish_verify_t)(void *op_context, + const uint8_t *p_mac, + size_t mac_length); + +/** \brief A function that aborts a previous started secure element MAC + * operation + * + * \param[in,out] op_context A hardware-specific structure for the previously + * started MAC operation to be aborted + */ +typedef psa_status_t (*psa_drv_se_mac_abort_t)(void *op_context); + +/** \brief A function that performs a secure element MAC operation in one + * command and returns the calculated MAC + * + * \param[in,out] drv_context The driver context structure. + * \param[in] p_input A buffer containing the message to be MACed + * \param[in] input_length The size in bytes of `p_input` + * \param[in] key_slot The slot of the key to be used + * \param[in] alg The algorithm to be used to underlie the MAC + * operation + * \param[out] p_mac A buffer where the generated MAC will be + * placed + * \param[in] mac_size The size in bytes of the `p_mac` buffer + * \param[out] p_mac_length After completion, will contain the number of + * bytes placed in the `output` buffer + * + * \retval PSA_SUCCESS + * Success. + */ +typedef psa_status_t (*psa_drv_se_mac_generate_t)(psa_drv_se_context_t *drv_context, + const uint8_t *p_input, + size_t input_length, + psa_key_slot_number_t key_slot, + psa_algorithm_t alg, + uint8_t *p_mac, + size_t mac_size, + size_t *p_mac_length); + +/** \brief A function that performs a secure element MAC operation in one + * command and compares the resulting MAC against a provided value + * + * \param[in,out] drv_context The driver context structure. + * \param[in] p_input A buffer containing the message to be MACed + * \param[in] input_length The size in bytes of `input` + * \param[in] key_slot The slot of the key to be used + * \param[in] alg The algorithm to be used to underlie the MAC + * operation + * \param[in] p_mac The MAC value against which the resulting MAC will + * be compared against + * \param[in] mac_length The size in bytes of `mac` + * + * \retval PSA_SUCCESS + * The operation completed successfully and the MACs matched each + * other + * \retval PSA_ERROR_INVALID_SIGNATURE + * The operation completed successfully, but the calculated MAC did + * not match the provided MAC + */ +typedef psa_status_t (*psa_drv_se_mac_verify_t)(psa_drv_se_context_t *drv_context, + const uint8_t *p_input, + size_t input_length, + psa_key_slot_number_t key_slot, + psa_algorithm_t alg, + const uint8_t *p_mac, + size_t mac_length); + +/** \brief A struct containing all of the function pointers needed to + * perform secure element MAC operations + * + * PSA Crypto API implementations should populate the table as appropriate + * upon startup. + * + * If one of the functions is not implemented (such as + * `psa_drv_se_mac_generate_t`), it should be set to NULL. + * + * Driver implementers should ensure that they implement all of the functions + * that make sense for their hardware, and that they provide a full solution + * (for example, if they support `p_setup`, they should also support + * `p_update` and at least one of `p_finish` or `p_finish_verify`). + * + */ +typedef struct { + /**The size in bytes of the hardware-specific secure element MAC context + * structure + */ + size_t context_size; + /** Function that performs a MAC setup operation + */ + psa_drv_se_mac_setup_t p_setup; + /** Function that performs a MAC update operation + */ + psa_drv_se_mac_update_t p_update; + /** Function that completes a MAC operation + */ + psa_drv_se_mac_finish_t p_finish; + /** Function that completes a MAC operation with a verify check + */ + psa_drv_se_mac_finish_verify_t p_finish_verify; + /** Function that aborts a previoustly started MAC operation + */ + psa_drv_se_mac_abort_t p_abort; + /** Function that performs a MAC operation in one call + */ + psa_drv_se_mac_generate_t p_mac; + /** Function that performs a MAC and verify operation in one call + */ + psa_drv_se_mac_verify_t p_mac_verify; +} psa_drv_se_mac_t; +/**@}*/ + +/** \defgroup se_cipher Secure Element Symmetric Ciphers + * + * Encryption and Decryption using secure element keys in block modes other + * than ECB must be done in multiple parts, using the following flow: + * - `psa_drv_se_cipher_setup_t` + * - `psa_drv_se_cipher_set_iv_t` (optional depending upon block mode) + * - `psa_drv_se_cipher_update_t` + * - `psa_drv_se_cipher_update_t` + * - ... + * - `psa_drv_se_cipher_finish_t` + * + * If a previously started secure element Cipher operation needs to be + * terminated, it should be done so by the `psa_drv_se_cipher_abort_t`. Failure + * to do so may result in allocated resources not being freed or in other + * undefined behavior. + * + * In situations where a PSA Cryptographic API implementation is using a block + * mode not-supported by the underlying hardware or driver, it can construct + * the block mode itself, while calling the `psa_drv_se_cipher_ecb_t` function + * for the cipher operations. + */ +/**@{*/ + +/** \brief A function that provides the cipher setup function for a + * secure element driver + * + * \param[in,out] drv_context The driver context structure. + * \param[in,out] op_context A structure that will contain the + * hardware-specific cipher context. + * \param[in] key_slot The slot of the key to be used for the + * operation + * \param[in] algorithm The algorithm to be used in the cipher + * operation + * \param[in] direction Indicates whether the operation is an encrypt + * or decrypt + * + * \retval PSA_SUCCESS + * \retval PSA_ERROR_NOT_SUPPORTED + */ +typedef psa_status_t (*psa_drv_se_cipher_setup_t)(psa_drv_se_context_t *drv_context, + void *op_context, + psa_key_slot_number_t key_slot, + psa_algorithm_t algorithm, + psa_encrypt_or_decrypt_t direction); + +/** \brief A function that sets the initialization vector (if + * necessary) for an secure element cipher operation + * + * Rationale: The `psa_se_cipher_*` operation in the PSA Cryptographic API has + * two IV functions: one to set the IV, and one to generate it internally. The + * generate function is not necessary for the drivers to implement as the PSA + * Crypto implementation can do the generation using its RNG features. + * + * \param[in,out] op_context A structure that contains the previously set up + * hardware-specific cipher context + * \param[in] p_iv A buffer containing the initialization vector + * \param[in] iv_length The size (in bytes) of the `p_iv` buffer + * + * \retval PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_se_cipher_set_iv_t)(void *op_context, + const uint8_t *p_iv, + size_t iv_length); + +/** \brief A function that continues a previously started secure element cipher + * operation + * + * \param[in,out] op_context A hardware-specific structure for the + * previously started cipher operation + * \param[in] p_input A buffer containing the data to be + * encrypted/decrypted + * \param[in] input_size The size in bytes of the buffer pointed to + * by `p_input` + * \param[out] p_output The caller-allocated buffer where the + * output will be placed + * \param[in] output_size The allocated size in bytes of the + * `p_output` buffer + * \param[out] p_output_length After completion, will contain the number + * of bytes placed in the `p_output` buffer + * + * \retval PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_se_cipher_update_t)(void *op_context, + const uint8_t *p_input, + size_t input_size, + uint8_t *p_output, + size_t output_size, + size_t *p_output_length); + +/** \brief A function that completes a previously started secure element cipher + * operation + * + * \param[in,out] op_context A hardware-specific structure for the + * previously started cipher operation + * \param[out] p_output The caller-allocated buffer where the output + * will be placed + * \param[in] output_size The allocated size in bytes of the `p_output` + * buffer + * \param[out] p_output_length After completion, will contain the number of + * bytes placed in the `p_output` buffer + * + * \retval PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_se_cipher_finish_t)(void *op_context, + uint8_t *p_output, + size_t output_size, + size_t *p_output_length); + +/** \brief A function that aborts a previously started secure element cipher + * operation + * + * \param[in,out] op_context A hardware-specific structure for the + * previously started cipher operation + */ +typedef psa_status_t (*psa_drv_se_cipher_abort_t)(void *op_context); + +/** \brief A function that performs the ECB block mode for secure element + * cipher operations + * + * Note: this function should only be used with implementations that do not + * provide a needed higher-level operation. + * + * \param[in,out] drv_context The driver context structure. + * \param[in] key_slot The slot of the key to be used for the operation + * \param[in] algorithm The algorithm to be used in the cipher operation + * \param[in] direction Indicates whether the operation is an encrypt or + * decrypt + * \param[in] p_input A buffer containing the data to be + * encrypted/decrypted + * \param[in] input_size The size in bytes of the buffer pointed to by + * `p_input` + * \param[out] p_output The caller-allocated buffer where the output + * will be placed + * \param[in] output_size The allocated size in bytes of the `p_output` + * buffer + * + * \retval PSA_SUCCESS + * \retval PSA_ERROR_NOT_SUPPORTED + */ +typedef psa_status_t (*psa_drv_se_cipher_ecb_t)(psa_drv_se_context_t *drv_context, + psa_key_slot_number_t key_slot, + psa_algorithm_t algorithm, + psa_encrypt_or_decrypt_t direction, + const uint8_t *p_input, + size_t input_size, + uint8_t *p_output, + size_t output_size); + +/** + * \brief A struct containing all of the function pointers needed to implement + * cipher operations using secure elements. + * + * PSA Crypto API implementations should populate instances of the table as + * appropriate upon startup or at build time. + * + * If one of the functions is not implemented (such as + * `psa_drv_se_cipher_ecb_t`), it should be set to NULL. + */ +typedef struct { + /** The size in bytes of the hardware-specific secure element cipher + * context structure + */ + size_t context_size; + /** Function that performs a cipher setup operation */ + psa_drv_se_cipher_setup_t p_setup; + /** Function that sets a cipher IV (if necessary) */ + psa_drv_se_cipher_set_iv_t p_set_iv; + /** Function that performs a cipher update operation */ + psa_drv_se_cipher_update_t p_update; + /** Function that completes a cipher operation */ + psa_drv_se_cipher_finish_t p_finish; + /** Function that aborts a cipher operation */ + psa_drv_se_cipher_abort_t p_abort; + /** Function that performs ECB mode for a cipher operation + * (Danger: ECB mode should not be used directly by clients of the PSA + * Crypto Client API) + */ + psa_drv_se_cipher_ecb_t p_ecb; +} psa_drv_se_cipher_t; + +/**@}*/ + +/** \defgroup se_asymmetric Secure Element Asymmetric Cryptography + * + * Since the amount of data that can (or should) be encrypted or signed using + * asymmetric keys is limited by the key size, asymmetric key operations using + * keys in a secure element must be done in single function calls. + */ +/**@{*/ + +/** + * \brief A function that signs a hash or short message with a private key in + * a secure element + * + * \param[in,out] drv_context The driver context structure. + * \param[in] key_slot Key slot of an asymmetric key pair + * \param[in] alg A signature algorithm that is compatible + * with the type of `key` + * \param[in] p_hash The hash to sign + * \param[in] hash_length Size of the `p_hash` buffer in bytes + * \param[out] p_signature Buffer where the signature is to be written + * \param[in] signature_size Size of the `p_signature` buffer in bytes + * \param[out] p_signature_length On success, the number of bytes + * that make up the returned signature value + * + * \retval PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_se_asymmetric_sign_t)(psa_drv_se_context_t *drv_context, + psa_key_slot_number_t key_slot, + psa_algorithm_t alg, + const uint8_t *p_hash, + size_t hash_length, + uint8_t *p_signature, + size_t signature_size, + size_t *p_signature_length); + +/** + * \brief A function that verifies the signature a hash or short message using + * an asymmetric public key in a secure element + * + * \param[in,out] drv_context The driver context structure. + * \param[in] key_slot Key slot of a public key or an asymmetric key + * pair + * \param[in] alg A signature algorithm that is compatible with + * the type of `key` + * \param[in] p_hash The hash whose signature is to be verified + * \param[in] hash_length Size of the `p_hash` buffer in bytes + * \param[in] p_signature Buffer containing the signature to verify + * \param[in] signature_length Size of the `p_signature` buffer in bytes + * + * \retval PSA_SUCCESS + * The signature is valid. + */ +typedef psa_status_t (*psa_drv_se_asymmetric_verify_t)(psa_drv_se_context_t *drv_context, + psa_key_slot_number_t key_slot, + psa_algorithm_t alg, + const uint8_t *p_hash, + size_t hash_length, + const uint8_t *p_signature, + size_t signature_length); + +/** + * \brief A function that encrypts a short message with an asymmetric public + * key in a secure element + * + * \param[in,out] drv_context The driver context structure. + * \param[in] key_slot Key slot of a public key or an asymmetric key + * pair + * \param[in] alg An asymmetric encryption algorithm that is + * compatible with the type of `key` + * \param[in] p_input The message to encrypt + * \param[in] input_length Size of the `p_input` buffer in bytes + * \param[in] p_salt A salt or label, if supported by the + * encryption algorithm + * If the algorithm does not support a + * salt, pass `NULL`. + * If the algorithm supports an optional + * salt and you do not want to pass a salt, + * pass `NULL`. + * For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is + * supported. + * \param[in] salt_length Size of the `p_salt` buffer in bytes + * If `p_salt` is `NULL`, pass 0. + * \param[out] p_output Buffer where the encrypted message is to + * be written + * \param[in] output_size Size of the `p_output` buffer in bytes + * \param[out] p_output_length On success, the number of bytes that make up + * the returned output + * + * \retval PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_se_asymmetric_encrypt_t)(psa_drv_se_context_t *drv_context, + psa_key_slot_number_t key_slot, + psa_algorithm_t alg, + const uint8_t *p_input, + size_t input_length, + const uint8_t *p_salt, + size_t salt_length, + uint8_t *p_output, + size_t output_size, + size_t *p_output_length); + +/** + * \brief A function that decrypts a short message with an asymmetric private + * key in a secure element. + * + * \param[in,out] drv_context The driver context structure. + * \param[in] key_slot Key slot of an asymmetric key pair + * \param[in] alg An asymmetric encryption algorithm that is + * compatible with the type of `key` + * \param[in] p_input The message to decrypt + * \param[in] input_length Size of the `p_input` buffer in bytes + * \param[in] p_salt A salt or label, if supported by the + * encryption algorithm + * If the algorithm does not support a + * salt, pass `NULL`. + * If the algorithm supports an optional + * salt and you do not want to pass a salt, + * pass `NULL`. + * For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is + * supported. + * \param[in] salt_length Size of the `p_salt` buffer in bytes + * If `p_salt` is `NULL`, pass 0. + * \param[out] p_output Buffer where the decrypted message is to + * be written + * \param[in] output_size Size of the `p_output` buffer in bytes + * \param[out] p_output_length On success, the number of bytes + * that make up the returned output + * + * \retval PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_se_asymmetric_decrypt_t)(psa_drv_se_context_t *drv_context, + psa_key_slot_number_t key_slot, + psa_algorithm_t alg, + const uint8_t *p_input, + size_t input_length, + const uint8_t *p_salt, + size_t salt_length, + uint8_t *p_output, + size_t output_size, + size_t *p_output_length); + +/** + * \brief A struct containing all of the function pointers needed to implement + * asymmetric cryptographic operations using secure elements. + * + * PSA Crypto API implementations should populate instances of the table as + * appropriate upon startup or at build time. + * + * If one of the functions is not implemented, it should be set to NULL. + */ +typedef struct { + /** Function that performs an asymmetric sign operation */ + psa_drv_se_asymmetric_sign_t p_sign; + /** Function that performs an asymmetric verify operation */ + psa_drv_se_asymmetric_verify_t p_verify; + /** Function that performs an asymmetric encrypt operation */ + psa_drv_se_asymmetric_encrypt_t p_encrypt; + /** Function that performs an asymmetric decrypt operation */ + psa_drv_se_asymmetric_decrypt_t p_decrypt; +} psa_drv_se_asymmetric_t; + +/**@}*/ + +/** \defgroup se_aead Secure Element Authenticated Encryption with Additional Data + * Authenticated Encryption with Additional Data (AEAD) operations with secure + * elements must be done in one function call. While this creates a burden for + * implementers as there must be sufficient space in memory for the entire + * message, it prevents decrypted data from being made available before the + * authentication operation is complete and the data is known to be authentic. + */ +/**@{*/ + +/** \brief A function that performs a secure element authenticated encryption + * operation + * + * \param[in,out] drv_context The driver context structure. + * \param[in] key_slot Slot containing the key to use. + * \param[in] algorithm The AEAD algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(`alg`) is true) + * \param[in] p_nonce Nonce or IV to use + * \param[in] nonce_length Size of the `p_nonce` buffer in bytes + * \param[in] p_additional_data Additional data that will be + * authenticated but not encrypted + * \param[in] additional_data_length Size of `p_additional_data` in bytes + * \param[in] p_plaintext Data that will be authenticated and + * encrypted + * \param[in] plaintext_length Size of `p_plaintext` in bytes + * \param[out] p_ciphertext Output buffer for the authenticated and + * encrypted data. The additional data is + * not part of this output. For algorithms + * where the encrypted data and the + * authentication tag are defined as + * separate outputs, the authentication + * tag is appended to the encrypted data. + * \param[in] ciphertext_size Size of the `p_ciphertext` buffer in + * bytes + * \param[out] p_ciphertext_length On success, the size of the output in + * the `p_ciphertext` buffer + * + * \retval #PSA_SUCCESS + * Success. + */ +typedef psa_status_t (*psa_drv_se_aead_encrypt_t)(psa_drv_se_context_t *drv_context, + psa_key_slot_number_t key_slot, + psa_algorithm_t algorithm, + const uint8_t *p_nonce, + size_t nonce_length, + const uint8_t *p_additional_data, + size_t additional_data_length, + const uint8_t *p_plaintext, + size_t plaintext_length, + uint8_t *p_ciphertext, + size_t ciphertext_size, + size_t *p_ciphertext_length); + +/** A function that peforms a secure element authenticated decryption operation + * + * \param[in,out] drv_context The driver context structure. + * \param[in] key_slot Slot containing the key to use + * \param[in] algorithm The AEAD algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(`alg`) is true) + * \param[in] p_nonce Nonce or IV to use + * \param[in] nonce_length Size of the `p_nonce` buffer in bytes + * \param[in] p_additional_data Additional data that has been + * authenticated but not encrypted + * \param[in] additional_data_length Size of `p_additional_data` in bytes + * \param[in] p_ciphertext Data that has been authenticated and + * encrypted. + * For algorithms where the encrypted data + * and the authentication tag are defined + * as separate inputs, the buffer must + * contain the encrypted data followed by + * the authentication tag. + * \param[in] ciphertext_length Size of `p_ciphertext` in bytes + * \param[out] p_plaintext Output buffer for the decrypted data + * \param[in] plaintext_size Size of the `p_plaintext` buffer in + * bytes + * \param[out] p_plaintext_length On success, the size of the output in + * the `p_plaintext` buffer + * + * \retval #PSA_SUCCESS + * Success. + */ +typedef psa_status_t (*psa_drv_se_aead_decrypt_t)(psa_drv_se_context_t *drv_context, + psa_key_slot_number_t key_slot, + psa_algorithm_t algorithm, + const uint8_t *p_nonce, + size_t nonce_length, + const uint8_t *p_additional_data, + size_t additional_data_length, + const uint8_t *p_ciphertext, + size_t ciphertext_length, + uint8_t *p_plaintext, + size_t plaintext_size, + size_t *p_plaintext_length); + +/** + * \brief A struct containing all of the function pointers needed to implement + * secure element Authenticated Encryption with Additional Data operations + * + * PSA Crypto API implementations should populate instances of the table as + * appropriate upon startup. + * + * If one of the functions is not implemented, it should be set to NULL. + */ +typedef struct { + /** Function that performs the AEAD encrypt operation */ + psa_drv_se_aead_encrypt_t p_encrypt; + /** Function that performs the AEAD decrypt operation */ + psa_drv_se_aead_decrypt_t p_decrypt; +} psa_drv_se_aead_t; +/**@}*/ + +/** \defgroup se_key_management Secure Element Key Management + * Currently, key management is limited to importing keys in the clear, + * destroying keys, and exporting keys in the clear. + * Whether a key may be exported is determined by the key policies in place + * on the key slot. + */ +/**@{*/ + +/** An enumeration indicating how a key is created. + */ +typedef enum +{ + PSA_KEY_CREATION_IMPORT, /**< During psa_import_key() */ + PSA_KEY_CREATION_GENERATE, /**< During psa_generate_key() */ + PSA_KEY_CREATION_DERIVE, /**< During psa_key_derivation_output_key() */ + PSA_KEY_CREATION_COPY, /**< During psa_copy_key() */ + +#ifndef __DOXYGEN_ONLY__ + /** A key is being registered with mbedtls_psa_register_se_key(). + * + * The core only passes this value to + * psa_drv_se_key_management_t::p_validate_slot_number, not to + * psa_drv_se_key_management_t::p_allocate. The call to + * `p_validate_slot_number` is not followed by any other call to the + * driver: the key is considered successfully registered if the call to + * `p_validate_slot_number` succeeds, or if `p_validate_slot_number` is + * null. + * + * With this creation method, the driver must return #PSA_SUCCESS if + * the given attributes are compatible with the existing key in the slot, + * and #PSA_ERROR_DOES_NOT_EXIST if the driver can determine that there + * is no key with the specified slot number. + * + * This is an Mbed Crypto extension. + */ + PSA_KEY_CREATION_REGISTER, +#endif +} psa_key_creation_method_t; + +/** \brief A function that allocates a slot for a key. + * + * To create a key in a specific slot in a secure element, the core + * first calls this function to determine a valid slot number, + * then calls a function to create the key material in that slot. + * In nominal conditions (that is, if no error occurs), + * the effect of a call to a key creation function in the PSA Cryptography + * API with a lifetime that places the key in a secure element is the + * following: + * -# The core calls psa_drv_se_key_management_t::p_allocate + * (or in some implementations + * psa_drv_se_key_management_t::p_validate_slot_number). The driver + * selects (or validates) a suitable slot number given the key attributes + * and the state of the secure element. + * -# The core calls a key creation function in the driver. + * + * The key creation functions in the PSA Cryptography API are: + * - psa_import_key(), which causes + * a call to `p_allocate` with \p method = #PSA_KEY_CREATION_IMPORT + * then a call to psa_drv_se_key_management_t::p_import. + * - psa_generate_key(), which causes + * a call to `p_allocate` with \p method = #PSA_KEY_CREATION_GENERATE + * then a call to psa_drv_se_key_management_t::p_import. + * - psa_key_derivation_output_key(), which causes + * a call to `p_allocate` with \p method = #PSA_KEY_CREATION_DERIVE + * then a call to psa_drv_se_key_derivation_t::p_derive. + * - psa_copy_key(), which causes + * a call to `p_allocate` with \p method = #PSA_KEY_CREATION_COPY + * then a call to psa_drv_se_key_management_t::p_export. + * + * In case of errors, other behaviors are possible. + * - If the PSA Cryptography subsystem dies after the first step, + * for example because the device has lost power abruptly, + * the second step may never happen, or may happen after a reset + * and re-initialization. Alternatively, after a reset and + * re-initialization, the core may call + * psa_drv_se_key_management_t::p_destroy on the slot number that + * was allocated (or validated) instead of calling a key creation function. + * - If an error occurs, the core may call + * psa_drv_se_key_management_t::p_destroy on the slot number that + * was allocated (or validated) instead of calling a key creation function. + * + * Errors and system resets also have an impact on the driver's persistent + * data. If a reset happens before the overall key creation process is + * completed (before or after the second step above), it is unspecified + * whether the persistent data after the reset is identical to what it + * was before or after the call to `p_allocate` (or `p_validate_slot_number`). + * + * \param[in,out] drv_context The driver context structure. + * \param[in,out] persistent_data A pointer to the persistent data + * that allows writing. + * \param[in] attributes Attributes of the key. + * \param method The way in which the key is being created. + * \param[out] key_slot Slot where the key will be stored. + * This must be a valid slot for a key of the + * chosen type. It must be unoccupied. + * + * \retval #PSA_SUCCESS + * Success. + * The core will record \c *key_slot as the key slot where the key + * is stored and will update the persistent data in storage. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE + */ +typedef psa_status_t (*psa_drv_se_allocate_key_t)( + psa_drv_se_context_t *drv_context, + void *persistent_data, + const psa_key_attributes_t *attributes, + psa_key_creation_method_t method, + psa_key_slot_number_t *key_slot); + +/** \brief A function that determines whether a slot number is valid + * for a key. + * + * To create a key in a specific slot in a secure element, the core + * first calls this function to validate the choice of slot number, + * then calls a function to create the key material in that slot. + * See the documentation of #psa_drv_se_allocate_key_t for more details. + * + * As of the PSA Cryptography API specification version 1.0, there is no way + * for applications to trigger a call to this function. However some + * implementations offer the capability to create or declare a key in + * a specific slot via implementation-specific means, generally for the + * sake of initial device provisioning or onboarding. Such a mechanism may + * be added to a future version of the PSA Cryptography API specification. + * + * This function may update the driver's persistent data through + * \p persistent_data. The core will save the updated persistent data at the + * end of the key creation process. See the description of + * ::psa_drv_se_allocate_key_t for more information. + * + * \param[in,out] drv_context The driver context structure. + * \param[in,out] persistent_data A pointer to the persistent data + * that allows writing. + * \param[in] attributes Attributes of the key. + * \param method The way in which the key is being created. + * \param[in] key_slot Slot where the key is to be stored. + * + * \retval #PSA_SUCCESS + * The given slot number is valid for a key with the given + * attributes. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The given slot number is not valid for a key with the + * given attributes. This includes the case where the slot + * number is not valid at all. + * \retval #PSA_ERROR_ALREADY_EXISTS + * There is already a key with the specified slot number. + * Drivers may choose to return this error from the key + * creation function instead. + */ +typedef psa_status_t (*psa_drv_se_validate_slot_number_t)( + psa_drv_se_context_t *drv_context, + void *persistent_data, + const psa_key_attributes_t *attributes, + psa_key_creation_method_t method, + psa_key_slot_number_t key_slot); + +/** \brief A function that imports a key into a secure element in binary format + * + * This function can support any output from psa_export_key(). Refer to the + * documentation of psa_export_key() for the format for each key type. + * + * \param[in,out] drv_context The driver context structure. + * \param key_slot Slot where the key will be stored. + * This must be a valid slot for a key of the + * chosen type. It must be unoccupied. + * \param[in] attributes The key attributes, including the lifetime, + * the key type and the usage policy. + * Drivers should not access the key size stored + * in the attributes: it may not match the + * data passed in \p data. + * Drivers can call psa_get_key_lifetime(), + * psa_get_key_type(), + * psa_get_key_usage_flags() and + * psa_get_key_algorithm() to access this + * information. + * \param[in] data Buffer containing the key data. + * \param[in] data_length Size of the \p data buffer in bytes. + * \param[out] bits On success, the key size in bits. The driver + * must determine this value after parsing the + * key according to the key type. + * This value is not used if the function fails. + * + * \retval #PSA_SUCCESS + * Success. + */ +typedef psa_status_t (*psa_drv_se_import_key_t)( + psa_drv_se_context_t *drv_context, + psa_key_slot_number_t key_slot, + const psa_key_attributes_t *attributes, + const uint8_t *data, + size_t data_length, + size_t *bits); + +/** + * \brief A function that destroys a secure element key and restore the slot to + * its default state + * + * This function destroys the content of the key from a secure element. + * Implementations shall make a best effort to ensure that any previous content + * of the slot is unrecoverable. + * + * This function returns the specified slot to its default state. + * + * \param[in,out] drv_context The driver context structure. + * \param[in,out] persistent_data A pointer to the persistent data + * that allows writing. + * \param key_slot The key slot to erase. + * + * \retval #PSA_SUCCESS + * The slot's content, if any, has been erased. + */ +typedef psa_status_t (*psa_drv_se_destroy_key_t)( + psa_drv_se_context_t *drv_context, + void *persistent_data, + psa_key_slot_number_t key_slot); + +/** + * \brief A function that exports a secure element key in binary format + * + * The output of this function can be passed to psa_import_key() to + * create an equivalent object. + * + * If a key is created with `psa_import_key()` and then exported with + * this function, it is not guaranteed that the resulting data is + * identical: the implementation may choose a different representation + * of the same key if the format permits it. + * + * This function should generate output in the same format that + * `psa_export_key()` does. Refer to the + * documentation of `psa_export_key()` for the format for each key type. + * + * \param[in,out] drv_context The driver context structure. + * \param[in] key Slot whose content is to be exported. This must + * be an occupied key slot. + * \param[out] p_data Buffer where the key data is to be written. + * \param[in] data_size Size of the `p_data` buffer in bytes. + * \param[out] p_data_length On success, the number of bytes + * that make up the key data. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_DOES_NOT_EXIST + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + */ +typedef psa_status_t (*psa_drv_se_export_key_t)(psa_drv_se_context_t *drv_context, + psa_key_slot_number_t key, + uint8_t *p_data, + size_t data_size, + size_t *p_data_length); + +/** + * \brief A function that generates a symmetric or asymmetric key on a secure + * element + * + * If \p type is asymmetric (#PSA_KEY_TYPE_IS_ASYMMETRIC(\p type) = 1), + * the driver may export the public key at the time of generation, + * in the format documented for psa_export_public_key() by writing it + * to the \p pubkey buffer. + * This is optional, intended for secure elements that output the + * public key at generation time and that cannot export the public key + * later. Drivers that do not need this feature should leave + * \p *pubkey_length set to 0 and should + * implement the psa_drv_key_management_t::p_export_public function. + * Some implementations do not support this feature, in which case + * \p pubkey is \c NULL and \p pubkey_size is 0. + * + * \param[in,out] drv_context The driver context structure. + * \param key_slot Slot where the key will be stored. + * This must be a valid slot for a key of the + * chosen type. It must be unoccupied. + * \param[in] attributes The key attributes, including the lifetime, + * the key type and size, and the usage policy. + * Drivers can call psa_get_key_lifetime(), + * psa_get_key_type(), psa_get_key_bits(), + * psa_get_key_usage_flags() and + * psa_get_key_algorithm() to access this + * information. + * \param[out] pubkey A buffer where the driver can write the + * public key, when generating an asymmetric + * key pair. + * This is \c NULL when generating a symmetric + * key or if the core does not support + * exporting the public key at generation time. + * \param pubkey_size The size of the `pubkey` buffer in bytes. + * This is 0 when generating a symmetric + * key or if the core does not support + * exporting the public key at generation time. + * \param[out] pubkey_length On entry, this is always 0. + * On success, the number of bytes written to + * \p pubkey. If this is 0 or unchanged on return, + * the core will not read the \p pubkey buffer, + * and will instead call the driver's + * psa_drv_key_management_t::p_export_public + * function to export the public key when needed. + */ +typedef psa_status_t (*psa_drv_se_generate_key_t)( + psa_drv_se_context_t *drv_context, + psa_key_slot_number_t key_slot, + const psa_key_attributes_t *attributes, + uint8_t *pubkey, size_t pubkey_size, size_t *pubkey_length); + +/** + * \brief A struct containing all of the function pointers needed to for secure + * element key management + * + * PSA Crypto API implementations should populate instances of the table as + * appropriate upon startup or at build time. + * + * If one of the functions is not implemented, it should be set to NULL. + */ +typedef struct { + /** Function that allocates a slot for a key. */ + psa_drv_se_allocate_key_t p_allocate; + /** Function that checks the validity of a slot for a key. */ + psa_drv_se_validate_slot_number_t p_validate_slot_number; + /** Function that performs a key import operation */ + psa_drv_se_import_key_t p_import; + /** Function that performs a generation */ + psa_drv_se_generate_key_t p_generate; + /** Function that performs a key destroy operation */ + psa_drv_se_destroy_key_t p_destroy; + /** Function that performs a key export operation */ + psa_drv_se_export_key_t p_export; + /** Function that performs a public key export operation */ + psa_drv_se_export_key_t p_export_public; +} psa_drv_se_key_management_t; + +/**@}*/ + +/** \defgroup driver_derivation Secure Element Key Derivation and Agreement + * Key derivation is the process of generating new key material using an + * existing key and additional parameters, iterating through a basic + * cryptographic function, such as a hash. + * Key agreement is a part of cryptographic protocols that allows two parties + * to agree on the same key value, but starting from different original key + * material. + * The flows are similar, and the PSA Crypto Driver Model uses the same functions + * for both of the flows. + * + * There are two different final functions for the flows, + * `psa_drv_se_key_derivation_derive` and `psa_drv_se_key_derivation_export`. + * `psa_drv_se_key_derivation_derive` is used when the key material should be + * placed in a slot on the hardware and not exposed to the caller. + * `psa_drv_se_key_derivation_export` is used when the key material should be + * returned to the PSA Cryptographic API implementation. + * + * Different key derivation algorithms require a different number of inputs. + * Instead of having an API that takes as input variable length arrays, which + * can be problemmatic to manage on embedded platforms, the inputs are passed + * to the driver via a function, `psa_drv_se_key_derivation_collateral`, that + * is called multiple times with different `collateral_id`s. Thus, for a key + * derivation algorithm that required 3 paramter inputs, the flow would look + * something like: + * ~~~~~~~~~~~~~{.c} + * psa_drv_se_key_derivation_setup(kdf_algorithm, source_key, dest_key_size_bytes); + * psa_drv_se_key_derivation_collateral(kdf_algorithm_collateral_id_0, + * p_collateral_0, + * collateral_0_size); + * psa_drv_se_key_derivation_collateral(kdf_algorithm_collateral_id_1, + * p_collateral_1, + * collateral_1_size); + * psa_drv_se_key_derivation_collateral(kdf_algorithm_collateral_id_2, + * p_collateral_2, + * collateral_2_size); + * psa_drv_se_key_derivation_derive(); + * ~~~~~~~~~~~~~ + * + * key agreement example: + * ~~~~~~~~~~~~~{.c} + * psa_drv_se_key_derivation_setup(alg, source_key. dest_key_size_bytes); + * psa_drv_se_key_derivation_collateral(DHE_PUBKEY, p_pubkey, pubkey_size); + * psa_drv_se_key_derivation_export(p_session_key, + * session_key_size, + * &session_key_length); + * ~~~~~~~~~~~~~ + */ +/**@{*/ + +/** \brief A function that Sets up a secure element key derivation operation by + * specifying the algorithm and the source key sot + * + * \param[in,out] drv_context The driver context structure. + * \param[in,out] op_context A hardware-specific structure containing any + * context information for the implementation + * \param[in] kdf_alg The algorithm to be used for the key derivation + * \param[in] source_key The key to be used as the source material for + * the key derivation + * + * \retval PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_se_key_derivation_setup_t)(psa_drv_se_context_t *drv_context, + void *op_context, + psa_algorithm_t kdf_alg, + psa_key_slot_number_t source_key); + +/** \brief A function that provides collateral (parameters) needed for a secure + * element key derivation or key agreement operation + * + * Since many key derivation algorithms require multiple parameters, it is + * expeced that this function may be called multiple times for the same + * operation, each with a different algorithm-specific `collateral_id` + * + * \param[in,out] op_context A hardware-specific structure containing any + * context information for the implementation + * \param[in] collateral_id An ID for the collateral being provided + * \param[in] p_collateral A buffer containing the collateral data + * \param[in] collateral_size The size in bytes of the collateral + * + * \retval PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_se_key_derivation_collateral_t)(void *op_context, + uint32_t collateral_id, + const uint8_t *p_collateral, + size_t collateral_size); + +/** \brief A function that performs the final secure element key derivation + * step and place the generated key material in a slot + * + * \param[in,out] op_context A hardware-specific structure containing any + * context information for the implementation + * \param[in] dest_key The slot where the generated key material + * should be placed + * + * \retval PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_se_key_derivation_derive_t)(void *op_context, + psa_key_slot_number_t dest_key); + +/** \brief A function that performs the final step of a secure element key + * agreement and place the generated key material in a buffer + * + * \param[out] p_output Buffer in which to place the generated key + * material + * \param[in] output_size The size in bytes of `p_output` + * \param[out] p_output_length Upon success, contains the number of bytes of + * key material placed in `p_output` + * + * \retval PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_se_key_derivation_export_t)(void *op_context, + uint8_t *p_output, + size_t output_size, + size_t *p_output_length); + +/** + * \brief A struct containing all of the function pointers needed to for secure + * element key derivation and agreement + * + * PSA Crypto API implementations should populate instances of the table as + * appropriate upon startup. + * + * If one of the functions is not implemented, it should be set to NULL. + */ +typedef struct { + /** The driver-specific size of the key derivation context */ + size_t context_size; + /** Function that performs a key derivation setup */ + psa_drv_se_key_derivation_setup_t p_setup; + /** Function that sets key derivation collateral */ + psa_drv_se_key_derivation_collateral_t p_collateral; + /** Function that performs a final key derivation step */ + psa_drv_se_key_derivation_derive_t p_derive; + /** Function that perforsm a final key derivation or agreement and + * exports the key */ + psa_drv_se_key_derivation_export_t p_export; +} psa_drv_se_key_derivation_t; + +/**@}*/ + +/** \defgroup se_registration Secure element driver registration + */ +/**@{*/ + +/** A structure containing pointers to all the entry points of a + * secure element driver. + * + * Future versions of this specification may add extra substructures at + * the end of this structure. + */ +typedef struct { + /** The version of the driver HAL that this driver implements. + * This is a protection against loading driver binaries built against + * a different version of this specification. + * Use #PSA_DRV_SE_HAL_VERSION. + */ + uint32_t hal_version; + + /** The size of the driver's persistent data in bytes. + * + * This can be 0 if the driver does not need persistent data. + * + * See the documentation of psa_drv_se_context_t::persistent_data + * for more information about why and how a driver can use + * persistent data. + */ + size_t persistent_data_size; + + /** The driver initialization function. + * + * This function is called once during the initialization of the + * PSA Cryptography subsystem, before any other function of the + * driver is called. If this function returns a failure status, + * the driver will be unusable, at least until the next system reset. + * + * If this field is \c NULL, it is equivalent to a function that does + * nothing and returns #PSA_SUCCESS. + */ + psa_drv_se_init_t p_init; + + const psa_drv_se_key_management_t *key_management; + const psa_drv_se_mac_t *mac; + const psa_drv_se_cipher_t *cipher; + const psa_drv_se_aead_t *aead; + const psa_drv_se_asymmetric_t *asymmetric; + const psa_drv_se_key_derivation_t *derivation; +} psa_drv_se_t; + +/** The current version of the secure element driver HAL. + */ +/* 0.0.0 patchlevel 5 */ +#define PSA_DRV_SE_HAL_VERSION 0x00000005 + +/** Register an external cryptoprocessor (secure element) driver. + * + * This function is only intended to be used by driver code, not by + * application code. In implementations with separation between the + * PSA cryptography module and applications, this function should + * only be available to callers that run in the same memory space as + * the cryptography module, and should not be exposed to applications + * running in a different memory space. + * + * This function may be called before psa_crypto_init(). It is + * implementation-defined whether this function may be called + * after psa_crypto_init(). + * + * \note Implementations store metadata about keys including the lifetime + * value, which contains the driver's location indicator. Therefore, + * from one instantiation of the PSA Cryptography + * library to the next one, if there is a key in storage with a certain + * lifetime value, you must always register the same driver (or an + * updated version that communicates with the same secure element) + * with the same location value. + * + * \param location The location value through which this driver will + * be exposed to applications. + * This driver will be used for all keys such that + * `location == PSA_KEY_LIFETIME_LOCATION( lifetime )`. + * The value #PSA_KEY_LOCATION_LOCAL_STORAGE is reserved + * and may not be used for drivers. Implementations + * may reserve other values. + * \param[in] methods The method table of the driver. This structure must + * remain valid for as long as the cryptography + * module keeps running. It is typically a global + * constant. + * + * \return PSA_SUCCESS + * The driver was successfully registered. Applications can now + * use \p lifetime to access keys through the methods passed to + * this function. + * \return PSA_ERROR_BAD_STATE + * This function was called after the initialization of the + * cryptography module, and this implementation does not support + * driver registration at this stage. + * \return PSA_ERROR_ALREADY_EXISTS + * There is already a registered driver for this value of \p lifetime. + * \return PSA_ERROR_INVALID_ARGUMENT + * \p lifetime is a reserved value. + * \return PSA_ERROR_NOT_SUPPORTED + * `methods->hal_version` is not supported by this implementation. + * \return PSA_ERROR_INSUFFICIENT_MEMORY + * \return PSA_ERROR_NOT_PERMITTED + */ +psa_status_t psa_register_se_driver( + psa_key_location_t location, + const psa_drv_se_t *methods); + +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* PSA_CRYPTO_SE_DRIVER_H */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/psa/crypto_sizes.h b/Android/Level4/app/src/main/c/mbedtls/include/psa/crypto_sizes.h new file mode 100644 index 0000000..4dc8ad4 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/psa/crypto_sizes.h @@ -0,0 +1,747 @@ +/** + * \file psa/crypto_sizes.h + * + * \brief PSA cryptography module: Mbed TLS buffer size macros + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. + * + * This file contains the definitions of macros that are useful to + * compute buffer sizes. The signatures and semantics of these macros + * are standardized, but the definitions are not, because they depend on + * the available algorithms and, in some cases, on permitted tolerances + * on buffer sizes. + * + * In implementations with isolation between the application and the + * cryptography module, implementers should take care to ensure that + * the definitions that are exposed to applications match what the + * module implements. + * + * Macros that compute sizes whose values do not depend on the + * implementation are in crypto.h. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 PSA_CRYPTO_SIZES_H +#define PSA_CRYPTO_SIZES_H + +/* Include the Mbed TLS configuration file, the way Mbed TLS does it + * in each of its header files. */ +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#define PSA_BITS_TO_BYTES(bits) (((bits) + 7) / 8) +#define PSA_BYTES_TO_BITS(bytes) ((bytes) * 8) + +#define PSA_ROUND_UP_TO_MULTIPLE(block_size, length) \ + (((length) + (block_size) - 1) / (block_size) * (block_size)) + +/** The size of the output of psa_hash_finish(), in bytes. + * + * This is also the hash size that psa_hash_verify() expects. + * + * \param alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p alg) is true), or an HMAC algorithm + * (#PSA_ALG_HMAC(\c hash_alg) where \c hash_alg is a + * hash algorithm). + * + * \return The hash size for the specified hash algorithm. + * If the hash algorithm is not recognized, return 0. + * An implementation may return either 0 or the correct size + * for a hash algorithm that it recognizes, but does not support. + */ +#define PSA_HASH_SIZE(alg) \ + ( \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD2 ? 16 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD4 ? 16 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD5 ? 16 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_RIPEMD160 ? 20 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_1 ? 20 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_224 ? 28 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_256 ? 32 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_384 ? 48 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512 ? 64 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_224 ? 28 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_256 ? 32 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_224 ? 28 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_256 ? 32 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_384 ? 48 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_512 ? 64 : \ + 0) + +/** \def PSA_HASH_MAX_SIZE + * + * Maximum size of a hash. + * + * This macro must expand to a compile-time constant integer. This value + * should be the maximum size of a hash supported by the implementation, + * in bytes, and must be no smaller than this maximum. + */ +/* Note: for HMAC-SHA-3, the block size is 144 bytes for HMAC-SHA3-226, + * 136 bytes for HMAC-SHA3-256, 104 bytes for SHA3-384, 72 bytes for + * HMAC-SHA3-512. */ +#if defined(MBEDTLS_SHA512_C) +#define PSA_HASH_MAX_SIZE 64 +#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 128 +#else +#define PSA_HASH_MAX_SIZE 32 +#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 64 +#endif + +/** \def PSA_MAC_MAX_SIZE + * + * Maximum size of a MAC. + * + * This macro must expand to a compile-time constant integer. This value + * should be the maximum size of a MAC supported by the implementation, + * in bytes, and must be no smaller than this maximum. + */ +/* All non-HMAC MACs have a maximum size that's smaller than the + * minimum possible value of PSA_HASH_MAX_SIZE in this implementation. */ +/* Note that the encoding of truncated MAC algorithms limits this value + * to 64 bytes. + */ +#define PSA_MAC_MAX_SIZE PSA_HASH_MAX_SIZE + +/** The tag size for an AEAD algorithm, in bytes. + * + * \param alg An AEAD algorithm + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \return The tag size for the specified algorithm. + * If the AEAD algorithm does not have an identified + * tag that can be distinguished from the rest of + * the ciphertext, return 0. + * If the AEAD algorithm is not recognized, return 0. + * An implementation may return either 0 or a + * correct size for an AEAD algorithm that it + * recognizes, but does not support. + */ +#define PSA_AEAD_TAG_LENGTH(alg) \ + (PSA_ALG_IS_AEAD(alg) ? \ + (((alg) & PSA_ALG_AEAD_TAG_LENGTH_MASK) >> PSA_AEAD_TAG_LENGTH_OFFSET) : \ + 0) + +/* The maximum size of an RSA key on this implementation, in bits. + * This is a vendor-specific macro. + * + * Mbed TLS does not set a hard limit on the size of RSA keys: any key + * whose parameters fit in a bignum is accepted. However large keys can + * induce a large memory usage and long computation times. Unlike other + * auxiliary macros in this file and in crypto.h, which reflect how the + * library is configured, this macro defines how the library is + * configured. This implementation refuses to import or generate an + * RSA key whose size is larger than the value defined here. + * + * Note that an implementation may set different size limits for different + * operations, and does not need to accept all key sizes up to the limit. */ +#define PSA_VENDOR_RSA_MAX_KEY_BITS 4096 + +/* The maximum size of an ECC key on this implementation, in bits. + * This is a vendor-specific macro. */ +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 521 +#elif defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 512 +#elif defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 448 +#elif defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 384 +#elif defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 384 +#elif defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 256 +#elif defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 256 +#elif defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 256 +#elif defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 255 +#elif defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 224 +#elif defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 224 +#elif defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 192 +#elif defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 192 +#else +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 0 +#endif + +/** \def PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN + * + * This macro returns the maximum length of the PSK supported + * by the TLS-1.2 PSK-to-MS key derivation. + * + * Quoting RFC 4279, Sect 5.3: + * TLS implementations supporting these ciphersuites MUST support + * arbitrary PSK identities up to 128 octets in length, and arbitrary + * PSKs up to 64 octets in length. Supporting longer identities and + * keys is RECOMMENDED. + * + * Therefore, no implementation should define a value smaller than 64 + * for #PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN. + */ +#define PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN 128 + +/** The maximum size of a block cipher supported by the implementation. */ +#define PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE 16 + +/** The size of the output of psa_mac_sign_finish(), in bytes. + * + * This is also the MAC size that psa_mac_verify_finish() expects. + * + * \param key_type The type of the MAC key. + * \param key_bits The size of the MAC key in bits. + * \param alg A MAC algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_MAC(\p alg) is true). + * + * \return The MAC size for the specified algorithm with + * the specified key parameters. + * \return 0 if the MAC algorithm is not recognized. + * \return Either 0 or the correct size for a MAC algorithm that + * the implementation recognizes, but does not support. + * \return Unspecified if the key parameters are not consistent + * with the algorithm. + */ +#define PSA_MAC_FINAL_SIZE(key_type, key_bits, alg) \ + ((alg) & PSA_ALG_MAC_TRUNCATION_MASK ? PSA_MAC_TRUNCATED_LENGTH(alg) : \ + PSA_ALG_IS_HMAC(alg) ? PSA_HASH_SIZE(PSA_ALG_HMAC_GET_HASH(alg)) : \ + PSA_ALG_IS_BLOCK_CIPHER_MAC(alg) ? PSA_BLOCK_CIPHER_BLOCK_SIZE(key_type) : \ + ((void)(key_type), (void)(key_bits), 0)) + +/** The maximum size of the output of psa_aead_encrypt(), in bytes. + * + * If the size of the ciphertext buffer is at least this large, it is + * guaranteed that psa_aead_encrypt() will not fail due to an + * insufficient buffer size. Depending on the algorithm, the actual size of + * the ciphertext may be smaller. + * + * \param alg An AEAD algorithm + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * \param plaintext_length Size of the plaintext in bytes. + * + * \return The AEAD ciphertext size for the specified + * algorithm. + * If the AEAD algorithm is not recognized, return 0. + * An implementation may return either 0 or a + * correct size for an AEAD algorithm that it + * recognizes, but does not support. + */ +#define PSA_AEAD_ENCRYPT_OUTPUT_SIZE(alg, plaintext_length) \ + (PSA_AEAD_TAG_LENGTH(alg) != 0 ? \ + (plaintext_length) + PSA_AEAD_TAG_LENGTH(alg) : \ + 0) + +/** The maximum size of the output of psa_aead_decrypt(), in bytes. + * + * If the size of the plaintext buffer is at least this large, it is + * guaranteed that psa_aead_decrypt() will not fail due to an + * insufficient buffer size. Depending on the algorithm, the actual size of + * the plaintext may be smaller. + * + * \param alg An AEAD algorithm + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * \param ciphertext_length Size of the plaintext in bytes. + * + * \return The AEAD ciphertext size for the specified + * algorithm. + * If the AEAD algorithm is not recognized, return 0. + * An implementation may return either 0 or a + * correct size for an AEAD algorithm that it + * recognizes, but does not support. + */ +#define PSA_AEAD_DECRYPT_OUTPUT_SIZE(alg, ciphertext_length) \ + (PSA_AEAD_TAG_LENGTH(alg) != 0 ? \ + (ciphertext_length) - PSA_AEAD_TAG_LENGTH(alg) : \ + 0) + +/** A sufficient output buffer size for psa_aead_update(). + * + * If the size of the output buffer is at least this large, it is + * guaranteed that psa_aead_update() will not fail due to an + * insufficient buffer size. The actual size of the output may be smaller + * in any given call. + * + * \param alg An AEAD algorithm + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * \param input_length Size of the input in bytes. + * + * \return A sufficient output buffer size for the specified + * algorithm. + * If the AEAD algorithm is not recognized, return 0. + * An implementation may return either 0 or a + * correct size for an AEAD algorithm that it + * recognizes, but does not support. + */ +/* For all the AEAD modes defined in this specification, it is possible + * to emit output without delay. However, hardware may not always be + * capable of this. So for modes based on a block cipher, allow the + * implementation to delay the output until it has a full block. */ +#define PSA_AEAD_UPDATE_OUTPUT_SIZE(alg, input_length) \ + (PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ? \ + PSA_ROUND_UP_TO_MULTIPLE(PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE, (input_length)) : \ + (input_length)) + +/** A sufficient ciphertext buffer size for psa_aead_finish(). + * + * If the size of the ciphertext buffer is at least this large, it is + * guaranteed that psa_aead_finish() will not fail due to an + * insufficient ciphertext buffer size. The actual size of the output may + * be smaller in any given call. + * + * \param alg An AEAD algorithm + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \return A sufficient ciphertext buffer size for the + * specified algorithm. + * If the AEAD algorithm is not recognized, return 0. + * An implementation may return either 0 or a + * correct size for an AEAD algorithm that it + * recognizes, but does not support. + */ +#define PSA_AEAD_FINISH_OUTPUT_SIZE(alg) \ + (PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ? \ + PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE : \ + 0) + +/** A sufficient plaintext buffer size for psa_aead_verify(). + * + * If the size of the plaintext buffer is at least this large, it is + * guaranteed that psa_aead_verify() will not fail due to an + * insufficient plaintext buffer size. The actual size of the output may + * be smaller in any given call. + * + * \param alg An AEAD algorithm + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \return A sufficient plaintext buffer size for the + * specified algorithm. + * If the AEAD algorithm is not recognized, return 0. + * An implementation may return either 0 or a + * correct size for an AEAD algorithm that it + * recognizes, but does not support. + */ +#define PSA_AEAD_VERIFY_OUTPUT_SIZE(alg) \ + (PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ? \ + PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE : \ + 0) + +#define PSA_RSA_MINIMUM_PADDING_SIZE(alg) \ + (PSA_ALG_IS_RSA_OAEP(alg) ? \ + 2 * PSA_HASH_SIZE(PSA_ALG_RSA_OAEP_GET_HASH(alg)) + 1 : \ + 11 /*PKCS#1v1.5*/) + +/** + * \brief ECDSA signature size for a given curve bit size + * + * \param curve_bits Curve size in bits. + * \return Signature size in bytes. + * + * \note This macro returns a compile-time constant if its argument is one. + */ +#define PSA_ECDSA_SIGNATURE_SIZE(curve_bits) \ + (PSA_BITS_TO_BYTES(curve_bits) * 2) + +/** Sufficient signature buffer size for psa_sign_hash(). + * + * This macro returns a sufficient buffer size for a signature using a key + * of the specified type and size, with the specified algorithm. + * Note that the actual size of the signature may be smaller + * (some algorithms produce a variable-size signature). + * + * \warning This function may call its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * \param key_type An asymmetric key type (this may indifferently be a + * key pair type or a public key type). + * \param key_bits The size of the key in bits. + * \param alg The signature algorithm. + * + * \return If the parameters are valid and supported, return + * a buffer size in bytes that guarantees that + * psa_sign_hash() will not fail with + * #PSA_ERROR_BUFFER_TOO_SMALL. + * If the parameters are a valid combination that is not supported + * by the implementation, this macro shall return either a + * sensible size or 0. + * If the parameters are not valid, the + * return value is unspecified. + */ +#define PSA_SIGN_OUTPUT_SIZE(key_type, key_bits, alg) \ + (PSA_KEY_TYPE_IS_RSA(key_type) ? ((void)alg, PSA_BITS_TO_BYTES(key_bits)) : \ + PSA_KEY_TYPE_IS_ECC(key_type) ? PSA_ECDSA_SIGNATURE_SIZE(key_bits) : \ + ((void)alg, 0)) + +#define PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE \ + PSA_ECDSA_SIGNATURE_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) + +/** \def PSA_SIGNATURE_MAX_SIZE + * + * Maximum size of an asymmetric signature. + * + * This macro must expand to a compile-time constant integer. This value + * should be the maximum size of a signature supported by the implementation, + * in bytes, and must be no smaller than this maximum. + */ +#define PSA_SIGNATURE_MAX_SIZE \ + (PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS) > PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE ? \ + PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS) : \ + PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE) + +/** Sufficient output buffer size for psa_asymmetric_encrypt(). + * + * This macro returns a sufficient buffer size for a ciphertext produced using + * a key of the specified type and size, with the specified algorithm. + * Note that the actual size of the ciphertext may be smaller, depending + * on the algorithm. + * + * \warning This function may call its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * \param key_type An asymmetric key type (this may indifferently be a + * key pair type or a public key type). + * \param key_bits The size of the key in bits. + * \param alg The asymmetric encryption algorithm. + * + * \return If the parameters are valid and supported, return + * a buffer size in bytes that guarantees that + * psa_asymmetric_encrypt() will not fail with + * #PSA_ERROR_BUFFER_TOO_SMALL. + * If the parameters are a valid combination that is not supported + * by the implementation, this macro shall return either a + * sensible size or 0. + * If the parameters are not valid, the + * return value is unspecified. + */ +#define PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(key_type, key_bits, alg) \ + (PSA_KEY_TYPE_IS_RSA(key_type) ? \ + ((void)alg, PSA_BITS_TO_BYTES(key_bits)) : \ + 0) + +/** Sufficient output buffer size for psa_asymmetric_decrypt(). + * + * This macro returns a sufficient buffer size for a plaintext produced using + * a key of the specified type and size, with the specified algorithm. + * Note that the actual size of the plaintext may be smaller, depending + * on the algorithm. + * + * \warning This function may call its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * \param key_type An asymmetric key type (this may indifferently be a + * key pair type or a public key type). + * \param key_bits The size of the key in bits. + * \param alg The asymmetric encryption algorithm. + * + * \return If the parameters are valid and supported, return + * a buffer size in bytes that guarantees that + * psa_asymmetric_decrypt() will not fail with + * #PSA_ERROR_BUFFER_TOO_SMALL. + * If the parameters are a valid combination that is not supported + * by the implementation, this macro shall return either a + * sensible size or 0. + * If the parameters are not valid, the + * return value is unspecified. + */ +#define PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(key_type, key_bits, alg) \ + (PSA_KEY_TYPE_IS_RSA(key_type) ? \ + PSA_BITS_TO_BYTES(key_bits) - PSA_RSA_MINIMUM_PADDING_SIZE(alg) : \ + 0) + +/* Maximum size of the ASN.1 encoding of an INTEGER with the specified + * number of bits. + * + * This definition assumes that bits <= 2^19 - 9 so that the length field + * is at most 3 bytes. The length of the encoding is the length of the + * bit string padded to a whole number of bytes plus: + * - 1 type byte; + * - 1 to 3 length bytes; + * - 0 to 1 bytes of leading 0 due to the sign bit. + */ +#define PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(bits) \ + ((bits) / 8 + 5) + +/* Maximum size of the export encoding of an RSA public key. + * Assumes that the public exponent is less than 2^32. + * + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER } -- e + * + * - 4 bytes of SEQUENCE overhead; + * - n : INTEGER; + * - 7 bytes for the public exponent. + */ +#define PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(key_bits) \ + (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) + 11) + +/* Maximum size of the export encoding of an RSA key pair. + * Assumes thatthe public exponent is less than 2^32 and that the size + * difference between the two primes is at most 1 bit. + * + * RSAPrivateKey ::= SEQUENCE { + * version Version, -- 0 + * modulus INTEGER, -- N-bit + * publicExponent INTEGER, -- 32-bit + * privateExponent INTEGER, -- N-bit + * prime1 INTEGER, -- N/2-bit + * prime2 INTEGER, -- N/2-bit + * exponent1 INTEGER, -- N/2-bit + * exponent2 INTEGER, -- N/2-bit + * coefficient INTEGER, -- N/2-bit + * } + * + * - 4 bytes of SEQUENCE overhead; + * - 3 bytes of version; + * - 7 half-size INTEGERs plus 2 full-size INTEGERs, + * overapproximated as 9 half-size INTEGERS; + * - 7 bytes for the public exponent. + */ +#define PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(key_bits) \ + (9 * PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE((key_bits) / 2 + 1) + 14) + +/* Maximum size of the export encoding of a DSA public key. + * + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING } -- contains DSAPublicKey + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters Dss-Parms } -- SEQUENCE of 3 INTEGERs + * DSAPublicKey ::= INTEGER -- public key, Y + * + * - 3 * 4 bytes of SEQUENCE overhead; + * - 1 + 1 + 7 bytes of algorithm (DSA OID); + * - 4 bytes of BIT STRING overhead; + * - 3 full-size INTEGERs (p, g, y); + * - 1 + 1 + 32 bytes for 1 sub-size INTEGER (q <= 256 bits). + */ +#define PSA_KEY_EXPORT_DSA_PUBLIC_KEY_MAX_SIZE(key_bits) \ + (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) * 3 + 59) + +/* Maximum size of the export encoding of a DSA key pair. + * + * DSAPrivateKey ::= SEQUENCE { + * version Version, -- 0 + * prime INTEGER, -- p + * subprime INTEGER, -- q + * generator INTEGER, -- g + * public INTEGER, -- y + * private INTEGER, -- x + * } + * + * - 4 bytes of SEQUENCE overhead; + * - 3 bytes of version; + * - 3 full-size INTEGERs (p, g, y); + * - 2 * (1 + 1 + 32) bytes for 2 sub-size INTEGERs (q, x <= 256 bits). + */ +#define PSA_KEY_EXPORT_DSA_KEY_PAIR_MAX_SIZE(key_bits) \ + (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) * 3 + 75) + +/* Maximum size of the export encoding of an ECC public key. + * + * The representation of an ECC public key is: + * - The byte 0x04; + * - `x_P` as a `ceiling(m/8)`-byte string, big-endian; + * - `y_P` as a `ceiling(m/8)`-byte string, big-endian; + * - where m is the bit size associated with the curve. + * + * - 1 byte + 2 * point size. + */ +#define PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits) \ + (2 * PSA_BITS_TO_BYTES(key_bits) + 1) + +/* Maximum size of the export encoding of an ECC key pair. + * + * An ECC key pair is represented by the secret value. + */ +#define PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(key_bits) \ + (PSA_BITS_TO_BYTES(key_bits)) + +/** Sufficient output buffer size for psa_export_key() or psa_export_public_key(). + * + * This macro returns a compile-time constant if its arguments are + * compile-time constants. + * + * \warning This function may call its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * The following code illustrates how to allocate enough memory to export + * a key by querying the key type and size at runtime. + * \code{c} + * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + * psa_status_t status; + * status = psa_get_key_attributes(key, &attributes); + * if (status != PSA_SUCCESS) handle_error(...); + * psa_key_type_t key_type = psa_get_key_type(&attributes); + * size_t key_bits = psa_get_key_bits(&attributes); + * size_t buffer_size = PSA_KEY_EXPORT_MAX_SIZE(key_type, key_bits); + * psa_reset_key_attributes(&attributes); + * uint8_t *buffer = malloc(buffer_size); + * if (buffer == NULL) handle_error(...); + * size_t buffer_length; + * status = psa_export_key(key, buffer, buffer_size, &buffer_length); + * if (status != PSA_SUCCESS) handle_error(...); + * \endcode + * + * For psa_export_public_key(), calculate the buffer size from the + * public key type. You can use the macro #PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR + * to convert a key pair type to the corresponding public key type. + * \code{c} + * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + * psa_status_t status; + * status = psa_get_key_attributes(key, &attributes); + * if (status != PSA_SUCCESS) handle_error(...); + * psa_key_type_t key_type = psa_get_key_type(&attributes); + * psa_key_type_t public_key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(key_type); + * size_t key_bits = psa_get_key_bits(&attributes); + * size_t buffer_size = PSA_KEY_EXPORT_MAX_SIZE(public_key_type, key_bits); + * psa_reset_key_attributes(&attributes); + * uint8_t *buffer = malloc(buffer_size); + * if (buffer == NULL) handle_error(...); + * size_t buffer_length; + * status = psa_export_public_key(key, buffer, buffer_size, &buffer_length); + * if (status != PSA_SUCCESS) handle_error(...); + * \endcode + * + * \param key_type A supported key type. + * \param key_bits The size of the key in bits. + * + * \return If the parameters are valid and supported, return + * a buffer size in bytes that guarantees that + * psa_sign_hash() will not fail with + * #PSA_ERROR_BUFFER_TOO_SMALL. + * If the parameters are a valid combination that is not supported + * by the implementation, this macro shall return either a + * sensible size or 0. + * If the parameters are not valid, the + * return value is unspecified. + */ +#define PSA_KEY_EXPORT_MAX_SIZE(key_type, key_bits) \ + (PSA_KEY_TYPE_IS_UNSTRUCTURED(key_type) ? PSA_BITS_TO_BYTES(key_bits) : \ + (key_type) == PSA_KEY_TYPE_RSA_KEY_PAIR ? PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(key_bits) : \ + (key_type) == PSA_KEY_TYPE_RSA_PUBLIC_KEY ? PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(key_bits) : \ + (key_type) == PSA_KEY_TYPE_DSA_KEY_PAIR ? PSA_KEY_EXPORT_DSA_KEY_PAIR_MAX_SIZE(key_bits) : \ + (key_type) == PSA_KEY_TYPE_DSA_PUBLIC_KEY ? PSA_KEY_EXPORT_DSA_PUBLIC_KEY_MAX_SIZE(key_bits) : \ + PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type) ? PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(key_bits) : \ + PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(key_type) ? PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits) : \ + 0) + +/** The default nonce size for an AEAD algorithm, in bytes. + * + * This macro can be used to allocate a buffer of sufficient size to + * store the nonce output from #psa_aead_generate_nonce(). + * + * See also #PSA_AEAD_NONCE_MAX_SIZE. + * + * \note This is not the maximum size of nonce supported as input to #psa_aead_set_nonce(), + * #psa_aead_encrypt() or #psa_aead_decrypt(), just the default size that is generated by + * #psa_aead_generate_nonce(). + * + * \warning This macro may evaluate its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * \param key_type A symmetric key type that is compatible with algorithm \p alg. + * + * \param alg An AEAD algorithm (\c PSA_ALG_XXX value such that #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \return The default nonce size for the specified key type and algorithm. + * If the key type or AEAD algorithm is not recognized, + * or the parameters are incompatible, return 0. + * An implementation can return either 0 or a correct size for a key type + * and AEAD algorithm that it recognizes, but does not support. + */ +#define PSA_AEAD_NONCE_LENGTH(key_type, alg) \ + (PSA_BLOCK_CIPHER_BLOCK_SIZE(key_type) == 16 && \ + (PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH(alg) == PSA_ALG_CCM || \ + PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH(alg) == PSA_ALG_GCM) ? 12 : \ + (key_type) == PSA_KEY_TYPE_CHACHA20 && \ + PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH(alg) == PSA_ALG_CHACHA20_POLY1305 ? 12 : \ + 0) + +/** The maximum default nonce size among all supported pairs of key types and AEAD algorithms, in bytes. + * + * This is equal to or greater than any value that #PSA_AEAD_NONCE_LENGTH() may return. + * + * \note This is not the maximum size of nonce supported as input to #psa_aead_set_nonce(), + * #psa_aead_encrypt() or #psa_aead_decrypt(), just the largest size that may be generated by + * #psa_aead_generate_nonce(). + */ +#define PSA_AEAD_NONCE_MAX_SIZE 12 + +/** The default IV size for a cipher algorithm, in bytes. + * + * The IV that is generated as part of a call to #psa_cipher_encrypt() is always + * the default IV length for the algorithm. + * + * This macro can be used to allocate a buffer of sufficient size to + * store the IV output from #psa_cipher_generate_iv() when using + * a multi-part cipher operation. + * + * See also #PSA_CIPHER_IV_MAX_SIZE. + * + * \warning This macro may evaluate its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * \param key_type A symmetric key type that is compatible with algorithm \p alg. + * + * \param alg A cipher algorithm (\c PSA_ALG_XXX value such that #PSA_ALG_IS_CIPHER(\p alg) is true). + * + * \return The default IV size for the specified key type and algorithm. + * If the algorithm does not use an IV, return 0. + * If the key type or cipher algorithm is not recognized, + * or the parameters are incompatible, return 0. + * An implementation can return either 0 or a correct size for a key type + * and cipher algorithm that it recognizes, but does not support. + */ +#define PSA_CIPHER_IV_LENGTH(key_type, alg) \ + (PSA_BLOCK_CIPHER_BLOCK_SIZE(key_type) > 1 && \ + ((alg) == PSA_ALG_CTR || \ + (alg) == PSA_ALG_CFB || \ + (alg) == PSA_ALG_OFB || \ + (alg) == PSA_ALG_XTS || \ + (alg) == PSA_ALG_CBC_NO_PADDING || \ + (alg) == PSA_ALG_CBC_PKCS7) ? PSA_BLOCK_CIPHER_BLOCK_SIZE(key_type) : \ + (key_type) == PSA_KEY_TYPE_CHACHA20 && \ + (alg) == PSA_ALG_CHACHA20 ? 12 : \ + 0) + +/** The maximum IV size for all supported cipher algorithms, in bytes. + * + * See also #PSA_CIPHER_IV_LENGTH(). + */ +#define PSA_CIPHER_IV_MAX_SIZE 16 + +#endif /* PSA_CRYPTO_SIZES_H */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/psa/crypto_struct.h b/Android/Level4/app/src/main/c/mbedtls/include/psa/crypto_struct.h new file mode 100644 index 0000000..be0e280 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/psa/crypto_struct.h @@ -0,0 +1,482 @@ +/** + * \file psa/crypto_struct.h + * + * \brief PSA cryptography module: Mbed TLS structured type implementations + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. + * + * This file contains the definitions of some data structures with + * implementation-specific definitions. + * + * In implementations with isolation between the application and the + * cryptography module, it is expected that the front-end and the back-end + * would have different versions of this file. + * + *

Design notes about multipart operation structures

+ * + * Each multipart operation structure contains a `psa_algorithm_t alg` + * field which indicates which specific algorithm the structure is for. + * When the structure is not in use, `alg` is 0. Most of the structure + * consists of a union which is discriminated by `alg`. + * + * Note that when `alg` is 0, the content of other fields is undefined. + * In particular, it is not guaranteed that a freshly-initialized structure + * is all-zero: we initialize structures to something like `{0, 0}`, which + * is only guaranteed to initializes the first member of the union; + * GCC and Clang initialize the whole structure to 0 (at the time of writing), + * but MSVC and CompCert don't. + * + * In Mbed Crypto, multipart operation structures live independently from + * the key. This allows Mbed Crypto to free the key objects when destroying + * a key slot. If a multipart operation needs to remember the key after + * the setup function returns, the operation structure needs to contain a + * copy of the key. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 PSA_CRYPTO_STRUCT_H +#define PSA_CRYPTO_STRUCT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Include the Mbed TLS configuration file, the way Mbed TLS does it + * in each of its header files. */ +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/cipher.h" +#include "mbedtls/cmac.h" +#include "mbedtls/gcm.h" +#include "mbedtls/md.h" +#include "mbedtls/md2.h" +#include "mbedtls/md4.h" +#include "mbedtls/md5.h" +#include "mbedtls/ripemd160.h" +#include "mbedtls/sha1.h" +#include "mbedtls/sha256.h" +#include "mbedtls/sha512.h" + +typedef struct { + /** Unique ID indicating which driver got assigned to do the + * operation. Since driver contexts are driver-specific, swapping + * drivers halfway through the operation is not supported. + * ID values are auto-generated in psa_driver_wrappers.h */ + unsigned int id; + /** Context structure for the assigned driver, when id is not zero. */ + void* ctx; +} psa_operation_driver_context_t; + +struct psa_hash_operation_s +{ + psa_algorithm_t alg; + union + { + unsigned dummy; /* Make the union non-empty even with no supported algorithms. */ +#if defined(MBEDTLS_MD2_C) + mbedtls_md2_context md2; +#endif +#if defined(MBEDTLS_MD4_C) + mbedtls_md4_context md4; +#endif +#if defined(MBEDTLS_MD5_C) + mbedtls_md5_context md5; +#endif +#if defined(MBEDTLS_RIPEMD160_C) + mbedtls_ripemd160_context ripemd160; +#endif +#if defined(MBEDTLS_SHA1_C) + mbedtls_sha1_context sha1; +#endif +#if defined(MBEDTLS_SHA256_C) + mbedtls_sha256_context sha256; +#endif +#if defined(MBEDTLS_SHA512_C) + mbedtls_sha512_context sha512; +#endif + } ctx; +}; + +#define PSA_HASH_OPERATION_INIT {0, {0}} +static inline struct psa_hash_operation_s psa_hash_operation_init( void ) +{ + const struct psa_hash_operation_s v = PSA_HASH_OPERATION_INIT; + return( v ); +} + +#if defined(MBEDTLS_MD_C) +typedef struct +{ + /** The hash context. */ + struct psa_hash_operation_s hash_ctx; + /** The HMAC part of the context. */ + uint8_t opad[PSA_HMAC_MAX_HASH_BLOCK_SIZE]; +} psa_hmac_internal_data; +#endif /* MBEDTLS_MD_C */ + +struct psa_mac_operation_s +{ + psa_algorithm_t alg; + unsigned int key_set : 1; + unsigned int iv_required : 1; + unsigned int iv_set : 1; + unsigned int has_input : 1; + unsigned int is_sign : 1; + uint8_t mac_size; + union + { + unsigned dummy; /* Make the union non-empty even with no supported algorithms. */ +#if defined(MBEDTLS_MD_C) + psa_hmac_internal_data hmac; +#endif +#if defined(MBEDTLS_CMAC_C) + mbedtls_cipher_context_t cmac; +#endif + } ctx; +}; + +#define PSA_MAC_OPERATION_INIT {0, 0, 0, 0, 0, 0, 0, {0}} +static inline struct psa_mac_operation_s psa_mac_operation_init( void ) +{ + const struct psa_mac_operation_s v = PSA_MAC_OPERATION_INIT; + return( v ); +} + +struct psa_cipher_operation_s +{ + psa_algorithm_t alg; + unsigned int key_set : 1; + unsigned int iv_required : 1; + unsigned int iv_set : 1; + unsigned int mbedtls_in_use : 1; /* Indicates mbed TLS is handling the operation. */ + uint8_t iv_size; + uint8_t block_size; + union + { + unsigned dummy; /* Enable easier initializing of the union. */ + mbedtls_cipher_context_t cipher; + psa_operation_driver_context_t driver; + } ctx; +}; + +#define PSA_CIPHER_OPERATION_INIT {0, 0, 0, 0, 0, 0, 0, {0}} +static inline struct psa_cipher_operation_s psa_cipher_operation_init( void ) +{ + const struct psa_cipher_operation_s v = PSA_CIPHER_OPERATION_INIT; + return( v ); +} + +struct psa_aead_operation_s +{ + psa_algorithm_t alg; + unsigned int key_set : 1; + unsigned int iv_set : 1; + uint8_t iv_size; + uint8_t block_size; + union + { + unsigned dummy; /* Enable easier initializing of the union. */ + mbedtls_cipher_context_t cipher; + } ctx; +}; + +#define PSA_AEAD_OPERATION_INIT {0, 0, 0, 0, 0, {0}} +static inline struct psa_aead_operation_s psa_aead_operation_init( void ) +{ + const struct psa_aead_operation_s v = PSA_AEAD_OPERATION_INIT; + return( v ); +} + +#if defined(MBEDTLS_MD_C) +typedef struct +{ + uint8_t *info; + size_t info_length; + psa_hmac_internal_data hmac; + uint8_t prk[PSA_HASH_MAX_SIZE]; + uint8_t output_block[PSA_HASH_MAX_SIZE]; +#if PSA_HASH_MAX_SIZE > 0xff +#error "PSA_HASH_MAX_SIZE does not fit in uint8_t" +#endif + uint8_t offset_in_block; + uint8_t block_number; + unsigned int state : 2; + unsigned int info_set : 1; +} psa_hkdf_key_derivation_t; +#endif /* MBEDTLS_MD_C */ + +#if defined(MBEDTLS_MD_C) +typedef enum +{ + TLS12_PRF_STATE_INIT, /* no input provided */ + TLS12_PRF_STATE_SEED_SET, /* seed has been set */ + TLS12_PRF_STATE_KEY_SET, /* key has been set */ + TLS12_PRF_STATE_LABEL_SET, /* label has been set */ + TLS12_PRF_STATE_OUTPUT /* output has been started */ +} psa_tls12_prf_key_derivation_state_t; + +typedef struct psa_tls12_prf_key_derivation_s +{ +#if PSA_HASH_MAX_SIZE > 0xff +#error "PSA_HASH_MAX_SIZE does not fit in uint8_t" +#endif + + /* Indicates how many bytes in the current HMAC block have + * not yet been read by the user. */ + uint8_t left_in_block; + + /* The 1-based number of the block. */ + uint8_t block_number; + + psa_tls12_prf_key_derivation_state_t state; + + uint8_t *seed; + size_t seed_length; + uint8_t *label; + size_t label_length; + psa_hmac_internal_data hmac; + uint8_t Ai[PSA_HASH_MAX_SIZE]; + + /* `HMAC_hash( prk, A(i) + seed )` in the notation of RFC 5246, Sect. 5. */ + uint8_t output_block[PSA_HASH_MAX_SIZE]; +} psa_tls12_prf_key_derivation_t; +#endif /* MBEDTLS_MD_C */ + +struct psa_key_derivation_s +{ + psa_algorithm_t alg; + unsigned int can_output_key : 1; + size_t capacity; + union + { + /* Make the union non-empty even with no supported algorithms. */ + uint8_t dummy; +#if defined(MBEDTLS_MD_C) + psa_hkdf_key_derivation_t hkdf; + psa_tls12_prf_key_derivation_t tls12_prf; +#endif + } ctx; +}; + +/* This only zeroes out the first byte in the union, the rest is unspecified. */ +#define PSA_KEY_DERIVATION_OPERATION_INIT {0, 0, 0, {0}} +static inline struct psa_key_derivation_s psa_key_derivation_operation_init( void ) +{ + const struct psa_key_derivation_s v = PSA_KEY_DERIVATION_OPERATION_INIT; + return( v ); +} + +struct psa_key_policy_s +{ + psa_key_usage_t usage; + psa_algorithm_t alg; + psa_algorithm_t alg2; +}; +typedef struct psa_key_policy_s psa_key_policy_t; + +#define PSA_KEY_POLICY_INIT {0, 0, 0} +static inline struct psa_key_policy_s psa_key_policy_init( void ) +{ + const struct psa_key_policy_s v = PSA_KEY_POLICY_INIT; + return( v ); +} + +/* The type used internally for key sizes. + * Public interfaces use size_t, but internally we use a smaller type. */ +typedef uint16_t psa_key_bits_t; +/* The maximum value of the type used to represent bit-sizes. + * This is used to mark an invalid key size. */ +#define PSA_KEY_BITS_TOO_LARGE ( (psa_key_bits_t) ( -1 ) ) +/* The maximum size of a key in bits. + * Currently defined as the maximum that can be represented, rounded down + * to a whole number of bytes. + * This is an uncast value so that it can be used in preprocessor + * conditionals. */ +#define PSA_MAX_KEY_BITS 0xfff8 + +/** A mask of flags that can be stored in key attributes. + * + * This type is also used internally to store flags in slots. Internal + * flags are defined in library/psa_crypto_core.h. Internal flags may have + * the same value as external flags if they are properly handled during + * key creation and in psa_get_key_attributes. + */ +typedef uint16_t psa_key_attributes_flag_t; + +#define MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER \ + ( (psa_key_attributes_flag_t) 0x0001 ) + +/* A mask of key attribute flags used externally only. + * Only meant for internal checks inside the library. */ +#define MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY ( \ + MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER | \ + 0 ) + +/* A mask of key attribute flags used both internally and externally. + * Currently there aren't any. */ +#define MBEDTLS_PSA_KA_MASK_DUAL_USE ( \ + 0 ) + +typedef struct +{ + psa_key_type_t type; + psa_key_bits_t bits; + psa_key_lifetime_t lifetime; + mbedtls_svc_key_id_t id; + psa_key_policy_t policy; + psa_key_attributes_flag_t flags; +} psa_core_key_attributes_t; + +#define PSA_CORE_KEY_ATTRIBUTES_INIT {PSA_KEY_TYPE_NONE, 0, PSA_KEY_LIFETIME_VOLATILE, MBEDTLS_SVC_KEY_ID_INIT, PSA_KEY_POLICY_INIT, 0} + +struct psa_key_attributes_s +{ + psa_core_key_attributes_t core; +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + psa_key_slot_number_t slot_number; +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + void *domain_parameters; + size_t domain_parameters_size; +}; + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) +#define PSA_KEY_ATTRIBUTES_INIT {PSA_CORE_KEY_ATTRIBUTES_INIT, 0, NULL, 0} +#else +#define PSA_KEY_ATTRIBUTES_INIT {PSA_CORE_KEY_ATTRIBUTES_INIT, NULL, 0} +#endif + +static inline struct psa_key_attributes_s psa_key_attributes_init( void ) +{ + const struct psa_key_attributes_s v = PSA_KEY_ATTRIBUTES_INIT; + return( v ); +} + +static inline void psa_set_key_id( psa_key_attributes_t *attributes, + mbedtls_svc_key_id_t key ) +{ + attributes->core.id = key; + if( attributes->core.lifetime == PSA_KEY_LIFETIME_VOLATILE ) + attributes->core.lifetime = PSA_KEY_LIFETIME_PERSISTENT; +} + +static inline mbedtls_svc_key_id_t psa_get_key_id( + const psa_key_attributes_t *attributes) +{ + return( attributes->core.id ); +} + +static inline void psa_set_key_lifetime(psa_key_attributes_t *attributes, + psa_key_lifetime_t lifetime) +{ + attributes->core.lifetime = lifetime; + if( lifetime == PSA_KEY_LIFETIME_VOLATILE ) + { +#ifdef MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER + attributes->core.id.key_id = 0; +#else + attributes->core.id = 0; +#endif + } +} + +static inline psa_key_lifetime_t psa_get_key_lifetime( + const psa_key_attributes_t *attributes) +{ + return( attributes->core.lifetime ); +} + +static inline void psa_set_key_usage_flags(psa_key_attributes_t *attributes, + psa_key_usage_t usage_flags) +{ + attributes->core.policy.usage = usage_flags; +} + +static inline psa_key_usage_t psa_get_key_usage_flags( + const psa_key_attributes_t *attributes) +{ + return( attributes->core.policy.usage ); +} + +static inline void psa_set_key_algorithm(psa_key_attributes_t *attributes, + psa_algorithm_t alg) +{ + attributes->core.policy.alg = alg; +} + +static inline psa_algorithm_t psa_get_key_algorithm( + const psa_key_attributes_t *attributes) +{ + return( attributes->core.policy.alg ); +} + +/* This function is declared in crypto_extra.h, which comes after this + * header file, but we need the function here, so repeat the declaration. */ +psa_status_t psa_set_key_domain_parameters(psa_key_attributes_t *attributes, + psa_key_type_t type, + const uint8_t *data, + size_t data_length); + +static inline void psa_set_key_type(psa_key_attributes_t *attributes, + psa_key_type_t type) +{ + if( attributes->domain_parameters == NULL ) + { + /* Common case: quick path */ + attributes->core.type = type; + } + else + { + /* Call the bigger function to free the old domain paramteres. + * Ignore any errors which may arise due to type requiring + * non-default domain parameters, since this function can't + * report errors. */ + (void) psa_set_key_domain_parameters( attributes, type, NULL, 0 ); + } +} + +static inline psa_key_type_t psa_get_key_type( + const psa_key_attributes_t *attributes) +{ + return( attributes->core.type ); +} + +static inline void psa_set_key_bits(psa_key_attributes_t *attributes, + size_t bits) +{ + if( bits > PSA_MAX_KEY_BITS ) + attributes->core.bits = PSA_KEY_BITS_TOO_LARGE; + else + attributes->core.bits = (psa_key_bits_t) bits; +} + +static inline size_t psa_get_key_bits( + const psa_key_attributes_t *attributes) +{ + return( attributes->core.bits ); +} + +#ifdef __cplusplus +} +#endif + +#endif /* PSA_CRYPTO_STRUCT_H */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/psa/crypto_types.h b/Android/Level4/app/src/main/c/mbedtls/include/psa/crypto_types.h new file mode 100644 index 0000000..923b02b --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/psa/crypto_types.h @@ -0,0 +1,395 @@ +/** + * \file psa/crypto_types.h + * + * \brief PSA cryptography module: type aliases. + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. Drivers must include the appropriate driver + * header file. + * + * This file contains portable definitions of integral types for properties + * of cryptographic keys, designations of cryptographic algorithms, and + * error codes returned by the library. + * + * This header file does not declare any function. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 PSA_CRYPTO_TYPES_H +#define PSA_CRYPTO_TYPES_H + +#include "crypto_platform.h" + +#include + +/** \defgroup error Error codes + * @{ + */ + +/** + * \brief Function return status. + * + * This is either #PSA_SUCCESS (which is zero), indicating success, + * or a small negative value indicating that an error occurred. Errors are + * encoded as one of the \c PSA_ERROR_xxx values defined here. */ +/* If #PSA_SUCCESS is already defined, it means that #psa_status_t + * is also defined in an external header, so prevent its multiple + * definition. + */ +#ifndef PSA_SUCCESS +typedef int32_t psa_status_t; +#endif + +/**@}*/ + +/** \defgroup crypto_types Key and algorithm types + * @{ + */ + +/** \brief Encoding of a key type. + */ +typedef uint16_t psa_key_type_t; + +/** The type of PSA elliptic curve family identifiers. + * + * The curve identifier is required to create an ECC key using the + * PSA_KEY_TYPE_ECC_KEY_PAIR() or PSA_KEY_TYPE_ECC_PUBLIC_KEY() + * macros. + * + * Values defined by this standard will never be in the range 0x80-0xff. + * Vendors who define additional families must use an encoding in this range. + */ +typedef uint8_t psa_ecc_family_t; + +/** The type of PSA Diffie-Hellman group family identifiers. + * + * The group identifier is required to create an Diffie-Hellman key using the + * PSA_KEY_TYPE_DH_KEY_PAIR() or PSA_KEY_TYPE_DH_PUBLIC_KEY() + * macros. + * + * Values defined by this standard will never be in the range 0x80-0xff. + * Vendors who define additional families must use an encoding in this range. + */ +typedef uint8_t psa_dh_family_t; + +/** \brief Encoding of a cryptographic algorithm. + * + * For algorithms that can be applied to multiple key types, this type + * does not encode the key type. For example, for symmetric ciphers + * based on a block cipher, #psa_algorithm_t encodes the block cipher + * mode and the padding mode while the block cipher itself is encoded + * via #psa_key_type_t. + */ +typedef uint32_t psa_algorithm_t; + +/**@}*/ + +/** \defgroup key_lifetimes Key lifetimes + * @{ + */ + +/** Encoding of key lifetimes. + * + * The lifetime of a key indicates where it is stored and what system actions + * may create and destroy it. + * + * Lifetime values have the following structure: + * - Bits 0-7 (#PSA_KEY_LIFETIME_GET_PERSISTENCE(\c lifetime)): + * persistence level. This value indicates what device management + * actions can cause it to be destroyed. In particular, it indicates + * whether the key is _volatile_ or _persistent_. + * See ::psa_key_persistence_t for more information. + * - Bits 8-31 (#PSA_KEY_LIFETIME_GET_LOCATION(\c lifetime)): + * location indicator. This value indicates where the key is stored + * and where operations on the key are performed. + * See ::psa_key_location_t for more information. + * + * Volatile keys are automatically destroyed when the application instance + * terminates or on a power reset of the device. Persistent keys are + * preserved until the application explicitly destroys them or until an + * implementation-specific device management event occurs (for example, + * a factory reset). + * + * Persistent keys have a key identifier of type #mbedtls_svc_key_id_t. + * This identifier remains valid throughout the lifetime of the key, + * even if the application instance that created the key terminates. + * The application can call psa_open_key() to open a persistent key that + * it created previously. + * + * This specification defines two basic lifetime values: + * - Keys with the lifetime #PSA_KEY_LIFETIME_VOLATILE are volatile. + * All implementations should support this lifetime. + * - Keys with the lifetime #PSA_KEY_LIFETIME_PERSISTENT are persistent. + * All implementations that have access to persistent storage with + * appropriate security guarantees should support this lifetime. + */ +typedef uint32_t psa_key_lifetime_t; + +/** Encoding of key persistence levels. + * + * What distinguishes different persistence levels is what device management + * events may cause keys to be destroyed. _Volatile_ keys are destroyed + * by a power reset. Persistent keys may be destroyed by events such as + * a transfer of ownership or a factory reset. What management events + * actually affect persistent keys at different levels is outside the + * scope of the PSA Cryptography specification. + * + * This specification defines the following values of persistence levels: + * - \c 0 = #PSA_KEY_PERSISTENCE_VOLATILE: volatile key. + * A volatile key is automatically destroyed by the implementation when + * the application instance terminates. In particular, a volatile key + * is automatically destroyed on a power reset of the device. + * - \c 1 = #PSA_KEY_PERSISTENCE_DEFAULT: + * persistent key with a default lifetime. + * Implementations should support this value if they support persistent + * keys at all. + * Applications should use this value if they have no specific needs that + * are only met by implementation-specific features. + * - \c 2-127: persistent key with a PSA-specified lifetime. + * The PSA Cryptography specification does not define the meaning of these + * values, but other PSA specifications may do so. + * - \c 128-254: persistent key with a vendor-specified lifetime. + * No PSA specification will define the meaning of these values, so + * implementations may choose the meaning freely. + * As a guideline, higher persistence levels should cause a key to survive + * more management events than lower levels. + * - \c 255 = #PSA_KEY_PERSISTENCE_READ_ONLY: + * read-only or write-once key. + * A key with this persistence level cannot be destroyed. + * Implementations that support such keys may either allow their creation + * through the PSA Cryptography API, preferably only to applications with + * the appropriate privilege, or only expose keys created through + * implementation-specific means such as a factory ROM engraving process. + * Note that keys that are read-only due to policy restrictions + * rather than due to physical limitations should not have this + * persistence levels. + * + * \note Key persistence levels are 8-bit values. Key management + * interfaces operate on lifetimes (type ::psa_key_lifetime_t) which + * encode the persistence as the lower 8 bits of a 32-bit value. + */ +typedef uint8_t psa_key_persistence_t; + +/** Encoding of key location indicators. + * + * If an implementation of this API can make calls to external + * cryptoprocessors such as secure elements, the location of a key + * indicates which secure element performs the operations on the key. + * If an implementation offers multiple physical locations for persistent + * storage, the location indicator reflects at which physical location + * the key is stored. + * + * This specification defines the following values of location indicators: + * - \c 0: primary local storage. + * All implementations should support this value. + * The primary local storage is typically the same storage area that + * contains the key metadata. + * - \c 1: primary secure element. + * Implementations should support this value if there is a secure element + * attached to the operating environment. + * As a guideline, secure elements may provide higher resistance against + * side channel and physical attacks than the primary local storage, but may + * have restrictions on supported key types, sizes, policies and operations + * and may have different performance characteristics. + * - \c 2-0x7fffff: other locations defined by a PSA specification. + * The PSA Cryptography API does not currently assign any meaning to these + * locations, but future versions of this specification or other PSA + * specifications may do so. + * - \c 0x800000-0xffffff: vendor-defined locations. + * No PSA specification will assign a meaning to locations in this range. + * + * \note Key location indicators are 24-bit values. Key management + * interfaces operate on lifetimes (type ::psa_key_lifetime_t) which + * encode the location as the upper 24 bits of a 32-bit value. + */ +typedef uint32_t psa_key_location_t; + +/** Encoding of identifiers of persistent keys. + * + * - Applications may freely choose key identifiers in the range + * #PSA_KEY_ID_USER_MIN to #PSA_KEY_ID_USER_MAX. + * - Implementations may define additional key identifiers in the range + * #PSA_KEY_ID_VENDOR_MIN to #PSA_KEY_ID_VENDOR_MAX. + * - 0 is reserved as an invalid key identifier. + * - Key identifiers outside these ranges are reserved for future use. + */ +typedef uint32_t psa_key_id_t; + +#if !defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) +typedef psa_key_id_t mbedtls_svc_key_id_t; + +#else /* MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */ +/* Implementation-specific: The Mbed Cryptography library can be built as + * part of a multi-client service that exposes the PSA Cryptograpy API in each + * client and encodes the client identity in the key identifier argument of + * functions such as psa_open_key(). + */ +typedef struct +{ + psa_key_id_t key_id; + mbedtls_key_owner_id_t owner; +} mbedtls_svc_key_id_t; + +#endif /* !MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */ + +/**@}*/ + +/** \defgroup policy Key policies + * @{ + */ + +/** \brief Encoding of permitted usage on a key. */ +typedef uint32_t psa_key_usage_t; + +/**@}*/ + +/** \defgroup attributes Key attributes + * @{ + */ + +/** The type of a structure containing key attributes. + * + * This is an opaque structure that can represent the metadata of a key + * object. Metadata that can be stored in attributes includes: + * - The location of the key in storage, indicated by its key identifier + * and its lifetime. + * - The key's policy, comprising usage flags and a specification of + * the permitted algorithm(s). + * - Information about the key itself: the key type and its size. + * - Implementations may define additional attributes. + * + * The actual key material is not considered an attribute of a key. + * Key attributes do not contain information that is generally considered + * highly confidential. + * + * An attribute structure can be a simple data structure where each function + * `psa_set_key_xxx` sets a field and the corresponding function + * `psa_get_key_xxx` retrieves the value of the corresponding field. + * However, implementations may report values that are equivalent to the + * original one, but have a different encoding. For example, an + * implementation may use a more compact representation for types where + * many bit-patterns are invalid or not supported, and store all values + * that it does not support as a special marker value. In such an + * implementation, after setting an invalid value, the corresponding + * get function returns an invalid value which may not be the one that + * was originally stored. + * + * An attribute structure may contain references to auxiliary resources, + * for example pointers to allocated memory or indirect references to + * pre-calculated values. In order to free such resources, the application + * must call psa_reset_key_attributes(). As an exception, calling + * psa_reset_key_attributes() on an attribute structure is optional if + * the structure has only been modified by the following functions + * since it was initialized or last reset with psa_reset_key_attributes(): + * - psa_set_key_id() + * - psa_set_key_lifetime() + * - psa_set_key_type() + * - psa_set_key_bits() + * - psa_set_key_usage_flags() + * - psa_set_key_algorithm() + * + * Before calling any function on a key attribute structure, the application + * must initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_key_attributes_t attributes; + * memset(&attributes, 0, sizeof(attributes)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_key_attributes_t attributes = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_KEY_ATTRIBUTES_INIT, + * for example: + * \code + * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + * \endcode + * - Assign the result of the function psa_key_attributes_init() + * to the structure, for example: + * \code + * psa_key_attributes_t attributes; + * attributes = psa_key_attributes_init(); + * \endcode + * + * A freshly initialized attribute structure contains the following + * values: + * + * - lifetime: #PSA_KEY_LIFETIME_VOLATILE. + * - key identifier: 0 (which is not a valid key identifier). + * - type: \c 0 (meaning that the type is unspecified). + * - key size: \c 0 (meaning that the size is unspecified). + * - usage flags: \c 0 (which allows no usage except exporting a public key). + * - algorithm: \c 0 (which allows no cryptographic usage, but allows + * exporting). + * + * A typical sequence to create a key is as follows: + * -# Create and initialize an attribute structure. + * -# If the key is persistent, call psa_set_key_id(). + * Also call psa_set_key_lifetime() to place the key in a non-default + * location. + * -# Set the key policy with psa_set_key_usage_flags() and + * psa_set_key_algorithm(). + * -# Set the key type with psa_set_key_type(). + * Skip this step if copying an existing key with psa_copy_key(). + * -# When generating a random key with psa_generate_key() or deriving a key + * with psa_key_derivation_output_key(), set the desired key size with + * psa_set_key_bits(). + * -# Call a key creation function: psa_import_key(), psa_generate_key(), + * psa_key_derivation_output_key() or psa_copy_key(). This function reads + * the attribute structure, creates a key with these attributes, and + * outputs a handle to the newly created key. + * -# The attribute structure is now no longer necessary. + * You may call psa_reset_key_attributes(), although this is optional + * with the workflow presented here because the attributes currently + * defined in this specification do not require any additional resources + * beyond the structure itself. + * + * A typical sequence to query a key's attributes is as follows: + * -# Call psa_get_key_attributes(). + * -# Call `psa_get_key_xxx` functions to retrieve the attribute(s) that + * you are interested in. + * -# Call psa_reset_key_attributes() to free any resources that may be + * used by the attribute structure. + * + * Once a key has been created, it is impossible to change its attributes. + */ +typedef struct psa_key_attributes_s psa_key_attributes_t; + + +#ifndef __DOXYGEN_ONLY__ +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) +/* Mbed Crypto defines this type in crypto_types.h because it is also + * visible to applications through an implementation-specific extension. + * For the PSA Cryptography specification, this type is only visible + * via crypto_se_driver.h. */ +typedef uint64_t psa_key_slot_number_t; +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ +#endif /* !__DOXYGEN_ONLY__ */ + +/**@}*/ + +/** \defgroup derivation Key derivation + * @{ + */ + +/** \brief Encoding of the step of a key derivation. */ +typedef uint16_t psa_key_derivation_step_t; + +/**@}*/ + +#endif /* PSA_CRYPTO_TYPES_H */ diff --git a/Android/Level4/app/src/main/c/mbedtls/include/psa/crypto_values.h b/Android/Level4/app/src/main/c/mbedtls/include/psa/crypto_values.h new file mode 100644 index 0000000..3eb64d8 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/include/psa/crypto_values.h @@ -0,0 +1,1868 @@ +/** + * \file psa/crypto_values.h + * + * \brief PSA cryptography module: macros to build and analyze integer values. + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. Drivers must include the appropriate driver + * header file. + * + * This file contains portable definitions of macros to build and analyze + * values of integral types that encode properties of cryptographic keys, + * designations of cryptographic algorithms, and error codes returned by + * the library. + * + * This header file only defines preprocessor macros. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 PSA_CRYPTO_VALUES_H +#define PSA_CRYPTO_VALUES_H + +/** \defgroup error Error codes + * @{ + */ + +/* PSA error codes */ + +/** The action was completed successfully. */ +#define PSA_SUCCESS ((psa_status_t)0) + +/** An error occurred that does not correspond to any defined + * failure cause. + * + * Implementations may use this error code if none of the other standard + * error codes are applicable. */ +#define PSA_ERROR_GENERIC_ERROR ((psa_status_t)-132) + +/** The requested operation or a parameter is not supported + * by this implementation. + * + * Implementations should return this error code when an enumeration + * parameter such as a key type, algorithm, etc. is not recognized. + * If a combination of parameters is recognized and identified as + * not valid, return #PSA_ERROR_INVALID_ARGUMENT instead. */ +#define PSA_ERROR_NOT_SUPPORTED ((psa_status_t)-134) + +/** The requested action is denied by a policy. + * + * Implementations should return this error code when the parameters + * are recognized as valid and supported, and a policy explicitly + * denies the requested operation. + * + * If a subset of the parameters of a function call identify a + * forbidden operation, and another subset of the parameters are + * not valid or not supported, it is unspecified whether the function + * returns #PSA_ERROR_NOT_PERMITTED, #PSA_ERROR_NOT_SUPPORTED or + * #PSA_ERROR_INVALID_ARGUMENT. */ +#define PSA_ERROR_NOT_PERMITTED ((psa_status_t)-133) + +/** An output buffer is too small. + * + * Applications can call the \c PSA_xxx_SIZE macro listed in the function + * description to determine a sufficient buffer size. + * + * Implementations should preferably return this error code only + * in cases when performing the operation with a larger output + * buffer would succeed. However implementations may return this + * error if a function has invalid or unsupported parameters in addition + * to the parameters that determine the necessary output buffer size. */ +#define PSA_ERROR_BUFFER_TOO_SMALL ((psa_status_t)-138) + +/** Asking for an item that already exists + * + * Implementations should return this error, when attempting + * to write an item (like a key) that already exists. */ +#define PSA_ERROR_ALREADY_EXISTS ((psa_status_t)-139) + +/** Asking for an item that doesn't exist + * + * Implementations should return this error, if a requested item (like + * a key) does not exist. */ +#define PSA_ERROR_DOES_NOT_EXIST ((psa_status_t)-140) + +/** The requested action cannot be performed in the current state. + * + * Multipart operations return this error when one of the + * functions is called out of sequence. Refer to the function + * descriptions for permitted sequencing of functions. + * + * Implementations shall not return this error code to indicate + * that a key either exists or not, + * but shall instead return #PSA_ERROR_ALREADY_EXISTS or #PSA_ERROR_DOES_NOT_EXIST + * as applicable. + * + * Implementations shall not return this error code to indicate that a + * key handle is invalid, but shall return #PSA_ERROR_INVALID_HANDLE + * instead. */ +#define PSA_ERROR_BAD_STATE ((psa_status_t)-137) + +/** The parameters passed to the function are invalid. + * + * Implementations may return this error any time a parameter or + * combination of parameters are recognized as invalid. + * + * Implementations shall not return this error code to indicate that a + * key handle is invalid, but shall return #PSA_ERROR_INVALID_HANDLE + * instead. + */ +#define PSA_ERROR_INVALID_ARGUMENT ((psa_status_t)-135) + +/** There is not enough runtime memory. + * + * If the action is carried out across multiple security realms, this + * error can refer to available memory in any of the security realms. */ +#define PSA_ERROR_INSUFFICIENT_MEMORY ((psa_status_t)-141) + +/** There is not enough persistent storage. + * + * Functions that modify the key storage return this error code if + * there is insufficient storage space on the host media. In addition, + * many functions that do not otherwise access storage may return this + * error code if the implementation requires a mandatory log entry for + * the requested action and the log storage space is full. */ +#define PSA_ERROR_INSUFFICIENT_STORAGE ((psa_status_t)-142) + +/** There was a communication failure inside the implementation. + * + * This can indicate a communication failure between the application + * and an external cryptoprocessor or between the cryptoprocessor and + * an external volatile or persistent memory. A communication failure + * may be transient or permanent depending on the cause. + * + * \warning If a function returns this error, it is undetermined + * whether the requested action has completed or not. Implementations + * should return #PSA_SUCCESS on successful completion whenever + * possible, however functions may return #PSA_ERROR_COMMUNICATION_FAILURE + * if the requested action was completed successfully in an external + * cryptoprocessor but there was a breakdown of communication before + * the cryptoprocessor could report the status to the application. + */ +#define PSA_ERROR_COMMUNICATION_FAILURE ((psa_status_t)-145) + +/** There was a storage failure that may have led to data loss. + * + * This error indicates that some persistent storage is corrupted. + * It should not be used for a corruption of volatile memory + * (use #PSA_ERROR_CORRUPTION_DETECTED), for a communication error + * between the cryptoprocessor and its external storage (use + * #PSA_ERROR_COMMUNICATION_FAILURE), or when the storage is + * in a valid state but is full (use #PSA_ERROR_INSUFFICIENT_STORAGE). + * + * Note that a storage failure does not indicate that any data that was + * previously read is invalid. However this previously read data may no + * longer be readable from storage. + * + * When a storage failure occurs, it is no longer possible to ensure + * the global integrity of the keystore. Depending on the global + * integrity guarantees offered by the implementation, access to other + * data may or may not fail even if the data is still readable but + * its integrity cannot be guaranteed. + * + * Implementations should only use this error code to report a + * permanent storage corruption. However application writers should + * keep in mind that transient errors while reading the storage may be + * reported using this error code. */ +#define PSA_ERROR_STORAGE_FAILURE ((psa_status_t)-146) + +/** A hardware failure was detected. + * + * A hardware failure may be transient or permanent depending on the + * cause. */ +#define PSA_ERROR_HARDWARE_FAILURE ((psa_status_t)-147) + +/** A tampering attempt was detected. + * + * If an application receives this error code, there is no guarantee + * that previously accessed or computed data was correct and remains + * confidential. Applications should not perform any security function + * and should enter a safe failure state. + * + * Implementations may return this error code if they detect an invalid + * state that cannot happen during normal operation and that indicates + * that the implementation's security guarantees no longer hold. Depending + * on the implementation architecture and on its security and safety goals, + * the implementation may forcibly terminate the application. + * + * This error code is intended as a last resort when a security breach + * is detected and it is unsure whether the keystore data is still + * protected. Implementations shall only return this error code + * to report an alarm from a tampering detector, to indicate that + * the confidentiality of stored data can no longer be guaranteed, + * or to indicate that the integrity of previously returned data is now + * considered compromised. Implementations shall not use this error code + * to indicate a hardware failure that merely makes it impossible to + * perform the requested operation (use #PSA_ERROR_COMMUNICATION_FAILURE, + * #PSA_ERROR_STORAGE_FAILURE, #PSA_ERROR_HARDWARE_FAILURE, + * #PSA_ERROR_INSUFFICIENT_ENTROPY or other applicable error code + * instead). + * + * This error indicates an attack against the application. Implementations + * shall not return this error code as a consequence of the behavior of + * the application itself. */ +#define PSA_ERROR_CORRUPTION_DETECTED ((psa_status_t)-151) + +/** There is not enough entropy to generate random data needed + * for the requested action. + * + * This error indicates a failure of a hardware random generator. + * Application writers should note that this error can be returned not + * only by functions whose purpose is to generate random data, such + * as key, IV or nonce generation, but also by functions that execute + * an algorithm with a randomized result, as well as functions that + * use randomization of intermediate computations as a countermeasure + * to certain attacks. + * + * Implementations should avoid returning this error after psa_crypto_init() + * has succeeded. Implementations should generate sufficient + * entropy during initialization and subsequently use a cryptographically + * secure pseudorandom generator (PRNG). However implementations may return + * this error at any time if a policy requires the PRNG to be reseeded + * during normal operation. */ +#define PSA_ERROR_INSUFFICIENT_ENTROPY ((psa_status_t)-148) + +/** The signature, MAC or hash is incorrect. + * + * Verification functions return this error if the verification + * calculations completed successfully, and the value to be verified + * was determined to be incorrect. + * + * If the value to verify has an invalid size, implementations may return + * either #PSA_ERROR_INVALID_ARGUMENT or #PSA_ERROR_INVALID_SIGNATURE. */ +#define PSA_ERROR_INVALID_SIGNATURE ((psa_status_t)-149) + +/** The decrypted padding is incorrect. + * + * \warning In some protocols, when decrypting data, it is essential that + * the behavior of the application does not depend on whether the padding + * is correct, down to precise timing. Applications should prefer + * protocols that use authenticated encryption rather than plain + * encryption. If the application must perform a decryption of + * unauthenticated data, the application writer should take care not + * to reveal whether the padding is invalid. + * + * Implementations should strive to make valid and invalid padding + * as close as possible to indistinguishable to an external observer. + * In particular, the timing of a decryption operation should not + * depend on the validity of the padding. */ +#define PSA_ERROR_INVALID_PADDING ((psa_status_t)-150) + +/** Return this error when there's insufficient data when attempting + * to read from a resource. */ +#define PSA_ERROR_INSUFFICIENT_DATA ((psa_status_t)-143) + +/** The key handle is not valid. See also :ref:\`key-handles\`. + */ +#define PSA_ERROR_INVALID_HANDLE ((psa_status_t)-136) + +/**@}*/ + +/** \defgroup crypto_types Key and algorithm types + * @{ + */ + +/** An invalid key type value. + * + * Zero is not the encoding of any key type. + */ +#define PSA_KEY_TYPE_NONE ((psa_key_type_t)0x0000) + +/** Vendor-defined key type flag. + * + * Key types defined by this standard will never have the + * #PSA_KEY_TYPE_VENDOR_FLAG bit set. Vendors who define additional key types + * must use an encoding with the #PSA_KEY_TYPE_VENDOR_FLAG bit set and should + * respect the bitwise structure used by standard encodings whenever practical. + */ +#define PSA_KEY_TYPE_VENDOR_FLAG ((psa_key_type_t)0x8000) + +#define PSA_KEY_TYPE_CATEGORY_MASK ((psa_key_type_t)0x7000) +#define PSA_KEY_TYPE_CATEGORY_RAW ((psa_key_type_t)0x1000) +#define PSA_KEY_TYPE_CATEGORY_SYMMETRIC ((psa_key_type_t)0x2000) +#define PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY ((psa_key_type_t)0x4000) +#define PSA_KEY_TYPE_CATEGORY_KEY_PAIR ((psa_key_type_t)0x7000) + +#define PSA_KEY_TYPE_CATEGORY_FLAG_PAIR ((psa_key_type_t)0x3000) + +/** Whether a key type is vendor-defined. + * + * See also #PSA_KEY_TYPE_VENDOR_FLAG. + */ +#define PSA_KEY_TYPE_IS_VENDOR_DEFINED(type) \ + (((type) & PSA_KEY_TYPE_VENDOR_FLAG) != 0) + +/** Whether a key type is an unstructured array of bytes. + * + * This encompasses both symmetric keys and non-key data. + */ +#define PSA_KEY_TYPE_IS_UNSTRUCTURED(type) \ + (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_RAW || \ + ((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_SYMMETRIC) + +/** Whether a key type is asymmetric: either a key pair or a public key. */ +#define PSA_KEY_TYPE_IS_ASYMMETRIC(type) \ + (((type) & PSA_KEY_TYPE_CATEGORY_MASK \ + & ~PSA_KEY_TYPE_CATEGORY_FLAG_PAIR) == \ + PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY) +/** Whether a key type is the public part of a key pair. */ +#define PSA_KEY_TYPE_IS_PUBLIC_KEY(type) \ + (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY) +/** Whether a key type is a key pair containing a private part and a public + * part. */ +#define PSA_KEY_TYPE_IS_KEY_PAIR(type) \ + (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_KEY_PAIR) +/** The key pair type corresponding to a public key type. + * + * You may also pass a key pair type as \p type, it will be left unchanged. + * + * \param type A public key type or key pair type. + * + * \return The corresponding key pair type. + * If \p type is not a public key or a key pair, + * the return value is undefined. + */ +#define PSA_KEY_TYPE_KEY_PAIR_OF_PUBLIC_KEY(type) \ + ((type) | PSA_KEY_TYPE_CATEGORY_FLAG_PAIR) +/** The public key type corresponding to a key pair type. + * + * You may also pass a key pair type as \p type, it will be left unchanged. + * + * \param type A public key type or key pair type. + * + * \return The corresponding public key type. + * If \p type is not a public key or a key pair, + * the return value is undefined. + */ +#define PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) \ + ((type) & ~PSA_KEY_TYPE_CATEGORY_FLAG_PAIR) + +/** Raw data. + * + * A "key" of this type cannot be used for any cryptographic operation. + * Applications may use this type to store arbitrary data in the keystore. */ +#define PSA_KEY_TYPE_RAW_DATA ((psa_key_type_t)0x1001) + +/** HMAC key. + * + * The key policy determines which underlying hash algorithm the key can be + * used for. + * + * HMAC keys should generally have the same size as the underlying hash. + * This size can be calculated with #PSA_HASH_SIZE(\c alg) where + * \c alg is the HMAC algorithm or the underlying hash algorithm. */ +#define PSA_KEY_TYPE_HMAC ((psa_key_type_t)0x1100) + +/** A secret for key derivation. + * + * The key policy determines which key derivation algorithm the key + * can be used for. + */ +#define PSA_KEY_TYPE_DERIVE ((psa_key_type_t)0x1200) + +/** Key for a cipher, AEAD or MAC algorithm based on the AES block cipher. + * + * The size of the key can be 16 bytes (AES-128), 24 bytes (AES-192) or + * 32 bytes (AES-256). + */ +#define PSA_KEY_TYPE_AES ((psa_key_type_t)0x2400) + +/** Key for a cipher or MAC algorithm based on DES or 3DES (Triple-DES). + * + * The size of the key can be 8 bytes (single DES), 16 bytes (2-key 3DES) or + * 24 bytes (3-key 3DES). + * + * Note that single DES and 2-key 3DES are weak and strongly + * deprecated and should only be used to decrypt legacy data. 3-key 3DES + * is weak and deprecated and should only be used in legacy protocols. + */ +#define PSA_KEY_TYPE_DES ((psa_key_type_t)0x2301) + +/** Key for a cipher, AEAD or MAC algorithm based on the + * Camellia block cipher. */ +#define PSA_KEY_TYPE_CAMELLIA ((psa_key_type_t)0x2403) + +/** Key for the RC4 stream cipher. + * + * Note that RC4 is weak and deprecated and should only be used in + * legacy protocols. */ +#define PSA_KEY_TYPE_ARC4 ((psa_key_type_t)0x2002) + +/** Key for the ChaCha20 stream cipher or the Chacha20-Poly1305 AEAD algorithm. + * + * ChaCha20 and the ChaCha20_Poly1305 construction are defined in RFC 7539. + * + * Implementations must support 12-byte nonces, may support 8-byte nonces, + * and should reject other sizes. + */ +#define PSA_KEY_TYPE_CHACHA20 ((psa_key_type_t)0x2004) + +/** RSA public key. */ +#define PSA_KEY_TYPE_RSA_PUBLIC_KEY ((psa_key_type_t)0x4001) +/** RSA key pair (private and public key). */ +#define PSA_KEY_TYPE_RSA_KEY_PAIR ((psa_key_type_t)0x7001) +/** Whether a key type is an RSA key (pair or public-only). */ +#define PSA_KEY_TYPE_IS_RSA(type) \ + (PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) == PSA_KEY_TYPE_RSA_PUBLIC_KEY) + +#define PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE ((psa_key_type_t)0x4100) +#define PSA_KEY_TYPE_ECC_KEY_PAIR_BASE ((psa_key_type_t)0x7100) +#define PSA_KEY_TYPE_ECC_CURVE_MASK ((psa_key_type_t)0x00ff) +/** Elliptic curve key pair. + * + * \param curve A value of type ::psa_ecc_family_t that + * identifies the ECC curve to be used. + */ +#define PSA_KEY_TYPE_ECC_KEY_PAIR(curve) \ + (PSA_KEY_TYPE_ECC_KEY_PAIR_BASE | (curve)) +/** Elliptic curve public key. + * + * \param curve A value of type ::psa_ecc_family_t that + * identifies the ECC curve to be used. + */ +#define PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve) \ + (PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE | (curve)) + +/** Whether a key type is an elliptic curve key (pair or public-only). */ +#define PSA_KEY_TYPE_IS_ECC(type) \ + ((PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) & \ + ~PSA_KEY_TYPE_ECC_CURVE_MASK) == PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE) +/** Whether a key type is an elliptic curve key pair. */ +#define PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type) \ + (((type) & ~PSA_KEY_TYPE_ECC_CURVE_MASK) == \ + PSA_KEY_TYPE_ECC_KEY_PAIR_BASE) +/** Whether a key type is an elliptic curve public key. */ +#define PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(type) \ + (((type) & ~PSA_KEY_TYPE_ECC_CURVE_MASK) == \ + PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE) + +/** Extract the curve from an elliptic curve key type. */ +#define PSA_KEY_TYPE_ECC_GET_FAMILY(type) \ + ((psa_ecc_family_t) (PSA_KEY_TYPE_IS_ECC(type) ? \ + ((type) & PSA_KEY_TYPE_ECC_CURVE_MASK) : \ + 0)) + +/** SEC Koblitz curves over prime fields. + * + * This family comprises the following curves: + * secp192k1, secp224k1, secp256k1. + * They are defined in _Standards for Efficient Cryptography_, + * _SEC 2: Recommended Elliptic Curve Domain Parameters_. + * https://www.secg.org/sec2-v2.pdf + */ +#define PSA_ECC_FAMILY_SECP_K1 ((psa_ecc_family_t) 0x17) + +/** SEC random curves over prime fields. + * + * This family comprises the following curves: + * secp192k1, secp224r1, secp256r1, secp384r1, secp521r1. + * They are defined in _Standards for Efficient Cryptography_, + * _SEC 2: Recommended Elliptic Curve Domain Parameters_. + * https://www.secg.org/sec2-v2.pdf + */ +#define PSA_ECC_FAMILY_SECP_R1 ((psa_ecc_family_t) 0x12) +/* SECP160R2 (SEC2 v1, obsolete) */ +#define PSA_ECC_FAMILY_SECP_R2 ((psa_ecc_family_t) 0x1b) + +/** SEC Koblitz curves over binary fields. + * + * This family comprises the following curves: + * sect163k1, sect233k1, sect239k1, sect283k1, sect409k1, sect571k1. + * They are defined in _Standards for Efficient Cryptography_, + * _SEC 2: Recommended Elliptic Curve Domain Parameters_. + * https://www.secg.org/sec2-v2.pdf + */ +#define PSA_ECC_FAMILY_SECT_K1 ((psa_ecc_family_t) 0x27) + +/** SEC random curves over binary fields. + * + * This family comprises the following curves: + * sect163r1, sect233r1, sect283r1, sect409r1, sect571r1. + * They are defined in _Standards for Efficient Cryptography_, + * _SEC 2: Recommended Elliptic Curve Domain Parameters_. + * https://www.secg.org/sec2-v2.pdf + */ +#define PSA_ECC_FAMILY_SECT_R1 ((psa_ecc_family_t) 0x22) + +/** SEC additional random curves over binary fields. + * + * This family comprises the following curve: + * sect163r2. + * It is defined in _Standards for Efficient Cryptography_, + * _SEC 2: Recommended Elliptic Curve Domain Parameters_. + * https://www.secg.org/sec2-v2.pdf + */ +#define PSA_ECC_FAMILY_SECT_R2 ((psa_ecc_family_t) 0x2b) + +/** Brainpool P random curves. + * + * This family comprises the following curves: + * brainpoolP160r1, brainpoolP192r1, brainpoolP224r1, brainpoolP256r1, + * brainpoolP320r1, brainpoolP384r1, brainpoolP512r1. + * It is defined in RFC 5639. + */ +#define PSA_ECC_FAMILY_BRAINPOOL_P_R1 ((psa_ecc_family_t) 0x30) + +/** Curve25519 and Curve448. + * + * This family comprises the following Montgomery curves: + * - 255-bit: Bernstein et al., + * _Curve25519: new Diffie-Hellman speed records_, LNCS 3958, 2006. + * The algorithm #PSA_ALG_ECDH performs X25519 when used with this curve. + * - 448-bit: Hamburg, + * _Ed448-Goldilocks, a new elliptic curve_, NIST ECC Workshop, 2015. + * The algorithm #PSA_ALG_ECDH performs X448 when used with this curve. + */ +#define PSA_ECC_FAMILY_MONTGOMERY ((psa_ecc_family_t) 0x41) + +#define PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE ((psa_key_type_t)0x4200) +#define PSA_KEY_TYPE_DH_KEY_PAIR_BASE ((psa_key_type_t)0x7200) +#define PSA_KEY_TYPE_DH_GROUP_MASK ((psa_key_type_t)0x00ff) +/** Diffie-Hellman key pair. + * + * \param group A value of type ::psa_dh_family_t that identifies the + * Diffie-Hellman group to be used. + */ +#define PSA_KEY_TYPE_DH_KEY_PAIR(group) \ + (PSA_KEY_TYPE_DH_KEY_PAIR_BASE | (group)) +/** Diffie-Hellman public key. + * + * \param group A value of type ::psa_dh_family_t that identifies the + * Diffie-Hellman group to be used. + */ +#define PSA_KEY_TYPE_DH_PUBLIC_KEY(group) \ + (PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE | (group)) + +/** Whether a key type is a Diffie-Hellman key (pair or public-only). */ +#define PSA_KEY_TYPE_IS_DH(type) \ + ((PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) & \ + ~PSA_KEY_TYPE_DH_GROUP_MASK) == PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE) +/** Whether a key type is a Diffie-Hellman key pair. */ +#define PSA_KEY_TYPE_IS_DH_KEY_PAIR(type) \ + (((type) & ~PSA_KEY_TYPE_DH_GROUP_MASK) == \ + PSA_KEY_TYPE_DH_KEY_PAIR_BASE) +/** Whether a key type is a Diffie-Hellman public key. */ +#define PSA_KEY_TYPE_IS_DH_PUBLIC_KEY(type) \ + (((type) & ~PSA_KEY_TYPE_DH_GROUP_MASK) == \ + PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE) + +/** Extract the group from a Diffie-Hellman key type. */ +#define PSA_KEY_TYPE_DH_GET_FAMILY(type) \ + ((psa_dh_family_t) (PSA_KEY_TYPE_IS_DH(type) ? \ + ((type) & PSA_KEY_TYPE_DH_GROUP_MASK) : \ + 0)) + +/** Diffie-Hellman groups defined in RFC 7919 Appendix A. + * + * This family includes groups with the following key sizes (in bits): + * 2048, 3072, 4096, 6144, 8192. A given implementation may support + * all of these sizes or only a subset. + */ +#define PSA_DH_FAMILY_RFC7919 ((psa_dh_family_t) 0x03) + +#define PSA_GET_KEY_TYPE_BLOCK_SIZE_EXPONENT(type) \ + (((type) >> 8) & 7) +/** The block size of a block cipher. + * + * \param type A cipher key type (value of type #psa_key_type_t). + * + * \return The block size for a block cipher, or 1 for a stream cipher. + * The return value is undefined if \p type is not a supported + * cipher key type. + * + * \note It is possible to build stream cipher algorithms on top of a block + * cipher, for example CTR mode (#PSA_ALG_CTR). + * This macro only takes the key type into account, so it cannot be + * used to determine the size of the data that #psa_cipher_update() + * might buffer for future processing in general. + * + * \note This macro returns a compile-time constant if its argument is one. + * + * \warning This macro may evaluate its argument multiple times. + */ +#define PSA_BLOCK_CIPHER_BLOCK_SIZE(type) \ + (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_SYMMETRIC ? \ + 1u << PSA_GET_KEY_TYPE_BLOCK_SIZE_EXPONENT(type) : \ + 0u) + +/** Vendor-defined algorithm flag. + * + * Algorithms defined by this standard will never have the #PSA_ALG_VENDOR_FLAG + * bit set. Vendors who define additional algorithms must use an encoding with + * the #PSA_ALG_VENDOR_FLAG bit set and should respect the bitwise structure + * used by standard encodings whenever practical. + */ +#define PSA_ALG_VENDOR_FLAG ((psa_algorithm_t)0x80000000) + +#define PSA_ALG_CATEGORY_MASK ((psa_algorithm_t)0x7f000000) +#define PSA_ALG_CATEGORY_HASH ((psa_algorithm_t)0x01000000) +#define PSA_ALG_CATEGORY_MAC ((psa_algorithm_t)0x02000000) +#define PSA_ALG_CATEGORY_CIPHER ((psa_algorithm_t)0x04000000) +#define PSA_ALG_CATEGORY_AEAD ((psa_algorithm_t)0x06000000) +#define PSA_ALG_CATEGORY_SIGN ((psa_algorithm_t)0x10000000) +#define PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION ((psa_algorithm_t)0x12000000) +#define PSA_ALG_CATEGORY_KEY_DERIVATION ((psa_algorithm_t)0x20000000) +#define PSA_ALG_CATEGORY_KEY_AGREEMENT ((psa_algorithm_t)0x30000000) + +/** Whether an algorithm is vendor-defined. + * + * See also #PSA_ALG_VENDOR_FLAG. + */ +#define PSA_ALG_IS_VENDOR_DEFINED(alg) \ + (((alg) & PSA_ALG_VENDOR_FLAG) != 0) + +/** Whether the specified algorithm is a hash algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a hash algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_HASH(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_HASH) + +/** Whether the specified algorithm is a MAC algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a MAC algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_MAC(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_MAC) + +/** Whether the specified algorithm is a symmetric cipher algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a symmetric cipher algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_CIPHER(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_CIPHER) + +/** Whether the specified algorithm is an authenticated encryption + * with associated data (AEAD) algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is an AEAD algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_AEAD(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_AEAD) + +/** Whether the specified algorithm is an asymmetric signature algorithm, + * also known as public-key signature algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is an asymmetric signature algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_SIGN(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_SIGN) + +/** Whether the specified algorithm is an asymmetric encryption algorithm, + * also known as public-key encryption algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is an asymmetric encryption algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_ASYMMETRIC_ENCRYPTION(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION) + +/** Whether the specified algorithm is a key agreement algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a key agreement algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_KEY_AGREEMENT(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_AGREEMENT) + +/** Whether the specified algorithm is a key derivation algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a key derivation algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_KEY_DERIVATION(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_DERIVATION) + +#define PSA_ALG_HASH_MASK ((psa_algorithm_t)0x000000ff) +/** MD2 */ +#define PSA_ALG_MD2 ((psa_algorithm_t)0x01000001) +/** MD4 */ +#define PSA_ALG_MD4 ((psa_algorithm_t)0x01000002) +/** MD5 */ +#define PSA_ALG_MD5 ((psa_algorithm_t)0x01000003) +/** PSA_ALG_RIPEMD160 */ +#define PSA_ALG_RIPEMD160 ((psa_algorithm_t)0x01000004) +/** SHA1 */ +#define PSA_ALG_SHA_1 ((psa_algorithm_t)0x01000005) +/** SHA2-224 */ +#define PSA_ALG_SHA_224 ((psa_algorithm_t)0x01000008) +/** SHA2-256 */ +#define PSA_ALG_SHA_256 ((psa_algorithm_t)0x01000009) +/** SHA2-384 */ +#define PSA_ALG_SHA_384 ((psa_algorithm_t)0x0100000a) +/** SHA2-512 */ +#define PSA_ALG_SHA_512 ((psa_algorithm_t)0x0100000b) +/** SHA2-512/224 */ +#define PSA_ALG_SHA_512_224 ((psa_algorithm_t)0x0100000c) +/** SHA2-512/256 */ +#define PSA_ALG_SHA_512_256 ((psa_algorithm_t)0x0100000d) +/** SHA3-224 */ +#define PSA_ALG_SHA3_224 ((psa_algorithm_t)0x01000010) +/** SHA3-256 */ +#define PSA_ALG_SHA3_256 ((psa_algorithm_t)0x01000011) +/** SHA3-384 */ +#define PSA_ALG_SHA3_384 ((psa_algorithm_t)0x01000012) +/** SHA3-512 */ +#define PSA_ALG_SHA3_512 ((psa_algorithm_t)0x01000013) + +/** In a hash-and-sign algorithm policy, allow any hash algorithm. + * + * This value may be used to form the algorithm usage field of a policy + * for a signature algorithm that is parametrized by a hash. The key + * may then be used to perform operations using the same signature + * algorithm parametrized with any supported hash. + * + * That is, suppose that `PSA_xxx_SIGNATURE` is one of the following macros: + * - #PSA_ALG_RSA_PKCS1V15_SIGN, #PSA_ALG_RSA_PSS, + * - #PSA_ALG_ECDSA, #PSA_ALG_DETERMINISTIC_ECDSA. + * Then you may create and use a key as follows: + * - Set the key usage field using #PSA_ALG_ANY_HASH, for example: + * ``` + * psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH); // or VERIFY + * psa_set_key_algorithm(&attributes, PSA_xxx_SIGNATURE(PSA_ALG_ANY_HASH)); + * ``` + * - Import or generate key material. + * - Call psa_sign_hash() or psa_verify_hash(), passing + * an algorithm built from `PSA_xxx_SIGNATURE` and a specific hash. Each + * call to sign or verify a message may use a different hash. + * ``` + * psa_sign_hash(handle, PSA_xxx_SIGNATURE(PSA_ALG_SHA_256), ...); + * psa_sign_hash(handle, PSA_xxx_SIGNATURE(PSA_ALG_SHA_512), ...); + * psa_sign_hash(handle, PSA_xxx_SIGNATURE(PSA_ALG_SHA3_256), ...); + * ``` + * + * This value may not be used to build other algorithms that are + * parametrized over a hash. For any valid use of this macro to build + * an algorithm \c alg, #PSA_ALG_IS_HASH_AND_SIGN(\c alg) is true. + * + * This value may not be used to build an algorithm specification to + * perform an operation. It is only valid to build policies. + */ +#define PSA_ALG_ANY_HASH ((psa_algorithm_t)0x010000ff) + +#define PSA_ALG_MAC_SUBCATEGORY_MASK ((psa_algorithm_t)0x00c00000) +#define PSA_ALG_HMAC_BASE ((psa_algorithm_t)0x02800000) +/** Macro to build an HMAC algorithm. + * + * For example, #PSA_ALG_HMAC(#PSA_ALG_SHA_256) is HMAC-SHA-256. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * + * \return The corresponding HMAC algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_HMAC(hash_alg) \ + (PSA_ALG_HMAC_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) + +#define PSA_ALG_HMAC_GET_HASH(hmac_alg) \ + (PSA_ALG_CATEGORY_HASH | ((hmac_alg) & PSA_ALG_HASH_MASK)) + +/** Whether the specified algorithm is an HMAC algorithm. + * + * HMAC is a family of MAC algorithms that are based on a hash function. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is an HMAC algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_HMAC(alg) \ + (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_MAC_SUBCATEGORY_MASK)) == \ + PSA_ALG_HMAC_BASE) + +/* In the encoding of a MAC algorithm, the bits corresponding to + * PSA_ALG_MAC_TRUNCATION_MASK encode the length to which the MAC is + * truncated. As an exception, the value 0 means the untruncated algorithm, + * whatever its length is. The length is encoded in 6 bits, so it can + * reach up to 63; the largest MAC is 64 bytes so its trivial truncation + * to full length is correctly encoded as 0 and any non-trivial truncation + * is correctly encoded as a value between 1 and 63. */ +#define PSA_ALG_MAC_TRUNCATION_MASK ((psa_algorithm_t)0x00003f00) +#define PSA_MAC_TRUNCATION_OFFSET 8 + +/** Macro to build a truncated MAC algorithm. + * + * A truncated MAC algorithm is identical to the corresponding MAC + * algorithm except that the MAC value for the truncated algorithm + * consists of only the first \p mac_length bytes of the MAC value + * for the untruncated algorithm. + * + * \note This macro may allow constructing algorithm identifiers that + * are not valid, either because the specified length is larger + * than the untruncated MAC or because the specified length is + * smaller than permitted by the implementation. + * + * \note It is implementation-defined whether a truncated MAC that + * is truncated to the same length as the MAC of the untruncated + * algorithm is considered identical to the untruncated algorithm + * for policy comparison purposes. + * + * \param mac_alg A MAC algorithm identifier (value of type + * #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p alg) + * is true). This may be a truncated or untruncated + * MAC algorithm. + * \param mac_length Desired length of the truncated MAC in bytes. + * This must be at most the full length of the MAC + * and must be at least an implementation-specified + * minimum. The implementation-specified minimum + * shall not be zero. + * + * \return The corresponding MAC algorithm with the specified + * length. + * \return Unspecified if \p alg is not a supported + * MAC algorithm or if \p mac_length is too small or + * too large for the specified MAC algorithm. + */ +#define PSA_ALG_TRUNCATED_MAC(mac_alg, mac_length) \ + (((mac_alg) & ~PSA_ALG_MAC_TRUNCATION_MASK) | \ + ((mac_length) << PSA_MAC_TRUNCATION_OFFSET & PSA_ALG_MAC_TRUNCATION_MASK)) + +/** Macro to build the base MAC algorithm corresponding to a truncated + * MAC algorithm. + * + * \param mac_alg A MAC algorithm identifier (value of type + * #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p alg) + * is true). This may be a truncated or untruncated + * MAC algorithm. + * + * \return The corresponding base MAC algorithm. + * \return Unspecified if \p alg is not a supported + * MAC algorithm. + */ +#define PSA_ALG_FULL_LENGTH_MAC(mac_alg) \ + ((mac_alg) & ~PSA_ALG_MAC_TRUNCATION_MASK) + +/** Length to which a MAC algorithm is truncated. + * + * \param mac_alg A MAC algorithm identifier (value of type + * #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p alg) + * is true). + * + * \return Length of the truncated MAC in bytes. + * \return 0 if \p alg is a non-truncated MAC algorithm. + * \return Unspecified if \p alg is not a supported + * MAC algorithm. + */ +#define PSA_MAC_TRUNCATED_LENGTH(mac_alg) \ + (((mac_alg) & PSA_ALG_MAC_TRUNCATION_MASK) >> PSA_MAC_TRUNCATION_OFFSET) + +#define PSA_ALG_CIPHER_MAC_BASE ((psa_algorithm_t)0x02c00000) +/** The CBC-MAC construction over a block cipher + * + * \warning CBC-MAC is insecure in many cases. + * A more secure mode, such as #PSA_ALG_CMAC, is recommended. + */ +#define PSA_ALG_CBC_MAC ((psa_algorithm_t)0x02c00001) +/** The CMAC construction over a block cipher */ +#define PSA_ALG_CMAC ((psa_algorithm_t)0x02c00002) + +/** Whether the specified algorithm is a MAC algorithm based on a block cipher. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a MAC algorithm based on a block cipher, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_BLOCK_CIPHER_MAC(alg) \ + (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_MAC_SUBCATEGORY_MASK)) == \ + PSA_ALG_CIPHER_MAC_BASE) + +#define PSA_ALG_CIPHER_STREAM_FLAG ((psa_algorithm_t)0x00800000) +#define PSA_ALG_CIPHER_FROM_BLOCK_FLAG ((psa_algorithm_t)0x00400000) + +/** Whether the specified algorithm is a stream cipher. + * + * A stream cipher is a symmetric cipher that encrypts or decrypts messages + * by applying a bitwise-xor with a stream of bytes that is generated + * from a key. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a stream cipher algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier or if it is not a symmetric cipher algorithm. + */ +#define PSA_ALG_IS_STREAM_CIPHER(alg) \ + (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_CIPHER_STREAM_FLAG)) == \ + (PSA_ALG_CATEGORY_CIPHER | PSA_ALG_CIPHER_STREAM_FLAG)) + +/** The ARC4 stream cipher algorithm. + */ +#define PSA_ALG_ARC4 ((psa_algorithm_t)0x04800001) + +/** The ChaCha20 stream cipher. + * + * ChaCha20 is defined in RFC 7539. + * + * The nonce size for psa_cipher_set_iv() or psa_cipher_generate_iv() + * must be 12. + * + * The initial block counter is always 0. + * + */ +#define PSA_ALG_CHACHA20 ((psa_algorithm_t)0x04800005) + +/** The CTR stream cipher mode. + * + * CTR is a stream cipher which is built from a block cipher. + * The underlying block cipher is determined by the key type. + * For example, to use AES-128-CTR, use this algorithm with + * a key of type #PSA_KEY_TYPE_AES and a length of 128 bits (16 bytes). + */ +#define PSA_ALG_CTR ((psa_algorithm_t)0x04c00001) + +/** The CFB stream cipher mode. + * + * The underlying block cipher is determined by the key type. + */ +#define PSA_ALG_CFB ((psa_algorithm_t)0x04c00002) + +/** The OFB stream cipher mode. + * + * The underlying block cipher is determined by the key type. + */ +#define PSA_ALG_OFB ((psa_algorithm_t)0x04c00003) + +/** The XTS cipher mode. + * + * XTS is a cipher mode which is built from a block cipher. It requires at + * least one full block of input, but beyond this minimum the input + * does not need to be a whole number of blocks. + */ +#define PSA_ALG_XTS ((psa_algorithm_t)0x044000ff) + +/** The Electronic Code Book (ECB) mode of a block cipher, with no padding. + * + * \warning ECB mode does not protect the confidentiality of the encrypted data + * except in extremely narrow circumstances. It is recommended that applications + * only use ECB if they need to construct an operating mode that the + * implementation does not provide. Implementations are encouraged to provide + * the modes that applications need in preference to supporting direct access + * to ECB. + * + * The underlying block cipher is determined by the key type. + * + * This symmetric cipher mode can only be used with messages whose lengths are a + * multiple of the block size of the chosen block cipher. + * + * ECB mode does not accept an initialization vector (IV). When using a + * multi-part cipher operation with this algorithm, psa_cipher_generate_iv() + * and psa_cipher_set_iv() must not be called. + */ +#define PSA_ALG_ECB_NO_PADDING ((psa_algorithm_t)0x04404400) + +/** The CBC block cipher chaining mode, with no padding. + * + * The underlying block cipher is determined by the key type. + * + * This symmetric cipher mode can only be used with messages whose lengths + * are whole number of blocks for the chosen block cipher. + */ +#define PSA_ALG_CBC_NO_PADDING ((psa_algorithm_t)0x04600100) + +/** The CBC block cipher chaining mode with PKCS#7 padding. + * + * The underlying block cipher is determined by the key type. + * + * This is the padding method defined by PKCS#7 (RFC 2315) §10.3. + */ +#define PSA_ALG_CBC_PKCS7 ((psa_algorithm_t)0x04600101) + +#define PSA_ALG_AEAD_FROM_BLOCK_FLAG ((psa_algorithm_t)0x00400000) + +/** Whether the specified algorithm is an AEAD mode on a block cipher. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is an AEAD algorithm which is an AEAD mode based on + * a block cipher, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) \ + (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_AEAD_FROM_BLOCK_FLAG)) == \ + (PSA_ALG_CATEGORY_AEAD | PSA_ALG_AEAD_FROM_BLOCK_FLAG)) + +/** The CCM authenticated encryption algorithm. + * + * The underlying block cipher is determined by the key type. + */ +#define PSA_ALG_CCM ((psa_algorithm_t)0x06401001) + +/** The GCM authenticated encryption algorithm. + * + * The underlying block cipher is determined by the key type. + */ +#define PSA_ALG_GCM ((psa_algorithm_t)0x06401002) + +/** The Chacha20-Poly1305 AEAD algorithm. + * + * The ChaCha20_Poly1305 construction is defined in RFC 7539. + * + * Implementations must support 12-byte nonces, may support 8-byte nonces, + * and should reject other sizes. + * + * Implementations must support 16-byte tags and should reject other sizes. + */ +#define PSA_ALG_CHACHA20_POLY1305 ((psa_algorithm_t)0x06001005) + +/* In the encoding of a AEAD algorithm, the bits corresponding to + * PSA_ALG_AEAD_TAG_LENGTH_MASK encode the length of the AEAD tag. + * The constants for default lengths follow this encoding. + */ +#define PSA_ALG_AEAD_TAG_LENGTH_MASK ((psa_algorithm_t)0x00003f00) +#define PSA_AEAD_TAG_LENGTH_OFFSET 8 + +/** Macro to build a shortened AEAD algorithm. + * + * A shortened AEAD algorithm is similar to the corresponding AEAD + * algorithm, but has an authentication tag that consists of fewer bytes. + * Depending on the algorithm, the tag length may affect the calculation + * of the ciphertext. + * + * \param aead_alg An AEAD algorithm identifier (value of type + * #psa_algorithm_t such that #PSA_ALG_IS_AEAD(\p alg) + * is true). + * \param tag_length Desired length of the authentication tag in bytes. + * + * \return The corresponding AEAD algorithm with the specified + * length. + * \return Unspecified if \p alg is not a supported + * AEAD algorithm or if \p tag_length is not valid + * for the specified AEAD algorithm. + */ +#define PSA_ALG_AEAD_WITH_TAG_LENGTH(aead_alg, tag_length) \ + (((aead_alg) & ~PSA_ALG_AEAD_TAG_LENGTH_MASK) | \ + ((tag_length) << PSA_AEAD_TAG_LENGTH_OFFSET & \ + PSA_ALG_AEAD_TAG_LENGTH_MASK)) + +/** Calculate the corresponding AEAD algorithm with the default tag length. + * + * \param aead_alg An AEAD algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \return The corresponding AEAD algorithm with the default + * tag length for that algorithm. + */ +#define PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH(aead_alg) \ + ( \ + PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH_CASE(aead_alg, PSA_ALG_CCM) \ + PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH_CASE(aead_alg, PSA_ALG_GCM) \ + PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH_CASE(aead_alg, PSA_ALG_CHACHA20_POLY1305) \ + 0) +#define PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH_CASE(aead_alg, ref) \ + PSA_ALG_AEAD_WITH_TAG_LENGTH(aead_alg, 0) == \ + PSA_ALG_AEAD_WITH_TAG_LENGTH(ref, 0) ? \ + ref : + +#define PSA_ALG_RSA_PKCS1V15_SIGN_BASE ((psa_algorithm_t)0x10020000) +/** RSA PKCS#1 v1.5 signature with hashing. + * + * This is the signature scheme defined by RFC 8017 + * (PKCS#1: RSA Cryptography Specifications) under the name + * RSASSA-PKCS1-v1_5. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * This includes #PSA_ALG_ANY_HASH + * when specifying the algorithm in a usage policy. + * + * \return The corresponding RSA PKCS#1 v1.5 signature algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_RSA_PKCS1V15_SIGN(hash_alg) \ + (PSA_ALG_RSA_PKCS1V15_SIGN_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +/** Raw PKCS#1 v1.5 signature. + * + * The input to this algorithm is the DigestInfo structure used by + * RFC 8017 (PKCS#1: RSA Cryptography Specifications), §9.2 + * steps 3–6. + */ +#define PSA_ALG_RSA_PKCS1V15_SIGN_RAW PSA_ALG_RSA_PKCS1V15_SIGN_BASE +#define PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PKCS1V15_SIGN_BASE) + +#define PSA_ALG_RSA_PSS_BASE ((psa_algorithm_t)0x10030000) +/** RSA PSS signature with hashing. + * + * This is the signature scheme defined by RFC 8017 + * (PKCS#1: RSA Cryptography Specifications) under the name + * RSASSA-PSS, with the message generation function MGF1, and with + * a salt length equal to the length of the hash. The specified + * hash algorithm is used to hash the input message, to create the + * salted hash, and for the mask generation. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * This includes #PSA_ALG_ANY_HASH + * when specifying the algorithm in a usage policy. + * + * \return The corresponding RSA PSS signature algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_RSA_PSS(hash_alg) \ + (PSA_ALG_RSA_PSS_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +#define PSA_ALG_IS_RSA_PSS(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PSS_BASE) + +#define PSA_ALG_ECDSA_BASE ((psa_algorithm_t)0x10060000) +/** ECDSA signature with hashing. + * + * This is the ECDSA signature scheme defined by ANSI X9.62, + * with a random per-message secret number (*k*). + * + * The representation of the signature as a byte string consists of + * the concatentation of the signature values *r* and *s*. Each of + * *r* and *s* is encoded as an *N*-octet string, where *N* is the length + * of the base point of the curve in octets. Each value is represented + * in big-endian order (most significant octet first). + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * This includes #PSA_ALG_ANY_HASH + * when specifying the algorithm in a usage policy. + * + * \return The corresponding ECDSA signature algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_ECDSA(hash_alg) \ + (PSA_ALG_ECDSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +/** ECDSA signature without hashing. + * + * This is the same signature scheme as #PSA_ALG_ECDSA(), but + * without specifying a hash algorithm. This algorithm may only be + * used to sign or verify a sequence of bytes that should be an + * already-calculated hash. Note that the input is padded with + * zeros on the left or truncated on the left as required to fit + * the curve size. + */ +#define PSA_ALG_ECDSA_ANY PSA_ALG_ECDSA_BASE +#define PSA_ALG_DETERMINISTIC_ECDSA_BASE ((psa_algorithm_t)0x10070000) +/** Deterministic ECDSA signature with hashing. + * + * This is the deterministic ECDSA signature scheme defined by RFC 6979. + * + * The representation of a signature is the same as with #PSA_ALG_ECDSA(). + * + * Note that when this algorithm is used for verification, signatures + * made with randomized ECDSA (#PSA_ALG_ECDSA(\p hash_alg)) with the + * same private key are accepted. In other words, + * #PSA_ALG_DETERMINISTIC_ECDSA(\p hash_alg) differs from + * #PSA_ALG_ECDSA(\p hash_alg) only for signature, not for verification. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * This includes #PSA_ALG_ANY_HASH + * when specifying the algorithm in a usage policy. + * + * \return The corresponding deterministic ECDSA signature + * algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_DETERMINISTIC_ECDSA(hash_alg) \ + (PSA_ALG_DETERMINISTIC_ECDSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +#define PSA_ALG_ECDSA_DETERMINISTIC_FLAG ((psa_algorithm_t)0x00010000) +#define PSA_ALG_IS_ECDSA(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK & ~PSA_ALG_ECDSA_DETERMINISTIC_FLAG) == \ + PSA_ALG_ECDSA_BASE) +#define PSA_ALG_ECDSA_IS_DETERMINISTIC(alg) \ + (((alg) & PSA_ALG_ECDSA_DETERMINISTIC_FLAG) != 0) +#define PSA_ALG_IS_DETERMINISTIC_ECDSA(alg) \ + (PSA_ALG_IS_ECDSA(alg) && PSA_ALG_ECDSA_IS_DETERMINISTIC(alg)) +#define PSA_ALG_IS_RANDOMIZED_ECDSA(alg) \ + (PSA_ALG_IS_ECDSA(alg) && !PSA_ALG_ECDSA_IS_DETERMINISTIC(alg)) + +/** Whether the specified algorithm is a hash-and-sign algorithm. + * + * Hash-and-sign algorithms are asymmetric (public-key) signature algorithms + * structured in two parts: first the calculation of a hash in a way that + * does not depend on the key, then the calculation of a signature from the + * hash value and the key. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a hash-and-sign algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_HASH_AND_SIGN(alg) \ + (PSA_ALG_IS_RSA_PSS(alg) || PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) || \ + PSA_ALG_IS_ECDSA(alg)) + +/** Get the hash used by a hash-and-sign signature algorithm. + * + * A hash-and-sign algorithm is a signature algorithm which is + * composed of two phases: first a hashing phase which does not use + * the key and produces a hash of the input message, then a signing + * phase which only uses the hash and the key and not the message + * itself. + * + * \param alg A signature algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_SIGN(\p alg) is true). + * + * \return The underlying hash algorithm if \p alg is a hash-and-sign + * algorithm. + * \return 0 if \p alg is a signature algorithm that does not + * follow the hash-and-sign structure. + * \return Unspecified if \p alg is not a signature algorithm or + * if it is not supported by the implementation. + */ +#define PSA_ALG_SIGN_GET_HASH(alg) \ + (PSA_ALG_IS_HASH_AND_SIGN(alg) ? \ + ((alg) & PSA_ALG_HASH_MASK) == 0 ? /*"raw" algorithm*/ 0 : \ + ((alg) & PSA_ALG_HASH_MASK) | PSA_ALG_CATEGORY_HASH : \ + 0) + +/** RSA PKCS#1 v1.5 encryption. + */ +#define PSA_ALG_RSA_PKCS1V15_CRYPT ((psa_algorithm_t)0x12020000) + +#define PSA_ALG_RSA_OAEP_BASE ((psa_algorithm_t)0x12030000) +/** RSA OAEP encryption. + * + * This is the encryption scheme defined by RFC 8017 + * (PKCS#1: RSA Cryptography Specifications) under the name + * RSAES-OAEP, with the message generation function MGF1. + * + * \param hash_alg The hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true) to use + * for MGF1. + * + * \return The corresponding RSA OAEP encryption algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_RSA_OAEP(hash_alg) \ + (PSA_ALG_RSA_OAEP_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +#define PSA_ALG_IS_RSA_OAEP(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_OAEP_BASE) +#define PSA_ALG_RSA_OAEP_GET_HASH(alg) \ + (PSA_ALG_IS_RSA_OAEP(alg) ? \ + ((alg) & PSA_ALG_HASH_MASK) | PSA_ALG_CATEGORY_HASH : \ + 0) + +#define PSA_ALG_HKDF_BASE ((psa_algorithm_t)0x20000100) +/** Macro to build an HKDF algorithm. + * + * For example, `PSA_ALG_HKDF(PSA_ALG_SHA256)` is HKDF using HMAC-SHA-256. + * + * This key derivation algorithm uses the following inputs: + * - #PSA_KEY_DERIVATION_INPUT_SALT is the salt used in the "extract" step. + * It is optional; if omitted, the derivation uses an empty salt. + * - #PSA_KEY_DERIVATION_INPUT_SECRET is the secret key used in the "extract" step. + * - #PSA_KEY_DERIVATION_INPUT_INFO is the info string used in the "expand" step. + * You must pass #PSA_KEY_DERIVATION_INPUT_SALT before #PSA_KEY_DERIVATION_INPUT_SECRET. + * You may pass #PSA_KEY_DERIVATION_INPUT_INFO at any time after steup and before + * starting to generate output. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * + * \return The corresponding HKDF algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_HKDF(hash_alg) \ + (PSA_ALG_HKDF_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +/** Whether the specified algorithm is an HKDF algorithm. + * + * HKDF is a family of key derivation algorithms that are based on a hash + * function and the HMAC construction. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is an HKDF algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * key derivation algorithm identifier. + */ +#define PSA_ALG_IS_HKDF(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HKDF_BASE) +#define PSA_ALG_HKDF_GET_HASH(hkdf_alg) \ + (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK)) + +#define PSA_ALG_TLS12_PRF_BASE ((psa_algorithm_t)0x20000200) +/** Macro to build a TLS-1.2 PRF algorithm. + * + * TLS 1.2 uses a custom pseudorandom function (PRF) for key schedule, + * specified in Section 5 of RFC 5246. It is based on HMAC and can be + * used with either SHA-256 or SHA-384. + * + * This key derivation algorithm uses the following inputs, which must be + * passed in the order given here: + * - #PSA_KEY_DERIVATION_INPUT_SEED is the seed. + * - #PSA_KEY_DERIVATION_INPUT_SECRET is the secret key. + * - #PSA_KEY_DERIVATION_INPUT_LABEL is the label. + * + * For the application to TLS-1.2 key expansion, the seed is the + * concatenation of ServerHello.Random + ClientHello.Random, + * and the label is "key expansion". + * + * For example, `PSA_ALG_TLS12_PRF(PSA_ALG_SHA256)` represents the + * TLS 1.2 PRF using HMAC-SHA-256. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * + * \return The corresponding TLS-1.2 PRF algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_TLS12_PRF(hash_alg) \ + (PSA_ALG_TLS12_PRF_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) + +/** Whether the specified algorithm is a TLS-1.2 PRF algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is a TLS-1.2 PRF algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * key derivation algorithm identifier. + */ +#define PSA_ALG_IS_TLS12_PRF(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_TLS12_PRF_BASE) +#define PSA_ALG_TLS12_PRF_GET_HASH(hkdf_alg) \ + (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK)) + +#define PSA_ALG_TLS12_PSK_TO_MS_BASE ((psa_algorithm_t)0x20000300) +/** Macro to build a TLS-1.2 PSK-to-MasterSecret algorithm. + * + * In a pure-PSK handshake in TLS 1.2, the master secret is derived + * from the PreSharedKey (PSK) through the application of padding + * (RFC 4279, Section 2) and the TLS-1.2 PRF (RFC 5246, Section 5). + * The latter is based on HMAC and can be used with either SHA-256 + * or SHA-384. + * + * This key derivation algorithm uses the following inputs, which must be + * passed in the order given here: + * - #PSA_KEY_DERIVATION_INPUT_SEED is the seed. + * - #PSA_KEY_DERIVATION_INPUT_SECRET is the secret key. + * - #PSA_KEY_DERIVATION_INPUT_LABEL is the label. + * + * For the application to TLS-1.2, the seed (which is + * forwarded to the TLS-1.2 PRF) is the concatenation of the + * ClientHello.Random + ServerHello.Random, + * and the label is "master secret" or "extended master secret". + * + * For example, `PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA256)` represents the + * TLS-1.2 PSK to MasterSecret derivation PRF using HMAC-SHA-256. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * + * \return The corresponding TLS-1.2 PSK to MS algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_TLS12_PSK_TO_MS(hash_alg) \ + (PSA_ALG_TLS12_PSK_TO_MS_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) + +/** Whether the specified algorithm is a TLS-1.2 PSK to MS algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is a TLS-1.2 PSK to MS algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * key derivation algorithm identifier. + */ +#define PSA_ALG_IS_TLS12_PSK_TO_MS(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_TLS12_PSK_TO_MS_BASE) +#define PSA_ALG_TLS12_PSK_TO_MS_GET_HASH(hkdf_alg) \ + (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK)) + +#define PSA_ALG_KEY_DERIVATION_MASK ((psa_algorithm_t)0x0803ffff) +#define PSA_ALG_KEY_AGREEMENT_MASK ((psa_algorithm_t)0x10fc0000) + +/** Macro to build a combined algorithm that chains a key agreement with + * a key derivation. + * + * \param ka_alg A key agreement algorithm (\c PSA_ALG_XXX value such + * that #PSA_ALG_IS_KEY_AGREEMENT(\p ka_alg) is true). + * \param kdf_alg A key derivation algorithm (\c PSA_ALG_XXX value such + * that #PSA_ALG_IS_KEY_DERIVATION(\p kdf_alg) is true). + * + * \return The corresponding key agreement and derivation + * algorithm. + * \return Unspecified if \p ka_alg is not a supported + * key agreement algorithm or \p kdf_alg is not a + * supported key derivation algorithm. + */ +#define PSA_ALG_KEY_AGREEMENT(ka_alg, kdf_alg) \ + ((ka_alg) | (kdf_alg)) + +#define PSA_ALG_KEY_AGREEMENT_GET_KDF(alg) \ + (((alg) & PSA_ALG_KEY_DERIVATION_MASK) | PSA_ALG_CATEGORY_KEY_DERIVATION) + +#define PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) \ + (((alg) & PSA_ALG_KEY_AGREEMENT_MASK) | PSA_ALG_CATEGORY_KEY_AGREEMENT) + +/** Whether the specified algorithm is a raw key agreement algorithm. + * + * A raw key agreement algorithm is one that does not specify + * a key derivation function. + * Usually, raw key agreement algorithms are constructed directly with + * a \c PSA_ALG_xxx macro while non-raw key agreement algorithms are + * constructed with PSA_ALG_KEY_AGREEMENT(). + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a raw key agreement algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_RAW_KEY_AGREEMENT(alg) \ + (PSA_ALG_IS_KEY_AGREEMENT(alg) && \ + PSA_ALG_KEY_AGREEMENT_GET_KDF(alg) == PSA_ALG_CATEGORY_KEY_DERIVATION) + +#define PSA_ALG_IS_KEY_DERIVATION_OR_AGREEMENT(alg) \ + ((PSA_ALG_IS_KEY_DERIVATION(alg) || PSA_ALG_IS_KEY_AGREEMENT(alg))) + +/** The finite-field Diffie-Hellman (DH) key agreement algorithm. + * + * The shared secret produced by key agreement is + * `g^{ab}` in big-endian format. + * It is `ceiling(m / 8)` bytes long where `m` is the size of the prime `p` + * in bits. + */ +#define PSA_ALG_FFDH ((psa_algorithm_t)0x30100000) + +/** Whether the specified algorithm is a finite field Diffie-Hellman algorithm. + * + * This includes the raw finite field Diffie-Hellman algorithm as well as + * finite-field Diffie-Hellman followed by any supporter key derivation + * algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is a finite field Diffie-Hellman algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * key agreement algorithm identifier. + */ +#define PSA_ALG_IS_FFDH(alg) \ + (PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) == PSA_ALG_FFDH) + +/** The elliptic curve Diffie-Hellman (ECDH) key agreement algorithm. + * + * The shared secret produced by key agreement is the x-coordinate of + * the shared secret point. It is always `ceiling(m / 8)` bytes long where + * `m` is the bit size associated with the curve, i.e. the bit size of the + * order of the curve's coordinate field. When `m` is not a multiple of 8, + * the byte containing the most significant bit of the shared secret + * is padded with zero bits. The byte order is either little-endian + * or big-endian depending on the curve type. + * + * - For Montgomery curves (curve types `PSA_ECC_FAMILY_CURVEXXX`), + * the shared secret is the x-coordinate of `d_A Q_B = d_B Q_A` + * in little-endian byte order. + * The bit size is 448 for Curve448 and 255 for Curve25519. + * - For Weierstrass curves over prime fields (curve types + * `PSA_ECC_FAMILY_SECPXXX` and `PSA_ECC_FAMILY_BRAINPOOL_PXXX`), + * the shared secret is the x-coordinate of `d_A Q_B = d_B Q_A` + * in big-endian byte order. + * The bit size is `m = ceiling(log_2(p))` for the field `F_p`. + * - For Weierstrass curves over binary fields (curve types + * `PSA_ECC_FAMILY_SECTXXX`), + * the shared secret is the x-coordinate of `d_A Q_B = d_B Q_A` + * in big-endian byte order. + * The bit size is `m` for the field `F_{2^m}`. + */ +#define PSA_ALG_ECDH ((psa_algorithm_t)0x30200000) + +/** Whether the specified algorithm is an elliptic curve Diffie-Hellman + * algorithm. + * + * This includes the raw elliptic curve Diffie-Hellman algorithm as well as + * elliptic curve Diffie-Hellman followed by any supporter key derivation + * algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is an elliptic curve Diffie-Hellman algorithm, + * 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * key agreement algorithm identifier. + */ +#define PSA_ALG_IS_ECDH(alg) \ + (PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) == PSA_ALG_ECDH) + +/** Whether the specified algorithm encoding is a wildcard. + * + * Wildcard values may only be used to set the usage algorithm field in + * a policy, not to perform an operation. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is a wildcard algorithm encoding. + * \return 0 if \c alg is a non-wildcard algorithm encoding (suitable for + * an operation). + * \return This macro may return either 0 or 1 if \c alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_WILDCARD(alg) \ + (PSA_ALG_IS_HASH_AND_SIGN(alg) ? \ + PSA_ALG_SIGN_GET_HASH(alg) == PSA_ALG_ANY_HASH : \ + (alg) == PSA_ALG_ANY_HASH) + +/**@}*/ + +/** \defgroup key_lifetimes Key lifetimes + * @{ + */ + +/** The default lifetime for volatile keys. + * + * A volatile key only exists as long as the handle to it is not closed. + * The key material is guaranteed to be erased on a power reset. + * + * A key with this lifetime is typically stored in the RAM area of the + * PSA Crypto subsystem. However this is an implementation choice. + * If an implementation stores data about the key in a non-volatile memory, + * it must release all the resources associated with the key and erase the + * key material if the calling application terminates. + */ +#define PSA_KEY_LIFETIME_VOLATILE ((psa_key_lifetime_t)0x00000000) + +/** The default lifetime for persistent keys. + * + * A persistent key remains in storage until it is explicitly destroyed or + * until the corresponding storage area is wiped. This specification does + * not define any mechanism to wipe a storage area, but implementations may + * provide their own mechanism (for example to perform a factory reset, + * to prepare for device refurbishment, or to uninstall an application). + * + * This lifetime value is the default storage area for the calling + * application. Implementations may offer other storage areas designated + * by other lifetime values as implementation-specific extensions. + * See ::psa_key_lifetime_t for more information. + */ +#define PSA_KEY_LIFETIME_PERSISTENT ((psa_key_lifetime_t)0x00000001) + +/** The persistence level of volatile keys. + * + * See ::psa_key_persistence_t for more information. + */ +#define PSA_KEY_PERSISTENCE_VOLATILE ((psa_key_persistence_t)0x00) + +/** The default persistence level for persistent keys. + * + * See ::psa_key_persistence_t for more information. + */ +#define PSA_KEY_PERSISTENCE_DEFAULT ((psa_key_persistence_t)0x01) + +/** A persistence level indicating that a key is never destroyed. + * + * See ::psa_key_persistence_t for more information. + */ +#define PSA_KEY_PERSISTENCE_READ_ONLY ((psa_key_persistence_t)0xff) + +#define PSA_KEY_LIFETIME_GET_PERSISTENCE(lifetime) \ + ((psa_key_persistence_t)((lifetime) & 0x000000ff)) + +#define PSA_KEY_LIFETIME_GET_LOCATION(lifetime) \ + ((psa_key_location_t)((lifetime) >> 8)) + +/** Whether a key lifetime indicates that the key is volatile. + * + * A volatile key is automatically destroyed by the implementation when + * the application instance terminates. In particular, a volatile key + * is automatically destroyed on a power reset of the device. + * + * A key that is not volatile is persistent. Persistent keys are + * preserved until the application explicitly destroys them or until an + * implementation-specific device management event occurs (for example, + * a factory reset). + * + * \param lifetime The lifetime value to query (value of type + * ::psa_key_lifetime_t). + * + * \return \c 1 if the key is volatile, otherwise \c 0. + */ +#define PSA_KEY_LIFETIME_IS_VOLATILE(lifetime) \ + (PSA_KEY_LIFETIME_GET_PERSISTENCE(lifetime) == \ + PSA_KEY_PERSISTENCE_VOLATILE) + +/** Construct a lifetime from a persistence level and a location. + * + * \param persistence The persistence level + * (value of type ::psa_key_persistence_t). + * \param location The location indicator + * (value of type ::psa_key_location_t). + * + * \return The constructed lifetime value. + */ +#define PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(persistence, location) \ + ((location) << 8 | (persistence)) + +/** The local storage area for persistent keys. + * + * This storage area is available on all systems that can store persistent + * keys without delegating the storage to a third-party cryptoprocessor. + * + * See ::psa_key_location_t for more information. + */ +#define PSA_KEY_LOCATION_LOCAL_STORAGE ((psa_key_location_t)0x000000) + +#define PSA_KEY_LOCATION_VENDOR_FLAG ((psa_key_location_t)0x800000) + +/** The minimum value for a key identifier chosen by the application. + */ +#define PSA_KEY_ID_USER_MIN ((psa_key_id_t)0x00000001) +/** The maximum value for a key identifier chosen by the application. + */ +#define PSA_KEY_ID_USER_MAX ((psa_key_id_t)0x3fffffff) +/** The minimum value for a key identifier chosen by the implementation. + */ +#define PSA_KEY_ID_VENDOR_MIN ((psa_key_id_t)0x40000000) +/** The maximum value for a key identifier chosen by the implementation. + */ +#define PSA_KEY_ID_VENDOR_MAX ((psa_key_id_t)0x7fffffff) + + +#if !defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) + +#define MBEDTLS_SVC_KEY_ID_INIT ( (psa_key_id_t)0 ) +#define MBEDTLS_SVC_KEY_ID_GET_KEY_ID( id ) ( id ) +#define MBEDTLS_SVC_KEY_ID_GET_OWNER_ID( id ) ( 0 ) + +/** Utility to initialize a key identifier at runtime. + * + * \param unused Unused parameter. + * \param key_id Identifier of the key. + */ +static inline mbedtls_svc_key_id_t mbedtls_svc_key_id_make( + unsigned int unused, psa_key_id_t key_id ) +{ + (void)unused; + + return( key_id ); +} + +/** Compare two key identifiers. + * + * \param id1 First key identifier. + * \param id2 Second key identifier. + * + * \return Non-zero if the two key identifier are equal, zero otherwise. + */ +static inline int mbedtls_svc_key_id_equal( mbedtls_svc_key_id_t id1, + mbedtls_svc_key_id_t id2 ) +{ + return( id1 == id2 ); +} + +#else /* MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */ + +#define MBEDTLS_SVC_KEY_ID_INIT ( (mbedtls_svc_key_id_t){ 0, 0 } ) +#define MBEDTLS_SVC_KEY_ID_GET_KEY_ID( id ) ( ( id ).key_id ) +#define MBEDTLS_SVC_KEY_ID_GET_OWNER_ID( id ) ( ( id ).owner ) + +/** Utility to initialize a key identifier at runtime. + * + * \param owner_id Identifier of the key owner. + * \param key_id Identifier of the key. + */ +static inline mbedtls_svc_key_id_t mbedtls_svc_key_id_make( + mbedtls_key_owner_id_t owner_id, psa_key_id_t key_id ) +{ + return( (mbedtls_svc_key_id_t){ .key_id = key_id, + .owner = owner_id } ); +} + +/** Compare two key identifiers. + * + * \param id1 First key identifier. + * \param id2 Second key identifier. + * + * \return Non-zero if the two key identifier are equal, zero otherwise. + */ +static inline int mbedtls_svc_key_id_equal( mbedtls_svc_key_id_t id1, + mbedtls_svc_key_id_t id2 ) +{ + return( ( id1.key_id == id2.key_id ) && + mbedtls_key_owner_id_equal( id1.owner, id2.owner ) ); +} + +#endif /* !MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */ + +/**@}*/ + +/** \defgroup policy Key policies + * @{ + */ + +/** Whether the key may be exported. + * + * A public key or the public part of a key pair may always be exported + * regardless of the value of this permission flag. + * + * If a key does not have export permission, implementations shall not + * allow the key to be exported in plain form from the cryptoprocessor, + * whether through psa_export_key() or through a proprietary interface. + * The key may however be exportable in a wrapped form, i.e. in a form + * where it is encrypted by another key. + */ +#define PSA_KEY_USAGE_EXPORT ((psa_key_usage_t)0x00000001) + +/** Whether the key may be copied. + * + * This flag allows the use of psa_copy_key() to make a copy of the key + * with the same policy or a more restrictive policy. + * + * For lifetimes for which the key is located in a secure element which + * enforce the non-exportability of keys, copying a key outside the secure + * element also requires the usage flag #PSA_KEY_USAGE_EXPORT. + * Copying the key inside the secure element is permitted with just + * #PSA_KEY_USAGE_COPY if the secure element supports it. + * For keys with the lifetime #PSA_KEY_LIFETIME_VOLATILE or + * #PSA_KEY_LIFETIME_PERSISTENT, the usage flag #PSA_KEY_USAGE_COPY + * is sufficient to permit the copy. + */ +#define PSA_KEY_USAGE_COPY ((psa_key_usage_t)0x00000002) + +/** Whether the key may be used to encrypt a message. + * + * This flag allows the key to be used for a symmetric encryption operation, + * for an AEAD encryption-and-authentication operation, + * or for an asymmetric encryption operation, + * if otherwise permitted by the key's type and policy. + * + * For a key pair, this concerns the public key. + */ +#define PSA_KEY_USAGE_ENCRYPT ((psa_key_usage_t)0x00000100) + +/** Whether the key may be used to decrypt a message. + * + * This flag allows the key to be used for a symmetric decryption operation, + * for an AEAD decryption-and-verification operation, + * or for an asymmetric decryption operation, + * if otherwise permitted by the key's type and policy. + * + * For a key pair, this concerns the private key. + */ +#define PSA_KEY_USAGE_DECRYPT ((psa_key_usage_t)0x00000200) + +/** Whether the key may be used to sign a message. + * + * This flag allows the key to be used for a MAC calculation operation + * or for an asymmetric signature operation, + * if otherwise permitted by the key's type and policy. + * + * For a key pair, this concerns the private key. + */ +#define PSA_KEY_USAGE_SIGN_HASH ((psa_key_usage_t)0x00000400) + +/** Whether the key may be used to verify a message signature. + * + * This flag allows the key to be used for a MAC verification operation + * or for an asymmetric signature verification operation, + * if otherwise permitted by by the key's type and policy. + * + * For a key pair, this concerns the public key. + */ +#define PSA_KEY_USAGE_VERIFY_HASH ((psa_key_usage_t)0x00000800) + +/** Whether the key may be used to derive other keys. + */ +#define PSA_KEY_USAGE_DERIVE ((psa_key_usage_t)0x00001000) + +/**@}*/ + +/** \defgroup derivation Key derivation + * @{ + */ + +/** A secret input for key derivation. + * + * This should be a key of type #PSA_KEY_TYPE_DERIVE + * (passed to psa_key_derivation_input_key()) + * or the shared secret resulting from a key agreement + * (obtained via psa_key_derivation_key_agreement()). + * + * The secret can also be a direct input (passed to + * key_derivation_input_bytes()). In this case, the derivation operation + * may not be used to derive keys: the operation will only allow + * psa_key_derivation_output_bytes(), not psa_key_derivation_output_key(). + */ +#define PSA_KEY_DERIVATION_INPUT_SECRET ((psa_key_derivation_step_t)0x0101) + +/** A label for key derivation. + * + * This should be a direct input. + * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA. + */ +#define PSA_KEY_DERIVATION_INPUT_LABEL ((psa_key_derivation_step_t)0x0201) + +/** A salt for key derivation. + * + * This should be a direct input. + * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA. + */ +#define PSA_KEY_DERIVATION_INPUT_SALT ((psa_key_derivation_step_t)0x0202) + +/** An information string for key derivation. + * + * This should be a direct input. + * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA. + */ +#define PSA_KEY_DERIVATION_INPUT_INFO ((psa_key_derivation_step_t)0x0203) + +/** A seed for key derivation. + * + * This should be a direct input. + * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA. + */ +#define PSA_KEY_DERIVATION_INPUT_SEED ((psa_key_derivation_step_t)0x0204) + +/**@}*/ + +#endif /* PSA_CRYPTO_VALUES_H */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/CMakeLists.txt b/Android/Level4/app/src/main/c/mbedtls/library/CMakeLists.txt new file mode 100644 index 0000000..8962555 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/CMakeLists.txt @@ -0,0 +1,231 @@ +option(USE_STATIC_MBEDTLS_LIBRARY "Build mbed TLS static library." ON) +option(USE_SHARED_MBEDTLS_LIBRARY "Build mbed TLS shared library." OFF) +option(LINK_WITH_PTHREAD "Explicitly link mbed TLS library to pthread." OFF) +option(LINK_WITH_TRUSTED_STORAGE "Explicitly link mbed TLS library to trusted_storage." OFF) + +# Set the project root directory if it's not already defined, as may happen if +# the library folder is included directly by a parent project, without +# including the top level CMakeLists.txt. +if(NOT DEFINED MBEDTLS_DIR) + set(MBEDTLS_DIR ${CMAKE_SOURCE_DIR}) +endif() + +set(src_crypto + aes.c + aesni.c + arc4.c + aria.c + asn1parse.c + asn1write.c + base64.c + bignum.c + blowfish.c + camellia.c + ccm.c + chacha20.c + chachapoly.c + cipher.c + cipher_wrap.c + cmac.c + ctr_drbg.c + des.c + dhm.c + ecdh.c + ecdsa.c + ecjpake.c + ecp.c + ecp_curves.c + entropy.c + entropy_poll.c + error.c + gcm.c + havege.c + hkdf.c + hmac_drbg.c + md.c + md2.c + md4.c + md5.c + memory_buffer_alloc.c + nist_kw.c + oid.c + padlock.c + pem.c + pk.c + pk_wrap.c + pkcs12.c + pkcs5.c + pkparse.c + pkwrite.c + platform.c + platform_util.c + poly1305.c + psa_crypto.c + psa_crypto_driver_wrappers.c + psa_crypto_se.c + psa_crypto_slot_management.c + psa_crypto_storage.c + psa_its_file.c + ripemd160.c + rsa.c + rsa_internal.c + sha1.c + sha256.c + sha512.c + threading.c + timing.c + version.c + version_features.c + xtea.c +) + +list(APPEND src_crypto ${thirdparty_src}) + +set(src_x509 + certs.c + pkcs11.c + x509.c + x509_create.c + x509_crl.c + x509_crt.c + x509_csr.c + x509write_crt.c + x509write_csr.c +) + +set(src_tls + debug.c + net_sockets.c + ssl_cache.c + ssl_ciphersuites.c + ssl_cli.c + ssl_cookie.c + ssl_msg.c + ssl_srv.c + ssl_ticket.c + ssl_tls.c + ssl_tls13_keys.c +) + +if(CMAKE_COMPILER_IS_GNUCC) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-declarations -Wmissing-prototypes") +endif(CMAKE_COMPILER_IS_GNUCC) + +if(CMAKE_COMPILER_IS_CLANG) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-declarations -Wmissing-prototypes -Wdocumentation -Wno-documentation-deprecated-sync -Wunreachable-code") +endif(CMAKE_COMPILER_IS_CLANG) + +if(WIN32) + set(libs ${libs} ws2_32) +endif(WIN32) + +if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + SET(CMAKE_C_ARCHIVE_CREATE " Scr ") + SET(CMAKE_CXX_ARCHIVE_CREATE " Scr ") + SET(CMAKE_C_ARCHIVE_FINISH " -no_warning_for_no_symbols -c ") + SET(CMAKE_CXX_ARCHIVE_FINISH " -no_warning_for_no_symbols -c ") +endif() + +if(HAIKU) + set(libs ${libs} network) +endif(HAIKU) + +if(USE_PKCS11_HELPER_LIBRARY) + set(libs ${libs} pkcs11-helper) +endif(USE_PKCS11_HELPER_LIBRARY) + +if(ENABLE_ZLIB_SUPPORT) + set(libs ${libs} ${ZLIB_LIBRARIES}) +endif(ENABLE_ZLIB_SUPPORT) + +if(LINK_WITH_PTHREAD) + set(libs ${libs} pthread) +endif() + +if(LINK_WITH_TRUSTED_STORAGE) + set(libs ${libs} trusted_storage) +endif() + +if (NOT USE_STATIC_MBEDTLS_LIBRARY AND NOT USE_SHARED_MBEDTLS_LIBRARY) + message(FATAL_ERROR "Need to choose static or shared mbedtls build!") +endif(NOT USE_STATIC_MBEDTLS_LIBRARY AND NOT USE_SHARED_MBEDTLS_LIBRARY) + +set(mbedtls_target "${MBEDTLS_TARGET_PREFIX}mbedtls") +set(mbedx509_target "${MBEDTLS_TARGET_PREFIX}mbedx509") +set(mbedcrypto_target "${MBEDTLS_TARGET_PREFIX}mbedcrypto") + +set(mbedtls_target ${mbedtls_target} PARENT_SCOPE) +set(mbedx509_target ${mbedx509_target} PARENT_SCOPE) +set(mbedcrypto_target ${mbedcrypto_target} PARENT_SCOPE) + +if (USE_STATIC_MBEDTLS_LIBRARY) + set(mbedtls_static_target ${mbedtls_target}) + set(mbedx509_static_target ${mbedx509_target}) + set(mbedcrypto_static_target ${mbedcrypto_target}) +endif() + +set(target_libraries ${mbedcrypto_target} ${mbedx509_target} ${mbedtls_target}) + +if(USE_STATIC_MBEDTLS_LIBRARY AND USE_SHARED_MBEDTLS_LIBRARY) + string(APPEND mbedtls_static_target "_static") + string(APPEND mbedx509_static_target "_static") + string(APPEND mbedcrypto_static_target "_static") + + list(APPEND target_libraries + ${mbedcrypto_static_target} + ${mbedx509_static_target} + ${mbedtls_static_target}) +endif() + +if(USE_STATIC_MBEDTLS_LIBRARY) + add_library(${mbedcrypto_static_target} STATIC ${src_crypto}) + set_target_properties(${mbedcrypto_static_target} PROPERTIES OUTPUT_NAME mbedcrypto) + target_link_libraries(${mbedcrypto_static_target} PUBLIC ${libs}) + + add_library(${mbedx509_static_target} STATIC ${src_x509}) + set_target_properties(${mbedx509_static_target} PROPERTIES OUTPUT_NAME mbedx509) + target_link_libraries(${mbedx509_static_target} PUBLIC ${libs} ${mbedcrypto_static_target}) + + add_library(${mbedtls_static_target} STATIC ${src_tls}) + set_target_properties(${mbedtls_static_target} PROPERTIES OUTPUT_NAME mbedtls) + target_link_libraries(${mbedtls_static_target} PUBLIC ${libs} ${mbedx509_static_target}) +endif(USE_STATIC_MBEDTLS_LIBRARY) + +if(USE_SHARED_MBEDTLS_LIBRARY) + add_library(${mbedcrypto_target} SHARED ${src_crypto}) + set_target_properties(${mbedcrypto_target} PROPERTIES VERSION 2.24.0 SOVERSION 5) + target_link_libraries(${mbedcrypto_target} PUBLIC ${libs}) + + add_library(${mbedx509_target} SHARED ${src_x509}) + set_target_properties(${mbedx509_target} PROPERTIES VERSION 2.24.0 SOVERSION 1) + target_link_libraries(${mbedx509_target} PUBLIC ${libs} ${mbedcrypto_target}) + + add_library(${mbedtls_target} SHARED ${src_tls}) + set_target_properties(${mbedtls_target} PROPERTIES VERSION 2.24.0 SOVERSION 13) + target_link_libraries(${mbedtls_target} PUBLIC ${libs} ${mbedx509_target}) +endif(USE_SHARED_MBEDTLS_LIBRARY) + +foreach(target IN LISTS target_libraries) + # Include public header files from /include and other directories + # declared by /3rdparty/**/CMakeLists.txt. Include private header files + # from /library and others declared by /3rdparty/**/CMakeLists.txt. + # /library needs to be listed explicitly when building .c files outside + # of /library (which currently means: under /3rdparty). + target_include_directories(${target} + PUBLIC ${MBEDTLS_DIR}/include/ + PUBLIC ${thirdparty_inc_public} + PRIVATE ${MBEDTLS_DIR}/library/ + PRIVATE ${thirdparty_inc}) + target_compile_definitions(${target} + PRIVATE ${thirdparty_def}) + install(TARGETS ${target} + DESTINATION ${LIB_INSTALL_DIR} + PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ) +endforeach(target) + +set(lib_target "${MBEDTLS_TARGET_PREFIX}lib") + +add_custom_target(${lib_target} DEPENDS ${mbedcrypto_target} ${mbedx509_target} ${mbedtls_target}) +if(USE_STATIC_MBEDTLS_LIBRARY AND USE_SHARED_MBEDTLS_LIBRARY) + add_dependencies(${lib_target} ${mbedcrypto_static_target} ${mbedx509_static_target} ${mbedtls_static_target}) +endif() diff --git a/Android/Level4/app/src/main/c/mbedtls/library/Makefile b/Android/Level4/app/src/main/c/mbedtls/library/Makefile new file mode 100644 index 0000000..a6db9b3 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/Makefile @@ -0,0 +1,276 @@ + +# Also see "include/mbedtls/config.h" + +CFLAGS ?= -O2 +WARNING_CFLAGS ?= -Wall -Wextra +LDFLAGS ?= + +# Include ../include for public headers and . for private headers. +# Note that . needs to be included explicitly for the sake of library +# files that are not in the /library directory (which currently means +# under /3rdparty). +LOCAL_CFLAGS = $(WARNING_CFLAGS) -I. -I../include -D_FILE_OFFSET_BITS=64 +LOCAL_LDFLAGS = + +ifdef DEBUG +LOCAL_CFLAGS += -g3 +endif + +# MicroBlaze specific options: +# CFLAGS += -mno-xl-soft-mul -mxl-barrel-shift + +# To compile on Plan9: +# CFLAGS += -D_BSD_EXTENSION + +# if were running on Windows build for Windows +ifdef WINDOWS +WINDOWS_BUILD=1 +else ifeq ($(shell uname -s),Darwin) +ifeq ($(AR),ar) +APPLE_BUILD ?= 1 +endif +endif + +# To compile as a shared library: +ifdef SHARED +# all code is position-indep with mingw, avoid warning about useless flag +ifndef WINDOWS_BUILD +LOCAL_CFLAGS += -fPIC -fpic +endif +endif + +SOEXT_TLS=so.13 +SOEXT_X509=so.1 +SOEXT_CRYPTO=so.5 + +# Set AR_DASH= (empty string) to use an ar implementation that does not accept +# the - prefix for command line options (e.g. llvm-ar) +AR_DASH ?= - + +ARFLAGS = $(AR_DASH)src +ifdef APPLE_BUILD +ifneq ($(APPLE_BUILD),0) +ARFLAGS = $(AR_DASH)Src +RLFLAGS = -no_warning_for_no_symbols -c +RL ?= ranlib +endif +endif + +DLEXT ?= so +ifdef WINDOWS_BUILD +# Windows shared library extension: +DLEXT = dll +else ifdef APPLE_BUILD +ifneq ($(APPLE_BUILD),0) +# Mac OS X shared library extension: +DLEXT = dylib +endif +endif + +OBJS_CRYPTO= \ + aes.o \ + aesni.o \ + arc4.o \ + aria.o \ + asn1parse.o \ + asn1write.o \ + base64.o \ + bignum.o \ + blowfish.o \ + camellia.o \ + ccm.o \ + chacha20.o \ + chachapoly.o \ + cipher.o \ + cipher_wrap.o \ + cmac.o \ + ctr_drbg.o \ + des.o \ + dhm.o \ + ecdh.o \ + ecdsa.o \ + ecjpake.o \ + ecp.o \ + ecp_curves.o \ + entropy.o \ + entropy_poll.o \ + error.o \ + gcm.o \ + havege.o \ + hkdf.o \ + hmac_drbg.o \ + md.o \ + md2.o \ + md4.o \ + md5.o \ + memory_buffer_alloc.o \ + nist_kw.o \ + oid.o \ + padlock.o \ + pem.o \ + pk.o \ + pk_wrap.o \ + pkcs12.o \ + pkcs5.o \ + pkparse.o \ + pkwrite.o \ + platform.o \ + platform_util.o \ + poly1305.o \ + psa_crypto.o \ + psa_crypto_driver_wrappers.o \ + psa_crypto_se.o \ + psa_crypto_slot_management.o \ + psa_crypto_storage.o \ + psa_its_file.o \ + ripemd160.o \ + rsa.o \ + rsa_internal.o \ + sha1.o \ + sha256.o \ + sha512.o \ + threading.o \ + timing.o \ + version.o \ + version_features.o \ + xtea.o \ + # This line is intentionally left blank + +include ../3rdparty/Makefile.inc +LOCAL_CFLAGS+=$(THIRDPARTY_INCLUDES) +OBJS_CRYPTO+=$(THIRDPARTY_CRYPTO_OBJECTS) + +OBJS_X509= \ + certs.o \ + pkcs11.o \ + x509.o \ + x509_create.o \ + x509_crl.o \ + x509_crt.o \ + x509_csr.o \ + x509write_crt.o \ + x509write_csr.o \ + # This line is intentionally left blank + +OBJS_TLS= \ + debug.o \ + net_sockets.o \ + ssl_cache.o \ + ssl_ciphersuites.o \ + ssl_cli.o \ + ssl_cookie.o \ + ssl_msg.o \ + ssl_srv.o \ + ssl_ticket.o \ + ssl_tls.o \ + ssl_tls13_keys.o \ + # This line is intentionally left blank + +.SILENT: + +.PHONY: all static shared clean + +ifndef SHARED +all: static +else +all: shared static +endif + +static: libmbedcrypto.a libmbedx509.a libmbedtls.a + +shared: libmbedcrypto.$(DLEXT) libmbedx509.$(DLEXT) libmbedtls.$(DLEXT) + +# tls +libmbedtls.a: $(OBJS_TLS) + echo " AR $@" + $(AR) $(ARFLAGS) $@ $(OBJS_TLS) +ifdef APPLE_BUILD +ifneq ($(APPLE_BUILD),0) + echo " RL $@" + $(RL) $(RLFLAGS) $@ +endif +endif + +libmbedtls.$(SOEXT_TLS): $(OBJS_TLS) libmbedx509.so + echo " LD $@" + $(CC) -shared -Wl,-soname,$@ -L. -lmbedcrypto -lmbedx509 $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ $(OBJS_TLS) + +libmbedtls.so: libmbedtls.$(SOEXT_TLS) + echo " LN $@ -> $<" + ln -sf $< $@ + +libmbedtls.dylib: $(OBJS_TLS) libmbedx509.dylib + echo " LD $@" + $(CC) -dynamiclib -L. -lmbedcrypto -lmbedx509 $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ $(OBJS_TLS) + +libmbedtls.dll: $(OBJS_TLS) libmbedx509.dll + echo " LD $@" + $(CC) -shared -Wl,-soname,$@ -Wl,--out-implib,$@.a -o $@ $(OBJS_TLS) -lws2_32 -lwinmm -lgdi32 -L. -lmbedcrypto -lmbedx509 -static-libgcc $(LOCAL_LDFLAGS) $(LDFLAGS) + +# x509 +libmbedx509.a: $(OBJS_X509) + echo " AR $@" + $(AR) $(ARFLAGS) $@ $(OBJS_X509) +ifdef APPLE_BUILD +ifneq ($(APPLE_BUILD),0) + echo " RL $@" + $(RL) $(RLFLAGS) $@ +endif +endif + +libmbedx509.$(SOEXT_X509): $(OBJS_X509) libmbedcrypto.so + echo " LD $@" + $(CC) -shared -Wl,-soname,$@ -L. -lmbedcrypto $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ $(OBJS_X509) + +libmbedx509.so: libmbedx509.$(SOEXT_X509) + echo " LN $@ -> $<" + ln -sf $< $@ + +libmbedx509.dylib: $(OBJS_X509) libmbedcrypto.dylib + echo " LD $@" + $(CC) -dynamiclib -L. -lmbedcrypto $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ $(OBJS_X509) + +libmbedx509.dll: $(OBJS_X509) libmbedcrypto.dll + echo " LD $@" + $(CC) -shared -Wl,-soname,$@ -Wl,--out-implib,$@.a -o $@ $(OBJS_X509) -lws2_32 -lwinmm -lgdi32 -L. -lmbedcrypto -static-libgcc $(LOCAL_LDFLAGS) $(LDFLAGS) + +# crypto +libmbedcrypto.a: $(OBJS_CRYPTO) + echo " AR $@" + $(AR) $(ARFLAGS) $@ $(OBJS_CRYPTO) +ifdef APPLE_BUILD +ifneq ($(APPLE_BUILD),0) + echo " RL $@" + $(RL) $(RLFLAGS) $@ +endif +endif + +libmbedcrypto.$(SOEXT_CRYPTO): $(OBJS_CRYPTO) + echo " LD $@" + $(CC) -shared -Wl,-soname,$@ $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ $(OBJS_CRYPTO) + +libmbedcrypto.so: libmbedcrypto.$(SOEXT_CRYPTO) + echo " LN $@ -> $<" + ln -sf $< $@ + +libmbedcrypto.dylib: $(OBJS_CRYPTO) + echo " LD $@" + $(CC) -dynamiclib $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ $(OBJS_CRYPTO) + +libmbedcrypto.dll: $(OBJS_CRYPTO) + echo " LD $@" + $(CC) -shared -Wl,-soname,$@ -Wl,--out-implib,$@.a -o $@ $(OBJS_CRYPTO) -lws2_32 -lwinmm -lgdi32 -static-libgcc $(LOCAL_LDFLAGS) $(LDFLAGS) + +.c.o: + echo " CC $<" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) -o $@ -c $< + +clean: +ifndef WINDOWS + rm -f *.o libmbed* + rm -f $(THIRDPARTY_CRYPTO_OBJECTS) +else + if exist *.o del /Q /F *.o + if exist libmbed* del /Q /F libmbed* + del /Q /F del_errors_out_if_the_file_list_is_empty_but_not_if_a_file_does_not_exist $(subst /,\,$(THIRDPARTY_CRYPTO_OBJECTS)) +endif diff --git a/Android/Level4/app/src/main/c/mbedtls/library/aes.c b/Android/Level4/app/src/main/c/mbedtls/library/aes.c new file mode 100644 index 0000000..3f61642 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/aes.c @@ -0,0 +1,2213 @@ +/* + * FIPS-197 compliant AES implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ +/* + * The AES block cipher was designed by Vincent Rijmen and Joan Daemen. + * + * http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf + * http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf + */ + +#include "common.h" + +#if defined(MBEDTLS_AES_C) + +#include + +#include "mbedtls/aes.h" +#include "mbedtls/platform.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" +#if defined(MBEDTLS_PADLOCK_C) +#include "mbedtls/padlock.h" +#endif +#if defined(MBEDTLS_AESNI_C) +#include "mbedtls/aesni.h" +#endif + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_AES_ALT) + +/* Parameter validation macros based on platform_util.h */ +#define AES_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_AES_BAD_INPUT_DATA ) +#define AES_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_UINT32_LE +#define GET_UINT32_LE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] ) \ + | ( (uint32_t) (b)[(i) + 1] << 8 ) \ + | ( (uint32_t) (b)[(i) + 2] << 16 ) \ + | ( (uint32_t) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef PUT_UINT32_LE +#define PUT_UINT32_LE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ + (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ + (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ + (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ +} +#endif + +#if defined(MBEDTLS_PADLOCK_C) && \ + ( defined(MBEDTLS_HAVE_X86) || defined(MBEDTLS_PADLOCK_ALIGN16) ) +static int aes_padlock_ace = -1; +#endif + +#if defined(MBEDTLS_AES_ROM_TABLES) +/* + * Forward S-box + */ +static const unsigned char FSb[256] = +{ + 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, + 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, + 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, + 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, + 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, + 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, + 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, + 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, + 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, + 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, + 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, + 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, + 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, + 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, + 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, + 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, + 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, + 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, + 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, + 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, + 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, + 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, + 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, + 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, + 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, + 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, + 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, + 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, + 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, + 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, + 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, + 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 +}; + +/* + * Forward tables + */ +#define FT \ +\ + V(A5,63,63,C6), V(84,7C,7C,F8), V(99,77,77,EE), V(8D,7B,7B,F6), \ + V(0D,F2,F2,FF), V(BD,6B,6B,D6), V(B1,6F,6F,DE), V(54,C5,C5,91), \ + V(50,30,30,60), V(03,01,01,02), V(A9,67,67,CE), V(7D,2B,2B,56), \ + V(19,FE,FE,E7), V(62,D7,D7,B5), V(E6,AB,AB,4D), V(9A,76,76,EC), \ + V(45,CA,CA,8F), V(9D,82,82,1F), V(40,C9,C9,89), V(87,7D,7D,FA), \ + V(15,FA,FA,EF), V(EB,59,59,B2), V(C9,47,47,8E), V(0B,F0,F0,FB), \ + V(EC,AD,AD,41), V(67,D4,D4,B3), V(FD,A2,A2,5F), V(EA,AF,AF,45), \ + V(BF,9C,9C,23), V(F7,A4,A4,53), V(96,72,72,E4), V(5B,C0,C0,9B), \ + V(C2,B7,B7,75), V(1C,FD,FD,E1), V(AE,93,93,3D), V(6A,26,26,4C), \ + V(5A,36,36,6C), V(41,3F,3F,7E), V(02,F7,F7,F5), V(4F,CC,CC,83), \ + V(5C,34,34,68), V(F4,A5,A5,51), V(34,E5,E5,D1), V(08,F1,F1,F9), \ + V(93,71,71,E2), V(73,D8,D8,AB), V(53,31,31,62), V(3F,15,15,2A), \ + V(0C,04,04,08), V(52,C7,C7,95), V(65,23,23,46), V(5E,C3,C3,9D), \ + V(28,18,18,30), V(A1,96,96,37), V(0F,05,05,0A), V(B5,9A,9A,2F), \ + V(09,07,07,0E), V(36,12,12,24), V(9B,80,80,1B), V(3D,E2,E2,DF), \ + V(26,EB,EB,CD), V(69,27,27,4E), V(CD,B2,B2,7F), V(9F,75,75,EA), \ + V(1B,09,09,12), V(9E,83,83,1D), V(74,2C,2C,58), V(2E,1A,1A,34), \ + V(2D,1B,1B,36), V(B2,6E,6E,DC), V(EE,5A,5A,B4), V(FB,A0,A0,5B), \ + V(F6,52,52,A4), V(4D,3B,3B,76), V(61,D6,D6,B7), V(CE,B3,B3,7D), \ + V(7B,29,29,52), V(3E,E3,E3,DD), V(71,2F,2F,5E), V(97,84,84,13), \ + V(F5,53,53,A6), V(68,D1,D1,B9), V(00,00,00,00), V(2C,ED,ED,C1), \ + V(60,20,20,40), V(1F,FC,FC,E3), V(C8,B1,B1,79), V(ED,5B,5B,B6), \ + V(BE,6A,6A,D4), V(46,CB,CB,8D), V(D9,BE,BE,67), V(4B,39,39,72), \ + V(DE,4A,4A,94), V(D4,4C,4C,98), V(E8,58,58,B0), V(4A,CF,CF,85), \ + V(6B,D0,D0,BB), V(2A,EF,EF,C5), V(E5,AA,AA,4F), V(16,FB,FB,ED), \ + V(C5,43,43,86), V(D7,4D,4D,9A), V(55,33,33,66), V(94,85,85,11), \ + V(CF,45,45,8A), V(10,F9,F9,E9), V(06,02,02,04), V(81,7F,7F,FE), \ + V(F0,50,50,A0), V(44,3C,3C,78), V(BA,9F,9F,25), V(E3,A8,A8,4B), \ + V(F3,51,51,A2), V(FE,A3,A3,5D), V(C0,40,40,80), V(8A,8F,8F,05), \ + V(AD,92,92,3F), V(BC,9D,9D,21), V(48,38,38,70), V(04,F5,F5,F1), \ + V(DF,BC,BC,63), V(C1,B6,B6,77), V(75,DA,DA,AF), V(63,21,21,42), \ + V(30,10,10,20), V(1A,FF,FF,E5), V(0E,F3,F3,FD), V(6D,D2,D2,BF), \ + V(4C,CD,CD,81), V(14,0C,0C,18), V(35,13,13,26), V(2F,EC,EC,C3), \ + V(E1,5F,5F,BE), V(A2,97,97,35), V(CC,44,44,88), V(39,17,17,2E), \ + V(57,C4,C4,93), V(F2,A7,A7,55), V(82,7E,7E,FC), V(47,3D,3D,7A), \ + V(AC,64,64,C8), V(E7,5D,5D,BA), V(2B,19,19,32), V(95,73,73,E6), \ + V(A0,60,60,C0), V(98,81,81,19), V(D1,4F,4F,9E), V(7F,DC,DC,A3), \ + V(66,22,22,44), V(7E,2A,2A,54), V(AB,90,90,3B), V(83,88,88,0B), \ + V(CA,46,46,8C), V(29,EE,EE,C7), V(D3,B8,B8,6B), V(3C,14,14,28), \ + V(79,DE,DE,A7), V(E2,5E,5E,BC), V(1D,0B,0B,16), V(76,DB,DB,AD), \ + V(3B,E0,E0,DB), V(56,32,32,64), V(4E,3A,3A,74), V(1E,0A,0A,14), \ + V(DB,49,49,92), V(0A,06,06,0C), V(6C,24,24,48), V(E4,5C,5C,B8), \ + V(5D,C2,C2,9F), V(6E,D3,D3,BD), V(EF,AC,AC,43), V(A6,62,62,C4), \ + V(A8,91,91,39), V(A4,95,95,31), V(37,E4,E4,D3), V(8B,79,79,F2), \ + V(32,E7,E7,D5), V(43,C8,C8,8B), V(59,37,37,6E), V(B7,6D,6D,DA), \ + V(8C,8D,8D,01), V(64,D5,D5,B1), V(D2,4E,4E,9C), V(E0,A9,A9,49), \ + V(B4,6C,6C,D8), V(FA,56,56,AC), V(07,F4,F4,F3), V(25,EA,EA,CF), \ + V(AF,65,65,CA), V(8E,7A,7A,F4), V(E9,AE,AE,47), V(18,08,08,10), \ + V(D5,BA,BA,6F), V(88,78,78,F0), V(6F,25,25,4A), V(72,2E,2E,5C), \ + V(24,1C,1C,38), V(F1,A6,A6,57), V(C7,B4,B4,73), V(51,C6,C6,97), \ + V(23,E8,E8,CB), V(7C,DD,DD,A1), V(9C,74,74,E8), V(21,1F,1F,3E), \ + V(DD,4B,4B,96), V(DC,BD,BD,61), V(86,8B,8B,0D), V(85,8A,8A,0F), \ + V(90,70,70,E0), V(42,3E,3E,7C), V(C4,B5,B5,71), V(AA,66,66,CC), \ + V(D8,48,48,90), V(05,03,03,06), V(01,F6,F6,F7), V(12,0E,0E,1C), \ + V(A3,61,61,C2), V(5F,35,35,6A), V(F9,57,57,AE), V(D0,B9,B9,69), \ + V(91,86,86,17), V(58,C1,C1,99), V(27,1D,1D,3A), V(B9,9E,9E,27), \ + V(38,E1,E1,D9), V(13,F8,F8,EB), V(B3,98,98,2B), V(33,11,11,22), \ + V(BB,69,69,D2), V(70,D9,D9,A9), V(89,8E,8E,07), V(A7,94,94,33), \ + V(B6,9B,9B,2D), V(22,1E,1E,3C), V(92,87,87,15), V(20,E9,E9,C9), \ + V(49,CE,CE,87), V(FF,55,55,AA), V(78,28,28,50), V(7A,DF,DF,A5), \ + V(8F,8C,8C,03), V(F8,A1,A1,59), V(80,89,89,09), V(17,0D,0D,1A), \ + V(DA,BF,BF,65), V(31,E6,E6,D7), V(C6,42,42,84), V(B8,68,68,D0), \ + V(C3,41,41,82), V(B0,99,99,29), V(77,2D,2D,5A), V(11,0F,0F,1E), \ + V(CB,B0,B0,7B), V(FC,54,54,A8), V(D6,BB,BB,6D), V(3A,16,16,2C) + +#define V(a,b,c,d) 0x##a##b##c##d +static const uint32_t FT0[256] = { FT }; +#undef V + +#if !defined(MBEDTLS_AES_FEWER_TABLES) + +#define V(a,b,c,d) 0x##b##c##d##a +static const uint32_t FT1[256] = { FT }; +#undef V + +#define V(a,b,c,d) 0x##c##d##a##b +static const uint32_t FT2[256] = { FT }; +#undef V + +#define V(a,b,c,d) 0x##d##a##b##c +static const uint32_t FT3[256] = { FT }; +#undef V + +#endif /* !MBEDTLS_AES_FEWER_TABLES */ + +#undef FT + +/* + * Reverse S-box + */ +static const unsigned char RSb[256] = +{ + 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, + 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, + 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, + 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, + 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, + 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, + 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, + 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, + 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, + 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, + 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, + 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, + 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, + 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, + 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, + 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, + 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, + 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, + 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, + 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, + 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, + 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, + 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, + 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, + 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, + 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, + 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, + 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, + 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, + 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, + 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D +}; + +/* + * Reverse tables + */ +#define RT \ +\ + V(50,A7,F4,51), V(53,65,41,7E), V(C3,A4,17,1A), V(96,5E,27,3A), \ + V(CB,6B,AB,3B), V(F1,45,9D,1F), V(AB,58,FA,AC), V(93,03,E3,4B), \ + V(55,FA,30,20), V(F6,6D,76,AD), V(91,76,CC,88), V(25,4C,02,F5), \ + V(FC,D7,E5,4F), V(D7,CB,2A,C5), V(80,44,35,26), V(8F,A3,62,B5), \ + V(49,5A,B1,DE), V(67,1B,BA,25), V(98,0E,EA,45), V(E1,C0,FE,5D), \ + V(02,75,2F,C3), V(12,F0,4C,81), V(A3,97,46,8D), V(C6,F9,D3,6B), \ + V(E7,5F,8F,03), V(95,9C,92,15), V(EB,7A,6D,BF), V(DA,59,52,95), \ + V(2D,83,BE,D4), V(D3,21,74,58), V(29,69,E0,49), V(44,C8,C9,8E), \ + V(6A,89,C2,75), V(78,79,8E,F4), V(6B,3E,58,99), V(DD,71,B9,27), \ + V(B6,4F,E1,BE), V(17,AD,88,F0), V(66,AC,20,C9), V(B4,3A,CE,7D), \ + V(18,4A,DF,63), V(82,31,1A,E5), V(60,33,51,97), V(45,7F,53,62), \ + V(E0,77,64,B1), V(84,AE,6B,BB), V(1C,A0,81,FE), V(94,2B,08,F9), \ + V(58,68,48,70), V(19,FD,45,8F), V(87,6C,DE,94), V(B7,F8,7B,52), \ + V(23,D3,73,AB), V(E2,02,4B,72), V(57,8F,1F,E3), V(2A,AB,55,66), \ + V(07,28,EB,B2), V(03,C2,B5,2F), V(9A,7B,C5,86), V(A5,08,37,D3), \ + V(F2,87,28,30), V(B2,A5,BF,23), V(BA,6A,03,02), V(5C,82,16,ED), \ + V(2B,1C,CF,8A), V(92,B4,79,A7), V(F0,F2,07,F3), V(A1,E2,69,4E), \ + V(CD,F4,DA,65), V(D5,BE,05,06), V(1F,62,34,D1), V(8A,FE,A6,C4), \ + V(9D,53,2E,34), V(A0,55,F3,A2), V(32,E1,8A,05), V(75,EB,F6,A4), \ + V(39,EC,83,0B), V(AA,EF,60,40), V(06,9F,71,5E), V(51,10,6E,BD), \ + V(F9,8A,21,3E), V(3D,06,DD,96), V(AE,05,3E,DD), V(46,BD,E6,4D), \ + V(B5,8D,54,91), V(05,5D,C4,71), V(6F,D4,06,04), V(FF,15,50,60), \ + V(24,FB,98,19), V(97,E9,BD,D6), V(CC,43,40,89), V(77,9E,D9,67), \ + V(BD,42,E8,B0), V(88,8B,89,07), V(38,5B,19,E7), V(DB,EE,C8,79), \ + V(47,0A,7C,A1), V(E9,0F,42,7C), V(C9,1E,84,F8), V(00,00,00,00), \ + V(83,86,80,09), V(48,ED,2B,32), V(AC,70,11,1E), V(4E,72,5A,6C), \ + V(FB,FF,0E,FD), V(56,38,85,0F), V(1E,D5,AE,3D), V(27,39,2D,36), \ + V(64,D9,0F,0A), V(21,A6,5C,68), V(D1,54,5B,9B), V(3A,2E,36,24), \ + V(B1,67,0A,0C), V(0F,E7,57,93), V(D2,96,EE,B4), V(9E,91,9B,1B), \ + V(4F,C5,C0,80), V(A2,20,DC,61), V(69,4B,77,5A), V(16,1A,12,1C), \ + V(0A,BA,93,E2), V(E5,2A,A0,C0), V(43,E0,22,3C), V(1D,17,1B,12), \ + V(0B,0D,09,0E), V(AD,C7,8B,F2), V(B9,A8,B6,2D), V(C8,A9,1E,14), \ + V(85,19,F1,57), V(4C,07,75,AF), V(BB,DD,99,EE), V(FD,60,7F,A3), \ + V(9F,26,01,F7), V(BC,F5,72,5C), V(C5,3B,66,44), V(34,7E,FB,5B), \ + V(76,29,43,8B), V(DC,C6,23,CB), V(68,FC,ED,B6), V(63,F1,E4,B8), \ + V(CA,DC,31,D7), V(10,85,63,42), V(40,22,97,13), V(20,11,C6,84), \ + V(7D,24,4A,85), V(F8,3D,BB,D2), V(11,32,F9,AE), V(6D,A1,29,C7), \ + V(4B,2F,9E,1D), V(F3,30,B2,DC), V(EC,52,86,0D), V(D0,E3,C1,77), \ + V(6C,16,B3,2B), V(99,B9,70,A9), V(FA,48,94,11), V(22,64,E9,47), \ + V(C4,8C,FC,A8), V(1A,3F,F0,A0), V(D8,2C,7D,56), V(EF,90,33,22), \ + V(C7,4E,49,87), V(C1,D1,38,D9), V(FE,A2,CA,8C), V(36,0B,D4,98), \ + V(CF,81,F5,A6), V(28,DE,7A,A5), V(26,8E,B7,DA), V(A4,BF,AD,3F), \ + V(E4,9D,3A,2C), V(0D,92,78,50), V(9B,CC,5F,6A), V(62,46,7E,54), \ + V(C2,13,8D,F6), V(E8,B8,D8,90), V(5E,F7,39,2E), V(F5,AF,C3,82), \ + V(BE,80,5D,9F), V(7C,93,D0,69), V(A9,2D,D5,6F), V(B3,12,25,CF), \ + V(3B,99,AC,C8), V(A7,7D,18,10), V(6E,63,9C,E8), V(7B,BB,3B,DB), \ + V(09,78,26,CD), V(F4,18,59,6E), V(01,B7,9A,EC), V(A8,9A,4F,83), \ + V(65,6E,95,E6), V(7E,E6,FF,AA), V(08,CF,BC,21), V(E6,E8,15,EF), \ + V(D9,9B,E7,BA), V(CE,36,6F,4A), V(D4,09,9F,EA), V(D6,7C,B0,29), \ + V(AF,B2,A4,31), V(31,23,3F,2A), V(30,94,A5,C6), V(C0,66,A2,35), \ + V(37,BC,4E,74), V(A6,CA,82,FC), V(B0,D0,90,E0), V(15,D8,A7,33), \ + V(4A,98,04,F1), V(F7,DA,EC,41), V(0E,50,CD,7F), V(2F,F6,91,17), \ + V(8D,D6,4D,76), V(4D,B0,EF,43), V(54,4D,AA,CC), V(DF,04,96,E4), \ + V(E3,B5,D1,9E), V(1B,88,6A,4C), V(B8,1F,2C,C1), V(7F,51,65,46), \ + V(04,EA,5E,9D), V(5D,35,8C,01), V(73,74,87,FA), V(2E,41,0B,FB), \ + V(5A,1D,67,B3), V(52,D2,DB,92), V(33,56,10,E9), V(13,47,D6,6D), \ + V(8C,61,D7,9A), V(7A,0C,A1,37), V(8E,14,F8,59), V(89,3C,13,EB), \ + V(EE,27,A9,CE), V(35,C9,61,B7), V(ED,E5,1C,E1), V(3C,B1,47,7A), \ + V(59,DF,D2,9C), V(3F,73,F2,55), V(79,CE,14,18), V(BF,37,C7,73), \ + V(EA,CD,F7,53), V(5B,AA,FD,5F), V(14,6F,3D,DF), V(86,DB,44,78), \ + V(81,F3,AF,CA), V(3E,C4,68,B9), V(2C,34,24,38), V(5F,40,A3,C2), \ + V(72,C3,1D,16), V(0C,25,E2,BC), V(8B,49,3C,28), V(41,95,0D,FF), \ + V(71,01,A8,39), V(DE,B3,0C,08), V(9C,E4,B4,D8), V(90,C1,56,64), \ + V(61,84,CB,7B), V(70,B6,32,D5), V(74,5C,6C,48), V(42,57,B8,D0) + +#define V(a,b,c,d) 0x##a##b##c##d +static const uint32_t RT0[256] = { RT }; +#undef V + +#if !defined(MBEDTLS_AES_FEWER_TABLES) + +#define V(a,b,c,d) 0x##b##c##d##a +static const uint32_t RT1[256] = { RT }; +#undef V + +#define V(a,b,c,d) 0x##c##d##a##b +static const uint32_t RT2[256] = { RT }; +#undef V + +#define V(a,b,c,d) 0x##d##a##b##c +static const uint32_t RT3[256] = { RT }; +#undef V + +#endif /* !MBEDTLS_AES_FEWER_TABLES */ + +#undef RT + +/* + * Round constants + */ +static const uint32_t RCON[10] = +{ + 0x00000001, 0x00000002, 0x00000004, 0x00000008, + 0x00000010, 0x00000020, 0x00000040, 0x00000080, + 0x0000001B, 0x00000036 +}; + +#else /* MBEDTLS_AES_ROM_TABLES */ + +/* + * Forward S-box & tables + */ +static unsigned char FSb[256]; +static uint32_t FT0[256]; +#if !defined(MBEDTLS_AES_FEWER_TABLES) +static uint32_t FT1[256]; +static uint32_t FT2[256]; +static uint32_t FT3[256]; +#endif /* !MBEDTLS_AES_FEWER_TABLES */ + +/* + * Reverse S-box & tables + */ +static unsigned char RSb[256]; +static uint32_t RT0[256]; +#if !defined(MBEDTLS_AES_FEWER_TABLES) +static uint32_t RT1[256]; +static uint32_t RT2[256]; +static uint32_t RT3[256]; +#endif /* !MBEDTLS_AES_FEWER_TABLES */ + +/* + * Round constants + */ +static uint32_t RCON[10]; + +/* + * Tables generation code + */ +#define ROTL8(x) ( ( (x) << 8 ) & 0xFFFFFFFF ) | ( (x) >> 24 ) +#define XTIME(x) ( ( (x) << 1 ) ^ ( ( (x) & 0x80 ) ? 0x1B : 0x00 ) ) +#define MUL(x,y) ( ( (x) && (y) ) ? pow[(log[(x)]+log[(y)]) % 255] : 0 ) + +static int aes_init_done = 0; + +static void aes_gen_tables( void ) +{ + int i, x, y, z; + int pow[256]; + int log[256]; + + /* + * compute pow and log tables over GF(2^8) + */ + for( i = 0, x = 1; i < 256; i++ ) + { + pow[i] = x; + log[x] = i; + x = ( x ^ XTIME( x ) ) & 0xFF; + } + + /* + * calculate the round constants + */ + for( i = 0, x = 1; i < 10; i++ ) + { + RCON[i] = (uint32_t) x; + x = XTIME( x ) & 0xFF; + } + + /* + * generate the forward and reverse S-boxes + */ + FSb[0x00] = 0x63; + RSb[0x63] = 0x00; + + for( i = 1; i < 256; i++ ) + { + x = pow[255 - log[i]]; + + y = x; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; + x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; + x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; + x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; + x ^= y ^ 0x63; + + FSb[i] = (unsigned char) x; + RSb[x] = (unsigned char) i; + } + + /* + * generate the forward and reverse tables + */ + for( i = 0; i < 256; i++ ) + { + x = FSb[i]; + y = XTIME( x ) & 0xFF; + z = ( y ^ x ) & 0xFF; + + FT0[i] = ( (uint32_t) y ) ^ + ( (uint32_t) x << 8 ) ^ + ( (uint32_t) x << 16 ) ^ + ( (uint32_t) z << 24 ); + +#if !defined(MBEDTLS_AES_FEWER_TABLES) + FT1[i] = ROTL8( FT0[i] ); + FT2[i] = ROTL8( FT1[i] ); + FT3[i] = ROTL8( FT2[i] ); +#endif /* !MBEDTLS_AES_FEWER_TABLES */ + + x = RSb[i]; + + RT0[i] = ( (uint32_t) MUL( 0x0E, x ) ) ^ + ( (uint32_t) MUL( 0x09, x ) << 8 ) ^ + ( (uint32_t) MUL( 0x0D, x ) << 16 ) ^ + ( (uint32_t) MUL( 0x0B, x ) << 24 ); + +#if !defined(MBEDTLS_AES_FEWER_TABLES) + RT1[i] = ROTL8( RT0[i] ); + RT2[i] = ROTL8( RT1[i] ); + RT3[i] = ROTL8( RT2[i] ); +#endif /* !MBEDTLS_AES_FEWER_TABLES */ + } +} + +#undef ROTL8 + +#endif /* MBEDTLS_AES_ROM_TABLES */ + +#if defined(MBEDTLS_AES_FEWER_TABLES) + +#define ROTL8(x) ( (uint32_t)( ( x ) << 8 ) + (uint32_t)( ( x ) >> 24 ) ) +#define ROTL16(x) ( (uint32_t)( ( x ) << 16 ) + (uint32_t)( ( x ) >> 16 ) ) +#define ROTL24(x) ( (uint32_t)( ( x ) << 24 ) + (uint32_t)( ( x ) >> 8 ) ) + +#define AES_RT0(idx) RT0[idx] +#define AES_RT1(idx) ROTL8( RT0[idx] ) +#define AES_RT2(idx) ROTL16( RT0[idx] ) +#define AES_RT3(idx) ROTL24( RT0[idx] ) + +#define AES_FT0(idx) FT0[idx] +#define AES_FT1(idx) ROTL8( FT0[idx] ) +#define AES_FT2(idx) ROTL16( FT0[idx] ) +#define AES_FT3(idx) ROTL24( FT0[idx] ) + +#else /* MBEDTLS_AES_FEWER_TABLES */ + +#define AES_RT0(idx) RT0[idx] +#define AES_RT1(idx) RT1[idx] +#define AES_RT2(idx) RT2[idx] +#define AES_RT3(idx) RT3[idx] + +#define AES_FT0(idx) FT0[idx] +#define AES_FT1(idx) FT1[idx] +#define AES_FT2(idx) FT2[idx] +#define AES_FT3(idx) FT3[idx] + +#endif /* MBEDTLS_AES_FEWER_TABLES */ + +void mbedtls_aes_init( mbedtls_aes_context *ctx ) +{ + AES_VALIDATE( ctx != NULL ); + + memset( ctx, 0, sizeof( mbedtls_aes_context ) ); +} + +void mbedtls_aes_free( mbedtls_aes_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_aes_context ) ); +} + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +void mbedtls_aes_xts_init( mbedtls_aes_xts_context *ctx ) +{ + AES_VALIDATE( ctx != NULL ); + + mbedtls_aes_init( &ctx->crypt ); + mbedtls_aes_init( &ctx->tweak ); +} + +void mbedtls_aes_xts_free( mbedtls_aes_xts_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_aes_free( &ctx->crypt ); + mbedtls_aes_free( &ctx->tweak ); +} +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +/* + * AES key schedule (encryption) + */ +#if !defined(MBEDTLS_AES_SETKEY_ENC_ALT) +int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits ) +{ + unsigned int i; + uint32_t *RK; + + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( key != NULL ); + + switch( keybits ) + { + case 128: ctx->nr = 10; break; + case 192: ctx->nr = 12; break; + case 256: ctx->nr = 14; break; + default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH ); + } + +#if !defined(MBEDTLS_AES_ROM_TABLES) + if( aes_init_done == 0 ) + { + aes_gen_tables(); + aes_init_done = 1; + } +#endif + +#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_PADLOCK_ALIGN16) + if( aes_padlock_ace == -1 ) + aes_padlock_ace = mbedtls_padlock_has_support( MBEDTLS_PADLOCK_ACE ); + + if( aes_padlock_ace ) + ctx->rk = RK = MBEDTLS_PADLOCK_ALIGN16( ctx->buf ); + else +#endif + ctx->rk = RK = ctx->buf; + +#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) + if( mbedtls_aesni_has_support( MBEDTLS_AESNI_AES ) ) + return( mbedtls_aesni_setkey_enc( (unsigned char *) ctx->rk, key, keybits ) ); +#endif + + for( i = 0; i < ( keybits >> 5 ); i++ ) + { + GET_UINT32_LE( RK[i], key, i << 2 ); + } + + switch( ctx->nr ) + { + case 10: + + for( i = 0; i < 10; i++, RK += 4 ) + { + RK[4] = RK[0] ^ RCON[i] ^ + ( (uint32_t) FSb[ ( RK[3] >> 8 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( RK[3] >> 16 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( RK[3] >> 24 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( RK[3] ) & 0xFF ] << 24 ); + + RK[5] = RK[1] ^ RK[4]; + RK[6] = RK[2] ^ RK[5]; + RK[7] = RK[3] ^ RK[6]; + } + break; + + case 12: + + for( i = 0; i < 8; i++, RK += 6 ) + { + RK[6] = RK[0] ^ RCON[i] ^ + ( (uint32_t) FSb[ ( RK[5] >> 8 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( RK[5] >> 16 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( RK[5] >> 24 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( RK[5] ) & 0xFF ] << 24 ); + + RK[7] = RK[1] ^ RK[6]; + RK[8] = RK[2] ^ RK[7]; + RK[9] = RK[3] ^ RK[8]; + RK[10] = RK[4] ^ RK[9]; + RK[11] = RK[5] ^ RK[10]; + } + break; + + case 14: + + for( i = 0; i < 7; i++, RK += 8 ) + { + RK[8] = RK[0] ^ RCON[i] ^ + ( (uint32_t) FSb[ ( RK[7] >> 8 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( RK[7] >> 16 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( RK[7] >> 24 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( RK[7] ) & 0xFF ] << 24 ); + + RK[9] = RK[1] ^ RK[8]; + RK[10] = RK[2] ^ RK[9]; + RK[11] = RK[3] ^ RK[10]; + + RK[12] = RK[4] ^ + ( (uint32_t) FSb[ ( RK[11] ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( RK[11] >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( RK[11] >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( RK[11] >> 24 ) & 0xFF ] << 24 ); + + RK[13] = RK[5] ^ RK[12]; + RK[14] = RK[6] ^ RK[13]; + RK[15] = RK[7] ^ RK[14]; + } + break; + } + + return( 0 ); +} +#endif /* !MBEDTLS_AES_SETKEY_ENC_ALT */ + +/* + * AES key schedule (decryption) + */ +#if !defined(MBEDTLS_AES_SETKEY_DEC_ALT) +int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits ) +{ + int i, j, ret; + mbedtls_aes_context cty; + uint32_t *RK; + uint32_t *SK; + + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( key != NULL ); + + mbedtls_aes_init( &cty ); + +#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_PADLOCK_ALIGN16) + if( aes_padlock_ace == -1 ) + aes_padlock_ace = mbedtls_padlock_has_support( MBEDTLS_PADLOCK_ACE ); + + if( aes_padlock_ace ) + ctx->rk = RK = MBEDTLS_PADLOCK_ALIGN16( ctx->buf ); + else +#endif + ctx->rk = RK = ctx->buf; + + /* Also checks keybits */ + if( ( ret = mbedtls_aes_setkey_enc( &cty, key, keybits ) ) != 0 ) + goto exit; + + ctx->nr = cty.nr; + +#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) + if( mbedtls_aesni_has_support( MBEDTLS_AESNI_AES ) ) + { + mbedtls_aesni_inverse_key( (unsigned char *) ctx->rk, + (const unsigned char *) cty.rk, ctx->nr ); + goto exit; + } +#endif + + SK = cty.rk + cty.nr * 4; + + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + + for( i = ctx->nr - 1, SK -= 8; i > 0; i--, SK -= 8 ) + { + for( j = 0; j < 4; j++, SK++ ) + { + *RK++ = AES_RT0( FSb[ ( *SK ) & 0xFF ] ) ^ + AES_RT1( FSb[ ( *SK >> 8 ) & 0xFF ] ) ^ + AES_RT2( FSb[ ( *SK >> 16 ) & 0xFF ] ) ^ + AES_RT3( FSb[ ( *SK >> 24 ) & 0xFF ] ); + } + } + + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + +exit: + mbedtls_aes_free( &cty ); + + return( ret ); +} +#endif /* !MBEDTLS_AES_SETKEY_DEC_ALT */ + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +static int mbedtls_aes_xts_decode_keys( const unsigned char *key, + unsigned int keybits, + const unsigned char **key1, + unsigned int *key1bits, + const unsigned char **key2, + unsigned int *key2bits ) +{ + const unsigned int half_keybits = keybits / 2; + const unsigned int half_keybytes = half_keybits / 8; + + switch( keybits ) + { + case 256: break; + case 512: break; + default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH ); + } + + *key1bits = half_keybits; + *key2bits = half_keybits; + *key1 = &key[0]; + *key2 = &key[half_keybytes]; + + return 0; +} + +int mbedtls_aes_xts_setkey_enc( mbedtls_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const unsigned char *key1, *key2; + unsigned int key1bits, key2bits; + + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( key != NULL ); + + ret = mbedtls_aes_xts_decode_keys( key, keybits, &key1, &key1bits, + &key2, &key2bits ); + if( ret != 0 ) + return( ret ); + + /* Set the tweak key. Always set tweak key for the encryption mode. */ + ret = mbedtls_aes_setkey_enc( &ctx->tweak, key2, key2bits ); + if( ret != 0 ) + return( ret ); + + /* Set crypt key for encryption. */ + return mbedtls_aes_setkey_enc( &ctx->crypt, key1, key1bits ); +} + +int mbedtls_aes_xts_setkey_dec( mbedtls_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const unsigned char *key1, *key2; + unsigned int key1bits, key2bits; + + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( key != NULL ); + + ret = mbedtls_aes_xts_decode_keys( key, keybits, &key1, &key1bits, + &key2, &key2bits ); + if( ret != 0 ) + return( ret ); + + /* Set the tweak key. Always set tweak key for encryption. */ + ret = mbedtls_aes_setkey_enc( &ctx->tweak, key2, key2bits ); + if( ret != 0 ) + return( ret ); + + /* Set crypt key for decryption. */ + return mbedtls_aes_setkey_dec( &ctx->crypt, key1, key1bits ); +} +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ + do \ + { \ + (X0) = *RK++ ^ AES_FT0( ( (Y0) ) & 0xFF ) ^ \ + AES_FT1( ( (Y1) >> 8 ) & 0xFF ) ^ \ + AES_FT2( ( (Y2) >> 16 ) & 0xFF ) ^ \ + AES_FT3( ( (Y3) >> 24 ) & 0xFF ); \ + \ + (X1) = *RK++ ^ AES_FT0( ( (Y1) ) & 0xFF ) ^ \ + AES_FT1( ( (Y2) >> 8 ) & 0xFF ) ^ \ + AES_FT2( ( (Y3) >> 16 ) & 0xFF ) ^ \ + AES_FT3( ( (Y0) >> 24 ) & 0xFF ); \ + \ + (X2) = *RK++ ^ AES_FT0( ( (Y2) ) & 0xFF ) ^ \ + AES_FT1( ( (Y3) >> 8 ) & 0xFF ) ^ \ + AES_FT2( ( (Y0) >> 16 ) & 0xFF ) ^ \ + AES_FT3( ( (Y1) >> 24 ) & 0xFF ); \ + \ + (X3) = *RK++ ^ AES_FT0( ( (Y3) ) & 0xFF ) ^ \ + AES_FT1( ( (Y0) >> 8 ) & 0xFF ) ^ \ + AES_FT2( ( (Y1) >> 16 ) & 0xFF ) ^ \ + AES_FT3( ( (Y2) >> 24 ) & 0xFF ); \ + } while( 0 ) + +#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ + do \ + { \ + (X0) = *RK++ ^ AES_RT0( ( (Y0) ) & 0xFF ) ^ \ + AES_RT1( ( (Y3) >> 8 ) & 0xFF ) ^ \ + AES_RT2( ( (Y2) >> 16 ) & 0xFF ) ^ \ + AES_RT3( ( (Y1) >> 24 ) & 0xFF ); \ + \ + (X1) = *RK++ ^ AES_RT0( ( (Y1) ) & 0xFF ) ^ \ + AES_RT1( ( (Y0) >> 8 ) & 0xFF ) ^ \ + AES_RT2( ( (Y3) >> 16 ) & 0xFF ) ^ \ + AES_RT3( ( (Y2) >> 24 ) & 0xFF ); \ + \ + (X2) = *RK++ ^ AES_RT0( ( (Y2) ) & 0xFF ) ^ \ + AES_RT1( ( (Y1) >> 8 ) & 0xFF ) ^ \ + AES_RT2( ( (Y0) >> 16 ) & 0xFF ) ^ \ + AES_RT3( ( (Y3) >> 24 ) & 0xFF ); \ + \ + (X3) = *RK++ ^ AES_RT0( ( (Y3) ) & 0xFF ) ^ \ + AES_RT1( ( (Y2) >> 8 ) & 0xFF ) ^ \ + AES_RT2( ( (Y1) >> 16 ) & 0xFF ) ^ \ + AES_RT3( ( (Y0) >> 24 ) & 0xFF ); \ + } while( 0 ) + +/* + * AES-ECB block encryption + */ +#if !defined(MBEDTLS_AES_ENCRYPT_ALT) +int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) +{ + int i; + uint32_t *RK = ctx->rk; + struct + { + uint32_t X[4]; + uint32_t Y[4]; + } t; + + GET_UINT32_LE( t.X[0], input, 0 ); t.X[0] ^= *RK++; + GET_UINT32_LE( t.X[1], input, 4 ); t.X[1] ^= *RK++; + GET_UINT32_LE( t.X[2], input, 8 ); t.X[2] ^= *RK++; + GET_UINT32_LE( t.X[3], input, 12 ); t.X[3] ^= *RK++; + + for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- ) + { + AES_FROUND( t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3] ); + AES_FROUND( t.X[0], t.X[1], t.X[2], t.X[3], t.Y[0], t.Y[1], t.Y[2], t.Y[3] ); + } + + AES_FROUND( t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3] ); + + t.X[0] = *RK++ ^ \ + ( (uint32_t) FSb[ ( t.Y[0] ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( t.Y[1] >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( t.Y[2] >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( t.Y[3] >> 24 ) & 0xFF ] << 24 ); + + t.X[1] = *RK++ ^ \ + ( (uint32_t) FSb[ ( t.Y[1] ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( t.Y[2] >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( t.Y[3] >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( t.Y[0] >> 24 ) & 0xFF ] << 24 ); + + t.X[2] = *RK++ ^ \ + ( (uint32_t) FSb[ ( t.Y[2] ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( t.Y[3] >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( t.Y[0] >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( t.Y[1] >> 24 ) & 0xFF ] << 24 ); + + t.X[3] = *RK++ ^ \ + ( (uint32_t) FSb[ ( t.Y[3] ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( t.Y[0] >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( t.Y[1] >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( t.Y[2] >> 24 ) & 0xFF ] << 24 ); + + PUT_UINT32_LE( t.X[0], output, 0 ); + PUT_UINT32_LE( t.X[1], output, 4 ); + PUT_UINT32_LE( t.X[2], output, 8 ); + PUT_UINT32_LE( t.X[3], output, 12 ); + + mbedtls_platform_zeroize( &t, sizeof( t ) ); + + return( 0 ); +} +#endif /* !MBEDTLS_AES_ENCRYPT_ALT */ + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_aes_encrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) +{ + mbedtls_internal_aes_encrypt( ctx, input, output ); +} +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/* + * AES-ECB block decryption + */ +#if !defined(MBEDTLS_AES_DECRYPT_ALT) +int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) +{ + int i; + uint32_t *RK = ctx->rk; + struct + { + uint32_t X[4]; + uint32_t Y[4]; + } t; + + GET_UINT32_LE( t.X[0], input, 0 ); t.X[0] ^= *RK++; + GET_UINT32_LE( t.X[1], input, 4 ); t.X[1] ^= *RK++; + GET_UINT32_LE( t.X[2], input, 8 ); t.X[2] ^= *RK++; + GET_UINT32_LE( t.X[3], input, 12 ); t.X[3] ^= *RK++; + + for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- ) + { + AES_RROUND( t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3] ); + AES_RROUND( t.X[0], t.X[1], t.X[2], t.X[3], t.Y[0], t.Y[1], t.Y[2], t.Y[3] ); + } + + AES_RROUND( t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3] ); + + t.X[0] = *RK++ ^ \ + ( (uint32_t) RSb[ ( t.Y[0] ) & 0xFF ] ) ^ + ( (uint32_t) RSb[ ( t.Y[3] >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) RSb[ ( t.Y[2] >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) RSb[ ( t.Y[1] >> 24 ) & 0xFF ] << 24 ); + + t.X[1] = *RK++ ^ \ + ( (uint32_t) RSb[ ( t.Y[1] ) & 0xFF ] ) ^ + ( (uint32_t) RSb[ ( t.Y[0] >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) RSb[ ( t.Y[3] >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) RSb[ ( t.Y[2] >> 24 ) & 0xFF ] << 24 ); + + t.X[2] = *RK++ ^ \ + ( (uint32_t) RSb[ ( t.Y[2] ) & 0xFF ] ) ^ + ( (uint32_t) RSb[ ( t.Y[1] >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) RSb[ ( t.Y[0] >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) RSb[ ( t.Y[3] >> 24 ) & 0xFF ] << 24 ); + + t.X[3] = *RK++ ^ \ + ( (uint32_t) RSb[ ( t.Y[3] ) & 0xFF ] ) ^ + ( (uint32_t) RSb[ ( t.Y[2] >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) RSb[ ( t.Y[1] >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) RSb[ ( t.Y[0] >> 24 ) & 0xFF ] << 24 ); + + PUT_UINT32_LE( t.X[0], output, 0 ); + PUT_UINT32_LE( t.X[1], output, 4 ); + PUT_UINT32_LE( t.X[2], output, 8 ); + PUT_UINT32_LE( t.X[3], output, 12 ); + + mbedtls_platform_zeroize( &t, sizeof( t ) ); + + return( 0 ); +} +#endif /* !MBEDTLS_AES_DECRYPT_ALT */ + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_aes_decrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) +{ + mbedtls_internal_aes_decrypt( ctx, input, output ); +} +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/* + * AES-ECB block encryption/decryption + */ +int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ) +{ + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( input != NULL ); + AES_VALIDATE_RET( output != NULL ); + AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT || + mode == MBEDTLS_AES_DECRYPT ); + +#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) + if( mbedtls_aesni_has_support( MBEDTLS_AESNI_AES ) ) + return( mbedtls_aesni_crypt_ecb( ctx, mode, input, output ) ); +#endif + +#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86) + if( aes_padlock_ace ) + { + if( mbedtls_padlock_xcryptecb( ctx, mode, input, output ) == 0 ) + return( 0 ); + + // If padlock data misaligned, we just fall back to + // unaccelerated mode + // + } +#endif + + if( mode == MBEDTLS_AES_ENCRYPT ) + return( mbedtls_internal_aes_encrypt( ctx, input, output ) ); + else + return( mbedtls_internal_aes_decrypt( ctx, input, output ) ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/* + * AES-CBC buffer encryption/decryption + */ +int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int i; + unsigned char temp[16]; + + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT || + mode == MBEDTLS_AES_DECRYPT ); + AES_VALIDATE_RET( iv != NULL ); + AES_VALIDATE_RET( input != NULL ); + AES_VALIDATE_RET( output != NULL ); + + if( length % 16 ) + return( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH ); + +#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86) + if( aes_padlock_ace ) + { + if( mbedtls_padlock_xcryptcbc( ctx, mode, length, iv, input, output ) == 0 ) + return( 0 ); + + // If padlock data misaligned, we just fall back to + // unaccelerated mode + // + } +#endif + + if( mode == MBEDTLS_AES_DECRYPT ) + { + while( length > 0 ) + { + memcpy( temp, input, 16 ); + mbedtls_aes_crypt_ecb( ctx, mode, input, output ); + + for( i = 0; i < 16; i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, 16 ); + + input += 16; + output += 16; + length -= 16; + } + } + else + { + while( length > 0 ) + { + for( i = 0; i < 16; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + mbedtls_aes_crypt_ecb( ctx, mode, output, output ); + memcpy( iv, output, 16 ); + + input += 16; + output += 16; + length -= 16; + } + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_XTS) + +/* Endianess with 64 bits values */ +#ifndef GET_UINT64_LE +#define GET_UINT64_LE(n,b,i) \ +{ \ + (n) = ( (uint64_t) (b)[(i) + 7] << 56 ) \ + | ( (uint64_t) (b)[(i) + 6] << 48 ) \ + | ( (uint64_t) (b)[(i) + 5] << 40 ) \ + | ( (uint64_t) (b)[(i) + 4] << 32 ) \ + | ( (uint64_t) (b)[(i) + 3] << 24 ) \ + | ( (uint64_t) (b)[(i) + 2] << 16 ) \ + | ( (uint64_t) (b)[(i) + 1] << 8 ) \ + | ( (uint64_t) (b)[(i) ] ); \ +} +#endif + +#ifndef PUT_UINT64_LE +#define PUT_UINT64_LE(n,b,i) \ +{ \ + (b)[(i) + 7] = (unsigned char) ( (n) >> 56 ); \ + (b)[(i) + 6] = (unsigned char) ( (n) >> 48 ); \ + (b)[(i) + 5] = (unsigned char) ( (n) >> 40 ); \ + (b)[(i) + 4] = (unsigned char) ( (n) >> 32 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) ] = (unsigned char) ( (n) ); \ +} +#endif + +typedef unsigned char mbedtls_be128[16]; + +/* + * GF(2^128) multiplication function + * + * This function multiplies a field element by x in the polynomial field + * representation. It uses 64-bit word operations to gain speed but compensates + * for machine endianess and hence works correctly on both big and little + * endian machines. + */ +static void mbedtls_gf128mul_x_ble( unsigned char r[16], + const unsigned char x[16] ) +{ + uint64_t a, b, ra, rb; + + GET_UINT64_LE( a, x, 0 ); + GET_UINT64_LE( b, x, 8 ); + + ra = ( a << 1 ) ^ 0x0087 >> ( 8 - ( ( b >> 63 ) << 3 ) ); + rb = ( a >> 63 ) | ( b << 1 ); + + PUT_UINT64_LE( ra, r, 0 ); + PUT_UINT64_LE( rb, r, 8 ); +} + +/* + * AES-XTS buffer encryption/decryption + */ +int mbedtls_aes_crypt_xts( mbedtls_aes_xts_context *ctx, + int mode, + size_t length, + const unsigned char data_unit[16], + const unsigned char *input, + unsigned char *output ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t blocks = length / 16; + size_t leftover = length % 16; + unsigned char tweak[16]; + unsigned char prev_tweak[16]; + unsigned char tmp[16]; + + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT || + mode == MBEDTLS_AES_DECRYPT ); + AES_VALIDATE_RET( data_unit != NULL ); + AES_VALIDATE_RET( input != NULL ); + AES_VALIDATE_RET( output != NULL ); + + /* Data units must be at least 16 bytes long. */ + if( length < 16 ) + return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH; + + /* NIST SP 800-38E disallows data units larger than 2**20 blocks. */ + if( length > ( 1 << 20 ) * 16 ) + return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH; + + /* Compute the tweak. */ + ret = mbedtls_aes_crypt_ecb( &ctx->tweak, MBEDTLS_AES_ENCRYPT, + data_unit, tweak ); + if( ret != 0 ) + return( ret ); + + while( blocks-- ) + { + size_t i; + + if( leftover && ( mode == MBEDTLS_AES_DECRYPT ) && blocks == 0 ) + { + /* We are on the last block in a decrypt operation that has + * leftover bytes, so we need to use the next tweak for this block, + * and this tweak for the lefover bytes. Save the current tweak for + * the leftovers and then update the current tweak for use on this, + * the last full block. */ + memcpy( prev_tweak, tweak, sizeof( tweak ) ); + mbedtls_gf128mul_x_ble( tweak, tweak ); + } + + for( i = 0; i < 16; i++ ) + tmp[i] = input[i] ^ tweak[i]; + + ret = mbedtls_aes_crypt_ecb( &ctx->crypt, mode, tmp, tmp ); + if( ret != 0 ) + return( ret ); + + for( i = 0; i < 16; i++ ) + output[i] = tmp[i] ^ tweak[i]; + + /* Update the tweak for the next block. */ + mbedtls_gf128mul_x_ble( tweak, tweak ); + + output += 16; + input += 16; + } + + if( leftover ) + { + /* If we are on the leftover bytes in a decrypt operation, we need to + * use the previous tweak for these bytes (as saved in prev_tweak). */ + unsigned char *t = mode == MBEDTLS_AES_DECRYPT ? prev_tweak : tweak; + + /* We are now on the final part of the data unit, which doesn't divide + * evenly by 16. It's time for ciphertext stealing. */ + size_t i; + unsigned char *prev_output = output - 16; + + /* Copy ciphertext bytes from the previous block to our output for each + * byte of cyphertext we won't steal. At the same time, copy the + * remainder of the input for this final round (since the loop bounds + * are the same). */ + for( i = 0; i < leftover; i++ ) + { + output[i] = prev_output[i]; + tmp[i] = input[i] ^ t[i]; + } + + /* Copy ciphertext bytes from the previous block for input in this + * round. */ + for( ; i < 16; i++ ) + tmp[i] = prev_output[i] ^ t[i]; + + ret = mbedtls_aes_crypt_ecb( &ctx->crypt, mode, tmp, tmp ); + if( ret != 0 ) + return ret; + + /* Write the result back to the previous block, overriding the previous + * output we copied. */ + for( i = 0; i < 16; i++ ) + prev_output[i] = tmp[i] ^ t[i]; + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/* + * AES-CFB128 buffer encryption/decryption + */ +int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int c; + size_t n; + + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT || + mode == MBEDTLS_AES_DECRYPT ); + AES_VALIDATE_RET( iv_off != NULL ); + AES_VALIDATE_RET( iv != NULL ); + AES_VALIDATE_RET( input != NULL ); + AES_VALIDATE_RET( output != NULL ); + + n = *iv_off; + + if( n > 15 ) + return( MBEDTLS_ERR_AES_BAD_INPUT_DATA ); + + if( mode == MBEDTLS_AES_DECRYPT ) + { + while( length-- ) + { + if( n == 0 ) + mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv ); + + c = *input++; + *output++ = (unsigned char)( c ^ iv[n] ); + iv[n] = (unsigned char) c; + + n = ( n + 1 ) & 0x0F; + } + } + else + { + while( length-- ) + { + if( n == 0 ) + mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv ); + + iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); + + n = ( n + 1 ) & 0x0F; + } + } + + *iv_off = n; + + return( 0 ); +} + +/* + * AES-CFB8 buffer encryption/decryption + */ +int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + unsigned char c; + unsigned char ov[17]; + + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT || + mode == MBEDTLS_AES_DECRYPT ); + AES_VALIDATE_RET( iv != NULL ); + AES_VALIDATE_RET( input != NULL ); + AES_VALIDATE_RET( output != NULL ); + while( length-- ) + { + memcpy( ov, iv, 16 ); + mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv ); + + if( mode == MBEDTLS_AES_DECRYPT ) + ov[16] = *input; + + c = *output++ = (unsigned char)( iv[0] ^ *input++ ); + + if( mode == MBEDTLS_AES_ENCRYPT ) + ov[16] = c; + + memcpy( iv, ov + 1, 16 ); + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_OFB) +/* + * AES-OFB (Output Feedback Mode) buffer encryption/decryption + */ +int mbedtls_aes_crypt_ofb( mbedtls_aes_context *ctx, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int ret = 0; + size_t n; + + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( iv_off != NULL ); + AES_VALIDATE_RET( iv != NULL ); + AES_VALIDATE_RET( input != NULL ); + AES_VALIDATE_RET( output != NULL ); + + n = *iv_off; + + if( n > 15 ) + return( MBEDTLS_ERR_AES_BAD_INPUT_DATA ); + + while( length-- ) + { + if( n == 0 ) + { + ret = mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv ); + if( ret != 0 ) + goto exit; + } + *output++ = *input++ ^ iv[n]; + + n = ( n + 1 ) & 0x0F; + } + + *iv_off = n; + +exit: + return( ret ); +} +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/* + * AES-CTR buffer encryption/decryption + */ +int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output ) +{ + int c, i; + size_t n; + + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( nc_off != NULL ); + AES_VALIDATE_RET( nonce_counter != NULL ); + AES_VALIDATE_RET( stream_block != NULL ); + AES_VALIDATE_RET( input != NULL ); + AES_VALIDATE_RET( output != NULL ); + + n = *nc_off; + + if ( n > 0x0F ) + return( MBEDTLS_ERR_AES_BAD_INPUT_DATA ); + + while( length-- ) + { + if( n == 0 ) { + mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, nonce_counter, stream_block ); + + for( i = 16; i > 0; i-- ) + if( ++nonce_counter[i - 1] != 0 ) + break; + } + c = *input++; + *output++ = (unsigned char)( c ^ stream_block[n] ); + + n = ( n + 1 ) & 0x0F; + } + + *nc_off = n; + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#endif /* !MBEDTLS_AES_ALT */ + +#if defined(MBEDTLS_SELF_TEST) +/* + * AES test vectors from: + * + * http://csrc.nist.gov/archive/aes/rijndael/rijndael-vals.zip + */ +static const unsigned char aes_test_ecb_dec[3][16] = +{ + { 0x44, 0x41, 0x6A, 0xC2, 0xD1, 0xF5, 0x3C, 0x58, + 0x33, 0x03, 0x91, 0x7E, 0x6B, 0xE9, 0xEB, 0xE0 }, + { 0x48, 0xE3, 0x1E, 0x9E, 0x25, 0x67, 0x18, 0xF2, + 0x92, 0x29, 0x31, 0x9C, 0x19, 0xF1, 0x5B, 0xA4 }, + { 0x05, 0x8C, 0xCF, 0xFD, 0xBB, 0xCB, 0x38, 0x2D, + 0x1F, 0x6F, 0x56, 0x58, 0x5D, 0x8A, 0x4A, 0xDE } +}; + +static const unsigned char aes_test_ecb_enc[3][16] = +{ + { 0xC3, 0x4C, 0x05, 0x2C, 0xC0, 0xDA, 0x8D, 0x73, + 0x45, 0x1A, 0xFE, 0x5F, 0x03, 0xBE, 0x29, 0x7F }, + { 0xF3, 0xF6, 0x75, 0x2A, 0xE8, 0xD7, 0x83, 0x11, + 0x38, 0xF0, 0x41, 0x56, 0x06, 0x31, 0xB1, 0x14 }, + { 0x8B, 0x79, 0xEE, 0xCC, 0x93, 0xA0, 0xEE, 0x5D, + 0xFF, 0x30, 0xB4, 0xEA, 0x21, 0x63, 0x6D, 0xA4 } +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const unsigned char aes_test_cbc_dec[3][16] = +{ + { 0xFA, 0xCA, 0x37, 0xE0, 0xB0, 0xC8, 0x53, 0x73, + 0xDF, 0x70, 0x6E, 0x73, 0xF7, 0xC9, 0xAF, 0x86 }, + { 0x5D, 0xF6, 0x78, 0xDD, 0x17, 0xBA, 0x4E, 0x75, + 0xB6, 0x17, 0x68, 0xC6, 0xAD, 0xEF, 0x7C, 0x7B }, + { 0x48, 0x04, 0xE1, 0x81, 0x8F, 0xE6, 0x29, 0x75, + 0x19, 0xA3, 0xE8, 0x8C, 0x57, 0x31, 0x04, 0x13 } +}; + +static const unsigned char aes_test_cbc_enc[3][16] = +{ + { 0x8A, 0x05, 0xFC, 0x5E, 0x09, 0x5A, 0xF4, 0x84, + 0x8A, 0x08, 0xD3, 0x28, 0xD3, 0x68, 0x8E, 0x3D }, + { 0x7B, 0xD9, 0x66, 0xD5, 0x3A, 0xD8, 0xC1, 0xBB, + 0x85, 0xD2, 0xAD, 0xFA, 0xE8, 0x7B, 0xB1, 0x04 }, + { 0xFE, 0x3C, 0x53, 0x65, 0x3E, 0x2F, 0x45, 0xB5, + 0x6F, 0xCD, 0x88, 0xB2, 0xCC, 0x89, 0x8F, 0xF0 } +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/* + * AES-CFB128 test vectors from: + * + * http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf + */ +static const unsigned char aes_test_cfb128_key[3][32] = +{ + { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, + 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }, + { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, + 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, + 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B }, + { 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 } +}; + +static const unsigned char aes_test_cfb128_iv[16] = +{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F +}; + +static const unsigned char aes_test_cfb128_pt[64] = +{ + 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 +}; + +static const unsigned char aes_test_cfb128_ct[3][64] = +{ + { 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20, + 0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A, + 0xC8, 0xA6, 0x45, 0x37, 0xA0, 0xB3, 0xA9, 0x3F, + 0xCD, 0xE3, 0xCD, 0xAD, 0x9F, 0x1C, 0xE5, 0x8B, + 0x26, 0x75, 0x1F, 0x67, 0xA3, 0xCB, 0xB1, 0x40, + 0xB1, 0x80, 0x8C, 0xF1, 0x87, 0xA4, 0xF4, 0xDF, + 0xC0, 0x4B, 0x05, 0x35, 0x7C, 0x5D, 0x1C, 0x0E, + 0xEA, 0xC4, 0xC6, 0x6F, 0x9F, 0xF7, 0xF2, 0xE6 }, + { 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB, + 0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74, + 0x67, 0xCE, 0x7F, 0x7F, 0x81, 0x17, 0x36, 0x21, + 0x96, 0x1A, 0x2B, 0x70, 0x17, 0x1D, 0x3D, 0x7A, + 0x2E, 0x1E, 0x8A, 0x1D, 0xD5, 0x9B, 0x88, 0xB1, + 0xC8, 0xE6, 0x0F, 0xED, 0x1E, 0xFA, 0xC4, 0xC9, + 0xC0, 0x5F, 0x9F, 0x9C, 0xA9, 0x83, 0x4F, 0xA0, + 0x42, 0xAE, 0x8F, 0xBA, 0x58, 0x4B, 0x09, 0xFF }, + { 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B, + 0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60, + 0x39, 0xFF, 0xED, 0x14, 0x3B, 0x28, 0xB1, 0xC8, + 0x32, 0x11, 0x3C, 0x63, 0x31, 0xE5, 0x40, 0x7B, + 0xDF, 0x10, 0x13, 0x24, 0x15, 0xE5, 0x4B, 0x92, + 0xA1, 0x3E, 0xD0, 0xA8, 0x26, 0x7A, 0xE2, 0xF9, + 0x75, 0xA3, 0x85, 0x74, 0x1A, 0xB9, 0xCE, 0xF8, + 0x20, 0x31, 0x62, 0x3D, 0x55, 0xB1, 0xE4, 0x71 } +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_OFB) +/* + * AES-OFB test vectors from: + * + * https://csrc.nist.gov/publications/detail/sp/800-38a/final + */ +static const unsigned char aes_test_ofb_key[3][32] = +{ + { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, + 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }, + { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, + 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, + 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B }, + { 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 } +}; + +static const unsigned char aes_test_ofb_iv[16] = +{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F +}; + +static const unsigned char aes_test_ofb_pt[64] = +{ + 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 +}; + +static const unsigned char aes_test_ofb_ct[3][64] = +{ + { 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20, + 0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A, + 0x77, 0x89, 0x50, 0x8d, 0x16, 0x91, 0x8f, 0x03, + 0xf5, 0x3c, 0x52, 0xda, 0xc5, 0x4e, 0xd8, 0x25, + 0x97, 0x40, 0x05, 0x1e, 0x9c, 0x5f, 0xec, 0xf6, + 0x43, 0x44, 0xf7, 0xa8, 0x22, 0x60, 0xed, 0xcc, + 0x30, 0x4c, 0x65, 0x28, 0xf6, 0x59, 0xc7, 0x78, + 0x66, 0xa5, 0x10, 0xd9, 0xc1, 0xd6, 0xae, 0x5e }, + { 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB, + 0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74, + 0xfc, 0xc2, 0x8b, 0x8d, 0x4c, 0x63, 0x83, 0x7c, + 0x09, 0xe8, 0x17, 0x00, 0xc1, 0x10, 0x04, 0x01, + 0x8d, 0x9a, 0x9a, 0xea, 0xc0, 0xf6, 0x59, 0x6f, + 0x55, 0x9c, 0x6d, 0x4d, 0xaf, 0x59, 0xa5, 0xf2, + 0x6d, 0x9f, 0x20, 0x08, 0x57, 0xca, 0x6c, 0x3e, + 0x9c, 0xac, 0x52, 0x4b, 0xd9, 0xac, 0xc9, 0x2a }, + { 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B, + 0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60, + 0x4f, 0xeb, 0xdc, 0x67, 0x40, 0xd2, 0x0b, 0x3a, + 0xc8, 0x8f, 0x6a, 0xd8, 0x2a, 0x4f, 0xb0, 0x8d, + 0x71, 0xab, 0x47, 0xa0, 0x86, 0xe8, 0x6e, 0xed, + 0xf3, 0x9d, 0x1c, 0x5b, 0xba, 0x97, 0xc4, 0x08, + 0x01, 0x26, 0x14, 0x1d, 0x67, 0xf3, 0x7b, 0xe8, + 0x53, 0x8f, 0x5a, 0x8b, 0xe7, 0x40, 0xe4, 0x84 } +}; +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/* + * AES-CTR test vectors from: + * + * http://www.faqs.org/rfcs/rfc3686.html + */ + +static const unsigned char aes_test_ctr_key[3][16] = +{ + { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC, + 0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E }, + { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7, + 0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 }, + { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8, + 0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC } +}; + +static const unsigned char aes_test_ctr_nonce_counter[3][16] = +{ + { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59, + 0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 }, + { 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F, + 0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 } +}; + +static const unsigned char aes_test_ctr_pt[3][48] = +{ + { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62, + 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 }, + + { 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, 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 } +}; + +static const unsigned char aes_test_ctr_ct[3][48] = +{ + { 0xE4, 0x09, 0x5D, 0x4F, 0xB7, 0xA7, 0xB3, 0x79, + 0x2D, 0x61, 0x75, 0xA3, 0x26, 0x13, 0x11, 0xB8 }, + { 0x51, 0x04, 0xA1, 0x06, 0x16, 0x8A, 0x72, 0xD9, + 0x79, 0x0D, 0x41, 0xEE, 0x8E, 0xDA, 0xD3, 0x88, + 0xEB, 0x2E, 0x1E, 0xFC, 0x46, 0xDA, 0x57, 0xC8, + 0xFC, 0xE6, 0x30, 0xDF, 0x91, 0x41, 0xBE, 0x28 }, + { 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 } +}; + +static const int aes_test_ctr_len[3] = + { 16, 32, 36 }; +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +/* + * AES-XTS test vectors from: + * + * IEEE P1619/D16 Annex B + * https://web.archive.org/web/20150629024421/http://grouper.ieee.org/groups/1619/email/pdf00086.pdf + * (Archived from original at http://grouper.ieee.org/groups/1619/email/pdf00086.pdf) + */ +static const unsigned char aes_test_xts_key[][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 }, + { 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 }, + { 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, + 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 }, +}; + +static const unsigned char aes_test_xts_pt32[][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 }, + { 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 }, + { 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 }, +}; + +static const unsigned char aes_test_xts_ct32[][32] = +{ + { 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 }, + { 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 }, + { 0xaf, 0x85, 0x33, 0x6b, 0x59, 0x7a, 0xfc, 0x1a, + 0x90, 0x0b, 0x2e, 0xb2, 0x1e, 0xc9, 0x49, 0xd2, + 0x92, 0xdf, 0x4c, 0x04, 0x7e, 0x0b, 0x21, 0x53, + 0x21, 0x86, 0xa5, 0x97, 0x1a, 0x22, 0x7a, 0x89 }, +}; + +static const unsigned char aes_test_xts_data_unit[][16] = +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, +}; + +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +/* + * Checkup routine + */ +int mbedtls_aes_self_test( int verbose ) +{ + int ret = 0, i, j, u, mode; + unsigned int keybits; + unsigned char key[32]; + unsigned char buf[64]; + const unsigned char *aes_tests; +#if defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB) + unsigned char iv[16]; +#endif +#if defined(MBEDTLS_CIPHER_MODE_CBC) + unsigned char prv[16]; +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_CFB) || \ + defined(MBEDTLS_CIPHER_MODE_OFB) + size_t offset; +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_XTS) + int len; +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + unsigned char nonce_counter[16]; + unsigned char stream_block[16]; +#endif + mbedtls_aes_context ctx; + + memset( key, 0, 32 ); + mbedtls_aes_init( &ctx ); + + /* + * ECB mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + keybits = 128 + u * 64; + mode = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " AES-ECB-%3u (%s): ", keybits, + ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + + memset( buf, 0, 16 ); + + if( mode == MBEDTLS_AES_DECRYPT ) + { + ret = mbedtls_aes_setkey_dec( &ctx, key, keybits ); + aes_tests = aes_test_ecb_dec[u]; + } + else + { + ret = mbedtls_aes_setkey_enc( &ctx, key, keybits ); + aes_tests = aes_test_ecb_enc[u]; + } + + /* + * AES-192 is an optional feature that may be unavailable when + * there is an alternative underlying implementation i.e. when + * MBEDTLS_AES_ALT is defined. + */ + if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192 ) + { + mbedtls_printf( "skipped\n" ); + continue; + } + else if( ret != 0 ) + { + goto exit; + } + + for( j = 0; j < 10000; j++ ) + { + ret = mbedtls_aes_crypt_ecb( &ctx, mode, buf, buf ); + if( ret != 0 ) + goto exit; + } + + if( memcmp( buf, aes_tests, 16 ) != 0 ) + { + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + /* + * CBC mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + keybits = 128 + u * 64; + mode = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " AES-CBC-%3u (%s): ", keybits, + ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + + memset( iv , 0, 16 ); + memset( prv, 0, 16 ); + memset( buf, 0, 16 ); + + if( mode == MBEDTLS_AES_DECRYPT ) + { + ret = mbedtls_aes_setkey_dec( &ctx, key, keybits ); + aes_tests = aes_test_cbc_dec[u]; + } + else + { + ret = mbedtls_aes_setkey_enc( &ctx, key, keybits ); + aes_tests = aes_test_cbc_enc[u]; + } + + /* + * AES-192 is an optional feature that may be unavailable when + * there is an alternative underlying implementation i.e. when + * MBEDTLS_AES_ALT is defined. + */ + if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192 ) + { + mbedtls_printf( "skipped\n" ); + continue; + } + else if( ret != 0 ) + { + goto exit; + } + + for( j = 0; j < 10000; j++ ) + { + if( mode == MBEDTLS_AES_ENCRYPT ) + { + unsigned char tmp[16]; + + memcpy( tmp, prv, 16 ); + memcpy( prv, buf, 16 ); + memcpy( buf, tmp, 16 ); + } + + ret = mbedtls_aes_crypt_cbc( &ctx, mode, 16, iv, buf, buf ); + if( ret != 0 ) + goto exit; + + } + + if( memcmp( buf, aes_tests, 16 ) != 0 ) + { + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) + /* + * CFB128 mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + keybits = 128 + u * 64; + mode = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " AES-CFB128-%3u (%s): ", keybits, + ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + + memcpy( iv, aes_test_cfb128_iv, 16 ); + memcpy( key, aes_test_cfb128_key[u], keybits / 8 ); + + offset = 0; + ret = mbedtls_aes_setkey_enc( &ctx, key, keybits ); + /* + * AES-192 is an optional feature that may be unavailable when + * there is an alternative underlying implementation i.e. when + * MBEDTLS_AES_ALT is defined. + */ + if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192 ) + { + mbedtls_printf( "skipped\n" ); + continue; + } + else if( ret != 0 ) + { + goto exit; + } + + if( mode == MBEDTLS_AES_DECRYPT ) + { + memcpy( buf, aes_test_cfb128_ct[u], 64 ); + aes_tests = aes_test_cfb128_pt; + } + else + { + memcpy( buf, aes_test_cfb128_pt, 64 ); + aes_tests = aes_test_cfb128_ct[u]; + } + + ret = mbedtls_aes_crypt_cfb128( &ctx, mode, 64, &offset, iv, buf, buf ); + if( ret != 0 ) + goto exit; + + if( memcmp( buf, aes_tests, 64 ) != 0 ) + { + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_OFB) + /* + * OFB mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + keybits = 128 + u * 64; + mode = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " AES-OFB-%3u (%s): ", keybits, + ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + + memcpy( iv, aes_test_ofb_iv, 16 ); + memcpy( key, aes_test_ofb_key[u], keybits / 8 ); + + offset = 0; + ret = mbedtls_aes_setkey_enc( &ctx, key, keybits ); + /* + * AES-192 is an optional feature that may be unavailable when + * there is an alternative underlying implementation i.e. when + * MBEDTLS_AES_ALT is defined. + */ + if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192 ) + { + mbedtls_printf( "skipped\n" ); + continue; + } + else if( ret != 0 ) + { + goto exit; + } + + if( mode == MBEDTLS_AES_DECRYPT ) + { + memcpy( buf, aes_test_ofb_ct[u], 64 ); + aes_tests = aes_test_ofb_pt; + } + else + { + memcpy( buf, aes_test_ofb_pt, 64 ); + aes_tests = aes_test_ofb_ct[u]; + } + + ret = mbedtls_aes_crypt_ofb( &ctx, 64, &offset, iv, buf, buf ); + if( ret != 0 ) + goto exit; + + if( memcmp( buf, aes_tests, 64 ) != 0 ) + { + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) + /* + * CTR mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + mode = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " AES-CTR-128 (%s): ", + ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + + memcpy( nonce_counter, aes_test_ctr_nonce_counter[u], 16 ); + memcpy( key, aes_test_ctr_key[u], 16 ); + + offset = 0; + if( ( ret = mbedtls_aes_setkey_enc( &ctx, key, 128 ) ) != 0 ) + goto exit; + + len = aes_test_ctr_len[u]; + + if( mode == MBEDTLS_AES_DECRYPT ) + { + memcpy( buf, aes_test_ctr_ct[u], len ); + aes_tests = aes_test_ctr_pt[u]; + } + else + { + memcpy( buf, aes_test_ctr_pt[u], len ); + aes_tests = aes_test_ctr_ct[u]; + } + + ret = mbedtls_aes_crypt_ctr( &ctx, len, &offset, nonce_counter, + stream_block, buf, buf ); + if( ret != 0 ) + goto exit; + + if( memcmp( buf, aes_tests, len ) != 0 ) + { + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_CIPHER_MODE_XTS) + { + static const int num_tests = + sizeof(aes_test_xts_key) / sizeof(*aes_test_xts_key); + mbedtls_aes_xts_context ctx_xts; + + /* + * XTS mode + */ + mbedtls_aes_xts_init( &ctx_xts ); + + for( i = 0; i < num_tests << 1; i++ ) + { + const unsigned char *data_unit; + u = i >> 1; + mode = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " AES-XTS-128 (%s): ", + ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + + memset( key, 0, sizeof( key ) ); + memcpy( key, aes_test_xts_key[u], 32 ); + data_unit = aes_test_xts_data_unit[u]; + + len = sizeof( *aes_test_xts_ct32 ); + + if( mode == MBEDTLS_AES_DECRYPT ) + { + ret = mbedtls_aes_xts_setkey_dec( &ctx_xts, key, 256 ); + if( ret != 0) + goto exit; + memcpy( buf, aes_test_xts_ct32[u], len ); + aes_tests = aes_test_xts_pt32[u]; + } + else + { + ret = mbedtls_aes_xts_setkey_enc( &ctx_xts, key, 256 ); + if( ret != 0) + goto exit; + memcpy( buf, aes_test_xts_pt32[u], len ); + aes_tests = aes_test_xts_ct32[u]; + } + + + ret = mbedtls_aes_crypt_xts( &ctx_xts, mode, len, data_unit, + buf, buf ); + if( ret != 0 ) + goto exit; + + if( memcmp( buf, aes_tests, len ) != 0 ) + { + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + mbedtls_aes_xts_free( &ctx_xts ); + } +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + + ret = 0; + +exit: + if( ret != 0 && verbose != 0 ) + mbedtls_printf( "failed\n" ); + + mbedtls_aes_free( &ctx ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_AES_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/aesni.c b/Android/Level4/app/src/main/c/mbedtls/library/aesni.c new file mode 100644 index 0000000..996292f --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/aesni.c @@ -0,0 +1,464 @@ +/* + * AES-NI support functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ + +/* + * [AES-WP] http://software.intel.com/en-us/articles/intel-advanced-encryption-standard-aes-instructions-set + * [CLMUL-WP] http://software.intel.com/en-us/articles/intel-carry-less-multiplication-instruction-and-its-usage-for-computing-the-gcm-mode/ + */ + +#include "common.h" + +#if defined(MBEDTLS_AESNI_C) + +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) +#warning "MBEDTLS_AESNI_C is known to cause spurious error reports with some memory sanitizers as they do not understand the assembly code." +#endif +#endif + +#include "mbedtls/aesni.h" + +#include + +#ifndef asm +#define asm __asm +#endif + +#if defined(MBEDTLS_HAVE_X86_64) + +/* + * AES-NI support detection routine + */ +int mbedtls_aesni_has_support( unsigned int what ) +{ + static int done = 0; + static unsigned int c = 0; + + if( ! done ) + { + asm( "movl $1, %%eax \n\t" + "cpuid \n\t" + : "=c" (c) + : + : "eax", "ebx", "edx" ); + done = 1; + } + + return( ( c & what ) != 0 ); +} + +/* + * Binutils needs to be at least 2.19 to support AES-NI instructions. + * Unfortunately, a lot of users have a lower version now (2014-04). + * Emit bytecode directly in order to support "old" version of gas. + * + * Opcodes from the Intel architecture reference manual, vol. 3. + * We always use registers, so we don't need prefixes for memory operands. + * Operand macros are in gas order (src, dst) as opposed to Intel order + * (dst, src) in order to blend better into the surrounding assembly code. + */ +#define AESDEC ".byte 0x66,0x0F,0x38,0xDE," +#define AESDECLAST ".byte 0x66,0x0F,0x38,0xDF," +#define AESENC ".byte 0x66,0x0F,0x38,0xDC," +#define AESENCLAST ".byte 0x66,0x0F,0x38,0xDD," +#define AESIMC ".byte 0x66,0x0F,0x38,0xDB," +#define AESKEYGENA ".byte 0x66,0x0F,0x3A,0xDF," +#define PCLMULQDQ ".byte 0x66,0x0F,0x3A,0x44," + +#define xmm0_xmm0 "0xC0" +#define xmm0_xmm1 "0xC8" +#define xmm0_xmm2 "0xD0" +#define xmm0_xmm3 "0xD8" +#define xmm0_xmm4 "0xE0" +#define xmm1_xmm0 "0xC1" +#define xmm1_xmm2 "0xD1" + +/* + * AES-NI AES-ECB block en(de)cryption + */ +int mbedtls_aesni_crypt_ecb( mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ) +{ + asm( "movdqu (%3), %%xmm0 \n\t" // load input + "movdqu (%1), %%xmm1 \n\t" // load round key 0 + "pxor %%xmm1, %%xmm0 \n\t" // round 0 + "add $16, %1 \n\t" // point to next round key + "subl $1, %0 \n\t" // normal rounds = nr - 1 + "test %2, %2 \n\t" // mode? + "jz 2f \n\t" // 0 = decrypt + + "1: \n\t" // encryption loop + "movdqu (%1), %%xmm1 \n\t" // load round key + AESENC xmm1_xmm0 "\n\t" // do round + "add $16, %1 \n\t" // point to next round key + "subl $1, %0 \n\t" // loop + "jnz 1b \n\t" + "movdqu (%1), %%xmm1 \n\t" // load round key + AESENCLAST xmm1_xmm0 "\n\t" // last round + "jmp 3f \n\t" + + "2: \n\t" // decryption loop + "movdqu (%1), %%xmm1 \n\t" + AESDEC xmm1_xmm0 "\n\t" // do round + "add $16, %1 \n\t" + "subl $1, %0 \n\t" + "jnz 2b \n\t" + "movdqu (%1), %%xmm1 \n\t" // load round key + AESDECLAST xmm1_xmm0 "\n\t" // last round + + "3: \n\t" + "movdqu %%xmm0, (%4) \n\t" // export output + : + : "r" (ctx->nr), "r" (ctx->rk), "r" (mode), "r" (input), "r" (output) + : "memory", "cc", "xmm0", "xmm1" ); + + + return( 0 ); +} + +/* + * GCM multiplication: c = a times b in GF(2^128) + * Based on [CLMUL-WP] algorithms 1 (with equation 27) and 5. + */ +void mbedtls_aesni_gcm_mult( unsigned char c[16], + const unsigned char a[16], + const unsigned char b[16] ) +{ + unsigned char aa[16], bb[16], cc[16]; + size_t i; + + /* The inputs are in big-endian order, so byte-reverse them */ + for( i = 0; i < 16; i++ ) + { + aa[i] = a[15 - i]; + bb[i] = b[15 - i]; + } + + asm( "movdqu (%0), %%xmm0 \n\t" // a1:a0 + "movdqu (%1), %%xmm1 \n\t" // b1:b0 + + /* + * Caryless multiplication xmm2:xmm1 = xmm0 * xmm1 + * using [CLMUL-WP] algorithm 1 (p. 13). + */ + "movdqa %%xmm1, %%xmm2 \n\t" // copy of b1:b0 + "movdqa %%xmm1, %%xmm3 \n\t" // same + "movdqa %%xmm1, %%xmm4 \n\t" // same + PCLMULQDQ xmm0_xmm1 ",0x00 \n\t" // a0*b0 = c1:c0 + PCLMULQDQ xmm0_xmm2 ",0x11 \n\t" // a1*b1 = d1:d0 + PCLMULQDQ xmm0_xmm3 ",0x10 \n\t" // a0*b1 = e1:e0 + PCLMULQDQ xmm0_xmm4 ",0x01 \n\t" // a1*b0 = f1:f0 + "pxor %%xmm3, %%xmm4 \n\t" // e1+f1:e0+f0 + "movdqa %%xmm4, %%xmm3 \n\t" // same + "psrldq $8, %%xmm4 \n\t" // 0:e1+f1 + "pslldq $8, %%xmm3 \n\t" // e0+f0:0 + "pxor %%xmm4, %%xmm2 \n\t" // d1:d0+e1+f1 + "pxor %%xmm3, %%xmm1 \n\t" // c1+e0+f1:c0 + + /* + * Now shift the result one bit to the left, + * taking advantage of [CLMUL-WP] eq 27 (p. 20) + */ + "movdqa %%xmm1, %%xmm3 \n\t" // r1:r0 + "movdqa %%xmm2, %%xmm4 \n\t" // r3:r2 + "psllq $1, %%xmm1 \n\t" // r1<<1:r0<<1 + "psllq $1, %%xmm2 \n\t" // r3<<1:r2<<1 + "psrlq $63, %%xmm3 \n\t" // r1>>63:r0>>63 + "psrlq $63, %%xmm4 \n\t" // r3>>63:r2>>63 + "movdqa %%xmm3, %%xmm5 \n\t" // r1>>63:r0>>63 + "pslldq $8, %%xmm3 \n\t" // r0>>63:0 + "pslldq $8, %%xmm4 \n\t" // r2>>63:0 + "psrldq $8, %%xmm5 \n\t" // 0:r1>>63 + "por %%xmm3, %%xmm1 \n\t" // r1<<1|r0>>63:r0<<1 + "por %%xmm4, %%xmm2 \n\t" // r3<<1|r2>>62:r2<<1 + "por %%xmm5, %%xmm2 \n\t" // r3<<1|r2>>62:r2<<1|r1>>63 + + /* + * Now reduce modulo the GCM polynomial x^128 + x^7 + x^2 + x + 1 + * using [CLMUL-WP] algorithm 5 (p. 20). + * Currently xmm2:xmm1 holds x3:x2:x1:x0 (already shifted). + */ + /* Step 2 (1) */ + "movdqa %%xmm1, %%xmm3 \n\t" // x1:x0 + "movdqa %%xmm1, %%xmm4 \n\t" // same + "movdqa %%xmm1, %%xmm5 \n\t" // same + "psllq $63, %%xmm3 \n\t" // x1<<63:x0<<63 = stuff:a + "psllq $62, %%xmm4 \n\t" // x1<<62:x0<<62 = stuff:b + "psllq $57, %%xmm5 \n\t" // x1<<57:x0<<57 = stuff:c + + /* Step 2 (2) */ + "pxor %%xmm4, %%xmm3 \n\t" // stuff:a+b + "pxor %%xmm5, %%xmm3 \n\t" // stuff:a+b+c + "pslldq $8, %%xmm3 \n\t" // a+b+c:0 + "pxor %%xmm3, %%xmm1 \n\t" // x1+a+b+c:x0 = d:x0 + + /* Steps 3 and 4 */ + "movdqa %%xmm1,%%xmm0 \n\t" // d:x0 + "movdqa %%xmm1,%%xmm4 \n\t" // same + "movdqa %%xmm1,%%xmm5 \n\t" // same + "psrlq $1, %%xmm0 \n\t" // e1:x0>>1 = e1:e0' + "psrlq $2, %%xmm4 \n\t" // f1:x0>>2 = f1:f0' + "psrlq $7, %%xmm5 \n\t" // g1:x0>>7 = g1:g0' + "pxor %%xmm4, %%xmm0 \n\t" // e1+f1:e0'+f0' + "pxor %%xmm5, %%xmm0 \n\t" // e1+f1+g1:e0'+f0'+g0' + // e0'+f0'+g0' is almost e0+f0+g0, ex\tcept for some missing + // bits carried from d. Now get those\t bits back in. + "movdqa %%xmm1,%%xmm3 \n\t" // d:x0 + "movdqa %%xmm1,%%xmm4 \n\t" // same + "movdqa %%xmm1,%%xmm5 \n\t" // same + "psllq $63, %%xmm3 \n\t" // d<<63:stuff + "psllq $62, %%xmm4 \n\t" // d<<62:stuff + "psllq $57, %%xmm5 \n\t" // d<<57:stuff + "pxor %%xmm4, %%xmm3 \n\t" // d<<63+d<<62:stuff + "pxor %%xmm5, %%xmm3 \n\t" // missing bits of d:stuff + "psrldq $8, %%xmm3 \n\t" // 0:missing bits of d + "pxor %%xmm3, %%xmm0 \n\t" // e1+f1+g1:e0+f0+g0 + "pxor %%xmm1, %%xmm0 \n\t" // h1:h0 + "pxor %%xmm2, %%xmm0 \n\t" // x3+h1:x2+h0 + + "movdqu %%xmm0, (%2) \n\t" // done + : + : "r" (aa), "r" (bb), "r" (cc) + : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" ); + + /* Now byte-reverse the outputs */ + for( i = 0; i < 16; i++ ) + c[i] = cc[15 - i]; + + return; +} + +/* + * Compute decryption round keys from encryption round keys + */ +void mbedtls_aesni_inverse_key( unsigned char *invkey, + const unsigned char *fwdkey, int nr ) +{ + unsigned char *ik = invkey; + const unsigned char *fk = fwdkey + 16 * nr; + + memcpy( ik, fk, 16 ); + + for( fk -= 16, ik += 16; fk > fwdkey; fk -= 16, ik += 16 ) + asm( "movdqu (%0), %%xmm0 \n\t" + AESIMC xmm0_xmm0 "\n\t" + "movdqu %%xmm0, (%1) \n\t" + : + : "r" (fk), "r" (ik) + : "memory", "xmm0" ); + + memcpy( ik, fk, 16 ); +} + +/* + * Key expansion, 128-bit case + */ +static void aesni_setkey_enc_128( unsigned char *rk, + const unsigned char *key ) +{ + asm( "movdqu (%1), %%xmm0 \n\t" // copy the original key + "movdqu %%xmm0, (%0) \n\t" // as round key 0 + "jmp 2f \n\t" // skip auxiliary routine + + /* + * Finish generating the next round key. + * + * On entry xmm0 is r3:r2:r1:r0 and xmm1 is X:stuff:stuff:stuff + * with X = rot( sub( r3 ) ) ^ RCON. + * + * On exit, xmm0 is r7:r6:r5:r4 + * with r4 = X + r0, r5 = r4 + r1, r6 = r5 + r2, r7 = r6 + r3 + * and those are written to the round key buffer. + */ + "1: \n\t" + "pshufd $0xff, %%xmm1, %%xmm1 \n\t" // X:X:X:X + "pxor %%xmm0, %%xmm1 \n\t" // X+r3:X+r2:X+r1:r4 + "pslldq $4, %%xmm0 \n\t" // r2:r1:r0:0 + "pxor %%xmm0, %%xmm1 \n\t" // X+r3+r2:X+r2+r1:r5:r4 + "pslldq $4, %%xmm0 \n\t" // etc + "pxor %%xmm0, %%xmm1 \n\t" + "pslldq $4, %%xmm0 \n\t" + "pxor %%xmm1, %%xmm0 \n\t" // update xmm0 for next time! + "add $16, %0 \n\t" // point to next round key + "movdqu %%xmm0, (%0) \n\t" // write it + "ret \n\t" + + /* Main "loop" */ + "2: \n\t" + AESKEYGENA xmm0_xmm1 ",0x01 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x02 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x04 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x08 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x10 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x20 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x40 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x80 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x1B \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x36 \n\tcall 1b \n\t" + : + : "r" (rk), "r" (key) + : "memory", "cc", "0" ); +} + +/* + * Key expansion, 192-bit case + */ +static void aesni_setkey_enc_192( unsigned char *rk, + const unsigned char *key ) +{ + asm( "movdqu (%1), %%xmm0 \n\t" // copy original round key + "movdqu %%xmm0, (%0) \n\t" + "add $16, %0 \n\t" + "movq 16(%1), %%xmm1 \n\t" + "movq %%xmm1, (%0) \n\t" + "add $8, %0 \n\t" + "jmp 2f \n\t" // skip auxiliary routine + + /* + * Finish generating the next 6 quarter-keys. + * + * On entry xmm0 is r3:r2:r1:r0, xmm1 is stuff:stuff:r5:r4 + * and xmm2 is stuff:stuff:X:stuff with X = rot( sub( r3 ) ) ^ RCON. + * + * On exit, xmm0 is r9:r8:r7:r6 and xmm1 is stuff:stuff:r11:r10 + * and those are written to the round key buffer. + */ + "1: \n\t" + "pshufd $0x55, %%xmm2, %%xmm2 \n\t" // X:X:X:X + "pxor %%xmm0, %%xmm2 \n\t" // X+r3:X+r2:X+r1:r4 + "pslldq $4, %%xmm0 \n\t" // etc + "pxor %%xmm0, %%xmm2 \n\t" + "pslldq $4, %%xmm0 \n\t" + "pxor %%xmm0, %%xmm2 \n\t" + "pslldq $4, %%xmm0 \n\t" + "pxor %%xmm2, %%xmm0 \n\t" // update xmm0 = r9:r8:r7:r6 + "movdqu %%xmm0, (%0) \n\t" + "add $16, %0 \n\t" + "pshufd $0xff, %%xmm0, %%xmm2 \n\t" // r9:r9:r9:r9 + "pxor %%xmm1, %%xmm2 \n\t" // stuff:stuff:r9+r5:r10 + "pslldq $4, %%xmm1 \n\t" // r2:r1:r0:0 + "pxor %%xmm2, %%xmm1 \n\t" // xmm1 = stuff:stuff:r11:r10 + "movq %%xmm1, (%0) \n\t" + "add $8, %0 \n\t" + "ret \n\t" + + "2: \n\t" + AESKEYGENA xmm1_xmm2 ",0x01 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x02 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x04 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x08 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x10 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x20 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x40 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x80 \n\tcall 1b \n\t" + + : + : "r" (rk), "r" (key) + : "memory", "cc", "0" ); +} + +/* + * Key expansion, 256-bit case + */ +static void aesni_setkey_enc_256( unsigned char *rk, + const unsigned char *key ) +{ + asm( "movdqu (%1), %%xmm0 \n\t" + "movdqu %%xmm0, (%0) \n\t" + "add $16, %0 \n\t" + "movdqu 16(%1), %%xmm1 \n\t" + "movdqu %%xmm1, (%0) \n\t" + "jmp 2f \n\t" // skip auxiliary routine + + /* + * Finish generating the next two round keys. + * + * On entry xmm0 is r3:r2:r1:r0, xmm1 is r7:r6:r5:r4 and + * xmm2 is X:stuff:stuff:stuff with X = rot( sub( r7 )) ^ RCON + * + * On exit, xmm0 is r11:r10:r9:r8 and xmm1 is r15:r14:r13:r12 + * and those have been written to the output buffer. + */ + "1: \n\t" + "pshufd $0xff, %%xmm2, %%xmm2 \n\t" + "pxor %%xmm0, %%xmm2 \n\t" + "pslldq $4, %%xmm0 \n\t" + "pxor %%xmm0, %%xmm2 \n\t" + "pslldq $4, %%xmm0 \n\t" + "pxor %%xmm0, %%xmm2 \n\t" + "pslldq $4, %%xmm0 \n\t" + "pxor %%xmm2, %%xmm0 \n\t" + "add $16, %0 \n\t" + "movdqu %%xmm0, (%0) \n\t" + + /* Set xmm2 to stuff:Y:stuff:stuff with Y = subword( r11 ) + * and proceed to generate next round key from there */ + AESKEYGENA xmm0_xmm2 ",0x00 \n\t" + "pshufd $0xaa, %%xmm2, %%xmm2 \n\t" + "pxor %%xmm1, %%xmm2 \n\t" + "pslldq $4, %%xmm1 \n\t" + "pxor %%xmm1, %%xmm2 \n\t" + "pslldq $4, %%xmm1 \n\t" + "pxor %%xmm1, %%xmm2 \n\t" + "pslldq $4, %%xmm1 \n\t" + "pxor %%xmm2, %%xmm1 \n\t" + "add $16, %0 \n\t" + "movdqu %%xmm1, (%0) \n\t" + "ret \n\t" + + /* + * Main "loop" - Generating one more key than necessary, + * see definition of mbedtls_aes_context.buf + */ + "2: \n\t" + AESKEYGENA xmm1_xmm2 ",0x01 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x02 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x04 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x08 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x10 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x20 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x40 \n\tcall 1b \n\t" + : + : "r" (rk), "r" (key) + : "memory", "cc", "0" ); +} + +/* + * Key expansion, wrapper + */ +int mbedtls_aesni_setkey_enc( unsigned char *rk, + const unsigned char *key, + size_t bits ) +{ + switch( bits ) + { + case 128: aesni_setkey_enc_128( rk, key ); break; + case 192: aesni_setkey_enc_192( rk, key ); break; + case 256: aesni_setkey_enc_256( rk, key ); break; + default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH ); + } + + return( 0 ); +} + +#endif /* MBEDTLS_HAVE_X86_64 */ + +#endif /* MBEDTLS_AESNI_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/arc4.c b/Android/Level4/app/src/main/c/mbedtls/library/arc4.c new file mode 100644 index 0000000..b34dc5e --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/arc4.c @@ -0,0 +1,195 @@ +/* + * An implementation of the ARCFOUR algorithm + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ +/* + * The ARCFOUR algorithm was publicly disclosed on 94/09. + * + * http://groups.google.com/group/sci.crypt/msg/10a300c9d21afca0 + */ + +#include "common.h" + +#if defined(MBEDTLS_ARC4_C) + +#include "mbedtls/arc4.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_ARC4_ALT) + +void mbedtls_arc4_init( mbedtls_arc4_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_arc4_context ) ); +} + +void mbedtls_arc4_free( mbedtls_arc4_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_arc4_context ) ); +} + +/* + * ARC4 key schedule + */ +void mbedtls_arc4_setup( mbedtls_arc4_context *ctx, const unsigned char *key, + unsigned int keylen ) +{ + int i, j, a; + unsigned int k; + unsigned char *m; + + ctx->x = 0; + ctx->y = 0; + m = ctx->m; + + for( i = 0; i < 256; i++ ) + m[i] = (unsigned char) i; + + j = k = 0; + + for( i = 0; i < 256; i++, k++ ) + { + if( k >= keylen ) k = 0; + + a = m[i]; + j = ( j + a + key[k] ) & 0xFF; + m[i] = m[j]; + m[j] = (unsigned char) a; + } +} + +/* + * ARC4 cipher function + */ +int mbedtls_arc4_crypt( mbedtls_arc4_context *ctx, size_t length, const unsigned char *input, + unsigned char *output ) +{ + int x, y, a, b; + size_t i; + unsigned char *m; + + x = ctx->x; + y = ctx->y; + m = ctx->m; + + for( i = 0; i < length; i++ ) + { + x = ( x + 1 ) & 0xFF; a = m[x]; + y = ( y + a ) & 0xFF; b = m[y]; + + m[x] = (unsigned char) b; + m[y] = (unsigned char) a; + + output[i] = (unsigned char) + ( input[i] ^ m[(unsigned char)( a + b )] ); + } + + ctx->x = x; + ctx->y = y; + + return( 0 ); +} + +#endif /* !MBEDTLS_ARC4_ALT */ + +#if defined(MBEDTLS_SELF_TEST) +/* + * ARC4 tests vectors as posted by Eric Rescorla in sep. 1994: + * + * http://groups.google.com/group/comp.security.misc/msg/10a300c9d21afca0 + */ +static const unsigned char arc4_test_key[3][8] = +{ + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } +}; + +static const unsigned char arc4_test_pt[3][8] = +{ + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } +}; + +static const unsigned char arc4_test_ct[3][8] = +{ + { 0x75, 0xB7, 0x87, 0x80, 0x99, 0xE0, 0xC5, 0x96 }, + { 0x74, 0x94, 0xC2, 0xE7, 0x10, 0x4B, 0x08, 0x79 }, + { 0xDE, 0x18, 0x89, 0x41, 0xA3, 0x37, 0x5D, 0x3A } +}; + +/* + * Checkup routine + */ +int mbedtls_arc4_self_test( int verbose ) +{ + int i, ret = 0; + unsigned char ibuf[8]; + unsigned char obuf[8]; + mbedtls_arc4_context ctx; + + mbedtls_arc4_init( &ctx ); + + for( i = 0; i < 3; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " ARC4 test #%d: ", i + 1 ); + + memcpy( ibuf, arc4_test_pt[i], 8 ); + + mbedtls_arc4_setup( &ctx, arc4_test_key[i], 8 ); + mbedtls_arc4_crypt( &ctx, 8, ibuf, obuf ); + + if( memcmp( obuf, arc4_test_ct[i], 8 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +exit: + mbedtls_arc4_free( &ctx ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_ARC4_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/aria.c b/Android/Level4/app/src/main/c/mbedtls/library/aria.c new file mode 100644 index 0000000..1875635 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/aria.c @@ -0,0 +1,1073 @@ +/* + * ARIA implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 implementation is based on the following standards: + * [1] http://210.104.33.10/ARIA/doc/ARIA-specification-e.pdf + * [2] https://tools.ietf.org/html/rfc5794 + */ + +#include "common.h" + +#if defined(MBEDTLS_ARIA_C) + +#include "mbedtls/aria.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_ARIA_ALT) + +#include "mbedtls/platform_util.h" + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +/* Parameter validation macros */ +#define ARIA_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ARIA_BAD_INPUT_DATA ) +#define ARIA_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_UINT32_LE +#define GET_UINT32_LE( n, b, i ) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] ) \ + | ( (uint32_t) (b)[(i) + 1] << 8 ) \ + | ( (uint32_t) (b)[(i) + 2] << 16 ) \ + | ( (uint32_t) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef PUT_UINT32_LE +#define PUT_UINT32_LE( n, b, i ) \ +{ \ + (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ + (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ + (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ + (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ +} +#endif + +/* + * modify byte order: ( A B C D ) -> ( B A D C ), i.e. swap pairs of bytes + * + * This is submatrix P1 in [1] Appendix B.1 + * + * Common compilers fail to translate this to minimal number of instructions, + * so let's provide asm versions for common platforms with C fallback. + */ +#if defined(MBEDTLS_HAVE_ASM) +#if defined(__arm__) /* rev16 available from v6 up */ +/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */ +#if defined(__GNUC__) && \ + ( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 ) && \ + __ARM_ARCH >= 6 +static inline uint32_t aria_p1( uint32_t x ) +{ + uint32_t r; + __asm( "rev16 %0, %1" : "=l" (r) : "l" (x) ); + return( r ); +} +#define ARIA_P1 aria_p1 +#elif defined(__ARMCC_VERSION) && __ARMCC_VERSION < 6000000 && \ + ( __TARGET_ARCH_ARM >= 6 || __TARGET_ARCH_THUMB >= 3 ) +static inline uint32_t aria_p1( uint32_t x ) +{ + uint32_t r; + __asm( "rev16 r, x" ); + return( r ); +} +#define ARIA_P1 aria_p1 +#endif +#endif /* arm */ +#if defined(__GNUC__) && \ + defined(__i386__) || defined(__amd64__) || defined( __x86_64__) +/* I couldn't find an Intel equivalent of rev16, so two instructions */ +#define ARIA_P1(x) ARIA_P2( ARIA_P3( x ) ) +#endif /* x86 gnuc */ +#endif /* MBEDTLS_HAVE_ASM && GNUC */ +#if !defined(ARIA_P1) +#define ARIA_P1(x) ((((x) >> 8) & 0x00FF00FF) ^ (((x) & 0x00FF00FF) << 8)) +#endif + +/* + * modify byte order: ( A B C D ) -> ( C D A B ), i.e. rotate by 16 bits + * + * This is submatrix P2 in [1] Appendix B.1 + * + * Common compilers will translate this to a single instruction. + */ +#define ARIA_P2(x) (((x) >> 16) ^ ((x) << 16)) + +/* + * modify byte order: ( A B C D ) -> ( D C B A ), i.e. change endianness + * + * This is submatrix P3 in [1] Appendix B.1 + * + * Some compilers fail to translate this to a single instruction, + * so let's provide asm versions for common platforms with C fallback. + */ +#if defined(MBEDTLS_HAVE_ASM) +#if defined(__arm__) /* rev available from v6 up */ +/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */ +#if defined(__GNUC__) && \ + ( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 ) && \ + __ARM_ARCH >= 6 +static inline uint32_t aria_p3( uint32_t x ) +{ + uint32_t r; + __asm( "rev %0, %1" : "=l" (r) : "l" (x) ); + return( r ); +} +#define ARIA_P3 aria_p3 +#elif defined(__ARMCC_VERSION) && __ARMCC_VERSION < 6000000 && \ + ( __TARGET_ARCH_ARM >= 6 || __TARGET_ARCH_THUMB >= 3 ) +static inline uint32_t aria_p3( uint32_t x ) +{ + uint32_t r; + __asm( "rev r, x" ); + return( r ); +} +#define ARIA_P3 aria_p3 +#endif +#endif /* arm */ +#if defined(__GNUC__) && \ + defined(__i386__) || defined(__amd64__) || defined( __x86_64__) +static inline uint32_t aria_p3( uint32_t x ) +{ + __asm( "bswap %0" : "=r" (x) : "0" (x) ); + return( x ); +} +#define ARIA_P3 aria_p3 +#endif /* x86 gnuc */ +#endif /* MBEDTLS_HAVE_ASM && GNUC */ +#if !defined(ARIA_P3) +#define ARIA_P3(x) ARIA_P2( ARIA_P1 ( x ) ) +#endif + +/* + * ARIA Affine Transform + * (a, b, c, d) = state in/out + * + * If we denote the first byte of input by 0, ..., the last byte by f, + * then inputs are: a = 0123, b = 4567, c = 89ab, d = cdef. + * + * Reading [1] 2.4 or [2] 2.4.3 in columns and performing simple + * rearrangements on adjacent pairs, output is: + * + * a = 3210 + 4545 + 6767 + 88aa + 99bb + dccd + effe + * = 3210 + 4567 + 6745 + 89ab + 98ba + dcfe + efcd + * b = 0101 + 2323 + 5476 + 8998 + baab + eecc + ffdd + * = 0123 + 2301 + 5476 + 89ab + ba98 + efcd + fedc + * c = 0022 + 1133 + 4554 + 7667 + ab89 + dcdc + fefe + * = 0123 + 1032 + 4567 + 7654 + ab89 + dcfe + fedc + * d = 1001 + 2332 + 6644 + 7755 + 9898 + baba + cdef + * = 1032 + 2301 + 6745 + 7654 + 98ba + ba98 + cdef + * + * Note: another presentation of the A transform can be found as the first + * half of App. B.1 in [1] in terms of 4-byte operators P1, P2, P3 and P4. + * The implementation below uses only P1 and P2 as they are sufficient. + */ +static inline void aria_a( uint32_t *a, uint32_t *b, + uint32_t *c, uint32_t *d ) +{ + uint32_t ta, tb, tc; + ta = *b; // 4567 + *b = *a; // 0123 + *a = ARIA_P2( ta ); // 6745 + tb = ARIA_P2( *d ); // efcd + *d = ARIA_P1( *c ); // 98ba + *c = ARIA_P1( tb ); // fedc + ta ^= *d; // 4567+98ba + tc = ARIA_P2( *b ); // 2301 + ta = ARIA_P1( ta ) ^ tc ^ *c; // 2301+5476+89ab+fedc + tb ^= ARIA_P2( *d ); // ba98+efcd + tc ^= ARIA_P1( *a ); // 2301+7654 + *b ^= ta ^ tb; // 0123+2301+5476+89ab+ba98+efcd+fedc OUT + tb = ARIA_P2( tb ) ^ ta; // 2301+5476+89ab+98ba+cdef+fedc + *a ^= ARIA_P1( tb ); // 3210+4567+6745+89ab+98ba+dcfe+efcd OUT + ta = ARIA_P2( ta ); // 0123+7654+ab89+dcfe + *d ^= ARIA_P1( ta ) ^ tc; // 1032+2301+6745+7654+98ba+ba98+cdef OUT + tc = ARIA_P2( tc ); // 0123+5476 + *c ^= ARIA_P1( tc ) ^ ta; // 0123+1032+4567+7654+ab89+dcfe+fedc OUT +} + +/* + * ARIA Substitution Layer SL1 / SL2 + * (a, b, c, d) = state in/out + * (sa, sb, sc, sd) = 256 8-bit S-Boxes (see below) + * + * By passing sb1, sb2, is1, is2 as S-Boxes you get SL1 + * By passing is1, is2, sb1, sb2 as S-Boxes you get SL2 + */ +static inline void aria_sl( uint32_t *a, uint32_t *b, + uint32_t *c, uint32_t *d, + const uint8_t sa[256], const uint8_t sb[256], + const uint8_t sc[256], const uint8_t sd[256] ) +{ + *a = ( (uint32_t) sa[ *a & 0xFF] ) ^ + (((uint32_t) sb[(*a >> 8) & 0xFF]) << 8) ^ + (((uint32_t) sc[(*a >> 16) & 0xFF]) << 16) ^ + (((uint32_t) sd[ *a >> 24 ]) << 24); + *b = ( (uint32_t) sa[ *b & 0xFF] ) ^ + (((uint32_t) sb[(*b >> 8) & 0xFF]) << 8) ^ + (((uint32_t) sc[(*b >> 16) & 0xFF]) << 16) ^ + (((uint32_t) sd[ *b >> 24 ]) << 24); + *c = ( (uint32_t) sa[ *c & 0xFF] ) ^ + (((uint32_t) sb[(*c >> 8) & 0xFF]) << 8) ^ + (((uint32_t) sc[(*c >> 16) & 0xFF]) << 16) ^ + (((uint32_t) sd[ *c >> 24 ]) << 24); + *d = ( (uint32_t) sa[ *d & 0xFF] ) ^ + (((uint32_t) sb[(*d >> 8) & 0xFF]) << 8) ^ + (((uint32_t) sc[(*d >> 16) & 0xFF]) << 16) ^ + (((uint32_t) sd[ *d >> 24 ]) << 24); +} + +/* + * S-Boxes + */ +static const uint8_t aria_sb1[256] = +{ + 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, + 0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, + 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26, + 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, + 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, + 0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, + 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 0x53, 0xD1, 0x00, 0xED, + 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, + 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, + 0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, + 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0xCD, 0x0C, 0x13, 0xEC, + 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, + 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, + 0xDE, 0x5E, 0x0B, 0xDB, 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, + 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D, + 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, + 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, + 0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, + 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11, + 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, + 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, + 0xB0, 0x54, 0xBB, 0x16 +}; + +static const uint8_t aria_sb2[256] = +{ + 0xE2, 0x4E, 0x54, 0xFC, 0x94, 0xC2, 0x4A, 0xCC, 0x62, 0x0D, 0x6A, 0x46, + 0x3C, 0x4D, 0x8B, 0xD1, 0x5E, 0xFA, 0x64, 0xCB, 0xB4, 0x97, 0xBE, 0x2B, + 0xBC, 0x77, 0x2E, 0x03, 0xD3, 0x19, 0x59, 0xC1, 0x1D, 0x06, 0x41, 0x6B, + 0x55, 0xF0, 0x99, 0x69, 0xEA, 0x9C, 0x18, 0xAE, 0x63, 0xDF, 0xE7, 0xBB, + 0x00, 0x73, 0x66, 0xFB, 0x96, 0x4C, 0x85, 0xE4, 0x3A, 0x09, 0x45, 0xAA, + 0x0F, 0xEE, 0x10, 0xEB, 0x2D, 0x7F, 0xF4, 0x29, 0xAC, 0xCF, 0xAD, 0x91, + 0x8D, 0x78, 0xC8, 0x95, 0xF9, 0x2F, 0xCE, 0xCD, 0x08, 0x7A, 0x88, 0x38, + 0x5C, 0x83, 0x2A, 0x28, 0x47, 0xDB, 0xB8, 0xC7, 0x93, 0xA4, 0x12, 0x53, + 0xFF, 0x87, 0x0E, 0x31, 0x36, 0x21, 0x58, 0x48, 0x01, 0x8E, 0x37, 0x74, + 0x32, 0xCA, 0xE9, 0xB1, 0xB7, 0xAB, 0x0C, 0xD7, 0xC4, 0x56, 0x42, 0x26, + 0x07, 0x98, 0x60, 0xD9, 0xB6, 0xB9, 0x11, 0x40, 0xEC, 0x20, 0x8C, 0xBD, + 0xA0, 0xC9, 0x84, 0x04, 0x49, 0x23, 0xF1, 0x4F, 0x50, 0x1F, 0x13, 0xDC, + 0xD8, 0xC0, 0x9E, 0x57, 0xE3, 0xC3, 0x7B, 0x65, 0x3B, 0x02, 0x8F, 0x3E, + 0xE8, 0x25, 0x92, 0xE5, 0x15, 0xDD, 0xFD, 0x17, 0xA9, 0xBF, 0xD4, 0x9A, + 0x7E, 0xC5, 0x39, 0x67, 0xFE, 0x76, 0x9D, 0x43, 0xA7, 0xE1, 0xD0, 0xF5, + 0x68, 0xF2, 0x1B, 0x34, 0x70, 0x05, 0xA3, 0x8A, 0xD5, 0x79, 0x86, 0xA8, + 0x30, 0xC6, 0x51, 0x4B, 0x1E, 0xA6, 0x27, 0xF6, 0x35, 0xD2, 0x6E, 0x24, + 0x16, 0x82, 0x5F, 0xDA, 0xE6, 0x75, 0xA2, 0xEF, 0x2C, 0xB2, 0x1C, 0x9F, + 0x5D, 0x6F, 0x80, 0x0A, 0x72, 0x44, 0x9B, 0x6C, 0x90, 0x0B, 0x5B, 0x33, + 0x7D, 0x5A, 0x52, 0xF3, 0x61, 0xA1, 0xF7, 0xB0, 0xD6, 0x3F, 0x7C, 0x6D, + 0xED, 0x14, 0xE0, 0xA5, 0x3D, 0x22, 0xB3, 0xF8, 0x89, 0xDE, 0x71, 0x1A, + 0xAF, 0xBA, 0xB5, 0x81 +}; + +static const uint8_t aria_is1[256] = +{ + 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, + 0x81, 0xF3, 0xD7, 0xFB, 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, + 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, 0x54, 0x7B, 0x94, 0x32, + 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, + 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, + 0x6D, 0x8B, 0xD1, 0x25, 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, + 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, 0x6C, 0x70, 0x48, 0x50, + 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, + 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, + 0xB8, 0xB3, 0x45, 0x06, 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, + 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, 0x3A, 0x91, 0x11, 0x41, + 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, + 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, + 0x1C, 0x75, 0xDF, 0x6E, 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, + 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, 0xFC, 0x56, 0x3E, 0x4B, + 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, + 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, + 0x27, 0x80, 0xEC, 0x5F, 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, + 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, 0xA0, 0xE0, 0x3B, 0x4D, + 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, + 0x55, 0x21, 0x0C, 0x7D +}; + +static const uint8_t aria_is2[256] = +{ + 0x30, 0x68, 0x99, 0x1B, 0x87, 0xB9, 0x21, 0x78, 0x50, 0x39, 0xDB, 0xE1, + 0x72, 0x09, 0x62, 0x3C, 0x3E, 0x7E, 0x5E, 0x8E, 0xF1, 0xA0, 0xCC, 0xA3, + 0x2A, 0x1D, 0xFB, 0xB6, 0xD6, 0x20, 0xC4, 0x8D, 0x81, 0x65, 0xF5, 0x89, + 0xCB, 0x9D, 0x77, 0xC6, 0x57, 0x43, 0x56, 0x17, 0xD4, 0x40, 0x1A, 0x4D, + 0xC0, 0x63, 0x6C, 0xE3, 0xB7, 0xC8, 0x64, 0x6A, 0x53, 0xAA, 0x38, 0x98, + 0x0C, 0xF4, 0x9B, 0xED, 0x7F, 0x22, 0x76, 0xAF, 0xDD, 0x3A, 0x0B, 0x58, + 0x67, 0x88, 0x06, 0xC3, 0x35, 0x0D, 0x01, 0x8B, 0x8C, 0xC2, 0xE6, 0x5F, + 0x02, 0x24, 0x75, 0x93, 0x66, 0x1E, 0xE5, 0xE2, 0x54, 0xD8, 0x10, 0xCE, + 0x7A, 0xE8, 0x08, 0x2C, 0x12, 0x97, 0x32, 0xAB, 0xB4, 0x27, 0x0A, 0x23, + 0xDF, 0xEF, 0xCA, 0xD9, 0xB8, 0xFA, 0xDC, 0x31, 0x6B, 0xD1, 0xAD, 0x19, + 0x49, 0xBD, 0x51, 0x96, 0xEE, 0xE4, 0xA8, 0x41, 0xDA, 0xFF, 0xCD, 0x55, + 0x86, 0x36, 0xBE, 0x61, 0x52, 0xF8, 0xBB, 0x0E, 0x82, 0x48, 0x69, 0x9A, + 0xE0, 0x47, 0x9E, 0x5C, 0x04, 0x4B, 0x34, 0x15, 0x79, 0x26, 0xA7, 0xDE, + 0x29, 0xAE, 0x92, 0xD7, 0x84, 0xE9, 0xD2, 0xBA, 0x5D, 0xF3, 0xC5, 0xB0, + 0xBF, 0xA4, 0x3B, 0x71, 0x44, 0x46, 0x2B, 0xFC, 0xEB, 0x6F, 0xD5, 0xF6, + 0x14, 0xFE, 0x7C, 0x70, 0x5A, 0x7D, 0xFD, 0x2F, 0x18, 0x83, 0x16, 0xA5, + 0x91, 0x1F, 0x05, 0x95, 0x74, 0xA9, 0xC1, 0x5B, 0x4A, 0x85, 0x6D, 0x13, + 0x07, 0x4F, 0x4E, 0x45, 0xB2, 0x0F, 0xC9, 0x1C, 0xA6, 0xBC, 0xEC, 0x73, + 0x90, 0x7B, 0xCF, 0x59, 0x8F, 0xA1, 0xF9, 0x2D, 0xF2, 0xB1, 0x00, 0x94, + 0x37, 0x9F, 0xD0, 0x2E, 0x9C, 0x6E, 0x28, 0x3F, 0x80, 0xF0, 0x3D, 0xD3, + 0x25, 0x8A, 0xB5, 0xE7, 0x42, 0xB3, 0xC7, 0xEA, 0xF7, 0x4C, 0x11, 0x33, + 0x03, 0xA2, 0xAC, 0x60 +}; + +/* + * Helper for key schedule: r = FO( p, k ) ^ x + */ +static void aria_fo_xor( uint32_t r[4], const uint32_t p[4], + const uint32_t k[4], const uint32_t x[4] ) +{ + uint32_t a, b, c, d; + + a = p[0] ^ k[0]; + b = p[1] ^ k[1]; + c = p[2] ^ k[2]; + d = p[3] ^ k[3]; + + aria_sl( &a, &b, &c, &d, aria_sb1, aria_sb2, aria_is1, aria_is2 ); + aria_a( &a, &b, &c, &d ); + + r[0] = a ^ x[0]; + r[1] = b ^ x[1]; + r[2] = c ^ x[2]; + r[3] = d ^ x[3]; +} + +/* + * Helper for key schedule: r = FE( p, k ) ^ x + */ +static void aria_fe_xor( uint32_t r[4], const uint32_t p[4], + const uint32_t k[4], const uint32_t x[4] ) +{ + uint32_t a, b, c, d; + + a = p[0] ^ k[0]; + b = p[1] ^ k[1]; + c = p[2] ^ k[2]; + d = p[3] ^ k[3]; + + aria_sl( &a, &b, &c, &d, aria_is1, aria_is2, aria_sb1, aria_sb2 ); + aria_a( &a, &b, &c, &d ); + + r[0] = a ^ x[0]; + r[1] = b ^ x[1]; + r[2] = c ^ x[2]; + r[3] = d ^ x[3]; +} + +/* + * Big endian 128-bit rotation: r = a ^ (b <<< n), used only in key setup. + * + * We chose to store bytes into 32-bit words in little-endian format (see + * GET/PUT_UINT32_LE) so we need to reverse bytes here. + */ +static void aria_rot128( uint32_t r[4], const uint32_t a[4], + const uint32_t b[4], uint8_t n ) +{ + uint8_t i, j; + uint32_t t, u; + + const uint8_t n1 = n % 32; // bit offset + const uint8_t n2 = n1 ? 32 - n1 : 0; // reverse bit offset + + j = ( n / 32 ) % 4; // initial word offset + t = ARIA_P3( b[j] ); // big endian + for( i = 0; i < 4; i++ ) + { + j = ( j + 1 ) % 4; // get next word, big endian + u = ARIA_P3( b[j] ); + t <<= n1; // rotate + t |= u >> n2; + t = ARIA_P3( t ); // back to little endian + r[i] = a[i] ^ t; // store + t = u; // move to next word + } +} + +/* + * Set encryption key + */ +int mbedtls_aria_setkey_enc( mbedtls_aria_context *ctx, + const unsigned char *key, unsigned int keybits ) +{ + /* round constant masks */ + const uint32_t rc[3][4] = + { + { 0xB7C17C51, 0x940A2227, 0xE8AB13FE, 0xE06E9AFA }, + { 0xCC4AB16D, 0x20C8219E, 0xD5B128FF, 0xB0E25DEF }, + { 0x1D3792DB, 0x70E92621, 0x75972403, 0x0EC9E804 } + }; + + int i; + uint32_t w[4][4], *w2; + ARIA_VALIDATE_RET( ctx != NULL ); + ARIA_VALIDATE_RET( key != NULL ); + + if( keybits != 128 && keybits != 192 && keybits != 256 ) + return( MBEDTLS_ERR_ARIA_BAD_INPUT_DATA ); + + /* Copy key to W0 (and potential remainder to W1) */ + GET_UINT32_LE( w[0][0], key, 0 ); + GET_UINT32_LE( w[0][1], key, 4 ); + GET_UINT32_LE( w[0][2], key, 8 ); + GET_UINT32_LE( w[0][3], key, 12 ); + + memset( w[1], 0, 16 ); + if( keybits >= 192 ) + { + GET_UINT32_LE( w[1][0], key, 16 ); // 192 bit key + GET_UINT32_LE( w[1][1], key, 20 ); + } + if( keybits == 256 ) + { + GET_UINT32_LE( w[1][2], key, 24 ); // 256 bit key + GET_UINT32_LE( w[1][3], key, 28 ); + } + + i = ( keybits - 128 ) >> 6; // index: 0, 1, 2 + ctx->nr = 12 + 2 * i; // no. rounds: 12, 14, 16 + + aria_fo_xor( w[1], w[0], rc[i], w[1] ); // W1 = FO(W0, CK1) ^ KR + i = i < 2 ? i + 1 : 0; + aria_fe_xor( w[2], w[1], rc[i], w[0] ); // W2 = FE(W1, CK2) ^ W0 + i = i < 2 ? i + 1 : 0; + aria_fo_xor( w[3], w[2], rc[i], w[1] ); // W3 = FO(W2, CK3) ^ W1 + + for( i = 0; i < 4; i++ ) // create round keys + { + w2 = w[(i + 1) & 3]; + aria_rot128( ctx->rk[i ], w[i], w2, 128 - 19 ); + aria_rot128( ctx->rk[i + 4], w[i], w2, 128 - 31 ); + aria_rot128( ctx->rk[i + 8], w[i], w2, 61 ); + aria_rot128( ctx->rk[i + 12], w[i], w2, 31 ); + } + aria_rot128( ctx->rk[16], w[0], w[1], 19 ); + + /* w holds enough info to reconstruct the round keys */ + mbedtls_platform_zeroize( w, sizeof( w ) ); + + return( 0 ); +} + +/* + * Set decryption key + */ +int mbedtls_aria_setkey_dec( mbedtls_aria_context *ctx, + const unsigned char *key, unsigned int keybits ) +{ + int i, j, k, ret; + ARIA_VALIDATE_RET( ctx != NULL ); + ARIA_VALIDATE_RET( key != NULL ); + + ret = mbedtls_aria_setkey_enc( ctx, key, keybits ); + if( ret != 0 ) + return( ret ); + + /* flip the order of round keys */ + for( i = 0, j = ctx->nr; i < j; i++, j-- ) + { + for( k = 0; k < 4; k++ ) + { + uint32_t t = ctx->rk[i][k]; + ctx->rk[i][k] = ctx->rk[j][k]; + ctx->rk[j][k] = t; + } + } + + /* apply affine transform to middle keys */ + for( i = 1; i < ctx->nr; i++ ) + { + aria_a( &ctx->rk[i][0], &ctx->rk[i][1], + &ctx->rk[i][2], &ctx->rk[i][3] ); + } + + return( 0 ); +} + +/* + * Encrypt a block + */ +int mbedtls_aria_crypt_ecb( mbedtls_aria_context *ctx, + const unsigned char input[MBEDTLS_ARIA_BLOCKSIZE], + unsigned char output[MBEDTLS_ARIA_BLOCKSIZE] ) +{ + int i; + + uint32_t a, b, c, d; + ARIA_VALIDATE_RET( ctx != NULL ); + ARIA_VALIDATE_RET( input != NULL ); + ARIA_VALIDATE_RET( output != NULL ); + + GET_UINT32_LE( a, input, 0 ); + GET_UINT32_LE( b, input, 4 ); + GET_UINT32_LE( c, input, 8 ); + GET_UINT32_LE( d, input, 12 ); + + i = 0; + while( 1 ) + { + a ^= ctx->rk[i][0]; + b ^= ctx->rk[i][1]; + c ^= ctx->rk[i][2]; + d ^= ctx->rk[i][3]; + i++; + + aria_sl( &a, &b, &c, &d, aria_sb1, aria_sb2, aria_is1, aria_is2 ); + aria_a( &a, &b, &c, &d ); + + a ^= ctx->rk[i][0]; + b ^= ctx->rk[i][1]; + c ^= ctx->rk[i][2]; + d ^= ctx->rk[i][3]; + i++; + + aria_sl( &a, &b, &c, &d, aria_is1, aria_is2, aria_sb1, aria_sb2 ); + if( i >= ctx->nr ) + break; + aria_a( &a, &b, &c, &d ); + } + + /* final key mixing */ + a ^= ctx->rk[i][0]; + b ^= ctx->rk[i][1]; + c ^= ctx->rk[i][2]; + d ^= ctx->rk[i][3]; + + PUT_UINT32_LE( a, output, 0 ); + PUT_UINT32_LE( b, output, 4 ); + PUT_UINT32_LE( c, output, 8 ); + PUT_UINT32_LE( d, output, 12 ); + + return( 0 ); +} + +/* Initialize context */ +void mbedtls_aria_init( mbedtls_aria_context *ctx ) +{ + ARIA_VALIDATE( ctx != NULL ); + memset( ctx, 0, sizeof( mbedtls_aria_context ) ); +} + +/* Clear context */ +void mbedtls_aria_free( mbedtls_aria_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_aria_context ) ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/* + * ARIA-CBC buffer encryption/decryption + */ +int mbedtls_aria_crypt_cbc( mbedtls_aria_context *ctx, + int mode, + size_t length, + unsigned char iv[MBEDTLS_ARIA_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ) +{ + int i; + unsigned char temp[MBEDTLS_ARIA_BLOCKSIZE]; + + ARIA_VALIDATE_RET( ctx != NULL ); + ARIA_VALIDATE_RET( mode == MBEDTLS_ARIA_ENCRYPT || + mode == MBEDTLS_ARIA_DECRYPT ); + ARIA_VALIDATE_RET( length == 0 || input != NULL ); + ARIA_VALIDATE_RET( length == 0 || output != NULL ); + ARIA_VALIDATE_RET( iv != NULL ); + + if( length % MBEDTLS_ARIA_BLOCKSIZE ) + return( MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH ); + + if( mode == MBEDTLS_ARIA_DECRYPT ) + { + while( length > 0 ) + { + memcpy( temp, input, MBEDTLS_ARIA_BLOCKSIZE ); + mbedtls_aria_crypt_ecb( ctx, input, output ); + + for( i = 0; i < MBEDTLS_ARIA_BLOCKSIZE; i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, MBEDTLS_ARIA_BLOCKSIZE ); + + input += MBEDTLS_ARIA_BLOCKSIZE; + output += MBEDTLS_ARIA_BLOCKSIZE; + length -= MBEDTLS_ARIA_BLOCKSIZE; + } + } + else + { + while( length > 0 ) + { + for( i = 0; i < MBEDTLS_ARIA_BLOCKSIZE; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + mbedtls_aria_crypt_ecb( ctx, output, output ); + memcpy( iv, output, MBEDTLS_ARIA_BLOCKSIZE ); + + input += MBEDTLS_ARIA_BLOCKSIZE; + output += MBEDTLS_ARIA_BLOCKSIZE; + length -= MBEDTLS_ARIA_BLOCKSIZE; + } + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/* + * ARIA-CFB128 buffer encryption/decryption + */ +int mbedtls_aria_crypt_cfb128( mbedtls_aria_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[MBEDTLS_ARIA_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ) +{ + unsigned char c; + size_t n; + + ARIA_VALIDATE_RET( ctx != NULL ); + ARIA_VALIDATE_RET( mode == MBEDTLS_ARIA_ENCRYPT || + mode == MBEDTLS_ARIA_DECRYPT ); + ARIA_VALIDATE_RET( length == 0 || input != NULL ); + ARIA_VALIDATE_RET( length == 0 || output != NULL ); + ARIA_VALIDATE_RET( iv != NULL ); + ARIA_VALIDATE_RET( iv_off != NULL ); + + n = *iv_off; + + /* An overly large value of n can lead to an unlimited + * buffer overflow. Therefore, guard against this + * outside of parameter validation. */ + if( n >= MBEDTLS_ARIA_BLOCKSIZE ) + return( MBEDTLS_ERR_ARIA_BAD_INPUT_DATA ); + + if( mode == MBEDTLS_ARIA_DECRYPT ) + { + while( length-- ) + { + if( n == 0 ) + mbedtls_aria_crypt_ecb( ctx, iv, iv ); + + c = *input++; + *output++ = c ^ iv[n]; + iv[n] = c; + + n = ( n + 1 ) & 0x0F; + } + } + else + { + while( length-- ) + { + if( n == 0 ) + mbedtls_aria_crypt_ecb( ctx, iv, iv ); + + iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); + + n = ( n + 1 ) & 0x0F; + } + } + + *iv_off = n; + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/* + * ARIA-CTR buffer encryption/decryption + */ +int mbedtls_aria_crypt_ctr( mbedtls_aria_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[MBEDTLS_ARIA_BLOCKSIZE], + unsigned char stream_block[MBEDTLS_ARIA_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ) +{ + int c, i; + size_t n; + + ARIA_VALIDATE_RET( ctx != NULL ); + ARIA_VALIDATE_RET( length == 0 || input != NULL ); + ARIA_VALIDATE_RET( length == 0 || output != NULL ); + ARIA_VALIDATE_RET( nonce_counter != NULL ); + ARIA_VALIDATE_RET( stream_block != NULL ); + ARIA_VALIDATE_RET( nc_off != NULL ); + + n = *nc_off; + /* An overly large value of n can lead to an unlimited + * buffer overflow. Therefore, guard against this + * outside of parameter validation. */ + if( n >= MBEDTLS_ARIA_BLOCKSIZE ) + return( MBEDTLS_ERR_ARIA_BAD_INPUT_DATA ); + + while( length-- ) + { + if( n == 0 ) { + mbedtls_aria_crypt_ecb( ctx, nonce_counter, + stream_block ); + + for( i = MBEDTLS_ARIA_BLOCKSIZE; i > 0; i-- ) + if( ++nonce_counter[i - 1] != 0 ) + break; + } + c = *input++; + *output++ = (unsigned char)( c ^ stream_block[n] ); + + n = ( n + 1 ) & 0x0F; + } + + *nc_off = n; + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ +#endif /* !MBEDTLS_ARIA_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +/* + * Basic ARIA ECB test vectors from RFC 5794 + */ +static const uint8_t aria_test1_ecb_key[32] = // test key +{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // 128 bit + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, // 192 bit + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F // 256 bit +}; + +static const uint8_t aria_test1_ecb_pt[MBEDTLS_ARIA_BLOCKSIZE] = // plaintext +{ + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, // same for all + 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF // key sizes +}; + +static const uint8_t aria_test1_ecb_ct[3][MBEDTLS_ARIA_BLOCKSIZE] = // ciphertext +{ + { 0xD7, 0x18, 0xFB, 0xD6, 0xAB, 0x64, 0x4C, 0x73, // 128 bit + 0x9D, 0xA9, 0x5F, 0x3B, 0xE6, 0x45, 0x17, 0x78 }, + { 0x26, 0x44, 0x9C, 0x18, 0x05, 0xDB, 0xE7, 0xAA, // 192 bit + 0x25, 0xA4, 0x68, 0xCE, 0x26, 0x3A, 0x9E, 0x79 }, + { 0xF9, 0x2B, 0xD7, 0xC7, 0x9F, 0xB7, 0x2E, 0x2F, // 256 bit + 0x2B, 0x8F, 0x80, 0xC1, 0x97, 0x2D, 0x24, 0xFC } +}; + +/* + * Mode tests from "Test Vectors for ARIA" Version 1.0 + * http://210.104.33.10/ARIA/doc/ARIA-testvector-e.pdf + */ +#if (defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB) || \ + defined(MBEDTLS_CIPHER_MODE_CTR)) +static const uint8_t aria_test2_key[32] = +{ + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, // 128 bit + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, // 192 bit + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff // 256 bit +}; + +static const uint8_t aria_test2_pt[48] = +{ + 0x11, 0x11, 0x11, 0x11, 0xaa, 0xaa, 0xaa, 0xaa, // same for all + 0x11, 0x11, 0x11, 0x11, 0xbb, 0xbb, 0xbb, 0xbb, + 0x11, 0x11, 0x11, 0x11, 0xcc, 0xcc, 0xcc, 0xcc, + 0x11, 0x11, 0x11, 0x11, 0xdd, 0xdd, 0xdd, 0xdd, + 0x22, 0x22, 0x22, 0x22, 0xaa, 0xaa, 0xaa, 0xaa, + 0x22, 0x22, 0x22, 0x22, 0xbb, 0xbb, 0xbb, 0xbb, +}; +#endif + +#if (defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB)) +static const uint8_t aria_test2_iv[MBEDTLS_ARIA_BLOCKSIZE] = +{ + 0x0f, 0x1e, 0x2d, 0x3c, 0x4b, 0x5a, 0x69, 0x78, // same for CBC, CFB + 0x87, 0x96, 0xa5, 0xb4, 0xc3, 0xd2, 0xe1, 0xf0 // CTR has zero IV +}; +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const uint8_t aria_test2_cbc_ct[3][48] = // CBC ciphertext +{ + { 0x49, 0xd6, 0x18, 0x60, 0xb1, 0x49, 0x09, 0x10, // 128-bit key + 0x9c, 0xef, 0x0d, 0x22, 0xa9, 0x26, 0x81, 0x34, + 0xfa, 0xdf, 0x9f, 0xb2, 0x31, 0x51, 0xe9, 0x64, + 0x5f, 0xba, 0x75, 0x01, 0x8b, 0xdb, 0x15, 0x38, + 0xb5, 0x33, 0x34, 0x63, 0x4b, 0xbf, 0x7d, 0x4c, + 0xd4, 0xb5, 0x37, 0x70, 0x33, 0x06, 0x0c, 0x15 }, + { 0xaf, 0xe6, 0xcf, 0x23, 0x97, 0x4b, 0x53, 0x3c, // 192-bit key + 0x67, 0x2a, 0x82, 0x62, 0x64, 0xea, 0x78, 0x5f, + 0x4e, 0x4f, 0x7f, 0x78, 0x0d, 0xc7, 0xf3, 0xf1, + 0xe0, 0x96, 0x2b, 0x80, 0x90, 0x23, 0x86, 0xd5, + 0x14, 0xe9, 0xc3, 0xe7, 0x72, 0x59, 0xde, 0x92, + 0xdd, 0x11, 0x02, 0xff, 0xab, 0x08, 0x6c, 0x1e }, + { 0x52, 0x3a, 0x8a, 0x80, 0x6a, 0xe6, 0x21, 0xf1, // 256-bit key + 0x55, 0xfd, 0xd2, 0x8d, 0xbc, 0x34, 0xe1, 0xab, + 0x7b, 0x9b, 0x42, 0x43, 0x2a, 0xd8, 0xb2, 0xef, + 0xb9, 0x6e, 0x23, 0xb1, 0x3f, 0x0a, 0x6e, 0x52, + 0xf3, 0x61, 0x85, 0xd5, 0x0a, 0xd0, 0x02, 0xc5, + 0xf6, 0x01, 0xbe, 0xe5, 0x49, 0x3f, 0x11, 0x8b } +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static const uint8_t aria_test2_cfb_ct[3][48] = // CFB ciphertext +{ + { 0x37, 0x20, 0xe5, 0x3b, 0xa7, 0xd6, 0x15, 0x38, // 128-bit key + 0x34, 0x06, 0xb0, 0x9f, 0x0a, 0x05, 0xa2, 0x00, + 0xc0, 0x7c, 0x21, 0xe6, 0x37, 0x0f, 0x41, 0x3a, + 0x5d, 0x13, 0x25, 0x00, 0xa6, 0x82, 0x85, 0x01, + 0x7c, 0x61, 0xb4, 0x34, 0xc7, 0xb7, 0xca, 0x96, + 0x85, 0xa5, 0x10, 0x71, 0x86, 0x1e, 0x4d, 0x4b }, + { 0x41, 0x71, 0xf7, 0x19, 0x2b, 0xf4, 0x49, 0x54, // 192-bit key + 0x94, 0xd2, 0x73, 0x61, 0x29, 0x64, 0x0f, 0x5c, + 0x4d, 0x87, 0xa9, 0xa2, 0x13, 0x66, 0x4c, 0x94, + 0x48, 0x47, 0x7c, 0x6e, 0xcc, 0x20, 0x13, 0x59, + 0x8d, 0x97, 0x66, 0x95, 0x2d, 0xd8, 0xc3, 0x86, + 0x8f, 0x17, 0xe3, 0x6e, 0xf6, 0x6f, 0xd8, 0x4b }, + { 0x26, 0x83, 0x47, 0x05, 0xb0, 0xf2, 0xc0, 0xe2, // 256-bit key + 0x58, 0x8d, 0x4a, 0x7f, 0x09, 0x00, 0x96, 0x35, + 0xf2, 0x8b, 0xb9, 0x3d, 0x8c, 0x31, 0xf8, 0x70, + 0xec, 0x1e, 0x0b, 0xdb, 0x08, 0x2b, 0x66, 0xfa, + 0x40, 0x2d, 0xd9, 0xc2, 0x02, 0xbe, 0x30, 0x0c, + 0x45, 0x17, 0xd1, 0x96, 0xb1, 0x4d, 0x4c, 0xe1 } +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static const uint8_t aria_test2_ctr_ct[3][48] = // CTR ciphertext +{ + { 0xac, 0x5d, 0x7d, 0xe8, 0x05, 0xa0, 0xbf, 0x1c, // 128-bit key + 0x57, 0xc8, 0x54, 0x50, 0x1a, 0xf6, 0x0f, 0xa1, + 0x14, 0x97, 0xe2, 0xa3, 0x45, 0x19, 0xde, 0xa1, + 0x56, 0x9e, 0x91, 0xe5, 0xb5, 0xcc, 0xae, 0x2f, + 0xf3, 0xbf, 0xa1, 0xbf, 0x97, 0x5f, 0x45, 0x71, + 0xf4, 0x8b, 0xe1, 0x91, 0x61, 0x35, 0x46, 0xc3 }, + { 0x08, 0x62, 0x5c, 0xa8, 0xfe, 0x56, 0x9c, 0x19, // 192-bit key + 0xba, 0x7a, 0xf3, 0x76, 0x0a, 0x6e, 0xd1, 0xce, + 0xf4, 0xd1, 0x99, 0x26, 0x3e, 0x99, 0x9d, 0xde, + 0x14, 0x08, 0x2d, 0xbb, 0xa7, 0x56, 0x0b, 0x79, + 0xa4, 0xc6, 0xb4, 0x56, 0xb8, 0x70, 0x7d, 0xce, + 0x75, 0x1f, 0x98, 0x54, 0xf1, 0x88, 0x93, 0xdf }, + { 0x30, 0x02, 0x6c, 0x32, 0x96, 0x66, 0x14, 0x17, // 256-bit key + 0x21, 0x17, 0x8b, 0x99, 0xc0, 0xa1, 0xf1, 0xb2, + 0xf0, 0x69, 0x40, 0x25, 0x3f, 0x7b, 0x30, 0x89, + 0xe2, 0xa3, 0x0e, 0xa8, 0x6a, 0xa3, 0xc8, 0x8f, + 0x59, 0x40, 0xf0, 0x5a, 0xd7, 0xee, 0x41, 0xd7, + 0x13, 0x47, 0xbb, 0x72, 0x61, 0xe3, 0x48, 0xf1 } +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#define ARIA_SELF_TEST_IF_FAIL \ + { \ + if( verbose ) \ + mbedtls_printf( "failed\n" ); \ + return( 1 ); \ + } else { \ + if( verbose ) \ + mbedtls_printf( "passed\n" ); \ + } + +/* + * Checkup routine + */ +int mbedtls_aria_self_test( int verbose ) +{ + int i; + uint8_t blk[MBEDTLS_ARIA_BLOCKSIZE]; + mbedtls_aria_context ctx; + +#if (defined(MBEDTLS_CIPHER_MODE_CFB) || defined(MBEDTLS_CIPHER_MODE_CTR)) + size_t j; +#endif + +#if (defined(MBEDTLS_CIPHER_MODE_CBC) || \ + defined(MBEDTLS_CIPHER_MODE_CFB) || \ + defined(MBEDTLS_CIPHER_MODE_CTR)) + uint8_t buf[48], iv[MBEDTLS_ARIA_BLOCKSIZE]; +#endif + + /* + * Test set 1 + */ + for( i = 0; i < 3; i++ ) + { + /* test ECB encryption */ + if( verbose ) + mbedtls_printf( " ARIA-ECB-%d (enc): ", 128 + 64 * i ); + mbedtls_aria_setkey_enc( &ctx, aria_test1_ecb_key, 128 + 64 * i ); + mbedtls_aria_crypt_ecb( &ctx, aria_test1_ecb_pt, blk ); + if( memcmp( blk, aria_test1_ecb_ct[i], MBEDTLS_ARIA_BLOCKSIZE ) != 0 ) + ARIA_SELF_TEST_IF_FAIL; + + /* test ECB decryption */ + if( verbose ) + mbedtls_printf( " ARIA-ECB-%d (dec): ", 128 + 64 * i ); + mbedtls_aria_setkey_dec( &ctx, aria_test1_ecb_key, 128 + 64 * i ); + mbedtls_aria_crypt_ecb( &ctx, aria_test1_ecb_ct[i], blk ); + if( memcmp( blk, aria_test1_ecb_pt, MBEDTLS_ARIA_BLOCKSIZE ) != 0 ) + ARIA_SELF_TEST_IF_FAIL; + } + if( verbose ) + mbedtls_printf( "\n" ); + + /* + * Test set 2 + */ +#if defined(MBEDTLS_CIPHER_MODE_CBC) + for( i = 0; i < 3; i++ ) + { + /* Test CBC encryption */ + if( verbose ) + mbedtls_printf( " ARIA-CBC-%d (enc): ", 128 + 64 * i ); + mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i ); + memcpy( iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE ); + memset( buf, 0x55, sizeof( buf ) ); + mbedtls_aria_crypt_cbc( &ctx, MBEDTLS_ARIA_ENCRYPT, 48, iv, + aria_test2_pt, buf ); + if( memcmp( buf, aria_test2_cbc_ct[i], 48 ) != 0 ) + ARIA_SELF_TEST_IF_FAIL; + + /* Test CBC decryption */ + if( verbose ) + mbedtls_printf( " ARIA-CBC-%d (dec): ", 128 + 64 * i ); + mbedtls_aria_setkey_dec( &ctx, aria_test2_key, 128 + 64 * i ); + memcpy( iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE ); + memset( buf, 0xAA, sizeof( buf ) ); + mbedtls_aria_crypt_cbc( &ctx, MBEDTLS_ARIA_DECRYPT, 48, iv, + aria_test2_cbc_ct[i], buf ); + if( memcmp( buf, aria_test2_pt, 48 ) != 0 ) + ARIA_SELF_TEST_IF_FAIL; + } + if( verbose ) + mbedtls_printf( "\n" ); + +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) + for( i = 0; i < 3; i++ ) + { + /* Test CFB encryption */ + if( verbose ) + mbedtls_printf( " ARIA-CFB-%d (enc): ", 128 + 64 * i ); + mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i ); + memcpy( iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE ); + memset( buf, 0x55, sizeof( buf ) ); + j = 0; + mbedtls_aria_crypt_cfb128( &ctx, MBEDTLS_ARIA_ENCRYPT, 48, &j, iv, + aria_test2_pt, buf ); + if( memcmp( buf, aria_test2_cfb_ct[i], 48 ) != 0 ) + ARIA_SELF_TEST_IF_FAIL; + + /* Test CFB decryption */ + if( verbose ) + mbedtls_printf( " ARIA-CFB-%d (dec): ", 128 + 64 * i ); + mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i ); + memcpy( iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE ); + memset( buf, 0xAA, sizeof( buf ) ); + j = 0; + mbedtls_aria_crypt_cfb128( &ctx, MBEDTLS_ARIA_DECRYPT, 48, &j, + iv, aria_test2_cfb_ct[i], buf ); + if( memcmp( buf, aria_test2_pt, 48 ) != 0 ) + ARIA_SELF_TEST_IF_FAIL; + } + if( verbose ) + mbedtls_printf( "\n" ); +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) + for( i = 0; i < 3; i++ ) + { + /* Test CTR encryption */ + if( verbose ) + mbedtls_printf( " ARIA-CTR-%d (enc): ", 128 + 64 * i ); + mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i ); + memset( iv, 0, MBEDTLS_ARIA_BLOCKSIZE ); // IV = 0 + memset( buf, 0x55, sizeof( buf ) ); + j = 0; + mbedtls_aria_crypt_ctr( &ctx, 48, &j, iv, blk, + aria_test2_pt, buf ); + if( memcmp( buf, aria_test2_ctr_ct[i], 48 ) != 0 ) + ARIA_SELF_TEST_IF_FAIL; + + /* Test CTR decryption */ + if( verbose ) + mbedtls_printf( " ARIA-CTR-%d (dec): ", 128 + 64 * i ); + mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i ); + memset( iv, 0, MBEDTLS_ARIA_BLOCKSIZE ); // IV = 0 + memset( buf, 0xAA, sizeof( buf ) ); + j = 0; + mbedtls_aria_crypt_ctr( &ctx, 48, &j, iv, blk, + aria_test2_ctr_ct[i], buf ); + if( memcmp( buf, aria_test2_pt, 48 ) != 0 ) + ARIA_SELF_TEST_IF_FAIL; + } + if( verbose ) + mbedtls_printf( "\n" ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_ARIA_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/asn1parse.c b/Android/Level4/app/src/main/c/mbedtls/library/asn1parse.c new file mode 100644 index 0000000..22747d3 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/asn1parse.c @@ -0,0 +1,481 @@ +/* + * Generic ASN.1 parsing + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 "common.h" + +#if defined(MBEDTLS_ASN1_PARSE_C) + +#include "mbedtls/asn1.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_BIGNUM_C) +#include "mbedtls/bignum.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +/* + * ASN.1 DER decoding routines + */ +int mbedtls_asn1_get_len( unsigned char **p, + const unsigned char *end, + size_t *len ) +{ + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + if( ( **p & 0x80 ) == 0 ) + *len = *(*p)++; + else + { + switch( **p & 0x7F ) + { + case 1: + if( ( end - *p ) < 2 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + *len = (*p)[1]; + (*p) += 2; + break; + + case 2: + if( ( end - *p ) < 3 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + *len = ( (size_t)(*p)[1] << 8 ) | (*p)[2]; + (*p) += 3; + break; + + case 3: + if( ( end - *p ) < 4 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + *len = ( (size_t)(*p)[1] << 16 ) | + ( (size_t)(*p)[2] << 8 ) | (*p)[3]; + (*p) += 4; + break; + + case 4: + if( ( end - *p ) < 5 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + *len = ( (size_t)(*p)[1] << 24 ) | ( (size_t)(*p)[2] << 16 ) | + ( (size_t)(*p)[3] << 8 ) | (*p)[4]; + (*p) += 5; + break; + + default: + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + } + } + + if( *len > (size_t) ( end - *p ) ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + return( 0 ); +} + +int mbedtls_asn1_get_tag( unsigned char **p, + const unsigned char *end, + size_t *len, int tag ) +{ + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + if( **p != tag ) + return( MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + (*p)++; + + return( mbedtls_asn1_get_len( p, end, len ) ); +} + +int mbedtls_asn1_get_bool( unsigned char **p, + const unsigned char *end, + int *val ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_BOOLEAN ) ) != 0 ) + return( ret ); + + if( len != 1 ) + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + + *val = ( **p != 0 ) ? 1 : 0; + (*p)++; + + return( 0 ); +} + +static int asn1_get_tagged_int( unsigned char **p, + const unsigned char *end, + int tag, int *val ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, tag ) ) != 0 ) + return( ret ); + + /* + * len==0 is malformed (0 must be represented as 020100 for INTEGER, + * or 0A0100 for ENUMERATED tags + */ + if( len == 0 ) + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + /* This is a cryptography library. Reject negative integers. */ + if( ( **p & 0x80 ) != 0 ) + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + + /* Skip leading zeros. */ + while( len > 0 && **p == 0 ) + { + ++( *p ); + --len; + } + + /* Reject integers that don't fit in an int. This code assumes that + * the int type has no padding bit. */ + if( len > sizeof( int ) ) + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + if( len == sizeof( int ) && ( **p & 0x80 ) != 0 ) + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + + *val = 0; + while( len-- > 0 ) + { + *val = ( *val << 8 ) | **p; + (*p)++; + } + + return( 0 ); +} + +int mbedtls_asn1_get_int( unsigned char **p, + const unsigned char *end, + int *val ) +{ + return( asn1_get_tagged_int( p, end, MBEDTLS_ASN1_INTEGER, val) ); +} + +int mbedtls_asn1_get_enum( unsigned char **p, + const unsigned char *end, + int *val ) +{ + return( asn1_get_tagged_int( p, end, MBEDTLS_ASN1_ENUMERATED, val) ); +} + +#if defined(MBEDTLS_BIGNUM_C) +int mbedtls_asn1_get_mpi( unsigned char **p, + const unsigned char *end, + mbedtls_mpi *X ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 ) + return( ret ); + + ret = mbedtls_mpi_read_binary( X, *p, len ); + + *p += len; + + return( ret ); +} +#endif /* MBEDTLS_BIGNUM_C */ + +int mbedtls_asn1_get_bitstring( unsigned char **p, const unsigned char *end, + mbedtls_asn1_bitstring *bs) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* Certificate type is a single byte bitstring */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &bs->len, MBEDTLS_ASN1_BIT_STRING ) ) != 0 ) + return( ret ); + + /* Check length, subtract one for actual bit string length */ + if( bs->len < 1 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + bs->len -= 1; + + /* Get number of unused bits, ensure unused bits <= 7 */ + bs->unused_bits = **p; + if( bs->unused_bits > 7 ) + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + (*p)++; + + /* Get actual bitstring */ + bs->p = *p; + *p += bs->len; + + if( *p != end ) + return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * Traverse an ASN.1 "SEQUENCE OF " + * and call a callback for each entry found. + */ +int mbedtls_asn1_traverse_sequence_of( + unsigned char **p, + const unsigned char *end, + unsigned char tag_must_mask, unsigned char tag_must_val, + unsigned char tag_may_mask, unsigned char tag_may_val, + int (*cb)( void *ctx, int tag, + unsigned char *start, size_t len ), + void *ctx ) +{ + int ret; + size_t len; + + /* Get main sequence tag */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( ret ); + } + + if( *p + len != end ) + return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + while( *p < end ) + { + unsigned char const tag = *(*p)++; + + if( ( tag & tag_must_mask ) != tag_must_val ) + return( MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + if( ( ret = mbedtls_asn1_get_len( p, end, &len ) ) != 0 ) + return( ret ); + + if( ( tag & tag_may_mask ) == tag_may_val ) + { + if( cb != NULL ) + { + ret = cb( ctx, tag, *p, len ); + if( ret != 0 ) + return( ret ); + } + } + + *p += len; + } + + return( 0 ); +} + +/* + * Get a bit string without unused bits + */ +int mbedtls_asn1_get_bitstring_null( unsigned char **p, const unsigned char *end, + size_t *len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ( ret = mbedtls_asn1_get_tag( p, end, len, MBEDTLS_ASN1_BIT_STRING ) ) != 0 ) + return( ret ); + + if( *len == 0 ) + return( MBEDTLS_ERR_ASN1_INVALID_DATA ); + --( *len ); + + if( **p != 0 ) + return( MBEDTLS_ERR_ASN1_INVALID_DATA ); + ++( *p ); + + return( 0 ); +} + +void mbedtls_asn1_sequence_free( mbedtls_asn1_sequence *seq ) +{ + while( seq != NULL ) + { + mbedtls_asn1_sequence *next = seq->next; + mbedtls_platform_zeroize( seq, sizeof( *seq ) ); + mbedtls_free( seq ); + seq = next; + } +} + +typedef struct +{ + int tag; + mbedtls_asn1_sequence *cur; +} asn1_get_sequence_of_cb_ctx_t; + +static int asn1_get_sequence_of_cb( void *ctx, + int tag, + unsigned char *start, + size_t len ) +{ + asn1_get_sequence_of_cb_ctx_t *cb_ctx = + (asn1_get_sequence_of_cb_ctx_t *) ctx; + mbedtls_asn1_sequence *cur = + cb_ctx->cur; + + if( cur->buf.p != NULL ) + { + cur->next = + mbedtls_calloc( 1, sizeof( mbedtls_asn1_sequence ) ); + + if( cur->next == NULL ) + return( MBEDTLS_ERR_ASN1_ALLOC_FAILED ); + + cur = cur->next; + } + + cur->buf.p = start; + cur->buf.len = len; + cur->buf.tag = tag; + + cb_ctx->cur = cur; + return( 0 ); +} + +/* + * Parses and splits an ASN.1 "SEQUENCE OF " + */ +int mbedtls_asn1_get_sequence_of( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_sequence *cur, + int tag) +{ + asn1_get_sequence_of_cb_ctx_t cb_ctx = { tag, cur }; + memset( cur, 0, sizeof( mbedtls_asn1_sequence ) ); + return( mbedtls_asn1_traverse_sequence_of( + p, end, 0xFF, tag, 0, 0, + asn1_get_sequence_of_cb, &cb_ctx ) ); +} + +int mbedtls_asn1_get_alg( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( ret ); + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + alg->tag = **p; + end = *p + len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &alg->len, MBEDTLS_ASN1_OID ) ) != 0 ) + return( ret ); + + alg->p = *p; + *p += alg->len; + + if( *p == end ) + { + mbedtls_platform_zeroize( params, sizeof(mbedtls_asn1_buf) ); + return( 0 ); + } + + params->tag = **p; + (*p)++; + + if( ( ret = mbedtls_asn1_get_len( p, end, ¶ms->len ) ) != 0 ) + return( ret ); + + params->p = *p; + *p += params->len; + + if( *p != end ) + return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +int mbedtls_asn1_get_alg_null( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_buf *alg ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_asn1_buf params; + + memset( ¶ms, 0, sizeof(mbedtls_asn1_buf) ); + + if( ( ret = mbedtls_asn1_get_alg( p, end, alg, ¶ms ) ) != 0 ) + return( ret ); + + if( ( params.tag != MBEDTLS_ASN1_NULL && params.tag != 0 ) || params.len != 0 ) + return( MBEDTLS_ERR_ASN1_INVALID_DATA ); + + return( 0 ); +} + +void mbedtls_asn1_free_named_data( mbedtls_asn1_named_data *cur ) +{ + if( cur == NULL ) + return; + + mbedtls_free( cur->oid.p ); + mbedtls_free( cur->val.p ); + + mbedtls_platform_zeroize( cur, sizeof( mbedtls_asn1_named_data ) ); +} + +void mbedtls_asn1_free_named_data_list( mbedtls_asn1_named_data **head ) +{ + mbedtls_asn1_named_data *cur; + + while( ( cur = *head ) != NULL ) + { + *head = cur->next; + mbedtls_asn1_free_named_data( cur ); + mbedtls_free( cur ); + } +} + +mbedtls_asn1_named_data *mbedtls_asn1_find_named_data( mbedtls_asn1_named_data *list, + const char *oid, size_t len ) +{ + while( list != NULL ) + { + if( list->oid.len == len && + memcmp( list->oid.p, oid, len ) == 0 ) + { + break; + } + + list = list->next; + } + + return( list ); +} + +#endif /* MBEDTLS_ASN1_PARSE_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/asn1write.c b/Android/Level4/app/src/main/c/mbedtls/library/asn1write.c new file mode 100644 index 0000000..deb1a2f --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/asn1write.c @@ -0,0 +1,480 @@ +/* + * ASN.1 buffer writing functionality + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 "common.h" + +#if defined(MBEDTLS_ASN1_WRITE_C) + +#include "mbedtls/asn1write.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, size_t len ) +{ + if( len < 0x80 ) + { + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = (unsigned char) len; + return( 1 ); + } + + if( len <= 0xFF ) + { + if( *p - start < 2 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = (unsigned char) len; + *--(*p) = 0x81; + return( 2 ); + } + + if( len <= 0xFFFF ) + { + if( *p - start < 3 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = ( len ) & 0xFF; + *--(*p) = ( len >> 8 ) & 0xFF; + *--(*p) = 0x82; + return( 3 ); + } + + if( len <= 0xFFFFFF ) + { + if( *p - start < 4 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = ( len ) & 0xFF; + *--(*p) = ( len >> 8 ) & 0xFF; + *--(*p) = ( len >> 16 ) & 0xFF; + *--(*p) = 0x83; + return( 4 ); + } + +#if SIZE_MAX > 0xFFFFFFFF + if( len <= 0xFFFFFFFF ) +#endif + { + if( *p - start < 5 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = ( len ) & 0xFF; + *--(*p) = ( len >> 8 ) & 0xFF; + *--(*p) = ( len >> 16 ) & 0xFF; + *--(*p) = ( len >> 24 ) & 0xFF; + *--(*p) = 0x84; + return( 5 ); + } + +#if SIZE_MAX > 0xFFFFFFFF + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); +#endif +} + +int mbedtls_asn1_write_tag( unsigned char **p, unsigned char *start, unsigned char tag ) +{ + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = tag; + + return( 1 ); +} + +int mbedtls_asn1_write_raw_buffer( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t size ) +{ + size_t len = 0; + + if( *p < start || (size_t)( *p - start ) < size ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + len = size; + (*p) -= len; + memcpy( *p, buf, len ); + + return( (int) len ); +} + +#if defined(MBEDTLS_BIGNUM_C) +int mbedtls_asn1_write_mpi( unsigned char **p, unsigned char *start, const mbedtls_mpi *X ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + // Write the MPI + // + len = mbedtls_mpi_size( X ); + + if( *p < start || (size_t)( *p - start ) < len ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + (*p) -= len; + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( X, *p, len ) ); + + // DER format assumes 2s complement for numbers, so the leftmost bit + // should be 0 for positive numbers and 1 for negative numbers. + // + if( X->s ==1 && **p & 0x80 ) + { + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = 0x00; + len += 1; + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_INTEGER ) ); + + ret = (int) len; + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_BIGNUM_C */ + +int mbedtls_asn1_write_null( unsigned char **p, unsigned char *start ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + // Write NULL + // + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, 0) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_NULL ) ); + + return( (int) len ); +} + +int mbedtls_asn1_write_oid( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, + (const unsigned char *) oid, oid_len ) ); + MBEDTLS_ASN1_CHK_ADD( len , mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len , mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OID ) ); + + return( (int) len ); +} + +int mbedtls_asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len, + size_t par_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + if( par_len == 0 ) + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_null( p, start ) ); + else + len += par_len; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); + + return( (int) len ); +} + +int mbedtls_asn1_write_bool( unsigned char **p, unsigned char *start, int boolean ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = (boolean) ? 255 : 0; + len++; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BOOLEAN ) ); + + return( (int) len ); +} + +static int asn1_write_tagged_int( unsigned char **p, unsigned char *start, int val, int tag ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + do + { + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + len += 1; + *--(*p) = val & 0xff; + val >>= 8; + } + while( val > 0 ); + + if( **p & 0x80 ) + { + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + *--(*p) = 0x00; + len += 1; + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, tag ) ); + + return( (int) len ); +} + +int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val ) +{ + return( asn1_write_tagged_int( p, start, val, MBEDTLS_ASN1_INTEGER ) ); +} + +int mbedtls_asn1_write_enum( unsigned char **p, unsigned char *start, int val ) +{ + return( asn1_write_tagged_int( p, start, val, MBEDTLS_ASN1_ENUMERATED ) ); +} + +int mbedtls_asn1_write_tagged_string( unsigned char **p, unsigned char *start, int tag, + const char *text, size_t text_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, + (const unsigned char *) text, text_len ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, tag ) ); + + return( (int) len ); +} + +int mbedtls_asn1_write_utf8_string( unsigned char **p, unsigned char *start, + const char *text, size_t text_len ) +{ + return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_UTF8_STRING, text, text_len) ); +} + +int mbedtls_asn1_write_printable_string( unsigned char **p, unsigned char *start, + const char *text, size_t text_len ) +{ + return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_PRINTABLE_STRING, text, text_len) ); +} + +int mbedtls_asn1_write_ia5_string( unsigned char **p, unsigned char *start, + const char *text, size_t text_len ) +{ + return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_IA5_STRING, text, text_len) ); +} + +int mbedtls_asn1_write_named_bitstring( unsigned char **p, + unsigned char *start, + const unsigned char *buf, + size_t bits ) +{ + size_t unused_bits, byte_len; + const unsigned char *cur_byte; + unsigned char cur_byte_shifted; + unsigned char bit; + + byte_len = ( bits + 7 ) / 8; + unused_bits = ( byte_len * 8 ) - bits; + + /* + * Named bitstrings require that trailing 0s are excluded in the encoding + * of the bitstring. Trailing 0s are considered part of the 'unused' bits + * when encoding this value in the first content octet + */ + if( bits != 0 ) + { + cur_byte = buf + byte_len - 1; + cur_byte_shifted = *cur_byte >> unused_bits; + + for( ; ; ) + { + bit = cur_byte_shifted & 0x1; + cur_byte_shifted >>= 1; + + if( bit != 0 ) + break; + + bits--; + if( bits == 0 ) + break; + + if( bits % 8 == 0 ) + cur_byte_shifted = *--cur_byte; + } + } + + return( mbedtls_asn1_write_bitstring( p, start, buf, bits ) ); +} + +int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t bits ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + size_t unused_bits, byte_len; + + byte_len = ( bits + 7 ) / 8; + unused_bits = ( byte_len * 8 ) - bits; + + if( *p < start || (size_t)( *p - start ) < byte_len + 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + len = byte_len + 1; + + /* Write the bitstring. Ensure the unused bits are zeroed */ + if( byte_len > 0 ) + { + byte_len--; + *--( *p ) = buf[byte_len] & ~( ( 0x1 << unused_bits ) - 1 ); + ( *p ) -= byte_len; + memcpy( *p, buf, byte_len ); + } + + /* Write unused bits */ + *--( *p ) = (unsigned char)unused_bits; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BIT_STRING ) ); + + return( (int) len ); +} + +int mbedtls_asn1_write_octet_string( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t size ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, buf, size ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OCTET_STRING ) ); + + return( (int) len ); +} + + +/* This is a copy of the ASN.1 parsing function mbedtls_asn1_find_named_data(), + * which is replicated to avoid a dependency ASN1_WRITE_C on ASN1_PARSE_C. */ +static mbedtls_asn1_named_data *asn1_find_named_data( + mbedtls_asn1_named_data *list, + const char *oid, size_t len ) +{ + while( list != NULL ) + { + if( list->oid.len == len && + memcmp( list->oid.p, oid, len ) == 0 ) + { + break; + } + + list = list->next; + } + + return( list ); +} + +mbedtls_asn1_named_data *mbedtls_asn1_store_named_data( + mbedtls_asn1_named_data **head, + const char *oid, size_t oid_len, + const unsigned char *val, + size_t val_len ) +{ + mbedtls_asn1_named_data *cur; + + if( ( cur = asn1_find_named_data( *head, oid, oid_len ) ) == NULL ) + { + // Add new entry if not present yet based on OID + // + cur = (mbedtls_asn1_named_data*)mbedtls_calloc( 1, + sizeof(mbedtls_asn1_named_data) ); + if( cur == NULL ) + return( NULL ); + + cur->oid.len = oid_len; + cur->oid.p = mbedtls_calloc( 1, oid_len ); + if( cur->oid.p == NULL ) + { + mbedtls_free( cur ); + return( NULL ); + } + + memcpy( cur->oid.p, oid, oid_len ); + + cur->val.len = val_len; + if( val_len != 0 ) + { + cur->val.p = mbedtls_calloc( 1, val_len ); + if( cur->val.p == NULL ) + { + mbedtls_free( cur->oid.p ); + mbedtls_free( cur ); + return( NULL ); + } + } + + cur->next = *head; + *head = cur; + } + else if( val_len == 0 ) + { + mbedtls_free( cur->val.p ); + cur->val.p = NULL; + } + else if( cur->val.len != val_len ) + { + /* + * Enlarge existing value buffer if needed + * Preserve old data until the allocation succeeded, to leave list in + * a consistent state in case allocation fails. + */ + void *p = mbedtls_calloc( 1, val_len ); + if( p == NULL ) + return( NULL ); + + mbedtls_free( cur->val.p ); + cur->val.p = p; + cur->val.len = val_len; + } + + if( val != NULL ) + memcpy( cur->val.p, val, val_len ); + + return( cur ); +} +#endif /* MBEDTLS_ASN1_WRITE_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/base64.c b/Android/Level4/app/src/main/c/mbedtls/library/base64.c new file mode 100644 index 0000000..d39474a --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/base64.c @@ -0,0 +1,287 @@ +/* + * RFC 1521 base64 encoding/decoding + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 "common.h" + +#if defined(MBEDTLS_BASE64_C) + +#include "mbedtls/base64.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#include +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +static const unsigned char base64_enc_map[64] = +{ + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', + 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', + 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', + 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', '+', '/' +}; + +static const unsigned char base64_dec_map[128] = +{ + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 62, 127, 127, 127, 63, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 61, 127, 127, + 127, 64, 127, 127, 127, 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, 127, 127, 127, 127, 127, 127, 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, 127, 127, 127, 127, 127 +}; + +#define BASE64_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */ + +/* + * Encode a buffer into base64 format + */ +int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen, + const unsigned char *src, size_t slen ) +{ + size_t i, n; + int C1, C2, C3; + unsigned char *p; + + if( slen == 0 ) + { + *olen = 0; + return( 0 ); + } + + n = slen / 3 + ( slen % 3 != 0 ); + + if( n > ( BASE64_SIZE_T_MAX - 1 ) / 4 ) + { + *olen = BASE64_SIZE_T_MAX; + return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); + } + + n *= 4; + + if( ( dlen < n + 1 ) || ( NULL == dst ) ) + { + *olen = n + 1; + return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); + } + + n = ( slen / 3 ) * 3; + + for( i = 0, p = dst; i < n; i += 3 ) + { + C1 = *src++; + C2 = *src++; + C3 = *src++; + + *p++ = base64_enc_map[(C1 >> 2) & 0x3F]; + *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F]; + *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F]; + *p++ = base64_enc_map[C3 & 0x3F]; + } + + if( i < slen ) + { + C1 = *src++; + C2 = ( ( i + 1 ) < slen ) ? *src++ : 0; + + *p++ = base64_enc_map[(C1 >> 2) & 0x3F]; + *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F]; + + if( ( i + 1 ) < slen ) + *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F]; + else *p++ = '='; + + *p++ = '='; + } + + *olen = p - dst; + *p = 0; + + return( 0 ); +} + +/* + * Decode a base64-formatted buffer + */ +int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen, + const unsigned char *src, size_t slen ) +{ + size_t i, n; + uint32_t j, x; + unsigned char *p; + + /* First pass: check for validity and get output length */ + for( i = n = j = 0; i < slen; i++ ) + { + /* Skip spaces before checking for EOL */ + x = 0; + while( i < slen && src[i] == ' ' ) + { + ++i; + ++x; + } + + /* Spaces at end of buffer are OK */ + if( i == slen ) + break; + + if( ( slen - i ) >= 2 && + src[i] == '\r' && src[i + 1] == '\n' ) + continue; + + if( src[i] == '\n' ) + continue; + + /* Space inside a line is an error */ + if( x != 0 ) + return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); + + if( src[i] == '=' && ++j > 2 ) + return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); + + if( src[i] > 127 || base64_dec_map[src[i]] == 127 ) + return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); + + if( base64_dec_map[src[i]] < 64 && j != 0 ) + return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); + + n++; + } + + if( n == 0 ) + { + *olen = 0; + return( 0 ); + } + + /* The following expression is to calculate the following formula without + * risk of integer overflow in n: + * n = ( ( n * 6 ) + 7 ) >> 3; + */ + n = ( 6 * ( n >> 3 ) ) + ( ( 6 * ( n & 0x7 ) + 7 ) >> 3 ); + n -= j; + + if( dst == NULL || dlen < n ) + { + *olen = n; + return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); + } + + for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ ) + { + if( *src == '\r' || *src == '\n' || *src == ' ' ) + continue; + + j -= ( base64_dec_map[*src] == 64 ); + x = ( x << 6 ) | ( base64_dec_map[*src] & 0x3F ); + + if( ++n == 4 ) + { + n = 0; + if( j > 0 ) *p++ = (unsigned char)( x >> 16 ); + if( j > 1 ) *p++ = (unsigned char)( x >> 8 ); + if( j > 2 ) *p++ = (unsigned char)( x ); + } + } + + *olen = p - dst; + + return( 0 ); +} + +#if defined(MBEDTLS_SELF_TEST) + +static const unsigned char base64_test_dec[64] = +{ + 0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD, + 0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01, + 0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09, + 0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13, + 0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31, + 0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38, + 0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B, + 0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97 +}; + +static const unsigned char base64_test_enc[] = + "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK" + "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw=="; + +/* + * Checkup routine + */ +int mbedtls_base64_self_test( int verbose ) +{ + size_t len; + const unsigned char *src; + unsigned char buffer[128]; + + if( verbose != 0 ) + mbedtls_printf( " Base64 encoding test: " ); + + src = base64_test_dec; + + if( mbedtls_base64_encode( buffer, sizeof( buffer ), &len, src, 64 ) != 0 || + memcmp( base64_test_enc, buffer, 88 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n Base64 decoding test: " ); + + src = base64_test_enc; + + if( mbedtls_base64_decode( buffer, sizeof( buffer ), &len, src, 88 ) != 0 || + memcmp( base64_test_dec, buffer, 64 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_BASE64_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/bignum.c b/Android/Level4/app/src/main/c/mbedtls/library/bignum.c new file mode 100644 index 0000000..fa97d19 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/bignum.c @@ -0,0 +1,3010 @@ +/* + * Multi-precision integer library + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ + +/* + * The following sources were referenced in the design of this Multi-precision + * Integer library: + * + * [1] Handbook of Applied Cryptography - 1997 + * Menezes, van Oorschot and Vanstone + * + * [2] Multi-Precision Math + * Tom St Denis + * https://github.com/libtom/libtommath/blob/develop/tommath.pdf + * + * [3] GNU Multi-Precision Arithmetic Library + * https://gmplib.org/manual/index.html + * + */ + +#include "common.h" + +#if defined(MBEDTLS_BIGNUM_C) + +#include "mbedtls/bignum.h" +#include "mbedtls/bn_mul.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#define MPI_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA ) +#define MPI_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */ +#define biL (ciL << 3) /* bits in limb */ +#define biH (ciL << 2) /* half limb size */ + +#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */ + +/* + * Convert between bits/chars and number of limbs + * Divide first in order to avoid potential overflows + */ +#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) ) +#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) ) + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n ) +{ + mbedtls_platform_zeroize( v, ciL * n ); +} + +/* + * Initialize one MPI + */ +void mbedtls_mpi_init( mbedtls_mpi *X ) +{ + MPI_VALIDATE( X != NULL ); + + X->s = 1; + X->n = 0; + X->p = NULL; +} + +/* + * Unallocate one MPI + */ +void mbedtls_mpi_free( mbedtls_mpi *X ) +{ + if( X == NULL ) + return; + + if( X->p != NULL ) + { + mbedtls_mpi_zeroize( X->p, X->n ); + mbedtls_free( X->p ); + } + + X->s = 1; + X->n = 0; + X->p = NULL; +} + +/* + * Enlarge to the specified number of limbs + */ +int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs ) +{ + mbedtls_mpi_uint *p; + MPI_VALIDATE_RET( X != NULL ); + + if( nblimbs > MBEDTLS_MPI_MAX_LIMBS ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + + if( X->n < nblimbs ) + { + if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + + if( X->p != NULL ) + { + memcpy( p, X->p, X->n * ciL ); + mbedtls_mpi_zeroize( X->p, X->n ); + mbedtls_free( X->p ); + } + + X->n = nblimbs; + X->p = p; + } + + return( 0 ); +} + +/* + * Resize down as much as possible, + * while keeping at least the specified number of limbs + */ +int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs ) +{ + mbedtls_mpi_uint *p; + size_t i; + MPI_VALIDATE_RET( X != NULL ); + + if( nblimbs > MBEDTLS_MPI_MAX_LIMBS ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + + /* Actually resize up if there are currently fewer than nblimbs limbs. */ + if( X->n <= nblimbs ) + return( mbedtls_mpi_grow( X, nblimbs ) ); + /* After this point, then X->n > nblimbs and in particular X->n > 0. */ + + for( i = X->n - 1; i > 0; i-- ) + if( X->p[i] != 0 ) + break; + i++; + + if( i < nblimbs ) + i = nblimbs; + + if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + + if( X->p != NULL ) + { + memcpy( p, X->p, i * ciL ); + mbedtls_mpi_zeroize( X->p, X->n ); + mbedtls_free( X->p ); + } + + X->n = i; + X->p = p; + + return( 0 ); +} + +/* + * Copy the contents of Y into X + */ +int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y ) +{ + int ret = 0; + size_t i; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( Y != NULL ); + + if( X == Y ) + return( 0 ); + + if( Y->n == 0 ) + { + mbedtls_mpi_free( X ); + return( 0 ); + } + + for( i = Y->n - 1; i > 0; i-- ) + if( Y->p[i] != 0 ) + break; + i++; + + X->s = Y->s; + + if( X->n < i ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) ); + } + else + { + memset( X->p + i, 0, ( X->n - i ) * ciL ); + } + + memcpy( X->p, Y->p, i * ciL ); + +cleanup: + + return( ret ); +} + +/* + * Swap the contents of X and Y + */ +void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y ) +{ + mbedtls_mpi T; + MPI_VALIDATE( X != NULL ); + MPI_VALIDATE( Y != NULL ); + + memcpy( &T, X, sizeof( mbedtls_mpi ) ); + memcpy( X, Y, sizeof( mbedtls_mpi ) ); + memcpy( Y, &T, sizeof( mbedtls_mpi ) ); +} + +/* + * Conditionally assign dest = src, without leaking information + * about whether the assignment was made or not. + * dest and src must be arrays of limbs of size n. + * assign must be 0 or 1. + */ +static void mpi_safe_cond_assign( size_t n, + mbedtls_mpi_uint *dest, + const mbedtls_mpi_uint *src, + unsigned char assign ) +{ + size_t i; + for( i = 0; i < n; i++ ) + dest[i] = dest[i] * ( 1 - assign ) + src[i] * assign; +} + +/* + * Conditionally assign X = Y, without leaking information + * about whether the assignment was made or not. + * (Leaking information about the respective sizes of X and Y is ok however.) + */ +int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign ) +{ + int ret = 0; + size_t i; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( Y != NULL ); + + /* make sure assign is 0 or 1 in a time-constant manner */ + assign = (assign | (unsigned char)-assign) >> 7; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) ); + + X->s = X->s * ( 1 - assign ) + Y->s * assign; + + mpi_safe_cond_assign( Y->n, X->p, Y->p, assign ); + + for( i = Y->n; i < X->n; i++ ) + X->p[i] *= ( 1 - assign ); + +cleanup: + return( ret ); +} + +/* + * Conditionally swap X and Y, without leaking information + * about whether the swap was made or not. + * Here it is not ok to simply swap the pointers, which whould lead to + * different memory access patterns when X and Y are used afterwards. + */ +int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap ) +{ + int ret, s; + size_t i; + mbedtls_mpi_uint tmp; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( Y != NULL ); + + if( X == Y ) + return( 0 ); + + /* make sure swap is 0 or 1 in a time-constant manner */ + swap = (swap | (unsigned char)-swap) >> 7; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) ); + + s = X->s; + X->s = X->s * ( 1 - swap ) + Y->s * swap; + Y->s = Y->s * ( 1 - swap ) + s * swap; + + + for( i = 0; i < X->n; i++ ) + { + tmp = X->p[i]; + X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap; + Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap; + } + +cleanup: + return( ret ); +} + +/* + * Set value from integer + */ +int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + MPI_VALIDATE_RET( X != NULL ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) ); + memset( X->p, 0, X->n * ciL ); + + X->p[0] = ( z < 0 ) ? -z : z; + X->s = ( z < 0 ) ? -1 : 1; + +cleanup: + + return( ret ); +} + +/* + * Get a specific bit + */ +int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos ) +{ + MPI_VALIDATE_RET( X != NULL ); + + if( X->n * biL <= pos ) + return( 0 ); + + return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 ); +} + +/* Get a specific byte, without range checks. */ +#define GET_BYTE( X, i ) \ + ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff ) + +/* + * Set a bit to a specific value of 0 or 1 + */ +int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val ) +{ + int ret = 0; + size_t off = pos / biL; + size_t idx = pos % biL; + MPI_VALIDATE_RET( X != NULL ); + + if( val != 0 && val != 1 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + if( X->n * biL <= pos ) + { + if( val == 0 ) + return( 0 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) ); + } + + X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx ); + X->p[off] |= (mbedtls_mpi_uint) val << idx; + +cleanup: + + return( ret ); +} + +/* + * Return the number of less significant zero-bits + */ +size_t mbedtls_mpi_lsb( const mbedtls_mpi *X ) +{ + size_t i, j, count = 0; + MBEDTLS_INTERNAL_VALIDATE_RET( X != NULL, 0 ); + + for( i = 0; i < X->n; i++ ) + for( j = 0; j < biL; j++, count++ ) + if( ( ( X->p[i] >> j ) & 1 ) != 0 ) + return( count ); + + return( 0 ); +} + +/* + * Count leading zero bits in a given integer + */ +static size_t mbedtls_clz( const mbedtls_mpi_uint x ) +{ + size_t j; + mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1); + + for( j = 0; j < biL; j++ ) + { + if( x & mask ) break; + + mask >>= 1; + } + + return j; +} + +/* + * Return the number of bits + */ +size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X ) +{ + size_t i, j; + + if( X->n == 0 ) + return( 0 ); + + for( i = X->n - 1; i > 0; i-- ) + if( X->p[i] != 0 ) + break; + + j = biL - mbedtls_clz( X->p[i] ); + + return( ( i * biL ) + j ); +} + +/* + * Return the total size in bytes + */ +size_t mbedtls_mpi_size( const mbedtls_mpi *X ) +{ + return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 ); +} + +/* + * Convert an ASCII character to digit value + */ +static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c ) +{ + *d = 255; + + if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30; + if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37; + if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57; + + if( *d >= (mbedtls_mpi_uint) radix ) + return( MBEDTLS_ERR_MPI_INVALID_CHARACTER ); + + return( 0 ); +} + +/* + * Import from an ASCII string + */ +int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i, j, slen, n; + mbedtls_mpi_uint d; + mbedtls_mpi T; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( s != NULL ); + + if( radix < 2 || radix > 16 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &T ); + + slen = strlen( s ); + + if( radix == 16 ) + { + if( slen > MPI_SIZE_T_MAX >> 2 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + n = BITS_TO_LIMBS( slen << 2 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); + + for( i = slen, j = 0; i > 0; i--, j++ ) + { + if( i == 1 && s[i - 1] == '-' ) + { + X->s = -1; + break; + } + + MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) ); + X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 ); + } + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); + + for( i = 0; i < slen; i++ ) + { + if( i == 0 && s[i] == '-' ) + { + X->s = -1; + continue; + } + + MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) ); + + if( X->s == 1 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) ); + } + } + } + +cleanup: + + mbedtls_mpi_free( &T ); + + return( ret ); +} + +/* + * Helper to write the digits high-order first. + */ +static int mpi_write_hlp( mbedtls_mpi *X, int radix, + char **p, const size_t buflen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi_uint r; + size_t length = 0; + char *p_end = *p + buflen; + + do + { + if( length >= buflen ) + { + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) ); + /* + * Write the residue in the current position, as an ASCII character. + */ + if( r < 0xA ) + *(--p_end) = (char)( '0' + r ); + else + *(--p_end) = (char)( 'A' + ( r - 0xA ) ); + + length++; + } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 ); + + memmove( *p, p_end, length ); + *p += length; + +cleanup: + + return( ret ); +} + +/* + * Export into an ASCII string + */ +int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix, + char *buf, size_t buflen, size_t *olen ) +{ + int ret = 0; + size_t n; + char *p; + mbedtls_mpi T; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( olen != NULL ); + MPI_VALIDATE_RET( buflen == 0 || buf != NULL ); + + if( radix < 2 || radix > 16 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */ + if( radix >= 4 ) n >>= 1; /* Number of 4-adic digits necessary to present + * `n`. If radix > 4, this might be a strict + * overapproximation of the number of + * radix-adic digits needed to present `n`. */ + if( radix >= 16 ) n >>= 1; /* Number of hexadecimal digits necessary to + * present `n`. */ + + n += 1; /* Terminating null byte */ + n += 1; /* Compensate for the divisions above, which round down `n` + * in case it's not even. */ + n += 1; /* Potential '-'-sign. */ + n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing, + * which always uses an even number of hex-digits. */ + + if( buflen < n ) + { + *olen = n; + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + } + + p = buf; + mbedtls_mpi_init( &T ); + + if( X->s == -1 ) + { + *p++ = '-'; + buflen--; + } + + if( radix == 16 ) + { + int c; + size_t i, j, k; + + for( i = X->n, k = 0; i > 0; i-- ) + { + for( j = ciL; j > 0; j-- ) + { + c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF; + + if( c == 0 && k == 0 && ( i + j ) != 2 ) + continue; + + *(p++) = "0123456789ABCDEF" [c / 16]; + *(p++) = "0123456789ABCDEF" [c % 16]; + k = 1; + } + } + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) ); + + if( T.s == -1 ) + T.s = 1; + + MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) ); + } + + *p++ = '\0'; + *olen = p - buf; + +cleanup: + + mbedtls_mpi_free( &T ); + + return( ret ); +} + +#if defined(MBEDTLS_FS_IO) +/* + * Read X from an opened file + */ +int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin ) +{ + mbedtls_mpi_uint d; + size_t slen; + char *p; + /* + * Buffer should have space for (short) label and decimal formatted MPI, + * newline characters and '\0' + */ + char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ]; + + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( fin != NULL ); + + if( radix < 2 || radix > 16 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + memset( s, 0, sizeof( s ) ); + if( fgets( s, sizeof( s ) - 1, fin ) == NULL ) + return( MBEDTLS_ERR_MPI_FILE_IO_ERROR ); + + slen = strlen( s ); + if( slen == sizeof( s ) - 2 ) + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + + if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; } + if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; } + + p = s + slen; + while( p-- > s ) + if( mpi_get_digit( &d, radix, *p ) != 0 ) + break; + + return( mbedtls_mpi_read_string( X, radix, p + 1 ) ); +} + +/* + * Write X into an opened file (or stdout if fout == NULL) + */ +int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n, slen, plen; + /* + * Buffer should have space for (short) label and decimal formatted MPI, + * newline characters and '\0' + */ + char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ]; + MPI_VALIDATE_RET( X != NULL ); + + if( radix < 2 || radix > 16 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + memset( s, 0, sizeof( s ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) ); + + if( p == NULL ) p = ""; + + plen = strlen( p ); + slen = strlen( s ); + s[slen++] = '\r'; + s[slen++] = '\n'; + + if( fout != NULL ) + { + if( fwrite( p, 1, plen, fout ) != plen || + fwrite( s, 1, slen, fout ) != slen ) + return( MBEDTLS_ERR_MPI_FILE_IO_ERROR ); + } + else + mbedtls_printf( "%s%s", p, s ); + +cleanup: + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + + +/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint + * into the storage form used by mbedtls_mpi. */ + +static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c( mbedtls_mpi_uint x ) +{ + uint8_t i; + unsigned char *x_ptr; + mbedtls_mpi_uint tmp = 0; + + for( i = 0, x_ptr = (unsigned char*) &x; i < ciL; i++, x_ptr++ ) + { + tmp <<= CHAR_BIT; + tmp |= (mbedtls_mpi_uint) *x_ptr; + } + + return( tmp ); +} + +static mbedtls_mpi_uint mpi_uint_bigendian_to_host( mbedtls_mpi_uint x ) +{ +#if defined(__BYTE_ORDER__) + +/* Nothing to do on bigendian systems. */ +#if ( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ) + return( x ); +#endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */ + +#if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ ) + +/* For GCC and Clang, have builtins for byte swapping. */ +#if defined(__GNUC__) && defined(__GNUC_PREREQ) +#if __GNUC_PREREQ(4,3) +#define have_bswap +#endif +#endif + +#if defined(__clang__) && defined(__has_builtin) +#if __has_builtin(__builtin_bswap32) && \ + __has_builtin(__builtin_bswap64) +#define have_bswap +#endif +#endif + +#if defined(have_bswap) + /* The compiler is hopefully able to statically evaluate this! */ + switch( sizeof(mbedtls_mpi_uint) ) + { + case 4: + return( __builtin_bswap32(x) ); + case 8: + return( __builtin_bswap64(x) ); + } +#endif +#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */ +#endif /* __BYTE_ORDER__ */ + + /* Fall back to C-based reordering if we don't know the byte order + * or we couldn't use a compiler-specific builtin. */ + return( mpi_uint_bigendian_to_host_c( x ) ); +} + +static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs ) +{ + mbedtls_mpi_uint *cur_limb_left; + mbedtls_mpi_uint *cur_limb_right; + if( limbs == 0 ) + return; + + /* + * Traverse limbs and + * - adapt byte-order in each limb + * - swap the limbs themselves. + * For that, simultaneously traverse the limbs from left to right + * and from right to left, as long as the left index is not bigger + * than the right index (it's not a problem if limbs is odd and the + * indices coincide in the last iteration). + */ + for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 ); + cur_limb_left <= cur_limb_right; + cur_limb_left++, cur_limb_right-- ) + { + mbedtls_mpi_uint tmp; + /* Note that if cur_limb_left == cur_limb_right, + * this code effectively swaps the bytes only once. */ + tmp = mpi_uint_bigendian_to_host( *cur_limb_left ); + *cur_limb_left = mpi_uint_bigendian_to_host( *cur_limb_right ); + *cur_limb_right = tmp; + } +} + +/* + * Import X from unsigned binary data, little endian + */ +int mbedtls_mpi_read_binary_le( mbedtls_mpi *X, + const unsigned char *buf, size_t buflen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i; + size_t const limbs = CHARS_TO_LIMBS( buflen ); + + /* Ensure that target MPI has exactly the necessary number of limbs */ + if( X->n != limbs ) + { + mbedtls_mpi_free( X ); + mbedtls_mpi_init( X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); + + for( i = 0; i < buflen; i++ ) + X->p[i / ciL] |= ((mbedtls_mpi_uint) buf[i]) << ((i % ciL) << 3); + +cleanup: + + /* + * This function is also used to import keys. However, wiping the buffers + * upon failure is not necessary because failure only can happen before any + * input is copied. + */ + return( ret ); +} + +/* + * Import X from unsigned binary data, big endian + */ +int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t const limbs = CHARS_TO_LIMBS( buflen ); + size_t const overhead = ( limbs * ciL ) - buflen; + unsigned char *Xp; + + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( buflen == 0 || buf != NULL ); + + /* Ensure that target MPI has exactly the necessary number of limbs */ + if( X->n != limbs ) + { + mbedtls_mpi_free( X ); + mbedtls_mpi_init( X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) ); + } + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); + + /* Avoid calling `memcpy` with NULL source argument, + * even if buflen is 0. */ + if( buf != NULL ) + { + Xp = (unsigned char*) X->p; + memcpy( Xp + overhead, buf, buflen ); + + mpi_bigendian_to_host( X->p, limbs ); + } + +cleanup: + + /* + * This function is also used to import keys. However, wiping the buffers + * upon failure is not necessary because failure only can happen before any + * input is copied. + */ + return( ret ); +} + +/* + * Export X into unsigned binary data, little endian + */ +int mbedtls_mpi_write_binary_le( const mbedtls_mpi *X, + unsigned char *buf, size_t buflen ) +{ + size_t stored_bytes = X->n * ciL; + size_t bytes_to_copy; + size_t i; + + if( stored_bytes < buflen ) + { + bytes_to_copy = stored_bytes; + } + else + { + bytes_to_copy = buflen; + + /* The output buffer is smaller than the allocated size of X. + * However X may fit if its leading bytes are zero. */ + for( i = bytes_to_copy; i < stored_bytes; i++ ) + { + if( GET_BYTE( X, i ) != 0 ) + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + } + } + + for( i = 0; i < bytes_to_copy; i++ ) + buf[i] = GET_BYTE( X, i ); + + if( stored_bytes < buflen ) + { + /* Write trailing 0 bytes */ + memset( buf + stored_bytes, 0, buflen - stored_bytes ); + } + + return( 0 ); +} + +/* + * Export X into unsigned binary data, big endian + */ +int mbedtls_mpi_write_binary( const mbedtls_mpi *X, + unsigned char *buf, size_t buflen ) +{ + size_t stored_bytes; + size_t bytes_to_copy; + unsigned char *p; + size_t i; + + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( buflen == 0 || buf != NULL ); + + stored_bytes = X->n * ciL; + + if( stored_bytes < buflen ) + { + /* There is enough space in the output buffer. Write initial + * null bytes and record the position at which to start + * writing the significant bytes. In this case, the execution + * trace of this function does not depend on the value of the + * number. */ + bytes_to_copy = stored_bytes; + p = buf + buflen - stored_bytes; + memset( buf, 0, buflen - stored_bytes ); + } + else + { + /* The output buffer is smaller than the allocated size of X. + * However X may fit if its leading bytes are zero. */ + bytes_to_copy = buflen; + p = buf; + for( i = bytes_to_copy; i < stored_bytes; i++ ) + { + if( GET_BYTE( X, i ) != 0 ) + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + } + } + + for( i = 0; i < bytes_to_copy; i++ ) + p[bytes_to_copy - i - 1] = GET_BYTE( X, i ); + + return( 0 ); +} + +/* + * Left-shift: X <<= count + */ +int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i, v0, t1; + mbedtls_mpi_uint r0 = 0, r1; + MPI_VALIDATE_RET( X != NULL ); + + v0 = count / (biL ); + t1 = count & (biL - 1); + + i = mbedtls_mpi_bitlen( X ) + count; + + if( X->n * biL < i ) + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) ); + + ret = 0; + + /* + * shift by count / limb_size + */ + if( v0 > 0 ) + { + for( i = X->n; i > v0; i-- ) + X->p[i - 1] = X->p[i - v0 - 1]; + + for( ; i > 0; i-- ) + X->p[i - 1] = 0; + } + + /* + * shift by count % limb_size + */ + if( t1 > 0 ) + { + for( i = v0; i < X->n; i++ ) + { + r1 = X->p[i] >> (biL - t1); + X->p[i] <<= t1; + X->p[i] |= r0; + r0 = r1; + } + } + +cleanup: + + return( ret ); +} + +/* + * Right-shift: X >>= count + */ +int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count ) +{ + size_t i, v0, v1; + mbedtls_mpi_uint r0 = 0, r1; + MPI_VALIDATE_RET( X != NULL ); + + v0 = count / biL; + v1 = count & (biL - 1); + + if( v0 > X->n || ( v0 == X->n && v1 > 0 ) ) + return mbedtls_mpi_lset( X, 0 ); + + /* + * shift by count / limb_size + */ + if( v0 > 0 ) + { + for( i = 0; i < X->n - v0; i++ ) + X->p[i] = X->p[i + v0]; + + for( ; i < X->n; i++ ) + X->p[i] = 0; + } + + /* + * shift by count % limb_size + */ + if( v1 > 0 ) + { + for( i = X->n; i > 0; i-- ) + { + r1 = X->p[i - 1] << (biL - v1); + X->p[i - 1] >>= v1; + X->p[i - 1] |= r0; + r0 = r1; + } + } + + return( 0 ); +} + +/* + * Compare unsigned values + */ +int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y ) +{ + size_t i, j; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( Y != NULL ); + + for( i = X->n; i > 0; i-- ) + if( X->p[i - 1] != 0 ) + break; + + for( j = Y->n; j > 0; j-- ) + if( Y->p[j - 1] != 0 ) + break; + + if( i == 0 && j == 0 ) + return( 0 ); + + if( i > j ) return( 1 ); + if( j > i ) return( -1 ); + + for( ; i > 0; i-- ) + { + if( X->p[i - 1] > Y->p[i - 1] ) return( 1 ); + if( X->p[i - 1] < Y->p[i - 1] ) return( -1 ); + } + + return( 0 ); +} + +/* + * Compare signed values + */ +int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y ) +{ + size_t i, j; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( Y != NULL ); + + for( i = X->n; i > 0; i-- ) + if( X->p[i - 1] != 0 ) + break; + + for( j = Y->n; j > 0; j-- ) + if( Y->p[j - 1] != 0 ) + break; + + if( i == 0 && j == 0 ) + return( 0 ); + + if( i > j ) return( X->s ); + if( j > i ) return( -Y->s ); + + if( X->s > 0 && Y->s < 0 ) return( 1 ); + if( Y->s > 0 && X->s < 0 ) return( -1 ); + + for( ; i > 0; i-- ) + { + if( X->p[i - 1] > Y->p[i - 1] ) return( X->s ); + if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s ); + } + + return( 0 ); +} + +/** Decide if an integer is less than the other, without branches. + * + * \param x First integer. + * \param y Second integer. + * + * \return 1 if \p x is less than \p y, 0 otherwise + */ +static unsigned ct_lt_mpi_uint( const mbedtls_mpi_uint x, + const mbedtls_mpi_uint y ) +{ + mbedtls_mpi_uint ret; + mbedtls_mpi_uint cond; + + /* + * Check if the most significant bits (MSB) of the operands are different. + */ + cond = ( x ^ y ); + /* + * If the MSB are the same then the difference x-y will be negative (and + * have its MSB set to 1 during conversion to unsigned) if and only if x> ( biL - 1 ); + + return (unsigned) ret; +} + +/* + * Compare signed values in constant time + */ +int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y, + unsigned *ret ) +{ + size_t i; + /* The value of any of these variables is either 0 or 1 at all times. */ + unsigned cond, done, X_is_negative, Y_is_negative; + + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( Y != NULL ); + MPI_VALIDATE_RET( ret != NULL ); + + if( X->n != Y->n ) + return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + + /* + * Set sign_N to 1 if N >= 0, 0 if N < 0. + * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0. + */ + X_is_negative = ( X->s & 2 ) >> 1; + Y_is_negative = ( Y->s & 2 ) >> 1; + + /* + * If the signs are different, then the positive operand is the bigger. + * That is if X is negative (X_is_negative == 1), then X < Y is true and it + * is false if X is positive (X_is_negative == 0). + */ + cond = ( X_is_negative ^ Y_is_negative ); + *ret = cond & X_is_negative; + + /* + * This is a constant-time function. We might have the result, but we still + * need to go through the loop. Record if we have the result already. + */ + done = cond; + + for( i = X->n; i > 0; i-- ) + { + /* + * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both + * X and Y are negative. + * + * Again even if we can make a decision, we just mark the result and + * the fact that we are done and continue looping. + */ + cond = ct_lt_mpi_uint( Y->p[i - 1], X->p[i - 1] ); + *ret |= cond & ( 1 - done ) & X_is_negative; + done |= cond; + + /* + * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both + * X and Y are positive. + * + * Again even if we can make a decision, we just mark the result and + * the fact that we are done and continue looping. + */ + cond = ct_lt_mpi_uint( X->p[i - 1], Y->p[i - 1] ); + *ret |= cond & ( 1 - done ) & ( 1 - X_is_negative ); + done |= cond; + } + + return( 0 ); +} + +/* + * Compare signed values + */ +int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z ) +{ + mbedtls_mpi Y; + mbedtls_mpi_uint p[1]; + MPI_VALIDATE_RET( X != NULL ); + + *p = ( z < 0 ) ? -z : z; + Y.s = ( z < 0 ) ? -1 : 1; + Y.n = 1; + Y.p = p; + + return( mbedtls_mpi_cmp_mpi( X, &Y ) ); +} + +/* + * Unsigned addition: X = |A| + |B| (HAC 14.7) + */ +int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i, j; + mbedtls_mpi_uint *o, *p, c, tmp; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + + if( X == B ) + { + const mbedtls_mpi *T = A; A = X; B = T; + } + + if( X != A ) + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) ); + + /* + * X should always be positive as a result of unsigned additions. + */ + X->s = 1; + + for( j = B->n; j > 0; j-- ) + if( B->p[j - 1] != 0 ) + break; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) ); + + o = B->p; p = X->p; c = 0; + + /* + * tmp is used because it might happen that p == o + */ + for( i = 0; i < j; i++, o++, p++ ) + { + tmp= *o; + *p += c; c = ( *p < c ); + *p += tmp; c += ( *p < tmp ); + } + + while( c != 0 ) + { + if( i >= X->n ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) ); + p = X->p + i; + } + + *p += c; c = ( *p < c ); i++; p++; + } + +cleanup: + + return( ret ); +} + +/** + * Helper for mbedtls_mpi subtraction. + * + * Calculate d - s where d and s have the same size. + * This function operates modulo (2^ciL)^n and returns the carry + * (1 if there was a wraparound, i.e. if `d < s`, and 0 otherwise). + * + * \param n Number of limbs of \p d and \p s. + * \param[in,out] d On input, the left operand. + * On output, the result of the subtraction: + * \param[in] s The right operand. + * + * \return 1 if `d < s`. + * 0 if `d >= s`. + */ +static mbedtls_mpi_uint mpi_sub_hlp( size_t n, + mbedtls_mpi_uint *d, + const mbedtls_mpi_uint *s ) +{ + size_t i; + mbedtls_mpi_uint c, z; + + for( i = c = 0; i < n; i++, s++, d++ ) + { + z = ( *d < c ); *d -= c; + c = ( *d < *s ) + z; *d -= *s; + } + + return( c ); +} + +/* + * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10) + */ +int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + mbedtls_mpi TB; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n; + mbedtls_mpi_uint carry; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + + mbedtls_mpi_init( &TB ); + + if( X == B ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); + B = &TB; + } + + if( X != A ) + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) ); + + /* + * X should always be positive as a result of unsigned subtractions. + */ + X->s = 1; + + ret = 0; + + for( n = B->n; n > 0; n-- ) + if( B->p[n - 1] != 0 ) + break; + + carry = mpi_sub_hlp( n, X->p, B->p ); + if( carry != 0 ) + { + /* Propagate the carry to the first nonzero limb of X. */ + for( ; n < X->n && X->p[n] == 0; n++ ) + --X->p[n]; + /* If we ran out of space for the carry, it means that the result + * is negative. */ + if( n == X->n ) + return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); + --X->p[n]; + } + +cleanup: + + mbedtls_mpi_free( &TB ); + + return( ret ); +} + +/* + * Signed addition: X = A + B + */ +int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret, s; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + + s = A->s; + if( A->s * B->s < 0 ) + { + if( mbedtls_mpi_cmp_abs( A, B ) >= 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) ); + X->s = s; + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) ); + X->s = -s; + } + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) ); + X->s = s; + } + +cleanup: + + return( ret ); +} + +/* + * Signed subtraction: X = A - B + */ +int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret, s; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + + s = A->s; + if( A->s * B->s > 0 ) + { + if( mbedtls_mpi_cmp_abs( A, B ) >= 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) ); + X->s = s; + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) ); + X->s = -s; + } + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) ); + X->s = s; + } + +cleanup: + + return( ret ); +} + +/* + * Signed addition: X = A + b + */ +int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ) +{ + mbedtls_mpi _B; + mbedtls_mpi_uint p[1]; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + + p[0] = ( b < 0 ) ? -b : b; + _B.s = ( b < 0 ) ? -1 : 1; + _B.n = 1; + _B.p = p; + + return( mbedtls_mpi_add_mpi( X, A, &_B ) ); +} + +/* + * Signed subtraction: X = A - b + */ +int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ) +{ + mbedtls_mpi _B; + mbedtls_mpi_uint p[1]; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + + p[0] = ( b < 0 ) ? -b : b; + _B.s = ( b < 0 ) ? -1 : 1; + _B.n = 1; + _B.p = p; + + return( mbedtls_mpi_sub_mpi( X, A, &_B ) ); +} + +/* + * Helper for mbedtls_mpi multiplication + */ +static +#if defined(__APPLE__) && defined(__arm__) +/* + * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn) + * appears to need this to prevent bad ARM code generation at -O3. + */ +__attribute__ ((noinline)) +#endif +void mpi_mul_hlp( size_t i, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d, mbedtls_mpi_uint b ) +{ + mbedtls_mpi_uint c = 0, t = 0; + +#if defined(MULADDC_HUIT) + for( ; i >= 8; i -= 8 ) + { + MULADDC_INIT + MULADDC_HUIT + MULADDC_STOP + } + + for( ; i > 0; i-- ) + { + MULADDC_INIT + MULADDC_CORE + MULADDC_STOP + } +#else /* MULADDC_HUIT */ + for( ; i >= 16; i -= 16 ) + { + MULADDC_INIT + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_STOP + } + + for( ; i >= 8; i -= 8 ) + { + MULADDC_INIT + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_STOP + } + + for( ; i > 0; i-- ) + { + MULADDC_INIT + MULADDC_CORE + MULADDC_STOP + } +#endif /* MULADDC_HUIT */ + + t++; + + do { + *d += c; c = ( *d < c ); d++; + } + while( c != 0 ); +} + +/* + * Baseline multiplication: X = A * B (HAC 14.12) + */ +int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i, j; + mbedtls_mpi TA, TB; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + + mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB ); + + if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; } + if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; } + + for( i = A->n; i > 0; i-- ) + if( A->p[i - 1] != 0 ) + break; + + for( j = B->n; j > 0; j-- ) + if( B->p[j - 1] != 0 ) + break; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); + + for( ; j > 0; j-- ) + mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] ); + + X->s = A->s * B->s; + +cleanup: + + mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA ); + + return( ret ); +} + +/* + * Baseline multiplication: X = A * b + */ +int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b ) +{ + mbedtls_mpi _B; + mbedtls_mpi_uint p[1]; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + + _B.s = 1; + _B.n = 1; + _B.p = p; + p[0] = b; + + return( mbedtls_mpi_mul_mpi( X, A, &_B ) ); +} + +/* + * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and + * mbedtls_mpi_uint divisor, d + */ +static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1, + mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r ) +{ +#if defined(MBEDTLS_HAVE_UDBL) + mbedtls_t_udbl dividend, quotient; +#else + const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH; + const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1; + mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient; + mbedtls_mpi_uint u0_msw, u0_lsw; + size_t s; +#endif + + /* + * Check for overflow + */ + if( 0 == d || u1 >= d ) + { + if (r != NULL) *r = ~0; + + return ( ~0 ); + } + +#if defined(MBEDTLS_HAVE_UDBL) + dividend = (mbedtls_t_udbl) u1 << biL; + dividend |= (mbedtls_t_udbl) u0; + quotient = dividend / d; + if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 ) + quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1; + + if( r != NULL ) + *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) ); + + return (mbedtls_mpi_uint) quotient; +#else + + /* + * Algorithm D, Section 4.3.1 - The Art of Computer Programming + * Vol. 2 - Seminumerical Algorithms, Knuth + */ + + /* + * Normalize the divisor, d, and dividend, u0, u1 + */ + s = mbedtls_clz( d ); + d = d << s; + + u1 = u1 << s; + u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) ); + u0 = u0 << s; + + d1 = d >> biH; + d0 = d & uint_halfword_mask; + + u0_msw = u0 >> biH; + u0_lsw = u0 & uint_halfword_mask; + + /* + * Find the first quotient and remainder + */ + q1 = u1 / d1; + r0 = u1 - d1 * q1; + + while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) ) + { + q1 -= 1; + r0 += d1; + + if ( r0 >= radix ) break; + } + + rAX = ( u1 * radix ) + ( u0_msw - q1 * d ); + q0 = rAX / d1; + r0 = rAX - q0 * d1; + + while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) ) + { + q0 -= 1; + r0 += d1; + + if ( r0 >= radix ) break; + } + + if (r != NULL) + *r = ( rAX * radix + u0_lsw - q0 * d ) >> s; + + quotient = q1 * radix + q0; + + return quotient; +#endif +} + +/* + * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20) + */ +int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, + const mbedtls_mpi *B ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i, n, t, k; + mbedtls_mpi X, Y, Z, T1, T2; + mbedtls_mpi_uint TP2[3]; + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + + if( mbedtls_mpi_cmp_int( B, 0 ) == 0 ) + return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO ); + + mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z ); + mbedtls_mpi_init( &T1 ); + /* + * Avoid dynamic memory allocations for constant-size T2. + * + * T2 is used for comparison only and the 3 limbs are assigned explicitly, + * so nobody increase the size of the MPI and we're safe to use an on-stack + * buffer. + */ + T2.s = 1; + T2.n = sizeof( TP2 ) / sizeof( *TP2 ); + T2.p = TP2; + + if( mbedtls_mpi_cmp_abs( A, B ) < 0 ) + { + if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) ); + if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) ); + return( 0 ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) ); + X.s = Y.s = 1; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) ); + + k = mbedtls_mpi_bitlen( &Y ) % biL; + if( k < biL - 1 ) + { + k = biL - 1 - k; + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) ); + } + else k = 0; + + n = X.n - 1; + t = Y.n - 1; + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) ); + + while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 ) + { + Z.p[n - t]++; + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) ); + } + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) ); + + for( i = n; i > t ; i-- ) + { + if( X.p[i] >= Y.p[t] ) + Z.p[i - t - 1] = ~0; + else + { + Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1], + Y.p[t], NULL); + } + + T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2]; + T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1]; + T2.p[2] = X.p[i]; + + Z.p[i - t - 1]++; + do + { + Z.p[i - t - 1]--; + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) ); + T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1]; + T1.p[1] = Y.p[t]; + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) ); + } + while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) ); + + if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) ); + Z.p[i - t - 1]--; + } + } + + if( Q != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) ); + Q->s = A->s * B->s; + } + + if( R != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) ); + X.s = A->s; + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) ); + + if( mbedtls_mpi_cmp_int( R, 0 ) == 0 ) + R->s = 1; + } + +cleanup: + + mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z ); + mbedtls_mpi_free( &T1 ); + mbedtls_platform_zeroize( TP2, sizeof( TP2 ) ); + + return( ret ); +} + +/* + * Division by int: A = Q * b + R + */ +int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, + const mbedtls_mpi *A, + mbedtls_mpi_sint b ) +{ + mbedtls_mpi _B; + mbedtls_mpi_uint p[1]; + MPI_VALIDATE_RET( A != NULL ); + + p[0] = ( b < 0 ) ? -b : b; + _B.s = ( b < 0 ) ? -1 : 1; + _B.n = 1; + _B.p = p; + + return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) ); +} + +/* + * Modulo: R = A mod B + */ +int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + MPI_VALIDATE_RET( R != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + + if( mbedtls_mpi_cmp_int( B, 0 ) < 0 ) + return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) ); + + while( mbedtls_mpi_cmp_int( R, 0 ) < 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) ); + + while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) ); + +cleanup: + + return( ret ); +} + +/* + * Modulo: r = A mod b + */ +int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b ) +{ + size_t i; + mbedtls_mpi_uint x, y, z; + MPI_VALIDATE_RET( r != NULL ); + MPI_VALIDATE_RET( A != NULL ); + + if( b == 0 ) + return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO ); + + if( b < 0 ) + return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); + + /* + * handle trivial cases + */ + if( b == 1 ) + { + *r = 0; + return( 0 ); + } + + if( b == 2 ) + { + *r = A->p[0] & 1; + return( 0 ); + } + + /* + * general case + */ + for( i = A->n, y = 0; i > 0; i-- ) + { + x = A->p[i - 1]; + y = ( y << biH ) | ( x >> biH ); + z = y / b; + y -= z * b; + + x <<= biH; + y = ( y << biH ) | ( x >> biH ); + z = y / b; + y -= z * b; + } + + /* + * If A is negative, then the current y represents a negative value. + * Flipping it to the positive side. + */ + if( A->s < 0 && y != 0 ) + y = b - y; + + *r = y; + + return( 0 ); +} + +/* + * Fast Montgomery initialization (thanks to Tom St Denis) + */ +static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N ) +{ + mbedtls_mpi_uint x, m0 = N->p[0]; + unsigned int i; + + x = m0; + x += ( ( m0 + 2 ) & 4 ) << 1; + + for( i = biL; i >= 8; i /= 2 ) + x *= ( 2 - ( m0 * x ) ); + + *mm = ~x + 1; +} + +/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36) + * + * \param[in,out] A One of the numbers to multiply. + * It must have at least as many limbs as N + * (A->n >= N->n), and any limbs beyond n are ignored. + * On successful completion, A contains the result of + * the multiplication A * B * R^-1 mod N where + * R = (2^ciL)^n. + * \param[in] B One of the numbers to multiply. + * It must be nonzero and must not have more limbs than N + * (B->n <= N->n). + * \param[in] N The modulo. N must be odd. + * \param mm The value calculated by `mpi_montg_init(&mm, N)`. + * This is -N^-1 mod 2^ciL. + * \param[in,out] T A bignum for temporary storage. + * It must be at least twice the limb size of N plus 2 + * (T->n >= 2 * (N->n + 1)). + * Its initial content is unused and + * its final content is indeterminate. + * Note that unlike the usual convention in the library + * for `const mbedtls_mpi*`, the content of T can change. + */ +static void mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm, + const mbedtls_mpi *T ) +{ + size_t i, n, m; + mbedtls_mpi_uint u0, u1, *d; + + memset( T->p, 0, T->n * ciL ); + + d = T->p; + n = N->n; + m = ( B->n < n ) ? B->n : n; + + for( i = 0; i < n; i++ ) + { + /* + * T = (T + u0*B + u1*N) / 2^biL + */ + u0 = A->p[i]; + u1 = ( d[0] + u0 * B->p[0] ) * mm; + + mpi_mul_hlp( m, B->p, d, u0 ); + mpi_mul_hlp( n, N->p, d, u1 ); + + *d++ = u0; d[n + 1] = 0; + } + + /* At this point, d is either the desired result or the desired result + * plus N. We now potentially subtract N, avoiding leaking whether the + * subtraction is performed through side channels. */ + + /* Copy the n least significant limbs of d to A, so that + * A = d if d < N (recall that N has n limbs). */ + memcpy( A->p, d, n * ciL ); + /* If d >= N then we want to set A to d - N. To prevent timing attacks, + * do the calculation without using conditional tests. */ + /* Set d to d0 + (2^biL)^n - N where d0 is the current value of d. */ + d[n] += 1; + d[n] -= mpi_sub_hlp( n, d, N->p ); + /* If d0 < N then d < (2^biL)^n + * so d[n] == 0 and we want to keep A as it is. + * If d0 >= N then d >= (2^biL)^n, and d <= (2^biL)^n + N < 2 * (2^biL)^n + * so d[n] == 1 and we want to set A to the result of the subtraction + * which is d - (2^biL)^n, i.e. the n least significant limbs of d. + * This exactly corresponds to a conditional assignment. */ + mpi_safe_cond_assign( n, A->p, d, (unsigned char) d[n] ); +} + +/* + * Montgomery reduction: A = A * R^-1 mod N + * + * See mpi_montmul() regarding constraints and guarantees on the parameters. + */ +static void mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, + mbedtls_mpi_uint mm, const mbedtls_mpi *T ) +{ + mbedtls_mpi_uint z = 1; + mbedtls_mpi U; + + U.n = U.s = (int) z; + U.p = &z; + + mpi_montmul( A, &U, N, mm, T ); +} + +/* + * Sliding-window exponentiation: X = A^E mod N (HAC 14.85) + */ +int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *E, const mbedtls_mpi *N, + mbedtls_mpi *_RR ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t wbits, wsize, one = 1; + size_t i, j, nblimbs; + size_t bufsize, nbits; + mbedtls_mpi_uint ei, mm, state; + mbedtls_mpi RR, T, W[ 1 << MBEDTLS_MPI_WINDOW_SIZE ], Apos; + int neg; + + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( E != NULL ); + MPI_VALIDATE_RET( N != NULL ); + + if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + if( mbedtls_mpi_cmp_int( E, 0 ) < 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + /* + * Init temps and window size + */ + mpi_montg_init( &mm, N ); + mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T ); + mbedtls_mpi_init( &Apos ); + memset( W, 0, sizeof( W ) ); + + i = mbedtls_mpi_bitlen( E ); + + wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 : + ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1; + +#if( MBEDTLS_MPI_WINDOW_SIZE < 6 ) + if( wsize > MBEDTLS_MPI_WINDOW_SIZE ) + wsize = MBEDTLS_MPI_WINDOW_SIZE; +#endif + + j = N->n + 1; + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) ); + + /* + * Compensate for negative A (and correct at the end) + */ + neg = ( A->s == -1 ); + if( neg ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) ); + Apos.s = 1; + A = &Apos; + } + + /* + * If 1st call, pre-compute R^2 mod N + */ + if( _RR == NULL || _RR->p == NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) ); + + if( _RR != NULL ) + memcpy( _RR, &RR, sizeof( mbedtls_mpi ) ); + } + else + memcpy( &RR, _RR, sizeof( mbedtls_mpi ) ); + + /* + * W[1] = A * R^2 * R^-1 mod N = A * R mod N + */ + if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) ); + else + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) ); + + mpi_montmul( &W[1], &RR, N, mm, &T ); + + /* + * X = R^2 * R^-1 mod N = R mod N + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) ); + mpi_montred( X, N, mm, &T ); + + if( wsize > 1 ) + { + /* + * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1) + */ + j = one << ( wsize - 1 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) ); + + for( i = 0; i < wsize - 1; i++ ) + mpi_montmul( &W[j], &W[j], N, mm, &T ); + + /* + * W[i] = W[i - 1] * W[1] + */ + for( i = j + 1; i < ( one << wsize ); i++ ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) ); + + mpi_montmul( &W[i], &W[1], N, mm, &T ); + } + } + + nblimbs = E->n; + bufsize = 0; + nbits = 0; + wbits = 0; + state = 0; + + while( 1 ) + { + if( bufsize == 0 ) + { + if( nblimbs == 0 ) + break; + + nblimbs--; + + bufsize = sizeof( mbedtls_mpi_uint ) << 3; + } + + bufsize--; + + ei = (E->p[nblimbs] >> bufsize) & 1; + + /* + * skip leading 0s + */ + if( ei == 0 && state == 0 ) + continue; + + if( ei == 0 && state == 1 ) + { + /* + * out of window, square X + */ + mpi_montmul( X, X, N, mm, &T ); + continue; + } + + /* + * add ei to current window + */ + state = 2; + + nbits++; + wbits |= ( ei << ( wsize - nbits ) ); + + if( nbits == wsize ) + { + /* + * X = X^wsize R^-1 mod N + */ + for( i = 0; i < wsize; i++ ) + mpi_montmul( X, X, N, mm, &T ); + + /* + * X = X * W[wbits] R^-1 mod N + */ + mpi_montmul( X, &W[wbits], N, mm, &T ); + + state--; + nbits = 0; + wbits = 0; + } + } + + /* + * process the remaining bits + */ + for( i = 0; i < nbits; i++ ) + { + mpi_montmul( X, X, N, mm, &T ); + + wbits <<= 1; + + if( ( wbits & ( one << wsize ) ) != 0 ) + mpi_montmul( X, &W[1], N, mm, &T ); + } + + /* + * X = A^E * R * R^-1 mod N = A^E mod N + */ + mpi_montred( X, N, mm, &T ); + + if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 ) + { + X->s = -1; + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) ); + } + +cleanup: + + for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ ) + mbedtls_mpi_free( &W[i] ); + + mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos ); + + if( _RR == NULL || _RR->p == NULL ) + mbedtls_mpi_free( &RR ); + + return( ret ); +} + +/* + * Greatest common divisor: G = gcd(A, B) (HAC 14.54) + */ +int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t lz, lzt; + mbedtls_mpi TA, TB; + + MPI_VALIDATE_RET( G != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + + mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); + + lz = mbedtls_mpi_lsb( &TA ); + lzt = mbedtls_mpi_lsb( &TB ); + + if( lzt < lz ) + lz = lzt; + + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) ); + + TA.s = TB.s = 1; + + while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) ); + + if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) ); + } + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) ); + +cleanup: + + mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB ); + + return( ret ); +} + +/* + * Fill X with size bytes of random. + * + * Use a temporary bytes representation to make sure the result is the same + * regardless of the platform endianness (useful when f_rng is actually + * deterministic, eg for tests). + */ +int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t const limbs = CHARS_TO_LIMBS( size ); + size_t const overhead = ( limbs * ciL ) - size; + unsigned char *Xp; + + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( f_rng != NULL ); + + /* Ensure that target MPI has exactly the necessary number of limbs */ + if( X->n != limbs ) + { + mbedtls_mpi_free( X ); + mbedtls_mpi_init( X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) ); + } + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); + + Xp = (unsigned char*) X->p; + f_rng( p_rng, Xp + overhead, size ); + + mpi_bigendian_to_host( X->p, limbs ); + +cleanup: + return( ret ); +} + +/* + * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64) + */ +int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( N != NULL ); + + if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 ); + mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV ); + mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) ); + + if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 ) + { + ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) ); + + do + { + while( ( TU.p[0] & 1 ) == 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) ); + + if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) ); + } + + while( ( TV.p[0] & 1 ) == 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) ); + + if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) ); + } + + if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) ); + } + } + while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 ); + + while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) ); + + while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) ); + +cleanup: + + mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 ); + mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV ); + mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 ); + + return( ret ); +} + +#if defined(MBEDTLS_GENPRIME) + +static const int small_prime[] = +{ + 3, 5, 7, 11, 13, 17, 19, 23, + 29, 31, 37, 41, 43, 47, 53, 59, + 61, 67, 71, 73, 79, 83, 89, 97, + 101, 103, 107, 109, 113, 127, 131, 137, + 139, 149, 151, 157, 163, 167, 173, 179, + 181, 191, 193, 197, 199, 211, 223, 227, + 229, 233, 239, 241, 251, 257, 263, 269, + 271, 277, 281, 283, 293, 307, 311, 313, + 317, 331, 337, 347, 349, 353, 359, 367, + 373, 379, 383, 389, 397, 401, 409, 419, + 421, 431, 433, 439, 443, 449, 457, 461, + 463, 467, 479, 487, 491, 499, 503, 509, + 521, 523, 541, 547, 557, 563, 569, 571, + 577, 587, 593, 599, 601, 607, 613, 617, + 619, 631, 641, 643, 647, 653, 659, 661, + 673, 677, 683, 691, 701, 709, 719, 727, + 733, 739, 743, 751, 757, 761, 769, 773, + 787, 797, 809, 811, 821, 823, 827, 829, + 839, 853, 857, 859, 863, 877, 881, 883, + 887, 907, 911, 919, 929, 937, 941, 947, + 953, 967, 971, 977, 983, 991, 997, -103 +}; + +/* + * Small divisors test (X must be positive) + * + * Return values: + * 0: no small factor (possible prime, more tests needed) + * 1: certain prime + * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime + * other negative: error + */ +static int mpi_check_small_factors( const mbedtls_mpi *X ) +{ + int ret = 0; + size_t i; + mbedtls_mpi_uint r; + + if( ( X->p[0] & 1 ) == 0 ) + return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); + + for( i = 0; small_prime[i] > 0; i++ ) + { + if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 ) + return( 1 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) ); + + if( r == 0 ) + return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); + } + +cleanup: + return( ret ); +} + +/* + * Miller-Rabin pseudo-primality test (HAC 4.24) + */ +static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret, count; + size_t i, j, k, s; + mbedtls_mpi W, R, T, A, RR; + + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( f_rng != NULL ); + + mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); + mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A ); + mbedtls_mpi_init( &RR ); + + /* + * W = |X| - 1 + * R = W >> lsb( W ) + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) ); + s = mbedtls_mpi_lsb( &W ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) ); + + for( i = 0; i < rounds; i++ ) + { + /* + * pick a random A, 1 < A < |X| - 1 + */ + count = 0; + do { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) ); + + j = mbedtls_mpi_bitlen( &A ); + k = mbedtls_mpi_bitlen( &W ); + if (j > k) { + A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1; + } + + if (count++ > 30) { + ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + goto cleanup; + } + + } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 || + mbedtls_mpi_cmp_int( &A, 1 ) <= 0 ); + + /* + * A = A^R mod |X| + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) ); + + if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 || + mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) + continue; + + j = 1; + while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ) + { + /* + * A = A * A mod |X| + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) ); + + if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) + break; + + j++; + } + + /* + * not prime if A != |X| - 1 or A == 1 + */ + if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 || + mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) + { + ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + break; + } + } + +cleanup: + mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); + mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A ); + mbedtls_mpi_free( &RR ); + + return( ret ); +} + +/* + * Pseudo-primality test: small factors, then Miller-Rabin + */ +int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi XX; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( f_rng != NULL ); + + XX.s = 1; + XX.n = X->n; + XX.p = X->p; + + if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 || + mbedtls_mpi_cmp_int( &XX, 1 ) == 0 ) + return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); + + if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 ) + return( 0 ); + + if( ( ret = mpi_check_small_factors( &XX ) ) != 0 ) + { + if( ret == 1 ) + return( 0 ); + + return( ret ); + } + + return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +/* + * Pseudo-primality test, error probability 2^-80 + */ +int mbedtls_mpi_is_prime( const mbedtls_mpi *X, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( f_rng != NULL ); + + /* + * In the past our key generation aimed for an error rate of at most + * 2^-80. Since this function is deprecated, aim for the same certainty + * here as well. + */ + return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) ); +} +#endif + +/* + * Prime number generation + * + * To generate an RSA key in a way recommended by FIPS 186-4, both primes must + * be either 1024 bits or 1536 bits long, and flags must contain + * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR. + */ +int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ +#ifdef MBEDTLS_HAVE_INT64 +// ceil(2^63.5) +#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL +#else +// ceil(2^31.5) +#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U +#endif + int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + size_t k, n; + int rounds; + mbedtls_mpi_uint r; + mbedtls_mpi Y; + + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( f_rng != NULL ); + + if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &Y ); + + n = BITS_TO_LIMBS( nbits ); + + if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 ) + { + /* + * 2^-80 error probability, number of rounds chosen per HAC, table 4.4 + */ + rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 : + ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 : + ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 ); + } + else + { + /* + * 2^-100 error probability, number of rounds computed based on HAC, + * fact 4.48 + */ + rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 : + ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 : + ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 : + ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 ); + } + + while( 1 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) ); + /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */ + if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue; + + k = n * biL; + if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) ); + X->p[0] |= 1; + + if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 ) + { + ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng ); + + if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) + goto cleanup; + } + else + { + /* + * An necessary condition for Y and X = 2Y + 1 to be prime + * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3). + * Make sure it is satisfied, while keeping X = 3 mod 4 + */ + + X->p[0] |= 2; + + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) ); + if( r == 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) ); + else if( r == 1 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) ); + + /* Set Y = (X-1) / 2, which is X / 2 because X is odd */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) ); + + while( 1 ) + { + /* + * First, check small factors for X and Y + * before doing Miller-Rabin on any of them + */ + if( ( ret = mpi_check_small_factors( X ) ) == 0 && + ( ret = mpi_check_small_factors( &Y ) ) == 0 && + ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) ) + == 0 && + ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) ) + == 0 ) + goto cleanup; + + if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) + goto cleanup; + + /* + * Next candidates. We want to preserve Y = (X-1) / 2 and + * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3) + * so up Y by 6 and X by 12. + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) ); + } + } + } + +cleanup: + + mbedtls_mpi_free( &Y ); + + return( ret ); +} + +#endif /* MBEDTLS_GENPRIME */ + +#if defined(MBEDTLS_SELF_TEST) + +#define GCD_PAIR_COUNT 3 + +static const int gcd_pairs[GCD_PAIR_COUNT][3] = +{ + { 693, 609, 21 }, + { 1764, 868, 28 }, + { 768454923, 542167814, 1 } +}; + +/* + * Checkup routine + */ +int mbedtls_mpi_self_test( int verbose ) +{ + int ret, i; + mbedtls_mpi A, E, N, X, Y, U, V; + + mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X ); + mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16, + "EFE021C2645FD1DC586E69184AF4A31E" \ + "D5F53E93B5F123FA41680867BA110131" \ + "944FE7952E2517337780CB0DB80E61AA" \ + "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16, + "B2E7EFD37075B9F03FF989C7C5051C20" \ + "34D2A323810251127E7BF8625A4F49A5" \ + "F3E27F4DA8BD59C47D6DAABA4C8127BD" \ + "5B5C25763222FEFCCFC38B832366C29E" ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16, + "0066A198186C18C10B2F5ED9B522752A" \ + "9830B69916E535C8F047518A889A43A5" \ + "94B6BED27A168D31D4A52F88925AA8F5" ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, + "602AB7ECA597A3D6B56FF9829A5E8B85" \ + "9E857EA95A03512E2BAE7391688D264A" \ + "A5663B0341DB9CCFD2C4C5F421FEC814" \ + "8001B72E848A38CAE1C65F78E56ABDEF" \ + "E12D3C039B8A02D6BE593F0BBBDA56F1" \ + "ECF677152EF804370C1A305CAF3B5BF1" \ + "30879B56C61DE584A0F53A2447A51E" ) ); + + if( verbose != 0 ) + mbedtls_printf( " MPI test #1 (mul_mpi): " ); + + if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, + "256567336059E52CAE22925474705F39A94" ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16, + "6613F26162223DF488E9CD48CC132C7A" \ + "0AC93C701B001B092E4E5B9F73BCD27B" \ + "9EE50D0657C77F374E903CDFA4C642" ) ); + + if( verbose != 0 ) + mbedtls_printf( " MPI test #2 (div_mpi): " ); + + if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 || + mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, + "36E139AEA55215609D2816998ED020BB" \ + "BD96C37890F65171D948E9BC7CBAA4D9" \ + "325D24D6A3C12710F10A09FA08AB87" ) ); + + if( verbose != 0 ) + mbedtls_printf( " MPI test #3 (exp_mod): " ); + + if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, + "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \ + "C3DBA76456363A10869622EAC2DD84EC" \ + "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) ); + + if( verbose != 0 ) + mbedtls_printf( " MPI test #4 (inv_mod): " ); + + if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " MPI test #5 (simple gcd): " ); + + for( i = 0; i < GCD_PAIR_COUNT; i++ ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) ); + + if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed at %d\n", i ); + + ret = 1; + goto cleanup; + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + +cleanup: + + if( ret != 0 && verbose != 0 ) + mbedtls_printf( "Unexpected error, return code = %08X\n", (unsigned int) ret ); + + mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X ); + mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V ); + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_BIGNUM_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/blowfish.c b/Android/Level4/app/src/main/c/mbedtls/library/blowfish.c new file mode 100644 index 0000000..76da448 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/blowfish.c @@ -0,0 +1,690 @@ +/* + * Blowfish implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ +/* + * The Blowfish block cipher was designed by Bruce Schneier in 1993. + * http://www.schneier.com/blowfish.html + * http://en.wikipedia.org/wiki/Blowfish_%28cipher%29 + * + */ + +#include "common.h" + +#if defined(MBEDTLS_BLOWFISH_C) + +#include "mbedtls/blowfish.h" +#include "mbedtls/platform_util.h" + +#include + +#if !defined(MBEDTLS_BLOWFISH_ALT) + +/* Parameter validation macros */ +#define BLOWFISH_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA ) +#define BLOWFISH_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +static const uint32_t P[MBEDTLS_BLOWFISH_ROUNDS + 2] = { + 0x243F6A88L, 0x85A308D3L, 0x13198A2EL, 0x03707344L, + 0xA4093822L, 0x299F31D0L, 0x082EFA98L, 0xEC4E6C89L, + 0x452821E6L, 0x38D01377L, 0xBE5466CFL, 0x34E90C6CL, + 0xC0AC29B7L, 0xC97C50DDL, 0x3F84D5B5L, 0xB5470917L, + 0x9216D5D9L, 0x8979FB1BL +}; + +/* declarations of data at the end of this file */ +static const uint32_t S[4][256]; + +static uint32_t F( mbedtls_blowfish_context *ctx, uint32_t x ) +{ + unsigned short a, b, c, d; + uint32_t y; + + d = (unsigned short)(x & 0xFF); + x >>= 8; + c = (unsigned short)(x & 0xFF); + x >>= 8; + b = (unsigned short)(x & 0xFF); + x >>= 8; + a = (unsigned short)(x & 0xFF); + y = ctx->S[0][a] + ctx->S[1][b]; + y = y ^ ctx->S[2][c]; + y = y + ctx->S[3][d]; + + return( y ); +} + +static void blowfish_enc( mbedtls_blowfish_context *ctx, uint32_t *xl, uint32_t *xr ) +{ + uint32_t Xl, Xr, temp; + short i; + + Xl = *xl; + Xr = *xr; + + for( i = 0; i < MBEDTLS_BLOWFISH_ROUNDS; ++i ) + { + Xl = Xl ^ ctx->P[i]; + Xr = F( ctx, Xl ) ^ Xr; + + temp = Xl; + Xl = Xr; + Xr = temp; + } + + temp = Xl; + Xl = Xr; + Xr = temp; + + Xr = Xr ^ ctx->P[MBEDTLS_BLOWFISH_ROUNDS]; + Xl = Xl ^ ctx->P[MBEDTLS_BLOWFISH_ROUNDS + 1]; + + *xl = Xl; + *xr = Xr; +} + +static void blowfish_dec( mbedtls_blowfish_context *ctx, uint32_t *xl, uint32_t *xr ) +{ + uint32_t Xl, Xr, temp; + short i; + + Xl = *xl; + Xr = *xr; + + for( i = MBEDTLS_BLOWFISH_ROUNDS + 1; i > 1; --i ) + { + Xl = Xl ^ ctx->P[i]; + Xr = F( ctx, Xl ) ^ Xr; + + temp = Xl; + Xl = Xr; + Xr = temp; + } + + temp = Xl; + Xl = Xr; + Xr = temp; + + Xr = Xr ^ ctx->P[1]; + Xl = Xl ^ ctx->P[0]; + + *xl = Xl; + *xr = Xr; +} + +void mbedtls_blowfish_init( mbedtls_blowfish_context *ctx ) +{ + BLOWFISH_VALIDATE( ctx != NULL ); + memset( ctx, 0, sizeof( mbedtls_blowfish_context ) ); +} + +void mbedtls_blowfish_free( mbedtls_blowfish_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_blowfish_context ) ); +} + +/* + * Blowfish key schedule + */ +int mbedtls_blowfish_setkey( mbedtls_blowfish_context *ctx, + const unsigned char *key, + unsigned int keybits ) +{ + unsigned int i, j, k; + uint32_t data, datal, datar; + BLOWFISH_VALIDATE_RET( ctx != NULL ); + BLOWFISH_VALIDATE_RET( key != NULL ); + + if( keybits < MBEDTLS_BLOWFISH_MIN_KEY_BITS || + keybits > MBEDTLS_BLOWFISH_MAX_KEY_BITS || + keybits % 8 != 0 ) + { + return( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA ); + } + + keybits >>= 3; + + for( i = 0; i < 4; i++ ) + { + for( j = 0; j < 256; j++ ) + ctx->S[i][j] = S[i][j]; + } + + j = 0; + for( i = 0; i < MBEDTLS_BLOWFISH_ROUNDS + 2; ++i ) + { + data = 0x00000000; + for( k = 0; k < 4; ++k ) + { + data = ( data << 8 ) | key[j++]; + if( j >= keybits ) + j = 0; + } + ctx->P[i] = P[i] ^ data; + } + + datal = 0x00000000; + datar = 0x00000000; + + for( i = 0; i < MBEDTLS_BLOWFISH_ROUNDS + 2; i += 2 ) + { + blowfish_enc( ctx, &datal, &datar ); + ctx->P[i] = datal; + ctx->P[i + 1] = datar; + } + + for( i = 0; i < 4; i++ ) + { + for( j = 0; j < 256; j += 2 ) + { + blowfish_enc( ctx, &datal, &datar ); + ctx->S[i][j] = datal; + ctx->S[i][j + 1] = datar; + } + } + return( 0 ); +} + +/* + * Blowfish-ECB block encryption/decryption + */ +int mbedtls_blowfish_crypt_ecb( mbedtls_blowfish_context *ctx, + int mode, + const unsigned char input[MBEDTLS_BLOWFISH_BLOCKSIZE], + unsigned char output[MBEDTLS_BLOWFISH_BLOCKSIZE] ) +{ + uint32_t X0, X1; + BLOWFISH_VALIDATE_RET( ctx != NULL ); + BLOWFISH_VALIDATE_RET( mode == MBEDTLS_BLOWFISH_ENCRYPT || + mode == MBEDTLS_BLOWFISH_DECRYPT ); + BLOWFISH_VALIDATE_RET( input != NULL ); + BLOWFISH_VALIDATE_RET( output != NULL ); + + GET_UINT32_BE( X0, input, 0 ); + GET_UINT32_BE( X1, input, 4 ); + + if( mode == MBEDTLS_BLOWFISH_DECRYPT ) + { + blowfish_dec( ctx, &X0, &X1 ); + } + else /* MBEDTLS_BLOWFISH_ENCRYPT */ + { + blowfish_enc( ctx, &X0, &X1 ); + } + + PUT_UINT32_BE( X0, output, 0 ); + PUT_UINT32_BE( X1, output, 4 ); + + return( 0 ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/* + * Blowfish-CBC buffer encryption/decryption + */ +int mbedtls_blowfish_crypt_cbc( mbedtls_blowfish_context *ctx, + int mode, + size_t length, + unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ) +{ + int i; + unsigned char temp[MBEDTLS_BLOWFISH_BLOCKSIZE]; + BLOWFISH_VALIDATE_RET( ctx != NULL ); + BLOWFISH_VALIDATE_RET( mode == MBEDTLS_BLOWFISH_ENCRYPT || + mode == MBEDTLS_BLOWFISH_DECRYPT ); + BLOWFISH_VALIDATE_RET( iv != NULL ); + BLOWFISH_VALIDATE_RET( length == 0 || input != NULL ); + BLOWFISH_VALIDATE_RET( length == 0 || output != NULL ); + + if( length % MBEDTLS_BLOWFISH_BLOCKSIZE ) + return( MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH ); + + if( mode == MBEDTLS_BLOWFISH_DECRYPT ) + { + while( length > 0 ) + { + memcpy( temp, input, MBEDTLS_BLOWFISH_BLOCKSIZE ); + mbedtls_blowfish_crypt_ecb( ctx, mode, input, output ); + + for( i = 0; i < MBEDTLS_BLOWFISH_BLOCKSIZE;i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, MBEDTLS_BLOWFISH_BLOCKSIZE ); + + input += MBEDTLS_BLOWFISH_BLOCKSIZE; + output += MBEDTLS_BLOWFISH_BLOCKSIZE; + length -= MBEDTLS_BLOWFISH_BLOCKSIZE; + } + } + else + { + while( length > 0 ) + { + for( i = 0; i < MBEDTLS_BLOWFISH_BLOCKSIZE; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + mbedtls_blowfish_crypt_ecb( ctx, mode, output, output ); + memcpy( iv, output, MBEDTLS_BLOWFISH_BLOCKSIZE ); + + input += MBEDTLS_BLOWFISH_BLOCKSIZE; + output += MBEDTLS_BLOWFISH_BLOCKSIZE; + length -= MBEDTLS_BLOWFISH_BLOCKSIZE; + } + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/* + * Blowfish CFB buffer encryption/decryption + */ +int mbedtls_blowfish_crypt_cfb64( mbedtls_blowfish_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ) +{ + int c; + size_t n; + + BLOWFISH_VALIDATE_RET( ctx != NULL ); + BLOWFISH_VALIDATE_RET( mode == MBEDTLS_BLOWFISH_ENCRYPT || + mode == MBEDTLS_BLOWFISH_DECRYPT ); + BLOWFISH_VALIDATE_RET( iv != NULL ); + BLOWFISH_VALIDATE_RET( iv_off != NULL ); + BLOWFISH_VALIDATE_RET( length == 0 || input != NULL ); + BLOWFISH_VALIDATE_RET( length == 0 || output != NULL ); + + n = *iv_off; + if( n >= 8 ) + return( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA ); + + if( mode == MBEDTLS_BLOWFISH_DECRYPT ) + { + while( length-- ) + { + if( n == 0 ) + mbedtls_blowfish_crypt_ecb( ctx, MBEDTLS_BLOWFISH_ENCRYPT, iv, iv ); + + c = *input++; + *output++ = (unsigned char)( c ^ iv[n] ); + iv[n] = (unsigned char) c; + + n = ( n + 1 ) % MBEDTLS_BLOWFISH_BLOCKSIZE; + } + } + else + { + while( length-- ) + { + if( n == 0 ) + mbedtls_blowfish_crypt_ecb( ctx, MBEDTLS_BLOWFISH_ENCRYPT, iv, iv ); + + iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); + + n = ( n + 1 ) % MBEDTLS_BLOWFISH_BLOCKSIZE; + } + } + + *iv_off = n; + + return( 0 ); +} +#endif /*MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/* + * Blowfish CTR buffer encryption/decryption + */ +int mbedtls_blowfish_crypt_ctr( mbedtls_blowfish_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[MBEDTLS_BLOWFISH_BLOCKSIZE], + unsigned char stream_block[MBEDTLS_BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ) +{ + int c, i; + size_t n; + BLOWFISH_VALIDATE_RET( ctx != NULL ); + BLOWFISH_VALIDATE_RET( nonce_counter != NULL ); + BLOWFISH_VALIDATE_RET( stream_block != NULL ); + BLOWFISH_VALIDATE_RET( nc_off != NULL ); + BLOWFISH_VALIDATE_RET( length == 0 || input != NULL ); + BLOWFISH_VALIDATE_RET( length == 0 || output != NULL ); + + n = *nc_off; + if( n >= 8 ) + return( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA ); + + while( length-- ) + { + if( n == 0 ) { + mbedtls_blowfish_crypt_ecb( ctx, MBEDTLS_BLOWFISH_ENCRYPT, nonce_counter, + stream_block ); + + for( i = MBEDTLS_BLOWFISH_BLOCKSIZE; i > 0; i-- ) + if( ++nonce_counter[i - 1] != 0 ) + break; + } + c = *input++; + *output++ = (unsigned char)( c ^ stream_block[n] ); + + n = ( n + 1 ) % MBEDTLS_BLOWFISH_BLOCKSIZE; + } + + *nc_off = n; + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +static const uint32_t S[4][256] = { + { 0xD1310BA6L, 0x98DFB5ACL, 0x2FFD72DBL, 0xD01ADFB7L, + 0xB8E1AFEDL, 0x6A267E96L, 0xBA7C9045L, 0xF12C7F99L, + 0x24A19947L, 0xB3916CF7L, 0x0801F2E2L, 0x858EFC16L, + 0x636920D8L, 0x71574E69L, 0xA458FEA3L, 0xF4933D7EL, + 0x0D95748FL, 0x728EB658L, 0x718BCD58L, 0x82154AEEL, + 0x7B54A41DL, 0xC25A59B5L, 0x9C30D539L, 0x2AF26013L, + 0xC5D1B023L, 0x286085F0L, 0xCA417918L, 0xB8DB38EFL, + 0x8E79DCB0L, 0x603A180EL, 0x6C9E0E8BL, 0xB01E8A3EL, + 0xD71577C1L, 0xBD314B27L, 0x78AF2FDAL, 0x55605C60L, + 0xE65525F3L, 0xAA55AB94L, 0x57489862L, 0x63E81440L, + 0x55CA396AL, 0x2AAB10B6L, 0xB4CC5C34L, 0x1141E8CEL, + 0xA15486AFL, 0x7C72E993L, 0xB3EE1411L, 0x636FBC2AL, + 0x2BA9C55DL, 0x741831F6L, 0xCE5C3E16L, 0x9B87931EL, + 0xAFD6BA33L, 0x6C24CF5CL, 0x7A325381L, 0x28958677L, + 0x3B8F4898L, 0x6B4BB9AFL, 0xC4BFE81BL, 0x66282193L, + 0x61D809CCL, 0xFB21A991L, 0x487CAC60L, 0x5DEC8032L, + 0xEF845D5DL, 0xE98575B1L, 0xDC262302L, 0xEB651B88L, + 0x23893E81L, 0xD396ACC5L, 0x0F6D6FF3L, 0x83F44239L, + 0x2E0B4482L, 0xA4842004L, 0x69C8F04AL, 0x9E1F9B5EL, + 0x21C66842L, 0xF6E96C9AL, 0x670C9C61L, 0xABD388F0L, + 0x6A51A0D2L, 0xD8542F68L, 0x960FA728L, 0xAB5133A3L, + 0x6EEF0B6CL, 0x137A3BE4L, 0xBA3BF050L, 0x7EFB2A98L, + 0xA1F1651DL, 0x39AF0176L, 0x66CA593EL, 0x82430E88L, + 0x8CEE8619L, 0x456F9FB4L, 0x7D84A5C3L, 0x3B8B5EBEL, + 0xE06F75D8L, 0x85C12073L, 0x401A449FL, 0x56C16AA6L, + 0x4ED3AA62L, 0x363F7706L, 0x1BFEDF72L, 0x429B023DL, + 0x37D0D724L, 0xD00A1248L, 0xDB0FEAD3L, 0x49F1C09BL, + 0x075372C9L, 0x80991B7BL, 0x25D479D8L, 0xF6E8DEF7L, + 0xE3FE501AL, 0xB6794C3BL, 0x976CE0BDL, 0x04C006BAL, + 0xC1A94FB6L, 0x409F60C4L, 0x5E5C9EC2L, 0x196A2463L, + 0x68FB6FAFL, 0x3E6C53B5L, 0x1339B2EBL, 0x3B52EC6FL, + 0x6DFC511FL, 0x9B30952CL, 0xCC814544L, 0xAF5EBD09L, + 0xBEE3D004L, 0xDE334AFDL, 0x660F2807L, 0x192E4BB3L, + 0xC0CBA857L, 0x45C8740FL, 0xD20B5F39L, 0xB9D3FBDBL, + 0x5579C0BDL, 0x1A60320AL, 0xD6A100C6L, 0x402C7279L, + 0x679F25FEL, 0xFB1FA3CCL, 0x8EA5E9F8L, 0xDB3222F8L, + 0x3C7516DFL, 0xFD616B15L, 0x2F501EC8L, 0xAD0552ABL, + 0x323DB5FAL, 0xFD238760L, 0x53317B48L, 0x3E00DF82L, + 0x9E5C57BBL, 0xCA6F8CA0L, 0x1A87562EL, 0xDF1769DBL, + 0xD542A8F6L, 0x287EFFC3L, 0xAC6732C6L, 0x8C4F5573L, + 0x695B27B0L, 0xBBCA58C8L, 0xE1FFA35DL, 0xB8F011A0L, + 0x10FA3D98L, 0xFD2183B8L, 0x4AFCB56CL, 0x2DD1D35BL, + 0x9A53E479L, 0xB6F84565L, 0xD28E49BCL, 0x4BFB9790L, + 0xE1DDF2DAL, 0xA4CB7E33L, 0x62FB1341L, 0xCEE4C6E8L, + 0xEF20CADAL, 0x36774C01L, 0xD07E9EFEL, 0x2BF11FB4L, + 0x95DBDA4DL, 0xAE909198L, 0xEAAD8E71L, 0x6B93D5A0L, + 0xD08ED1D0L, 0xAFC725E0L, 0x8E3C5B2FL, 0x8E7594B7L, + 0x8FF6E2FBL, 0xF2122B64L, 0x8888B812L, 0x900DF01CL, + 0x4FAD5EA0L, 0x688FC31CL, 0xD1CFF191L, 0xB3A8C1ADL, + 0x2F2F2218L, 0xBE0E1777L, 0xEA752DFEL, 0x8B021FA1L, + 0xE5A0CC0FL, 0xB56F74E8L, 0x18ACF3D6L, 0xCE89E299L, + 0xB4A84FE0L, 0xFD13E0B7L, 0x7CC43B81L, 0xD2ADA8D9L, + 0x165FA266L, 0x80957705L, 0x93CC7314L, 0x211A1477L, + 0xE6AD2065L, 0x77B5FA86L, 0xC75442F5L, 0xFB9D35CFL, + 0xEBCDAF0CL, 0x7B3E89A0L, 0xD6411BD3L, 0xAE1E7E49L, + 0x00250E2DL, 0x2071B35EL, 0x226800BBL, 0x57B8E0AFL, + 0x2464369BL, 0xF009B91EL, 0x5563911DL, 0x59DFA6AAL, + 0x78C14389L, 0xD95A537FL, 0x207D5BA2L, 0x02E5B9C5L, + 0x83260376L, 0x6295CFA9L, 0x11C81968L, 0x4E734A41L, + 0xB3472DCAL, 0x7B14A94AL, 0x1B510052L, 0x9A532915L, + 0xD60F573FL, 0xBC9BC6E4L, 0x2B60A476L, 0x81E67400L, + 0x08BA6FB5L, 0x571BE91FL, 0xF296EC6BL, 0x2A0DD915L, + 0xB6636521L, 0xE7B9F9B6L, 0xFF34052EL, 0xC5855664L, + 0x53B02D5DL, 0xA99F8FA1L, 0x08BA4799L, 0x6E85076AL }, + { 0x4B7A70E9L, 0xB5B32944L, 0xDB75092EL, 0xC4192623L, + 0xAD6EA6B0L, 0x49A7DF7DL, 0x9CEE60B8L, 0x8FEDB266L, + 0xECAA8C71L, 0x699A17FFL, 0x5664526CL, 0xC2B19EE1L, + 0x193602A5L, 0x75094C29L, 0xA0591340L, 0xE4183A3EL, + 0x3F54989AL, 0x5B429D65L, 0x6B8FE4D6L, 0x99F73FD6L, + 0xA1D29C07L, 0xEFE830F5L, 0x4D2D38E6L, 0xF0255DC1L, + 0x4CDD2086L, 0x8470EB26L, 0x6382E9C6L, 0x021ECC5EL, + 0x09686B3FL, 0x3EBAEFC9L, 0x3C971814L, 0x6B6A70A1L, + 0x687F3584L, 0x52A0E286L, 0xB79C5305L, 0xAA500737L, + 0x3E07841CL, 0x7FDEAE5CL, 0x8E7D44ECL, 0x5716F2B8L, + 0xB03ADA37L, 0xF0500C0DL, 0xF01C1F04L, 0x0200B3FFL, + 0xAE0CF51AL, 0x3CB574B2L, 0x25837A58L, 0xDC0921BDL, + 0xD19113F9L, 0x7CA92FF6L, 0x94324773L, 0x22F54701L, + 0x3AE5E581L, 0x37C2DADCL, 0xC8B57634L, 0x9AF3DDA7L, + 0xA9446146L, 0x0FD0030EL, 0xECC8C73EL, 0xA4751E41L, + 0xE238CD99L, 0x3BEA0E2FL, 0x3280BBA1L, 0x183EB331L, + 0x4E548B38L, 0x4F6DB908L, 0x6F420D03L, 0xF60A04BFL, + 0x2CB81290L, 0x24977C79L, 0x5679B072L, 0xBCAF89AFL, + 0xDE9A771FL, 0xD9930810L, 0xB38BAE12L, 0xDCCF3F2EL, + 0x5512721FL, 0x2E6B7124L, 0x501ADDE6L, 0x9F84CD87L, + 0x7A584718L, 0x7408DA17L, 0xBC9F9ABCL, 0xE94B7D8CL, + 0xEC7AEC3AL, 0xDB851DFAL, 0x63094366L, 0xC464C3D2L, + 0xEF1C1847L, 0x3215D908L, 0xDD433B37L, 0x24C2BA16L, + 0x12A14D43L, 0x2A65C451L, 0x50940002L, 0x133AE4DDL, + 0x71DFF89EL, 0x10314E55L, 0x81AC77D6L, 0x5F11199BL, + 0x043556F1L, 0xD7A3C76BL, 0x3C11183BL, 0x5924A509L, + 0xF28FE6EDL, 0x97F1FBFAL, 0x9EBABF2CL, 0x1E153C6EL, + 0x86E34570L, 0xEAE96FB1L, 0x860E5E0AL, 0x5A3E2AB3L, + 0x771FE71CL, 0x4E3D06FAL, 0x2965DCB9L, 0x99E71D0FL, + 0x803E89D6L, 0x5266C825L, 0x2E4CC978L, 0x9C10B36AL, + 0xC6150EBAL, 0x94E2EA78L, 0xA5FC3C53L, 0x1E0A2DF4L, + 0xF2F74EA7L, 0x361D2B3DL, 0x1939260FL, 0x19C27960L, + 0x5223A708L, 0xF71312B6L, 0xEBADFE6EL, 0xEAC31F66L, + 0xE3BC4595L, 0xA67BC883L, 0xB17F37D1L, 0x018CFF28L, + 0xC332DDEFL, 0xBE6C5AA5L, 0x65582185L, 0x68AB9802L, + 0xEECEA50FL, 0xDB2F953BL, 0x2AEF7DADL, 0x5B6E2F84L, + 0x1521B628L, 0x29076170L, 0xECDD4775L, 0x619F1510L, + 0x13CCA830L, 0xEB61BD96L, 0x0334FE1EL, 0xAA0363CFL, + 0xB5735C90L, 0x4C70A239L, 0xD59E9E0BL, 0xCBAADE14L, + 0xEECC86BCL, 0x60622CA7L, 0x9CAB5CABL, 0xB2F3846EL, + 0x648B1EAFL, 0x19BDF0CAL, 0xA02369B9L, 0x655ABB50L, + 0x40685A32L, 0x3C2AB4B3L, 0x319EE9D5L, 0xC021B8F7L, + 0x9B540B19L, 0x875FA099L, 0x95F7997EL, 0x623D7DA8L, + 0xF837889AL, 0x97E32D77L, 0x11ED935FL, 0x16681281L, + 0x0E358829L, 0xC7E61FD6L, 0x96DEDFA1L, 0x7858BA99L, + 0x57F584A5L, 0x1B227263L, 0x9B83C3FFL, 0x1AC24696L, + 0xCDB30AEBL, 0x532E3054L, 0x8FD948E4L, 0x6DBC3128L, + 0x58EBF2EFL, 0x34C6FFEAL, 0xFE28ED61L, 0xEE7C3C73L, + 0x5D4A14D9L, 0xE864B7E3L, 0x42105D14L, 0x203E13E0L, + 0x45EEE2B6L, 0xA3AAABEAL, 0xDB6C4F15L, 0xFACB4FD0L, + 0xC742F442L, 0xEF6ABBB5L, 0x654F3B1DL, 0x41CD2105L, + 0xD81E799EL, 0x86854DC7L, 0xE44B476AL, 0x3D816250L, + 0xCF62A1F2L, 0x5B8D2646L, 0xFC8883A0L, 0xC1C7B6A3L, + 0x7F1524C3L, 0x69CB7492L, 0x47848A0BL, 0x5692B285L, + 0x095BBF00L, 0xAD19489DL, 0x1462B174L, 0x23820E00L, + 0x58428D2AL, 0x0C55F5EAL, 0x1DADF43EL, 0x233F7061L, + 0x3372F092L, 0x8D937E41L, 0xD65FECF1L, 0x6C223BDBL, + 0x7CDE3759L, 0xCBEE7460L, 0x4085F2A7L, 0xCE77326EL, + 0xA6078084L, 0x19F8509EL, 0xE8EFD855L, 0x61D99735L, + 0xA969A7AAL, 0xC50C06C2L, 0x5A04ABFCL, 0x800BCADCL, + 0x9E447A2EL, 0xC3453484L, 0xFDD56705L, 0x0E1E9EC9L, + 0xDB73DBD3L, 0x105588CDL, 0x675FDA79L, 0xE3674340L, + 0xC5C43465L, 0x713E38D8L, 0x3D28F89EL, 0xF16DFF20L, + 0x153E21E7L, 0x8FB03D4AL, 0xE6E39F2BL, 0xDB83ADF7L }, + { 0xE93D5A68L, 0x948140F7L, 0xF64C261CL, 0x94692934L, + 0x411520F7L, 0x7602D4F7L, 0xBCF46B2EL, 0xD4A20068L, + 0xD4082471L, 0x3320F46AL, 0x43B7D4B7L, 0x500061AFL, + 0x1E39F62EL, 0x97244546L, 0x14214F74L, 0xBF8B8840L, + 0x4D95FC1DL, 0x96B591AFL, 0x70F4DDD3L, 0x66A02F45L, + 0xBFBC09ECL, 0x03BD9785L, 0x7FAC6DD0L, 0x31CB8504L, + 0x96EB27B3L, 0x55FD3941L, 0xDA2547E6L, 0xABCA0A9AL, + 0x28507825L, 0x530429F4L, 0x0A2C86DAL, 0xE9B66DFBL, + 0x68DC1462L, 0xD7486900L, 0x680EC0A4L, 0x27A18DEEL, + 0x4F3FFEA2L, 0xE887AD8CL, 0xB58CE006L, 0x7AF4D6B6L, + 0xAACE1E7CL, 0xD3375FECL, 0xCE78A399L, 0x406B2A42L, + 0x20FE9E35L, 0xD9F385B9L, 0xEE39D7ABL, 0x3B124E8BL, + 0x1DC9FAF7L, 0x4B6D1856L, 0x26A36631L, 0xEAE397B2L, + 0x3A6EFA74L, 0xDD5B4332L, 0x6841E7F7L, 0xCA7820FBL, + 0xFB0AF54EL, 0xD8FEB397L, 0x454056ACL, 0xBA489527L, + 0x55533A3AL, 0x20838D87L, 0xFE6BA9B7L, 0xD096954BL, + 0x55A867BCL, 0xA1159A58L, 0xCCA92963L, 0x99E1DB33L, + 0xA62A4A56L, 0x3F3125F9L, 0x5EF47E1CL, 0x9029317CL, + 0xFDF8E802L, 0x04272F70L, 0x80BB155CL, 0x05282CE3L, + 0x95C11548L, 0xE4C66D22L, 0x48C1133FL, 0xC70F86DCL, + 0x07F9C9EEL, 0x41041F0FL, 0x404779A4L, 0x5D886E17L, + 0x325F51EBL, 0xD59BC0D1L, 0xF2BCC18FL, 0x41113564L, + 0x257B7834L, 0x602A9C60L, 0xDFF8E8A3L, 0x1F636C1BL, + 0x0E12B4C2L, 0x02E1329EL, 0xAF664FD1L, 0xCAD18115L, + 0x6B2395E0L, 0x333E92E1L, 0x3B240B62L, 0xEEBEB922L, + 0x85B2A20EL, 0xE6BA0D99L, 0xDE720C8CL, 0x2DA2F728L, + 0xD0127845L, 0x95B794FDL, 0x647D0862L, 0xE7CCF5F0L, + 0x5449A36FL, 0x877D48FAL, 0xC39DFD27L, 0xF33E8D1EL, + 0x0A476341L, 0x992EFF74L, 0x3A6F6EABL, 0xF4F8FD37L, + 0xA812DC60L, 0xA1EBDDF8L, 0x991BE14CL, 0xDB6E6B0DL, + 0xC67B5510L, 0x6D672C37L, 0x2765D43BL, 0xDCD0E804L, + 0xF1290DC7L, 0xCC00FFA3L, 0xB5390F92L, 0x690FED0BL, + 0x667B9FFBL, 0xCEDB7D9CL, 0xA091CF0BL, 0xD9155EA3L, + 0xBB132F88L, 0x515BAD24L, 0x7B9479BFL, 0x763BD6EBL, + 0x37392EB3L, 0xCC115979L, 0x8026E297L, 0xF42E312DL, + 0x6842ADA7L, 0xC66A2B3BL, 0x12754CCCL, 0x782EF11CL, + 0x6A124237L, 0xB79251E7L, 0x06A1BBE6L, 0x4BFB6350L, + 0x1A6B1018L, 0x11CAEDFAL, 0x3D25BDD8L, 0xE2E1C3C9L, + 0x44421659L, 0x0A121386L, 0xD90CEC6EL, 0xD5ABEA2AL, + 0x64AF674EL, 0xDA86A85FL, 0xBEBFE988L, 0x64E4C3FEL, + 0x9DBC8057L, 0xF0F7C086L, 0x60787BF8L, 0x6003604DL, + 0xD1FD8346L, 0xF6381FB0L, 0x7745AE04L, 0xD736FCCCL, + 0x83426B33L, 0xF01EAB71L, 0xB0804187L, 0x3C005E5FL, + 0x77A057BEL, 0xBDE8AE24L, 0x55464299L, 0xBF582E61L, + 0x4E58F48FL, 0xF2DDFDA2L, 0xF474EF38L, 0x8789BDC2L, + 0x5366F9C3L, 0xC8B38E74L, 0xB475F255L, 0x46FCD9B9L, + 0x7AEB2661L, 0x8B1DDF84L, 0x846A0E79L, 0x915F95E2L, + 0x466E598EL, 0x20B45770L, 0x8CD55591L, 0xC902DE4CL, + 0xB90BACE1L, 0xBB8205D0L, 0x11A86248L, 0x7574A99EL, + 0xB77F19B6L, 0xE0A9DC09L, 0x662D09A1L, 0xC4324633L, + 0xE85A1F02L, 0x09F0BE8CL, 0x4A99A025L, 0x1D6EFE10L, + 0x1AB93D1DL, 0x0BA5A4DFL, 0xA186F20FL, 0x2868F169L, + 0xDCB7DA83L, 0x573906FEL, 0xA1E2CE9BL, 0x4FCD7F52L, + 0x50115E01L, 0xA70683FAL, 0xA002B5C4L, 0x0DE6D027L, + 0x9AF88C27L, 0x773F8641L, 0xC3604C06L, 0x61A806B5L, + 0xF0177A28L, 0xC0F586E0L, 0x006058AAL, 0x30DC7D62L, + 0x11E69ED7L, 0x2338EA63L, 0x53C2DD94L, 0xC2C21634L, + 0xBBCBEE56L, 0x90BCB6DEL, 0xEBFC7DA1L, 0xCE591D76L, + 0x6F05E409L, 0x4B7C0188L, 0x39720A3DL, 0x7C927C24L, + 0x86E3725FL, 0x724D9DB9L, 0x1AC15BB4L, 0xD39EB8FCL, + 0xED545578L, 0x08FCA5B5L, 0xD83D7CD3L, 0x4DAD0FC4L, + 0x1E50EF5EL, 0xB161E6F8L, 0xA28514D9L, 0x6C51133CL, + 0x6FD5C7E7L, 0x56E14EC4L, 0x362ABFCEL, 0xDDC6C837L, + 0xD79A3234L, 0x92638212L, 0x670EFA8EL, 0x406000E0L }, + { 0x3A39CE37L, 0xD3FAF5CFL, 0xABC27737L, 0x5AC52D1BL, + 0x5CB0679EL, 0x4FA33742L, 0xD3822740L, 0x99BC9BBEL, + 0xD5118E9DL, 0xBF0F7315L, 0xD62D1C7EL, 0xC700C47BL, + 0xB78C1B6BL, 0x21A19045L, 0xB26EB1BEL, 0x6A366EB4L, + 0x5748AB2FL, 0xBC946E79L, 0xC6A376D2L, 0x6549C2C8L, + 0x530FF8EEL, 0x468DDE7DL, 0xD5730A1DL, 0x4CD04DC6L, + 0x2939BBDBL, 0xA9BA4650L, 0xAC9526E8L, 0xBE5EE304L, + 0xA1FAD5F0L, 0x6A2D519AL, 0x63EF8CE2L, 0x9A86EE22L, + 0xC089C2B8L, 0x43242EF6L, 0xA51E03AAL, 0x9CF2D0A4L, + 0x83C061BAL, 0x9BE96A4DL, 0x8FE51550L, 0xBA645BD6L, + 0x2826A2F9L, 0xA73A3AE1L, 0x4BA99586L, 0xEF5562E9L, + 0xC72FEFD3L, 0xF752F7DAL, 0x3F046F69L, 0x77FA0A59L, + 0x80E4A915L, 0x87B08601L, 0x9B09E6ADL, 0x3B3EE593L, + 0xE990FD5AL, 0x9E34D797L, 0x2CF0B7D9L, 0x022B8B51L, + 0x96D5AC3AL, 0x017DA67DL, 0xD1CF3ED6L, 0x7C7D2D28L, + 0x1F9F25CFL, 0xADF2B89BL, 0x5AD6B472L, 0x5A88F54CL, + 0xE029AC71L, 0xE019A5E6L, 0x47B0ACFDL, 0xED93FA9BL, + 0xE8D3C48DL, 0x283B57CCL, 0xF8D56629L, 0x79132E28L, + 0x785F0191L, 0xED756055L, 0xF7960E44L, 0xE3D35E8CL, + 0x15056DD4L, 0x88F46DBAL, 0x03A16125L, 0x0564F0BDL, + 0xC3EB9E15L, 0x3C9057A2L, 0x97271AECL, 0xA93A072AL, + 0x1B3F6D9BL, 0x1E6321F5L, 0xF59C66FBL, 0x26DCF319L, + 0x7533D928L, 0xB155FDF5L, 0x03563482L, 0x8ABA3CBBL, + 0x28517711L, 0xC20AD9F8L, 0xABCC5167L, 0xCCAD925FL, + 0x4DE81751L, 0x3830DC8EL, 0x379D5862L, 0x9320F991L, + 0xEA7A90C2L, 0xFB3E7BCEL, 0x5121CE64L, 0x774FBE32L, + 0xA8B6E37EL, 0xC3293D46L, 0x48DE5369L, 0x6413E680L, + 0xA2AE0810L, 0xDD6DB224L, 0x69852DFDL, 0x09072166L, + 0xB39A460AL, 0x6445C0DDL, 0x586CDECFL, 0x1C20C8AEL, + 0x5BBEF7DDL, 0x1B588D40L, 0xCCD2017FL, 0x6BB4E3BBL, + 0xDDA26A7EL, 0x3A59FF45L, 0x3E350A44L, 0xBCB4CDD5L, + 0x72EACEA8L, 0xFA6484BBL, 0x8D6612AEL, 0xBF3C6F47L, + 0xD29BE463L, 0x542F5D9EL, 0xAEC2771BL, 0xF64E6370L, + 0x740E0D8DL, 0xE75B1357L, 0xF8721671L, 0xAF537D5DL, + 0x4040CB08L, 0x4EB4E2CCL, 0x34D2466AL, 0x0115AF84L, + 0xE1B00428L, 0x95983A1DL, 0x06B89FB4L, 0xCE6EA048L, + 0x6F3F3B82L, 0x3520AB82L, 0x011A1D4BL, 0x277227F8L, + 0x611560B1L, 0xE7933FDCL, 0xBB3A792BL, 0x344525BDL, + 0xA08839E1L, 0x51CE794BL, 0x2F32C9B7L, 0xA01FBAC9L, + 0xE01CC87EL, 0xBCC7D1F6L, 0xCF0111C3L, 0xA1E8AAC7L, + 0x1A908749L, 0xD44FBD9AL, 0xD0DADECBL, 0xD50ADA38L, + 0x0339C32AL, 0xC6913667L, 0x8DF9317CL, 0xE0B12B4FL, + 0xF79E59B7L, 0x43F5BB3AL, 0xF2D519FFL, 0x27D9459CL, + 0xBF97222CL, 0x15E6FC2AL, 0x0F91FC71L, 0x9B941525L, + 0xFAE59361L, 0xCEB69CEBL, 0xC2A86459L, 0x12BAA8D1L, + 0xB6C1075EL, 0xE3056A0CL, 0x10D25065L, 0xCB03A442L, + 0xE0EC6E0EL, 0x1698DB3BL, 0x4C98A0BEL, 0x3278E964L, + 0x9F1F9532L, 0xE0D392DFL, 0xD3A0342BL, 0x8971F21EL, + 0x1B0A7441L, 0x4BA3348CL, 0xC5BE7120L, 0xC37632D8L, + 0xDF359F8DL, 0x9B992F2EL, 0xE60B6F47L, 0x0FE3F11DL, + 0xE54CDA54L, 0x1EDAD891L, 0xCE6279CFL, 0xCD3E7E6FL, + 0x1618B166L, 0xFD2C1D05L, 0x848FD2C5L, 0xF6FB2299L, + 0xF523F357L, 0xA6327623L, 0x93A83531L, 0x56CCCD02L, + 0xACF08162L, 0x5A75EBB5L, 0x6E163697L, 0x88D273CCL, + 0xDE966292L, 0x81B949D0L, 0x4C50901BL, 0x71C65614L, + 0xE6C6C7BDL, 0x327A140AL, 0x45E1D006L, 0xC3F27B9AL, + 0xC9AA53FDL, 0x62A80F00L, 0xBB25BFE2L, 0x35BDD2F6L, + 0x71126905L, 0xB2040222L, 0xB6CBCF7CL, 0xCD769C2BL, + 0x53113EC0L, 0x1640E3D3L, 0x38ABBD60L, 0x2547ADF0L, + 0xBA38209CL, 0xF746CE76L, 0x77AFA1C5L, 0x20756060L, + 0x85CBFE4EL, 0x8AE88DD8L, 0x7AAAF9B0L, 0x4CF9AA7EL, + 0x1948C25CL, 0x02FB8A8CL, 0x01C36AE4L, 0xD6EBE1F9L, + 0x90D4F869L, 0xA65CDEA0L, 0x3F09252DL, 0xC208E69FL, + 0xB74E6132L, 0xCE77E25BL, 0x578FDFE3L, 0x3AC372E6L } +}; + +#endif /* !MBEDTLS_BLOWFISH_ALT */ +#endif /* MBEDTLS_BLOWFISH_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/camellia.c b/Android/Level4/app/src/main/c/mbedtls/library/camellia.c new file mode 100644 index 0000000..d60f931 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/camellia.c @@ -0,0 +1,1108 @@ +/* + * Camellia implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ +/* + * The Camellia block cipher was designed by NTT and Mitsubishi Electric + * Corporation. + * + * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/01espec.pdf + */ + +#include "common.h" + +#if defined(MBEDTLS_CAMELLIA_C) + +#include "mbedtls/camellia.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_CAMELLIA_ALT) + +/* Parameter validation macros */ +#define CAMELLIA_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA ) +#define CAMELLIA_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +static const unsigned char SIGMA_CHARS[6][8] = +{ + { 0xa0, 0x9e, 0x66, 0x7f, 0x3b, 0xcc, 0x90, 0x8b }, + { 0xb6, 0x7a, 0xe8, 0x58, 0x4c, 0xaa, 0x73, 0xb2 }, + { 0xc6, 0xef, 0x37, 0x2f, 0xe9, 0x4f, 0x82, 0xbe }, + { 0x54, 0xff, 0x53, 0xa5, 0xf1, 0xd3, 0x6f, 0x1c }, + { 0x10, 0xe5, 0x27, 0xfa, 0xde, 0x68, 0x2d, 0x1d }, + { 0xb0, 0x56, 0x88, 0xc2, 0xb3, 0xe6, 0xc1, 0xfd } +}; + +#if defined(MBEDTLS_CAMELLIA_SMALL_MEMORY) + +static const unsigned char FSb[256] = +{ + 112,130, 44,236,179, 39,192,229,228,133, 87, 53,234, 12,174, 65, + 35,239,107,147, 69, 25,165, 33,237, 14, 79, 78, 29,101,146,189, + 134,184,175,143,124,235, 31,206, 62, 48,220, 95, 94,197, 11, 26, + 166,225, 57,202,213, 71, 93, 61,217, 1, 90,214, 81, 86,108, 77, + 139, 13,154,102,251,204,176, 45,116, 18, 43, 32,240,177,132,153, + 223, 76,203,194, 52,126,118, 5,109,183,169, 49,209, 23, 4,215, + 20, 88, 58, 97,222, 27, 17, 28, 50, 15,156, 22, 83, 24,242, 34, + 254, 68,207,178,195,181,122,145, 36, 8,232,168, 96,252,105, 80, + 170,208,160,125,161,137, 98,151, 84, 91, 30,149,224,255,100,210, + 16,196, 0, 72,163,247,117,219,138, 3,230,218, 9, 63,221,148, + 135, 92,131, 2,205, 74,144, 51,115,103,246,243,157,127,191,226, + 82,155,216, 38,200, 55,198, 59,129,150,111, 75, 19,190, 99, 46, + 233,121,167,140,159,110,188,142, 41,245,249,182, 47,253,180, 89, + 120,152, 6,106,231, 70,113,186,212, 37,171, 66,136,162,141,250, + 114, 7,185, 85,248,238,172, 10, 54, 73, 42,104, 60, 56,241,164, + 64, 40,211,123,187,201, 67,193, 21,227,173,244,119,199,128,158 +}; + +#define SBOX1(n) FSb[(n)] +#define SBOX2(n) (unsigned char)((FSb[(n)] >> 7 ^ FSb[(n)] << 1) & 0xff) +#define SBOX3(n) (unsigned char)((FSb[(n)] >> 1 ^ FSb[(n)] << 7) & 0xff) +#define SBOX4(n) FSb[((n) << 1 ^ (n) >> 7) &0xff] + +#else /* MBEDTLS_CAMELLIA_SMALL_MEMORY */ + +static const unsigned char FSb[256] = +{ + 112, 130, 44, 236, 179, 39, 192, 229, 228, 133, 87, 53, 234, 12, 174, 65, + 35, 239, 107, 147, 69, 25, 165, 33, 237, 14, 79, 78, 29, 101, 146, 189, + 134, 184, 175, 143, 124, 235, 31, 206, 62, 48, 220, 95, 94, 197, 11, 26, + 166, 225, 57, 202, 213, 71, 93, 61, 217, 1, 90, 214, 81, 86, 108, 77, + 139, 13, 154, 102, 251, 204, 176, 45, 116, 18, 43, 32, 240, 177, 132, 153, + 223, 76, 203, 194, 52, 126, 118, 5, 109, 183, 169, 49, 209, 23, 4, 215, + 20, 88, 58, 97, 222, 27, 17, 28, 50, 15, 156, 22, 83, 24, 242, 34, + 254, 68, 207, 178, 195, 181, 122, 145, 36, 8, 232, 168, 96, 252, 105, 80, + 170, 208, 160, 125, 161, 137, 98, 151, 84, 91, 30, 149, 224, 255, 100, 210, + 16, 196, 0, 72, 163, 247, 117, 219, 138, 3, 230, 218, 9, 63, 221, 148, + 135, 92, 131, 2, 205, 74, 144, 51, 115, 103, 246, 243, 157, 127, 191, 226, + 82, 155, 216, 38, 200, 55, 198, 59, 129, 150, 111, 75, 19, 190, 99, 46, + 233, 121, 167, 140, 159, 110, 188, 142, 41, 245, 249, 182, 47, 253, 180, 89, + 120, 152, 6, 106, 231, 70, 113, 186, 212, 37, 171, 66, 136, 162, 141, 250, + 114, 7, 185, 85, 248, 238, 172, 10, 54, 73, 42, 104, 60, 56, 241, 164, + 64, 40, 211, 123, 187, 201, 67, 193, 21, 227, 173, 244, 119, 199, 128, 158 +}; + +static const unsigned char FSb2[256] = +{ + 224, 5, 88, 217, 103, 78, 129, 203, 201, 11, 174, 106, 213, 24, 93, 130, + 70, 223, 214, 39, 138, 50, 75, 66, 219, 28, 158, 156, 58, 202, 37, 123, + 13, 113, 95, 31, 248, 215, 62, 157, 124, 96, 185, 190, 188, 139, 22, 52, + 77, 195, 114, 149, 171, 142, 186, 122, 179, 2, 180, 173, 162, 172, 216, 154, + 23, 26, 53, 204, 247, 153, 97, 90, 232, 36, 86, 64, 225, 99, 9, 51, + 191, 152, 151, 133, 104, 252, 236, 10, 218, 111, 83, 98, 163, 46, 8, 175, + 40, 176, 116, 194, 189, 54, 34, 56, 100, 30, 57, 44, 166, 48, 229, 68, + 253, 136, 159, 101, 135, 107, 244, 35, 72, 16, 209, 81, 192, 249, 210, 160, + 85, 161, 65, 250, 67, 19, 196, 47, 168, 182, 60, 43, 193, 255, 200, 165, + 32, 137, 0, 144, 71, 239, 234, 183, 21, 6, 205, 181, 18, 126, 187, 41, + 15, 184, 7, 4, 155, 148, 33, 102, 230, 206, 237, 231, 59, 254, 127, 197, + 164, 55, 177, 76, 145, 110, 141, 118, 3, 45, 222, 150, 38, 125, 198, 92, + 211, 242, 79, 25, 63, 220, 121, 29, 82, 235, 243, 109, 94, 251, 105, 178, + 240, 49, 12, 212, 207, 140, 226, 117, 169, 74, 87, 132, 17, 69, 27, 245, + 228, 14, 115, 170, 241, 221, 89, 20, 108, 146, 84, 208, 120, 112, 227, 73, + 128, 80, 167, 246, 119, 147, 134, 131, 42, 199, 91, 233, 238, 143, 1, 61 +}; + +static const unsigned char FSb3[256] = +{ + 56, 65, 22, 118, 217, 147, 96, 242, 114, 194, 171, 154, 117, 6, 87, 160, + 145, 247, 181, 201, 162, 140, 210, 144, 246, 7, 167, 39, 142, 178, 73, 222, + 67, 92, 215, 199, 62, 245, 143, 103, 31, 24, 110, 175, 47, 226, 133, 13, + 83, 240, 156, 101, 234, 163, 174, 158, 236, 128, 45, 107, 168, 43, 54, 166, + 197, 134, 77, 51, 253, 102, 88, 150, 58, 9, 149, 16, 120, 216, 66, 204, + 239, 38, 229, 97, 26, 63, 59, 130, 182, 219, 212, 152, 232, 139, 2, 235, + 10, 44, 29, 176, 111, 141, 136, 14, 25, 135, 78, 11, 169, 12, 121, 17, + 127, 34, 231, 89, 225, 218, 61, 200, 18, 4, 116, 84, 48, 126, 180, 40, + 85, 104, 80, 190, 208, 196, 49, 203, 42, 173, 15, 202, 112, 255, 50, 105, + 8, 98, 0, 36, 209, 251, 186, 237, 69, 129, 115, 109, 132, 159, 238, 74, + 195, 46, 193, 1, 230, 37, 72, 153, 185, 179, 123, 249, 206, 191, 223, 113, + 41, 205, 108, 19, 100, 155, 99, 157, 192, 75, 183, 165, 137, 95, 177, 23, + 244, 188, 211, 70, 207, 55, 94, 71, 148, 250, 252, 91, 151, 254, 90, 172, + 60, 76, 3, 53, 243, 35, 184, 93, 106, 146, 213, 33, 68, 81, 198, 125, + 57, 131, 220, 170, 124, 119, 86, 5, 27, 164, 21, 52, 30, 28, 248, 82, + 32, 20, 233, 189, 221, 228, 161, 224, 138, 241, 214, 122, 187, 227, 64, 79 +}; + +static const unsigned char FSb4[256] = +{ + 112, 44, 179, 192, 228, 87, 234, 174, 35, 107, 69, 165, 237, 79, 29, 146, + 134, 175, 124, 31, 62, 220, 94, 11, 166, 57, 213, 93, 217, 90, 81, 108, + 139, 154, 251, 176, 116, 43, 240, 132, 223, 203, 52, 118, 109, 169, 209, 4, + 20, 58, 222, 17, 50, 156, 83, 242, 254, 207, 195, 122, 36, 232, 96, 105, + 170, 160, 161, 98, 84, 30, 224, 100, 16, 0, 163, 117, 138, 230, 9, 221, + 135, 131, 205, 144, 115, 246, 157, 191, 82, 216, 200, 198, 129, 111, 19, 99, + 233, 167, 159, 188, 41, 249, 47, 180, 120, 6, 231, 113, 212, 171, 136, 141, + 114, 185, 248, 172, 54, 42, 60, 241, 64, 211, 187, 67, 21, 173, 119, 128, + 130, 236, 39, 229, 133, 53, 12, 65, 239, 147, 25, 33, 14, 78, 101, 189, + 184, 143, 235, 206, 48, 95, 197, 26, 225, 202, 71, 61, 1, 214, 86, 77, + 13, 102, 204, 45, 18, 32, 177, 153, 76, 194, 126, 5, 183, 49, 23, 215, + 88, 97, 27, 28, 15, 22, 24, 34, 68, 178, 181, 145, 8, 168, 252, 80, + 208, 125, 137, 151, 91, 149, 255, 210, 196, 72, 247, 219, 3, 218, 63, 148, + 92, 2, 74, 51, 103, 243, 127, 226, 155, 38, 55, 59, 150, 75, 190, 46, + 121, 140, 110, 142, 245, 182, 253, 89, 152, 106, 70, 186, 37, 66, 162, 250, + 7, 85, 238, 10, 73, 104, 56, 164, 40, 123, 201, 193, 227, 244, 199, 158 +}; + +#define SBOX1(n) FSb[(n)] +#define SBOX2(n) FSb2[(n)] +#define SBOX3(n) FSb3[(n)] +#define SBOX4(n) FSb4[(n)] + +#endif /* MBEDTLS_CAMELLIA_SMALL_MEMORY */ + +static const unsigned char shifts[2][4][4] = +{ + { + { 1, 1, 1, 1 }, /* KL */ + { 0, 0, 0, 0 }, /* KR */ + { 1, 1, 1, 1 }, /* KA */ + { 0, 0, 0, 0 } /* KB */ + }, + { + { 1, 0, 1, 1 }, /* KL */ + { 1, 1, 0, 1 }, /* KR */ + { 1, 1, 1, 0 }, /* KA */ + { 1, 1, 0, 1 } /* KB */ + } +}; + +static const signed char indexes[2][4][20] = +{ + { + { 0, 1, 2, 3, 8, 9, 10, 11, 38, 39, + 36, 37, 23, 20, 21, 22, 27, -1, -1, 26 }, /* KL -> RK */ + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* KR -> RK */ + { 4, 5, 6, 7, 12, 13, 14, 15, 16, 17, + 18, 19, -1, 24, 25, -1, 31, 28, 29, 30 }, /* KA -> RK */ + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } /* KB -> RK */ + }, + { + { 0, 1, 2, 3, 61, 62, 63, 60, -1, -1, + -1, -1, 27, 24, 25, 26, 35, 32, 33, 34 }, /* KL -> RK */ + { -1, -1, -1, -1, 8, 9, 10, 11, 16, 17, + 18, 19, -1, -1, -1, -1, 39, 36, 37, 38 }, /* KR -> RK */ + { -1, -1, -1, -1, 12, 13, 14, 15, 58, 59, + 56, 57, 31, 28, 29, 30, -1, -1, -1, -1 }, /* KA -> RK */ + { 4, 5, 6, 7, 65, 66, 67, 64, 20, 21, + 22, 23, -1, -1, -1, -1, 43, 40, 41, 42 } /* KB -> RK */ + } +}; + +static const signed char transposes[2][20] = +{ + { + 21, 22, 23, 20, + -1, -1, -1, -1, + 18, 19, 16, 17, + 11, 8, 9, 10, + 15, 12, 13, 14 + }, + { + 25, 26, 27, 24, + 29, 30, 31, 28, + 18, 19, 16, 17, + -1, -1, -1, -1, + -1, -1, -1, -1 + } +}; + +/* Shift macro for 128 bit strings with rotation smaller than 32 bits (!) */ +#define ROTL(DEST, SRC, SHIFT) \ +{ \ + (DEST)[0] = (SRC)[0] << (SHIFT) ^ (SRC)[1] >> (32 - (SHIFT)); \ + (DEST)[1] = (SRC)[1] << (SHIFT) ^ (SRC)[2] >> (32 - (SHIFT)); \ + (DEST)[2] = (SRC)[2] << (SHIFT) ^ (SRC)[3] >> (32 - (SHIFT)); \ + (DEST)[3] = (SRC)[3] << (SHIFT) ^ (SRC)[0] >> (32 - (SHIFT)); \ +} + +#define FL(XL, XR, KL, KR) \ +{ \ + (XR) = ((((XL) & (KL)) << 1) | (((XL) & (KL)) >> 31)) ^ (XR); \ + (XL) = ((XR) | (KR)) ^ (XL); \ +} + +#define FLInv(YL, YR, KL, KR) \ +{ \ + (YL) = ((YR) | (KR)) ^ (YL); \ + (YR) = ((((YL) & (KL)) << 1) | (((YL) & (KL)) >> 31)) ^ (YR); \ +} + +#define SHIFT_AND_PLACE(INDEX, OFFSET) \ +{ \ + TK[0] = KC[(OFFSET) * 4 + 0]; \ + TK[1] = KC[(OFFSET) * 4 + 1]; \ + TK[2] = KC[(OFFSET) * 4 + 2]; \ + TK[3] = KC[(OFFSET) * 4 + 3]; \ + \ + for( i = 1; i <= 4; i++ ) \ + if( shifts[(INDEX)][(OFFSET)][i -1] ) \ + ROTL(TK + i * 4, TK, ( 15 * i ) % 32); \ + \ + for( i = 0; i < 20; i++ ) \ + if( indexes[(INDEX)][(OFFSET)][i] != -1 ) { \ + RK[indexes[(INDEX)][(OFFSET)][i]] = TK[ i ]; \ + } \ +} + +static void camellia_feistel( const uint32_t x[2], const uint32_t k[2], + uint32_t z[2]) +{ + uint32_t I0, I1; + I0 = x[0] ^ k[0]; + I1 = x[1] ^ k[1]; + + I0 = ((uint32_t) SBOX1((I0 >> 24) & 0xFF) << 24) | + ((uint32_t) SBOX2((I0 >> 16) & 0xFF) << 16) | + ((uint32_t) SBOX3((I0 >> 8) & 0xFF) << 8) | + ((uint32_t) SBOX4((I0 ) & 0xFF) ); + I1 = ((uint32_t) SBOX2((I1 >> 24) & 0xFF) << 24) | + ((uint32_t) SBOX3((I1 >> 16) & 0xFF) << 16) | + ((uint32_t) SBOX4((I1 >> 8) & 0xFF) << 8) | + ((uint32_t) SBOX1((I1 ) & 0xFF) ); + + I0 ^= (I1 << 8) | (I1 >> 24); + I1 ^= (I0 << 16) | (I0 >> 16); + I0 ^= (I1 >> 8) | (I1 << 24); + I1 ^= (I0 >> 8) | (I0 << 24); + + z[0] ^= I1; + z[1] ^= I0; +} + +void mbedtls_camellia_init( mbedtls_camellia_context *ctx ) +{ + CAMELLIA_VALIDATE( ctx != NULL ); + memset( ctx, 0, sizeof( mbedtls_camellia_context ) ); +} + +void mbedtls_camellia_free( mbedtls_camellia_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_camellia_context ) ); +} + +/* + * Camellia key schedule (encryption) + */ +int mbedtls_camellia_setkey_enc( mbedtls_camellia_context *ctx, + const unsigned char *key, + unsigned int keybits ) +{ + int idx; + size_t i; + uint32_t *RK; + unsigned char t[64]; + uint32_t SIGMA[6][2]; + uint32_t KC[16]; + uint32_t TK[20]; + + CAMELLIA_VALIDATE_RET( ctx != NULL ); + CAMELLIA_VALIDATE_RET( key != NULL ); + + RK = ctx->rk; + + memset( t, 0, 64 ); + memset( RK, 0, sizeof(ctx->rk) ); + + switch( keybits ) + { + case 128: ctx->nr = 3; idx = 0; break; + case 192: + case 256: ctx->nr = 4; idx = 1; break; + default : return( MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA ); + } + + for( i = 0; i < keybits / 8; ++i ) + t[i] = key[i]; + + if( keybits == 192 ) { + for( i = 0; i < 8; i++ ) + t[24 + i] = ~t[16 + i]; + } + + /* + * Prepare SIGMA values + */ + for( i = 0; i < 6; i++ ) { + GET_UINT32_BE( SIGMA[i][0], SIGMA_CHARS[i], 0 ); + GET_UINT32_BE( SIGMA[i][1], SIGMA_CHARS[i], 4 ); + } + + /* + * Key storage in KC + * Order: KL, KR, KA, KB + */ + memset( KC, 0, sizeof(KC) ); + + /* Store KL, KR */ + for( i = 0; i < 8; i++ ) + GET_UINT32_BE( KC[i], t, i * 4 ); + + /* Generate KA */ + for( i = 0; i < 4; ++i ) + KC[8 + i] = KC[i] ^ KC[4 + i]; + + camellia_feistel( KC + 8, SIGMA[0], KC + 10 ); + camellia_feistel( KC + 10, SIGMA[1], KC + 8 ); + + for( i = 0; i < 4; ++i ) + KC[8 + i] ^= KC[i]; + + camellia_feistel( KC + 8, SIGMA[2], KC + 10 ); + camellia_feistel( KC + 10, SIGMA[3], KC + 8 ); + + if( keybits > 128 ) { + /* Generate KB */ + for( i = 0; i < 4; ++i ) + KC[12 + i] = KC[4 + i] ^ KC[8 + i]; + + camellia_feistel( KC + 12, SIGMA[4], KC + 14 ); + camellia_feistel( KC + 14, SIGMA[5], KC + 12 ); + } + + /* + * Generating subkeys + */ + + /* Manipulating KL */ + SHIFT_AND_PLACE( idx, 0 ); + + /* Manipulating KR */ + if( keybits > 128 ) { + SHIFT_AND_PLACE( idx, 1 ); + } + + /* Manipulating KA */ + SHIFT_AND_PLACE( idx, 2 ); + + /* Manipulating KB */ + if( keybits > 128 ) { + SHIFT_AND_PLACE( idx, 3 ); + } + + /* Do transpositions */ + for( i = 0; i < 20; i++ ) { + if( transposes[idx][i] != -1 ) { + RK[32 + 12 * idx + i] = RK[transposes[idx][i]]; + } + } + + return( 0 ); +} + +/* + * Camellia key schedule (decryption) + */ +int mbedtls_camellia_setkey_dec( mbedtls_camellia_context *ctx, + const unsigned char *key, + unsigned int keybits ) +{ + int idx, ret; + size_t i; + mbedtls_camellia_context cty; + uint32_t *RK; + uint32_t *SK; + CAMELLIA_VALIDATE_RET( ctx != NULL ); + CAMELLIA_VALIDATE_RET( key != NULL ); + + mbedtls_camellia_init( &cty ); + + /* Also checks keybits */ + if( ( ret = mbedtls_camellia_setkey_enc( &cty, key, keybits ) ) != 0 ) + goto exit; + + ctx->nr = cty.nr; + idx = ( ctx->nr == 4 ); + + RK = ctx->rk; + SK = cty.rk + 24 * 2 + 8 * idx * 2; + + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + + for( i = 22 + 8 * idx, SK -= 6; i > 0; i--, SK -= 4 ) + { + *RK++ = *SK++; + *RK++ = *SK++; + } + + SK -= 2; + + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + +exit: + mbedtls_camellia_free( &cty ); + + return( ret ); +} + +/* + * Camellia-ECB block encryption/decryption + */ +int mbedtls_camellia_crypt_ecb( mbedtls_camellia_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ) +{ + int NR; + uint32_t *RK, X[4]; + CAMELLIA_VALIDATE_RET( ctx != NULL ); + CAMELLIA_VALIDATE_RET( mode == MBEDTLS_CAMELLIA_ENCRYPT || + mode == MBEDTLS_CAMELLIA_DECRYPT ); + CAMELLIA_VALIDATE_RET( input != NULL ); + CAMELLIA_VALIDATE_RET( output != NULL ); + + ( (void) mode ); + + NR = ctx->nr; + RK = ctx->rk; + + GET_UINT32_BE( X[0], input, 0 ); + GET_UINT32_BE( X[1], input, 4 ); + GET_UINT32_BE( X[2], input, 8 ); + GET_UINT32_BE( X[3], input, 12 ); + + X[0] ^= *RK++; + X[1] ^= *RK++; + X[2] ^= *RK++; + X[3] ^= *RK++; + + while( NR ) { + --NR; + camellia_feistel( X, RK, X + 2 ); + RK += 2; + camellia_feistel( X + 2, RK, X ); + RK += 2; + camellia_feistel( X, RK, X + 2 ); + RK += 2; + camellia_feistel( X + 2, RK, X ); + RK += 2; + camellia_feistel( X, RK, X + 2 ); + RK += 2; + camellia_feistel( X + 2, RK, X ); + RK += 2; + + if( NR ) { + FL(X[0], X[1], RK[0], RK[1]); + RK += 2; + FLInv(X[2], X[3], RK[0], RK[1]); + RK += 2; + } + } + + X[2] ^= *RK++; + X[3] ^= *RK++; + X[0] ^= *RK++; + X[1] ^= *RK++; + + PUT_UINT32_BE( X[2], output, 0 ); + PUT_UINT32_BE( X[3], output, 4 ); + PUT_UINT32_BE( X[0], output, 8 ); + PUT_UINT32_BE( X[1], output, 12 ); + + return( 0 ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/* + * Camellia-CBC buffer encryption/decryption + */ +int mbedtls_camellia_crypt_cbc( mbedtls_camellia_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int i; + unsigned char temp[16]; + CAMELLIA_VALIDATE_RET( ctx != NULL ); + CAMELLIA_VALIDATE_RET( mode == MBEDTLS_CAMELLIA_ENCRYPT || + mode == MBEDTLS_CAMELLIA_DECRYPT ); + CAMELLIA_VALIDATE_RET( iv != NULL ); + CAMELLIA_VALIDATE_RET( length == 0 || input != NULL ); + CAMELLIA_VALIDATE_RET( length == 0 || output != NULL ); + + if( length % 16 ) + return( MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH ); + + if( mode == MBEDTLS_CAMELLIA_DECRYPT ) + { + while( length > 0 ) + { + memcpy( temp, input, 16 ); + mbedtls_camellia_crypt_ecb( ctx, mode, input, output ); + + for( i = 0; i < 16; i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, 16 ); + + input += 16; + output += 16; + length -= 16; + } + } + else + { + while( length > 0 ) + { + for( i = 0; i < 16; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + mbedtls_camellia_crypt_ecb( ctx, mode, output, output ); + memcpy( iv, output, 16 ); + + input += 16; + output += 16; + length -= 16; + } + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/* + * Camellia-CFB128 buffer encryption/decryption + */ +int mbedtls_camellia_crypt_cfb128( mbedtls_camellia_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int c; + size_t n; + CAMELLIA_VALIDATE_RET( ctx != NULL ); + CAMELLIA_VALIDATE_RET( mode == MBEDTLS_CAMELLIA_ENCRYPT || + mode == MBEDTLS_CAMELLIA_DECRYPT ); + CAMELLIA_VALIDATE_RET( iv != NULL ); + CAMELLIA_VALIDATE_RET( iv_off != NULL ); + CAMELLIA_VALIDATE_RET( length == 0 || input != NULL ); + CAMELLIA_VALIDATE_RET( length == 0 || output != NULL ); + + n = *iv_off; + if( n >= 16 ) + return( MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA ); + + if( mode == MBEDTLS_CAMELLIA_DECRYPT ) + { + while( length-- ) + { + if( n == 0 ) + mbedtls_camellia_crypt_ecb( ctx, MBEDTLS_CAMELLIA_ENCRYPT, iv, iv ); + + c = *input++; + *output++ = (unsigned char)( c ^ iv[n] ); + iv[n] = (unsigned char) c; + + n = ( n + 1 ) & 0x0F; + } + } + else + { + while( length-- ) + { + if( n == 0 ) + mbedtls_camellia_crypt_ecb( ctx, MBEDTLS_CAMELLIA_ENCRYPT, iv, iv ); + + iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); + + n = ( n + 1 ) & 0x0F; + } + } + + *iv_off = n; + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/* + * Camellia-CTR buffer encryption/decryption + */ +int mbedtls_camellia_crypt_ctr( mbedtls_camellia_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output ) +{ + int c, i; + size_t n; + CAMELLIA_VALIDATE_RET( ctx != NULL ); + CAMELLIA_VALIDATE_RET( nonce_counter != NULL ); + CAMELLIA_VALIDATE_RET( stream_block != NULL ); + CAMELLIA_VALIDATE_RET( nc_off != NULL ); + CAMELLIA_VALIDATE_RET( length == 0 || input != NULL ); + CAMELLIA_VALIDATE_RET( length == 0 || output != NULL ); + + n = *nc_off; + if( n >= 16 ) + return( MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA ); + + while( length-- ) + { + if( n == 0 ) { + mbedtls_camellia_crypt_ecb( ctx, MBEDTLS_CAMELLIA_ENCRYPT, nonce_counter, + stream_block ); + + for( i = 16; i > 0; i-- ) + if( ++nonce_counter[i - 1] != 0 ) + break; + } + c = *input++; + *output++ = (unsigned char)( c ^ stream_block[n] ); + + n = ( n + 1 ) & 0x0F; + } + + *nc_off = n; + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ +#endif /* !MBEDTLS_CAMELLIA_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +/* + * Camellia test vectors from: + * + * http://info.isl.ntt.co.jp/crypt/eng/camellia/technology.html: + * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/cryptrec/intermediate.txt + * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/cryptrec/t_camellia.txt + * (For each bitlength: Key 0, Nr 39) + */ +#define CAMELLIA_TESTS_ECB 2 + +static const unsigned char camellia_test_ecb_key[3][CAMELLIA_TESTS_ECB][32] = +{ + { + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } + }, + { + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }, + { 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, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } + }, +}; + +static const unsigned char camellia_test_ecb_plain[CAMELLIA_TESTS_ECB][16] = +{ + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, + { 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } +}; + +static const unsigned char camellia_test_ecb_cipher[3][CAMELLIA_TESTS_ECB][16] = +{ + { + { 0x67, 0x67, 0x31, 0x38, 0x54, 0x96, 0x69, 0x73, + 0x08, 0x57, 0x06, 0x56, 0x48, 0xea, 0xbe, 0x43 }, + { 0x38, 0x3C, 0x6C, 0x2A, 0xAB, 0xEF, 0x7F, 0xDE, + 0x25, 0xCD, 0x47, 0x0B, 0xF7, 0x74, 0xA3, 0x31 } + }, + { + { 0xb4, 0x99, 0x34, 0x01, 0xb3, 0xe9, 0x96, 0xf8, + 0x4e, 0xe5, 0xce, 0xe7, 0xd7, 0x9b, 0x09, 0xb9 }, + { 0xD1, 0x76, 0x3F, 0xC0, 0x19, 0xD7, 0x7C, 0xC9, + 0x30, 0xBF, 0xF2, 0xA5, 0x6F, 0x7C, 0x93, 0x64 } + }, + { + { 0x9a, 0xcc, 0x23, 0x7d, 0xff, 0x16, 0xd7, 0x6c, + 0x20, 0xef, 0x7c, 0x91, 0x9e, 0x3a, 0x75, 0x09 }, + { 0x05, 0x03, 0xFB, 0x10, 0xAB, 0x24, 0x1E, 0x7C, + 0xF4, 0x5D, 0x8C, 0xDE, 0xEE, 0x47, 0x43, 0x35 } + } +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#define CAMELLIA_TESTS_CBC 3 + +static const unsigned char camellia_test_cbc_key[3][32] = +{ + { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, + 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C } + , + { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, + 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, + 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B } + , + { 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 } +}; + +static const unsigned char camellia_test_cbc_iv[16] = + + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F } +; + +static const unsigned char camellia_test_cbc_plain[CAMELLIA_TESTS_CBC][16] = +{ + { 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 } + +}; + +static const unsigned char camellia_test_cbc_cipher[3][CAMELLIA_TESTS_CBC][16] = +{ + { + { 0x16, 0x07, 0xCF, 0x49, 0x4B, 0x36, 0xBB, 0xF0, + 0x0D, 0xAE, 0xB0, 0xB5, 0x03, 0xC8, 0x31, 0xAB }, + { 0xA2, 0xF2, 0xCF, 0x67, 0x16, 0x29, 0xEF, 0x78, + 0x40, 0xC5, 0xA5, 0xDF, 0xB5, 0x07, 0x48, 0x87 }, + { 0x0F, 0x06, 0x16, 0x50, 0x08, 0xCF, 0x8B, 0x8B, + 0x5A, 0x63, 0x58, 0x63, 0x62, 0x54, 0x3E, 0x54 } + }, + { + { 0x2A, 0x48, 0x30, 0xAB, 0x5A, 0xC4, 0xA1, 0xA2, + 0x40, 0x59, 0x55, 0xFD, 0x21, 0x95, 0xCF, 0x93 }, + { 0x5D, 0x5A, 0x86, 0x9B, 0xD1, 0x4C, 0xE5, 0x42, + 0x64, 0xF8, 0x92, 0xA6, 0xDD, 0x2E, 0xC3, 0xD5 }, + { 0x37, 0xD3, 0x59, 0xC3, 0x34, 0x98, 0x36, 0xD8, + 0x84, 0xE3, 0x10, 0xAD, 0xDF, 0x68, 0xC4, 0x49 } + }, + { + { 0xE6, 0xCF, 0xA3, 0x5F, 0xC0, 0x2B, 0x13, 0x4A, + 0x4D, 0x2C, 0x0B, 0x67, 0x37, 0xAC, 0x3E, 0xDA }, + { 0x36, 0xCB, 0xEB, 0x73, 0xBD, 0x50, 0x4B, 0x40, + 0x70, 0xB1, 0xB7, 0xDE, 0x2B, 0x21, 0xEB, 0x50 }, + { 0xE3, 0x1A, 0x60, 0x55, 0x29, 0x7D, 0x96, 0xCA, + 0x33, 0x30, 0xCD, 0xF1, 0xB1, 0x86, 0x0A, 0x83 } + } +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/* + * Camellia-CTR test vectors from: + * + * http://www.faqs.org/rfcs/rfc5528.html + */ + +static const unsigned char camellia_test_ctr_key[3][16] = +{ + { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC, + 0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E }, + { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7, + 0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 }, + { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8, + 0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC } +}; + +static const unsigned char camellia_test_ctr_nonce_counter[3][16] = +{ + { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59, + 0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 }, + { 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F, + 0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 } +}; + +static const unsigned char camellia_test_ctr_pt[3][48] = +{ + { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62, + 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 }, + + { 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, 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 } +}; + +static const unsigned char camellia_test_ctr_ct[3][48] = +{ + { 0xD0, 0x9D, 0xC2, 0x9A, 0x82, 0x14, 0x61, 0x9A, + 0x20, 0x87, 0x7C, 0x76, 0xDB, 0x1F, 0x0B, 0x3F }, + { 0xDB, 0xF3, 0xC7, 0x8D, 0xC0, 0x83, 0x96, 0xD4, + 0xDA, 0x7C, 0x90, 0x77, 0x65, 0xBB, 0xCB, 0x44, + 0x2B, 0x8E, 0x8E, 0x0F, 0x31, 0xF0, 0xDC, 0xA7, + 0x2C, 0x74, 0x17, 0xE3, 0x53, 0x60, 0xE0, 0x48 }, + { 0xB1, 0x9D, 0x1F, 0xCD, 0xCB, 0x75, 0xEB, 0x88, + 0x2F, 0x84, 0x9C, 0xE2, 0x4D, 0x85, 0xCF, 0x73, + 0x9C, 0xE6, 0x4B, 0x2B, 0x5C, 0x9D, 0x73, 0xF1, + 0x4F, 0x2D, 0x5D, 0x9D, 0xCE, 0x98, 0x89, 0xCD, + 0xDF, 0x50, 0x86, 0x96 } +}; + +static const int camellia_test_ctr_len[3] = + { 16, 32, 36 }; +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +/* + * Checkup routine + */ +int mbedtls_camellia_self_test( int verbose ) +{ + int i, j, u, v; + unsigned char key[32]; + unsigned char buf[64]; + unsigned char src[16]; + unsigned char dst[16]; +#if defined(MBEDTLS_CIPHER_MODE_CBC) + unsigned char iv[16]; +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + size_t offset, len; + unsigned char nonce_counter[16]; + unsigned char stream_block[16]; +#endif + + mbedtls_camellia_context ctx; + + memset( key, 0, 32 ); + + for( j = 0; j < 6; j++ ) { + u = j >> 1; + v = j & 1; + + if( verbose != 0 ) + mbedtls_printf( " CAMELLIA-ECB-%3d (%s): ", 128 + u * 64, + (v == MBEDTLS_CAMELLIA_DECRYPT) ? "dec" : "enc"); + + for( i = 0; i < CAMELLIA_TESTS_ECB; i++ ) { + memcpy( key, camellia_test_ecb_key[u][i], 16 + 8 * u ); + + if( v == MBEDTLS_CAMELLIA_DECRYPT ) { + mbedtls_camellia_setkey_dec( &ctx, key, 128 + u * 64 ); + memcpy( src, camellia_test_ecb_cipher[u][i], 16 ); + memcpy( dst, camellia_test_ecb_plain[i], 16 ); + } else { /* MBEDTLS_CAMELLIA_ENCRYPT */ + mbedtls_camellia_setkey_enc( &ctx, key, 128 + u * 64 ); + memcpy( src, camellia_test_ecb_plain[i], 16 ); + memcpy( dst, camellia_test_ecb_cipher[u][i], 16 ); + } + + mbedtls_camellia_crypt_ecb( &ctx, v, src, buf ); + + if( memcmp( buf, dst, 16 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + /* + * CBC mode + */ + for( j = 0; j < 6; j++ ) + { + u = j >> 1; + v = j & 1; + + if( verbose != 0 ) + mbedtls_printf( " CAMELLIA-CBC-%3d (%s): ", 128 + u * 64, + ( v == MBEDTLS_CAMELLIA_DECRYPT ) ? "dec" : "enc" ); + + memcpy( src, camellia_test_cbc_iv, 16 ); + memcpy( dst, camellia_test_cbc_iv, 16 ); + memcpy( key, camellia_test_cbc_key[u], 16 + 8 * u ); + + if( v == MBEDTLS_CAMELLIA_DECRYPT ) { + mbedtls_camellia_setkey_dec( &ctx, key, 128 + u * 64 ); + } else { + mbedtls_camellia_setkey_enc( &ctx, key, 128 + u * 64 ); + } + + for( i = 0; i < CAMELLIA_TESTS_CBC; i++ ) { + + if( v == MBEDTLS_CAMELLIA_DECRYPT ) { + memcpy( iv , src, 16 ); + memcpy( src, camellia_test_cbc_cipher[u][i], 16 ); + memcpy( dst, camellia_test_cbc_plain[i], 16 ); + } else { /* MBEDTLS_CAMELLIA_ENCRYPT */ + memcpy( iv , dst, 16 ); + memcpy( src, camellia_test_cbc_plain[i], 16 ); + memcpy( dst, camellia_test_cbc_cipher[u][i], 16 ); + } + + mbedtls_camellia_crypt_cbc( &ctx, v, 16, iv, src, buf ); + + if( memcmp( buf, dst, 16 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +#if defined(MBEDTLS_CIPHER_MODE_CTR) + /* + * CTR mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + v = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " CAMELLIA-CTR-128 (%s): ", + ( v == MBEDTLS_CAMELLIA_DECRYPT ) ? "dec" : "enc" ); + + memcpy( nonce_counter, camellia_test_ctr_nonce_counter[u], 16 ); + memcpy( key, camellia_test_ctr_key[u], 16 ); + + offset = 0; + mbedtls_camellia_setkey_enc( &ctx, key, 128 ); + + if( v == MBEDTLS_CAMELLIA_DECRYPT ) + { + len = camellia_test_ctr_len[u]; + memcpy( buf, camellia_test_ctr_ct[u], len ); + + mbedtls_camellia_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, + buf, buf ); + + if( memcmp( buf, camellia_test_ctr_pt[u], len ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + } + else + { + len = camellia_test_ctr_len[u]; + memcpy( buf, camellia_test_ctr_pt[u], len ); + + mbedtls_camellia_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, + buf, buf ); + + if( memcmp( buf, camellia_test_ctr_ct[u], len ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_CAMELLIA_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/ccm.c b/Android/Level4/app/src/main/c/mbedtls/library/ccm.c new file mode 100644 index 0000000..424ee77 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/ccm.c @@ -0,0 +1,547 @@ +/* + * NIST SP800-38C compliant CCM implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ + +/* + * Definition of CCM: + * http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf + * RFC 3610 "Counter with CBC-MAC (CCM)" + * + * Related: + * RFC 5116 "An Interface and Algorithms for Authenticated Encryption" + */ + +#include "common.h" + +#if defined(MBEDTLS_CCM_C) + +#include "mbedtls/ccm.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#if !defined(MBEDTLS_CCM_ALT) + +#define CCM_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CCM_BAD_INPUT ) +#define CCM_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#define CCM_ENCRYPT 0 +#define CCM_DECRYPT 1 + +/* + * Initialize context + */ +void mbedtls_ccm_init( mbedtls_ccm_context *ctx ) +{ + CCM_VALIDATE( ctx != NULL ); + memset( ctx, 0, sizeof( mbedtls_ccm_context ) ); +} + +int mbedtls_ccm_setkey( mbedtls_ccm_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const mbedtls_cipher_info_t *cipher_info; + + CCM_VALIDATE_RET( ctx != NULL ); + CCM_VALIDATE_RET( key != NULL ); + + cipher_info = mbedtls_cipher_info_from_values( cipher, keybits, + MBEDTLS_MODE_ECB ); + if( cipher_info == NULL ) + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + + if( cipher_info->block_size != 16 ) + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + + mbedtls_cipher_free( &ctx->cipher_ctx ); + + if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits, + MBEDTLS_ENCRYPT ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} + +/* + * Free context + */ +void mbedtls_ccm_free( mbedtls_ccm_context *ctx ) +{ + if( ctx == NULL ) + return; + mbedtls_cipher_free( &ctx->cipher_ctx ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ccm_context ) ); +} + +/* + * Macros for common operations. + * Results in smaller compiled code than static inline functions. + */ + +/* + * Update the CBC-MAC state in y using a block in b + * (Always using b as the source helps the compiler optimise a bit better.) + */ +#define UPDATE_CBC_MAC \ + for( i = 0; i < 16; i++ ) \ + y[i] ^= b[i]; \ + \ + if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, y, 16, y, &olen ) ) != 0 ) \ + return( ret ); + +/* + * Encrypt or decrypt a partial block with CTR + * Warning: using b for temporary storage! src and dst must not be b! + * This avoids allocating one more 16 bytes buffer while allowing src == dst. + */ +#define CTR_CRYPT( dst, src, len ) \ + do \ + { \ + if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctr, \ + 16, b, &olen ) ) != 0 ) \ + { \ + return( ret ); \ + } \ + \ + for( i = 0; i < (len); i++ ) \ + (dst)[i] = (src)[i] ^ b[i]; \ + } while( 0 ) + +/* + * Authenticated encryption or decryption + */ +static int ccm_auth_crypt( mbedtls_ccm_context *ctx, int mode, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + unsigned char *tag, size_t tag_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char i; + unsigned char q; + size_t len_left, olen; + unsigned char b[16]; + unsigned char y[16]; + unsigned char ctr[16]; + const unsigned char *src; + unsigned char *dst; + + /* + * Check length requirements: SP800-38C A.1 + * Additional requirement: a < 2^16 - 2^8 to simplify the code. + * 'length' checked later (when writing it to the first block) + * + * Also, loosen the requirements to enable support for CCM* (IEEE 802.15.4). + */ + if( tag_len == 2 || tag_len > 16 || tag_len % 2 != 0 ) + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + + /* Also implies q is within bounds */ + if( iv_len < 7 || iv_len > 13 ) + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + + if( add_len >= 0xFF00 ) + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + + q = 16 - 1 - (unsigned char) iv_len; + + /* + * First block B_0: + * 0 .. 0 flags + * 1 .. iv_len nonce (aka iv) + * iv_len+1 .. 15 length + * + * With flags as (bits): + * 7 0 + * 6 add present? + * 5 .. 3 (t - 2) / 2 + * 2 .. 0 q - 1 + */ + b[0] = 0; + b[0] |= ( add_len > 0 ) << 6; + b[0] |= ( ( tag_len - 2 ) / 2 ) << 3; + b[0] |= q - 1; + + memcpy( b + 1, iv, iv_len ); + + for( i = 0, len_left = length; i < q; i++, len_left >>= 8 ) + b[15-i] = (unsigned char)( len_left & 0xFF ); + + if( len_left > 0 ) + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + + + /* Start CBC-MAC with first block */ + memset( y, 0, 16 ); + UPDATE_CBC_MAC; + + /* + * If there is additional data, update CBC-MAC with + * add_len, add, 0 (padding to a block boundary) + */ + if( add_len > 0 ) + { + size_t use_len; + len_left = add_len; + src = add; + + memset( b, 0, 16 ); + b[0] = (unsigned char)( ( add_len >> 8 ) & 0xFF ); + b[1] = (unsigned char)( ( add_len ) & 0xFF ); + + use_len = len_left < 16 - 2 ? len_left : 16 - 2; + memcpy( b + 2, src, use_len ); + len_left -= use_len; + src += use_len; + + UPDATE_CBC_MAC; + + while( len_left > 0 ) + { + use_len = len_left > 16 ? 16 : len_left; + + memset( b, 0, 16 ); + memcpy( b, src, use_len ); + UPDATE_CBC_MAC; + + len_left -= use_len; + src += use_len; + } + } + + /* + * Prepare counter block for encryption: + * 0 .. 0 flags + * 1 .. iv_len nonce (aka iv) + * iv_len+1 .. 15 counter (initially 1) + * + * With flags as (bits): + * 7 .. 3 0 + * 2 .. 0 q - 1 + */ + ctr[0] = q - 1; + memcpy( ctr + 1, iv, iv_len ); + memset( ctr + 1 + iv_len, 0, q ); + ctr[15] = 1; + + /* + * Authenticate and {en,de}crypt the message. + * + * The only difference between encryption and decryption is + * the respective order of authentication and {en,de}cryption. + */ + len_left = length; + src = input; + dst = output; + + while( len_left > 0 ) + { + size_t use_len = len_left > 16 ? 16 : len_left; + + if( mode == CCM_ENCRYPT ) + { + memset( b, 0, 16 ); + memcpy( b, src, use_len ); + UPDATE_CBC_MAC; + } + + CTR_CRYPT( dst, src, use_len ); + + if( mode == CCM_DECRYPT ) + { + memset( b, 0, 16 ); + memcpy( b, dst, use_len ); + UPDATE_CBC_MAC; + } + + dst += use_len; + src += use_len; + len_left -= use_len; + + /* + * Increment counter. + * No need to check for overflow thanks to the length check above. + */ + for( i = 0; i < q; i++ ) + if( ++ctr[15-i] != 0 ) + break; + } + + /* + * Authentication: reset counter and crypt/mask internal tag + */ + for( i = 0; i < q; i++ ) + ctr[15-i] = 0; + + CTR_CRYPT( y, y, 16 ); + memcpy( tag, y, tag_len ); + + return( 0 ); +} + +/* + * Authenticated encryption + */ +int mbedtls_ccm_star_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + unsigned char *tag, size_t tag_len ) +{ + CCM_VALIDATE_RET( ctx != NULL ); + CCM_VALIDATE_RET( iv != NULL ); + CCM_VALIDATE_RET( add_len == 0 || add != NULL ); + CCM_VALIDATE_RET( length == 0 || input != NULL ); + CCM_VALIDATE_RET( length == 0 || output != NULL ); + CCM_VALIDATE_RET( tag_len == 0 || tag != NULL ); + return( ccm_auth_crypt( ctx, CCM_ENCRYPT, length, iv, iv_len, + add, add_len, input, output, tag, tag_len ) ); +} + +int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + unsigned char *tag, size_t tag_len ) +{ + CCM_VALIDATE_RET( ctx != NULL ); + CCM_VALIDATE_RET( iv != NULL ); + CCM_VALIDATE_RET( add_len == 0 || add != NULL ); + CCM_VALIDATE_RET( length == 0 || input != NULL ); + CCM_VALIDATE_RET( length == 0 || output != NULL ); + CCM_VALIDATE_RET( tag_len == 0 || tag != NULL ); + if( tag_len == 0 ) + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + + return( mbedtls_ccm_star_encrypt_and_tag( ctx, length, iv, iv_len, add, + add_len, input, output, tag, tag_len ) ); +} + +/* + * Authenticated decryption + */ +int mbedtls_ccm_star_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + const unsigned char *tag, size_t tag_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char check_tag[16]; + unsigned char i; + int diff; + + CCM_VALIDATE_RET( ctx != NULL ); + CCM_VALIDATE_RET( iv != NULL ); + CCM_VALIDATE_RET( add_len == 0 || add != NULL ); + CCM_VALIDATE_RET( length == 0 || input != NULL ); + CCM_VALIDATE_RET( length == 0 || output != NULL ); + CCM_VALIDATE_RET( tag_len == 0 || tag != NULL ); + + if( ( ret = ccm_auth_crypt( ctx, CCM_DECRYPT, length, + iv, iv_len, add, add_len, + input, output, check_tag, tag_len ) ) != 0 ) + { + return( ret ); + } + + /* Check tag in "constant-time" */ + for( diff = 0, i = 0; i < tag_len; i++ ) + diff |= tag[i] ^ check_tag[i]; + + if( diff != 0 ) + { + mbedtls_platform_zeroize( output, length ); + return( MBEDTLS_ERR_CCM_AUTH_FAILED ); + } + + return( 0 ); +} + +int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + const unsigned char *tag, size_t tag_len ) +{ + CCM_VALIDATE_RET( ctx != NULL ); + CCM_VALIDATE_RET( iv != NULL ); + CCM_VALIDATE_RET( add_len == 0 || add != NULL ); + CCM_VALIDATE_RET( length == 0 || input != NULL ); + CCM_VALIDATE_RET( length == 0 || output != NULL ); + CCM_VALIDATE_RET( tag_len == 0 || tag != NULL ); + + if( tag_len == 0 ) + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + + return( mbedtls_ccm_star_auth_decrypt( ctx, length, iv, iv_len, add, + add_len, input, output, tag, tag_len ) ); +} +#endif /* !MBEDTLS_CCM_ALT */ + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +/* + * Examples 1 to 3 from SP800-38C Appendix C + */ + +#define NB_TESTS 3 +#define CCM_SELFTEST_PT_MAX_LEN 24 +#define CCM_SELFTEST_CT_MAX_LEN 32 +/* + * The data is the same for all tests, only the used length changes + */ +static const unsigned char key_test_data[] = { + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f +}; + +static const unsigned char iv_test_data[] = { + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b +}; + +static const unsigned char ad_test_data[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13 +}; + +static const unsigned char msg_test_data[CCM_SELFTEST_PT_MAX_LEN] = { + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, +}; + +static const size_t iv_len_test_data [NB_TESTS] = { 7, 8, 12 }; +static const size_t add_len_test_data[NB_TESTS] = { 8, 16, 20 }; +static const size_t msg_len_test_data[NB_TESTS] = { 4, 16, 24 }; +static const size_t tag_len_test_data[NB_TESTS] = { 4, 6, 8 }; + +static const unsigned char res_test_data[NB_TESTS][CCM_SELFTEST_CT_MAX_LEN] = { + { 0x71, 0x62, 0x01, 0x5b, 0x4d, 0xac, 0x25, 0x5d }, + { 0xd2, 0xa1, 0xf0, 0xe0, 0x51, 0xea, 0x5f, 0x62, + 0x08, 0x1a, 0x77, 0x92, 0x07, 0x3d, 0x59, 0x3d, + 0x1f, 0xc6, 0x4f, 0xbf, 0xac, 0xcd }, + { 0xe3, 0xb2, 0x01, 0xa9, 0xf5, 0xb7, 0x1a, 0x7a, + 0x9b, 0x1c, 0xea, 0xec, 0xcd, 0x97, 0xe7, 0x0b, + 0x61, 0x76, 0xaa, 0xd9, 0xa4, 0x42, 0x8a, 0xa5, + 0x48, 0x43, 0x92, 0xfb, 0xc1, 0xb0, 0x99, 0x51 } +}; + +int mbedtls_ccm_self_test( int verbose ) +{ + mbedtls_ccm_context ctx; + /* + * Some hardware accelerators require the input and output buffers + * would be in RAM, because the flash is not accessible. + * Use buffers on the stack to hold the test vectors data. + */ + unsigned char plaintext[CCM_SELFTEST_PT_MAX_LEN]; + unsigned char ciphertext[CCM_SELFTEST_CT_MAX_LEN]; + size_t i; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + mbedtls_ccm_init( &ctx ); + + if( mbedtls_ccm_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, key_test_data, + 8 * sizeof key_test_data ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( " CCM: setup failed" ); + + return( 1 ); + } + + for( i = 0; i < NB_TESTS; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " CCM-AES #%u: ", (unsigned int) i + 1 ); + + memset( plaintext, 0, CCM_SELFTEST_PT_MAX_LEN ); + memset( ciphertext, 0, CCM_SELFTEST_CT_MAX_LEN ); + memcpy( plaintext, msg_test_data, msg_len_test_data[i] ); + + ret = mbedtls_ccm_encrypt_and_tag( &ctx, msg_len_test_data[i], + iv_test_data, iv_len_test_data[i], + ad_test_data, add_len_test_data[i], + plaintext, ciphertext, + ciphertext + msg_len_test_data[i], + tag_len_test_data[i] ); + + if( ret != 0 || + memcmp( ciphertext, res_test_data[i], + msg_len_test_data[i] + tag_len_test_data[i] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + memset( plaintext, 0, CCM_SELFTEST_PT_MAX_LEN ); + + ret = mbedtls_ccm_auth_decrypt( &ctx, msg_len_test_data[i], + iv_test_data, iv_len_test_data[i], + ad_test_data, add_len_test_data[i], + ciphertext, plaintext, + ciphertext + msg_len_test_data[i], + tag_len_test_data[i] ); + + if( ret != 0 || + memcmp( plaintext, msg_test_data, msg_len_test_data[i] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + mbedtls_ccm_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#endif /* MBEDTLS_CCM_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/certs.c b/Android/Level4/app/src/main/c/mbedtls/library/certs.c new file mode 100644 index 0000000..a5695e3 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/certs.c @@ -0,0 +1,1746 @@ +/* + * X.509 test certificates + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 "common.h" + +#include "mbedtls/certs.h" + +#if defined(MBEDTLS_CERTS_C) + +/* + * Test CA Certificates + * + * We define test CA certificates for each choice of the following parameters: + * - PEM or DER encoding + * - SHA-1 or SHA-256 hash + * - RSA or EC key + * + * Things to add: + * - multiple EC curve types + * + */ + +/* This is taken from tests/data_files/test-ca2.crt */ +/* BEGIN FILE string macro TEST_CA_CRT_EC_PEM tests/data_files/test-ca2.crt */ +#define TEST_CA_CRT_EC_PEM \ + "-----BEGIN CERTIFICATE-----\r\n" \ + "MIICBDCCAYigAwIBAgIJAMFD4n5iQ8zoMAwGCCqGSM49BAMCBQAwPjELMAkGA1UE\r\n" \ + "BhMCTkwxETAPBgNVBAoMCFBvbGFyU1NMMRwwGgYDVQQDDBNQb2xhcnNzbCBUZXN0\r\n" \ + "IEVDIENBMB4XDTE5MDIxMDE0NDQwMFoXDTI5MDIxMDE0NDQwMFowPjELMAkGA1UE\r\n" \ + "BhMCTkwxETAPBgNVBAoMCFBvbGFyU1NMMRwwGgYDVQQDDBNQb2xhcnNzbCBUZXN0\r\n" \ + "IEVDIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEw9orNEE3WC+HVv78ibopQ0tO\r\n" \ + "4G7DDldTMzlY1FK0kZU5CyPfXxckYkj8GpUpziwth8KIUoCv1mqrId240xxuWLjK\r\n" \ + "6LJpjvNBrSnDtF91p0dv1RkpVWmaUzsgtGYWYDMeo1AwTjAMBgNVHRMEBTADAQH/\r\n" \ + "MB0GA1UdDgQWBBSdbSAkSQE/K8t4tRm8fiTJ2/s2fDAfBgNVHSMEGDAWgBSdbSAk\r\n" \ + "SQE/K8t4tRm8fiTJ2/s2fDAMBggqhkjOPQQDAgUAA2gAMGUCMFHKrjAPpHB0BN1a\r\n" \ + "LH8TwcJ3vh0AxeKZj30mRdOKBmg/jLS3rU3g8VQBHpn8sOTTBwIxANxPO5AerimZ\r\n" \ + "hCjMe0d4CTHf1gFZMF70+IqEP+o5VHsIp2Cqvflb0VGWFC5l9a4cQg==\r\n" \ + "-----END CERTIFICATE-----\r\n" +/* END FILE */ + +/* This is generated from tests/data_files/test-ca2.crt.der using `xxd -i`. */ +/* BEGIN FILE binary macro TEST_CA_CRT_EC_DER tests/data_files/test-ca2.crt.der */ +#define TEST_CA_CRT_EC_DER { \ + 0x30, 0x82, 0x02, 0x04, 0x30, 0x82, 0x01, 0x88, 0xa0, 0x03, 0x02, 0x01, \ + 0x02, 0x02, 0x09, 0x00, 0xc1, 0x43, 0xe2, 0x7e, 0x62, 0x43, 0xcc, 0xe8, \ + 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, \ + 0x05, 0x00, 0x30, 0x3e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, \ + 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, \ + 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, \ + 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x13, 0x50, \ + 0x6f, 0x6c, 0x61, 0x72, 0x73, 0x73, 0x6c, 0x20, 0x54, 0x65, 0x73, 0x74, \ + 0x20, 0x45, 0x43, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x39, \ + 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, 0x30, 0x30, 0x5a, 0x17, \ + 0x0d, 0x32, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, 0x30, \ + 0x30, 0x5a, 0x30, 0x3e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, \ + 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, \ + 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, \ + 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x13, 0x50, \ + 0x6f, 0x6c, 0x61, 0x72, 0x73, 0x73, 0x6c, 0x20, 0x54, 0x65, 0x73, 0x74, \ + 0x20, 0x45, 0x43, 0x20, 0x43, 0x41, 0x30, 0x76, 0x30, 0x10, 0x06, 0x07, \ + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, \ + 0x00, 0x22, 0x03, 0x62, 0x00, 0x04, 0xc3, 0xda, 0x2b, 0x34, 0x41, 0x37, \ + 0x58, 0x2f, 0x87, 0x56, 0xfe, 0xfc, 0x89, 0xba, 0x29, 0x43, 0x4b, 0x4e, \ + 0xe0, 0x6e, 0xc3, 0x0e, 0x57, 0x53, 0x33, 0x39, 0x58, 0xd4, 0x52, 0xb4, \ + 0x91, 0x95, 0x39, 0x0b, 0x23, 0xdf, 0x5f, 0x17, 0x24, 0x62, 0x48, 0xfc, \ + 0x1a, 0x95, 0x29, 0xce, 0x2c, 0x2d, 0x87, 0xc2, 0x88, 0x52, 0x80, 0xaf, \ + 0xd6, 0x6a, 0xab, 0x21, 0xdd, 0xb8, 0xd3, 0x1c, 0x6e, 0x58, 0xb8, 0xca, \ + 0xe8, 0xb2, 0x69, 0x8e, 0xf3, 0x41, 0xad, 0x29, 0xc3, 0xb4, 0x5f, 0x75, \ + 0xa7, 0x47, 0x6f, 0xd5, 0x19, 0x29, 0x55, 0x69, 0x9a, 0x53, 0x3b, 0x20, \ + 0xb4, 0x66, 0x16, 0x60, 0x33, 0x1e, 0xa3, 0x50, 0x30, 0x4e, 0x30, 0x0c, \ + 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, \ + 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x9d, \ + 0x6d, 0x20, 0x24, 0x49, 0x01, 0x3f, 0x2b, 0xcb, 0x78, 0xb5, 0x19, 0xbc, \ + 0x7e, 0x24, 0xc9, 0xdb, 0xfb, 0x36, 0x7c, 0x30, 0x1f, 0x06, 0x03, 0x55, \ + 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x9d, 0x6d, 0x20, 0x24, \ + 0x49, 0x01, 0x3f, 0x2b, 0xcb, 0x78, 0xb5, 0x19, 0xbc, 0x7e, 0x24, 0xc9, \ + 0xdb, 0xfb, 0x36, 0x7c, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, \ + 0x3d, 0x04, 0x03, 0x02, 0x05, 0x00, 0x03, 0x68, 0x00, 0x30, 0x65, 0x02, \ + 0x30, 0x51, 0xca, 0xae, 0x30, 0x0f, 0xa4, 0x70, 0x74, 0x04, 0xdd, 0x5a, \ + 0x2c, 0x7f, 0x13, 0xc1, 0xc2, 0x77, 0xbe, 0x1d, 0x00, 0xc5, 0xe2, 0x99, \ + 0x8f, 0x7d, 0x26, 0x45, 0xd3, 0x8a, 0x06, 0x68, 0x3f, 0x8c, 0xb4, 0xb7, \ + 0xad, 0x4d, 0xe0, 0xf1, 0x54, 0x01, 0x1e, 0x99, 0xfc, 0xb0, 0xe4, 0xd3, \ + 0x07, 0x02, 0x31, 0x00, 0xdc, 0x4f, 0x3b, 0x90, 0x1e, 0xae, 0x29, 0x99, \ + 0x84, 0x28, 0xcc, 0x7b, 0x47, 0x78, 0x09, 0x31, 0xdf, 0xd6, 0x01, 0x59, \ + 0x30, 0x5e, 0xf4, 0xf8, 0x8a, 0x84, 0x3f, 0xea, 0x39, 0x54, 0x7b, 0x08, \ + 0xa7, 0x60, 0xaa, 0xbd, 0xf9, 0x5b, 0xd1, 0x51, 0x96, 0x14, 0x2e, 0x65, \ + 0xf5, 0xae, 0x1c, 0x42 \ +} +/* END FILE */ + +/* This is taken from tests/data_files/test-ca2.key.enc */ +/* BEGIN FILE string macro TEST_CA_KEY_EC_PEM tests/data_files/test-ca2.key.enc */ +#define TEST_CA_KEY_EC_PEM \ + "-----BEGIN EC PRIVATE KEY-----\r\n" \ + "Proc-Type: 4,ENCRYPTED\r\n" \ + "DEK-Info: DES-EDE3-CBC,307EAB469933D64E\r\n" \ + "\r\n" \ + "IxbrRmKcAzctJqPdTQLA4SWyBYYGYJVkYEna+F7Pa5t5Yg/gKADrFKcm6B72e7DG\r\n" \ + "ihExtZI648s0zdYw6qSJ74vrPSuWDe5qm93BqsfVH9svtCzWHW0pm1p0KTBCFfUq\r\n" \ + "UsuWTITwJImcnlAs1gaRZ3sAWm7cOUidL0fo2G0fYUFNcYoCSLffCFTEHBuPnagb\r\n" \ + "a77x/sY1Bvii8S9/XhDTb6pTMx06wzrm\r\n" \ + "-----END EC PRIVATE KEY-----\r\n" +/* END FILE */ + +#define TEST_CA_PWD_EC_PEM "PolarSSLTest" + +/* This is generated from tests/data_files/test-ca2.key.der using `xxd -i`. */ +/* BEGIN FILE binary macro TEST_CA_KEY_EC_DER tests/data_files/test-ca2.key.der */ +#define TEST_CA_KEY_EC_DER { \ + 0x30, 0x81, 0xa4, 0x02, 0x01, 0x01, 0x04, 0x30, 0x83, 0xd9, 0x15, 0x0e, \ + 0xa0, 0x71, 0xf0, 0x57, 0x10, 0x33, 0xa3, 0x38, 0xb8, 0x86, 0xc1, 0xa6, \ + 0x11, 0x5d, 0x6d, 0xb4, 0x03, 0xe1, 0x29, 0x76, 0x45, 0xd7, 0x87, 0x6f, \ + 0x23, 0xab, 0x44, 0x20, 0xea, 0x64, 0x7b, 0x85, 0xb1, 0x76, 0xe7, 0x85, \ + 0x95, 0xaa, 0x74, 0xd6, 0xd1, 0xa4, 0x5e, 0xea, 0xa0, 0x07, 0x06, 0x05, \ + 0x2b, 0x81, 0x04, 0x00, 0x22, 0xa1, 0x64, 0x03, 0x62, 0x00, 0x04, 0xc3, \ + 0xda, 0x2b, 0x34, 0x41, 0x37, 0x58, 0x2f, 0x87, 0x56, 0xfe, 0xfc, 0x89, \ + 0xba, 0x29, 0x43, 0x4b, 0x4e, 0xe0, 0x6e, 0xc3, 0x0e, 0x57, 0x53, 0x33, \ + 0x39, 0x58, 0xd4, 0x52, 0xb4, 0x91, 0x95, 0x39, 0x0b, 0x23, 0xdf, 0x5f, \ + 0x17, 0x24, 0x62, 0x48, 0xfc, 0x1a, 0x95, 0x29, 0xce, 0x2c, 0x2d, 0x87, \ + 0xc2, 0x88, 0x52, 0x80, 0xaf, 0xd6, 0x6a, 0xab, 0x21, 0xdd, 0xb8, 0xd3, \ + 0x1c, 0x6e, 0x58, 0xb8, 0xca, 0xe8, 0xb2, 0x69, 0x8e, 0xf3, 0x41, 0xad, \ + 0x29, 0xc3, 0xb4, 0x5f, 0x75, 0xa7, 0x47, 0x6f, 0xd5, 0x19, 0x29, 0x55, \ + 0x69, 0x9a, 0x53, 0x3b, 0x20, 0xb4, 0x66, 0x16, 0x60, 0x33, 0x1e \ +} +/* END FILE */ + +/* This is taken from tests/data_files/test-ca-sha256.crt. */ +/* BEGIN FILE string macro TEST_CA_CRT_RSA_SHA256_PEM tests/data_files/test-ca-sha256.crt */ +#define TEST_CA_CRT_RSA_SHA256_PEM \ + "-----BEGIN CERTIFICATE-----\r\n" \ + "MIIDQTCCAimgAwIBAgIBAzANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER\r\n" \ + "MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" \ + "MTkwMjEwMTQ0NDAwWhcNMjkwMjEwMTQ0NDAwWjA7MQswCQYDVQQGEwJOTDERMA8G\r\n" \ + "A1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwggEiMA0G\r\n" \ + "CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDA3zf8F7vglp0/ht6WMn1EpRagzSHx\r\n" \ + "mdTs6st8GFgIlKXsm8WL3xoemTiZhx57wI053zhdcHgH057Zk+i5clHFzqMwUqny\r\n" \ + "50BwFMtEonILwuVA+T7lpg6z+exKY8C4KQB0nFc7qKUEkHHxvYPZP9al4jwqj+8n\r\n" \ + "YMPGn8u67GB9t+aEMr5P+1gmIgNb1LTV+/Xjli5wwOQuvfwu7uJBVcA0Ln0kcmnL\r\n" \ + "R7EUQIN9Z/SG9jGr8XmksrUuEvmEF/Bibyc+E1ixVA0hmnM3oTDPb5Lc9un8rNsu\r\n" \ + "KNF+AksjoBXyOGVkCeoMbo4bF6BxyLObyavpw/LPh5aPgAIynplYb6LVAgMBAAGj\r\n" \ + "UDBOMAwGA1UdEwQFMAMBAf8wHQYDVR0OBBYEFLRa5KWz3tJS9rnVppUP6z68x/3/\r\n" \ + "MB8GA1UdIwQYMBaAFLRa5KWz3tJS9rnVppUP6z68x/3/MA0GCSqGSIb3DQEBCwUA\r\n" \ + "A4IBAQA4qFSCth2q22uJIdE4KGHJsJjVEfw2/xn+MkTvCMfxVrvmRvqCtjE4tKDl\r\n" \ + "oK4MxFOek07oDZwvtAT9ijn1hHftTNS7RH9zd/fxNpfcHnMZXVC4w4DNA1fSANtW\r\n" \ + "5sY1JB5Je9jScrsLSS+mAjyv0Ow3Hb2Bix8wu7xNNrV5fIf7Ubm+wt6SqEBxu3Kb\r\n" \ + "+EfObAT4huf3czznhH3C17ed6NSbXwoXfby7stWUDeRJv08RaFOykf/Aae7bY5PL\r\n" \ + "yTVrkAnikMntJ9YI+hNNYt3inqq11A5cN0+rVTst8UKCxzQ4GpvroSwPKTFkbMw4\r\n" \ + "/anT1dVxr/BtwJfiESoK3/4CeXR1\r\n" \ + "-----END CERTIFICATE-----\r\n" +/* END FILE */ + +/* This is generated from tests/data_files/test-ca-sha256.crt.der + * using `xxd -i`. */ +/* BEGIN FILE binary macro TEST_CA_CRT_RSA_SHA256_DER tests/data_files/test-ca-sha256.crt.der */ +#define TEST_CA_CRT_RSA_SHA256_DER { \ + 0x30, 0x82, 0x03, 0x41, 0x30, 0x82, 0x02, 0x29, 0xa0, 0x03, 0x02, 0x01, \ + 0x02, 0x02, 0x01, 0x03, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, \ + 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x3b, 0x31, 0x0b, 0x30, \ + 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, \ + 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, \ + 0x61, 0x72, 0x53, 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, \ + 0x04, 0x03, 0x0c, 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, \ + 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, \ + 0x31, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, 0x30, 0x30, \ + 0x5a, 0x17, 0x0d, 0x32, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, \ + 0x34, 0x30, 0x30, 0x5a, 0x30, 0x3b, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, \ + 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, \ + 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, \ + 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, \ + 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, 0x20, 0x54, 0x65, \ + 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, \ + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, \ + 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, \ + 0x01, 0x00, 0xc0, 0xdf, 0x37, 0xfc, 0x17, 0xbb, 0xe0, 0x96, 0x9d, 0x3f, \ + 0x86, 0xde, 0x96, 0x32, 0x7d, 0x44, 0xa5, 0x16, 0xa0, 0xcd, 0x21, 0xf1, \ + 0x99, 0xd4, 0xec, 0xea, 0xcb, 0x7c, 0x18, 0x58, 0x08, 0x94, 0xa5, 0xec, \ + 0x9b, 0xc5, 0x8b, 0xdf, 0x1a, 0x1e, 0x99, 0x38, 0x99, 0x87, 0x1e, 0x7b, \ + 0xc0, 0x8d, 0x39, 0xdf, 0x38, 0x5d, 0x70, 0x78, 0x07, 0xd3, 0x9e, 0xd9, \ + 0x93, 0xe8, 0xb9, 0x72, 0x51, 0xc5, 0xce, 0xa3, 0x30, 0x52, 0xa9, 0xf2, \ + 0xe7, 0x40, 0x70, 0x14, 0xcb, 0x44, 0xa2, 0x72, 0x0b, 0xc2, 0xe5, 0x40, \ + 0xf9, 0x3e, 0xe5, 0xa6, 0x0e, 0xb3, 0xf9, 0xec, 0x4a, 0x63, 0xc0, 0xb8, \ + 0x29, 0x00, 0x74, 0x9c, 0x57, 0x3b, 0xa8, 0xa5, 0x04, 0x90, 0x71, 0xf1, \ + 0xbd, 0x83, 0xd9, 0x3f, 0xd6, 0xa5, 0xe2, 0x3c, 0x2a, 0x8f, 0xef, 0x27, \ + 0x60, 0xc3, 0xc6, 0x9f, 0xcb, 0xba, 0xec, 0x60, 0x7d, 0xb7, 0xe6, 0x84, \ + 0x32, 0xbe, 0x4f, 0xfb, 0x58, 0x26, 0x22, 0x03, 0x5b, 0xd4, 0xb4, 0xd5, \ + 0xfb, 0xf5, 0xe3, 0x96, 0x2e, 0x70, 0xc0, 0xe4, 0x2e, 0xbd, 0xfc, 0x2e, \ + 0xee, 0xe2, 0x41, 0x55, 0xc0, 0x34, 0x2e, 0x7d, 0x24, 0x72, 0x69, 0xcb, \ + 0x47, 0xb1, 0x14, 0x40, 0x83, 0x7d, 0x67, 0xf4, 0x86, 0xf6, 0x31, 0xab, \ + 0xf1, 0x79, 0xa4, 0xb2, 0xb5, 0x2e, 0x12, 0xf9, 0x84, 0x17, 0xf0, 0x62, \ + 0x6f, 0x27, 0x3e, 0x13, 0x58, 0xb1, 0x54, 0x0d, 0x21, 0x9a, 0x73, 0x37, \ + 0xa1, 0x30, 0xcf, 0x6f, 0x92, 0xdc, 0xf6, 0xe9, 0xfc, 0xac, 0xdb, 0x2e, \ + 0x28, 0xd1, 0x7e, 0x02, 0x4b, 0x23, 0xa0, 0x15, 0xf2, 0x38, 0x65, 0x64, \ + 0x09, 0xea, 0x0c, 0x6e, 0x8e, 0x1b, 0x17, 0xa0, 0x71, 0xc8, 0xb3, 0x9b, \ + 0xc9, 0xab, 0xe9, 0xc3, 0xf2, 0xcf, 0x87, 0x96, 0x8f, 0x80, 0x02, 0x32, \ + 0x9e, 0x99, 0x58, 0x6f, 0xa2, 0xd5, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, \ + 0x50, 0x30, 0x4e, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, \ + 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, \ + 0x04, 0x16, 0x04, 0x14, 0xb4, 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, \ + 0xf6, 0xb9, 0xd5, 0xa6, 0x95, 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, \ + 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, \ + 0x14, 0xb4, 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, 0xf6, 0xb9, 0xd5, \ + 0xa6, 0x95, 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, 0x30, 0x0d, 0x06, \ + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, \ + 0x03, 0x82, 0x01, 0x01, 0x00, 0x38, 0xa8, 0x54, 0x82, 0xb6, 0x1d, 0xaa, \ + 0xdb, 0x6b, 0x89, 0x21, 0xd1, 0x38, 0x28, 0x61, 0xc9, 0xb0, 0x98, 0xd5, \ + 0x11, 0xfc, 0x36, 0xff, 0x19, 0xfe, 0x32, 0x44, 0xef, 0x08, 0xc7, 0xf1, \ + 0x56, 0xbb, 0xe6, 0x46, 0xfa, 0x82, 0xb6, 0x31, 0x38, 0xb4, 0xa0, 0xe5, \ + 0xa0, 0xae, 0x0c, 0xc4, 0x53, 0x9e, 0x93, 0x4e, 0xe8, 0x0d, 0x9c, 0x2f, \ + 0xb4, 0x04, 0xfd, 0x8a, 0x39, 0xf5, 0x84, 0x77, 0xed, 0x4c, 0xd4, 0xbb, \ + 0x44, 0x7f, 0x73, 0x77, 0xf7, 0xf1, 0x36, 0x97, 0xdc, 0x1e, 0x73, 0x19, \ + 0x5d, 0x50, 0xb8, 0xc3, 0x80, 0xcd, 0x03, 0x57, 0xd2, 0x00, 0xdb, 0x56, \ + 0xe6, 0xc6, 0x35, 0x24, 0x1e, 0x49, 0x7b, 0xd8, 0xd2, 0x72, 0xbb, 0x0b, \ + 0x49, 0x2f, 0xa6, 0x02, 0x3c, 0xaf, 0xd0, 0xec, 0x37, 0x1d, 0xbd, 0x81, \ + 0x8b, 0x1f, 0x30, 0xbb, 0xbc, 0x4d, 0x36, 0xb5, 0x79, 0x7c, 0x87, 0xfb, \ + 0x51, 0xb9, 0xbe, 0xc2, 0xde, 0x92, 0xa8, 0x40, 0x71, 0xbb, 0x72, 0x9b, \ + 0xf8, 0x47, 0xce, 0x6c, 0x04, 0xf8, 0x86, 0xe7, 0xf7, 0x73, 0x3c, 0xe7, \ + 0x84, 0x7d, 0xc2, 0xd7, 0xb7, 0x9d, 0xe8, 0xd4, 0x9b, 0x5f, 0x0a, 0x17, \ + 0x7d, 0xbc, 0xbb, 0xb2, 0xd5, 0x94, 0x0d, 0xe4, 0x49, 0xbf, 0x4f, 0x11, \ + 0x68, 0x53, 0xb2, 0x91, 0xff, 0xc0, 0x69, 0xee, 0xdb, 0x63, 0x93, 0xcb, \ + 0xc9, 0x35, 0x6b, 0x90, 0x09, 0xe2, 0x90, 0xc9, 0xed, 0x27, 0xd6, 0x08, \ + 0xfa, 0x13, 0x4d, 0x62, 0xdd, 0xe2, 0x9e, 0xaa, 0xb5, 0xd4, 0x0e, 0x5c, \ + 0x37, 0x4f, 0xab, 0x55, 0x3b, 0x2d, 0xf1, 0x42, 0x82, 0xc7, 0x34, 0x38, \ + 0x1a, 0x9b, 0xeb, 0xa1, 0x2c, 0x0f, 0x29, 0x31, 0x64, 0x6c, 0xcc, 0x38, \ + 0xfd, 0xa9, 0xd3, 0xd5, 0xd5, 0x71, 0xaf, 0xf0, 0x6d, 0xc0, 0x97, 0xe2, \ + 0x11, 0x2a, 0x0a, 0xdf, 0xfe, 0x02, 0x79, 0x74, 0x75 \ +} +/* END FILE */ + +/* This is taken from tests/data_files/test-ca-sha1.crt. */ +/* BEGIN FILE string macro TEST_CA_CRT_RSA_SHA1_PEM tests/data_files/test-ca-sha1.crt */ +#define TEST_CA_CRT_RSA_SHA1_PEM \ + "-----BEGIN CERTIFICATE-----\r\n" \ + "MIIDQTCCAimgAwIBAgIBAzANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n" \ + "MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" \ + "MTEwMjEyMTQ0NDAwWhcNMjEwMjEyMTQ0NDAwWjA7MQswCQYDVQQGEwJOTDERMA8G\r\n" \ + "A1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwggEiMA0G\r\n" \ + "CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDA3zf8F7vglp0/ht6WMn1EpRagzSHx\r\n" \ + "mdTs6st8GFgIlKXsm8WL3xoemTiZhx57wI053zhdcHgH057Zk+i5clHFzqMwUqny\r\n" \ + "50BwFMtEonILwuVA+T7lpg6z+exKY8C4KQB0nFc7qKUEkHHxvYPZP9al4jwqj+8n\r\n" \ + "YMPGn8u67GB9t+aEMr5P+1gmIgNb1LTV+/Xjli5wwOQuvfwu7uJBVcA0Ln0kcmnL\r\n" \ + "R7EUQIN9Z/SG9jGr8XmksrUuEvmEF/Bibyc+E1ixVA0hmnM3oTDPb5Lc9un8rNsu\r\n" \ + "KNF+AksjoBXyOGVkCeoMbo4bF6BxyLObyavpw/LPh5aPgAIynplYb6LVAgMBAAGj\r\n" \ + "UDBOMAwGA1UdEwQFMAMBAf8wHQYDVR0OBBYEFLRa5KWz3tJS9rnVppUP6z68x/3/\r\n" \ + "MB8GA1UdIwQYMBaAFLRa5KWz3tJS9rnVppUP6z68x/3/MA0GCSqGSIb3DQEBBQUA\r\n" \ + "A4IBAQABE3OEPfEd/bcJW5ZdU3/VgPNS4tMzh8gnJP/V2FcvFtGylMpQq6YnEBYI\r\n" \ + "yBHAL4DRvlMY5rnXGBp3ODR8MpqHC6AquRTCLzjS57iYff//4QFQqW9n92zctspv\r\n" \ + "czkaPKgjqo1No3Uq0Xaz10rcxyTUPrf5wNVRZ2V0KvllvAAVSzbI4mpdUXztjhST\r\n" \ + "S5A2BeWQAAOr0zq1F7TSRVJpJs7jmB2ai/igkh1IAjcuwV6VwlP+sbw0gjQ0NpGM\r\n" \ + "iHpnlzRAi/tIbtOvMIGOBU2TIfax/5jq1agUx5aPmT5TWAiJPOOP6l5xXnDwxeYS\r\n" \ + "NWqiX9GyusBZjezaCaHabjDLU0qQ\r\n" \ + "-----END CERTIFICATE-----\r\n" +/* END FILE */ + +/* This is taken from tests/data_files/test-ca-sha1.crt.der. */ +/* BEGIN FILE binary macro TEST_CA_CRT_RSA_SHA1_DER tests/data_files/test-ca-sha1.crt.der */ +#define TEST_CA_CRT_RSA_SHA1_DER { \ + 0x30, 0x82, 0x03, 0x41, 0x30, 0x82, 0x02, 0x29, 0xa0, 0x03, 0x02, 0x01, \ + 0x02, 0x02, 0x01, 0x03, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, \ + 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x3b, 0x31, 0x0b, 0x30, \ + 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, \ + 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, \ + 0x61, 0x72, 0x53, 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, \ + 0x04, 0x03, 0x0c, 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, \ + 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, \ + 0x31, 0x31, 0x30, 0x32, 0x31, 0x32, 0x31, 0x34, 0x34, 0x34, 0x30, 0x30, \ + 0x5a, 0x17, 0x0d, 0x32, 0x31, 0x30, 0x32, 0x31, 0x32, 0x31, 0x34, 0x34, \ + 0x34, 0x30, 0x30, 0x5a, 0x30, 0x3b, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, \ + 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, \ + 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, \ + 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, \ + 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, 0x20, 0x54, 0x65, \ + 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, \ + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, \ + 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, \ + 0x01, 0x00, 0xc0, 0xdf, 0x37, 0xfc, 0x17, 0xbb, 0xe0, 0x96, 0x9d, 0x3f, \ + 0x86, 0xde, 0x96, 0x32, 0x7d, 0x44, 0xa5, 0x16, 0xa0, 0xcd, 0x21, 0xf1, \ + 0x99, 0xd4, 0xec, 0xea, 0xcb, 0x7c, 0x18, 0x58, 0x08, 0x94, 0xa5, 0xec, \ + 0x9b, 0xc5, 0x8b, 0xdf, 0x1a, 0x1e, 0x99, 0x38, 0x99, 0x87, 0x1e, 0x7b, \ + 0xc0, 0x8d, 0x39, 0xdf, 0x38, 0x5d, 0x70, 0x78, 0x07, 0xd3, 0x9e, 0xd9, \ + 0x93, 0xe8, 0xb9, 0x72, 0x51, 0xc5, 0xce, 0xa3, 0x30, 0x52, 0xa9, 0xf2, \ + 0xe7, 0x40, 0x70, 0x14, 0xcb, 0x44, 0xa2, 0x72, 0x0b, 0xc2, 0xe5, 0x40, \ + 0xf9, 0x3e, 0xe5, 0xa6, 0x0e, 0xb3, 0xf9, 0xec, 0x4a, 0x63, 0xc0, 0xb8, \ + 0x29, 0x00, 0x74, 0x9c, 0x57, 0x3b, 0xa8, 0xa5, 0x04, 0x90, 0x71, 0xf1, \ + 0xbd, 0x83, 0xd9, 0x3f, 0xd6, 0xa5, 0xe2, 0x3c, 0x2a, 0x8f, 0xef, 0x27, \ + 0x60, 0xc3, 0xc6, 0x9f, 0xcb, 0xba, 0xec, 0x60, 0x7d, 0xb7, 0xe6, 0x84, \ + 0x32, 0xbe, 0x4f, 0xfb, 0x58, 0x26, 0x22, 0x03, 0x5b, 0xd4, 0xb4, 0xd5, \ + 0xfb, 0xf5, 0xe3, 0x96, 0x2e, 0x70, 0xc0, 0xe4, 0x2e, 0xbd, 0xfc, 0x2e, \ + 0xee, 0xe2, 0x41, 0x55, 0xc0, 0x34, 0x2e, 0x7d, 0x24, 0x72, 0x69, 0xcb, \ + 0x47, 0xb1, 0x14, 0x40, 0x83, 0x7d, 0x67, 0xf4, 0x86, 0xf6, 0x31, 0xab, \ + 0xf1, 0x79, 0xa4, 0xb2, 0xb5, 0x2e, 0x12, 0xf9, 0x84, 0x17, 0xf0, 0x62, \ + 0x6f, 0x27, 0x3e, 0x13, 0x58, 0xb1, 0x54, 0x0d, 0x21, 0x9a, 0x73, 0x37, \ + 0xa1, 0x30, 0xcf, 0x6f, 0x92, 0xdc, 0xf6, 0xe9, 0xfc, 0xac, 0xdb, 0x2e, \ + 0x28, 0xd1, 0x7e, 0x02, 0x4b, 0x23, 0xa0, 0x15, 0xf2, 0x38, 0x65, 0x64, \ + 0x09, 0xea, 0x0c, 0x6e, 0x8e, 0x1b, 0x17, 0xa0, 0x71, 0xc8, 0xb3, 0x9b, \ + 0xc9, 0xab, 0xe9, 0xc3, 0xf2, 0xcf, 0x87, 0x96, 0x8f, 0x80, 0x02, 0x32, \ + 0x9e, 0x99, 0x58, 0x6f, 0xa2, 0xd5, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, \ + 0x50, 0x30, 0x4e, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, \ + 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, \ + 0x04, 0x16, 0x04, 0x14, 0xb4, 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, \ + 0xf6, 0xb9, 0xd5, 0xa6, 0x95, 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, \ + 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, \ + 0x14, 0xb4, 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, 0xf6, 0xb9, 0xd5, \ + 0xa6, 0x95, 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, 0x30, 0x0d, 0x06, \ + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, \ + 0x03, 0x82, 0x01, 0x01, 0x00, 0x01, 0x13, 0x73, 0x84, 0x3d, 0xf1, 0x1d, \ + 0xfd, 0xb7, 0x09, 0x5b, 0x96, 0x5d, 0x53, 0x7f, 0xd5, 0x80, 0xf3, 0x52, \ + 0xe2, 0xd3, 0x33, 0x87, 0xc8, 0x27, 0x24, 0xff, 0xd5, 0xd8, 0x57, 0x2f, \ + 0x16, 0xd1, 0xb2, 0x94, 0xca, 0x50, 0xab, 0xa6, 0x27, 0x10, 0x16, 0x08, \ + 0xc8, 0x11, 0xc0, 0x2f, 0x80, 0xd1, 0xbe, 0x53, 0x18, 0xe6, 0xb9, 0xd7, \ + 0x18, 0x1a, 0x77, 0x38, 0x34, 0x7c, 0x32, 0x9a, 0x87, 0x0b, 0xa0, 0x2a, \ + 0xb9, 0x14, 0xc2, 0x2f, 0x38, 0xd2, 0xe7, 0xb8, 0x98, 0x7d, 0xff, 0xff, \ + 0xe1, 0x01, 0x50, 0xa9, 0x6f, 0x67, 0xf7, 0x6c, 0xdc, 0xb6, 0xca, 0x6f, \ + 0x73, 0x39, 0x1a, 0x3c, 0xa8, 0x23, 0xaa, 0x8d, 0x4d, 0xa3, 0x75, 0x2a, \ + 0xd1, 0x76, 0xb3, 0xd7, 0x4a, 0xdc, 0xc7, 0x24, 0xd4, 0x3e, 0xb7, 0xf9, \ + 0xc0, 0xd5, 0x51, 0x67, 0x65, 0x74, 0x2a, 0xf9, 0x65, 0xbc, 0x00, 0x15, \ + 0x4b, 0x36, 0xc8, 0xe2, 0x6a, 0x5d, 0x51, 0x7c, 0xed, 0x8e, 0x14, 0x93, \ + 0x4b, 0x90, 0x36, 0x05, 0xe5, 0x90, 0x00, 0x03, 0xab, 0xd3, 0x3a, 0xb5, \ + 0x17, 0xb4, 0xd2, 0x45, 0x52, 0x69, 0x26, 0xce, 0xe3, 0x98, 0x1d, 0x9a, \ + 0x8b, 0xf8, 0xa0, 0x92, 0x1d, 0x48, 0x02, 0x37, 0x2e, 0xc1, 0x5e, 0x95, \ + 0xc2, 0x53, 0xfe, 0xb1, 0xbc, 0x34, 0x82, 0x34, 0x34, 0x36, 0x91, 0x8c, \ + 0x88, 0x7a, 0x67, 0x97, 0x34, 0x40, 0x8b, 0xfb, 0x48, 0x6e, 0xd3, 0xaf, \ + 0x30, 0x81, 0x8e, 0x05, 0x4d, 0x93, 0x21, 0xf6, 0xb1, 0xff, 0x98, 0xea, \ + 0xd5, 0xa8, 0x14, 0xc7, 0x96, 0x8f, 0x99, 0x3e, 0x53, 0x58, 0x08, 0x89, \ + 0x3c, 0xe3, 0x8f, 0xea, 0x5e, 0x71, 0x5e, 0x70, 0xf0, 0xc5, 0xe6, 0x12, \ + 0x35, 0x6a, 0xa2, 0x5f, 0xd1, 0xb2, 0xba, 0xc0, 0x59, 0x8d, 0xec, 0xda, \ + 0x09, 0xa1, 0xda, 0x6e, 0x30, 0xcb, 0x53, 0x4a, 0x90 \ +} +/* END FILE */ + +/* This is taken from tests/data_files/test-ca.key */ +/* BEGIN FILE string macro TEST_CA_KEY_RSA_PEM tests/data_files/test-ca.key */ +#define TEST_CA_KEY_RSA_PEM \ + "-----BEGIN RSA PRIVATE KEY-----\r\n" \ + "Proc-Type: 4,ENCRYPTED\r\n" \ + "DEK-Info: DES-EDE3-CBC,A8A95B05D5B7206B\r\n" \ + "\r\n" \ + "9Qd9GeArejl1GDVh2lLV1bHt0cPtfbh5h/5zVpAVaFpqtSPMrElp50Rntn9et+JA\r\n" \ + "7VOyboR+Iy2t/HU4WvA687k3Bppe9GwKHjHhtl//8xFKwZr3Xb5yO5JUP8AUctQq\r\n" \ + "Nb8CLlZyuUC+52REAAthdWgsX+7dJO4yabzUcQ22Tp9JSD0hiL43BlkWYUNK3dAo\r\n" \ + "PZlmiptjnzVTjg1MxsBSydZinWOLBV8/JQgxSPo2yD4uEfig28qbvQ2wNIn0pnAb\r\n" \ + "GxnSAOazkongEGfvcjIIs+LZN9gXFhxcOh6kc4Q/c99B7QWETwLLkYgZ+z1a9VY9\r\n" \ + "gEU7CwCxYCD+h9hY6FPmsK0/lC4O7aeRKpYq00rPPxs6i7phiexg6ax6yTMmArQq\r\n" \ + "QmK3TAsJm8V/J5AWpLEV6jAFgRGymGGHnof0DXzVWZidrcZJWTNuGEX90nB3ee2w\r\n" \ + "PXJEFWKoD3K3aFcSLdHYr3mLGxP7H9ThQai9VsycxZKS5kwvBKQ//YMrmFfwPk8x\r\n" \ + "vTeY4KZMaUrveEel5tWZC94RSMKgxR6cyE1nBXyTQnDOGbfpNNgBKxyKbINWoOJU\r\n" \ + "WJZAwlsQn+QzCDwpri7+sV1mS3gBE6UY7aQmnmiiaC2V3Hbphxct/en5QsfDOt1X\r\n" \ + "JczSfpRWLlbPznZg8OQh/VgCMA58N5DjOzTIK7sJJ5r+94ZBTCpgAMbF588f0NTR\r\n" \ + "KCe4yrxGJR7X02M4nvD4IwOlpsQ8xQxZtOSgXv4LkxvdU9XJJKWZ/XNKJeWztxSe\r\n" \ + "Z1vdTc2YfsDBA2SEv33vxHx2g1vqtw8SjDRT2RaQSS0QuSaMJimdOX6mTOCBKk1J\r\n" \ + "9Q5mXTrER+/LnK0jEmXsBXWA5bqqVZIyahXSx4VYZ7l7w/PHiUDtDgyRhMMKi4n2\r\n" \ + "iQvQcWSQTjrpnlJbca1/DkpRt3YwrvJwdqb8asZU2VrNETh5x0QVefDRLFiVpif/\r\n" \ + "tUaeAe/P1F8OkS7OIZDs1SUbv/sD2vMbhNkUoCms3/PvNtdnvgL4F0zhaDpKCmlT\r\n" \ + "P8vx49E7v5CyRNmED9zZg4o3wmMqrQO93PtTug3Eu9oVx1zPQM1NVMyBa2+f29DL\r\n" \ + "1nuTCeXdo9+ni45xx+jAI4DCwrRdhJ9uzZyC6962H37H6D+5naNvClFR1s6li1Gb\r\n" \ + "nqPoiy/OBsEx9CaDGcqQBp5Wme/3XW+6z1ISOx+igwNTVCT14mHdBMbya0eIKft5\r\n" \ + "X+GnwtgEMyCYyyWuUct8g4RzErcY9+yW9Om5Hzpx4zOuW4NPZgPDTgK+t2RSL/Yq\r\n" \ + "rE1njrgeGYcVeG3f+OftH4s6fPbq7t1A5ZgUscbLMBqr9tK+OqygR4EgKBPsH6Cz\r\n" \ + "L6zlv/2RV0qAHvVuDJcIDIgwY5rJtINEm32rhOeFNJwZS5MNIC1czXZx5//ugX7l\r\n" \ + "I4sy5nbVhwSjtAk8Xg5dZbdTZ6mIrb7xqH+fdakZor1khG7bC2uIwibD3cSl2XkR\r\n" \ + "wN48lslbHnqqagr6Xm1nNOSVl8C/6kbJEsMpLhAezfRtGwvOucoaE+WbeUNolGde\r\n" \ + "P/eQiddSf0brnpiLJRh7qZrl9XuqYdpUqnoEdMAfotDOID8OtV7gt8a48ad8VPW2\r\n" \ + "-----END RSA PRIVATE KEY-----\r\n" +/* END FILE */ + +#define TEST_CA_PWD_RSA_PEM "PolarSSLTest" + +/* This was generated from test-ca.key.der using `xxd -i`. */ +/* BEGIN FILE binary macro TEST_CA_KEY_RSA_DER tests/data_files/test-ca.key.der */ +#define TEST_CA_KEY_RSA_DER { \ + 0x30, 0x82, 0x04, 0xa4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, \ + 0xc0, 0xdf, 0x37, 0xfc, 0x17, 0xbb, 0xe0, 0x96, 0x9d, 0x3f, 0x86, 0xde, \ + 0x96, 0x32, 0x7d, 0x44, 0xa5, 0x16, 0xa0, 0xcd, 0x21, 0xf1, 0x99, 0xd4, \ + 0xec, 0xea, 0xcb, 0x7c, 0x18, 0x58, 0x08, 0x94, 0xa5, 0xec, 0x9b, 0xc5, \ + 0x8b, 0xdf, 0x1a, 0x1e, 0x99, 0x38, 0x99, 0x87, 0x1e, 0x7b, 0xc0, 0x8d, \ + 0x39, 0xdf, 0x38, 0x5d, 0x70, 0x78, 0x07, 0xd3, 0x9e, 0xd9, 0x93, 0xe8, \ + 0xb9, 0x72, 0x51, 0xc5, 0xce, 0xa3, 0x30, 0x52, 0xa9, 0xf2, 0xe7, 0x40, \ + 0x70, 0x14, 0xcb, 0x44, 0xa2, 0x72, 0x0b, 0xc2, 0xe5, 0x40, 0xf9, 0x3e, \ + 0xe5, 0xa6, 0x0e, 0xb3, 0xf9, 0xec, 0x4a, 0x63, 0xc0, 0xb8, 0x29, 0x00, \ + 0x74, 0x9c, 0x57, 0x3b, 0xa8, 0xa5, 0x04, 0x90, 0x71, 0xf1, 0xbd, 0x83, \ + 0xd9, 0x3f, 0xd6, 0xa5, 0xe2, 0x3c, 0x2a, 0x8f, 0xef, 0x27, 0x60, 0xc3, \ + 0xc6, 0x9f, 0xcb, 0xba, 0xec, 0x60, 0x7d, 0xb7, 0xe6, 0x84, 0x32, 0xbe, \ + 0x4f, 0xfb, 0x58, 0x26, 0x22, 0x03, 0x5b, 0xd4, 0xb4, 0xd5, 0xfb, 0xf5, \ + 0xe3, 0x96, 0x2e, 0x70, 0xc0, 0xe4, 0x2e, 0xbd, 0xfc, 0x2e, 0xee, 0xe2, \ + 0x41, 0x55, 0xc0, 0x34, 0x2e, 0x7d, 0x24, 0x72, 0x69, 0xcb, 0x47, 0xb1, \ + 0x14, 0x40, 0x83, 0x7d, 0x67, 0xf4, 0x86, 0xf6, 0x31, 0xab, 0xf1, 0x79, \ + 0xa4, 0xb2, 0xb5, 0x2e, 0x12, 0xf9, 0x84, 0x17, 0xf0, 0x62, 0x6f, 0x27, \ + 0x3e, 0x13, 0x58, 0xb1, 0x54, 0x0d, 0x21, 0x9a, 0x73, 0x37, 0xa1, 0x30, \ + 0xcf, 0x6f, 0x92, 0xdc, 0xf6, 0xe9, 0xfc, 0xac, 0xdb, 0x2e, 0x28, 0xd1, \ + 0x7e, 0x02, 0x4b, 0x23, 0xa0, 0x15, 0xf2, 0x38, 0x65, 0x64, 0x09, 0xea, \ + 0x0c, 0x6e, 0x8e, 0x1b, 0x17, 0xa0, 0x71, 0xc8, 0xb3, 0x9b, 0xc9, 0xab, \ + 0xe9, 0xc3, 0xf2, 0xcf, 0x87, 0x96, 0x8f, 0x80, 0x02, 0x32, 0x9e, 0x99, \ + 0x58, 0x6f, 0xa2, 0xd5, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, \ + 0x00, 0x3f, 0xf7, 0x07, 0xd3, 0x34, 0x6f, 0xdb, 0xc9, 0x37, 0xb7, 0x84, \ + 0xdc, 0x37, 0x45, 0xe1, 0x63, 0xad, 0xb8, 0xb6, 0x75, 0xb1, 0xc7, 0x35, \ + 0xb4, 0x77, 0x2a, 0x5b, 0x77, 0xf9, 0x7e, 0xe0, 0xc1, 0xa3, 0xd1, 0xb7, \ + 0xcb, 0xa9, 0x5a, 0xc1, 0x87, 0xda, 0x5a, 0xfa, 0x17, 0xe4, 0xd5, 0x38, \ + 0x03, 0xde, 0x68, 0x98, 0x81, 0xec, 0xb5, 0xf2, 0x2a, 0x8d, 0xe9, 0x2c, \ + 0xf3, 0xa6, 0xe5, 0x32, 0x17, 0x7f, 0x33, 0x81, 0xe8, 0x38, 0x72, 0xd5, \ + 0x9c, 0xfa, 0x4e, 0xfb, 0x26, 0xf5, 0x15, 0x0b, 0xaf, 0x84, 0x66, 0xab, \ + 0x02, 0xe0, 0x18, 0xd5, 0x91, 0x7c, 0xd6, 0x8f, 0xc9, 0x4b, 0x76, 0x08, \ + 0x2b, 0x1d, 0x81, 0x68, 0x30, 0xe1, 0xfa, 0x70, 0x6c, 0x13, 0x4e, 0x10, \ + 0x03, 0x35, 0x3e, 0xc5, 0xca, 0x58, 0x20, 0x8a, 0x21, 0x18, 0x38, 0xa0, \ + 0x0f, 0xed, 0xc4, 0xbb, 0x45, 0x6f, 0xf5, 0x84, 0x5b, 0xb0, 0xcf, 0x4e, \ + 0x9d, 0x58, 0x13, 0x6b, 0x35, 0x35, 0x69, 0xa1, 0xd2, 0xc4, 0xf2, 0xc1, \ + 0x48, 0x04, 0x20, 0x51, 0xb9, 0x6b, 0xa4, 0x5d, 0xa5, 0x4b, 0x84, 0x88, \ + 0x43, 0x48, 0x99, 0x2c, 0xbb, 0xa4, 0x97, 0xd6, 0xd6, 0x18, 0xf6, 0xec, \ + 0x5c, 0xd1, 0x31, 0x49, 0xc9, 0xf2, 0x8f, 0x0b, 0x4d, 0xef, 0x09, 0x02, \ + 0xfe, 0x7d, 0xfd, 0xbb, 0xaf, 0x2b, 0x83, 0x94, 0x22, 0xc4, 0xa7, 0x3e, \ + 0x66, 0xf5, 0xe0, 0x57, 0xdc, 0xf2, 0xed, 0x2c, 0x3e, 0x81, 0x74, 0x76, \ + 0x1e, 0x96, 0x6f, 0x74, 0x1e, 0x32, 0x0e, 0x14, 0x31, 0xd0, 0x74, 0xf0, \ + 0xf4, 0x07, 0xbd, 0xc3, 0xd1, 0x22, 0xc2, 0xa8, 0x95, 0x92, 0x06, 0x7f, \ + 0x43, 0x02, 0x91, 0xbc, 0xdd, 0x23, 0x01, 0x89, 0x94, 0x20, 0x44, 0x64, \ + 0xf5, 0x1d, 0x67, 0xd2, 0x8f, 0xe8, 0x69, 0xa5, 0x29, 0x25, 0xe6, 0x50, \ + 0x9c, 0xe3, 0xe9, 0xcb, 0x75, 0x02, 0x81, 0x81, 0x00, 0xe2, 0x29, 0x3e, \ + 0xaa, 0x6b, 0xd5, 0x59, 0x1e, 0x9c, 0xe6, 0x47, 0xd5, 0xb6, 0xd7, 0xe3, \ + 0xf1, 0x8e, 0x9e, 0xe9, 0x83, 0x5f, 0x10, 0x9f, 0x63, 0xec, 0x04, 0x44, \ + 0xcc, 0x3f, 0xf8, 0xd9, 0x3a, 0x17, 0xe0, 0x4f, 0xfe, 0xd8, 0x4d, 0xcd, \ + 0x46, 0x54, 0x74, 0xbf, 0x0a, 0xc4, 0x67, 0x9c, 0xa7, 0xd8, 0x89, 0x65, \ + 0x4c, 0xfd, 0x58, 0x2a, 0x47, 0x0f, 0xf4, 0x37, 0xb6, 0x55, 0xb0, 0x1d, \ + 0xed, 0xa7, 0x39, 0xfc, 0x4f, 0xa3, 0xc4, 0x75, 0x3a, 0xa3, 0x98, 0xa7, \ + 0x45, 0xf5, 0x66, 0xcb, 0x7c, 0x65, 0xfb, 0x80, 0x23, 0xe6, 0xff, 0xfd, \ + 0x99, 0x1f, 0x8e, 0x6b, 0xff, 0x5e, 0x93, 0x66, 0xdf, 0x6c, 0x6f, 0xc3, \ + 0xf6, 0x38, 0x2e, 0xff, 0x69, 0xb5, 0xac, 0xae, 0xbb, 0xc6, 0x71, 0x16, \ + 0x6b, 0xd0, 0xf8, 0x22, 0xd9, 0xf8, 0xa2, 0x72, 0x20, 0xd2, 0xe2, 0x3a, \ + 0x70, 0x4b, 0xde, 0xab, 0x2f, 0x02, 0x81, 0x81, 0x00, 0xda, 0x51, 0x9b, \ + 0xb8, 0xb2, 0x2a, 0x14, 0x75, 0x58, 0x40, 0x8d, 0x27, 0x70, 0xfa, 0x31, \ + 0x48, 0xb0, 0x20, 0x21, 0x34, 0xfa, 0x4c, 0x57, 0xa8, 0x11, 0x88, 0xf3, \ + 0xa7, 0xae, 0x21, 0xe9, 0xb6, 0x2b, 0xd1, 0xcd, 0xa7, 0xf8, 0xd8, 0x0c, \ + 0x8a, 0x76, 0x22, 0x35, 0x44, 0xce, 0x3f, 0x25, 0x29, 0x83, 0x7d, 0x79, \ + 0xa7, 0x31, 0xd6, 0xec, 0xb2, 0xbf, 0xda, 0x34, 0xb6, 0xf6, 0xb2, 0x3b, \ + 0xf3, 0x78, 0x5a, 0x04, 0x83, 0x33, 0x3e, 0xa2, 0xe2, 0x81, 0x82, 0x13, \ + 0xd4, 0x35, 0x17, 0x63, 0x9b, 0x9e, 0xc4, 0x8d, 0x91, 0x4c, 0x03, 0x77, \ + 0xc7, 0x71, 0x5b, 0xee, 0x83, 0x6d, 0xd5, 0x78, 0x88, 0xf6, 0x2c, 0x79, \ + 0xc2, 0x4a, 0xb4, 0x79, 0x90, 0x70, 0xbf, 0xdf, 0x34, 0x56, 0x96, 0x71, \ + 0xe3, 0x0e, 0x68, 0x91, 0xbc, 0xea, 0xcb, 0x33, 0xc0, 0xbe, 0x45, 0xd7, \ + 0xfc, 0x30, 0xfd, 0x01, 0x3b, 0x02, 0x81, 0x81, 0x00, 0xd2, 0x9f, 0x2a, \ + 0xb7, 0x38, 0x19, 0xc7, 0x17, 0x95, 0x73, 0x78, 0xae, 0xf5, 0xcb, 0x75, \ + 0x83, 0x7f, 0x19, 0x4b, 0xcb, 0x86, 0xfb, 0x4a, 0x15, 0x9a, 0xb6, 0x17, \ + 0x04, 0x49, 0x07, 0x8d, 0xf6, 0x66, 0x4a, 0x06, 0xf6, 0x05, 0xa7, 0xdf, \ + 0x66, 0x82, 0x3c, 0xff, 0xb6, 0x1d, 0x57, 0x89, 0x33, 0x5f, 0x9c, 0x05, \ + 0x75, 0x7f, 0xf3, 0x5d, 0xdc, 0x34, 0x65, 0x72, 0x85, 0x22, 0xa4, 0x14, \ + 0x1b, 0x41, 0xc3, 0xe4, 0xd0, 0x9e, 0x69, 0xd5, 0xeb, 0x38, 0x74, 0x70, \ + 0x43, 0xdc, 0xd9, 0x50, 0xe4, 0x97, 0x6d, 0x73, 0xd6, 0xfb, 0xc8, 0xa7, \ + 0xfa, 0xb4, 0xc2, 0xc4, 0x9d, 0x5d, 0x0c, 0xd5, 0x9f, 0x79, 0xb3, 0x54, \ + 0xc2, 0xb7, 0x6c, 0x3d, 0x7d, 0xcb, 0x2d, 0xf8, 0xc4, 0xf3, 0x78, 0x5a, \ + 0x33, 0x2a, 0xb8, 0x0c, 0x6d, 0x06, 0xfa, 0xf2, 0x62, 0xd3, 0x42, 0xd0, \ + 0xbd, 0xc8, 0x4a, 0xa5, 0x0d, 0x02, 0x81, 0x81, 0x00, 0xd4, 0xa9, 0x90, \ + 0x15, 0xde, 0xbf, 0x2c, 0xc4, 0x8d, 0x9d, 0xfb, 0xa1, 0xc2, 0xe4, 0x83, \ + 0xe3, 0x79, 0x65, 0x22, 0xd3, 0xb7, 0x49, 0x6c, 0x4d, 0x94, 0x1f, 0x22, \ + 0xb1, 0x60, 0xe7, 0x3a, 0x00, 0xb1, 0x38, 0xa2, 0xab, 0x0f, 0xb4, 0x6c, \ + 0xaa, 0xe7, 0x9e, 0x34, 0xe3, 0x7c, 0x40, 0x78, 0x53, 0xb2, 0xf9, 0x23, \ + 0xea, 0xa0, 0x9a, 0xea, 0x60, 0xc8, 0x8f, 0xa6, 0xaf, 0xdf, 0x29, 0x09, \ + 0x4b, 0x06, 0x1e, 0x31, 0xad, 0x17, 0xda, 0xd8, 0xd1, 0xe9, 0x33, 0xab, \ + 0x5b, 0x18, 0x08, 0x5b, 0x87, 0xf8, 0xa5, 0x1f, 0xfd, 0xbb, 0xdc, 0xd8, \ + 0xed, 0x97, 0x57, 0xe4, 0xc3, 0x73, 0xd6, 0xf0, 0x9e, 0x01, 0xa6, 0x9b, \ + 0x48, 0x8e, 0x7a, 0xb4, 0xbb, 0xe5, 0x88, 0x91, 0xc5, 0x2a, 0xdf, 0x4b, \ + 0xba, 0xd0, 0x8b, 0x3e, 0x03, 0x97, 0x77, 0x2f, 0x47, 0x7e, 0x51, 0x0c, \ + 0xae, 0x65, 0x8d, 0xde, 0x87, 0x02, 0x81, 0x80, 0x20, 0x24, 0x0f, 0xd2, \ + 0xaf, 0xc2, 0x28, 0x3b, 0x97, 0x20, 0xb2, 0x92, 0x49, 0xeb, 0x09, 0x68, \ + 0x40, 0xb2, 0xbe, 0xd1, 0xc3, 0x83, 0x94, 0x34, 0x38, 0xd6, 0xc9, 0xec, \ + 0x34, 0x09, 0xf9, 0x41, 0x6d, 0x5c, 0x42, 0x94, 0xf7, 0x04, 0xfc, 0x32, \ + 0x39, 0x69, 0xbc, 0x1c, 0xfb, 0x3e, 0x61, 0x98, 0xc0, 0x80, 0xd8, 0x36, \ + 0x47, 0xc3, 0x6d, 0xc2, 0x2e, 0xe7, 0x81, 0x2a, 0x17, 0x34, 0x64, 0x30, \ + 0x4e, 0x96, 0xbb, 0x26, 0x16, 0xb9, 0x41, 0x36, 0xfe, 0x8a, 0xd6, 0x53, \ + 0x7c, 0xaa, 0xec, 0x39, 0x42, 0x50, 0xef, 0xe3, 0xb3, 0x01, 0x28, 0x32, \ + 0xca, 0x6d, 0xf5, 0x9a, 0x1e, 0x9f, 0x37, 0xbe, 0xfe, 0x38, 0x20, 0x22, \ + 0x91, 0x8c, 0xcd, 0x95, 0x02, 0xf2, 0x4d, 0x6f, 0x1a, 0xb4, 0x43, 0xf0, \ + 0x19, 0xdf, 0x65, 0xc0, 0x92, 0xe7, 0x9d, 0x2f, 0x09, 0xe7, 0xec, 0x69, \ + 0xa8, 0xc2, 0x8f, 0x0d \ +} +/* END FILE */ + +/* + * Test server Certificates + * + * Test server certificates are defined for each choice + * of the following parameters: + * - PEM or DER encoding + * - SHA-1 or SHA-256 hash + * - RSA or EC key + * + * Things to add: + * - multiple EC curve types + */ + +/* This is taken from tests/data_files/server5.crt. */ +/* BEGIN FILE string macro TEST_SRV_CRT_EC_PEM tests/data_files/server5.crt */ +#define TEST_SRV_CRT_EC_PEM \ + "-----BEGIN CERTIFICATE-----\r\n" \ + "MIICHzCCAaWgAwIBAgIBCTAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJOTDERMA8G\r\n" \ + "A1UEChMIUG9sYXJTU0wxHDAaBgNVBAMTE1BvbGFyc3NsIFRlc3QgRUMgQ0EwHhcN\r\n" \ + "MTMwOTI0MTU1MjA0WhcNMjMwOTIyMTU1MjA0WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n" \ + "A1UEChMIUG9sYXJTU0wxEjAQBgNVBAMTCWxvY2FsaG9zdDBZMBMGByqGSM49AgEG\r\n" \ + "CCqGSM49AwEHA0IABDfMVtl2CR5acj7HWS3/IG7ufPkGkXTQrRS192giWWKSTuUA\r\n" \ + "2CMR/+ov0jRdXRa9iojCa3cNVc2KKg76Aci07f+jgZ0wgZowCQYDVR0TBAIwADAd\r\n" \ + "BgNVHQ4EFgQUUGGlj9QH2deCAQzlZX+MY0anE74wbgYDVR0jBGcwZYAUnW0gJEkB\r\n" \ + "PyvLeLUZvH4kydv7NnyhQqRAMD4xCzAJBgNVBAYTAk5MMREwDwYDVQQKEwhQb2xh\r\n" \ + "clNTTDEcMBoGA1UEAxMTUG9sYXJzc2wgVGVzdCBFQyBDQYIJAMFD4n5iQ8zoMAoG\r\n" \ + "CCqGSM49BAMCA2gAMGUCMQCaLFzXptui5WQN8LlO3ddh1hMxx6tzgLvT03MTVK2S\r\n" \ + "C12r0Lz3ri/moSEpNZWqPjkCMCE2f53GXcYLqyfyJR078c/xNSUU5+Xxl7VZ414V\r\n" \ + "fGa5kHvHARBPc8YAIVIqDvHH1Q==\r\n" \ + "-----END CERTIFICATE-----\r\n" +/* END FILE */ + +/* This is generated from tests/data_files/server5.crt.der using `xxd -i`. */ +/* BEGIN FILE binary macro TEST_SRV_CRT_EC_DER tests/data_files/server5.crt.der */ +#define TEST_SRV_CRT_EC_DER { \ + 0x30, 0x82, 0x02, 0x1f, 0x30, 0x82, 0x01, 0xa5, 0xa0, 0x03, 0x02, 0x01, \ + 0x02, 0x02, 0x01, 0x09, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, \ + 0x3d, 0x04, 0x03, 0x02, 0x30, 0x3e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, \ + 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, \ + 0x03, 0x55, 0x04, 0x0a, 0x13, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, \ + 0x53, 0x4c, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, \ + 0x13, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x73, 0x73, 0x6c, 0x20, 0x54, 0x65, \ + 0x73, 0x74, 0x20, 0x45, 0x43, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, \ + 0x31, 0x33, 0x30, 0x39, 0x32, 0x34, 0x31, 0x35, 0x35, 0x32, 0x30, 0x34, \ + 0x5a, 0x17, 0x0d, 0x32, 0x33, 0x30, 0x39, 0x32, 0x32, 0x31, 0x35, 0x35, \ + 0x32, 0x30, 0x34, 0x5a, 0x30, 0x34, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, \ + 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, \ + 0x03, 0x55, 0x04, 0x0a, 0x13, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, \ + 0x53, 0x4c, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, \ + 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x30, 0x59, \ + 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, \ + 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, \ + 0x04, 0x37, 0xcc, 0x56, 0xd9, 0x76, 0x09, 0x1e, 0x5a, 0x72, 0x3e, 0xc7, \ + 0x59, 0x2d, 0xff, 0x20, 0x6e, 0xee, 0x7c, 0xf9, 0x06, 0x91, 0x74, 0xd0, \ + 0xad, 0x14, 0xb5, 0xf7, 0x68, 0x22, 0x59, 0x62, 0x92, 0x4e, 0xe5, 0x00, \ + 0xd8, 0x23, 0x11, 0xff, 0xea, 0x2f, 0xd2, 0x34, 0x5d, 0x5d, 0x16, 0xbd, \ + 0x8a, 0x88, 0xc2, 0x6b, 0x77, 0x0d, 0x55, 0xcd, 0x8a, 0x2a, 0x0e, 0xfa, \ + 0x01, 0xc8, 0xb4, 0xed, 0xff, 0xa3, 0x81, 0x9d, 0x30, 0x81, 0x9a, 0x30, \ + 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1d, \ + 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x50, 0x61, 0xa5, \ + 0x8f, 0xd4, 0x07, 0xd9, 0xd7, 0x82, 0x01, 0x0c, 0xe5, 0x65, 0x7f, 0x8c, \ + 0x63, 0x46, 0xa7, 0x13, 0xbe, 0x30, 0x6e, 0x06, 0x03, 0x55, 0x1d, 0x23, \ + 0x04, 0x67, 0x30, 0x65, 0x80, 0x14, 0x9d, 0x6d, 0x20, 0x24, 0x49, 0x01, \ + 0x3f, 0x2b, 0xcb, 0x78, 0xb5, 0x19, 0xbc, 0x7e, 0x24, 0xc9, 0xdb, 0xfb, \ + 0x36, 0x7c, 0xa1, 0x42, 0xa4, 0x40, 0x30, 0x3e, 0x31, 0x0b, 0x30, 0x09, \ + 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, \ + 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x08, 0x50, 0x6f, 0x6c, 0x61, \ + 0x72, 0x53, 0x53, 0x4c, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, \ + 0x03, 0x13, 0x13, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x73, 0x73, 0x6c, 0x20, \ + 0x54, 0x65, 0x73, 0x74, 0x20, 0x45, 0x43, 0x20, 0x43, 0x41, 0x82, 0x09, \ + 0x00, 0xc1, 0x43, 0xe2, 0x7e, 0x62, 0x43, 0xcc, 0xe8, 0x30, 0x0a, 0x06, \ + 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x68, 0x00, \ + 0x30, 0x65, 0x02, 0x31, 0x00, 0x9a, 0x2c, 0x5c, 0xd7, 0xa6, 0xdb, 0xa2, \ + 0xe5, 0x64, 0x0d, 0xf0, 0xb9, 0x4e, 0xdd, 0xd7, 0x61, 0xd6, 0x13, 0x31, \ + 0xc7, 0xab, 0x73, 0x80, 0xbb, 0xd3, 0xd3, 0x73, 0x13, 0x54, 0xad, 0x92, \ + 0x0b, 0x5d, 0xab, 0xd0, 0xbc, 0xf7, 0xae, 0x2f, 0xe6, 0xa1, 0x21, 0x29, \ + 0x35, 0x95, 0xaa, 0x3e, 0x39, 0x02, 0x30, 0x21, 0x36, 0x7f, 0x9d, 0xc6, \ + 0x5d, 0xc6, 0x0b, 0xab, 0x27, 0xf2, 0x25, 0x1d, 0x3b, 0xf1, 0xcf, 0xf1, \ + 0x35, 0x25, 0x14, 0xe7, 0xe5, 0xf1, 0x97, 0xb5, 0x59, 0xe3, 0x5e, 0x15, \ + 0x7c, 0x66, 0xb9, 0x90, 0x7b, 0xc7, 0x01, 0x10, 0x4f, 0x73, 0xc6, 0x00, \ + 0x21, 0x52, 0x2a, 0x0e, 0xf1, 0xc7, 0xd5 \ +} +/* END FILE */ + +/* This is taken from tests/data_files/server5.key. */ +/* BEGIN FILE string macro TEST_SRV_KEY_EC_PEM tests/data_files/server5.key */ +#define TEST_SRV_KEY_EC_PEM \ + "-----BEGIN EC PRIVATE KEY-----\r\n" \ + "MHcCAQEEIPEqEyB2AnCoPL/9U/YDHvdqXYbIogTywwyp6/UfDw6noAoGCCqGSM49\r\n" \ + "AwEHoUQDQgAEN8xW2XYJHlpyPsdZLf8gbu58+QaRdNCtFLX3aCJZYpJO5QDYIxH/\r\n" \ + "6i/SNF1dFr2KiMJrdw1VzYoqDvoByLTt/w==\r\n" \ + "-----END EC PRIVATE KEY-----\r\n" +/* END FILE */ + +/* This is generated from tests/data_files/server5.key.der using `xxd -i`. */ +/* BEGIN FILE binary macro TEST_SRV_KEY_EC_DER tests/data_files/server5.key.der */ +#define TEST_SRV_KEY_EC_DER { \ + 0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0xf1, 0x2a, 0x13, 0x20, 0x76, \ + 0x02, 0x70, 0xa8, 0x3c, 0xbf, 0xfd, 0x53, 0xf6, 0x03, 0x1e, 0xf7, 0x6a, \ + 0x5d, 0x86, 0xc8, 0xa2, 0x04, 0xf2, 0xc3, 0x0c, 0xa9, 0xeb, 0xf5, 0x1f, \ + 0x0f, 0x0e, 0xa7, 0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, \ + 0x03, 0x01, 0x07, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x37, 0xcc, 0x56, \ + 0xd9, 0x76, 0x09, 0x1e, 0x5a, 0x72, 0x3e, 0xc7, 0x59, 0x2d, 0xff, 0x20, \ + 0x6e, 0xee, 0x7c, 0xf9, 0x06, 0x91, 0x74, 0xd0, 0xad, 0x14, 0xb5, 0xf7, \ + 0x68, 0x22, 0x59, 0x62, 0x92, 0x4e, 0xe5, 0x00, 0xd8, 0x23, 0x11, 0xff, \ + 0xea, 0x2f, 0xd2, 0x34, 0x5d, 0x5d, 0x16, 0xbd, 0x8a, 0x88, 0xc2, 0x6b, \ + 0x77, 0x0d, 0x55, 0xcd, 0x8a, 0x2a, 0x0e, 0xfa, 0x01, 0xc8, 0xb4, 0xed, \ + 0xff \ +} +/* END FILE */ + +/* This is taken from tests/data_files/server2-sha256.crt. */ +/* BEGIN FILE string macro TEST_SRV_CRT_RSA_SHA256_PEM tests/data_files/server2-sha256.crt */ +#define TEST_SRV_CRT_RSA_SHA256_PEM \ + "-----BEGIN CERTIFICATE-----\r\n" \ + "MIIDNzCCAh+gAwIBAgIBAjANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER\r\n" \ + "MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" \ + "MTkwMjEwMTQ0NDA2WhcNMjkwMjEwMTQ0NDA2WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n" \ + "A1UECgwIUG9sYXJTU0wxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcN\r\n" \ + "AQEBBQADggEPADCCAQoCggEBAMFNo93nzR3RBNdJcriZrA545Do8Ss86ExbQWuTN\r\n" \ + "owCIp+4ea5anUrSQ7y1yej4kmvy2NKwk9XfgJmSMnLAofaHa6ozmyRyWvP7BBFKz\r\n" \ + "NtSj+uGxdtiQwWG0ZlI2oiZTqqt0Xgd9GYLbKtgfoNkNHC1JZvdbJXNG6AuKT2kM\r\n" \ + "tQCQ4dqCEGZ9rlQri2V5kaHiYcPNQEkI7mgM8YuG0ka/0LiqEQMef1aoGh5EGA8P\r\n" \ + "hYvai0Re4hjGYi/HZo36Xdh98yeJKQHFkA4/J/EwyEoO79bex8cna8cFPXrEAjya\r\n" \ + "HT4P6DSYW8tzS1KW2BGiLICIaTla0w+w3lkvEcf36hIBMJcCAwEAAaNNMEswCQYD\r\n" \ + "VR0TBAIwADAdBgNVHQ4EFgQUpQXoZLjc32APUBJNYKhkr02LQ5MwHwYDVR0jBBgw\r\n" \ + "FoAUtFrkpbPe0lL2udWmlQ/rPrzH/f8wDQYJKoZIhvcNAQELBQADggEBAC465FJh\r\n" \ + "Pqel7zJngHIHJrqj/wVAxGAFOTF396XKATGAp+HRCqJ81Ry60CNK1jDzk8dv6M6U\r\n" \ + "HoS7RIFiM/9rXQCbJfiPD5xMTejZp5n5UYHAmxsxDaazfA5FuBhkfokKK6jD4Eq9\r\n" \ + "1C94xGKb6X4/VkaPF7cqoBBw/bHxawXc0UEPjqayiBpCYU/rJoVZgLqFVP7Px3sv\r\n" \ + "a1nOrNx8rPPI1hJ+ZOg8maiPTxHZnBVLakSSLQy/sWeWyazO1RnrbxjrbgQtYKz0\r\n" \ + "e3nwGpu1w13vfckFmUSBhHXH7AAS/HpKC4IH7G2GAk3+n8iSSN71sZzpxonQwVbo\r\n" \ + "pMZqLmbBm/7WPLc=\r\n" \ + "-----END CERTIFICATE-----\r\n" +/* END FILE */ + +/* This is taken from tests/data_files/server2-sha256.crt.der. */ +/* BEGIN FILE binary macro TEST_SRV_CRT_RSA_SHA256_DER tests/data_files/server2-sha256.crt.der */ +#define TEST_SRV_CRT_RSA_SHA256_DER { \ + 0x30, 0x82, 0x03, 0x37, 0x30, 0x82, 0x02, 0x1f, 0xa0, 0x03, 0x02, 0x01, \ + 0x02, 0x02, 0x01, 0x02, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, \ + 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x3b, 0x31, 0x0b, 0x30, \ + 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, \ + 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, \ + 0x61, 0x72, 0x53, 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, \ + 0x04, 0x03, 0x0c, 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, \ + 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, \ + 0x31, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, 0x30, 0x36, \ + 0x5a, 0x17, 0x0d, 0x32, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, \ + 0x34, 0x30, 0x36, 0x5a, 0x30, 0x34, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, \ + 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, \ + 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, \ + 0x53, 0x4c, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, \ + 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x30, 0x82, \ + 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, \ + 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, \ + 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xc1, 0x4d, 0xa3, 0xdd, 0xe7, \ + 0xcd, 0x1d, 0xd1, 0x04, 0xd7, 0x49, 0x72, 0xb8, 0x99, 0xac, 0x0e, 0x78, \ + 0xe4, 0x3a, 0x3c, 0x4a, 0xcf, 0x3a, 0x13, 0x16, 0xd0, 0x5a, 0xe4, 0xcd, \ + 0xa3, 0x00, 0x88, 0xa7, 0xee, 0x1e, 0x6b, 0x96, 0xa7, 0x52, 0xb4, 0x90, \ + 0xef, 0x2d, 0x72, 0x7a, 0x3e, 0x24, 0x9a, 0xfc, 0xb6, 0x34, 0xac, 0x24, \ + 0xf5, 0x77, 0xe0, 0x26, 0x64, 0x8c, 0x9c, 0xb0, 0x28, 0x7d, 0xa1, 0xda, \ + 0xea, 0x8c, 0xe6, 0xc9, 0x1c, 0x96, 0xbc, 0xfe, 0xc1, 0x04, 0x52, 0xb3, \ + 0x36, 0xd4, 0xa3, 0xfa, 0xe1, 0xb1, 0x76, 0xd8, 0x90, 0xc1, 0x61, 0xb4, \ + 0x66, 0x52, 0x36, 0xa2, 0x26, 0x53, 0xaa, 0xab, 0x74, 0x5e, 0x07, 0x7d, \ + 0x19, 0x82, 0xdb, 0x2a, 0xd8, 0x1f, 0xa0, 0xd9, 0x0d, 0x1c, 0x2d, 0x49, \ + 0x66, 0xf7, 0x5b, 0x25, 0x73, 0x46, 0xe8, 0x0b, 0x8a, 0x4f, 0x69, 0x0c, \ + 0xb5, 0x00, 0x90, 0xe1, 0xda, 0x82, 0x10, 0x66, 0x7d, 0xae, 0x54, 0x2b, \ + 0x8b, 0x65, 0x79, 0x91, 0xa1, 0xe2, 0x61, 0xc3, 0xcd, 0x40, 0x49, 0x08, \ + 0xee, 0x68, 0x0c, 0xf1, 0x8b, 0x86, 0xd2, 0x46, 0xbf, 0xd0, 0xb8, 0xaa, \ + 0x11, 0x03, 0x1e, 0x7f, 0x56, 0xa8, 0x1a, 0x1e, 0x44, 0x18, 0x0f, 0x0f, \ + 0x85, 0x8b, 0xda, 0x8b, 0x44, 0x5e, 0xe2, 0x18, 0xc6, 0x62, 0x2f, 0xc7, \ + 0x66, 0x8d, 0xfa, 0x5d, 0xd8, 0x7d, 0xf3, 0x27, 0x89, 0x29, 0x01, 0xc5, \ + 0x90, 0x0e, 0x3f, 0x27, 0xf1, 0x30, 0xc8, 0x4a, 0x0e, 0xef, 0xd6, 0xde, \ + 0xc7, 0xc7, 0x27, 0x6b, 0xc7, 0x05, 0x3d, 0x7a, 0xc4, 0x02, 0x3c, 0x9a, \ + 0x1d, 0x3e, 0x0f, 0xe8, 0x34, 0x98, 0x5b, 0xcb, 0x73, 0x4b, 0x52, 0x96, \ + 0xd8, 0x11, 0xa2, 0x2c, 0x80, 0x88, 0x69, 0x39, 0x5a, 0xd3, 0x0f, 0xb0, \ + 0xde, 0x59, 0x2f, 0x11, 0xc7, 0xf7, 0xea, 0x12, 0x01, 0x30, 0x97, 0x02, \ + 0x03, 0x01, 0x00, 0x01, 0xa3, 0x4d, 0x30, 0x4b, 0x30, 0x09, 0x06, 0x03, \ + 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, \ + 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xa5, 0x05, 0xe8, 0x64, 0xb8, 0xdc, \ + 0xdf, 0x60, 0x0f, 0x50, 0x12, 0x4d, 0x60, 0xa8, 0x64, 0xaf, 0x4d, 0x8b, \ + 0x43, 0x93, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, \ + 0x16, 0x80, 0x14, 0xb4, 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, 0xf6, \ + 0xb9, 0xd5, 0xa6, 0x95, 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, 0x30, \ + 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, \ + 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x2e, 0x3a, 0xe4, 0x52, 0x61, \ + 0x3e, 0xa7, 0xa5, 0xef, 0x32, 0x67, 0x80, 0x72, 0x07, 0x26, 0xba, 0xa3, \ + 0xff, 0x05, 0x40, 0xc4, 0x60, 0x05, 0x39, 0x31, 0x77, 0xf7, 0xa5, 0xca, \ + 0x01, 0x31, 0x80, 0xa7, 0xe1, 0xd1, 0x0a, 0xa2, 0x7c, 0xd5, 0x1c, 0xba, \ + 0xd0, 0x23, 0x4a, 0xd6, 0x30, 0xf3, 0x93, 0xc7, 0x6f, 0xe8, 0xce, 0x94, \ + 0x1e, 0x84, 0xbb, 0x44, 0x81, 0x62, 0x33, 0xff, 0x6b, 0x5d, 0x00, 0x9b, \ + 0x25, 0xf8, 0x8f, 0x0f, 0x9c, 0x4c, 0x4d, 0xe8, 0xd9, 0xa7, 0x99, 0xf9, \ + 0x51, 0x81, 0xc0, 0x9b, 0x1b, 0x31, 0x0d, 0xa6, 0xb3, 0x7c, 0x0e, 0x45, \ + 0xb8, 0x18, 0x64, 0x7e, 0x89, 0x0a, 0x2b, 0xa8, 0xc3, 0xe0, 0x4a, 0xbd, \ + 0xd4, 0x2f, 0x78, 0xc4, 0x62, 0x9b, 0xe9, 0x7e, 0x3f, 0x56, 0x46, 0x8f, \ + 0x17, 0xb7, 0x2a, 0xa0, 0x10, 0x70, 0xfd, 0xb1, 0xf1, 0x6b, 0x05, 0xdc, \ + 0xd1, 0x41, 0x0f, 0x8e, 0xa6, 0xb2, 0x88, 0x1a, 0x42, 0x61, 0x4f, 0xeb, \ + 0x26, 0x85, 0x59, 0x80, 0xba, 0x85, 0x54, 0xfe, 0xcf, 0xc7, 0x7b, 0x2f, \ + 0x6b, 0x59, 0xce, 0xac, 0xdc, 0x7c, 0xac, 0xf3, 0xc8, 0xd6, 0x12, 0x7e, \ + 0x64, 0xe8, 0x3c, 0x99, 0xa8, 0x8f, 0x4f, 0x11, 0xd9, 0x9c, 0x15, 0x4b, \ + 0x6a, 0x44, 0x92, 0x2d, 0x0c, 0xbf, 0xb1, 0x67, 0x96, 0xc9, 0xac, 0xce, \ + 0xd5, 0x19, 0xeb, 0x6f, 0x18, 0xeb, 0x6e, 0x04, 0x2d, 0x60, 0xac, 0xf4, \ + 0x7b, 0x79, 0xf0, 0x1a, 0x9b, 0xb5, 0xc3, 0x5d, 0xef, 0x7d, 0xc9, 0x05, \ + 0x99, 0x44, 0x81, 0x84, 0x75, 0xc7, 0xec, 0x00, 0x12, 0xfc, 0x7a, 0x4a, \ + 0x0b, 0x82, 0x07, 0xec, 0x6d, 0x86, 0x02, 0x4d, 0xfe, 0x9f, 0xc8, 0x92, \ + 0x48, 0xde, 0xf5, 0xb1, 0x9c, 0xe9, 0xc6, 0x89, 0xd0, 0xc1, 0x56, 0xe8, \ + 0xa4, 0xc6, 0x6a, 0x2e, 0x66, 0xc1, 0x9b, 0xfe, 0xd6, 0x3c, 0xb7 \ +} +/* END FILE */ + +/* This is taken from tests/data_files/server2.crt. */ +/* BEGIN FILE string macro TEST_SRV_CRT_RSA_SHA1_PEM tests/data_files/server2.crt */ +#define TEST_SRV_CRT_RSA_SHA1_PEM \ +"-----BEGIN CERTIFICATE-----\r\n" \ +"MIIDNzCCAh+gAwIBAgIBAjANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n" \ +"MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" \ +"MTkwMjEwMTQ0NDA2WhcNMjkwMjEwMTQ0NDA2WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n" \ +"A1UECgwIUG9sYXJTU0wxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcN\r\n" \ +"AQEBBQADggEPADCCAQoCggEBAMFNo93nzR3RBNdJcriZrA545Do8Ss86ExbQWuTN\r\n" \ +"owCIp+4ea5anUrSQ7y1yej4kmvy2NKwk9XfgJmSMnLAofaHa6ozmyRyWvP7BBFKz\r\n" \ +"NtSj+uGxdtiQwWG0ZlI2oiZTqqt0Xgd9GYLbKtgfoNkNHC1JZvdbJXNG6AuKT2kM\r\n" \ +"tQCQ4dqCEGZ9rlQri2V5kaHiYcPNQEkI7mgM8YuG0ka/0LiqEQMef1aoGh5EGA8P\r\n" \ +"hYvai0Re4hjGYi/HZo36Xdh98yeJKQHFkA4/J/EwyEoO79bex8cna8cFPXrEAjya\r\n" \ +"HT4P6DSYW8tzS1KW2BGiLICIaTla0w+w3lkvEcf36hIBMJcCAwEAAaNNMEswCQYD\r\n" \ +"VR0TBAIwADAdBgNVHQ4EFgQUpQXoZLjc32APUBJNYKhkr02LQ5MwHwYDVR0jBBgw\r\n" \ +"FoAUtFrkpbPe0lL2udWmlQ/rPrzH/f8wDQYJKoZIhvcNAQEFBQADggEBAJklg3Q4\r\n" \ +"cB7v7BzsxM/vLyKccO6op0/gZzM4ghuLq2Y32kl0sM6kSNUUmduuq3u/+GmUZN2A\r\n" \ +"O/7c+Hw7hDFEIvZk98aBGjCLqn3DmgHIv8ToQ67nellQxx2Uj309PdgjNi/r9HOc\r\n" \ +"KNAYPbBcg6MJGWWj2TI6vNaceios/DhOYx5V0j5nfqSJ/pnU0g9Ign2LAhgYpGJE\r\n" \ +"iEM9wW7hEMkwmk0h/sqZsrJsGH5YsF/VThSq/JVO1e2mZH2vruyZKJVBq+8tDNYp\r\n" \ +"HkK6tSyVYQhzIt3StMJWKMl/o5k2AYz6tSC164+1oG+ML3LWg8XrGKa91H4UOKap\r\n" \ +"Awgk0+4m0T25cNs=\r\n" \ +"-----END CERTIFICATE-----\r\n" +/* END FILE */ + +/* This is taken from tests/data_files/server2.crt.der. */ +/* BEGIN FILE binary macro TEST_SRV_CRT_RSA_SHA1_DER tests/data_files/server2.crt.der */ +#define TEST_SRV_CRT_RSA_SHA1_DER { \ + 0x30, 0x82, 0x03, 0x37, 0x30, 0x82, 0x02, 0x1f, 0xa0, 0x03, 0x02, 0x01, \ + 0x02, 0x02, 0x01, 0x02, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, \ + 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x3b, 0x31, 0x0b, 0x30, \ + 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, \ + 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, \ + 0x61, 0x72, 0x53, 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, \ + 0x04, 0x03, 0x0c, 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, \ + 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, \ + 0x31, 0x31, 0x30, 0x32, 0x31, 0x32, 0x31, 0x34, 0x34, 0x34, 0x30, 0x36, \ + 0x5a, 0x17, 0x0d, 0x32, 0x31, 0x30, 0x32, 0x31, 0x32, 0x31, 0x34, 0x34, \ + 0x34, 0x30, 0x36, 0x5a, 0x30, 0x34, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, \ + 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, \ + 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, \ + 0x53, 0x4c, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, \ + 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x30, 0x82, \ + 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, \ + 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, \ + 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xc1, 0x4d, 0xa3, 0xdd, 0xe7, \ + 0xcd, 0x1d, 0xd1, 0x04, 0xd7, 0x49, 0x72, 0xb8, 0x99, 0xac, 0x0e, 0x78, \ + 0xe4, 0x3a, 0x3c, 0x4a, 0xcf, 0x3a, 0x13, 0x16, 0xd0, 0x5a, 0xe4, 0xcd, \ + 0xa3, 0x00, 0x88, 0xa7, 0xee, 0x1e, 0x6b, 0x96, 0xa7, 0x52, 0xb4, 0x90, \ + 0xef, 0x2d, 0x72, 0x7a, 0x3e, 0x24, 0x9a, 0xfc, 0xb6, 0x34, 0xac, 0x24, \ + 0xf5, 0x77, 0xe0, 0x26, 0x64, 0x8c, 0x9c, 0xb0, 0x28, 0x7d, 0xa1, 0xda, \ + 0xea, 0x8c, 0xe6, 0xc9, 0x1c, 0x96, 0xbc, 0xfe, 0xc1, 0x04, 0x52, 0xb3, \ + 0x36, 0xd4, 0xa3, 0xfa, 0xe1, 0xb1, 0x76, 0xd8, 0x90, 0xc1, 0x61, 0xb4, \ + 0x66, 0x52, 0x36, 0xa2, 0x26, 0x53, 0xaa, 0xab, 0x74, 0x5e, 0x07, 0x7d, \ + 0x19, 0x82, 0xdb, 0x2a, 0xd8, 0x1f, 0xa0, 0xd9, 0x0d, 0x1c, 0x2d, 0x49, \ + 0x66, 0xf7, 0x5b, 0x25, 0x73, 0x46, 0xe8, 0x0b, 0x8a, 0x4f, 0x69, 0x0c, \ + 0xb5, 0x00, 0x90, 0xe1, 0xda, 0x82, 0x10, 0x66, 0x7d, 0xae, 0x54, 0x2b, \ + 0x8b, 0x65, 0x79, 0x91, 0xa1, 0xe2, 0x61, 0xc3, 0xcd, 0x40, 0x49, 0x08, \ + 0xee, 0x68, 0x0c, 0xf1, 0x8b, 0x86, 0xd2, 0x46, 0xbf, 0xd0, 0xb8, 0xaa, \ + 0x11, 0x03, 0x1e, 0x7f, 0x56, 0xa8, 0x1a, 0x1e, 0x44, 0x18, 0x0f, 0x0f, \ + 0x85, 0x8b, 0xda, 0x8b, 0x44, 0x5e, 0xe2, 0x18, 0xc6, 0x62, 0x2f, 0xc7, \ + 0x66, 0x8d, 0xfa, 0x5d, 0xd8, 0x7d, 0xf3, 0x27, 0x89, 0x29, 0x01, 0xc5, \ + 0x90, 0x0e, 0x3f, 0x27, 0xf1, 0x30, 0xc8, 0x4a, 0x0e, 0xef, 0xd6, 0xde, \ + 0xc7, 0xc7, 0x27, 0x6b, 0xc7, 0x05, 0x3d, 0x7a, 0xc4, 0x02, 0x3c, 0x9a, \ + 0x1d, 0x3e, 0x0f, 0xe8, 0x34, 0x98, 0x5b, 0xcb, 0x73, 0x4b, 0x52, 0x96, \ + 0xd8, 0x11, 0xa2, 0x2c, 0x80, 0x88, 0x69, 0x39, 0x5a, 0xd3, 0x0f, 0xb0, \ + 0xde, 0x59, 0x2f, 0x11, 0xc7, 0xf7, 0xea, 0x12, 0x01, 0x30, 0x97, 0x02, \ + 0x03, 0x01, 0x00, 0x01, 0xa3, 0x4d, 0x30, 0x4b, 0x30, 0x09, 0x06, 0x03, \ + 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, \ + 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xa5, 0x05, 0xe8, 0x64, 0xb8, 0xdc, \ + 0xdf, 0x60, 0x0f, 0x50, 0x12, 0x4d, 0x60, 0xa8, 0x64, 0xaf, 0x4d, 0x8b, \ + 0x43, 0x93, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, \ + 0x16, 0x80, 0x14, 0xb4, 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, 0xf6, \ + 0xb9, 0xd5, 0xa6, 0x95, 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, 0x30, \ + 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, \ + 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x01, 0x73, 0x0b, 0x4a, 0xc5, \ + 0xcb, 0xa0, 0xde, 0xf1, 0x63, 0x1c, 0x76, 0x04, 0x2b, 0x13, 0x0d, 0xc0, \ + 0x84, 0x11, 0xc5, 0x8f, 0x3a, 0xa7, 0xc5, 0x9c, 0x35, 0x7a, 0x77, 0xb8, \ + 0x20, 0x14, 0x82, 0xee, 0x54, 0xf0, 0xf2, 0xb0, 0x52, 0xcb, 0x78, 0xce, \ + 0x59, 0x07, 0x4f, 0x51, 0x69, 0xfe, 0xd3, 0x2f, 0xe9, 0x09, 0xe7, 0x85, \ + 0x92, 0xd8, 0xba, 0xb1, 0xeb, 0xc5, 0x76, 0x5d, 0x61, 0x2d, 0xe9, 0x86, \ + 0xb5, 0xde, 0x2a, 0xf9, 0x3f, 0x53, 0x28, 0x42, 0x86, 0x83, 0x73, 0x43, \ + 0xe0, 0x04, 0x5f, 0x07, 0x90, 0x14, 0x65, 0x9f, 0x6e, 0x10, 0x7a, 0xbc, \ + 0x58, 0x19, 0x22, 0xc2, 0xeb, 0x39, 0x72, 0x51, 0x92, 0xd7, 0xb4, 0x1d, \ + 0x75, 0x2f, 0xd3, 0x3a, 0x2b, 0x01, 0xe7, 0xdb, 0x50, 0xae, 0xe2, 0xf1, \ + 0xd4, 0x4d, 0x5b, 0x3c, 0xbb, 0x41, 0x2b, 0x2a, 0xa4, 0xe2, 0x4a, 0x02, \ + 0xe5, 0x60, 0x14, 0x2c, 0x9c, 0x1f, 0xa6, 0xcc, 0x06, 0x4b, 0x25, 0x89, \ + 0x4e, 0x96, 0x30, 0x22, 0x9c, 0x5c, 0x58, 0x4d, 0xc3, 0xda, 0xd0, 0x6e, \ + 0x50, 0x1e, 0x8c, 0x65, 0xf5, 0xd9, 0x17, 0x35, 0xa6, 0x58, 0x43, 0xb2, \ + 0x29, 0xb7, 0xa8, 0x5e, 0x35, 0xde, 0xf0, 0x60, 0x42, 0x1a, 0x01, 0xcb, \ + 0xcb, 0x0b, 0xd8, 0x0e, 0xc1, 0x90, 0xdf, 0xa1, 0xd2, 0x1a, 0xd1, 0x2c, \ + 0x02, 0xf4, 0x76, 0x41, 0xa4, 0xcb, 0x4b, 0x15, 0x98, 0x71, 0xf9, 0x35, \ + 0x7d, 0xb0, 0xe7, 0xe2, 0x34, 0x96, 0x91, 0xbe, 0x32, 0x67, 0x2d, 0x6b, \ + 0xd3, 0x55, 0x04, 0x8a, 0x01, 0x50, 0xb4, 0xe3, 0x62, 0x78, 0x6c, 0x11, \ + 0x15, 0xa5, 0x2a, 0x11, 0xc1, 0x49, 0x1c, 0x9b, 0xc4, 0x10, 0x65, 0x60, \ + 0x87, 0xd9, 0x1e, 0x69, 0x59, 0x4e, 0x8f, 0x6b, 0xeb, 0xc1, 0xfe, 0x6b, \ + 0xe2, 0x63, 0x78, 0x95, 0x6e, 0xe0, 0x2d, 0xd7, 0xa7, 0x37, 0xa8 \ +} +/* END FILE */ + +/* This is taken from tests/data_files/server2.key. */ +/* BEGIN FILE string macro TEST_SRV_KEY_RSA_PEM tests/data_files/server2.key */ +#define TEST_SRV_KEY_RSA_PEM \ + "-----BEGIN RSA PRIVATE KEY-----\r\n" \ + "MIIEpAIBAAKCAQEAwU2j3efNHdEE10lyuJmsDnjkOjxKzzoTFtBa5M2jAIin7h5r\r\n" \ + "lqdStJDvLXJ6PiSa/LY0rCT1d+AmZIycsCh9odrqjObJHJa8/sEEUrM21KP64bF2\r\n" \ + "2JDBYbRmUjaiJlOqq3ReB30Zgtsq2B+g2Q0cLUlm91slc0boC4pPaQy1AJDh2oIQ\r\n" \ + "Zn2uVCuLZXmRoeJhw81ASQjuaAzxi4bSRr/QuKoRAx5/VqgaHkQYDw+Fi9qLRF7i\r\n" \ + "GMZiL8dmjfpd2H3zJ4kpAcWQDj8n8TDISg7v1t7HxydrxwU9esQCPJodPg/oNJhb\r\n" \ + "y3NLUpbYEaIsgIhpOVrTD7DeWS8Rx/fqEgEwlwIDAQABAoIBAQCXR0S8EIHFGORZ\r\n" \ + "++AtOg6eENxD+xVs0f1IeGz57Tjo3QnXX7VBZNdj+p1ECvhCE/G7XnkgU5hLZX+G\r\n" \ + "Z0jkz/tqJOI0vRSdLBbipHnWouyBQ4e/A1yIJdlBtqXxJ1KE/ituHRbNc4j4kL8Z\r\n" \ + "/r6pvwnTI0PSx2Eqs048YdS92LT6qAv4flbNDxMn2uY7s4ycS4Q8w1JXnCeaAnYm\r\n" \ + "WYI5wxO+bvRELR2Mcz5DmVnL8jRyml6l6582bSv5oufReFIbyPZbQWlXgYnpu6He\r\n" \ + "GTc7E1zKYQGG/9+DQUl/1vQuCPqQwny0tQoX2w5tdYpdMdVm+zkLtbajzdTviJJa\r\n" \ + "TWzL6lt5AoGBAN86+SVeJDcmQJcv4Eq6UhtRr4QGMiQMz0Sod6ettYxYzMgxtw28\r\n" \ + "CIrgpozCc+UaZJLo7UxvC6an85r1b2nKPCLQFaggJ0H4Q0J/sZOhBIXaoBzWxveK\r\n" \ + "nupceKdVxGsFi8CDy86DBfiyFivfBj+47BbaQzPBj7C4rK7UlLjab2rDAoGBAN2u\r\n" \ + "AM2gchoFiu4v1HFL8D7lweEpi6ZnMJjnEu/dEgGQJFjwdpLnPbsj4c75odQ4Gz8g\r\n" \ + "sw9lao9VVzbusoRE/JGI4aTdO0pATXyG7eG1Qu+5Yc1YGXcCrliA2xM9xx+d7f+s\r\n" \ + "mPzN+WIEg5GJDYZDjAzHG5BNvi/FfM1C9dOtjv2dAoGAF0t5KmwbjWHBhcVqO4Ic\r\n" \ + "BVvN3BIlc1ue2YRXEDlxY5b0r8N4XceMgKmW18OHApZxfl8uPDauWZLXOgl4uepv\r\n" \ + "whZC3EuWrSyyICNhLY21Ah7hbIEBPF3L3ZsOwC+UErL+dXWLdB56Jgy3gZaBeW7b\r\n" \ + "vDrEnocJbqCm7IukhXHOBK8CgYEAwqdHB0hqyNSzIOGY7v9abzB6pUdA3BZiQvEs\r\n" \ + "3LjHVd4HPJ2x0N8CgrBIWOE0q8+0hSMmeE96WW/7jD3fPWwCR5zlXknxBQsfv0gP\r\n" \ + "3BC5PR0Qdypz+d+9zfMf625kyit4T/hzwhDveZUzHnk1Cf+IG7Q+TOEnLnWAWBED\r\n" \ + "ISOWmrUCgYAFEmRxgwAc/u+D6t0syCwAYh6POtscq9Y0i9GyWk89NzgC4NdwwbBH\r\n" \ + "4AgahOxIxXx2gxJnq3yfkJfIjwf0s2DyP0kY2y6Ua1OeomPeY9mrIS4tCuDQ6LrE\r\n" \ + "TB6l9VGoxJL4fyHnZb8L5gGvnB1bbD8cL6YPaDiOhcRseC9vBiEuVg==\r\n" \ + "-----END RSA PRIVATE KEY-----\r\n" +/* END FILE */ + +/* This was generated from tests/data_files/server2.key.der using `xxd -i`. */ +/* BEGIN FILE binary macro TEST_SRV_KEY_RSA_DER tests/data_files/server2.key.der */ +#define TEST_SRV_KEY_RSA_DER { \ + 0x30, 0x82, 0x04, 0xa4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, \ + 0xc1, 0x4d, 0xa3, 0xdd, 0xe7, 0xcd, 0x1d, 0xd1, 0x04, 0xd7, 0x49, 0x72, \ + 0xb8, 0x99, 0xac, 0x0e, 0x78, 0xe4, 0x3a, 0x3c, 0x4a, 0xcf, 0x3a, 0x13, \ + 0x16, 0xd0, 0x5a, 0xe4, 0xcd, 0xa3, 0x00, 0x88, 0xa7, 0xee, 0x1e, 0x6b, \ + 0x96, 0xa7, 0x52, 0xb4, 0x90, 0xef, 0x2d, 0x72, 0x7a, 0x3e, 0x24, 0x9a, \ + 0xfc, 0xb6, 0x34, 0xac, 0x24, 0xf5, 0x77, 0xe0, 0x26, 0x64, 0x8c, 0x9c, \ + 0xb0, 0x28, 0x7d, 0xa1, 0xda, 0xea, 0x8c, 0xe6, 0xc9, 0x1c, 0x96, 0xbc, \ + 0xfe, 0xc1, 0x04, 0x52, 0xb3, 0x36, 0xd4, 0xa3, 0xfa, 0xe1, 0xb1, 0x76, \ + 0xd8, 0x90, 0xc1, 0x61, 0xb4, 0x66, 0x52, 0x36, 0xa2, 0x26, 0x53, 0xaa, \ + 0xab, 0x74, 0x5e, 0x07, 0x7d, 0x19, 0x82, 0xdb, 0x2a, 0xd8, 0x1f, 0xa0, \ + 0xd9, 0x0d, 0x1c, 0x2d, 0x49, 0x66, 0xf7, 0x5b, 0x25, 0x73, 0x46, 0xe8, \ + 0x0b, 0x8a, 0x4f, 0x69, 0x0c, 0xb5, 0x00, 0x90, 0xe1, 0xda, 0x82, 0x10, \ + 0x66, 0x7d, 0xae, 0x54, 0x2b, 0x8b, 0x65, 0x79, 0x91, 0xa1, 0xe2, 0x61, \ + 0xc3, 0xcd, 0x40, 0x49, 0x08, 0xee, 0x68, 0x0c, 0xf1, 0x8b, 0x86, 0xd2, \ + 0x46, 0xbf, 0xd0, 0xb8, 0xaa, 0x11, 0x03, 0x1e, 0x7f, 0x56, 0xa8, 0x1a, \ + 0x1e, 0x44, 0x18, 0x0f, 0x0f, 0x85, 0x8b, 0xda, 0x8b, 0x44, 0x5e, 0xe2, \ + 0x18, 0xc6, 0x62, 0x2f, 0xc7, 0x66, 0x8d, 0xfa, 0x5d, 0xd8, 0x7d, 0xf3, \ + 0x27, 0x89, 0x29, 0x01, 0xc5, 0x90, 0x0e, 0x3f, 0x27, 0xf1, 0x30, 0xc8, \ + 0x4a, 0x0e, 0xef, 0xd6, 0xde, 0xc7, 0xc7, 0x27, 0x6b, 0xc7, 0x05, 0x3d, \ + 0x7a, 0xc4, 0x02, 0x3c, 0x9a, 0x1d, 0x3e, 0x0f, 0xe8, 0x34, 0x98, 0x5b, \ + 0xcb, 0x73, 0x4b, 0x52, 0x96, 0xd8, 0x11, 0xa2, 0x2c, 0x80, 0x88, 0x69, \ + 0x39, 0x5a, 0xd3, 0x0f, 0xb0, 0xde, 0x59, 0x2f, 0x11, 0xc7, 0xf7, 0xea, \ + 0x12, 0x01, 0x30, 0x97, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, \ + 0x01, 0x00, 0x97, 0x47, 0x44, 0xbc, 0x10, 0x81, 0xc5, 0x18, 0xe4, 0x59, \ + 0xfb, 0xe0, 0x2d, 0x3a, 0x0e, 0x9e, 0x10, 0xdc, 0x43, 0xfb, 0x15, 0x6c, \ + 0xd1, 0xfd, 0x48, 0x78, 0x6c, 0xf9, 0xed, 0x38, 0xe8, 0xdd, 0x09, 0xd7, \ + 0x5f, 0xb5, 0x41, 0x64, 0xd7, 0x63, 0xfa, 0x9d, 0x44, 0x0a, 0xf8, 0x42, \ + 0x13, 0xf1, 0xbb, 0x5e, 0x79, 0x20, 0x53, 0x98, 0x4b, 0x65, 0x7f, 0x86, \ + 0x67, 0x48, 0xe4, 0xcf, 0xfb, 0x6a, 0x24, 0xe2, 0x34, 0xbd, 0x14, 0x9d, \ + 0x2c, 0x16, 0xe2, 0xa4, 0x79, 0xd6, 0xa2, 0xec, 0x81, 0x43, 0x87, 0xbf, \ + 0x03, 0x5c, 0x88, 0x25, 0xd9, 0x41, 0xb6, 0xa5, 0xf1, 0x27, 0x52, 0x84, \ + 0xfe, 0x2b, 0x6e, 0x1d, 0x16, 0xcd, 0x73, 0x88, 0xf8, 0x90, 0xbf, 0x19, \ + 0xfe, 0xbe, 0xa9, 0xbf, 0x09, 0xd3, 0x23, 0x43, 0xd2, 0xc7, 0x61, 0x2a, \ + 0xb3, 0x4e, 0x3c, 0x61, 0xd4, 0xbd, 0xd8, 0xb4, 0xfa, 0xa8, 0x0b, 0xf8, \ + 0x7e, 0x56, 0xcd, 0x0f, 0x13, 0x27, 0xda, 0xe6, 0x3b, 0xb3, 0x8c, 0x9c, \ + 0x4b, 0x84, 0x3c, 0xc3, 0x52, 0x57, 0x9c, 0x27, 0x9a, 0x02, 0x76, 0x26, \ + 0x59, 0x82, 0x39, 0xc3, 0x13, 0xbe, 0x6e, 0xf4, 0x44, 0x2d, 0x1d, 0x8c, \ + 0x73, 0x3e, 0x43, 0x99, 0x59, 0xcb, 0xf2, 0x34, 0x72, 0x9a, 0x5e, 0xa5, \ + 0xeb, 0x9f, 0x36, 0x6d, 0x2b, 0xf9, 0xa2, 0xe7, 0xd1, 0x78, 0x52, 0x1b, \ + 0xc8, 0xf6, 0x5b, 0x41, 0x69, 0x57, 0x81, 0x89, 0xe9, 0xbb, 0xa1, 0xde, \ + 0x19, 0x37, 0x3b, 0x13, 0x5c, 0xca, 0x61, 0x01, 0x86, 0xff, 0xdf, 0x83, \ + 0x41, 0x49, 0x7f, 0xd6, 0xf4, 0x2e, 0x08, 0xfa, 0x90, 0xc2, 0x7c, 0xb4, \ + 0xb5, 0x0a, 0x17, 0xdb, 0x0e, 0x6d, 0x75, 0x8a, 0x5d, 0x31, 0xd5, 0x66, \ + 0xfb, 0x39, 0x0b, 0xb5, 0xb6, 0xa3, 0xcd, 0xd4, 0xef, 0x88, 0x92, 0x5a, \ + 0x4d, 0x6c, 0xcb, 0xea, 0x5b, 0x79, 0x02, 0x81, 0x81, 0x00, 0xdf, 0x3a, \ + 0xf9, 0x25, 0x5e, 0x24, 0x37, 0x26, 0x40, 0x97, 0x2f, 0xe0, 0x4a, 0xba, \ + 0x52, 0x1b, 0x51, 0xaf, 0x84, 0x06, 0x32, 0x24, 0x0c, 0xcf, 0x44, 0xa8, \ + 0x77, 0xa7, 0xad, 0xb5, 0x8c, 0x58, 0xcc, 0xc8, 0x31, 0xb7, 0x0d, 0xbc, \ + 0x08, 0x8a, 0xe0, 0xa6, 0x8c, 0xc2, 0x73, 0xe5, 0x1a, 0x64, 0x92, 0xe8, \ + 0xed, 0x4c, 0x6f, 0x0b, 0xa6, 0xa7, 0xf3, 0x9a, 0xf5, 0x6f, 0x69, 0xca, \ + 0x3c, 0x22, 0xd0, 0x15, 0xa8, 0x20, 0x27, 0x41, 0xf8, 0x43, 0x42, 0x7f, \ + 0xb1, 0x93, 0xa1, 0x04, 0x85, 0xda, 0xa0, 0x1c, 0xd6, 0xc6, 0xf7, 0x8a, \ + 0x9e, 0xea, 0x5c, 0x78, 0xa7, 0x55, 0xc4, 0x6b, 0x05, 0x8b, 0xc0, 0x83, \ + 0xcb, 0xce, 0x83, 0x05, 0xf8, 0xb2, 0x16, 0x2b, 0xdf, 0x06, 0x3f, 0xb8, \ + 0xec, 0x16, 0xda, 0x43, 0x33, 0xc1, 0x8f, 0xb0, 0xb8, 0xac, 0xae, 0xd4, \ + 0x94, 0xb8, 0xda, 0x6f, 0x6a, 0xc3, 0x02, 0x81, 0x81, 0x00, 0xdd, 0xae, \ + 0x00, 0xcd, 0xa0, 0x72, 0x1a, 0x05, 0x8a, 0xee, 0x2f, 0xd4, 0x71, 0x4b, \ + 0xf0, 0x3e, 0xe5, 0xc1, 0xe1, 0x29, 0x8b, 0xa6, 0x67, 0x30, 0x98, 0xe7, \ + 0x12, 0xef, 0xdd, 0x12, 0x01, 0x90, 0x24, 0x58, 0xf0, 0x76, 0x92, 0xe7, \ + 0x3d, 0xbb, 0x23, 0xe1, 0xce, 0xf9, 0xa1, 0xd4, 0x38, 0x1b, 0x3f, 0x20, \ + 0xb3, 0x0f, 0x65, 0x6a, 0x8f, 0x55, 0x57, 0x36, 0xee, 0xb2, 0x84, 0x44, \ + 0xfc, 0x91, 0x88, 0xe1, 0xa4, 0xdd, 0x3b, 0x4a, 0x40, 0x4d, 0x7c, 0x86, \ + 0xed, 0xe1, 0xb5, 0x42, 0xef, 0xb9, 0x61, 0xcd, 0x58, 0x19, 0x77, 0x02, \ + 0xae, 0x58, 0x80, 0xdb, 0x13, 0x3d, 0xc7, 0x1f, 0x9d, 0xed, 0xff, 0xac, \ + 0x98, 0xfc, 0xcd, 0xf9, 0x62, 0x04, 0x83, 0x91, 0x89, 0x0d, 0x86, 0x43, \ + 0x8c, 0x0c, 0xc7, 0x1b, 0x90, 0x4d, 0xbe, 0x2f, 0xc5, 0x7c, 0xcd, 0x42, \ + 0xf5, 0xd3, 0xad, 0x8e, 0xfd, 0x9d, 0x02, 0x81, 0x80, 0x17, 0x4b, 0x79, \ + 0x2a, 0x6c, 0x1b, 0x8d, 0x61, 0xc1, 0x85, 0xc5, 0x6a, 0x3b, 0x82, 0x1c, \ + 0x05, 0x5b, 0xcd, 0xdc, 0x12, 0x25, 0x73, 0x5b, 0x9e, 0xd9, 0x84, 0x57, \ + 0x10, 0x39, 0x71, 0x63, 0x96, 0xf4, 0xaf, 0xc3, 0x78, 0x5d, 0xc7, 0x8c, \ + 0x80, 0xa9, 0x96, 0xd7, 0xc3, 0x87, 0x02, 0x96, 0x71, 0x7e, 0x5f, 0x2e, \ + 0x3c, 0x36, 0xae, 0x59, 0x92, 0xd7, 0x3a, 0x09, 0x78, 0xb9, 0xea, 0x6f, \ + 0xc2, 0x16, 0x42, 0xdc, 0x4b, 0x96, 0xad, 0x2c, 0xb2, 0x20, 0x23, 0x61, \ + 0x2d, 0x8d, 0xb5, 0x02, 0x1e, 0xe1, 0x6c, 0x81, 0x01, 0x3c, 0x5d, 0xcb, \ + 0xdd, 0x9b, 0x0e, 0xc0, 0x2f, 0x94, 0x12, 0xb2, 0xfe, 0x75, 0x75, 0x8b, \ + 0x74, 0x1e, 0x7a, 0x26, 0x0c, 0xb7, 0x81, 0x96, 0x81, 0x79, 0x6e, 0xdb, \ + 0xbc, 0x3a, 0xc4, 0x9e, 0x87, 0x09, 0x6e, 0xa0, 0xa6, 0xec, 0x8b, 0xa4, \ + 0x85, 0x71, 0xce, 0x04, 0xaf, 0x02, 0x81, 0x81, 0x00, 0xc2, 0xa7, 0x47, \ + 0x07, 0x48, 0x6a, 0xc8, 0xd4, 0xb3, 0x20, 0xe1, 0x98, 0xee, 0xff, 0x5a, \ + 0x6f, 0x30, 0x7a, 0xa5, 0x47, 0x40, 0xdc, 0x16, 0x62, 0x42, 0xf1, 0x2c, \ + 0xdc, 0xb8, 0xc7, 0x55, 0xde, 0x07, 0x3c, 0x9d, 0xb1, 0xd0, 0xdf, 0x02, \ + 0x82, 0xb0, 0x48, 0x58, 0xe1, 0x34, 0xab, 0xcf, 0xb4, 0x85, 0x23, 0x26, \ + 0x78, 0x4f, 0x7a, 0x59, 0x6f, 0xfb, 0x8c, 0x3d, 0xdf, 0x3d, 0x6c, 0x02, \ + 0x47, 0x9c, 0xe5, 0x5e, 0x49, 0xf1, 0x05, 0x0b, 0x1f, 0xbf, 0x48, 0x0f, \ + 0xdc, 0x10, 0xb9, 0x3d, 0x1d, 0x10, 0x77, 0x2a, 0x73, 0xf9, 0xdf, 0xbd, \ + 0xcd, 0xf3, 0x1f, 0xeb, 0x6e, 0x64, 0xca, 0x2b, 0x78, 0x4f, 0xf8, 0x73, \ + 0xc2, 0x10, 0xef, 0x79, 0x95, 0x33, 0x1e, 0x79, 0x35, 0x09, 0xff, 0x88, \ + 0x1b, 0xb4, 0x3e, 0x4c, 0xe1, 0x27, 0x2e, 0x75, 0x80, 0x58, 0x11, 0x03, \ + 0x21, 0x23, 0x96, 0x9a, 0xb5, 0x02, 0x81, 0x80, 0x05, 0x12, 0x64, 0x71, \ + 0x83, 0x00, 0x1c, 0xfe, 0xef, 0x83, 0xea, 0xdd, 0x2c, 0xc8, 0x2c, 0x00, \ + 0x62, 0x1e, 0x8f, 0x3a, 0xdb, 0x1c, 0xab, 0xd6, 0x34, 0x8b, 0xd1, 0xb2, \ + 0x5a, 0x4f, 0x3d, 0x37, 0x38, 0x02, 0xe0, 0xd7, 0x70, 0xc1, 0xb0, 0x47, \ + 0xe0, 0x08, 0x1a, 0x84, 0xec, 0x48, 0xc5, 0x7c, 0x76, 0x83, 0x12, 0x67, \ + 0xab, 0x7c, 0x9f, 0x90, 0x97, 0xc8, 0x8f, 0x07, 0xf4, 0xb3, 0x60, 0xf2, \ + 0x3f, 0x49, 0x18, 0xdb, 0x2e, 0x94, 0x6b, 0x53, 0x9e, 0xa2, 0x63, 0xde, \ + 0x63, 0xd9, 0xab, 0x21, 0x2e, 0x2d, 0x0a, 0xe0, 0xd0, 0xe8, 0xba, 0xc4, \ + 0x4c, 0x1e, 0xa5, 0xf5, 0x51, 0xa8, 0xc4, 0x92, 0xf8, 0x7f, 0x21, 0xe7, \ + 0x65, 0xbf, 0x0b, 0xe6, 0x01, 0xaf, 0x9c, 0x1d, 0x5b, 0x6c, 0x3f, 0x1c, \ + 0x2f, 0xa6, 0x0f, 0x68, 0x38, 0x8e, 0x85, 0xc4, 0x6c, 0x78, 0x2f, 0x6f, \ + 0x06, 0x21, 0x2e, 0x56 \ +} +/* END FILE */ + +/* + * Test client Certificates + * + * Test client certificates are defined for each choice + * of the following parameters: + * - PEM or DER encoding + * - RSA or EC key + * + * Things to add: + * - hash type + * - multiple EC curve types + */ + +/* This is taken from tests/data_files/cli2.crt. */ +/* BEGIN FILE string macro TEST_CLI_CRT_EC_PEM tests/data_files/cli2.crt */ +#define TEST_CLI_CRT_EC_PEM \ + "-----BEGIN CERTIFICATE-----\r\n" \ + "MIIB3zCCAWOgAwIBAgIBDTAMBggqhkjOPQQDAgUAMD4xCzAJBgNVBAYTAk5MMREw\r\n" \ + "DwYDVQQKDAhQb2xhclNTTDEcMBoGA1UEAwwTUG9sYXJTU0wgVGVzdCBFQyBDQTAe\r\n" \ + "Fw0xOTAyMTAxNDQ0MDBaFw0yOTAyMTAxNDQ0MDBaMEExCzAJBgNVBAYTAk5MMREw\r\n" \ + "DwYDVQQKDAhQb2xhclNTTDEfMB0GA1UEAwwWUG9sYXJTU0wgVGVzdCBDbGllbnQg\r\n" \ + "MjBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABFflrrFz39Osu5O4gf8Sru7mU6zO\r\n" \ + "VVP2NA7MLuNjJQvfmOLzXGA2lsDVGBRw5X+f1UtFGOWwbNVc+JaPh3Cj5MejTTBL\r\n" \ + "MAkGA1UdEwQCMAAwHQYDVR0OBBYEFHoAX4Zk/OBd5REQO7LmO8QmP8/iMB8GA1Ud\r\n" \ + "IwQYMBaAFJ1tICRJAT8ry3i1Gbx+JMnb+zZ8MAwGCCqGSM49BAMCBQADaAAwZQIx\r\n" \ + "AMqme4DKMldUlplDET9Q6Eptre7uUWKhsLOF+zPkKDlfzpIkJYEFgcloDHGYw80u\r\n" \ + "IgIwNftyPXsabTqMM7iEHgVpX/GRozKklY9yQI/5eoA6gGW7Y+imuGR/oao5ySOb\r\n" \ + "a9Vk\r\n" \ + "-----END CERTIFICATE-----\r\n" +/* END FILE */ + +/* This is generated from tests/data_files/cli2.crt.der using `xxd -i`. */ +/* BEGIN FILE binary macro TEST_CLI_CRT_EC_DER tests/data_files/cli2.crt.der */ +#define TEST_CLI_CRT_EC_DER { \ + 0x30, 0x82, 0x01, 0xdf, 0x30, 0x82, 0x01, 0x63, 0xa0, 0x03, 0x02, 0x01, \ + 0x02, 0x02, 0x01, 0x0d, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, \ + 0x3d, 0x04, 0x03, 0x02, 0x05, 0x00, 0x30, 0x3e, 0x31, 0x0b, 0x30, 0x09, \ + 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, \ + 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, \ + 0x72, 0x53, 0x53, 0x4c, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, \ + 0x03, 0x0c, 0x13, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, 0x20, \ + 0x54, 0x65, 0x73, 0x74, 0x20, 0x45, 0x43, 0x20, 0x43, 0x41, 0x30, 0x1e, \ + 0x17, 0x0d, 0x31, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, \ + 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x32, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, \ + 0x34, 0x34, 0x34, 0x30, 0x30, 0x5a, 0x30, 0x41, 0x31, 0x0b, 0x30, 0x09, \ + 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, \ + 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, \ + 0x72, 0x53, 0x53, 0x4c, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, \ + 0x03, 0x0c, 0x16, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, 0x20, \ + 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, \ + 0x32, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, \ + 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, \ + 0x03, 0x42, 0x00, 0x04, 0x57, 0xe5, 0xae, 0xb1, 0x73, 0xdf, 0xd3, 0xac, \ + 0xbb, 0x93, 0xb8, 0x81, 0xff, 0x12, 0xae, 0xee, 0xe6, 0x53, 0xac, 0xce, \ + 0x55, 0x53, 0xf6, 0x34, 0x0e, 0xcc, 0x2e, 0xe3, 0x63, 0x25, 0x0b, 0xdf, \ + 0x98, 0xe2, 0xf3, 0x5c, 0x60, 0x36, 0x96, 0xc0, 0xd5, 0x18, 0x14, 0x70, \ + 0xe5, 0x7f, 0x9f, 0xd5, 0x4b, 0x45, 0x18, 0xe5, 0xb0, 0x6c, 0xd5, 0x5c, \ + 0xf8, 0x96, 0x8f, 0x87, 0x70, 0xa3, 0xe4, 0xc7, 0xa3, 0x4d, 0x30, 0x4b, \ + 0x30, 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, \ + 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x7a, 0x00, \ + 0x5f, 0x86, 0x64, 0xfc, 0xe0, 0x5d, 0xe5, 0x11, 0x10, 0x3b, 0xb2, 0xe6, \ + 0x3b, 0xc4, 0x26, 0x3f, 0xcf, 0xe2, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, \ + 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x9d, 0x6d, 0x20, 0x24, 0x49, \ + 0x01, 0x3f, 0x2b, 0xcb, 0x78, 0xb5, 0x19, 0xbc, 0x7e, 0x24, 0xc9, 0xdb, \ + 0xfb, 0x36, 0x7c, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, \ + 0x04, 0x03, 0x02, 0x05, 0x00, 0x03, 0x68, 0x00, 0x30, 0x65, 0x02, 0x31, \ + 0x00, 0xca, 0xa6, 0x7b, 0x80, 0xca, 0x32, 0x57, 0x54, 0x96, 0x99, 0x43, \ + 0x11, 0x3f, 0x50, 0xe8, 0x4a, 0x6d, 0xad, 0xee, 0xee, 0x51, 0x62, 0xa1, \ + 0xb0, 0xb3, 0x85, 0xfb, 0x33, 0xe4, 0x28, 0x39, 0x5f, 0xce, 0x92, 0x24, \ + 0x25, 0x81, 0x05, 0x81, 0xc9, 0x68, 0x0c, 0x71, 0x98, 0xc3, 0xcd, 0x2e, \ + 0x22, 0x02, 0x30, 0x35, 0xfb, 0x72, 0x3d, 0x7b, 0x1a, 0x6d, 0x3a, 0x8c, \ + 0x33, 0xb8, 0x84, 0x1e, 0x05, 0x69, 0x5f, 0xf1, 0x91, 0xa3, 0x32, 0xa4, \ + 0x95, 0x8f, 0x72, 0x40, 0x8f, 0xf9, 0x7a, 0x80, 0x3a, 0x80, 0x65, 0xbb, \ + 0x63, 0xe8, 0xa6, 0xb8, 0x64, 0x7f, 0xa1, 0xaa, 0x39, 0xc9, 0x23, 0x9b, \ + 0x6b, 0xd5, 0x64 \ +} +/* END FILE */ + +/* This is taken from tests/data_files/cli2.key. */ +/* BEGIN FILE string macro TEST_CLI_KEY_EC_PEM tests/data_files/cli2.key */ +#define TEST_CLI_KEY_EC_PEM \ + "-----BEGIN EC PRIVATE KEY-----\r\n" \ + "MHcCAQEEIPb3hmTxZ3/mZI3vyk7p3U3wBf+WIop6hDhkFzJhmLcqoAoGCCqGSM49\r\n" \ + "AwEHoUQDQgAEV+WusXPf06y7k7iB/xKu7uZTrM5VU/Y0Dswu42MlC9+Y4vNcYDaW\r\n" \ + "wNUYFHDlf5/VS0UY5bBs1Vz4lo+HcKPkxw==\r\n" \ + "-----END EC PRIVATE KEY-----\r\n" +/* END FILE */ + +/* This is generated from tests/data_files/cli2.key.der using `xxd -i`. */ +/* BEGIN FILE binary macro TEST_CLI_KEY_EC_DER tests/data_files/cli2.key.der */ +#define TEST_CLI_KEY_EC_DER { \ + 0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0xf6, 0xf7, 0x86, 0x64, 0xf1, \ + 0x67, 0x7f, 0xe6, 0x64, 0x8d, 0xef, 0xca, 0x4e, 0xe9, 0xdd, 0x4d, 0xf0, \ + 0x05, 0xff, 0x96, 0x22, 0x8a, 0x7a, 0x84, 0x38, 0x64, 0x17, 0x32, 0x61, \ + 0x98, 0xb7, 0x2a, 0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, \ + 0x03, 0x01, 0x07, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x57, 0xe5, 0xae, \ + 0xb1, 0x73, 0xdf, 0xd3, 0xac, 0xbb, 0x93, 0xb8, 0x81, 0xff, 0x12, 0xae, \ + 0xee, 0xe6, 0x53, 0xac, 0xce, 0x55, 0x53, 0xf6, 0x34, 0x0e, 0xcc, 0x2e, \ + 0xe3, 0x63, 0x25, 0x0b, 0xdf, 0x98, 0xe2, 0xf3, 0x5c, 0x60, 0x36, 0x96, \ + 0xc0, 0xd5, 0x18, 0x14, 0x70, 0xe5, 0x7f, 0x9f, 0xd5, 0x4b, 0x45, 0x18, \ + 0xe5, 0xb0, 0x6c, 0xd5, 0x5c, 0xf8, 0x96, 0x8f, 0x87, 0x70, 0xa3, 0xe4, \ + 0xc7 \ +} +/* END FILE */ + +/* This is taken from tests/data_files/cli-rsa-sha256.crt. */ +/* BEGIN FILE string macro TEST_CLI_CRT_RSA_PEM tests/data_files/cli-rsa-sha256.crt */ +#define TEST_CLI_CRT_RSA_PEM \ + "-----BEGIN CERTIFICATE-----\r\n" \ + "MIIDPzCCAiegAwIBAgIBBDANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER\r\n" \ + "MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" \ + "MTkwMjEwMTQ0NDA2WhcNMjkwMjEwMTQ0NDA2WjA8MQswCQYDVQQGEwJOTDERMA8G\r\n" \ + "A1UECgwIUG9sYXJTU0wxGjAYBgNVBAMMEVBvbGFyU1NMIENsaWVudCAyMIIBIjAN\r\n" \ + "BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6f\r\n" \ + "M60Nj4o8VmXl3ETZzGaFB9X4J7BKNdBjngpuG7fa8H6r7gwQk4ZJGDTzqCrSV/Uu\r\n" \ + "1C93KYRhTYJQj6eVSHD1bk2y1RPD0hrt5kPqQhTrdOrA7R/UV06p86jt0uDBMHEw\r\n" \ + "MjDV0/YI0FZPRo7yX/k9Z5GIMC5Cst99++UMd//sMcB4j7/Cf8qtbCHWjdmLao5v\r\n" \ + "4Jv4EFbMs44TFeY0BGbH7vk2DmqV9gmaBmf0ZXH4yqSxJeD+PIs1BGe64E92hfx/\r\n" \ + "/DZrtenNLQNiTrM9AM+vdqBpVoNq0qjU51Bx5rU2BXcFbXvI5MT9TNUhXwIDAQAB\r\n" \ + "o00wSzAJBgNVHRMEAjAAMB0GA1UdDgQWBBRxoQBzckAvVHZeM/xSj7zx3WtGITAf\r\n" \ + "BgNVHSMEGDAWgBS0WuSls97SUva51aaVD+s+vMf9/zANBgkqhkiG9w0BAQsFAAOC\r\n" \ + "AQEAXidv1d4pLlBiKWED95rMycBdgDcgyNqJxakFkRfRyA2y1mlyTn7uBXRkNLY5\r\n" \ + "ZFzK82GCjk2Q2OD4RZSCPAJJqLpHHU34t71ciffvy2KK81YvrxczRhMAE64i+qna\r\n" \ + "yP3Td2XuWJR05PVPoSemsNELs9gWttdnYy3ce+EY2Y0n7Rsi7982EeLIAA7H6ca4\r\n" \ + "2Es/NUH//JZJT32OP0doMxeDRA+vplkKqTLLWf7dX26LIriBkBaRCgR5Yv9LBPFc\r\n" \ + "NOtpzu/LbrY7QFXKJMI+JXDudCsOn8KCmiA4d6Emisqfh3V3485l7HEQNcvLTxlD\r\n" \ + "6zDQyi0/ykYUYZkwQTK1N2Nvlw==\r\n" \ + "-----END CERTIFICATE-----\r\n" +/* END FILE */ + +/* This was generated from tests/data_files/cli-rsa-sha256.crt.der + using `xxd -i.` */ +/* BEGIN FILE binary macro TEST_CLI_CRT_RSA_DER tests/data_files/cli-rsa-sha256.crt.der */ +#define TEST_CLI_CRT_RSA_DER { \ + 0x30, 0x82, 0x03, 0x3f, 0x30, 0x82, 0x02, 0x27, 0xa0, 0x03, 0x02, 0x01, \ + 0x02, 0x02, 0x01, 0x04, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, \ + 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x3b, 0x31, 0x0b, 0x30, \ + 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, \ + 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, \ + 0x61, 0x72, 0x53, 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, \ + 0x04, 0x03, 0x0c, 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, \ + 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, \ + 0x31, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, 0x30, 0x36, \ + 0x5a, 0x17, 0x0d, 0x32, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, \ + 0x34, 0x30, 0x36, 0x5a, 0x30, 0x3c, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, \ + 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, \ + 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, \ + 0x53, 0x4c, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, \ + 0x11, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, 0x20, 0x43, 0x6c, \ + 0x69, 0x65, 0x6e, 0x74, 0x20, 0x32, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, \ + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, \ + 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, \ + 0x01, 0x01, 0x00, 0xc8, 0x74, 0xc4, 0xcc, 0xb9, 0xf9, 0xb5, 0x79, 0xe9, \ + 0x45, 0xd9, 0x14, 0x60, 0xb0, 0x7d, 0xbb, 0x93, 0xf2, 0x6b, 0x1e, 0x9f, \ + 0x33, 0xad, 0x0d, 0x8f, 0x8a, 0x3c, 0x56, 0x65, 0xe5, 0xdc, 0x44, 0xd9, \ + 0xcc, 0x66, 0x85, 0x07, 0xd5, 0xf8, 0x27, 0xb0, 0x4a, 0x35, 0xd0, 0x63, \ + 0x9e, 0x0a, 0x6e, 0x1b, 0xb7, 0xda, 0xf0, 0x7e, 0xab, 0xee, 0x0c, 0x10, \ + 0x93, 0x86, 0x49, 0x18, 0x34, 0xf3, 0xa8, 0x2a, 0xd2, 0x57, 0xf5, 0x2e, \ + 0xd4, 0x2f, 0x77, 0x29, 0x84, 0x61, 0x4d, 0x82, 0x50, 0x8f, 0xa7, 0x95, \ + 0x48, 0x70, 0xf5, 0x6e, 0x4d, 0xb2, 0xd5, 0x13, 0xc3, 0xd2, 0x1a, 0xed, \ + 0xe6, 0x43, 0xea, 0x42, 0x14, 0xeb, 0x74, 0xea, 0xc0, 0xed, 0x1f, 0xd4, \ + 0x57, 0x4e, 0xa9, 0xf3, 0xa8, 0xed, 0xd2, 0xe0, 0xc1, 0x30, 0x71, 0x30, \ + 0x32, 0x30, 0xd5, 0xd3, 0xf6, 0x08, 0xd0, 0x56, 0x4f, 0x46, 0x8e, 0xf2, \ + 0x5f, 0xf9, 0x3d, 0x67, 0x91, 0x88, 0x30, 0x2e, 0x42, 0xb2, 0xdf, 0x7d, \ + 0xfb, 0xe5, 0x0c, 0x77, 0xff, 0xec, 0x31, 0xc0, 0x78, 0x8f, 0xbf, 0xc2, \ + 0x7f, 0xca, 0xad, 0x6c, 0x21, 0xd6, 0x8d, 0xd9, 0x8b, 0x6a, 0x8e, 0x6f, \ + 0xe0, 0x9b, 0xf8, 0x10, 0x56, 0xcc, 0xb3, 0x8e, 0x13, 0x15, 0xe6, 0x34, \ + 0x04, 0x66, 0xc7, 0xee, 0xf9, 0x36, 0x0e, 0x6a, 0x95, 0xf6, 0x09, 0x9a, \ + 0x06, 0x67, 0xf4, 0x65, 0x71, 0xf8, 0xca, 0xa4, 0xb1, 0x25, 0xe0, 0xfe, \ + 0x3c, 0x8b, 0x35, 0x04, 0x67, 0xba, 0xe0, 0x4f, 0x76, 0x85, 0xfc, 0x7f, \ + 0xfc, 0x36, 0x6b, 0xb5, 0xe9, 0xcd, 0x2d, 0x03, 0x62, 0x4e, 0xb3, 0x3d, \ + 0x00, 0xcf, 0xaf, 0x76, 0xa0, 0x69, 0x56, 0x83, 0x6a, 0xd2, 0xa8, 0xd4, \ + 0xe7, 0x50, 0x71, 0xe6, 0xb5, 0x36, 0x05, 0x77, 0x05, 0x6d, 0x7b, 0xc8, \ + 0xe4, 0xc4, 0xfd, 0x4c, 0xd5, 0x21, 0x5f, 0x02, 0x03, 0x01, 0x00, 0x01, \ + 0xa3, 0x4d, 0x30, 0x4b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, \ + 0x02, 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, \ + 0x04, 0x14, 0x71, 0xa1, 0x00, 0x73, 0x72, 0x40, 0x2f, 0x54, 0x76, 0x5e, \ + 0x33, 0xfc, 0x52, 0x8f, 0xbc, 0xf1, 0xdd, 0x6b, 0x46, 0x21, 0x30, 0x1f, \ + 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xb4, \ + 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, 0xf6, 0xb9, 0xd5, 0xa6, 0x95, \ + 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, \ + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, \ + 0x01, 0x01, 0x00, 0x5e, 0x27, 0x6f, 0xd5, 0xde, 0x29, 0x2e, 0x50, 0x62, \ + 0x29, 0x61, 0x03, 0xf7, 0x9a, 0xcc, 0xc9, 0xc0, 0x5d, 0x80, 0x37, 0x20, \ + 0xc8, 0xda, 0x89, 0xc5, 0xa9, 0x05, 0x91, 0x17, 0xd1, 0xc8, 0x0d, 0xb2, \ + 0xd6, 0x69, 0x72, 0x4e, 0x7e, 0xee, 0x05, 0x74, 0x64, 0x34, 0xb6, 0x39, \ + 0x64, 0x5c, 0xca, 0xf3, 0x61, 0x82, 0x8e, 0x4d, 0x90, 0xd8, 0xe0, 0xf8, \ + 0x45, 0x94, 0x82, 0x3c, 0x02, 0x49, 0xa8, 0xba, 0x47, 0x1d, 0x4d, 0xf8, \ + 0xb7, 0xbd, 0x5c, 0x89, 0xf7, 0xef, 0xcb, 0x62, 0x8a, 0xf3, 0x56, 0x2f, \ + 0xaf, 0x17, 0x33, 0x46, 0x13, 0x00, 0x13, 0xae, 0x22, 0xfa, 0xa9, 0xda, \ + 0xc8, 0xfd, 0xd3, 0x77, 0x65, 0xee, 0x58, 0x94, 0x74, 0xe4, 0xf5, 0x4f, \ + 0xa1, 0x27, 0xa6, 0xb0, 0xd1, 0x0b, 0xb3, 0xd8, 0x16, 0xb6, 0xd7, 0x67, \ + 0x63, 0x2d, 0xdc, 0x7b, 0xe1, 0x18, 0xd9, 0x8d, 0x27, 0xed, 0x1b, 0x22, \ + 0xef, 0xdf, 0x36, 0x11, 0xe2, 0xc8, 0x00, 0x0e, 0xc7, 0xe9, 0xc6, 0xb8, \ + 0xd8, 0x4b, 0x3f, 0x35, 0x41, 0xff, 0xfc, 0x96, 0x49, 0x4f, 0x7d, 0x8e, \ + 0x3f, 0x47, 0x68, 0x33, 0x17, 0x83, 0x44, 0x0f, 0xaf, 0xa6, 0x59, 0x0a, \ + 0xa9, 0x32, 0xcb, 0x59, 0xfe, 0xdd, 0x5f, 0x6e, 0x8b, 0x22, 0xb8, 0x81, \ + 0x90, 0x16, 0x91, 0x0a, 0x04, 0x79, 0x62, 0xff, 0x4b, 0x04, 0xf1, 0x5c, \ + 0x34, 0xeb, 0x69, 0xce, 0xef, 0xcb, 0x6e, 0xb6, 0x3b, 0x40, 0x55, 0xca, \ + 0x24, 0xc2, 0x3e, 0x25, 0x70, 0xee, 0x74, 0x2b, 0x0e, 0x9f, 0xc2, 0x82, \ + 0x9a, 0x20, 0x38, 0x77, 0xa1, 0x26, 0x8a, 0xca, 0x9f, 0x87, 0x75, 0x77, \ + 0xe3, 0xce, 0x65, 0xec, 0x71, 0x10, 0x35, 0xcb, 0xcb, 0x4f, 0x19, 0x43, \ + 0xeb, 0x30, 0xd0, 0xca, 0x2d, 0x3f, 0xca, 0x46, 0x14, 0x61, 0x99, 0x30, \ + 0x41, 0x32, 0xb5, 0x37, 0x63, 0x6f, 0x97 \ +} +/* END FILE */ + +/* This is taken from tests/data_files/cli-rsa.key. */ +/* BEGIN FILE string macro TEST_CLI_KEY_RSA_PEM tests/data_files/cli-rsa.key */ +#define TEST_CLI_KEY_RSA_PEM \ + "-----BEGIN RSA PRIVATE KEY-----\r\n" \ + "MIIEpAIBAAKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6fM60Nj4o8VmXl3ETZzGaF\r\n" \ + "B9X4J7BKNdBjngpuG7fa8H6r7gwQk4ZJGDTzqCrSV/Uu1C93KYRhTYJQj6eVSHD1\r\n" \ + "bk2y1RPD0hrt5kPqQhTrdOrA7R/UV06p86jt0uDBMHEwMjDV0/YI0FZPRo7yX/k9\r\n" \ + "Z5GIMC5Cst99++UMd//sMcB4j7/Cf8qtbCHWjdmLao5v4Jv4EFbMs44TFeY0BGbH\r\n" \ + "7vk2DmqV9gmaBmf0ZXH4yqSxJeD+PIs1BGe64E92hfx//DZrtenNLQNiTrM9AM+v\r\n" \ + "dqBpVoNq0qjU51Bx5rU2BXcFbXvI5MT9TNUhXwIDAQABAoIBAGdNtfYDiap6bzst\r\n" \ + "yhCiI8m9TtrhZw4MisaEaN/ll3XSjaOG2dvV6xMZCMV+5TeXDHOAZnY18Yi18vzz\r\n" \ + "4Ut2TnNFzizCECYNaA2fST3WgInnxUkV3YXAyP6CNxJaCmv2aA0yFr2kFVSeaKGt\r\n" \ + "ymvljNp2NVkvm7Th8fBQBO7I7AXhz43k0mR7XmPgewe8ApZOG3hstkOaMvbWAvWA\r\n" \ + "zCZupdDjZYjOJqlA4eEA4H8/w7F83r5CugeBE8LgEREjLPiyejrU5H1fubEY+h0d\r\n" \ + "l5HZBJ68ybTXfQ5U9o/QKA3dd0toBEhhdRUDGzWtjvwkEQfqF1reGWj/tod/gCpf\r\n" \ + "DFi6X0ECgYEA4wOv/pjSC3ty6TuOvKX2rOUiBrLXXv2JSxZnMoMiWI5ipLQt+RYT\r\n" \ + "VPafL/m7Dn6MbwjayOkcZhBwk5CNz5A6Q4lJ64Mq/lqHznRCQQ2Mc1G8eyDF/fYL\r\n" \ + "Ze2pLvwP9VD5jTc2miDfw+MnvJhywRRLcemDFP8k4hQVtm8PMp3ZmNECgYEA4gz7\r\n" \ + "wzObR4gn8ibe617uQPZjWzUj9dUHYd+in1gwBCIrtNnaRn9I9U/Q6tegRYpii4ys\r\n" \ + "c176NmU+umy6XmuSKV5qD9bSpZWG2nLFnslrN15Lm3fhZxoeMNhBaEDTnLT26yoi\r\n" \ + "33gp0mSSWy94ZEqipms+ULF6sY1ZtFW6tpGFoy8CgYAQHhnnvJflIs2ky4q10B60\r\n" \ + "ZcxFp3rtDpkp0JxhFLhiizFrujMtZSjYNm5U7KkgPVHhLELEUvCmOnKTt4ap/vZ0\r\n" \ + "BxJNe1GZH3pW6SAvGDQpl9sG7uu/vTFP+lCxukmzxB0DrrDcvorEkKMom7ZCCRvW\r\n" \ + "KZsZ6YeH2Z81BauRj218kQKBgQCUV/DgKP2985xDTT79N08jUo3hTP5MVYCCuj/+\r\n" \ + "UeEw1TvZcx3LJby7P6Xad6a1/BqveaGyFKIfEFIaBUBItk801sDDpDaYc4gL00Xc\r\n" \ + "7lFuBHOZkxJYlss5QrGpuOEl9ZwUt5IrFLBdYaKqNHzNVC1pCPfb/JyH6Dr2HUxq\r\n" \ + "gxUwAQKBgQCcU6G2L8AG9d9c0UpOyL1tMvFe5Ttw0KjlQVdsh1MP6yigYo9DYuwu\r\n" \ + "bHFVW2r0dBTqegP2/KTOxKzaHfC1qf0RGDsUoJCNJrd1cwoCLG8P2EF4w3OBrKqv\r\n" \ + "8u4ytY0F+Vlanj5lm3TaoHSVF1+NWPyOTiwevIECGKwSxvlki4fDAA==\r\n" \ + "-----END RSA PRIVATE KEY-----\r\n"/* END FILE */ + +/* This was generated from tests/data_files/cli-rsa.key.der using `xxd -i`. */ +/* BEGIN FILE binary macro TEST_CLI_KEY_RSA_DER tests/data_files/cli-rsa.key.der */ +#define TEST_CLI_KEY_RSA_DER { \ + 0x30, 0x82, 0x04, 0xa4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, \ + 0xc8, 0x74, 0xc4, 0xcc, 0xb9, 0xf9, 0xb5, 0x79, 0xe9, 0x45, 0xd9, 0x14, \ + 0x60, 0xb0, 0x7d, 0xbb, 0x93, 0xf2, 0x6b, 0x1e, 0x9f, 0x33, 0xad, 0x0d, \ + 0x8f, 0x8a, 0x3c, 0x56, 0x65, 0xe5, 0xdc, 0x44, 0xd9, 0xcc, 0x66, 0x85, \ + 0x07, 0xd5, 0xf8, 0x27, 0xb0, 0x4a, 0x35, 0xd0, 0x63, 0x9e, 0x0a, 0x6e, \ + 0x1b, 0xb7, 0xda, 0xf0, 0x7e, 0xab, 0xee, 0x0c, 0x10, 0x93, 0x86, 0x49, \ + 0x18, 0x34, 0xf3, 0xa8, 0x2a, 0xd2, 0x57, 0xf5, 0x2e, 0xd4, 0x2f, 0x77, \ + 0x29, 0x84, 0x61, 0x4d, 0x82, 0x50, 0x8f, 0xa7, 0x95, 0x48, 0x70, 0xf5, \ + 0x6e, 0x4d, 0xb2, 0xd5, 0x13, 0xc3, 0xd2, 0x1a, 0xed, 0xe6, 0x43, 0xea, \ + 0x42, 0x14, 0xeb, 0x74, 0xea, 0xc0, 0xed, 0x1f, 0xd4, 0x57, 0x4e, 0xa9, \ + 0xf3, 0xa8, 0xed, 0xd2, 0xe0, 0xc1, 0x30, 0x71, 0x30, 0x32, 0x30, 0xd5, \ + 0xd3, 0xf6, 0x08, 0xd0, 0x56, 0x4f, 0x46, 0x8e, 0xf2, 0x5f, 0xf9, 0x3d, \ + 0x67, 0x91, 0x88, 0x30, 0x2e, 0x42, 0xb2, 0xdf, 0x7d, 0xfb, 0xe5, 0x0c, \ + 0x77, 0xff, 0xec, 0x31, 0xc0, 0x78, 0x8f, 0xbf, 0xc2, 0x7f, 0xca, 0xad, \ + 0x6c, 0x21, 0xd6, 0x8d, 0xd9, 0x8b, 0x6a, 0x8e, 0x6f, 0xe0, 0x9b, 0xf8, \ + 0x10, 0x56, 0xcc, 0xb3, 0x8e, 0x13, 0x15, 0xe6, 0x34, 0x04, 0x66, 0xc7, \ + 0xee, 0xf9, 0x36, 0x0e, 0x6a, 0x95, 0xf6, 0x09, 0x9a, 0x06, 0x67, 0xf4, \ + 0x65, 0x71, 0xf8, 0xca, 0xa4, 0xb1, 0x25, 0xe0, 0xfe, 0x3c, 0x8b, 0x35, \ + 0x04, 0x67, 0xba, 0xe0, 0x4f, 0x76, 0x85, 0xfc, 0x7f, 0xfc, 0x36, 0x6b, \ + 0xb5, 0xe9, 0xcd, 0x2d, 0x03, 0x62, 0x4e, 0xb3, 0x3d, 0x00, 0xcf, 0xaf, \ + 0x76, 0xa0, 0x69, 0x56, 0x83, 0x6a, 0xd2, 0xa8, 0xd4, 0xe7, 0x50, 0x71, \ + 0xe6, 0xb5, 0x36, 0x05, 0x77, 0x05, 0x6d, 0x7b, 0xc8, 0xe4, 0xc4, 0xfd, \ + 0x4c, 0xd5, 0x21, 0x5f, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, \ + 0x00, 0x67, 0x4d, 0xb5, 0xf6, 0x03, 0x89, 0xaa, 0x7a, 0x6f, 0x3b, 0x2d, \ + 0xca, 0x10, 0xa2, 0x23, 0xc9, 0xbd, 0x4e, 0xda, 0xe1, 0x67, 0x0e, 0x0c, \ + 0x8a, 0xc6, 0x84, 0x68, 0xdf, 0xe5, 0x97, 0x75, 0xd2, 0x8d, 0xa3, 0x86, \ + 0xd9, 0xdb, 0xd5, 0xeb, 0x13, 0x19, 0x08, 0xc5, 0x7e, 0xe5, 0x37, 0x97, \ + 0x0c, 0x73, 0x80, 0x66, 0x76, 0x35, 0xf1, 0x88, 0xb5, 0xf2, 0xfc, 0xf3, \ + 0xe1, 0x4b, 0x76, 0x4e, 0x73, 0x45, 0xce, 0x2c, 0xc2, 0x10, 0x26, 0x0d, \ + 0x68, 0x0d, 0x9f, 0x49, 0x3d, 0xd6, 0x80, 0x89, 0xe7, 0xc5, 0x49, 0x15, \ + 0xdd, 0x85, 0xc0, 0xc8, 0xfe, 0x82, 0x37, 0x12, 0x5a, 0x0a, 0x6b, 0xf6, \ + 0x68, 0x0d, 0x32, 0x16, 0xbd, 0xa4, 0x15, 0x54, 0x9e, 0x68, 0xa1, 0xad, \ + 0xca, 0x6b, 0xe5, 0x8c, 0xda, 0x76, 0x35, 0x59, 0x2f, 0x9b, 0xb4, 0xe1, \ + 0xf1, 0xf0, 0x50, 0x04, 0xee, 0xc8, 0xec, 0x05, 0xe1, 0xcf, 0x8d, 0xe4, \ + 0xd2, 0x64, 0x7b, 0x5e, 0x63, 0xe0, 0x7b, 0x07, 0xbc, 0x02, 0x96, 0x4e, \ + 0x1b, 0x78, 0x6c, 0xb6, 0x43, 0x9a, 0x32, 0xf6, 0xd6, 0x02, 0xf5, 0x80, \ + 0xcc, 0x26, 0x6e, 0xa5, 0xd0, 0xe3, 0x65, 0x88, 0xce, 0x26, 0xa9, 0x40, \ + 0xe1, 0xe1, 0x00, 0xe0, 0x7f, 0x3f, 0xc3, 0xb1, 0x7c, 0xde, 0xbe, 0x42, \ + 0xba, 0x07, 0x81, 0x13, 0xc2, 0xe0, 0x11, 0x11, 0x23, 0x2c, 0xf8, 0xb2, \ + 0x7a, 0x3a, 0xd4, 0xe4, 0x7d, 0x5f, 0xb9, 0xb1, 0x18, 0xfa, 0x1d, 0x1d, \ + 0x97, 0x91, 0xd9, 0x04, 0x9e, 0xbc, 0xc9, 0xb4, 0xd7, 0x7d, 0x0e, 0x54, \ + 0xf6, 0x8f, 0xd0, 0x28, 0x0d, 0xdd, 0x77, 0x4b, 0x68, 0x04, 0x48, 0x61, \ + 0x75, 0x15, 0x03, 0x1b, 0x35, 0xad, 0x8e, 0xfc, 0x24, 0x11, 0x07, 0xea, \ + 0x17, 0x5a, 0xde, 0x19, 0x68, 0xff, 0xb6, 0x87, 0x7f, 0x80, 0x2a, 0x5f, \ + 0x0c, 0x58, 0xba, 0x5f, 0x41, 0x02, 0x81, 0x81, 0x00, 0xe3, 0x03, 0xaf, \ + 0xfe, 0x98, 0xd2, 0x0b, 0x7b, 0x72, 0xe9, 0x3b, 0x8e, 0xbc, 0xa5, 0xf6, \ + 0xac, 0xe5, 0x22, 0x06, 0xb2, 0xd7, 0x5e, 0xfd, 0x89, 0x4b, 0x16, 0x67, \ + 0x32, 0x83, 0x22, 0x58, 0x8e, 0x62, 0xa4, 0xb4, 0x2d, 0xf9, 0x16, 0x13, \ + 0x54, 0xf6, 0x9f, 0x2f, 0xf9, 0xbb, 0x0e, 0x7e, 0x8c, 0x6f, 0x08, 0xda, \ + 0xc8, 0xe9, 0x1c, 0x66, 0x10, 0x70, 0x93, 0x90, 0x8d, 0xcf, 0x90, 0x3a, \ + 0x43, 0x89, 0x49, 0xeb, 0x83, 0x2a, 0xfe, 0x5a, 0x87, 0xce, 0x74, 0x42, \ + 0x41, 0x0d, 0x8c, 0x73, 0x51, 0xbc, 0x7b, 0x20, 0xc5, 0xfd, 0xf6, 0x0b, \ + 0x65, 0xed, 0xa9, 0x2e, 0xfc, 0x0f, 0xf5, 0x50, 0xf9, 0x8d, 0x37, 0x36, \ + 0x9a, 0x20, 0xdf, 0xc3, 0xe3, 0x27, 0xbc, 0x98, 0x72, 0xc1, 0x14, 0x4b, \ + 0x71, 0xe9, 0x83, 0x14, 0xff, 0x24, 0xe2, 0x14, 0x15, 0xb6, 0x6f, 0x0f, \ + 0x32, 0x9d, 0xd9, 0x98, 0xd1, 0x02, 0x81, 0x81, 0x00, 0xe2, 0x0c, 0xfb, \ + 0xc3, 0x33, 0x9b, 0x47, 0x88, 0x27, 0xf2, 0x26, 0xde, 0xeb, 0x5e, 0xee, \ + 0x40, 0xf6, 0x63, 0x5b, 0x35, 0x23, 0xf5, 0xd5, 0x07, 0x61, 0xdf, 0xa2, \ + 0x9f, 0x58, 0x30, 0x04, 0x22, 0x2b, 0xb4, 0xd9, 0xda, 0x46, 0x7f, 0x48, \ + 0xf5, 0x4f, 0xd0, 0xea, 0xd7, 0xa0, 0x45, 0x8a, 0x62, 0x8b, 0x8c, 0xac, \ + 0x73, 0x5e, 0xfa, 0x36, 0x65, 0x3e, 0xba, 0x6c, 0xba, 0x5e, 0x6b, 0x92, \ + 0x29, 0x5e, 0x6a, 0x0f, 0xd6, 0xd2, 0xa5, 0x95, 0x86, 0xda, 0x72, 0xc5, \ + 0x9e, 0xc9, 0x6b, 0x37, 0x5e, 0x4b, 0x9b, 0x77, 0xe1, 0x67, 0x1a, 0x1e, \ + 0x30, 0xd8, 0x41, 0x68, 0x40, 0xd3, 0x9c, 0xb4, 0xf6, 0xeb, 0x2a, 0x22, \ + 0xdf, 0x78, 0x29, 0xd2, 0x64, 0x92, 0x5b, 0x2f, 0x78, 0x64, 0x4a, 0xa2, \ + 0xa6, 0x6b, 0x3e, 0x50, 0xb1, 0x7a, 0xb1, 0x8d, 0x59, 0xb4, 0x55, 0xba, \ + 0xb6, 0x91, 0x85, 0xa3, 0x2f, 0x02, 0x81, 0x80, 0x10, 0x1e, 0x19, 0xe7, \ + 0xbc, 0x97, 0xe5, 0x22, 0xcd, 0xa4, 0xcb, 0x8a, 0xb5, 0xd0, 0x1e, 0xb4, \ + 0x65, 0xcc, 0x45, 0xa7, 0x7a, 0xed, 0x0e, 0x99, 0x29, 0xd0, 0x9c, 0x61, \ + 0x14, 0xb8, 0x62, 0x8b, 0x31, 0x6b, 0xba, 0x33, 0x2d, 0x65, 0x28, 0xd8, \ + 0x36, 0x6e, 0x54, 0xec, 0xa9, 0x20, 0x3d, 0x51, 0xe1, 0x2c, 0x42, 0xc4, \ + 0x52, 0xf0, 0xa6, 0x3a, 0x72, 0x93, 0xb7, 0x86, 0xa9, 0xfe, 0xf6, 0x74, \ + 0x07, 0x12, 0x4d, 0x7b, 0x51, 0x99, 0x1f, 0x7a, 0x56, 0xe9, 0x20, 0x2f, \ + 0x18, 0x34, 0x29, 0x97, 0xdb, 0x06, 0xee, 0xeb, 0xbf, 0xbd, 0x31, 0x4f, \ + 0xfa, 0x50, 0xb1, 0xba, 0x49, 0xb3, 0xc4, 0x1d, 0x03, 0xae, 0xb0, 0xdc, \ + 0xbe, 0x8a, 0xc4, 0x90, 0xa3, 0x28, 0x9b, 0xb6, 0x42, 0x09, 0x1b, 0xd6, \ + 0x29, 0x9b, 0x19, 0xe9, 0x87, 0x87, 0xd9, 0x9f, 0x35, 0x05, 0xab, 0x91, \ + 0x8f, 0x6d, 0x7c, 0x91, 0x02, 0x81, 0x81, 0x00, 0x94, 0x57, 0xf0, 0xe0, \ + 0x28, 0xfd, 0xbd, 0xf3, 0x9c, 0x43, 0x4d, 0x3e, 0xfd, 0x37, 0x4f, 0x23, \ + 0x52, 0x8d, 0xe1, 0x4c, 0xfe, 0x4c, 0x55, 0x80, 0x82, 0xba, 0x3f, 0xfe, \ + 0x51, 0xe1, 0x30, 0xd5, 0x3b, 0xd9, 0x73, 0x1d, 0xcb, 0x25, 0xbc, 0xbb, \ + 0x3f, 0xa5, 0xda, 0x77, 0xa6, 0xb5, 0xfc, 0x1a, 0xaf, 0x79, 0xa1, 0xb2, \ + 0x14, 0xa2, 0x1f, 0x10, 0x52, 0x1a, 0x05, 0x40, 0x48, 0xb6, 0x4f, 0x34, \ + 0xd6, 0xc0, 0xc3, 0xa4, 0x36, 0x98, 0x73, 0x88, 0x0b, 0xd3, 0x45, 0xdc, \ + 0xee, 0x51, 0x6e, 0x04, 0x73, 0x99, 0x93, 0x12, 0x58, 0x96, 0xcb, 0x39, \ + 0x42, 0xb1, 0xa9, 0xb8, 0xe1, 0x25, 0xf5, 0x9c, 0x14, 0xb7, 0x92, 0x2b, \ + 0x14, 0xb0, 0x5d, 0x61, 0xa2, 0xaa, 0x34, 0x7c, 0xcd, 0x54, 0x2d, 0x69, \ + 0x08, 0xf7, 0xdb, 0xfc, 0x9c, 0x87, 0xe8, 0x3a, 0xf6, 0x1d, 0x4c, 0x6a, \ + 0x83, 0x15, 0x30, 0x01, 0x02, 0x81, 0x81, 0x00, 0x9c, 0x53, 0xa1, 0xb6, \ + 0x2f, 0xc0, 0x06, 0xf5, 0xdf, 0x5c, 0xd1, 0x4a, 0x4e, 0xc8, 0xbd, 0x6d, \ + 0x32, 0xf1, 0x5e, 0xe5, 0x3b, 0x70, 0xd0, 0xa8, 0xe5, 0x41, 0x57, 0x6c, \ + 0x87, 0x53, 0x0f, 0xeb, 0x28, 0xa0, 0x62, 0x8f, 0x43, 0x62, 0xec, 0x2e, \ + 0x6c, 0x71, 0x55, 0x5b, 0x6a, 0xf4, 0x74, 0x14, 0xea, 0x7a, 0x03, 0xf6, \ + 0xfc, 0xa4, 0xce, 0xc4, 0xac, 0xda, 0x1d, 0xf0, 0xb5, 0xa9, 0xfd, 0x11, \ + 0x18, 0x3b, 0x14, 0xa0, 0x90, 0x8d, 0x26, 0xb7, 0x75, 0x73, 0x0a, 0x02, \ + 0x2c, 0x6f, 0x0f, 0xd8, 0x41, 0x78, 0xc3, 0x73, 0x81, 0xac, 0xaa, 0xaf, \ + 0xf2, 0xee, 0x32, 0xb5, 0x8d, 0x05, 0xf9, 0x59, 0x5a, 0x9e, 0x3e, 0x65, \ + 0x9b, 0x74, 0xda, 0xa0, 0x74, 0x95, 0x17, 0x5f, 0x8d, 0x58, 0xfc, 0x8e, \ + 0x4e, 0x2c, 0x1e, 0xbc, 0x81, 0x02, 0x18, 0xac, 0x12, 0xc6, 0xf9, 0x64, \ + 0x8b, 0x87, 0xc3, 0x00 \ +} +/* END FILE */ + +/* + * + * Test certificates and keys as C variables + * + */ + +/* + * CA + */ + +const char mbedtls_test_ca_crt_ec_pem[] = TEST_CA_CRT_EC_PEM; +const char mbedtls_test_ca_key_ec_pem[] = TEST_CA_KEY_EC_PEM; +const char mbedtls_test_ca_pwd_ec_pem[] = TEST_CA_PWD_EC_PEM; +const char mbedtls_test_ca_key_rsa_pem[] = TEST_CA_KEY_RSA_PEM; +const char mbedtls_test_ca_pwd_rsa_pem[] = TEST_CA_PWD_RSA_PEM; +const char mbedtls_test_ca_crt_rsa_sha1_pem[] = TEST_CA_CRT_RSA_SHA1_PEM; +const char mbedtls_test_ca_crt_rsa_sha256_pem[] = TEST_CA_CRT_RSA_SHA256_PEM; + +const unsigned char mbedtls_test_ca_crt_ec_der[] = TEST_CA_CRT_EC_DER; +const unsigned char mbedtls_test_ca_key_ec_der[] = TEST_CA_KEY_EC_DER; +const unsigned char mbedtls_test_ca_key_rsa_der[] = TEST_CA_KEY_RSA_DER; +const unsigned char mbedtls_test_ca_crt_rsa_sha1_der[] = + TEST_CA_CRT_RSA_SHA1_DER; +const unsigned char mbedtls_test_ca_crt_rsa_sha256_der[] = + TEST_CA_CRT_RSA_SHA256_DER; + +const size_t mbedtls_test_ca_crt_ec_pem_len = + sizeof( mbedtls_test_ca_crt_ec_pem ); +const size_t mbedtls_test_ca_key_ec_pem_len = + sizeof( mbedtls_test_ca_key_ec_pem ); +const size_t mbedtls_test_ca_pwd_ec_pem_len = + sizeof( mbedtls_test_ca_pwd_ec_pem ) - 1; +const size_t mbedtls_test_ca_key_rsa_pem_len = + sizeof( mbedtls_test_ca_key_rsa_pem ); +const size_t mbedtls_test_ca_pwd_rsa_pem_len = + sizeof( mbedtls_test_ca_pwd_rsa_pem ) - 1; +const size_t mbedtls_test_ca_crt_rsa_sha1_pem_len = + sizeof( mbedtls_test_ca_crt_rsa_sha1_pem ); +const size_t mbedtls_test_ca_crt_rsa_sha256_pem_len = + sizeof( mbedtls_test_ca_crt_rsa_sha256_pem ); + +const size_t mbedtls_test_ca_crt_ec_der_len = + sizeof( mbedtls_test_ca_crt_ec_der ); +const size_t mbedtls_test_ca_key_ec_der_len = + sizeof( mbedtls_test_ca_key_ec_der ); +const size_t mbedtls_test_ca_pwd_ec_der_len = 0; +const size_t mbedtls_test_ca_key_rsa_der_len = + sizeof( mbedtls_test_ca_key_rsa_der ); +const size_t mbedtls_test_ca_pwd_rsa_der_len = 0; +const size_t mbedtls_test_ca_crt_rsa_sha1_der_len = + sizeof( mbedtls_test_ca_crt_rsa_sha1_der ); +const size_t mbedtls_test_ca_crt_rsa_sha256_der_len = + sizeof( mbedtls_test_ca_crt_rsa_sha256_der ); + +/* + * Server + */ + +const char mbedtls_test_srv_crt_ec_pem[] = TEST_SRV_CRT_EC_PEM; +const char mbedtls_test_srv_key_ec_pem[] = TEST_SRV_KEY_EC_PEM; +const char mbedtls_test_srv_pwd_ec_pem[] = ""; +const char mbedtls_test_srv_key_rsa_pem[] = TEST_SRV_KEY_RSA_PEM; +const char mbedtls_test_srv_pwd_rsa_pem[] = ""; +const char mbedtls_test_srv_crt_rsa_sha1_pem[] = TEST_SRV_CRT_RSA_SHA1_PEM; +const char mbedtls_test_srv_crt_rsa_sha256_pem[] = TEST_SRV_CRT_RSA_SHA256_PEM; + +const unsigned char mbedtls_test_srv_crt_ec_der[] = TEST_SRV_CRT_EC_DER; +const unsigned char mbedtls_test_srv_key_ec_der[] = TEST_SRV_KEY_EC_DER; +const unsigned char mbedtls_test_srv_key_rsa_der[] = TEST_SRV_KEY_RSA_DER; +const unsigned char mbedtls_test_srv_crt_rsa_sha1_der[] = + TEST_SRV_CRT_RSA_SHA1_DER; +const unsigned char mbedtls_test_srv_crt_rsa_sha256_der[] = + TEST_SRV_CRT_RSA_SHA256_DER; + +const size_t mbedtls_test_srv_crt_ec_pem_len = + sizeof( mbedtls_test_srv_crt_ec_pem ); +const size_t mbedtls_test_srv_key_ec_pem_len = + sizeof( mbedtls_test_srv_key_ec_pem ); +const size_t mbedtls_test_srv_pwd_ec_pem_len = + sizeof( mbedtls_test_srv_pwd_ec_pem ) - 1; +const size_t mbedtls_test_srv_key_rsa_pem_len = + sizeof( mbedtls_test_srv_key_rsa_pem ); +const size_t mbedtls_test_srv_pwd_rsa_pem_len = + sizeof( mbedtls_test_srv_pwd_rsa_pem ) - 1; +const size_t mbedtls_test_srv_crt_rsa_sha1_pem_len = + sizeof( mbedtls_test_srv_crt_rsa_sha1_pem ); +const size_t mbedtls_test_srv_crt_rsa_sha256_pem_len = + sizeof( mbedtls_test_srv_crt_rsa_sha256_pem ); + +const size_t mbedtls_test_srv_crt_ec_der_len = + sizeof( mbedtls_test_srv_crt_ec_der ); +const size_t mbedtls_test_srv_key_ec_der_len = + sizeof( mbedtls_test_srv_key_ec_der ); +const size_t mbedtls_test_srv_pwd_ec_der_len = 0; +const size_t mbedtls_test_srv_key_rsa_der_len = + sizeof( mbedtls_test_srv_key_rsa_der ); +const size_t mbedtls_test_srv_pwd_rsa_der_len = 0; +const size_t mbedtls_test_srv_crt_rsa_sha1_der_len = + sizeof( mbedtls_test_srv_crt_rsa_sha1_der ); +const size_t mbedtls_test_srv_crt_rsa_sha256_der_len = + sizeof( mbedtls_test_srv_crt_rsa_sha256_der ); + +/* + * Client + */ + +const char mbedtls_test_cli_crt_ec_pem[] = TEST_CLI_CRT_EC_PEM; +const char mbedtls_test_cli_key_ec_pem[] = TEST_CLI_KEY_EC_PEM; +const char mbedtls_test_cli_pwd_ec_pem[] = ""; +const char mbedtls_test_cli_key_rsa_pem[] = TEST_CLI_KEY_RSA_PEM; +const char mbedtls_test_cli_pwd_rsa_pem[] = ""; +const char mbedtls_test_cli_crt_rsa_pem[] = TEST_CLI_CRT_RSA_PEM; + +const unsigned char mbedtls_test_cli_crt_ec_der[] = TEST_CLI_CRT_EC_DER; +const unsigned char mbedtls_test_cli_key_ec_der[] = TEST_CLI_KEY_EC_DER; +const unsigned char mbedtls_test_cli_key_rsa_der[] = TEST_CLI_KEY_RSA_DER; +const unsigned char mbedtls_test_cli_crt_rsa_der[] = TEST_CLI_CRT_RSA_DER; + +const size_t mbedtls_test_cli_crt_ec_pem_len = + sizeof( mbedtls_test_cli_crt_ec_pem ); +const size_t mbedtls_test_cli_key_ec_pem_len = + sizeof( mbedtls_test_cli_key_ec_pem ); +const size_t mbedtls_test_cli_pwd_ec_pem_len = + sizeof( mbedtls_test_cli_pwd_ec_pem ) - 1; +const size_t mbedtls_test_cli_key_rsa_pem_len = + sizeof( mbedtls_test_cli_key_rsa_pem ); +const size_t mbedtls_test_cli_pwd_rsa_pem_len = + sizeof( mbedtls_test_cli_pwd_rsa_pem ) - 1; +const size_t mbedtls_test_cli_crt_rsa_pem_len = + sizeof( mbedtls_test_cli_crt_rsa_pem ); + +const size_t mbedtls_test_cli_crt_ec_der_len = + sizeof( mbedtls_test_cli_crt_ec_der ); +const size_t mbedtls_test_cli_key_ec_der_len = + sizeof( mbedtls_test_cli_key_ec_der ); +const size_t mbedtls_test_cli_key_rsa_der_len = + sizeof( mbedtls_test_cli_key_rsa_der ); +const size_t mbedtls_test_cli_crt_rsa_der_len = + sizeof( mbedtls_test_cli_crt_rsa_der ); + +/* + * + * Definitions of test CRTs without specification of all parameters, choosing + * them automatically according to the config. For example, mbedtls_test_ca_crt + * is one of mbedtls_test_ca_crt_{rsa|ec}_{sha1|sha256}_{pem|der}. + * + */ + +/* + * Dispatch between PEM and DER according to config + */ + +#if defined(MBEDTLS_PEM_PARSE_C) + +/* PEM encoded test CA certificates and keys */ + +#define TEST_CA_KEY_RSA TEST_CA_KEY_RSA_PEM +#define TEST_CA_PWD_RSA TEST_CA_PWD_RSA_PEM +#define TEST_CA_CRT_RSA_SHA256 TEST_CA_CRT_RSA_SHA256_PEM +#define TEST_CA_CRT_RSA_SHA1 TEST_CA_CRT_RSA_SHA1_PEM +#define TEST_CA_KEY_EC TEST_CA_KEY_EC_PEM +#define TEST_CA_PWD_EC TEST_CA_PWD_EC_PEM +#define TEST_CA_CRT_EC TEST_CA_CRT_EC_PEM + +/* PEM encoded test server certificates and keys */ + +#define TEST_SRV_KEY_RSA TEST_SRV_KEY_RSA_PEM +#define TEST_SRV_PWD_RSA "" +#define TEST_SRV_CRT_RSA_SHA256 TEST_SRV_CRT_RSA_SHA256_PEM +#define TEST_SRV_CRT_RSA_SHA1 TEST_SRV_CRT_RSA_SHA1_PEM +#define TEST_SRV_KEY_EC TEST_SRV_KEY_EC_PEM +#define TEST_SRV_PWD_EC "" +#define TEST_SRV_CRT_EC TEST_SRV_CRT_EC_PEM + +/* PEM encoded test client certificates and keys */ + +#define TEST_CLI_KEY_RSA TEST_CLI_KEY_RSA_PEM +#define TEST_CLI_PWD_RSA "" +#define TEST_CLI_CRT_RSA TEST_CLI_CRT_RSA_PEM +#define TEST_CLI_KEY_EC TEST_CLI_KEY_EC_PEM +#define TEST_CLI_PWD_EC "" +#define TEST_CLI_CRT_EC TEST_CLI_CRT_EC_PEM + +#else /* MBEDTLS_PEM_PARSE_C */ + +/* DER encoded test CA certificates and keys */ + +#define TEST_CA_KEY_RSA TEST_CA_KEY_RSA_DER +#define TEST_CA_PWD_RSA "" +#define TEST_CA_CRT_RSA_SHA256 TEST_CA_CRT_RSA_SHA256_DER +#define TEST_CA_CRT_RSA_SHA1 TEST_CA_CRT_RSA_SHA1_DER +#define TEST_CA_KEY_EC TEST_CA_KEY_EC_DER +#define TEST_CA_PWD_EC "" +#define TEST_CA_CRT_EC TEST_CA_CRT_EC_DER + +/* DER encoded test server certificates and keys */ + +#define TEST_SRV_KEY_RSA TEST_SRV_KEY_RSA_DER +#define TEST_SRV_PWD_RSA "" +#define TEST_SRV_CRT_RSA_SHA256 TEST_SRV_CRT_RSA_SHA256_DER +#define TEST_SRV_CRT_RSA_SHA1 TEST_SRV_CRT_RSA_SHA1_DER +#define TEST_SRV_KEY_EC TEST_SRV_KEY_EC_DER +#define TEST_SRV_PWD_EC "" +#define TEST_SRV_CRT_EC TEST_SRV_CRT_EC_DER + +/* DER encoded test client certificates and keys */ + +#define TEST_CLI_KEY_RSA TEST_CLI_KEY_RSA_DER +#define TEST_CLI_PWD_RSA "" +#define TEST_CLI_CRT_RSA TEST_CLI_CRT_RSA_DER +#define TEST_CLI_KEY_EC TEST_CLI_KEY_EC_DER +#define TEST_CLI_PWD_EC "" +#define TEST_CLI_CRT_EC TEST_CLI_CRT_EC_DER + +#endif /* MBEDTLS_PEM_PARSE_C */ + +const char mbedtls_test_ca_key_rsa[] = TEST_CA_KEY_RSA; +const char mbedtls_test_ca_pwd_rsa[] = TEST_CA_PWD_RSA; +const char mbedtls_test_ca_crt_rsa_sha256[] = TEST_CA_CRT_RSA_SHA256; +const char mbedtls_test_ca_crt_rsa_sha1[] = TEST_CA_CRT_RSA_SHA1; +const char mbedtls_test_ca_key_ec[] = TEST_CA_KEY_EC; +const char mbedtls_test_ca_pwd_ec[] = TEST_CA_PWD_EC; +const char mbedtls_test_ca_crt_ec[] = TEST_CA_CRT_EC; + +const char mbedtls_test_srv_key_rsa[] = TEST_SRV_KEY_RSA; +const char mbedtls_test_srv_pwd_rsa[] = TEST_SRV_PWD_RSA; +const char mbedtls_test_srv_crt_rsa_sha256[] = TEST_SRV_CRT_RSA_SHA256; +const char mbedtls_test_srv_crt_rsa_sha1[] = TEST_SRV_CRT_RSA_SHA1; +const char mbedtls_test_srv_key_ec[] = TEST_SRV_KEY_EC; +const char mbedtls_test_srv_pwd_ec[] = TEST_SRV_PWD_EC; +const char mbedtls_test_srv_crt_ec[] = TEST_SRV_CRT_EC; + +const char mbedtls_test_cli_key_rsa[] = TEST_CLI_KEY_RSA; +const char mbedtls_test_cli_pwd_rsa[] = TEST_CLI_PWD_RSA; +const char mbedtls_test_cli_crt_rsa[] = TEST_CLI_CRT_RSA; +const char mbedtls_test_cli_key_ec[] = TEST_CLI_KEY_EC; +const char mbedtls_test_cli_pwd_ec[] = TEST_CLI_PWD_EC; +const char mbedtls_test_cli_crt_ec[] = TEST_CLI_CRT_EC; + +const size_t mbedtls_test_ca_key_rsa_len = + sizeof( mbedtls_test_ca_key_rsa ); +const size_t mbedtls_test_ca_pwd_rsa_len = + sizeof( mbedtls_test_ca_pwd_rsa ) - 1; +const size_t mbedtls_test_ca_crt_rsa_sha256_len = + sizeof( mbedtls_test_ca_crt_rsa_sha256 ); +const size_t mbedtls_test_ca_crt_rsa_sha1_len = + sizeof( mbedtls_test_ca_crt_rsa_sha1 ); +const size_t mbedtls_test_ca_key_ec_len = + sizeof( mbedtls_test_ca_key_ec ); +const size_t mbedtls_test_ca_pwd_ec_len = + sizeof( mbedtls_test_ca_pwd_ec ) - 1; +const size_t mbedtls_test_ca_crt_ec_len = + sizeof( mbedtls_test_ca_crt_ec ); + +const size_t mbedtls_test_srv_key_rsa_len = + sizeof( mbedtls_test_srv_key_rsa ); +const size_t mbedtls_test_srv_pwd_rsa_len = + sizeof( mbedtls_test_srv_pwd_rsa ) -1; +const size_t mbedtls_test_srv_crt_rsa_sha256_len = + sizeof( mbedtls_test_srv_crt_rsa_sha256 ); +const size_t mbedtls_test_srv_crt_rsa_sha1_len = + sizeof( mbedtls_test_srv_crt_rsa_sha1 ); +const size_t mbedtls_test_srv_key_ec_len = + sizeof( mbedtls_test_srv_key_ec ); +const size_t mbedtls_test_srv_pwd_ec_len = + sizeof( mbedtls_test_srv_pwd_ec ) - 1; +const size_t mbedtls_test_srv_crt_ec_len = + sizeof( mbedtls_test_srv_crt_ec ); + +const size_t mbedtls_test_cli_key_rsa_len = + sizeof( mbedtls_test_cli_key_rsa ); +const size_t mbedtls_test_cli_pwd_rsa_len = + sizeof( mbedtls_test_cli_pwd_rsa ) - 1; +const size_t mbedtls_test_cli_crt_rsa_len = + sizeof( mbedtls_test_cli_crt_rsa ); +const size_t mbedtls_test_cli_key_ec_len = + sizeof( mbedtls_test_cli_key_ec ); +const size_t mbedtls_test_cli_pwd_ec_len = + sizeof( mbedtls_test_cli_pwd_ec ) - 1; +const size_t mbedtls_test_cli_crt_ec_len = + sizeof( mbedtls_test_cli_crt_ec ); + +/* + * Dispatch between SHA-1 and SHA-256 + */ + +#if defined(MBEDTLS_SHA256_C) +#define TEST_CA_CRT_RSA TEST_CA_CRT_RSA_SHA256 +#define TEST_SRV_CRT_RSA TEST_SRV_CRT_RSA_SHA256 +#else +#define TEST_CA_CRT_RSA TEST_CA_CRT_RSA_SHA1 +#define TEST_SRV_CRT_RSA TEST_SRV_CRT_RSA_SHA1 +#endif /* MBEDTLS_SHA256_C */ + +const char mbedtls_test_ca_crt_rsa[] = TEST_CA_CRT_RSA; +const char mbedtls_test_srv_crt_rsa[] = TEST_SRV_CRT_RSA; + +const size_t mbedtls_test_ca_crt_rsa_len = + sizeof( mbedtls_test_ca_crt_rsa ); +const size_t mbedtls_test_srv_crt_rsa_len = + sizeof( mbedtls_test_srv_crt_rsa ); + +/* + * Dispatch between RSA and EC + */ + +#if defined(MBEDTLS_RSA_C) + +#define TEST_CA_KEY TEST_CA_KEY_RSA +#define TEST_CA_PWD TEST_CA_PWD_RSA +#define TEST_CA_CRT TEST_CA_CRT_RSA + +#define TEST_SRV_KEY TEST_SRV_KEY_RSA +#define TEST_SRV_PWD TEST_SRV_PWD_RSA +#define TEST_SRV_CRT TEST_SRV_CRT_RSA + +#define TEST_CLI_KEY TEST_CLI_KEY_RSA +#define TEST_CLI_PWD TEST_CLI_PWD_RSA +#define TEST_CLI_CRT TEST_CLI_CRT_RSA + +#else /* no RSA, so assume ECDSA */ + +#define TEST_CA_KEY TEST_CA_KEY_EC +#define TEST_CA_PWD TEST_CA_PWD_EC +#define TEST_CA_CRT TEST_CA_CRT_EC + +#define TEST_SRV_KEY TEST_SRV_KEY_EC +#define TEST_SRV_PWD TEST_SRV_PWD_EC +#define TEST_SRV_CRT TEST_SRV_CRT_EC + +#define TEST_CLI_KEY TEST_CLI_KEY_EC +#define TEST_CLI_PWD TEST_CLI_PWD_EC +#define TEST_CLI_CRT TEST_CLI_CRT_EC +#endif /* MBEDTLS_RSA_C */ + +/* API stability forces us to declare + * mbedtls_test_{ca|srv|cli}_{key|pwd|crt} + * as pointers. */ +static const char test_ca_key[] = TEST_CA_KEY; +static const char test_ca_pwd[] = TEST_CA_PWD; +static const char test_ca_crt[] = TEST_CA_CRT; + +static const char test_srv_key[] = TEST_SRV_KEY; +static const char test_srv_pwd[] = TEST_SRV_PWD; +static const char test_srv_crt[] = TEST_SRV_CRT; + +static const char test_cli_key[] = TEST_CLI_KEY; +static const char test_cli_pwd[] = TEST_CLI_PWD; +static const char test_cli_crt[] = TEST_CLI_CRT; + +const char *mbedtls_test_ca_key = test_ca_key; +const char *mbedtls_test_ca_pwd = test_ca_pwd; +const char *mbedtls_test_ca_crt = test_ca_crt; + +const char *mbedtls_test_srv_key = test_srv_key; +const char *mbedtls_test_srv_pwd = test_srv_pwd; +const char *mbedtls_test_srv_crt = test_srv_crt; + +const char *mbedtls_test_cli_key = test_cli_key; +const char *mbedtls_test_cli_pwd = test_cli_pwd; +const char *mbedtls_test_cli_crt = test_cli_crt; + +const size_t mbedtls_test_ca_key_len = + sizeof( test_ca_key ); +const size_t mbedtls_test_ca_pwd_len = + sizeof( test_ca_pwd ) - 1; +const size_t mbedtls_test_ca_crt_len = + sizeof( test_ca_crt ); + +const size_t mbedtls_test_srv_key_len = + sizeof( test_srv_key ); +const size_t mbedtls_test_srv_pwd_len = + sizeof( test_srv_pwd ) - 1; +const size_t mbedtls_test_srv_crt_len = + sizeof( test_srv_crt ); + +const size_t mbedtls_test_cli_key_len = + sizeof( test_cli_key ); +const size_t mbedtls_test_cli_pwd_len = + sizeof( test_cli_pwd ) - 1; +const size_t mbedtls_test_cli_crt_len = + sizeof( test_cli_crt ); + +/* + * + * Lists of certificates + * + */ + +/* List of CAs in PEM or DER, depending on config */ +const char * mbedtls_test_cas[] = { +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_SHA1_C) + mbedtls_test_ca_crt_rsa_sha1, +#endif +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_SHA256_C) + mbedtls_test_ca_crt_rsa_sha256, +#endif +#if defined(MBEDTLS_ECDSA_C) + mbedtls_test_ca_crt_ec, +#endif + NULL +}; +const size_t mbedtls_test_cas_len[] = { +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_SHA1_C) + sizeof( mbedtls_test_ca_crt_rsa_sha1 ), +#endif +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_SHA256_C) + sizeof( mbedtls_test_ca_crt_rsa_sha256 ), +#endif +#if defined(MBEDTLS_ECDSA_C) + sizeof( mbedtls_test_ca_crt_ec ), +#endif + 0 +}; + +/* List of all available CA certificates in DER format */ +const unsigned char * mbedtls_test_cas_der[] = { +#if defined(MBEDTLS_RSA_C) +#if defined(MBEDTLS_SHA256_C) + mbedtls_test_ca_crt_rsa_sha256_der, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA1_C) + mbedtls_test_ca_crt_rsa_sha1_der, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECDSA_C) + mbedtls_test_ca_crt_ec_der, +#endif /* MBEDTLS_ECDSA_C */ + NULL +}; + +const size_t mbedtls_test_cas_der_len[] = { +#if defined(MBEDTLS_RSA_C) +#if defined(MBEDTLS_SHA256_C) + sizeof( mbedtls_test_ca_crt_rsa_sha256_der ), +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA1_C) + sizeof( mbedtls_test_ca_crt_rsa_sha1_der ), +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECDSA_C) + sizeof( mbedtls_test_ca_crt_ec_der ), +#endif /* MBEDTLS_ECDSA_C */ + 0 +}; + +/* Concatenation of all available CA certificates in PEM format */ +#if defined(MBEDTLS_PEM_PARSE_C) +const char mbedtls_test_cas_pem[] = +#if defined(MBEDTLS_RSA_C) +#if defined(MBEDTLS_SHA256_C) + TEST_CA_CRT_RSA_SHA256_PEM +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA1_C) + TEST_CA_CRT_RSA_SHA1_PEM +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECDSA_C) + TEST_CA_CRT_EC_PEM +#endif /* MBEDTLS_ECDSA_C */ + ""; +const size_t mbedtls_test_cas_pem_len = sizeof( mbedtls_test_cas_pem ); +#endif /* MBEDTLS_PEM_PARSE_C */ + +#endif /* MBEDTLS_CERTS_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/chacha20.c b/Android/Level4/app/src/main/c/mbedtls/library/chacha20.c new file mode 100644 index 0000000..78467d3 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/chacha20.c @@ -0,0 +1,568 @@ +/** + * \file chacha20.c + * + * \brief ChaCha20 cipher. + * + * \author Daniel King + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 "common.h" + +#if defined(MBEDTLS_CHACHA20_C) + +#include "mbedtls/chacha20.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_CHACHA20_ALT) + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +/* Parameter validation macros */ +#define CHACHA20_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA ) +#define CHACHA20_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#define BYTES_TO_U32_LE( data, offset ) \ + ( (uint32_t) (data)[offset] \ + | (uint32_t) ( (uint32_t) (data)[( offset ) + 1] << 8 ) \ + | (uint32_t) ( (uint32_t) (data)[( offset ) + 2] << 16 ) \ + | (uint32_t) ( (uint32_t) (data)[( offset ) + 3] << 24 ) \ + ) + +#define ROTL32( value, amount ) \ + ( (uint32_t) ( (value) << (amount) ) | ( (value) >> ( 32 - (amount) ) ) ) + +#define CHACHA20_CTR_INDEX ( 12U ) + +#define CHACHA20_BLOCK_SIZE_BYTES ( 4U * 16U ) + +/** + * \brief ChaCha20 quarter round operation. + * + * The quarter round is defined as follows (from RFC 7539): + * 1. a += b; d ^= a; d <<<= 16; + * 2. c += d; b ^= c; b <<<= 12; + * 3. a += b; d ^= a; d <<<= 8; + * 4. c += d; b ^= c; b <<<= 7; + * + * \param state ChaCha20 state to modify. + * \param a The index of 'a' in the state. + * \param b The index of 'b' in the state. + * \param c The index of 'c' in the state. + * \param d The index of 'd' in the state. + */ +static inline void chacha20_quarter_round( uint32_t state[16], + size_t a, + size_t b, + size_t c, + size_t d ) +{ + /* a += b; d ^= a; d <<<= 16; */ + state[a] += state[b]; + state[d] ^= state[a]; + state[d] = ROTL32( state[d], 16 ); + + /* c += d; b ^= c; b <<<= 12 */ + state[c] += state[d]; + state[b] ^= state[c]; + state[b] = ROTL32( state[b], 12 ); + + /* a += b; d ^= a; d <<<= 8; */ + state[a] += state[b]; + state[d] ^= state[a]; + state[d] = ROTL32( state[d], 8 ); + + /* c += d; b ^= c; b <<<= 7; */ + state[c] += state[d]; + state[b] ^= state[c]; + state[b] = ROTL32( state[b], 7 ); +} + +/** + * \brief Perform the ChaCha20 inner block operation. + * + * This function performs two rounds: the column round and the + * diagonal round. + * + * \param state The ChaCha20 state to update. + */ +static void chacha20_inner_block( uint32_t state[16] ) +{ + chacha20_quarter_round( state, 0, 4, 8, 12 ); + chacha20_quarter_round( state, 1, 5, 9, 13 ); + chacha20_quarter_round( state, 2, 6, 10, 14 ); + chacha20_quarter_round( state, 3, 7, 11, 15 ); + + chacha20_quarter_round( state, 0, 5, 10, 15 ); + chacha20_quarter_round( state, 1, 6, 11, 12 ); + chacha20_quarter_round( state, 2, 7, 8, 13 ); + chacha20_quarter_round( state, 3, 4, 9, 14 ); +} + +/** + * \brief Generates a keystream block. + * + * \param initial_state The initial ChaCha20 state (key, nonce, counter). + * \param keystream Generated keystream bytes are written to this buffer. + */ +static void chacha20_block( const uint32_t initial_state[16], + unsigned char keystream[64] ) +{ + uint32_t working_state[16]; + size_t i; + + memcpy( working_state, + initial_state, + CHACHA20_BLOCK_SIZE_BYTES ); + + for( i = 0U; i < 10U; i++ ) + chacha20_inner_block( working_state ); + + working_state[ 0] += initial_state[ 0]; + working_state[ 1] += initial_state[ 1]; + working_state[ 2] += initial_state[ 2]; + working_state[ 3] += initial_state[ 3]; + working_state[ 4] += initial_state[ 4]; + working_state[ 5] += initial_state[ 5]; + working_state[ 6] += initial_state[ 6]; + working_state[ 7] += initial_state[ 7]; + working_state[ 8] += initial_state[ 8]; + working_state[ 9] += initial_state[ 9]; + working_state[10] += initial_state[10]; + working_state[11] += initial_state[11]; + working_state[12] += initial_state[12]; + working_state[13] += initial_state[13]; + working_state[14] += initial_state[14]; + working_state[15] += initial_state[15]; + + for( i = 0U; i < 16; i++ ) + { + size_t offset = i * 4U; + + keystream[offset ] = (unsigned char)( working_state[i] ); + keystream[offset + 1U] = (unsigned char)( working_state[i] >> 8 ); + keystream[offset + 2U] = (unsigned char)( working_state[i] >> 16 ); + keystream[offset + 3U] = (unsigned char)( working_state[i] >> 24 ); + } + + mbedtls_platform_zeroize( working_state, sizeof( working_state ) ); +} + +void mbedtls_chacha20_init( mbedtls_chacha20_context *ctx ) +{ + CHACHA20_VALIDATE( ctx != NULL ); + + mbedtls_platform_zeroize( ctx->state, sizeof( ctx->state ) ); + mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) ); + + /* Initially, there's no keystream bytes available */ + ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES; +} + +void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx ) +{ + if( ctx != NULL ) + { + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_chacha20_context ) ); + } +} + +int mbedtls_chacha20_setkey( mbedtls_chacha20_context *ctx, + const unsigned char key[32] ) +{ + CHACHA20_VALIDATE_RET( ctx != NULL ); + CHACHA20_VALIDATE_RET( key != NULL ); + + /* ChaCha20 constants - the string "expand 32-byte k" */ + ctx->state[0] = 0x61707865; + ctx->state[1] = 0x3320646e; + ctx->state[2] = 0x79622d32; + ctx->state[3] = 0x6b206574; + + /* Set key */ + ctx->state[4] = BYTES_TO_U32_LE( key, 0 ); + ctx->state[5] = BYTES_TO_U32_LE( key, 4 ); + ctx->state[6] = BYTES_TO_U32_LE( key, 8 ); + ctx->state[7] = BYTES_TO_U32_LE( key, 12 ); + ctx->state[8] = BYTES_TO_U32_LE( key, 16 ); + ctx->state[9] = BYTES_TO_U32_LE( key, 20 ); + ctx->state[10] = BYTES_TO_U32_LE( key, 24 ); + ctx->state[11] = BYTES_TO_U32_LE( key, 28 ); + + return( 0 ); +} + +int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx, + const unsigned char nonce[12], + uint32_t counter ) +{ + CHACHA20_VALIDATE_RET( ctx != NULL ); + CHACHA20_VALIDATE_RET( nonce != NULL ); + + /* Counter */ + ctx->state[12] = counter; + + /* Nonce */ + ctx->state[13] = BYTES_TO_U32_LE( nonce, 0 ); + ctx->state[14] = BYTES_TO_U32_LE( nonce, 4 ); + ctx->state[15] = BYTES_TO_U32_LE( nonce, 8 ); + + mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) ); + + /* Initially, there's no keystream bytes available */ + ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES; + + return( 0 ); +} + +int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx, + size_t size, + const unsigned char *input, + unsigned char *output ) +{ + size_t offset = 0U; + size_t i; + + CHACHA20_VALIDATE_RET( ctx != NULL ); + CHACHA20_VALIDATE_RET( size == 0 || input != NULL ); + CHACHA20_VALIDATE_RET( size == 0 || output != NULL ); + + /* Use leftover keystream bytes, if available */ + while( size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES ) + { + output[offset] = input[offset] + ^ ctx->keystream8[ctx->keystream_bytes_used]; + + ctx->keystream_bytes_used++; + offset++; + size--; + } + + /* Process full blocks */ + while( size >= CHACHA20_BLOCK_SIZE_BYTES ) + { + /* Generate new keystream block and increment counter */ + chacha20_block( ctx->state, ctx->keystream8 ); + ctx->state[CHACHA20_CTR_INDEX]++; + + for( i = 0U; i < 64U; i += 8U ) + { + output[offset + i ] = input[offset + i ] ^ ctx->keystream8[i ]; + output[offset + i+1] = input[offset + i+1] ^ ctx->keystream8[i+1]; + output[offset + i+2] = input[offset + i+2] ^ ctx->keystream8[i+2]; + output[offset + i+3] = input[offset + i+3] ^ ctx->keystream8[i+3]; + output[offset + i+4] = input[offset + i+4] ^ ctx->keystream8[i+4]; + output[offset + i+5] = input[offset + i+5] ^ ctx->keystream8[i+5]; + output[offset + i+6] = input[offset + i+6] ^ ctx->keystream8[i+6]; + output[offset + i+7] = input[offset + i+7] ^ ctx->keystream8[i+7]; + } + + offset += CHACHA20_BLOCK_SIZE_BYTES; + size -= CHACHA20_BLOCK_SIZE_BYTES; + } + + /* Last (partial) block */ + if( size > 0U ) + { + /* Generate new keystream block and increment counter */ + chacha20_block( ctx->state, ctx->keystream8 ); + ctx->state[CHACHA20_CTR_INDEX]++; + + for( i = 0U; i < size; i++) + { + output[offset + i] = input[offset + i] ^ ctx->keystream8[i]; + } + + ctx->keystream_bytes_used = size; + + } + + return( 0 ); +} + +int mbedtls_chacha20_crypt( const unsigned char key[32], + const unsigned char nonce[12], + uint32_t counter, + size_t data_len, + const unsigned char* input, + unsigned char* output ) +{ + mbedtls_chacha20_context ctx; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + CHACHA20_VALIDATE_RET( key != NULL ); + CHACHA20_VALIDATE_RET( nonce != NULL ); + CHACHA20_VALIDATE_RET( data_len == 0 || input != NULL ); + CHACHA20_VALIDATE_RET( data_len == 0 || output != NULL ); + + mbedtls_chacha20_init( &ctx ); + + ret = mbedtls_chacha20_setkey( &ctx, key ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_chacha20_starts( &ctx, nonce, counter ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_chacha20_update( &ctx, data_len, input, output ); + +cleanup: + mbedtls_chacha20_free( &ctx ); + return( ret ); +} + +#endif /* !MBEDTLS_CHACHA20_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +static const unsigned char test_keys[2][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 + }, + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 + } +}; + +static const unsigned char test_nonces[2][12] = +{ + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 + }, + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02 + } +}; + +static const uint32_t test_counters[2] = +{ + 0U, + 1U +}; + +static const unsigned char test_input[2][375] = +{ + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d, + 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74, + 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45, + 0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e, + 0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61, + 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72, + 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66, + 0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46, + 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, + 0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x20, + 0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61, + 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73, + 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, + 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69, + 0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, + 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49, + 0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69, + 0x76, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20, + 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72, + 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49, + 0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, + 0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, + 0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, + 0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, + 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45, + 0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20, + 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20, + 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20, + 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6c, 0x65, 0x63, + 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63, + 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61, + 0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e, + 0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f, + 0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c, + 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61, + 0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f + } +}; + +static const unsigned char test_output[2][375] = +{ + { + 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90, + 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28, + 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a, + 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7, + 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d, + 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37, + 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c, + 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86 + }, + { + 0xa3, 0xfb, 0xf0, 0x7d, 0xf3, 0xfa, 0x2f, 0xde, + 0x4f, 0x37, 0x6c, 0xa2, 0x3e, 0x82, 0x73, 0x70, + 0x41, 0x60, 0x5d, 0x9f, 0x4f, 0x4f, 0x57, 0xbd, + 0x8c, 0xff, 0x2c, 0x1d, 0x4b, 0x79, 0x55, 0xec, + 0x2a, 0x97, 0x94, 0x8b, 0xd3, 0x72, 0x29, 0x15, + 0xc8, 0xf3, 0xd3, 0x37, 0xf7, 0xd3, 0x70, 0x05, + 0x0e, 0x9e, 0x96, 0xd6, 0x47, 0xb7, 0xc3, 0x9f, + 0x56, 0xe0, 0x31, 0xca, 0x5e, 0xb6, 0x25, 0x0d, + 0x40, 0x42, 0xe0, 0x27, 0x85, 0xec, 0xec, 0xfa, + 0x4b, 0x4b, 0xb5, 0xe8, 0xea, 0xd0, 0x44, 0x0e, + 0x20, 0xb6, 0xe8, 0xdb, 0x09, 0xd8, 0x81, 0xa7, + 0xc6, 0x13, 0x2f, 0x42, 0x0e, 0x52, 0x79, 0x50, + 0x42, 0xbd, 0xfa, 0x77, 0x73, 0xd8, 0xa9, 0x05, + 0x14, 0x47, 0xb3, 0x29, 0x1c, 0xe1, 0x41, 0x1c, + 0x68, 0x04, 0x65, 0x55, 0x2a, 0xa6, 0xc4, 0x05, + 0xb7, 0x76, 0x4d, 0x5e, 0x87, 0xbe, 0xa8, 0x5a, + 0xd0, 0x0f, 0x84, 0x49, 0xed, 0x8f, 0x72, 0xd0, + 0xd6, 0x62, 0xab, 0x05, 0x26, 0x91, 0xca, 0x66, + 0x42, 0x4b, 0xc8, 0x6d, 0x2d, 0xf8, 0x0e, 0xa4, + 0x1f, 0x43, 0xab, 0xf9, 0x37, 0xd3, 0x25, 0x9d, + 0xc4, 0xb2, 0xd0, 0xdf, 0xb4, 0x8a, 0x6c, 0x91, + 0x39, 0xdd, 0xd7, 0xf7, 0x69, 0x66, 0xe9, 0x28, + 0xe6, 0x35, 0x55, 0x3b, 0xa7, 0x6c, 0x5c, 0x87, + 0x9d, 0x7b, 0x35, 0xd4, 0x9e, 0xb2, 0xe6, 0x2b, + 0x08, 0x71, 0xcd, 0xac, 0x63, 0x89, 0x39, 0xe2, + 0x5e, 0x8a, 0x1e, 0x0e, 0xf9, 0xd5, 0x28, 0x0f, + 0xa8, 0xca, 0x32, 0x8b, 0x35, 0x1c, 0x3c, 0x76, + 0x59, 0x89, 0xcb, 0xcf, 0x3d, 0xaa, 0x8b, 0x6c, + 0xcc, 0x3a, 0xaf, 0x9f, 0x39, 0x79, 0xc9, 0x2b, + 0x37, 0x20, 0xfc, 0x88, 0xdc, 0x95, 0xed, 0x84, + 0xa1, 0xbe, 0x05, 0x9c, 0x64, 0x99, 0xb9, 0xfd, + 0xa2, 0x36, 0xe7, 0xe8, 0x18, 0xb0, 0x4b, 0x0b, + 0xc3, 0x9c, 0x1e, 0x87, 0x6b, 0x19, 0x3b, 0xfe, + 0x55, 0x69, 0x75, 0x3f, 0x88, 0x12, 0x8c, 0xc0, + 0x8a, 0xaa, 0x9b, 0x63, 0xd1, 0xa1, 0x6f, 0x80, + 0xef, 0x25, 0x54, 0xd7, 0x18, 0x9c, 0x41, 0x1f, + 0x58, 0x69, 0xca, 0x52, 0xc5, 0xb8, 0x3f, 0xa3, + 0x6f, 0xf2, 0x16, 0xb9, 0xc1, 0xd3, 0x00, 0x62, + 0xbe, 0xbc, 0xfd, 0x2d, 0xc5, 0xbc, 0xe0, 0x91, + 0x19, 0x34, 0xfd, 0xa7, 0x9a, 0x86, 0xf6, 0xe6, + 0x98, 0xce, 0xd7, 0x59, 0xc3, 0xff, 0x9b, 0x64, + 0x77, 0x33, 0x8f, 0x3d, 0xa4, 0xf9, 0xcd, 0x85, + 0x14, 0xea, 0x99, 0x82, 0xcc, 0xaf, 0xb3, 0x41, + 0xb2, 0x38, 0x4d, 0xd9, 0x02, 0xf3, 0xd1, 0xab, + 0x7a, 0xc6, 0x1d, 0xd2, 0x9c, 0x6f, 0x21, 0xba, + 0x5b, 0x86, 0x2f, 0x37, 0x30, 0xe3, 0x7c, 0xfd, + 0xc4, 0xfd, 0x80, 0x6c, 0x22, 0xf2, 0x21 + } +}; + +static const size_t test_lengths[2] = +{ + 64U, + 375U +}; + +/* Make sure no other definition is already present. */ +#undef ASSERT + +#define ASSERT( cond, args ) \ + do \ + { \ + if( ! ( cond ) ) \ + { \ + if( verbose != 0 ) \ + mbedtls_printf args; \ + \ + return( -1 ); \ + } \ + } \ + while( 0 ) + +int mbedtls_chacha20_self_test( int verbose ) +{ + unsigned char output[381]; + unsigned i; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + for( i = 0U; i < 2U; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " ChaCha20 test %u ", i ); + + ret = mbedtls_chacha20_crypt( test_keys[i], + test_nonces[i], + test_counters[i], + test_lengths[i], + test_input[i], + output ); + + ASSERT( 0 == ret, ( "error code: %i\n", ret ) ); + + ASSERT( 0 == memcmp( output, test_output[i], test_lengths[i] ), + ( "failed (output)\n" ) ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* !MBEDTLS_CHACHA20_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/chachapoly.c b/Android/Level4/app/src/main/c/mbedtls/library/chachapoly.c new file mode 100644 index 0000000..77d5477 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/chachapoly.c @@ -0,0 +1,538 @@ +/** + * \file chachapoly.c + * + * \brief ChaCha20-Poly1305 AEAD construction based on RFC 7539. + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 "common.h" + +#if defined(MBEDTLS_CHACHAPOLY_C) + +#include "mbedtls/chachapoly.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_CHACHAPOLY_ALT) + +/* Parameter validation macros */ +#define CHACHAPOLY_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ) +#define CHACHAPOLY_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#define CHACHAPOLY_STATE_INIT ( 0 ) +#define CHACHAPOLY_STATE_AAD ( 1 ) +#define CHACHAPOLY_STATE_CIPHERTEXT ( 2 ) /* Encrypting or decrypting */ +#define CHACHAPOLY_STATE_FINISHED ( 3 ) + +/** + * \brief Adds nul bytes to pad the AAD for Poly1305. + * + * \param ctx The ChaCha20-Poly1305 context. + */ +static int chachapoly_pad_aad( mbedtls_chachapoly_context *ctx ) +{ + uint32_t partial_block_len = (uint32_t) ( ctx->aad_len % 16U ); + unsigned char zeroes[15]; + + if( partial_block_len == 0U ) + return( 0 ); + + memset( zeroes, 0, sizeof( zeroes ) ); + + return( mbedtls_poly1305_update( &ctx->poly1305_ctx, + zeroes, + 16U - partial_block_len ) ); +} + +/** + * \brief Adds nul bytes to pad the ciphertext for Poly1305. + * + * \param ctx The ChaCha20-Poly1305 context. + */ +static int chachapoly_pad_ciphertext( mbedtls_chachapoly_context *ctx ) +{ + uint32_t partial_block_len = (uint32_t) ( ctx->ciphertext_len % 16U ); + unsigned char zeroes[15]; + + if( partial_block_len == 0U ) + return( 0 ); + + memset( zeroes, 0, sizeof( zeroes ) ); + return( mbedtls_poly1305_update( &ctx->poly1305_ctx, + zeroes, + 16U - partial_block_len ) ); +} + +void mbedtls_chachapoly_init( mbedtls_chachapoly_context *ctx ) +{ + CHACHAPOLY_VALIDATE( ctx != NULL ); + + mbedtls_chacha20_init( &ctx->chacha20_ctx ); + mbedtls_poly1305_init( &ctx->poly1305_ctx ); + ctx->aad_len = 0U; + ctx->ciphertext_len = 0U; + ctx->state = CHACHAPOLY_STATE_INIT; + ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT; +} + +void mbedtls_chachapoly_free( mbedtls_chachapoly_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_chacha20_free( &ctx->chacha20_ctx ); + mbedtls_poly1305_free( &ctx->poly1305_ctx ); + ctx->aad_len = 0U; + ctx->ciphertext_len = 0U; + ctx->state = CHACHAPOLY_STATE_INIT; + ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT; +} + +int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx, + const unsigned char key[32] ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + CHACHAPOLY_VALIDATE_RET( ctx != NULL ); + CHACHAPOLY_VALIDATE_RET( key != NULL ); + + ret = mbedtls_chacha20_setkey( &ctx->chacha20_ctx, key ); + + return( ret ); +} + +int mbedtls_chachapoly_starts( mbedtls_chachapoly_context *ctx, + const unsigned char nonce[12], + mbedtls_chachapoly_mode_t mode ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char poly1305_key[64]; + CHACHAPOLY_VALIDATE_RET( ctx != NULL ); + CHACHAPOLY_VALIDATE_RET( nonce != NULL ); + + /* Set counter = 0, will be update to 1 when generating Poly1305 key */ + ret = mbedtls_chacha20_starts( &ctx->chacha20_ctx, nonce, 0U ); + if( ret != 0 ) + goto cleanup; + + /* Generate the Poly1305 key by getting the ChaCha20 keystream output with + * counter = 0. This is the same as encrypting a buffer of zeroes. + * Only the first 256-bits (32 bytes) of the key is used for Poly1305. + * The other 256 bits are discarded. + */ + memset( poly1305_key, 0, sizeof( poly1305_key ) ); + ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, sizeof( poly1305_key ), + poly1305_key, poly1305_key ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_poly1305_starts( &ctx->poly1305_ctx, poly1305_key ); + + if( ret == 0 ) + { + ctx->aad_len = 0U; + ctx->ciphertext_len = 0U; + ctx->state = CHACHAPOLY_STATE_AAD; + ctx->mode = mode; + } + +cleanup: + mbedtls_platform_zeroize( poly1305_key, 64U ); + return( ret ); +} + +int mbedtls_chachapoly_update_aad( mbedtls_chachapoly_context *ctx, + const unsigned char *aad, + size_t aad_len ) +{ + CHACHAPOLY_VALIDATE_RET( ctx != NULL ); + CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL ); + + if( ctx->state != CHACHAPOLY_STATE_AAD ) + return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE ); + + ctx->aad_len += aad_len; + + return( mbedtls_poly1305_update( &ctx->poly1305_ctx, aad, aad_len ) ); +} + +int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx, + size_t len, + const unsigned char *input, + unsigned char *output ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + CHACHAPOLY_VALIDATE_RET( ctx != NULL ); + CHACHAPOLY_VALIDATE_RET( len == 0 || input != NULL ); + CHACHAPOLY_VALIDATE_RET( len == 0 || output != NULL ); + + if( ( ctx->state != CHACHAPOLY_STATE_AAD ) && + ( ctx->state != CHACHAPOLY_STATE_CIPHERTEXT ) ) + { + return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE ); + } + + if( ctx->state == CHACHAPOLY_STATE_AAD ) + { + ctx->state = CHACHAPOLY_STATE_CIPHERTEXT; + + ret = chachapoly_pad_aad( ctx ); + if( ret != 0 ) + return( ret ); + } + + ctx->ciphertext_len += len; + + if( ctx->mode == MBEDTLS_CHACHAPOLY_ENCRYPT ) + { + ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, output, len ); + if( ret != 0 ) + return( ret ); + } + else /* DECRYPT */ + { + ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, input, len ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output ); + if( ret != 0 ) + return( ret ); + } + + return( 0 ); +} + +int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx, + unsigned char mac[16] ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char len_block[16]; + CHACHAPOLY_VALIDATE_RET( ctx != NULL ); + CHACHAPOLY_VALIDATE_RET( mac != NULL ); + + if( ctx->state == CHACHAPOLY_STATE_INIT ) + { + return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE ); + } + + if( ctx->state == CHACHAPOLY_STATE_AAD ) + { + ret = chachapoly_pad_aad( ctx ); + if( ret != 0 ) + return( ret ); + } + else if( ctx->state == CHACHAPOLY_STATE_CIPHERTEXT ) + { + ret = chachapoly_pad_ciphertext( ctx ); + if( ret != 0 ) + return( ret ); + } + + ctx->state = CHACHAPOLY_STATE_FINISHED; + + /* The lengths of the AAD and ciphertext are processed by + * Poly1305 as the final 128-bit block, encoded as little-endian integers. + */ + len_block[ 0] = (unsigned char)( ctx->aad_len ); + len_block[ 1] = (unsigned char)( ctx->aad_len >> 8 ); + len_block[ 2] = (unsigned char)( ctx->aad_len >> 16 ); + len_block[ 3] = (unsigned char)( ctx->aad_len >> 24 ); + len_block[ 4] = (unsigned char)( ctx->aad_len >> 32 ); + len_block[ 5] = (unsigned char)( ctx->aad_len >> 40 ); + len_block[ 6] = (unsigned char)( ctx->aad_len >> 48 ); + len_block[ 7] = (unsigned char)( ctx->aad_len >> 56 ); + len_block[ 8] = (unsigned char)( ctx->ciphertext_len ); + len_block[ 9] = (unsigned char)( ctx->ciphertext_len >> 8 ); + len_block[10] = (unsigned char)( ctx->ciphertext_len >> 16 ); + len_block[11] = (unsigned char)( ctx->ciphertext_len >> 24 ); + len_block[12] = (unsigned char)( ctx->ciphertext_len >> 32 ); + len_block[13] = (unsigned char)( ctx->ciphertext_len >> 40 ); + len_block[14] = (unsigned char)( ctx->ciphertext_len >> 48 ); + len_block[15] = (unsigned char)( ctx->ciphertext_len >> 56 ); + + ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, len_block, 16U ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_poly1305_finish( &ctx->poly1305_ctx, mac ); + + return( ret ); +} + +static int chachapoly_crypt_and_tag( mbedtls_chachapoly_context *ctx, + mbedtls_chachapoly_mode_t mode, + size_t length, + const unsigned char nonce[12], + const unsigned char *aad, + size_t aad_len, + const unsigned char *input, + unsigned char *output, + unsigned char tag[16] ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + ret = mbedtls_chachapoly_starts( ctx, nonce, mode ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_chachapoly_update_aad( ctx, aad, aad_len ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_chachapoly_update( ctx, length, input, output ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_chachapoly_finish( ctx, tag ); + +cleanup: + return( ret ); +} + +int mbedtls_chachapoly_encrypt_and_tag( mbedtls_chachapoly_context *ctx, + size_t length, + const unsigned char nonce[12], + const unsigned char *aad, + size_t aad_len, + const unsigned char *input, + unsigned char *output, + unsigned char tag[16] ) +{ + CHACHAPOLY_VALIDATE_RET( ctx != NULL ); + CHACHAPOLY_VALIDATE_RET( nonce != NULL ); + CHACHAPOLY_VALIDATE_RET( tag != NULL ); + CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL ); + CHACHAPOLY_VALIDATE_RET( length == 0 || input != NULL ); + CHACHAPOLY_VALIDATE_RET( length == 0 || output != NULL ); + + return( chachapoly_crypt_and_tag( ctx, MBEDTLS_CHACHAPOLY_ENCRYPT, + length, nonce, aad, aad_len, + input, output, tag ) ); +} + +int mbedtls_chachapoly_auth_decrypt( mbedtls_chachapoly_context *ctx, + size_t length, + const unsigned char nonce[12], + const unsigned char *aad, + size_t aad_len, + const unsigned char tag[16], + const unsigned char *input, + unsigned char *output ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char check_tag[16]; + size_t i; + int diff; + CHACHAPOLY_VALIDATE_RET( ctx != NULL ); + CHACHAPOLY_VALIDATE_RET( nonce != NULL ); + CHACHAPOLY_VALIDATE_RET( tag != NULL ); + CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL ); + CHACHAPOLY_VALIDATE_RET( length == 0 || input != NULL ); + CHACHAPOLY_VALIDATE_RET( length == 0 || output != NULL ); + + if( ( ret = chachapoly_crypt_and_tag( ctx, + MBEDTLS_CHACHAPOLY_DECRYPT, length, nonce, + aad, aad_len, input, output, check_tag ) ) != 0 ) + { + return( ret ); + } + + /* Check tag in "constant-time" */ + for( diff = 0, i = 0; i < sizeof( check_tag ); i++ ) + diff |= tag[i] ^ check_tag[i]; + + if( diff != 0 ) + { + mbedtls_platform_zeroize( output, length ); + return( MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED ); + } + + return( 0 ); +} + +#endif /* MBEDTLS_CHACHAPOLY_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +static const unsigned char test_key[1][32] = +{ + { + 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 + } +}; + +static const unsigned char test_nonce[1][12] = +{ + { + 0x07, 0x00, 0x00, 0x00, /* 32-bit common part */ + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 /* 64-bit IV */ + } +}; + +static const unsigned char test_aad[1][12] = +{ + { + 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3, + 0xc4, 0xc5, 0xc6, 0xc7 + } +}; + +static const size_t test_aad_len[1] = +{ + 12U +}; + +static const unsigned char test_input[1][114] = +{ + { + 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61, + 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c, + 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73, + 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39, + 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63, + 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66, + 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f, + 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20, + 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75, + 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73, + 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f, + 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69, + 0x74, 0x2e + } +}; + +static const unsigned char test_output[1][114] = +{ + { + 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 + } +}; + +static const size_t test_input_len[1] = +{ + 114U +}; + +static const unsigned char test_mac[1][16] = +{ + { + 0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a, + 0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91 + } +}; + +/* Make sure no other definition is already present. */ +#undef ASSERT + +#define ASSERT( cond, args ) \ + do \ + { \ + if( ! ( cond ) ) \ + { \ + if( verbose != 0 ) \ + mbedtls_printf args; \ + \ + return( -1 ); \ + } \ + } \ + while( 0 ) + +int mbedtls_chachapoly_self_test( int verbose ) +{ + mbedtls_chachapoly_context ctx; + unsigned i; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char output[200]; + unsigned char mac[16]; + + for( i = 0U; i < 1U; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " ChaCha20-Poly1305 test %u ", i ); + + mbedtls_chachapoly_init( &ctx ); + + ret = mbedtls_chachapoly_setkey( &ctx, test_key[i] ); + ASSERT( 0 == ret, ( "setkey() error code: %i\n", ret ) ); + + ret = mbedtls_chachapoly_encrypt_and_tag( &ctx, + test_input_len[i], + test_nonce[i], + test_aad[i], + test_aad_len[i], + test_input[i], + output, + mac ); + + ASSERT( 0 == ret, ( "crypt_and_tag() error code: %i\n", ret ) ); + + ASSERT( 0 == memcmp( output, test_output[i], test_input_len[i] ), + ( "failure (wrong output)\n" ) ); + + ASSERT( 0 == memcmp( mac, test_mac[i], 16U ), + ( "failure (wrong MAC)\n" ) ); + + mbedtls_chachapoly_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_CHACHAPOLY_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/cipher.c b/Android/Level4/app/src/main/c/mbedtls/library/cipher.c new file mode 100644 index 0000000..853eeec --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/cipher.c @@ -0,0 +1,1519 @@ +/** + * \file cipher.c + * + * \brief Generic cipher wrapper for mbed TLS + * + * \author Adriaan de Jong + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 "common.h" + +#if defined(MBEDTLS_CIPHER_C) + +#include "mbedtls/cipher.h" +#include "mbedtls/cipher_internal.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include +#include + +#if defined(MBEDTLS_CHACHAPOLY_C) +#include "mbedtls/chachapoly.h" +#endif + +#if defined(MBEDTLS_GCM_C) +#include "mbedtls/gcm.h" +#endif + +#if defined(MBEDTLS_CCM_C) +#include "mbedtls/ccm.h" +#endif + +#if defined(MBEDTLS_CHACHA20_C) +#include "mbedtls/chacha20.h" +#endif + +#if defined(MBEDTLS_CMAC_C) +#include "mbedtls/cmac.h" +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#include "mbedtls/psa_util.h" +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_NIST_KW_C) +#include "mbedtls/nist_kw.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#define CIPHER_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ) +#define CIPHER_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) +/* Compare the contents of two buffers in constant time. + * Returns 0 if the contents are bitwise identical, otherwise returns + * a non-zero value. + * This is currently only used by GCM and ChaCha20+Poly1305. + */ +static int mbedtls_constant_time_memcmp( const void *v1, const void *v2, + size_t len ) +{ + const unsigned char *p1 = (const unsigned char*) v1; + const unsigned char *p2 = (const unsigned char*) v2; + size_t i; + unsigned char diff; + + for( diff = 0, i = 0; i < len; i++ ) + diff |= p1[i] ^ p2[i]; + + return( (int)diff ); +} +#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ + +static int supported_init = 0; + +const int *mbedtls_cipher_list( void ) +{ + const mbedtls_cipher_definition_t *def; + int *type; + + if( ! supported_init ) + { + def = mbedtls_cipher_definitions; + type = mbedtls_cipher_supported; + + while( def->type != 0 ) + *type++ = (*def++).type; + + *type = 0; + + supported_init = 1; + } + + return( mbedtls_cipher_supported ); +} + +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( + const mbedtls_cipher_type_t cipher_type ) +{ + const mbedtls_cipher_definition_t *def; + + for( def = mbedtls_cipher_definitions; def->info != NULL; def++ ) + if( def->type == cipher_type ) + return( def->info ); + + return( NULL ); +} + +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( + const char *cipher_name ) +{ + const mbedtls_cipher_definition_t *def; + + if( NULL == cipher_name ) + return( NULL ); + + for( def = mbedtls_cipher_definitions; def->info != NULL; def++ ) + if( ! strcmp( def->info->name, cipher_name ) ) + return( def->info ); + + return( NULL ); +} + +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( + const mbedtls_cipher_id_t cipher_id, + int key_bitlen, + const mbedtls_cipher_mode_t mode ) +{ + const mbedtls_cipher_definition_t *def; + + for( def = mbedtls_cipher_definitions; def->info != NULL; def++ ) + if( def->info->base->cipher == cipher_id && + def->info->key_bitlen == (unsigned) key_bitlen && + def->info->mode == mode ) + return( def->info ); + + return( NULL ); +} + +void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx ) +{ + CIPHER_VALIDATE( ctx != NULL ); + memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) ); +} + +void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx ) +{ + if( ctx == NULL ) + return; + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ctx->psa_enabled == 1 ) + { + if( ctx->cipher_ctx != NULL ) + { + mbedtls_cipher_context_psa * const cipher_psa = + (mbedtls_cipher_context_psa *) ctx->cipher_ctx; + + if( cipher_psa->slot_state == MBEDTLS_CIPHER_PSA_KEY_OWNED ) + { + /* xxx_free() doesn't allow to return failures. */ + (void) psa_destroy_key( cipher_psa->slot ); + } + + mbedtls_platform_zeroize( cipher_psa, sizeof( *cipher_psa ) ); + mbedtls_free( cipher_psa ); + } + + mbedtls_platform_zeroize( ctx, sizeof(mbedtls_cipher_context_t) ); + return; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_CMAC_C) + if( ctx->cmac_ctx ) + { + mbedtls_platform_zeroize( ctx->cmac_ctx, + sizeof( mbedtls_cmac_context_t ) ); + mbedtls_free( ctx->cmac_ctx ); + } +#endif + + if( ctx->cipher_ctx ) + ctx->cipher_info->base->ctx_free_func( ctx->cipher_ctx ); + + mbedtls_platform_zeroize( ctx, sizeof(mbedtls_cipher_context_t) ); +} + +int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, + const mbedtls_cipher_info_t *cipher_info ) +{ + CIPHER_VALIDATE_RET( ctx != NULL ); + if( cipher_info == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) ); + + if( NULL == ( ctx->cipher_ctx = cipher_info->base->ctx_alloc_func() ) ) + return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED ); + + ctx->cipher_info = cipher_info; + +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) + /* + * Ignore possible errors caused by a cipher mode that doesn't use padding + */ +#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) + (void) mbedtls_cipher_set_padding_mode( ctx, MBEDTLS_PADDING_PKCS7 ); +#else + (void) mbedtls_cipher_set_padding_mode( ctx, MBEDTLS_PADDING_NONE ); +#endif +#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ + + return( 0 ); +} + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +int mbedtls_cipher_setup_psa( mbedtls_cipher_context_t *ctx, + const mbedtls_cipher_info_t *cipher_info, + size_t taglen ) +{ + psa_algorithm_t alg; + mbedtls_cipher_context_psa *cipher_psa; + + if( NULL == cipher_info || NULL == ctx ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + /* Check that the underlying cipher mode and cipher type are + * supported by the underlying PSA Crypto implementation. */ + alg = mbedtls_psa_translate_cipher_mode( cipher_info->mode, taglen ); + if( alg == 0 ) + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + if( mbedtls_psa_translate_cipher_type( cipher_info->type ) == 0 ) + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + + memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) ); + + cipher_psa = mbedtls_calloc( 1, sizeof(mbedtls_cipher_context_psa ) ); + if( cipher_psa == NULL ) + return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED ); + cipher_psa->alg = alg; + ctx->cipher_ctx = cipher_psa; + ctx->cipher_info = cipher_info; + ctx->psa_enabled = 1; + return( 0 ); +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, + const unsigned char *key, + int key_bitlen, + const mbedtls_operation_t operation ) +{ + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( key != NULL ); + CIPHER_VALIDATE_RET( operation == MBEDTLS_ENCRYPT || + operation == MBEDTLS_DECRYPT ); + if( ctx->cipher_info == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ctx->psa_enabled == 1 ) + { + mbedtls_cipher_context_psa * const cipher_psa = + (mbedtls_cipher_context_psa *) ctx->cipher_ctx; + + size_t const key_bytelen = ( (size_t) key_bitlen + 7 ) / 8; + + psa_status_t status; + psa_key_type_t key_type; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + + /* PSA Crypto API only accepts byte-aligned keys. */ + if( key_bitlen % 8 != 0 ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + /* Don't allow keys to be set multiple times. */ + if( cipher_psa->slot_state != MBEDTLS_CIPHER_PSA_KEY_UNSET ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + key_type = mbedtls_psa_translate_cipher_type( + ctx->cipher_info->type ); + if( key_type == 0 ) + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + psa_set_key_type( &attributes, key_type ); + + /* Mbed TLS' cipher layer doesn't enforce the mode of operation + * (encrypt vs. decrypt): it is possible to setup a key for encryption + * and use it for AEAD decryption. Until tests relying on this + * are changed, allow any usage in PSA. */ + psa_set_key_usage_flags( &attributes, + /* mbedtls_psa_translate_cipher_operation( operation ); */ + PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT ); + psa_set_key_algorithm( &attributes, cipher_psa->alg ); + + status = psa_import_key( &attributes, key, key_bytelen, + &cipher_psa->slot ); + switch( status ) + { + case PSA_SUCCESS: + break; + case PSA_ERROR_INSUFFICIENT_MEMORY: + return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED ); + case PSA_ERROR_NOT_SUPPORTED: + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + default: + return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED ); + } + /* Indicate that we own the key slot and need to + * destroy it in mbedtls_cipher_free(). */ + cipher_psa->slot_state = MBEDTLS_CIPHER_PSA_KEY_OWNED; + + ctx->key_bitlen = key_bitlen; + ctx->operation = operation; + return( 0 ); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_KEY_LEN ) == 0 && + (int) ctx->cipher_info->key_bitlen != key_bitlen ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + ctx->key_bitlen = key_bitlen; + ctx->operation = operation; + + /* + * For OFB, CFB and CTR mode always use the encryption key schedule + */ + if( MBEDTLS_ENCRYPT == operation || + MBEDTLS_MODE_CFB == ctx->cipher_info->mode || + MBEDTLS_MODE_OFB == ctx->cipher_info->mode || + MBEDTLS_MODE_CTR == ctx->cipher_info->mode ) + { + return( ctx->cipher_info->base->setkey_enc_func( ctx->cipher_ctx, key, + ctx->key_bitlen ) ); + } + + if( MBEDTLS_DECRYPT == operation ) + return( ctx->cipher_info->base->setkey_dec_func( ctx->cipher_ctx, key, + ctx->key_bitlen ) ); + + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); +} + +int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, + size_t iv_len ) +{ + size_t actual_iv_size; + + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL ); + if( ctx->cipher_info == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ctx->psa_enabled == 1 ) + { + /* While PSA Crypto has an API for multipart + * operations, we currently don't make it + * accessible through the cipher layer. */ + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + /* avoid buffer overflow in ctx->iv */ + if( iv_len > MBEDTLS_MAX_IV_LENGTH ) + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + + if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_IV_LEN ) != 0 ) + actual_iv_size = iv_len; + else + { + actual_iv_size = ctx->cipher_info->iv_size; + + /* avoid reading past the end of input buffer */ + if( actual_iv_size > iv_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + +#if defined(MBEDTLS_CHACHA20_C) + if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20 ) + { + if ( 0 != mbedtls_chacha20_starts( (mbedtls_chacha20_context*)ctx->cipher_ctx, + iv, + 0U ) ) /* Initial counter value */ + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + } +#endif + + if ( actual_iv_size != 0 ) + { + memcpy( ctx->iv, iv, actual_iv_size ); + ctx->iv_size = actual_iv_size; + } + + return( 0 ); +} + +int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx ) +{ + CIPHER_VALIDATE_RET( ctx != NULL ); + if( ctx->cipher_info == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ctx->psa_enabled == 1 ) + { + /* We don't support resetting PSA-based + * cipher contexts, yet. */ + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + ctx->unprocessed_len = 0; + + return( 0 ); +} + +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) +int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx, + const unsigned char *ad, size_t ad_len ) +{ + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL ); + if( ctx->cipher_info == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ctx->psa_enabled == 1 ) + { + /* While PSA Crypto has an API for multipart + * operations, we currently don't make it + * accessible through the cipher layer. */ + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_GCM_C) + if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) + { + return( mbedtls_gcm_starts( (mbedtls_gcm_context *) ctx->cipher_ctx, ctx->operation, + ctx->iv, ctx->iv_size, ad, ad_len ) ); + } +#endif + +#if defined(MBEDTLS_CHACHAPOLY_C) + if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) + { + int result; + mbedtls_chachapoly_mode_t mode; + + mode = ( ctx->operation == MBEDTLS_ENCRYPT ) + ? MBEDTLS_CHACHAPOLY_ENCRYPT + : MBEDTLS_CHACHAPOLY_DECRYPT; + + result = mbedtls_chachapoly_starts( (mbedtls_chachapoly_context*) ctx->cipher_ctx, + ctx->iv, + mode ); + if ( result != 0 ) + return( result ); + + return( mbedtls_chachapoly_update_aad( (mbedtls_chachapoly_context*) ctx->cipher_ctx, + ad, ad_len ) ); + } +#endif + + return( 0 ); +} +#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ + +int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *input, + size_t ilen, unsigned char *output, size_t *olen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t block_size; + + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( ilen == 0 || input != NULL ); + CIPHER_VALIDATE_RET( output != NULL ); + CIPHER_VALIDATE_RET( olen != NULL ); + if( ctx->cipher_info == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ctx->psa_enabled == 1 ) + { + /* While PSA Crypto has an API for multipart + * operations, we currently don't make it + * accessible through the cipher layer. */ + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + *olen = 0; + block_size = mbedtls_cipher_get_block_size( ctx ); + if ( 0 == block_size ) + { + return( MBEDTLS_ERR_CIPHER_INVALID_CONTEXT ); + } + + if( ctx->cipher_info->mode == MBEDTLS_MODE_ECB ) + { + if( ilen != block_size ) + return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); + + *olen = ilen; + + if( 0 != ( ret = ctx->cipher_info->base->ecb_func( ctx->cipher_ctx, + ctx->operation, input, output ) ) ) + { + return( ret ); + } + + return( 0 ); + } + +#if defined(MBEDTLS_GCM_C) + if( ctx->cipher_info->mode == MBEDTLS_MODE_GCM ) + { + *olen = ilen; + return( mbedtls_gcm_update( (mbedtls_gcm_context *) ctx->cipher_ctx, ilen, input, + output ) ); + } +#endif + +#if defined(MBEDTLS_CHACHAPOLY_C) + if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305 ) + { + *olen = ilen; + return( mbedtls_chachapoly_update( (mbedtls_chachapoly_context*) ctx->cipher_ctx, + ilen, input, output ) ); + } +#endif + + if( input == output && + ( ctx->unprocessed_len != 0 || ilen % block_size ) ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + if( ctx->cipher_info->mode == MBEDTLS_MODE_CBC ) + { + size_t copy_len = 0; + + /* + * If there is not enough data for a full block, cache it. + */ + if( ( ctx->operation == MBEDTLS_DECRYPT && NULL != ctx->add_padding && + ilen <= block_size - ctx->unprocessed_len ) || + ( ctx->operation == MBEDTLS_DECRYPT && NULL == ctx->add_padding && + ilen < block_size - ctx->unprocessed_len ) || + ( ctx->operation == MBEDTLS_ENCRYPT && + ilen < block_size - ctx->unprocessed_len ) ) + { + memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input, + ilen ); + + ctx->unprocessed_len += ilen; + return( 0 ); + } + + /* + * Process cached data first + */ + if( 0 != ctx->unprocessed_len ) + { + copy_len = block_size - ctx->unprocessed_len; + + memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input, + copy_len ); + + if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, + ctx->operation, block_size, ctx->iv, + ctx->unprocessed_data, output ) ) ) + { + return( ret ); + } + + *olen += block_size; + output += block_size; + ctx->unprocessed_len = 0; + + input += copy_len; + ilen -= copy_len; + } + + /* + * Cache final, incomplete block + */ + if( 0 != ilen ) + { + /* Encryption: only cache partial blocks + * Decryption w/ padding: always keep at least one whole block + * Decryption w/o padding: only cache partial blocks + */ + copy_len = ilen % block_size; + if( copy_len == 0 && + ctx->operation == MBEDTLS_DECRYPT && + NULL != ctx->add_padding) + { + copy_len = block_size; + } + + memcpy( ctx->unprocessed_data, &( input[ilen - copy_len] ), + copy_len ); + + ctx->unprocessed_len += copy_len; + ilen -= copy_len; + } + + /* + * Process remaining full blocks + */ + if( ilen ) + { + if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, + ctx->operation, ilen, ctx->iv, input, output ) ) ) + { + return( ret ); + } + + *olen += ilen; + } + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) + if( ctx->cipher_info->mode == MBEDTLS_MODE_CFB ) + { + if( 0 != ( ret = ctx->cipher_info->base->cfb_func( ctx->cipher_ctx, + ctx->operation, ilen, &ctx->unprocessed_len, ctx->iv, + input, output ) ) ) + { + return( ret ); + } + + *olen = ilen; + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_OFB) + if( ctx->cipher_info->mode == MBEDTLS_MODE_OFB ) + { + if( 0 != ( ret = ctx->cipher_info->base->ofb_func( ctx->cipher_ctx, + ilen, &ctx->unprocessed_len, ctx->iv, input, output ) ) ) + { + return( ret ); + } + + *olen = ilen; + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) + if( ctx->cipher_info->mode == MBEDTLS_MODE_CTR ) + { + if( 0 != ( ret = ctx->cipher_info->base->ctr_func( ctx->cipher_ctx, + ilen, &ctx->unprocessed_len, ctx->iv, + ctx->unprocessed_data, input, output ) ) ) + { + return( ret ); + } + + *olen = ilen; + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_CIPHER_MODE_XTS) + if( ctx->cipher_info->mode == MBEDTLS_MODE_XTS ) + { + if( ctx->unprocessed_len > 0 ) { + /* We can only process an entire data unit at a time. */ + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + } + + ret = ctx->cipher_info->base->xts_func( ctx->cipher_ctx, + ctx->operation, ilen, ctx->iv, input, output ); + if( ret != 0 ) + { + return( ret ); + } + + *olen = ilen; + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + if( ctx->cipher_info->mode == MBEDTLS_MODE_STREAM ) + { + if( 0 != ( ret = ctx->cipher_info->base->stream_func( ctx->cipher_ctx, + ilen, input, output ) ) ) + { + return( ret ); + } + + *olen = ilen; + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_STREAM */ + + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); +} + +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) +#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) +/* + * PKCS7 (and PKCS5) padding: fill with ll bytes, with ll = padding_len + */ +static void add_pkcs_padding( unsigned char *output, size_t output_len, + size_t data_len ) +{ + size_t padding_len = output_len - data_len; + unsigned char i; + + for( i = 0; i < padding_len; i++ ) + output[data_len + i] = (unsigned char) padding_len; +} + +static int get_pkcs_padding( unsigned char *input, size_t input_len, + size_t *data_len ) +{ + size_t i, pad_idx; + unsigned char padding_len, bad = 0; + + if( NULL == input || NULL == data_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + padding_len = input[input_len - 1]; + *data_len = input_len - padding_len; + + /* Avoid logical || since it results in a branch */ + bad |= padding_len > input_len; + bad |= padding_len == 0; + + /* The number of bytes checked must be independent of padding_len, + * so pick input_len, which is usually 8 or 16 (one block) */ + pad_idx = input_len - padding_len; + for( i = 0; i < input_len; i++ ) + bad |= ( input[i] ^ padding_len ) * ( i >= pad_idx ); + + return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); +} +#endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */ + +#if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) +/* + * One and zeros padding: fill with 80 00 ... 00 + */ +static void add_one_and_zeros_padding( unsigned char *output, + size_t output_len, size_t data_len ) +{ + size_t padding_len = output_len - data_len; + unsigned char i = 0; + + output[data_len] = 0x80; + for( i = 1; i < padding_len; i++ ) + output[data_len + i] = 0x00; +} + +static int get_one_and_zeros_padding( unsigned char *input, size_t input_len, + size_t *data_len ) +{ + size_t i; + unsigned char done = 0, prev_done, bad; + + if( NULL == input || NULL == data_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + bad = 0x80; + *data_len = 0; + for( i = input_len; i > 0; i-- ) + { + prev_done = done; + done |= ( input[i - 1] != 0 ); + *data_len |= ( i - 1 ) * ( done != prev_done ); + bad ^= input[i - 1] * ( done != prev_done ); + } + + return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); + +} +#endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */ + +#if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) +/* + * Zeros and len padding: fill with 00 ... 00 ll, where ll is padding length + */ +static void add_zeros_and_len_padding( unsigned char *output, + size_t output_len, size_t data_len ) +{ + size_t padding_len = output_len - data_len; + unsigned char i = 0; + + for( i = 1; i < padding_len; i++ ) + output[data_len + i - 1] = 0x00; + output[output_len - 1] = (unsigned char) padding_len; +} + +static int get_zeros_and_len_padding( unsigned char *input, size_t input_len, + size_t *data_len ) +{ + size_t i, pad_idx; + unsigned char padding_len, bad = 0; + + if( NULL == input || NULL == data_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + padding_len = input[input_len - 1]; + *data_len = input_len - padding_len; + + /* Avoid logical || since it results in a branch */ + bad |= padding_len > input_len; + bad |= padding_len == 0; + + /* The number of bytes checked must be independent of padding_len */ + pad_idx = input_len - padding_len; + for( i = 0; i < input_len - 1; i++ ) + bad |= input[i] * ( i >= pad_idx ); + + return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); +} +#endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */ + +#if defined(MBEDTLS_CIPHER_PADDING_ZEROS) +/* + * Zero padding: fill with 00 ... 00 + */ +static void add_zeros_padding( unsigned char *output, + size_t output_len, size_t data_len ) +{ + size_t i; + + for( i = data_len; i < output_len; i++ ) + output[i] = 0x00; +} + +static int get_zeros_padding( unsigned char *input, size_t input_len, + size_t *data_len ) +{ + size_t i; + unsigned char done = 0, prev_done; + + if( NULL == input || NULL == data_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + *data_len = 0; + for( i = input_len; i > 0; i-- ) + { + prev_done = done; + done |= ( input[i-1] != 0 ); + *data_len |= i * ( done != prev_done ); + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_PADDING_ZEROS */ + +/* + * No padding: don't pad :) + * + * There is no add_padding function (check for NULL in mbedtls_cipher_finish) + * but a trivial get_padding function + */ +static int get_no_padding( unsigned char *input, size_t input_len, + size_t *data_len ) +{ + if( NULL == input || NULL == data_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + *data_len = input_len; + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ + +int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx, + unsigned char *output, size_t *olen ) +{ + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( output != NULL ); + CIPHER_VALIDATE_RET( olen != NULL ); + if( ctx->cipher_info == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ctx->psa_enabled == 1 ) + { + /* While PSA Crypto has an API for multipart + * operations, we currently don't make it + * accessible through the cipher layer. */ + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + *olen = 0; + + if( MBEDTLS_MODE_CFB == ctx->cipher_info->mode || + MBEDTLS_MODE_OFB == ctx->cipher_info->mode || + MBEDTLS_MODE_CTR == ctx->cipher_info->mode || + MBEDTLS_MODE_GCM == ctx->cipher_info->mode || + MBEDTLS_MODE_XTS == ctx->cipher_info->mode || + MBEDTLS_MODE_STREAM == ctx->cipher_info->mode ) + { + return( 0 ); + } + + if ( ( MBEDTLS_CIPHER_CHACHA20 == ctx->cipher_info->type ) || + ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) ) + { + return( 0 ); + } + + if( MBEDTLS_MODE_ECB == ctx->cipher_info->mode ) + { + if( ctx->unprocessed_len != 0 ) + return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); + + return( 0 ); + } + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + if( MBEDTLS_MODE_CBC == ctx->cipher_info->mode ) + { + int ret = 0; + + if( MBEDTLS_ENCRYPT == ctx->operation ) + { + /* check for 'no padding' mode */ + if( NULL == ctx->add_padding ) + { + if( 0 != ctx->unprocessed_len ) + return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); + + return( 0 ); + } + + ctx->add_padding( ctx->unprocessed_data, mbedtls_cipher_get_iv_size( ctx ), + ctx->unprocessed_len ); + } + else if( mbedtls_cipher_get_block_size( ctx ) != ctx->unprocessed_len ) + { + /* + * For decrypt operations, expect a full block, + * or an empty block if no padding + */ + if( NULL == ctx->add_padding && 0 == ctx->unprocessed_len ) + return( 0 ); + + return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); + } + + /* cipher block */ + if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, + ctx->operation, mbedtls_cipher_get_block_size( ctx ), ctx->iv, + ctx->unprocessed_data, output ) ) ) + { + return( ret ); + } + + /* Set output size for decryption */ + if( MBEDTLS_DECRYPT == ctx->operation ) + return( ctx->get_padding( output, mbedtls_cipher_get_block_size( ctx ), + olen ) ); + + /* Set output size for encryption */ + *olen = mbedtls_cipher_get_block_size( ctx ); + return( 0 ); + } +#else + ((void) output); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); +} + +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) +int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, + mbedtls_cipher_padding_t mode ) +{ + CIPHER_VALIDATE_RET( ctx != NULL ); + + if( NULL == ctx->cipher_info || MBEDTLS_MODE_CBC != ctx->cipher_info->mode ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ctx->psa_enabled == 1 ) + { + /* While PSA Crypto knows about CBC padding + * schemes, we currently don't make them + * accessible through the cipher layer. */ + if( mode != MBEDTLS_PADDING_NONE ) + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + + return( 0 ); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + switch( mode ) + { +#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) + case MBEDTLS_PADDING_PKCS7: + ctx->add_padding = add_pkcs_padding; + ctx->get_padding = get_pkcs_padding; + break; +#endif +#if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) + case MBEDTLS_PADDING_ONE_AND_ZEROS: + ctx->add_padding = add_one_and_zeros_padding; + ctx->get_padding = get_one_and_zeros_padding; + break; +#endif +#if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) + case MBEDTLS_PADDING_ZEROS_AND_LEN: + ctx->add_padding = add_zeros_and_len_padding; + ctx->get_padding = get_zeros_and_len_padding; + break; +#endif +#if defined(MBEDTLS_CIPHER_PADDING_ZEROS) + case MBEDTLS_PADDING_ZEROS: + ctx->add_padding = add_zeros_padding; + ctx->get_padding = get_zeros_padding; + break; +#endif + case MBEDTLS_PADDING_NONE: + ctx->add_padding = NULL; + ctx->get_padding = get_no_padding; + break; + + default: + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ + +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) +int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx, + unsigned char *tag, size_t tag_len ) +{ + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL ); + if( ctx->cipher_info == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( MBEDTLS_ENCRYPT != ctx->operation ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ctx->psa_enabled == 1 ) + { + /* While PSA Crypto has an API for multipart + * operations, we currently don't make it + * accessible through the cipher layer. */ + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_GCM_C) + if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) + return( mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx, + tag, tag_len ) ); +#endif + +#if defined(MBEDTLS_CHACHAPOLY_C) + if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) + { + /* Don't allow truncated MAC for Poly1305 */ + if ( tag_len != 16U ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + return( mbedtls_chachapoly_finish( + (mbedtls_chachapoly_context*) ctx->cipher_ctx, tag ) ); + } +#endif + + return( 0 ); +} + +int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx, + const unsigned char *tag, size_t tag_len ) +{ + unsigned char check_tag[16]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL ); + if( ctx->cipher_info == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( MBEDTLS_DECRYPT != ctx->operation ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ctx->psa_enabled == 1 ) + { + /* While PSA Crypto has an API for multipart + * operations, we currently don't make it + * accessible through the cipher layer. */ + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_GCM_C) + if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) + { + if( tag_len > sizeof( check_tag ) ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( 0 != ( ret = mbedtls_gcm_finish( + (mbedtls_gcm_context *) ctx->cipher_ctx, + check_tag, tag_len ) ) ) + { + return( ret ); + } + + /* Check the tag in "constant-time" */ + if( mbedtls_constant_time_memcmp( tag, check_tag, tag_len ) != 0 ) + return( MBEDTLS_ERR_CIPHER_AUTH_FAILED ); + + return( 0 ); + } +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CHACHAPOLY_C) + if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) + { + /* Don't allow truncated MAC for Poly1305 */ + if ( tag_len != sizeof( check_tag ) ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + ret = mbedtls_chachapoly_finish( + (mbedtls_chachapoly_context*) ctx->cipher_ctx, check_tag ); + if ( ret != 0 ) + { + return( ret ); + } + + /* Check the tag in "constant-time" */ + if( mbedtls_constant_time_memcmp( tag, check_tag, tag_len ) != 0 ) + return( MBEDTLS_ERR_CIPHER_AUTH_FAILED ); + + return( 0 ); + } +#endif /* MBEDTLS_CHACHAPOLY_C */ + + return( 0 ); +} +#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ + +/* + * Packet-oriented wrapper for non-AEAD modes + */ +int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t finish_olen; + + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL ); + CIPHER_VALIDATE_RET( ilen == 0 || input != NULL ); + CIPHER_VALIDATE_RET( output != NULL ); + CIPHER_VALIDATE_RET( olen != NULL ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ctx->psa_enabled == 1 ) + { + /* As in the non-PSA case, we don't check that + * a key has been set. If not, the key slot will + * still be in its default state of 0, which is + * guaranteed to be invalid, hence the PSA-call + * below will gracefully fail. */ + mbedtls_cipher_context_psa * const cipher_psa = + (mbedtls_cipher_context_psa *) ctx->cipher_ctx; + + psa_status_t status; + psa_cipher_operation_t cipher_op = PSA_CIPHER_OPERATION_INIT; + size_t part_len; + + if( ctx->operation == MBEDTLS_DECRYPT ) + { + status = psa_cipher_decrypt_setup( &cipher_op, + cipher_psa->slot, + cipher_psa->alg ); + } + else if( ctx->operation == MBEDTLS_ENCRYPT ) + { + status = psa_cipher_encrypt_setup( &cipher_op, + cipher_psa->slot, + cipher_psa->alg ); + } + else + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + /* In the following, we can immediately return on an error, + * because the PSA Crypto API guarantees that cipher operations + * are terminated by unsuccessful calls to psa_cipher_update(), + * and by any call to psa_cipher_finish(). */ + if( status != PSA_SUCCESS ) + return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED ); + + status = psa_cipher_set_iv( &cipher_op, iv, iv_len ); + if( status != PSA_SUCCESS ) + return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED ); + + status = psa_cipher_update( &cipher_op, + input, ilen, + output, ilen, olen ); + if( status != PSA_SUCCESS ) + return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED ); + + status = psa_cipher_finish( &cipher_op, + output + *olen, ilen - *olen, + &part_len ); + if( status != PSA_SUCCESS ) + return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED ); + + *olen += part_len; + return( 0 ); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + if( ( ret = mbedtls_cipher_set_iv( ctx, iv, iv_len ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_cipher_reset( ctx ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_cipher_update( ctx, input, ilen, + output, olen ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_cipher_finish( ctx, output + *olen, + &finish_olen ) ) != 0 ) + return( ret ); + + *olen += finish_olen; + + return( 0 ); +} + +#if defined(MBEDTLS_CIPHER_MODE_AEAD) +/* + * Packet-oriented encryption for AEAD modes + */ +int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, + unsigned char *tag, size_t tag_len ) +{ + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( iv != NULL ); + CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL ); + CIPHER_VALIDATE_RET( ilen == 0 || input != NULL ); + CIPHER_VALIDATE_RET( output != NULL ); + CIPHER_VALIDATE_RET( olen != NULL ); + CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ctx->psa_enabled == 1 ) + { + /* As in the non-PSA case, we don't check that + * a key has been set. If not, the key slot will + * still be in its default state of 0, which is + * guaranteed to be invalid, hence the PSA-call + * below will gracefully fail. */ + mbedtls_cipher_context_psa * const cipher_psa = + (mbedtls_cipher_context_psa *) ctx->cipher_ctx; + + psa_status_t status; + + /* PSA Crypto API always writes the authentication tag + * at the end of the encrypted message. */ + if( tag != output + ilen ) + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + + status = psa_aead_encrypt( cipher_psa->slot, + cipher_psa->alg, + iv, iv_len, + ad, ad_len, + input, ilen, + output, ilen + tag_len, olen ); + if( status != PSA_SUCCESS ) + return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED ); + + *olen -= tag_len; + return( 0 ); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_GCM_C) + if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) + { + *olen = ilen; + return( mbedtls_gcm_crypt_and_tag( ctx->cipher_ctx, MBEDTLS_GCM_ENCRYPT, + ilen, iv, iv_len, ad, ad_len, + input, output, tag_len, tag ) ); + } +#endif /* MBEDTLS_GCM_C */ +#if defined(MBEDTLS_CCM_C) + if( MBEDTLS_MODE_CCM == ctx->cipher_info->mode ) + { + *olen = ilen; + return( mbedtls_ccm_encrypt_and_tag( ctx->cipher_ctx, ilen, + iv, iv_len, ad, ad_len, input, output, + tag, tag_len ) ); + } +#endif /* MBEDTLS_CCM_C */ +#if defined(MBEDTLS_CHACHAPOLY_C) + if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) + { + /* ChachaPoly has fixed length nonce and MAC (tag) */ + if ( ( iv_len != ctx->cipher_info->iv_size ) || + ( tag_len != 16U ) ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + *olen = ilen; + return( mbedtls_chachapoly_encrypt_and_tag( ctx->cipher_ctx, + ilen, iv, ad, ad_len, input, output, tag ) ); + } +#endif /* MBEDTLS_CHACHAPOLY_C */ +#if defined(MBEDTLS_NIST_KW_C) + if( MBEDTLS_MODE_KW == ctx->cipher_info->mode || + MBEDTLS_MODE_KWP == ctx->cipher_info->mode ) + { + mbedtls_nist_kw_mode_t mode = ( MBEDTLS_MODE_KW == ctx->cipher_info->mode ) ? + MBEDTLS_KW_MODE_KW : MBEDTLS_KW_MODE_KWP; + + /* There is no iv, tag or ad associated with KW and KWP, these length should be 0 */ + if( iv_len != 0 || tag_len != 0 || ad_len != 0 ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + return( mbedtls_nist_kw_wrap( ctx->cipher_ctx, mode, input, ilen, output, olen, SIZE_MAX ) ); + } +#endif /* MBEDTLS_NIST_KW_C */ + + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); +} + +/* + * Packet-oriented decryption for AEAD modes + */ +int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, + const unsigned char *tag, size_t tag_len ) +{ + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( iv != NULL ); + CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL ); + CIPHER_VALIDATE_RET( ilen == 0 || input != NULL ); + CIPHER_VALIDATE_RET( output != NULL ); + CIPHER_VALIDATE_RET( olen != NULL ); + CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ctx->psa_enabled == 1 ) + { + /* As in the non-PSA case, we don't check that + * a key has been set. If not, the key slot will + * still be in its default state of 0, which is + * guaranteed to be invalid, hence the PSA-call + * below will gracefully fail. */ + mbedtls_cipher_context_psa * const cipher_psa = + (mbedtls_cipher_context_psa *) ctx->cipher_ctx; + + psa_status_t status; + + /* PSA Crypto API always writes the authentication tag + * at the end of the encrypted message. */ + if( tag != input + ilen ) + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + + status = psa_aead_decrypt( cipher_psa->slot, + cipher_psa->alg, + iv, iv_len, + ad, ad_len, + input, ilen + tag_len, + output, ilen, olen ); + if( status == PSA_ERROR_INVALID_SIGNATURE ) + return( MBEDTLS_ERR_CIPHER_AUTH_FAILED ); + else if( status != PSA_SUCCESS ) + return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED ); + + return( 0 ); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_GCM_C) + if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + *olen = ilen; + ret = mbedtls_gcm_auth_decrypt( ctx->cipher_ctx, ilen, + iv, iv_len, ad, ad_len, + tag, tag_len, input, output ); + + if( ret == MBEDTLS_ERR_GCM_AUTH_FAILED ) + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + + return( ret ); + } +#endif /* MBEDTLS_GCM_C */ +#if defined(MBEDTLS_CCM_C) + if( MBEDTLS_MODE_CCM == ctx->cipher_info->mode ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + *olen = ilen; + ret = mbedtls_ccm_auth_decrypt( ctx->cipher_ctx, ilen, + iv, iv_len, ad, ad_len, + input, output, tag, tag_len ); + + if( ret == MBEDTLS_ERR_CCM_AUTH_FAILED ) + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + + return( ret ); + } +#endif /* MBEDTLS_CCM_C */ +#if defined(MBEDTLS_CHACHAPOLY_C) + if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* ChachaPoly has fixed length nonce and MAC (tag) */ + if ( ( iv_len != ctx->cipher_info->iv_size ) || + ( tag_len != 16U ) ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + *olen = ilen; + ret = mbedtls_chachapoly_auth_decrypt( ctx->cipher_ctx, ilen, + iv, ad, ad_len, tag, input, output ); + + if( ret == MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED ) + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + + return( ret ); + } +#endif /* MBEDTLS_CHACHAPOLY_C */ +#if defined(MBEDTLS_NIST_KW_C) + if( MBEDTLS_MODE_KW == ctx->cipher_info->mode || + MBEDTLS_MODE_KWP == ctx->cipher_info->mode ) + { + mbedtls_nist_kw_mode_t mode = ( MBEDTLS_MODE_KW == ctx->cipher_info->mode ) ? + MBEDTLS_KW_MODE_KW : MBEDTLS_KW_MODE_KWP; + + /* There is no iv, tag or ad associated with KW and KWP, these length should be 0 */ + if( iv_len != 0 || tag_len != 0 || ad_len != 0 ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + return( mbedtls_nist_kw_unwrap( ctx->cipher_ctx, mode, input, ilen, output, olen, SIZE_MAX ) ); + } +#endif /* MBEDTLS_NIST_KW_C */ + + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); +} +#endif /* MBEDTLS_CIPHER_MODE_AEAD */ + +#endif /* MBEDTLS_CIPHER_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/cipher_wrap.c b/Android/Level4/app/src/main/c/mbedtls/library/cipher_wrap.c new file mode 100644 index 0000000..57eb3cb --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/cipher_wrap.c @@ -0,0 +1,2406 @@ +/** + * \file cipher_wrap.c + * + * \brief Generic cipher wrapper for mbed TLS + * + * \author Adriaan de Jong + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 "common.h" + +#if defined(MBEDTLS_CIPHER_C) + +#include "mbedtls/cipher_internal.h" +#include "mbedtls/error.h" + +#if defined(MBEDTLS_CHACHAPOLY_C) +#include "mbedtls/chachapoly.h" +#endif + +#if defined(MBEDTLS_AES_C) +#include "mbedtls/aes.h" +#endif + +#if defined(MBEDTLS_ARC4_C) +#include "mbedtls/arc4.h" +#endif + +#if defined(MBEDTLS_CAMELLIA_C) +#include "mbedtls/camellia.h" +#endif + +#if defined(MBEDTLS_ARIA_C) +#include "mbedtls/aria.h" +#endif + +#if defined(MBEDTLS_DES_C) +#include "mbedtls/des.h" +#endif + +#if defined(MBEDTLS_BLOWFISH_C) +#include "mbedtls/blowfish.h" +#endif + +#if defined(MBEDTLS_CHACHA20_C) +#include "mbedtls/chacha20.h" +#endif + +#if defined(MBEDTLS_GCM_C) +#include "mbedtls/gcm.h" +#endif + +#if defined(MBEDTLS_CCM_C) +#include "mbedtls/ccm.h" +#endif + +#if defined(MBEDTLS_NIST_KW_C) +#include "mbedtls/nist_kw.h" +#endif + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#include +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if defined(MBEDTLS_GCM_C) +/* shared by all GCM ciphers */ +static void *gcm_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_gcm_context ) ); + + if( ctx != NULL ) + mbedtls_gcm_init( (mbedtls_gcm_context *) ctx ); + + return( ctx ); +} + +static void gcm_ctx_free( void *ctx ) +{ + mbedtls_gcm_free( ctx ); + mbedtls_free( ctx ); +} +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CCM_C) +/* shared by all CCM ciphers */ +static void *ccm_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ccm_context ) ); + + if( ctx != NULL ) + mbedtls_ccm_init( (mbedtls_ccm_context *) ctx ); + + return( ctx ); +} + +static void ccm_ctx_free( void *ctx ) +{ + mbedtls_ccm_free( ctx ); + mbedtls_free( ctx ); +} +#endif /* MBEDTLS_CCM_C */ + +#if defined(MBEDTLS_AES_C) + +static int aes_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aes_crypt_ecb( (mbedtls_aes_context *) ctx, operation, input, output ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static int aes_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, size_t length, + unsigned char *iv, const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aes_crypt_cbc( (mbedtls_aes_context *) ctx, operation, length, iv, input, + output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static int aes_crypt_cfb128_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, size_t *iv_off, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aes_crypt_cfb128( (mbedtls_aes_context *) ctx, operation, length, iv_off, iv, + input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_OFB) +static int aes_crypt_ofb_wrap( void *ctx, size_t length, size_t *iv_off, + unsigned char *iv, const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aes_crypt_ofb( (mbedtls_aes_context *) ctx, length, iv_off, + iv, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static int aes_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, + unsigned char *nonce_counter, unsigned char *stream_block, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aes_crypt_ctr( (mbedtls_aes_context *) ctx, length, nc_off, nonce_counter, + stream_block, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +static int aes_crypt_xts_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, + const unsigned char data_unit[16], + const unsigned char *input, + unsigned char *output ) +{ + mbedtls_aes_xts_context *xts_ctx = ctx; + int mode; + + switch( operation ) + { + case MBEDTLS_ENCRYPT: + mode = MBEDTLS_AES_ENCRYPT; + break; + case MBEDTLS_DECRYPT: + mode = MBEDTLS_AES_DECRYPT; + break; + default: + return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; + } + + return mbedtls_aes_crypt_xts( xts_ctx, mode, length, + data_unit, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +static int aes_setkey_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_aes_setkey_dec( (mbedtls_aes_context *) ctx, key, key_bitlen ); +} + +static int aes_setkey_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_aes_setkey_enc( (mbedtls_aes_context *) ctx, key, key_bitlen ); +} + +static void * aes_ctx_alloc( void ) +{ + mbedtls_aes_context *aes = mbedtls_calloc( 1, sizeof( mbedtls_aes_context ) ); + + if( aes == NULL ) + return( NULL ); + + mbedtls_aes_init( aes ); + + return( aes ); +} + +static void aes_ctx_free( void *ctx ) +{ + mbedtls_aes_free( (mbedtls_aes_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t aes_info = { + MBEDTLS_CIPHER_ID_AES, + aes_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + aes_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + aes_crypt_cfb128_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + aes_crypt_ofb_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + aes_crypt_ctr_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + aes_setkey_enc_wrap, + aes_setkey_dec_wrap, + aes_ctx_alloc, + aes_ctx_free +}; + +static const mbedtls_cipher_info_t aes_128_ecb_info = { + MBEDTLS_CIPHER_AES_128_ECB, + MBEDTLS_MODE_ECB, + 128, + "AES-128-ECB", + 0, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_192_ecb_info = { + MBEDTLS_CIPHER_AES_192_ECB, + MBEDTLS_MODE_ECB, + 192, + "AES-192-ECB", + 0, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_256_ecb_info = { + MBEDTLS_CIPHER_AES_256_ECB, + MBEDTLS_MODE_ECB, + 256, + "AES-256-ECB", + 0, + 0, + 16, + &aes_info +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t aes_128_cbc_info = { + MBEDTLS_CIPHER_AES_128_CBC, + MBEDTLS_MODE_CBC, + 128, + "AES-128-CBC", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_192_cbc_info = { + MBEDTLS_CIPHER_AES_192_CBC, + MBEDTLS_MODE_CBC, + 192, + "AES-192-CBC", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_256_cbc_info = { + MBEDTLS_CIPHER_AES_256_CBC, + MBEDTLS_MODE_CBC, + 256, + "AES-256-CBC", + 16, + 0, + 16, + &aes_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static const mbedtls_cipher_info_t aes_128_cfb128_info = { + MBEDTLS_CIPHER_AES_128_CFB128, + MBEDTLS_MODE_CFB, + 128, + "AES-128-CFB128", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_192_cfb128_info = { + MBEDTLS_CIPHER_AES_192_CFB128, + MBEDTLS_MODE_CFB, + 192, + "AES-192-CFB128", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_256_cfb128_info = { + MBEDTLS_CIPHER_AES_256_CFB128, + MBEDTLS_MODE_CFB, + 256, + "AES-256-CFB128", + 16, + 0, + 16, + &aes_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_OFB) +static const mbedtls_cipher_info_t aes_128_ofb_info = { + MBEDTLS_CIPHER_AES_128_OFB, + MBEDTLS_MODE_OFB, + 128, + "AES-128-OFB", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_192_ofb_info = { + MBEDTLS_CIPHER_AES_192_OFB, + MBEDTLS_MODE_OFB, + 192, + "AES-192-OFB", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_256_ofb_info = { + MBEDTLS_CIPHER_AES_256_OFB, + MBEDTLS_MODE_OFB, + 256, + "AES-256-OFB", + 16, + 0, + 16, + &aes_info +}; +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static const mbedtls_cipher_info_t aes_128_ctr_info = { + MBEDTLS_CIPHER_AES_128_CTR, + MBEDTLS_MODE_CTR, + 128, + "AES-128-CTR", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_192_ctr_info = { + MBEDTLS_CIPHER_AES_192_CTR, + MBEDTLS_MODE_CTR, + 192, + "AES-192-CTR", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_256_ctr_info = { + MBEDTLS_CIPHER_AES_256_CTR, + MBEDTLS_MODE_CTR, + 256, + "AES-256-CTR", + 16, + 0, + 16, + &aes_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +static int xts_aes_setkey_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + mbedtls_aes_xts_context *xts_ctx = ctx; + return( mbedtls_aes_xts_setkey_enc( xts_ctx, key, key_bitlen ) ); +} + +static int xts_aes_setkey_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + mbedtls_aes_xts_context *xts_ctx = ctx; + return( mbedtls_aes_xts_setkey_dec( xts_ctx, key, key_bitlen ) ); +} + +static void *xts_aes_ctx_alloc( void ) +{ + mbedtls_aes_xts_context *xts_ctx = mbedtls_calloc( 1, sizeof( *xts_ctx ) ); + + if( xts_ctx != NULL ) + mbedtls_aes_xts_init( xts_ctx ); + + return( xts_ctx ); +} + +static void xts_aes_ctx_free( void *ctx ) +{ + mbedtls_aes_xts_context *xts_ctx = ctx; + + if( xts_ctx == NULL ) + return; + + mbedtls_aes_xts_free( xts_ctx ); + mbedtls_free( xts_ctx ); +} + +static const mbedtls_cipher_base_t xts_aes_info = { + MBEDTLS_CIPHER_ID_AES, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + aes_crypt_xts_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + xts_aes_setkey_enc_wrap, + xts_aes_setkey_dec_wrap, + xts_aes_ctx_alloc, + xts_aes_ctx_free +}; + +static const mbedtls_cipher_info_t aes_128_xts_info = { + MBEDTLS_CIPHER_AES_128_XTS, + MBEDTLS_MODE_XTS, + 256, + "AES-128-XTS", + 16, + 0, + 16, + &xts_aes_info +}; + +static const mbedtls_cipher_info_t aes_256_xts_info = { + MBEDTLS_CIPHER_AES_256_XTS, + MBEDTLS_MODE_XTS, + 512, + "AES-256-XTS", + 16, + 0, + 16, + &xts_aes_info +}; +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +#if defined(MBEDTLS_GCM_C) +static int gcm_aes_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_gcm_setkey( (mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_AES, + key, key_bitlen ); +} + +static const mbedtls_cipher_base_t gcm_aes_info = { + MBEDTLS_CIPHER_ID_AES, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + gcm_aes_setkey_wrap, + gcm_aes_setkey_wrap, + gcm_ctx_alloc, + gcm_ctx_free, +}; + +static const mbedtls_cipher_info_t aes_128_gcm_info = { + MBEDTLS_CIPHER_AES_128_GCM, + MBEDTLS_MODE_GCM, + 128, + "AES-128-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aes_info +}; + +static const mbedtls_cipher_info_t aes_192_gcm_info = { + MBEDTLS_CIPHER_AES_192_GCM, + MBEDTLS_MODE_GCM, + 192, + "AES-192-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aes_info +}; + +static const mbedtls_cipher_info_t aes_256_gcm_info = { + MBEDTLS_CIPHER_AES_256_GCM, + MBEDTLS_MODE_GCM, + 256, + "AES-256-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aes_info +}; +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CCM_C) +static int ccm_aes_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_ccm_setkey( (mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_AES, + key, key_bitlen ); +} + +static const mbedtls_cipher_base_t ccm_aes_info = { + MBEDTLS_CIPHER_ID_AES, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + ccm_aes_setkey_wrap, + ccm_aes_setkey_wrap, + ccm_ctx_alloc, + ccm_ctx_free, +}; + +static const mbedtls_cipher_info_t aes_128_ccm_info = { + MBEDTLS_CIPHER_AES_128_CCM, + MBEDTLS_MODE_CCM, + 128, + "AES-128-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aes_info +}; + +static const mbedtls_cipher_info_t aes_192_ccm_info = { + MBEDTLS_CIPHER_AES_192_CCM, + MBEDTLS_MODE_CCM, + 192, + "AES-192-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aes_info +}; + +static const mbedtls_cipher_info_t aes_256_ccm_info = { + MBEDTLS_CIPHER_AES_256_CCM, + MBEDTLS_MODE_CCM, + 256, + "AES-256-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aes_info +}; +#endif /* MBEDTLS_CCM_C */ + +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) + +static int camellia_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_camellia_crypt_ecb( (mbedtls_camellia_context *) ctx, operation, input, + output ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static int camellia_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_camellia_crypt_cbc( (mbedtls_camellia_context *) ctx, operation, length, iv, + input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static int camellia_crypt_cfb128_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, size_t *iv_off, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_camellia_crypt_cfb128( (mbedtls_camellia_context *) ctx, operation, length, + iv_off, iv, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static int camellia_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, + unsigned char *nonce_counter, unsigned char *stream_block, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_camellia_crypt_ctr( (mbedtls_camellia_context *) ctx, length, nc_off, + nonce_counter, stream_block, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +static int camellia_setkey_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_camellia_setkey_dec( (mbedtls_camellia_context *) ctx, key, key_bitlen ); +} + +static int camellia_setkey_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_camellia_setkey_enc( (mbedtls_camellia_context *) ctx, key, key_bitlen ); +} + +static void * camellia_ctx_alloc( void ) +{ + mbedtls_camellia_context *ctx; + ctx = mbedtls_calloc( 1, sizeof( mbedtls_camellia_context ) ); + + if( ctx == NULL ) + return( NULL ); + + mbedtls_camellia_init( ctx ); + + return( ctx ); +} + +static void camellia_ctx_free( void *ctx ) +{ + mbedtls_camellia_free( (mbedtls_camellia_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t camellia_info = { + MBEDTLS_CIPHER_ID_CAMELLIA, + camellia_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + camellia_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + camellia_crypt_cfb128_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + camellia_crypt_ctr_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + camellia_setkey_enc_wrap, + camellia_setkey_dec_wrap, + camellia_ctx_alloc, + camellia_ctx_free +}; + +static const mbedtls_cipher_info_t camellia_128_ecb_info = { + MBEDTLS_CIPHER_CAMELLIA_128_ECB, + MBEDTLS_MODE_ECB, + 128, + "CAMELLIA-128-ECB", + 0, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_ecb_info = { + MBEDTLS_CIPHER_CAMELLIA_192_ECB, + MBEDTLS_MODE_ECB, + 192, + "CAMELLIA-192-ECB", + 0, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_ecb_info = { + MBEDTLS_CIPHER_CAMELLIA_256_ECB, + MBEDTLS_MODE_ECB, + 256, + "CAMELLIA-256-ECB", + 0, + 0, + 16, + &camellia_info +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t camellia_128_cbc_info = { + MBEDTLS_CIPHER_CAMELLIA_128_CBC, + MBEDTLS_MODE_CBC, + 128, + "CAMELLIA-128-CBC", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_cbc_info = { + MBEDTLS_CIPHER_CAMELLIA_192_CBC, + MBEDTLS_MODE_CBC, + 192, + "CAMELLIA-192-CBC", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_cbc_info = { + MBEDTLS_CIPHER_CAMELLIA_256_CBC, + MBEDTLS_MODE_CBC, + 256, + "CAMELLIA-256-CBC", + 16, + 0, + 16, + &camellia_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static const mbedtls_cipher_info_t camellia_128_cfb128_info = { + MBEDTLS_CIPHER_CAMELLIA_128_CFB128, + MBEDTLS_MODE_CFB, + 128, + "CAMELLIA-128-CFB128", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_cfb128_info = { + MBEDTLS_CIPHER_CAMELLIA_192_CFB128, + MBEDTLS_MODE_CFB, + 192, + "CAMELLIA-192-CFB128", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_cfb128_info = { + MBEDTLS_CIPHER_CAMELLIA_256_CFB128, + MBEDTLS_MODE_CFB, + 256, + "CAMELLIA-256-CFB128", + 16, + 0, + 16, + &camellia_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static const mbedtls_cipher_info_t camellia_128_ctr_info = { + MBEDTLS_CIPHER_CAMELLIA_128_CTR, + MBEDTLS_MODE_CTR, + 128, + "CAMELLIA-128-CTR", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_ctr_info = { + MBEDTLS_CIPHER_CAMELLIA_192_CTR, + MBEDTLS_MODE_CTR, + 192, + "CAMELLIA-192-CTR", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_ctr_info = { + MBEDTLS_CIPHER_CAMELLIA_256_CTR, + MBEDTLS_MODE_CTR, + 256, + "CAMELLIA-256-CTR", + 16, + 0, + 16, + &camellia_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_GCM_C) +static int gcm_camellia_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_gcm_setkey( (mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_CAMELLIA, + key, key_bitlen ); +} + +static const mbedtls_cipher_base_t gcm_camellia_info = { + MBEDTLS_CIPHER_ID_CAMELLIA, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + gcm_camellia_setkey_wrap, + gcm_camellia_setkey_wrap, + gcm_ctx_alloc, + gcm_ctx_free, +}; + +static const mbedtls_cipher_info_t camellia_128_gcm_info = { + MBEDTLS_CIPHER_CAMELLIA_128_GCM, + MBEDTLS_MODE_GCM, + 128, + "CAMELLIA-128-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_gcm_info = { + MBEDTLS_CIPHER_CAMELLIA_192_GCM, + MBEDTLS_MODE_GCM, + 192, + "CAMELLIA-192-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_gcm_info = { + MBEDTLS_CIPHER_CAMELLIA_256_GCM, + MBEDTLS_MODE_GCM, + 256, + "CAMELLIA-256-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_camellia_info +}; +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CCM_C) +static int ccm_camellia_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_ccm_setkey( (mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_CAMELLIA, + key, key_bitlen ); +} + +static const mbedtls_cipher_base_t ccm_camellia_info = { + MBEDTLS_CIPHER_ID_CAMELLIA, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + ccm_camellia_setkey_wrap, + ccm_camellia_setkey_wrap, + ccm_ctx_alloc, + ccm_ctx_free, +}; + +static const mbedtls_cipher_info_t camellia_128_ccm_info = { + MBEDTLS_CIPHER_CAMELLIA_128_CCM, + MBEDTLS_MODE_CCM, + 128, + "CAMELLIA-128-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_ccm_info = { + MBEDTLS_CIPHER_CAMELLIA_192_CCM, + MBEDTLS_MODE_CCM, + 192, + "CAMELLIA-192-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_ccm_info = { + MBEDTLS_CIPHER_CAMELLIA_256_CCM, + MBEDTLS_MODE_CCM, + 256, + "CAMELLIA-256-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_camellia_info +}; +#endif /* MBEDTLS_CCM_C */ + +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_ARIA_C) + +static int aria_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + (void) operation; + return mbedtls_aria_crypt_ecb( (mbedtls_aria_context *) ctx, input, + output ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static int aria_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aria_crypt_cbc( (mbedtls_aria_context *) ctx, operation, length, iv, + input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static int aria_crypt_cfb128_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, size_t *iv_off, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aria_crypt_cfb128( (mbedtls_aria_context *) ctx, operation, length, + iv_off, iv, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static int aria_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, + unsigned char *nonce_counter, unsigned char *stream_block, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aria_crypt_ctr( (mbedtls_aria_context *) ctx, length, nc_off, + nonce_counter, stream_block, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +static int aria_setkey_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_aria_setkey_dec( (mbedtls_aria_context *) ctx, key, key_bitlen ); +} + +static int aria_setkey_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_aria_setkey_enc( (mbedtls_aria_context *) ctx, key, key_bitlen ); +} + +static void * aria_ctx_alloc( void ) +{ + mbedtls_aria_context *ctx; + ctx = mbedtls_calloc( 1, sizeof( mbedtls_aria_context ) ); + + if( ctx == NULL ) + return( NULL ); + + mbedtls_aria_init( ctx ); + + return( ctx ); +} + +static void aria_ctx_free( void *ctx ) +{ + mbedtls_aria_free( (mbedtls_aria_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t aria_info = { + MBEDTLS_CIPHER_ID_ARIA, + aria_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + aria_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + aria_crypt_cfb128_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + aria_crypt_ctr_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + aria_setkey_enc_wrap, + aria_setkey_dec_wrap, + aria_ctx_alloc, + aria_ctx_free +}; + +static const mbedtls_cipher_info_t aria_128_ecb_info = { + MBEDTLS_CIPHER_ARIA_128_ECB, + MBEDTLS_MODE_ECB, + 128, + "ARIA-128-ECB", + 0, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_192_ecb_info = { + MBEDTLS_CIPHER_ARIA_192_ECB, + MBEDTLS_MODE_ECB, + 192, + "ARIA-192-ECB", + 0, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_256_ecb_info = { + MBEDTLS_CIPHER_ARIA_256_ECB, + MBEDTLS_MODE_ECB, + 256, + "ARIA-256-ECB", + 0, + 0, + 16, + &aria_info +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t aria_128_cbc_info = { + MBEDTLS_CIPHER_ARIA_128_CBC, + MBEDTLS_MODE_CBC, + 128, + "ARIA-128-CBC", + 16, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_192_cbc_info = { + MBEDTLS_CIPHER_ARIA_192_CBC, + MBEDTLS_MODE_CBC, + 192, + "ARIA-192-CBC", + 16, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_256_cbc_info = { + MBEDTLS_CIPHER_ARIA_256_CBC, + MBEDTLS_MODE_CBC, + 256, + "ARIA-256-CBC", + 16, + 0, + 16, + &aria_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static const mbedtls_cipher_info_t aria_128_cfb128_info = { + MBEDTLS_CIPHER_ARIA_128_CFB128, + MBEDTLS_MODE_CFB, + 128, + "ARIA-128-CFB128", + 16, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_192_cfb128_info = { + MBEDTLS_CIPHER_ARIA_192_CFB128, + MBEDTLS_MODE_CFB, + 192, + "ARIA-192-CFB128", + 16, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_256_cfb128_info = { + MBEDTLS_CIPHER_ARIA_256_CFB128, + MBEDTLS_MODE_CFB, + 256, + "ARIA-256-CFB128", + 16, + 0, + 16, + &aria_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static const mbedtls_cipher_info_t aria_128_ctr_info = { + MBEDTLS_CIPHER_ARIA_128_CTR, + MBEDTLS_MODE_CTR, + 128, + "ARIA-128-CTR", + 16, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_192_ctr_info = { + MBEDTLS_CIPHER_ARIA_192_CTR, + MBEDTLS_MODE_CTR, + 192, + "ARIA-192-CTR", + 16, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_256_ctr_info = { + MBEDTLS_CIPHER_ARIA_256_CTR, + MBEDTLS_MODE_CTR, + 256, + "ARIA-256-CTR", + 16, + 0, + 16, + &aria_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_GCM_C) +static int gcm_aria_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_gcm_setkey( (mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_ARIA, + key, key_bitlen ); +} + +static const mbedtls_cipher_base_t gcm_aria_info = { + MBEDTLS_CIPHER_ID_ARIA, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + gcm_aria_setkey_wrap, + gcm_aria_setkey_wrap, + gcm_ctx_alloc, + gcm_ctx_free, +}; + +static const mbedtls_cipher_info_t aria_128_gcm_info = { + MBEDTLS_CIPHER_ARIA_128_GCM, + MBEDTLS_MODE_GCM, + 128, + "ARIA-128-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aria_info +}; + +static const mbedtls_cipher_info_t aria_192_gcm_info = { + MBEDTLS_CIPHER_ARIA_192_GCM, + MBEDTLS_MODE_GCM, + 192, + "ARIA-192-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aria_info +}; + +static const mbedtls_cipher_info_t aria_256_gcm_info = { + MBEDTLS_CIPHER_ARIA_256_GCM, + MBEDTLS_MODE_GCM, + 256, + "ARIA-256-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aria_info +}; +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CCM_C) +static int ccm_aria_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_ccm_setkey( (mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_ARIA, + key, key_bitlen ); +} + +static const mbedtls_cipher_base_t ccm_aria_info = { + MBEDTLS_CIPHER_ID_ARIA, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + ccm_aria_setkey_wrap, + ccm_aria_setkey_wrap, + ccm_ctx_alloc, + ccm_ctx_free, +}; + +static const mbedtls_cipher_info_t aria_128_ccm_info = { + MBEDTLS_CIPHER_ARIA_128_CCM, + MBEDTLS_MODE_CCM, + 128, + "ARIA-128-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aria_info +}; + +static const mbedtls_cipher_info_t aria_192_ccm_info = { + MBEDTLS_CIPHER_ARIA_192_CCM, + MBEDTLS_MODE_CCM, + 192, + "ARIA-192-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aria_info +}; + +static const mbedtls_cipher_info_t aria_256_ccm_info = { + MBEDTLS_CIPHER_ARIA_256_CCM, + MBEDTLS_MODE_CCM, + 256, + "ARIA-256-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aria_info +}; +#endif /* MBEDTLS_CCM_C */ + +#endif /* MBEDTLS_ARIA_C */ + +#if defined(MBEDTLS_DES_C) + +static int des_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + ((void) operation); + return mbedtls_des_crypt_ecb( (mbedtls_des_context *) ctx, input, output ); +} + +static int des3_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + ((void) operation); + return mbedtls_des3_crypt_ecb( (mbedtls_des3_context *) ctx, input, output ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static int des_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, size_t length, + unsigned char *iv, const unsigned char *input, unsigned char *output ) +{ + return mbedtls_des_crypt_cbc( (mbedtls_des_context *) ctx, operation, length, iv, input, + output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static int des3_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, size_t length, + unsigned char *iv, const unsigned char *input, unsigned char *output ) +{ + return mbedtls_des3_crypt_cbc( (mbedtls_des3_context *) ctx, operation, length, iv, input, + output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +static int des_setkey_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) key_bitlen); + + return mbedtls_des_setkey_dec( (mbedtls_des_context *) ctx, key ); +} + +static int des_setkey_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) key_bitlen); + + return mbedtls_des_setkey_enc( (mbedtls_des_context *) ctx, key ); +} + +static int des3_set2key_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) key_bitlen); + + return mbedtls_des3_set2key_dec( (mbedtls_des3_context *) ctx, key ); +} + +static int des3_set2key_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) key_bitlen); + + return mbedtls_des3_set2key_enc( (mbedtls_des3_context *) ctx, key ); +} + +static int des3_set3key_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) key_bitlen); + + return mbedtls_des3_set3key_dec( (mbedtls_des3_context *) ctx, key ); +} + +static int des3_set3key_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) key_bitlen); + + return mbedtls_des3_set3key_enc( (mbedtls_des3_context *) ctx, key ); +} + +static void * des_ctx_alloc( void ) +{ + mbedtls_des_context *des = mbedtls_calloc( 1, sizeof( mbedtls_des_context ) ); + + if( des == NULL ) + return( NULL ); + + mbedtls_des_init( des ); + + return( des ); +} + +static void des_ctx_free( void *ctx ) +{ + mbedtls_des_free( (mbedtls_des_context *) ctx ); + mbedtls_free( ctx ); +} + +static void * des3_ctx_alloc( void ) +{ + mbedtls_des3_context *des3; + des3 = mbedtls_calloc( 1, sizeof( mbedtls_des3_context ) ); + + if( des3 == NULL ) + return( NULL ); + + mbedtls_des3_init( des3 ); + + return( des3 ); +} + +static void des3_ctx_free( void *ctx ) +{ + mbedtls_des3_free( (mbedtls_des3_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t des_info = { + MBEDTLS_CIPHER_ID_DES, + des_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + des_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + des_setkey_enc_wrap, + des_setkey_dec_wrap, + des_ctx_alloc, + des_ctx_free +}; + +static const mbedtls_cipher_info_t des_ecb_info = { + MBEDTLS_CIPHER_DES_ECB, + MBEDTLS_MODE_ECB, + MBEDTLS_KEY_LENGTH_DES, + "DES-ECB", + 0, + 0, + 8, + &des_info +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t des_cbc_info = { + MBEDTLS_CIPHER_DES_CBC, + MBEDTLS_MODE_CBC, + MBEDTLS_KEY_LENGTH_DES, + "DES-CBC", + 8, + 0, + 8, + &des_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +static const mbedtls_cipher_base_t des_ede_info = { + MBEDTLS_CIPHER_ID_DES, + des3_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + des3_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + des3_set2key_enc_wrap, + des3_set2key_dec_wrap, + des3_ctx_alloc, + des3_ctx_free +}; + +static const mbedtls_cipher_info_t des_ede_ecb_info = { + MBEDTLS_CIPHER_DES_EDE_ECB, + MBEDTLS_MODE_ECB, + MBEDTLS_KEY_LENGTH_DES_EDE, + "DES-EDE-ECB", + 0, + 0, + 8, + &des_ede_info +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t des_ede_cbc_info = { + MBEDTLS_CIPHER_DES_EDE_CBC, + MBEDTLS_MODE_CBC, + MBEDTLS_KEY_LENGTH_DES_EDE, + "DES-EDE-CBC", + 8, + 0, + 8, + &des_ede_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +static const mbedtls_cipher_base_t des_ede3_info = { + MBEDTLS_CIPHER_ID_3DES, + des3_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + des3_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + des3_set3key_enc_wrap, + des3_set3key_dec_wrap, + des3_ctx_alloc, + des3_ctx_free +}; + +static const mbedtls_cipher_info_t des_ede3_ecb_info = { + MBEDTLS_CIPHER_DES_EDE3_ECB, + MBEDTLS_MODE_ECB, + MBEDTLS_KEY_LENGTH_DES_EDE3, + "DES-EDE3-ECB", + 0, + 0, + 8, + &des_ede3_info +}; +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t des_ede3_cbc_info = { + MBEDTLS_CIPHER_DES_EDE3_CBC, + MBEDTLS_MODE_CBC, + MBEDTLS_KEY_LENGTH_DES_EDE3, + "DES-EDE3-CBC", + 8, + 0, + 8, + &des_ede3_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_BLOWFISH_C) + +static int blowfish_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_blowfish_crypt_ecb( (mbedtls_blowfish_context *) ctx, operation, input, + output ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static int blowfish_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, unsigned char *iv, const unsigned char *input, + unsigned char *output ) +{ + return mbedtls_blowfish_crypt_cbc( (mbedtls_blowfish_context *) ctx, operation, length, iv, + input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static int blowfish_crypt_cfb64_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, size_t *iv_off, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_blowfish_crypt_cfb64( (mbedtls_blowfish_context *) ctx, operation, length, + iv_off, iv, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static int blowfish_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, + unsigned char *nonce_counter, unsigned char *stream_block, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_blowfish_crypt_ctr( (mbedtls_blowfish_context *) ctx, length, nc_off, + nonce_counter, stream_block, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +static int blowfish_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_blowfish_setkey( (mbedtls_blowfish_context *) ctx, key, key_bitlen ); +} + +static void * blowfish_ctx_alloc( void ) +{ + mbedtls_blowfish_context *ctx; + ctx = mbedtls_calloc( 1, sizeof( mbedtls_blowfish_context ) ); + + if( ctx == NULL ) + return( NULL ); + + mbedtls_blowfish_init( ctx ); + + return( ctx ); +} + +static void blowfish_ctx_free( void *ctx ) +{ + mbedtls_blowfish_free( (mbedtls_blowfish_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t blowfish_info = { + MBEDTLS_CIPHER_ID_BLOWFISH, + blowfish_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + blowfish_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + blowfish_crypt_cfb64_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + blowfish_crypt_ctr_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + blowfish_setkey_wrap, + blowfish_setkey_wrap, + blowfish_ctx_alloc, + blowfish_ctx_free +}; + +static const mbedtls_cipher_info_t blowfish_ecb_info = { + MBEDTLS_CIPHER_BLOWFISH_ECB, + MBEDTLS_MODE_ECB, + 128, + "BLOWFISH-ECB", + 0, + MBEDTLS_CIPHER_VARIABLE_KEY_LEN, + 8, + &blowfish_info +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t blowfish_cbc_info = { + MBEDTLS_CIPHER_BLOWFISH_CBC, + MBEDTLS_MODE_CBC, + 128, + "BLOWFISH-CBC", + 8, + MBEDTLS_CIPHER_VARIABLE_KEY_LEN, + 8, + &blowfish_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static const mbedtls_cipher_info_t blowfish_cfb64_info = { + MBEDTLS_CIPHER_BLOWFISH_CFB64, + MBEDTLS_MODE_CFB, + 128, + "BLOWFISH-CFB64", + 8, + MBEDTLS_CIPHER_VARIABLE_KEY_LEN, + 8, + &blowfish_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static const mbedtls_cipher_info_t blowfish_ctr_info = { + MBEDTLS_CIPHER_BLOWFISH_CTR, + MBEDTLS_MODE_CTR, + 128, + "BLOWFISH-CTR", + 8, + MBEDTLS_CIPHER_VARIABLE_KEY_LEN, + 8, + &blowfish_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CTR */ +#endif /* MBEDTLS_BLOWFISH_C */ + +#if defined(MBEDTLS_ARC4_C) +static int arc4_crypt_stream_wrap( void *ctx, size_t length, + const unsigned char *input, + unsigned char *output ) +{ + return( mbedtls_arc4_crypt( (mbedtls_arc4_context *) ctx, length, input, output ) ); +} + +static int arc4_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + /* we get key_bitlen in bits, arc4 expects it in bytes */ + if( key_bitlen % 8 != 0 ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + mbedtls_arc4_setup( (mbedtls_arc4_context *) ctx, key, key_bitlen / 8 ); + return( 0 ); +} + +static void * arc4_ctx_alloc( void ) +{ + mbedtls_arc4_context *ctx; + ctx = mbedtls_calloc( 1, sizeof( mbedtls_arc4_context ) ); + + if( ctx == NULL ) + return( NULL ); + + mbedtls_arc4_init( ctx ); + + return( ctx ); +} + +static void arc4_ctx_free( void *ctx ) +{ + mbedtls_arc4_free( (mbedtls_arc4_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t arc4_base_info = { + MBEDTLS_CIPHER_ID_ARC4, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + arc4_crypt_stream_wrap, +#endif + arc4_setkey_wrap, + arc4_setkey_wrap, + arc4_ctx_alloc, + arc4_ctx_free +}; + +static const mbedtls_cipher_info_t arc4_128_info = { + MBEDTLS_CIPHER_ARC4_128, + MBEDTLS_MODE_STREAM, + 128, + "ARC4-128", + 0, + 0, + 1, + &arc4_base_info +}; +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_CHACHA20_C) + +static int chacha20_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + if( key_bitlen != 256U ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if ( 0 != mbedtls_chacha20_setkey( (mbedtls_chacha20_context*)ctx, key ) ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + return( 0 ); +} + +static int chacha20_stream_wrap( void *ctx, size_t length, + const unsigned char *input, + unsigned char *output ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + ret = mbedtls_chacha20_update( ctx, length, input, output ); + if( ret == MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + return( ret ); +} + +static void * chacha20_ctx_alloc( void ) +{ + mbedtls_chacha20_context *ctx; + ctx = mbedtls_calloc( 1, sizeof( mbedtls_chacha20_context ) ); + + if( ctx == NULL ) + return( NULL ); + + mbedtls_chacha20_init( ctx ); + + return( ctx ); +} + +static void chacha20_ctx_free( void *ctx ) +{ + mbedtls_chacha20_free( (mbedtls_chacha20_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t chacha20_base_info = { + MBEDTLS_CIPHER_ID_CHACHA20, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + chacha20_stream_wrap, +#endif + chacha20_setkey_wrap, + chacha20_setkey_wrap, + chacha20_ctx_alloc, + chacha20_ctx_free +}; +static const mbedtls_cipher_info_t chacha20_info = { + MBEDTLS_CIPHER_CHACHA20, + MBEDTLS_MODE_STREAM, + 256, + "CHACHA20", + 12, + 0, + 1, + &chacha20_base_info +}; +#endif /* MBEDTLS_CHACHA20_C */ + +#if defined(MBEDTLS_CHACHAPOLY_C) + +static int chachapoly_setkey_wrap( void *ctx, + const unsigned char *key, + unsigned int key_bitlen ) +{ + if( key_bitlen != 256U ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if ( 0 != mbedtls_chachapoly_setkey( (mbedtls_chachapoly_context*)ctx, key ) ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + return( 0 ); +} + +static void * chachapoly_ctx_alloc( void ) +{ + mbedtls_chachapoly_context *ctx; + ctx = mbedtls_calloc( 1, sizeof( mbedtls_chachapoly_context ) ); + + if( ctx == NULL ) + return( NULL ); + + mbedtls_chachapoly_init( ctx ); + + return( ctx ); +} + +static void chachapoly_ctx_free( void *ctx ) +{ + mbedtls_chachapoly_free( (mbedtls_chachapoly_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t chachapoly_base_info = { + MBEDTLS_CIPHER_ID_CHACHA20, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + chachapoly_setkey_wrap, + chachapoly_setkey_wrap, + chachapoly_ctx_alloc, + chachapoly_ctx_free +}; +static const mbedtls_cipher_info_t chachapoly_info = { + MBEDTLS_CIPHER_CHACHA20_POLY1305, + MBEDTLS_MODE_CHACHAPOLY, + 256, + "CHACHA20-POLY1305", + 12, + 0, + 1, + &chachapoly_base_info +}; +#endif /* MBEDTLS_CHACHAPOLY_C */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +static int null_crypt_stream( void *ctx, size_t length, + const unsigned char *input, + unsigned char *output ) +{ + ((void) ctx); + memmove( output, input, length ); + return( 0 ); +} + +static int null_setkey( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) ctx); + ((void) key); + ((void) key_bitlen); + + return( 0 ); +} + +static void * null_ctx_alloc( void ) +{ + return( (void *) 1 ); +} + +static void null_ctx_free( void *ctx ) +{ + ((void) ctx); +} + +static const mbedtls_cipher_base_t null_base_info = { + MBEDTLS_CIPHER_ID_NULL, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + null_crypt_stream, +#endif + null_setkey, + null_setkey, + null_ctx_alloc, + null_ctx_free +}; + +static const mbedtls_cipher_info_t null_cipher_info = { + MBEDTLS_CIPHER_NULL, + MBEDTLS_MODE_STREAM, + 0, + "NULL", + 0, + 0, + 1, + &null_base_info +}; +#endif /* defined(MBEDTLS_CIPHER_NULL_CIPHER) */ + +#if defined(MBEDTLS_NIST_KW_C) +static void *kw_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_nist_kw_context ) ); + + if( ctx != NULL ) + mbedtls_nist_kw_init( (mbedtls_nist_kw_context *) ctx ); + + return( ctx ); +} + +static void kw_ctx_free( void *ctx ) +{ + mbedtls_nist_kw_free( ctx ); + mbedtls_free( ctx ); +} + +static int kw_aes_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_nist_kw_setkey( (mbedtls_nist_kw_context *) ctx, + MBEDTLS_CIPHER_ID_AES, key, key_bitlen, 1 ); +} + +static int kw_aes_setkey_unwrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_nist_kw_setkey( (mbedtls_nist_kw_context *) ctx, + MBEDTLS_CIPHER_ID_AES, key, key_bitlen, 0 ); +} + +static const mbedtls_cipher_base_t kw_aes_info = { + MBEDTLS_CIPHER_ID_AES, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + kw_aes_setkey_wrap, + kw_aes_setkey_unwrap, + kw_ctx_alloc, + kw_ctx_free, +}; + +static const mbedtls_cipher_info_t aes_128_nist_kw_info = { + MBEDTLS_CIPHER_AES_128_KW, + MBEDTLS_MODE_KW, + 128, + "AES-128-KW", + 0, + 0, + 16, + &kw_aes_info +}; + +static const mbedtls_cipher_info_t aes_192_nist_kw_info = { + MBEDTLS_CIPHER_AES_192_KW, + MBEDTLS_MODE_KW, + 192, + "AES-192-KW", + 0, + 0, + 16, + &kw_aes_info +}; + +static const mbedtls_cipher_info_t aes_256_nist_kw_info = { + MBEDTLS_CIPHER_AES_256_KW, + MBEDTLS_MODE_KW, + 256, + "AES-256-KW", + 0, + 0, + 16, + &kw_aes_info +}; + +static const mbedtls_cipher_info_t aes_128_nist_kwp_info = { + MBEDTLS_CIPHER_AES_128_KWP, + MBEDTLS_MODE_KWP, + 128, + "AES-128-KWP", + 0, + 0, + 16, + &kw_aes_info +}; + +static const mbedtls_cipher_info_t aes_192_nist_kwp_info = { + MBEDTLS_CIPHER_AES_192_KWP, + MBEDTLS_MODE_KWP, + 192, + "AES-192-KWP", + 0, + 0, + 16, + &kw_aes_info +}; + +static const mbedtls_cipher_info_t aes_256_nist_kwp_info = { + MBEDTLS_CIPHER_AES_256_KWP, + MBEDTLS_MODE_KWP, + 256, + "AES-256-KWP", + 0, + 0, + 16, + &kw_aes_info +}; +#endif /* MBEDTLS_NIST_KW_C */ + +const mbedtls_cipher_definition_t mbedtls_cipher_definitions[] = +{ +#if defined(MBEDTLS_AES_C) + { MBEDTLS_CIPHER_AES_128_ECB, &aes_128_ecb_info }, + { MBEDTLS_CIPHER_AES_192_ECB, &aes_192_ecb_info }, + { MBEDTLS_CIPHER_AES_256_ECB, &aes_256_ecb_info }, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_CIPHER_AES_128_CBC, &aes_128_cbc_info }, + { MBEDTLS_CIPHER_AES_192_CBC, &aes_192_cbc_info }, + { MBEDTLS_CIPHER_AES_256_CBC, &aes_256_cbc_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + { MBEDTLS_CIPHER_AES_128_CFB128, &aes_128_cfb128_info }, + { MBEDTLS_CIPHER_AES_192_CFB128, &aes_192_cfb128_info }, + { MBEDTLS_CIPHER_AES_256_CFB128, &aes_256_cfb128_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + { MBEDTLS_CIPHER_AES_128_OFB, &aes_128_ofb_info }, + { MBEDTLS_CIPHER_AES_192_OFB, &aes_192_ofb_info }, + { MBEDTLS_CIPHER_AES_256_OFB, &aes_256_ofb_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + { MBEDTLS_CIPHER_AES_128_CTR, &aes_128_ctr_info }, + { MBEDTLS_CIPHER_AES_192_CTR, &aes_192_ctr_info }, + { MBEDTLS_CIPHER_AES_256_CTR, &aes_256_ctr_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + { MBEDTLS_CIPHER_AES_128_XTS, &aes_128_xts_info }, + { MBEDTLS_CIPHER_AES_256_XTS, &aes_256_xts_info }, +#endif +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_CIPHER_AES_128_GCM, &aes_128_gcm_info }, + { MBEDTLS_CIPHER_AES_192_GCM, &aes_192_gcm_info }, + { MBEDTLS_CIPHER_AES_256_GCM, &aes_256_gcm_info }, +#endif +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_CIPHER_AES_128_CCM, &aes_128_ccm_info }, + { MBEDTLS_CIPHER_AES_192_CCM, &aes_192_ccm_info }, + { MBEDTLS_CIPHER_AES_256_CCM, &aes_256_ccm_info }, +#endif +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_ARC4_C) + { MBEDTLS_CIPHER_ARC4_128, &arc4_128_info }, +#endif + +#if defined(MBEDTLS_BLOWFISH_C) + { MBEDTLS_CIPHER_BLOWFISH_ECB, &blowfish_ecb_info }, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_CIPHER_BLOWFISH_CBC, &blowfish_cbc_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + { MBEDTLS_CIPHER_BLOWFISH_CFB64, &blowfish_cfb64_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + { MBEDTLS_CIPHER_BLOWFISH_CTR, &blowfish_ctr_info }, +#endif +#endif /* MBEDTLS_BLOWFISH_C */ + +#if defined(MBEDTLS_CAMELLIA_C) + { MBEDTLS_CIPHER_CAMELLIA_128_ECB, &camellia_128_ecb_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_ECB, &camellia_192_ecb_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_ECB, &camellia_256_ecb_info }, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_CIPHER_CAMELLIA_128_CBC, &camellia_128_cbc_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_CBC, &camellia_192_cbc_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_CBC, &camellia_256_cbc_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + { MBEDTLS_CIPHER_CAMELLIA_128_CFB128, &camellia_128_cfb128_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_CFB128, &camellia_192_cfb128_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_CFB128, &camellia_256_cfb128_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + { MBEDTLS_CIPHER_CAMELLIA_128_CTR, &camellia_128_ctr_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_CTR, &camellia_192_ctr_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_CTR, &camellia_256_ctr_info }, +#endif +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_CIPHER_CAMELLIA_128_GCM, &camellia_128_gcm_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_GCM, &camellia_192_gcm_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_GCM, &camellia_256_gcm_info }, +#endif +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_CIPHER_CAMELLIA_128_CCM, &camellia_128_ccm_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_CCM, &camellia_192_ccm_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_CCM, &camellia_256_ccm_info }, +#endif +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_ARIA_C) + { MBEDTLS_CIPHER_ARIA_128_ECB, &aria_128_ecb_info }, + { MBEDTLS_CIPHER_ARIA_192_ECB, &aria_192_ecb_info }, + { MBEDTLS_CIPHER_ARIA_256_ECB, &aria_256_ecb_info }, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_CIPHER_ARIA_128_CBC, &aria_128_cbc_info }, + { MBEDTLS_CIPHER_ARIA_192_CBC, &aria_192_cbc_info }, + { MBEDTLS_CIPHER_ARIA_256_CBC, &aria_256_cbc_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + { MBEDTLS_CIPHER_ARIA_128_CFB128, &aria_128_cfb128_info }, + { MBEDTLS_CIPHER_ARIA_192_CFB128, &aria_192_cfb128_info }, + { MBEDTLS_CIPHER_ARIA_256_CFB128, &aria_256_cfb128_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + { MBEDTLS_CIPHER_ARIA_128_CTR, &aria_128_ctr_info }, + { MBEDTLS_CIPHER_ARIA_192_CTR, &aria_192_ctr_info }, + { MBEDTLS_CIPHER_ARIA_256_CTR, &aria_256_ctr_info }, +#endif +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_CIPHER_ARIA_128_GCM, &aria_128_gcm_info }, + { MBEDTLS_CIPHER_ARIA_192_GCM, &aria_192_gcm_info }, + { MBEDTLS_CIPHER_ARIA_256_GCM, &aria_256_gcm_info }, +#endif +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_CIPHER_ARIA_128_CCM, &aria_128_ccm_info }, + { MBEDTLS_CIPHER_ARIA_192_CCM, &aria_192_ccm_info }, + { MBEDTLS_CIPHER_ARIA_256_CCM, &aria_256_ccm_info }, +#endif +#endif /* MBEDTLS_ARIA_C */ + +#if defined(MBEDTLS_DES_C) + { MBEDTLS_CIPHER_DES_ECB, &des_ecb_info }, + { MBEDTLS_CIPHER_DES_EDE_ECB, &des_ede_ecb_info }, + { MBEDTLS_CIPHER_DES_EDE3_ECB, &des_ede3_ecb_info }, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_CIPHER_DES_CBC, &des_cbc_info }, + { MBEDTLS_CIPHER_DES_EDE_CBC, &des_ede_cbc_info }, + { MBEDTLS_CIPHER_DES_EDE3_CBC, &des_ede3_cbc_info }, +#endif +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_CHACHA20_C) + { MBEDTLS_CIPHER_CHACHA20, &chacha20_info }, +#endif + +#if defined(MBEDTLS_CHACHAPOLY_C) + { MBEDTLS_CIPHER_CHACHA20_POLY1305, &chachapoly_info }, +#endif + +#if defined(MBEDTLS_NIST_KW_C) + { MBEDTLS_CIPHER_AES_128_KW, &aes_128_nist_kw_info }, + { MBEDTLS_CIPHER_AES_192_KW, &aes_192_nist_kw_info }, + { MBEDTLS_CIPHER_AES_256_KW, &aes_256_nist_kw_info }, + { MBEDTLS_CIPHER_AES_128_KWP, &aes_128_nist_kwp_info }, + { MBEDTLS_CIPHER_AES_192_KWP, &aes_192_nist_kwp_info }, + { MBEDTLS_CIPHER_AES_256_KWP, &aes_256_nist_kwp_info }, +#endif + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) + { MBEDTLS_CIPHER_NULL, &null_cipher_info }, +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ + + { MBEDTLS_CIPHER_NONE, NULL } +}; + +#define NUM_CIPHERS ( sizeof(mbedtls_cipher_definitions) / \ + sizeof(mbedtls_cipher_definitions[0]) ) +int mbedtls_cipher_supported[NUM_CIPHERS]; + +#endif /* MBEDTLS_CIPHER_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/cmac.c b/Android/Level4/app/src/main/c/mbedtls/library/cmac.c new file mode 100644 index 0000000..816bf13 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/cmac.c @@ -0,0 +1,1073 @@ +/** + * \file cmac.c + * + * \brief NIST SP800-38B compliant CMAC implementation for AES and 3DES + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ + +/* + * References: + * + * - NIST SP 800-38B Recommendation for Block Cipher Modes of Operation: The + * CMAC Mode for Authentication + * http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38b.pdf + * + * - RFC 4493 - The AES-CMAC Algorithm + * https://tools.ietf.org/html/rfc4493 + * + * - RFC 4615 - The Advanced Encryption Standard-Cipher-based Message + * Authentication Code-Pseudo-Random Function-128 (AES-CMAC-PRF-128) + * Algorithm for the Internet Key Exchange Protocol (IKE) + * https://tools.ietf.org/html/rfc4615 + * + * Additional test vectors: ISO/IEC 9797-1 + * + */ + +#include "common.h" + +#if defined(MBEDTLS_CMAC_C) + +#include "mbedtls/cmac.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#if defined(MBEDTLS_SELF_TEST) +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_SELF_TEST */ +#endif /* MBEDTLS_PLATFORM_C */ + +#if !defined(MBEDTLS_CMAC_ALT) || defined(MBEDTLS_SELF_TEST) + +/* + * Multiplication by u in the Galois field of GF(2^n) + * + * As explained in NIST SP 800-38B, this can be computed: + * + * If MSB(p) = 0, then p = (p << 1) + * If MSB(p) = 1, then p = (p << 1) ^ R_n + * with R_64 = 0x1B and R_128 = 0x87 + * + * Input and output MUST NOT point to the same buffer + * Block size must be 8 bytes or 16 bytes - the block sizes for DES and AES. + */ +static int cmac_multiply_by_u( unsigned char *output, + const unsigned char *input, + size_t blocksize ) +{ + const unsigned char R_128 = 0x87; + const unsigned char R_64 = 0x1B; + unsigned char R_n, mask; + unsigned char overflow = 0x00; + int i; + + if( blocksize == MBEDTLS_AES_BLOCK_SIZE ) + { + R_n = R_128; + } + else if( blocksize == MBEDTLS_DES3_BLOCK_SIZE ) + { + R_n = R_64; + } + else + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + for( i = (int)blocksize - 1; i >= 0; i-- ) + { + output[i] = input[i] << 1 | overflow; + overflow = input[i] >> 7; + } + + /* mask = ( input[0] >> 7 ) ? 0xff : 0x00 + * using bit operations to avoid branches */ + + /* MSVC has a warning about unary minus on unsigned, but this is + * well-defined and precisely what we want to do here */ +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + mask = - ( input[0] >> 7 ); +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif + + output[ blocksize - 1 ] ^= R_n & mask; + + return( 0 ); +} + +/* + * Generate subkeys + * + * - as specified by RFC 4493, section 2.3 Subkey Generation Algorithm + */ +static int cmac_generate_subkeys( mbedtls_cipher_context_t *ctx, + unsigned char* K1, unsigned char* K2 ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char L[MBEDTLS_CIPHER_BLKSIZE_MAX]; + size_t olen, block_size; + + mbedtls_platform_zeroize( L, sizeof( L ) ); + + block_size = ctx->cipher_info->block_size; + + /* Calculate Ek(0) */ + if( ( ret = mbedtls_cipher_update( ctx, L, block_size, L, &olen ) ) != 0 ) + goto exit; + + /* + * Generate K1 and K2 + */ + if( ( ret = cmac_multiply_by_u( K1, L , block_size ) ) != 0 ) + goto exit; + + if( ( ret = cmac_multiply_by_u( K2, K1 , block_size ) ) != 0 ) + goto exit; + +exit: + mbedtls_platform_zeroize( L, sizeof( L ) ); + + return( ret ); +} +#endif /* !defined(MBEDTLS_CMAC_ALT) || defined(MBEDTLS_SELF_TEST) */ + +#if !defined(MBEDTLS_CMAC_ALT) +static void cmac_xor_block( unsigned char *output, const unsigned char *input1, + const unsigned char *input2, + const size_t block_size ) +{ + size_t idx; + + for( idx = 0; idx < block_size; idx++ ) + output[ idx ] = input1[ idx ] ^ input2[ idx ]; +} + +/* + * Create padded last block from (partial) last block. + * + * We can't use the padding option from the cipher layer, as it only works for + * CBC and we use ECB mode, and anyway we need to XOR K1 or K2 in addition. + */ +static void cmac_pad( unsigned char padded_block[MBEDTLS_CIPHER_BLKSIZE_MAX], + size_t padded_block_len, + const unsigned char *last_block, + size_t last_block_len ) +{ + size_t j; + + for( j = 0; j < padded_block_len; j++ ) + { + if( j < last_block_len ) + padded_block[j] = last_block[j]; + else if( j == last_block_len ) + padded_block[j] = 0x80; + else + padded_block[j] = 0x00; + } +} + +int mbedtls_cipher_cmac_starts( mbedtls_cipher_context_t *ctx, + const unsigned char *key, size_t keybits ) +{ + mbedtls_cipher_type_t type; + mbedtls_cmac_context_t *cmac_ctx; + int retval; + + if( ctx == NULL || ctx->cipher_info == NULL || key == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( ( retval = mbedtls_cipher_setkey( ctx, key, (int)keybits, + MBEDTLS_ENCRYPT ) ) != 0 ) + return( retval ); + + type = ctx->cipher_info->type; + + switch( type ) + { + case MBEDTLS_CIPHER_AES_128_ECB: + case MBEDTLS_CIPHER_AES_192_ECB: + case MBEDTLS_CIPHER_AES_256_ECB: + case MBEDTLS_CIPHER_DES_EDE3_ECB: + break; + default: + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + /* Allocated and initialise in the cipher context memory for the CMAC + * context */ + cmac_ctx = mbedtls_calloc( 1, sizeof( mbedtls_cmac_context_t ) ); + if( cmac_ctx == NULL ) + return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED ); + + ctx->cmac_ctx = cmac_ctx; + + mbedtls_platform_zeroize( cmac_ctx->state, sizeof( cmac_ctx->state ) ); + + return 0; +} + +int mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx, + const unsigned char *input, size_t ilen ) +{ + mbedtls_cmac_context_t* cmac_ctx; + unsigned char *state; + int ret = 0; + size_t n, j, olen, block_size; + + if( ctx == NULL || ctx->cipher_info == NULL || input == NULL || + ctx->cmac_ctx == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + cmac_ctx = ctx->cmac_ctx; + block_size = ctx->cipher_info->block_size; + state = ctx->cmac_ctx->state; + + /* Is there data still to process from the last call, that's greater in + * size than a block? */ + if( cmac_ctx->unprocessed_len > 0 && + ilen > block_size - cmac_ctx->unprocessed_len ) + { + memcpy( &cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len], + input, + block_size - cmac_ctx->unprocessed_len ); + + cmac_xor_block( state, cmac_ctx->unprocessed_block, state, block_size ); + + if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state, + &olen ) ) != 0 ) + { + goto exit; + } + + input += block_size - cmac_ctx->unprocessed_len; + ilen -= block_size - cmac_ctx->unprocessed_len; + cmac_ctx->unprocessed_len = 0; + } + + /* n is the number of blocks including any final partial block */ + n = ( ilen + block_size - 1 ) / block_size; + + /* Iterate across the input data in block sized chunks, excluding any + * final partial or complete block */ + for( j = 1; j < n; j++ ) + { + cmac_xor_block( state, input, state, block_size ); + + if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state, + &olen ) ) != 0 ) + goto exit; + + ilen -= block_size; + input += block_size; + } + + /* If there is data left over that wasn't aligned to a block */ + if( ilen > 0 ) + { + memcpy( &cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len], + input, + ilen ); + cmac_ctx->unprocessed_len += ilen; + } + +exit: + return( ret ); +} + +int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx, + unsigned char *output ) +{ + mbedtls_cmac_context_t* cmac_ctx; + unsigned char *state, *last_block; + unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX]; + unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX]; + unsigned char M_last[MBEDTLS_CIPHER_BLKSIZE_MAX]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t olen, block_size; + + if( ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL || + output == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + cmac_ctx = ctx->cmac_ctx; + block_size = ctx->cipher_info->block_size; + state = cmac_ctx->state; + + mbedtls_platform_zeroize( K1, sizeof( K1 ) ); + mbedtls_platform_zeroize( K2, sizeof( K2 ) ); + cmac_generate_subkeys( ctx, K1, K2 ); + + last_block = cmac_ctx->unprocessed_block; + + /* Calculate last block */ + if( cmac_ctx->unprocessed_len < block_size ) + { + cmac_pad( M_last, block_size, last_block, cmac_ctx->unprocessed_len ); + cmac_xor_block( M_last, M_last, K2, block_size ); + } + else + { + /* Last block is complete block */ + cmac_xor_block( M_last, last_block, K1, block_size ); + } + + + cmac_xor_block( state, M_last, state, block_size ); + if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state, + &olen ) ) != 0 ) + { + goto exit; + } + + memcpy( output, state, block_size ); + +exit: + /* Wipe the generated keys on the stack, and any other transients to avoid + * side channel leakage */ + mbedtls_platform_zeroize( K1, sizeof( K1 ) ); + mbedtls_platform_zeroize( K2, sizeof( K2 ) ); + + cmac_ctx->unprocessed_len = 0; + mbedtls_platform_zeroize( cmac_ctx->unprocessed_block, + sizeof( cmac_ctx->unprocessed_block ) ); + + mbedtls_platform_zeroize( state, MBEDTLS_CIPHER_BLKSIZE_MAX ); + return( ret ); +} + +int mbedtls_cipher_cmac_reset( mbedtls_cipher_context_t *ctx ) +{ + mbedtls_cmac_context_t* cmac_ctx; + + if( ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + cmac_ctx = ctx->cmac_ctx; + + /* Reset the internal state */ + cmac_ctx->unprocessed_len = 0; + mbedtls_platform_zeroize( cmac_ctx->unprocessed_block, + sizeof( cmac_ctx->unprocessed_block ) ); + mbedtls_platform_zeroize( cmac_ctx->state, + sizeof( cmac_ctx->state ) ); + + return( 0 ); +} + +int mbedtls_cipher_cmac( const mbedtls_cipher_info_t *cipher_info, + const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + mbedtls_cipher_context_t ctx; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( cipher_info == NULL || key == NULL || input == NULL || output == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + mbedtls_cipher_init( &ctx ); + + if( ( ret = mbedtls_cipher_setup( &ctx, cipher_info ) ) != 0 ) + goto exit; + + ret = mbedtls_cipher_cmac_starts( &ctx, key, keylen ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_cipher_cmac_update( &ctx, input, ilen ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_cipher_cmac_finish( &ctx, output ); + +exit: + mbedtls_cipher_free( &ctx ); + + return( ret ); +} + +#if defined(MBEDTLS_AES_C) +/* + * Implementation of AES-CMAC-PRF-128 defined in RFC 4615 + */ +int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_length, + const unsigned char *input, size_t in_len, + unsigned char *output ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const mbedtls_cipher_info_t *cipher_info; + unsigned char zero_key[MBEDTLS_AES_BLOCK_SIZE]; + unsigned char int_key[MBEDTLS_AES_BLOCK_SIZE]; + + if( key == NULL || input == NULL || output == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + cipher_info = mbedtls_cipher_info_from_type( MBEDTLS_CIPHER_AES_128_ECB ); + if( cipher_info == NULL ) + { + /* Failing at this point must be due to a build issue */ + ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; + goto exit; + } + + if( key_length == MBEDTLS_AES_BLOCK_SIZE ) + { + /* Use key as is */ + memcpy( int_key, key, MBEDTLS_AES_BLOCK_SIZE ); + } + else + { + memset( zero_key, 0, MBEDTLS_AES_BLOCK_SIZE ); + + ret = mbedtls_cipher_cmac( cipher_info, zero_key, 128, key, + key_length, int_key ); + if( ret != 0 ) + goto exit; + } + + ret = mbedtls_cipher_cmac( cipher_info, int_key, 128, input, in_len, + output ); + +exit: + mbedtls_platform_zeroize( int_key, sizeof( int_key ) ); + + return( ret ); +} +#endif /* MBEDTLS_AES_C */ + +#endif /* !MBEDTLS_CMAC_ALT */ + +#if defined(MBEDTLS_SELF_TEST) +/* + * CMAC test data for SP800-38B + * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/AES_CMAC.pdf + * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/TDES_CMAC.pdf + * + * AES-CMAC-PRF-128 test data from RFC 4615 + * https://tools.ietf.org/html/rfc4615#page-4 + */ + +#define NB_CMAC_TESTS_PER_KEY 4 +#define NB_PRF_TESTS 3 + +#if defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) +/* All CMAC test inputs are truncated from the same 64 byte buffer. */ +static const unsigned char test_message[] = { + /* PT */ + 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 +}; +#endif /* MBEDTLS_AES_C || MBEDTLS_DES_C */ + +#if defined(MBEDTLS_AES_C) +/* Truncation point of message for AES CMAC tests */ +static const unsigned int aes_message_lengths[NB_CMAC_TESTS_PER_KEY] = { + /* Mlen */ + 0, + 16, + 20, + 64 +}; + +/* CMAC-AES128 Test Data */ +static const unsigned char aes_128_key[16] = { + 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c +}; +static const unsigned char aes_128_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = { + { + /* K1 */ + 0xfb, 0xee, 0xd6, 0x18, 0x35, 0x71, 0x33, 0x66, + 0x7c, 0x85, 0xe0, 0x8f, 0x72, 0x36, 0xa8, 0xde + }, + { + /* K2 */ + 0xf7, 0xdd, 0xac, 0x30, 0x6a, 0xe2, 0x66, 0xcc, + 0xf9, 0x0b, 0xc1, 0x1e, 0xe4, 0x6d, 0x51, 0x3b + } +}; +static const unsigned char aes_128_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = { + { + /* Example #1 */ + 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28, + 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46 + }, + { + /* Example #2 */ + 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44, + 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c + }, + { + /* Example #3 */ + 0x7d, 0x85, 0x44, 0x9e, 0xa6, 0xea, 0x19, 0xc8, + 0x23, 0xa7, 0xbf, 0x78, 0x83, 0x7d, 0xfa, 0xde + }, + { + /* Example #4 */ + 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92, + 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe + } +}; + +/* CMAC-AES192 Test Data */ +static const unsigned char aes_192_key[24] = { + 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, + 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5, + 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b +}; +static const unsigned char aes_192_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = { + { + /* K1 */ + 0x44, 0x8a, 0x5b, 0x1c, 0x93, 0x51, 0x4b, 0x27, + 0x3e, 0xe6, 0x43, 0x9d, 0xd4, 0xda, 0xa2, 0x96 + }, + { + /* K2 */ + 0x89, 0x14, 0xb6, 0x39, 0x26, 0xa2, 0x96, 0x4e, + 0x7d, 0xcc, 0x87, 0x3b, 0xa9, 0xb5, 0x45, 0x2c + } +}; +static const unsigned char aes_192_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = { + { + /* Example #1 */ + 0xd1, 0x7d, 0xdf, 0x46, 0xad, 0xaa, 0xcd, 0xe5, + 0x31, 0xca, 0xc4, 0x83, 0xde, 0x7a, 0x93, 0x67 + }, + { + /* Example #2 */ + 0x9e, 0x99, 0xa7, 0xbf, 0x31, 0xe7, 0x10, 0x90, + 0x06, 0x62, 0xf6, 0x5e, 0x61, 0x7c, 0x51, 0x84 + }, + { + /* Example #3 */ + 0x3d, 0x75, 0xc1, 0x94, 0xed, 0x96, 0x07, 0x04, + 0x44, 0xa9, 0xfa, 0x7e, 0xc7, 0x40, 0xec, 0xf8 + }, + { + /* Example #4 */ + 0xa1, 0xd5, 0xdf, 0x0e, 0xed, 0x79, 0x0f, 0x79, + 0x4d, 0x77, 0x58, 0x96, 0x59, 0xf3, 0x9a, 0x11 + } +}; + +/* CMAC-AES256 Test Data */ +static const unsigned char aes_256_key[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 +}; +static const unsigned char aes_256_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = { + { + /* K1 */ + 0xca, 0xd1, 0xed, 0x03, 0x29, 0x9e, 0xed, 0xac, + 0x2e, 0x9a, 0x99, 0x80, 0x86, 0x21, 0x50, 0x2f + }, + { + /* K2 */ + 0x95, 0xa3, 0xda, 0x06, 0x53, 0x3d, 0xdb, 0x58, + 0x5d, 0x35, 0x33, 0x01, 0x0c, 0x42, 0xa0, 0xd9 + } +}; +static const unsigned char aes_256_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = { + { + /* Example #1 */ + 0x02, 0x89, 0x62, 0xf6, 0x1b, 0x7b, 0xf8, 0x9e, + 0xfc, 0x6b, 0x55, 0x1f, 0x46, 0x67, 0xd9, 0x83 + }, + { + /* Example #2 */ + 0x28, 0xa7, 0x02, 0x3f, 0x45, 0x2e, 0x8f, 0x82, + 0xbd, 0x4b, 0xf2, 0x8d, 0x8c, 0x37, 0xc3, 0x5c + }, + { + /* Example #3 */ + 0x15, 0x67, 0x27, 0xdc, 0x08, 0x78, 0x94, 0x4a, + 0x02, 0x3c, 0x1f, 0xe0, 0x3b, 0xad, 0x6d, 0x93 + }, + { + /* Example #4 */ + 0xe1, 0x99, 0x21, 0x90, 0x54, 0x9f, 0x6e, 0xd5, + 0x69, 0x6a, 0x2c, 0x05, 0x6c, 0x31, 0x54, 0x10 + } +}; +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_DES_C) +/* Truncation point of message for 3DES CMAC tests */ +static const unsigned int des3_message_lengths[NB_CMAC_TESTS_PER_KEY] = { + 0, + 16, + 20, + 32 +}; + +/* CMAC-TDES (Generation) - 2 Key Test Data */ +static const unsigned char des3_2key_key[24] = { + /* Key1 */ + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + /* Key2 */ + 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xEF, 0x01, + /* Key3 */ + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef +}; +static const unsigned char des3_2key_subkeys[2][8] = { + { + /* K1 */ + 0x0d, 0xd2, 0xcb, 0x7a, 0x3d, 0x88, 0x88, 0xd9 + }, + { + /* K2 */ + 0x1b, 0xa5, 0x96, 0xf4, 0x7b, 0x11, 0x11, 0xb2 + } +}; +static const unsigned char des3_2key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE] = { + { + /* Sample #1 */ + 0x79, 0xce, 0x52, 0xa7, 0xf7, 0x86, 0xa9, 0x60 + }, + { + /* Sample #2 */ + 0xcc, 0x18, 0xa0, 0xb7, 0x9a, 0xf2, 0x41, 0x3b + }, + { + /* Sample #3 */ + 0xc0, 0x6d, 0x37, 0x7e, 0xcd, 0x10, 0x19, 0x69 + }, + { + /* Sample #4 */ + 0x9c, 0xd3, 0x35, 0x80, 0xf9, 0xb6, 0x4d, 0xfb + } +}; + +/* CMAC-TDES (Generation) - 3 Key Test Data */ +static const unsigned char des3_3key_key[24] = { + /* Key1 */ + 0x01, 0x23, 0x45, 0x67, 0x89, 0xaa, 0xcd, 0xef, + /* Key2 */ + 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, + /* Key3 */ + 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23 +}; +static const unsigned char des3_3key_subkeys[2][8] = { + { + /* K1 */ + 0x9d, 0x74, 0xe7, 0x39, 0x33, 0x17, 0x96, 0xc0 + }, + { + /* K2 */ + 0x3a, 0xe9, 0xce, 0x72, 0x66, 0x2f, 0x2d, 0x9b + } +}; +static const unsigned char des3_3key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE] = { + { + /* Sample #1 */ + 0x7d, 0xb0, 0xd3, 0x7d, 0xf9, 0x36, 0xc5, 0x50 + }, + { + /* Sample #2 */ + 0x30, 0x23, 0x9c, 0xf1, 0xf5, 0x2e, 0x66, 0x09 + }, + { + /* Sample #3 */ + 0x6c, 0x9f, 0x3e, 0xe4, 0x92, 0x3f, 0x6b, 0xe2 + }, + { + /* Sample #4 */ + 0x99, 0x42, 0x9b, 0xd0, 0xbF, 0x79, 0x04, 0xe5 + } +}; + +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_AES_C) +/* AES AES-CMAC-PRF-128 Test Data */ +static const unsigned char PRFK[] = { + /* Key */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0xed, 0xcb +}; + +/* Sizes in bytes */ +static const size_t PRFKlen[NB_PRF_TESTS] = { + 18, + 16, + 10 +}; + +/* Message */ +static const unsigned char PRFM[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13 +}; + +static const unsigned char PRFT[NB_PRF_TESTS][16] = { + { + 0x84, 0xa3, 0x48, 0xa4, 0xa4, 0x5d, 0x23, 0x5b, + 0xab, 0xff, 0xfc, 0x0d, 0x2b, 0x4d, 0xa0, 0x9a + }, + { + 0x98, 0x0a, 0xe8, 0x7b, 0x5f, 0x4c, 0x9c, 0x52, + 0x14, 0xf5, 0xb6, 0xa8, 0x45, 0x5e, 0x4c, 0x2d + }, + { + 0x29, 0x0d, 0x9e, 0x11, 0x2e, 0xdb, 0x09, 0xee, + 0x14, 0x1f, 0xcf, 0x64, 0xc0, 0xb7, 0x2f, 0x3d + } +}; +#endif /* MBEDTLS_AES_C */ + +static int cmac_test_subkeys( int verbose, + const char* testname, + const unsigned char* key, + int keybits, + const unsigned char* subkeys, + mbedtls_cipher_type_t cipher_type, + int block_size, + int num_tests ) +{ + int i, ret = 0; + mbedtls_cipher_context_t ctx; + const mbedtls_cipher_info_t *cipher_info; + unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX]; + unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX]; + + cipher_info = mbedtls_cipher_info_from_type( cipher_type ); + if( cipher_info == NULL ) + { + /* Failing at this point must be due to a build issue */ + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + } + + for( i = 0; i < num_tests; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " %s CMAC subkey #%d: ", testname, i + 1 ); + + mbedtls_cipher_init( &ctx ); + + if( ( ret = mbedtls_cipher_setup( &ctx, cipher_info ) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "test execution failed\n" ); + + goto cleanup; + } + + if( ( ret = mbedtls_cipher_setkey( &ctx, key, keybits, + MBEDTLS_ENCRYPT ) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "test execution failed\n" ); + + goto cleanup; + } + + ret = cmac_generate_subkeys( &ctx, K1, K2 ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + goto cleanup; + } + + if( ( ret = memcmp( K1, subkeys, block_size ) ) != 0 || + ( ret = memcmp( K2, &subkeys[block_size], block_size ) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + mbedtls_cipher_free( &ctx ); + } + + ret = 0; + goto exit; + +cleanup: + mbedtls_cipher_free( &ctx ); + +exit: + return( ret ); +} + +static int cmac_test_wth_cipher( int verbose, + const char* testname, + const unsigned char* key, + int keybits, + const unsigned char* messages, + const unsigned int message_lengths[4], + const unsigned char* expected_result, + mbedtls_cipher_type_t cipher_type, + int block_size, + int num_tests ) +{ + const mbedtls_cipher_info_t *cipher_info; + int i, ret = 0; + unsigned char output[MBEDTLS_CIPHER_BLKSIZE_MAX]; + + cipher_info = mbedtls_cipher_info_from_type( cipher_type ); + if( cipher_info == NULL ) + { + /* Failing at this point must be due to a build issue */ + ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; + goto exit; + } + + for( i = 0; i < num_tests; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " %s CMAC #%d: ", testname, i + 1 ); + + if( ( ret = mbedtls_cipher_cmac( cipher_info, key, keybits, messages, + message_lengths[i], output ) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + goto exit; + } + + if( ( ret = memcmp( output, &expected_result[i * block_size], block_size ) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + ret = 0; + +exit: + return( ret ); +} + +#if defined(MBEDTLS_AES_C) +static int test_aes128_cmac_prf( int verbose ) +{ + int i; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char output[MBEDTLS_AES_BLOCK_SIZE]; + + for( i = 0; i < NB_PRF_TESTS; i++ ) + { + mbedtls_printf( " AES CMAC 128 PRF #%d: ", i ); + ret = mbedtls_aes_cmac_prf_128( PRFK, PRFKlen[i], PRFM, 20, output ); + if( ret != 0 || + memcmp( output, PRFT[i], MBEDTLS_AES_BLOCK_SIZE ) != 0 ) + { + + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( ret ); + } + else if( verbose != 0 ) + { + mbedtls_printf( "passed\n" ); + } + } + return( ret ); +} +#endif /* MBEDTLS_AES_C */ + +int mbedtls_cmac_self_test( int verbose ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + +#if defined(MBEDTLS_AES_C) + /* AES-128 */ + if( ( ret = cmac_test_subkeys( verbose, + "AES 128", + aes_128_key, + 128, + (const unsigned char*)aes_128_subkeys, + MBEDTLS_CIPHER_AES_128_ECB, + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cmac_test_wth_cipher( verbose, + "AES 128", + aes_128_key, + 128, + test_message, + aes_message_lengths, + (const unsigned char*)aes_128_expected_result, + MBEDTLS_CIPHER_AES_128_ECB, + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + /* AES-192 */ + if( ( ret = cmac_test_subkeys( verbose, + "AES 192", + aes_192_key, + 192, + (const unsigned char*)aes_192_subkeys, + MBEDTLS_CIPHER_AES_192_ECB, + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cmac_test_wth_cipher( verbose, + "AES 192", + aes_192_key, + 192, + test_message, + aes_message_lengths, + (const unsigned char*)aes_192_expected_result, + MBEDTLS_CIPHER_AES_192_ECB, + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + /* AES-256 */ + if( ( ret = cmac_test_subkeys( verbose, + "AES 256", + aes_256_key, + 256, + (const unsigned char*)aes_256_subkeys, + MBEDTLS_CIPHER_AES_256_ECB, + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cmac_test_wth_cipher ( verbose, + "AES 256", + aes_256_key, + 256, + test_message, + aes_message_lengths, + (const unsigned char*)aes_256_expected_result, + MBEDTLS_CIPHER_AES_256_ECB, + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_DES_C) + /* 3DES 2 key */ + if( ( ret = cmac_test_subkeys( verbose, + "3DES 2 key", + des3_2key_key, + 192, + (const unsigned char*)des3_2key_subkeys, + MBEDTLS_CIPHER_DES_EDE3_ECB, + MBEDTLS_DES3_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cmac_test_wth_cipher( verbose, + "3DES 2 key", + des3_2key_key, + 192, + test_message, + des3_message_lengths, + (const unsigned char*)des3_2key_expected_result, + MBEDTLS_CIPHER_DES_EDE3_ECB, + MBEDTLS_DES3_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + /* 3DES 3 key */ + if( ( ret = cmac_test_subkeys( verbose, + "3DES 3 key", + des3_3key_key, + 192, + (const unsigned char*)des3_3key_subkeys, + MBEDTLS_CIPHER_DES_EDE3_ECB, + MBEDTLS_DES3_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cmac_test_wth_cipher( verbose, + "3DES 3 key", + des3_3key_key, + 192, + test_message, + des3_message_lengths, + (const unsigned char*)des3_3key_expected_result, + MBEDTLS_CIPHER_DES_EDE3_ECB, + MBEDTLS_DES3_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_AES_C) + if( ( ret = test_aes128_cmac_prf( verbose ) ) != 0 ) + return( ret ); +#endif /* MBEDTLS_AES_C */ + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_CMAC_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/common.h b/Android/Level4/app/src/main/c/mbedtls/library/common.h new file mode 100644 index 0000000..5845766 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/common.h @@ -0,0 +1,53 @@ +/** + * \file common.h + * + * \brief Utility macros for internal use in the library + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_LIBRARY_COMMON_H +#define MBEDTLS_LIBRARY_COMMON_H + +#if defined(MBEDTLS_CONFIG_FILE) +#include MBEDTLS_CONFIG_FILE +#else +#include "mbedtls/config.h" +#endif + +/** Helper to define a function as static except when building invasive tests. + * + * If a function is only used inside its own source file and should be + * declared `static` to allow the compiler to optimize for code size, + * but that function has unit tests, define it with + * ``` + * MBEDTLS_STATIC_TESTABLE int mbedtls_foo(...) { ... } + * ``` + * and declare it in a header in the `library/` directory with + * ``` + * #if defined(MBEDTLS_TEST_HOOKS) + * int mbedtls_foo(...); + * #endif + * ``` + */ +#if defined(MBEDTLS_TEST_HOOKS) +#define MBEDTLS_STATIC_TESTABLE +#else +#define MBEDTLS_STATIC_TESTABLE static +#endif + +#endif /* MBEDTLS_LIBRARY_COMMON_H */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/ctr_drbg.c b/Android/Level4/app/src/main/c/mbedtls/library/ctr_drbg.c new file mode 100644 index 0000000..54843a7 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/ctr_drbg.c @@ -0,0 +1,810 @@ +/* + * CTR_DRBG implementation based on AES-256 (NIST SP 800-90) + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ +/* + * The NIST SP 800-90 DRBGs are described in the following publication. + * + * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf + */ + +#include "common.h" + +#if defined(MBEDTLS_CTR_DRBG_C) + +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +/* + * CTR_DRBG context initialization + */ +void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) ); + /* Indicate that the entropy nonce length is not set explicitly. + * See mbedtls_ctr_drbg_set_nonce_len(). */ + ctx->reseed_counter = -1; + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif +} + +void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx ) +{ + if( ctx == NULL ) + return; + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free( &ctx->mutex ); +#endif + mbedtls_aes_free( &ctx->aes_ctx ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) ); +} + +void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, + int resistance ) +{ + ctx->prediction_resistance = resistance; +} + +void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, + size_t len ) +{ + ctx->entropy_len = len; +} + +int mbedtls_ctr_drbg_set_nonce_len( mbedtls_ctr_drbg_context *ctx, + size_t len ) +{ + /* If mbedtls_ctr_drbg_seed() has already been called, it's + * too late. Return the error code that's closest to making sense. */ + if( ctx->f_entropy != NULL ) + return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED ); + + if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) + return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); +#if SIZE_MAX > INT_MAX + /* This shouldn't be an issue because + * MBEDTLS_CTR_DRBG_MAX_SEED_INPUT < INT_MAX in any sensible + * configuration, but make sure anyway. */ + if( len > INT_MAX ) + return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); +#endif + + /* For backward compatibility with Mbed TLS <= 2.19, store the + * entropy nonce length in a field that already exists, but isn't + * used until after the initial seeding. */ + /* Due to the capping of len above, the value fits in an int. */ + ctx->reseed_counter = (int) len; + return( 0 ); +} + +void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, + int interval ) +{ + ctx->reseed_interval = interval; +} + +static int block_cipher_df( unsigned char *output, + const unsigned char *data, size_t data_len ) +{ + unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16]; + unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN]; + unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE]; + unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE]; + unsigned char *p, *iv; + mbedtls_aes_context aes_ctx; + int ret = 0; + + int i, j; + size_t buf_len, use_len; + + if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) + return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); + + memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 ); + mbedtls_aes_init( &aes_ctx ); + + /* + * Construct IV (16 bytes) and S in buffer + * IV = Counter (in 32-bits) padded to 16 with zeroes + * S = Length input string (in 32-bits) || Length of output (in 32-bits) || + * data || 0x80 + * (Total is padded to a multiple of 16-bytes with zeroes) + */ + p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE; + *p++ = ( data_len >> 24 ) & 0xff; + *p++ = ( data_len >> 16 ) & 0xff; + *p++ = ( data_len >> 8 ) & 0xff; + *p++ = ( data_len ) & 0xff; + p += 3; + *p++ = MBEDTLS_CTR_DRBG_SEEDLEN; + memcpy( p, data, data_len ); + p[data_len] = 0x80; + + buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1; + + for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ ) + key[i] = i; + + if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key, + MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) + { + goto exit; + } + + /* + * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data + */ + for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) + { + p = buf; + memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE ); + use_len = buf_len; + + while( use_len > 0 ) + { + for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ ) + chain[i] ^= p[i]; + p += MBEDTLS_CTR_DRBG_BLOCKSIZE; + use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? + MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len; + + if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, + chain, chain ) ) != 0 ) + { + goto exit; + } + } + + memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE ); + + /* + * Update IV + */ + buf[3]++; + } + + /* + * Do final encryption with reduced data + */ + if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp, + MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) + { + goto exit; + } + iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE; + p = output; + + for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) + { + if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, + iv, iv ) ) != 0 ) + { + goto exit; + } + memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE ); + p += MBEDTLS_CTR_DRBG_BLOCKSIZE; + } +exit: + mbedtls_aes_free( &aes_ctx ); + /* + * tidy up the stack + */ + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); + mbedtls_platform_zeroize( key, sizeof( key ) ); + mbedtls_platform_zeroize( chain, sizeof( chain ) ); + if( 0 != ret ) + { + /* + * wipe partial seed from memory + */ + mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN ); + } + + return( ret ); +} + +/* CTR_DRBG_Update (SP 800-90A §10.2.1.2) + * ctr_drbg_update_internal(ctx, provided_data) + * implements + * CTR_DRBG_Update(provided_data, Key, V) + * with inputs and outputs + * ctx->aes_ctx = Key + * ctx->counter = V + */ +static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx, + const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] ) +{ + unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN]; + unsigned char *p = tmp; + int i, j; + int ret = 0; + + memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN ); + + for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) + { + /* + * Increase counter + */ + for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- ) + if( ++ctx->counter[i - 1] != 0 ) + break; + + /* + * Crypt counter block + */ + if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, + ctx->counter, p ) ) != 0 ) + { + goto exit; + } + + p += MBEDTLS_CTR_DRBG_BLOCKSIZE; + } + + for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ ) + tmp[i] ^= data[i]; + + /* + * Update key and counter + */ + if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, + MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) + { + goto exit; + } + memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, + MBEDTLS_CTR_DRBG_BLOCKSIZE ); + +exit: + mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); + return( ret ); +} + +/* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2) + * mbedtls_ctr_drbg_update(ctx, additional, add_len) + * implements + * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string, + * security_strength) -> initial_working_state + * with inputs + * ctx->counter = all-bits-0 + * ctx->aes_ctx = context from all-bits-0 key + * additional[:add_len] = entropy_input || nonce || personalization_string + * and with outputs + * ctx = initial_working_state + */ +int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, + size_t add_len ) +{ + unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( add_len == 0 ) + return( 0 ); + + if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 ) + goto exit; + if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) + goto exit; + +exit: + mbedtls_platform_zeroize( add_input, sizeof( add_input ) ); + return( ret ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, + size_t add_len ) +{ + /* MAX_INPUT would be more logical here, but we have to match + * block_cipher_df()'s limits since we can't propagate errors */ + if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) + add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT; + (void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len ); +} +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/* CTR_DRBG_Reseed with derivation function (SP 800-90A §10.2.1.4.2) + * mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len) + * implements + * CTR_DRBG_Reseed(working_state, entropy_input, additional_input) + * -> new_working_state + * with inputs + * ctx contains working_state + * additional[:len] = additional_input + * and entropy_input comes from calling ctx->f_entropy + * for (ctx->entropy_len + nonce_len) bytes + * and with output + * ctx contains new_working_state + */ +static int mbedtls_ctr_drbg_reseed_internal( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, + size_t len, + size_t nonce_len ) +{ + unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT]; + size_t seedlen = 0; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) + return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); + if( nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len ) + return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); + if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len ) + return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); + + memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ); + + /* Gather entropy_len bytes of entropy to seed state. */ + if( 0 != ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) ) + { + return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED ); + } + seedlen += ctx->entropy_len; + + /* Gather entropy for a nonce if requested. */ + if( nonce_len != 0 ) + { + if( 0 != ctx->f_entropy( ctx->p_entropy, seed, nonce_len ) ) + { + return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED ); + } + seedlen += nonce_len; + } + + /* Add additional data if provided. */ + if( additional != NULL && len != 0 ) + { + memcpy( seed + seedlen, additional, len ); + seedlen += len; + } + + /* Reduce to 384 bits. */ + if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 ) + goto exit; + + /* Update state. */ + if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 ) + goto exit; + ctx->reseed_counter = 1; + +exit: + mbedtls_platform_zeroize( seed, sizeof( seed ) ); + return( ret ); +} + +int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, size_t len ) +{ + return( mbedtls_ctr_drbg_reseed_internal( ctx, additional, len, 0 ) ); +} + +/* Return a "good" nonce length for CTR_DRBG. The chosen nonce length + * is sufficient to achieve the maximum security strength given the key + * size and entropy length. If there is enough entropy in the initial + * call to the entropy function to serve as both the entropy input and + * the nonce, don't make a second call to get a nonce. */ +static size_t good_nonce_len( size_t entropy_len ) +{ + if( entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2 ) + return( 0 ); + else + return( ( entropy_len + 1 ) / 2 ); +} + +/* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2) + * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len) + * implements + * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string, + * security_strength) -> initial_working_state + * with inputs + * custom[:len] = nonce || personalization_string + * where entropy_input comes from f_entropy for ctx->entropy_len bytes + * and with outputs + * ctx = initial_working_state + */ +int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx, + int (*f_entropy)(void *, unsigned char *, size_t), + void *p_entropy, + const unsigned char *custom, + size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE]; + size_t nonce_len; + + memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE ); + + mbedtls_aes_init( &ctx->aes_ctx ); + + ctx->f_entropy = f_entropy; + ctx->p_entropy = p_entropy; + + if( ctx->entropy_len == 0 ) + ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN; + /* ctx->reseed_counter contains the desired amount of entropy to + * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()). + * If it's -1, indicating that the entropy nonce length was not set + * explicitly, use a sufficiently large nonce for security. */ + nonce_len = ( ctx->reseed_counter >= 0 ? + (size_t) ctx->reseed_counter : + good_nonce_len( ctx->entropy_len ) ); + + ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL; + + /* Initialize with an empty key. */ + if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, + MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) + { + return( ret ); + } + + /* Do the initial seeding. */ + if( ( ret = mbedtls_ctr_drbg_reseed_internal( ctx, custom, len, + nonce_len ) ) != 0 ) + { + return( ret ); + } + return( 0 ); +} + +/* CTR_DRBG_Generate with derivation function (SP 800-90A §10.2.1.5.2) + * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len) + * implements + * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len]) + * -> working_state_after_reseed + * if required, then + * CTR_DRBG_Generate(working_state_after_reseed, + * requested_number_of_bits, additional_input) + * -> status, returned_bits, new_working_state + * with inputs + * ctx contains working_state + * requested_number_of_bits = 8 * output_len + * additional[:add_len] = additional_input + * and entropy_input comes from calling ctx->f_entropy + * and with outputs + * status = SUCCESS (this function does the reseed internally) + * returned_bits = output[:output_len] + * ctx contains new_working_state + */ +int mbedtls_ctr_drbg_random_with_add( void *p_rng, + unsigned char *output, size_t output_len, + const unsigned char *additional, size_t add_len ) +{ + int ret = 0; + mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng; + unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; + unsigned char *p = output; + unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE]; + int i; + size_t use_len; + + if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST ) + return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG ); + + if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT ) + return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); + + memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN ); + + if( ctx->reseed_counter > ctx->reseed_interval || + ctx->prediction_resistance ) + { + if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 ) + { + return( ret ); + } + add_len = 0; + } + + if( add_len > 0 ) + { + if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 ) + goto exit; + if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) + goto exit; + } + + while( output_len > 0 ) + { + /* + * Increase counter + */ + for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- ) + if( ++ctx->counter[i - 1] != 0 ) + break; + + /* + * Crypt counter block + */ + if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, + ctx->counter, tmp ) ) != 0 ) + { + goto exit; + } + + use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) + ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len; + /* + * Copy random block to destination + */ + memcpy( p, tmp, use_len ); + p += use_len; + output_len -= use_len; + } + + if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) + goto exit; + + ctx->reseed_counter++; + +exit: + mbedtls_platform_zeroize( add_input, sizeof( add_input ) ); + mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); + return( ret ); +} + +int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, + size_t output_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 ); + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +#if defined(MBEDTLS_FS_IO) +int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, + const char *path ) +{ + int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; + FILE *f; + unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ]; + + if( ( f = fopen( path, "wb" ) ) == NULL ) + return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR ); + + if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, + MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 ) + goto exit; + + if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != + MBEDTLS_CTR_DRBG_MAX_INPUT ) + { + ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; + } + else + { + ret = 0; + } + +exit: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + + fclose( f ); + return( ret ); +} + +int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, + const char *path ) +{ + int ret = 0; + FILE *f = NULL; + size_t n; + unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ]; + unsigned char c; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR ); + + n = fread( buf, 1, sizeof( buf ), f ); + if( fread( &c, 1, 1, f ) != 0 ) + { + ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; + goto exit; + } + if( n == 0 || ferror( f ) ) + { + ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; + goto exit; + } + fclose( f ); + f = NULL; + + ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n ); + +exit: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + if( f != NULL ) + fclose( f ); + if( ret != 0 ) + return( ret ); + return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) ); +} +#endif /* MBEDTLS_FS_IO */ + +#if defined(MBEDTLS_SELF_TEST) + +static const unsigned char entropy_source_pr[96] = + { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16, + 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02, + 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b, + 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb, + 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9, + 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95, + 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63, + 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3, + 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31, + 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4, + 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56, + 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 }; + +static const unsigned char entropy_source_nopr[64] = + { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14, + 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe, + 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d, + 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20, + 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9, + 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46, + 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e, + 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e }; + +static const unsigned char nonce_pers_pr[16] = + { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2, + 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c }; + +static const unsigned char nonce_pers_nopr[16] = + { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5, + 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f }; + +#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) +static const unsigned char result_pr[16] = + { 0x95, 0x3c, 0xa5, 0xbd, 0x44, 0x1, 0x34, 0xb7, + 0x13, 0x58, 0x3e, 0x6a, 0x6c, 0x7e, 0x88, 0x8a }; + +static const unsigned char result_nopr[16] = + { 0x6c, 0x25, 0x27, 0x95, 0xa3, 0x62, 0xd6, 0xdb, + 0x90, 0xfd, 0x69, 0xb5, 0x42, 0x9, 0x4b, 0x84 }; +#else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */ +static const unsigned char result_pr[16] = + { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f, + 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 }; + +static const unsigned char result_nopr[16] = + { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88, + 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f }; +#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */ + +static size_t test_offset; +static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf, + size_t len ) +{ + const unsigned char *p = data; + memcpy( buf, p + test_offset, len ); + test_offset += len; + return( 0 ); +} + +#define CHK( c ) if( (c) != 0 ) \ + { \ + if( verbose != 0 ) \ + mbedtls_printf( "failed\n" ); \ + return( 1 ); \ + } + +/* + * Checkup routine + */ +int mbedtls_ctr_drbg_self_test( int verbose ) +{ + mbedtls_ctr_drbg_context ctx; + unsigned char buf[16]; + + mbedtls_ctr_drbg_init( &ctx ); + + /* + * Based on a NIST CTR_DRBG test vector (PR = True) + */ + if( verbose != 0 ) + mbedtls_printf( " CTR_DRBG (PR = TRUE) : " ); + + test_offset = 0; + mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 ); + mbedtls_ctr_drbg_set_nonce_len( &ctx, 0 ); + CHK( mbedtls_ctr_drbg_seed( &ctx, + ctr_drbg_self_test_entropy, + (void *) entropy_source_pr, + nonce_pers_pr, 16 ) ); + mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON ); + CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) ); + CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) ); + CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) ); + + mbedtls_ctr_drbg_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + /* + * Based on a NIST CTR_DRBG test vector (PR = FALSE) + */ + if( verbose != 0 ) + mbedtls_printf( " CTR_DRBG (PR = FALSE): " ); + + mbedtls_ctr_drbg_init( &ctx ); + + test_offset = 0; + mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 ); + mbedtls_ctr_drbg_set_nonce_len( &ctx, 0 ); + CHK( mbedtls_ctr_drbg_seed( &ctx, + ctr_drbg_self_test_entropy, + (void *) entropy_source_nopr, + nonce_pers_nopr, 16 ) ); + CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) ); + CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) ); + CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) ); + CHK( memcmp( buf, result_nopr, 16 ) ); + + mbedtls_ctr_drbg_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_CTR_DRBG_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/debug.c b/Android/Level4/app/src/main/c/mbedtls/library/debug.c new file mode 100644 index 0000000..c3384be --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/debug.c @@ -0,0 +1,433 @@ +/* + * Debugging routines + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 "common.h" + +#if defined(MBEDTLS_DEBUG_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#define mbedtls_time_t time_t +#define mbedtls_snprintf snprintf +#define mbedtls_vsnprintf vsnprintf +#endif + +#include "mbedtls/debug.h" +#include "mbedtls/error.h" + +#include +#include +#include + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#define DEBUG_BUF_SIZE 512 + +static int debug_threshold = 0; + +void mbedtls_debug_set_threshold( int threshold ) +{ + debug_threshold = threshold; +} + +/* + * All calls to f_dbg must be made via this function + */ +static inline void debug_send_line( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *str ) +{ + /* + * If in a threaded environment, we need a thread identifier. + * Since there is no portable way to get one, use the address of the ssl + * context instead, as it shouldn't be shared between threads. + */ +#if defined(MBEDTLS_THREADING_C) + char idstr[20 + DEBUG_BUF_SIZE]; /* 0x + 16 nibbles + ': ' */ + mbedtls_snprintf( idstr, sizeof( idstr ), "%p: %s", (void*)ssl, str ); + ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, idstr ); +#else + ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, str ); +#endif +} + +void mbedtls_debug_print_msg( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *format, ... ) +{ + va_list argp; + char str[DEBUG_BUF_SIZE]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( NULL == ssl || + NULL == ssl->conf || + NULL == ssl->conf->f_dbg || + level > debug_threshold ) + { + return; + } + + va_start( argp, format ); + ret = mbedtls_vsnprintf( str, DEBUG_BUF_SIZE, format, argp ); + va_end( argp ); + + if( ret >= 0 && ret < DEBUG_BUF_SIZE - 1 ) + { + str[ret] = '\n'; + str[ret + 1] = '\0'; + } + + debug_send_line( ssl, level, file, line, str ); +} + +void mbedtls_debug_print_ret( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, int ret ) +{ + char str[DEBUG_BUF_SIZE]; + + if( NULL == ssl || + NULL == ssl->conf || + NULL == ssl->conf->f_dbg || + level > debug_threshold ) + { + return; + } + + /* + * With non-blocking I/O and examples that just retry immediately, + * the logs would be quickly flooded with WANT_READ, so ignore that. + * Don't ignore WANT_WRITE however, since is is usually rare. + */ + if( ret == MBEDTLS_ERR_SSL_WANT_READ ) + return; + + mbedtls_snprintf( str, sizeof( str ), "%s() returned %d (-0x%04x)\n", + text, ret, (unsigned int) -ret ); + + debug_send_line( ssl, level, file, line, str ); +} + +void mbedtls_debug_print_buf( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, const char *text, + const unsigned char *buf, size_t len ) +{ + char str[DEBUG_BUF_SIZE]; + char txt[17]; + size_t i, idx = 0; + + if( NULL == ssl || + NULL == ssl->conf || + NULL == ssl->conf->f_dbg || + level > debug_threshold ) + { + return; + } + + mbedtls_snprintf( str + idx, sizeof( str ) - idx, "dumping '%s' (%u bytes)\n", + text, (unsigned int) len ); + + debug_send_line( ssl, level, file, line, str ); + + idx = 0; + memset( txt, 0, sizeof( txt ) ); + for( i = 0; i < len; i++ ) + { + if( i >= 4096 ) + break; + + if( i % 16 == 0 ) + { + if( i > 0 ) + { + mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %s\n", txt ); + debug_send_line( ssl, level, file, line, str ); + + idx = 0; + memset( txt, 0, sizeof( txt ) ); + } + + idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, "%04x: ", + (unsigned int) i ); + + } + + idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %02x", + (unsigned int) buf[i] ); + txt[i % 16] = ( buf[i] > 31 && buf[i] < 127 ) ? buf[i] : '.' ; + } + + if( len > 0 ) + { + for( /* i = i */; i % 16 != 0; i++ ) + idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " " ); + + mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %s\n", txt ); + debug_send_line( ssl, level, file, line, str ); + } +} + +#if defined(MBEDTLS_ECP_C) +void mbedtls_debug_print_ecp( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_ecp_point *X ) +{ + char str[DEBUG_BUF_SIZE]; + + if( NULL == ssl || + NULL == ssl->conf || + NULL == ssl->conf->f_dbg || + level > debug_threshold ) + { + return; + } + + mbedtls_snprintf( str, sizeof( str ), "%s(X)", text ); + mbedtls_debug_print_mpi( ssl, level, file, line, str, &X->X ); + + mbedtls_snprintf( str, sizeof( str ), "%s(Y)", text ); + mbedtls_debug_print_mpi( ssl, level, file, line, str, &X->Y ); +} +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_BIGNUM_C) +void mbedtls_debug_print_mpi( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_mpi *X ) +{ + char str[DEBUG_BUF_SIZE]; + int j, k, zeros = 1; + size_t i, n, idx = 0; + + if( NULL == ssl || + NULL == ssl->conf || + NULL == ssl->conf->f_dbg || + NULL == X || + level > debug_threshold ) + { + return; + } + + for( n = X->n - 1; n > 0; n-- ) + if( X->p[n] != 0 ) + break; + + for( j = ( sizeof(mbedtls_mpi_uint) << 3 ) - 1; j >= 0; j-- ) + if( ( ( X->p[n] >> j ) & 1 ) != 0 ) + break; + + mbedtls_snprintf( str + idx, sizeof( str ) - idx, "value of '%s' (%d bits) is:\n", + text, (int) ( ( n * ( sizeof(mbedtls_mpi_uint) << 3 ) ) + j + 1 ) ); + + debug_send_line( ssl, level, file, line, str ); + + idx = 0; + for( i = n + 1, j = 0; i > 0; i-- ) + { + if( zeros && X->p[i - 1] == 0 ) + continue; + + for( k = sizeof( mbedtls_mpi_uint ) - 1; k >= 0; k-- ) + { + if( zeros && ( ( X->p[i - 1] >> ( k << 3 ) ) & 0xFF ) == 0 ) + continue; + else + zeros = 0; + + if( j % 16 == 0 ) + { + if( j > 0 ) + { + mbedtls_snprintf( str + idx, sizeof( str ) - idx, "\n" ); + debug_send_line( ssl, level, file, line, str ); + idx = 0; + } + } + + idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %02x", (unsigned int) + ( X->p[i - 1] >> ( k << 3 ) ) & 0xFF ); + + j++; + } + + } + + if( zeros == 1 ) + idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " 00" ); + + mbedtls_snprintf( str + idx, sizeof( str ) - idx, "\n" ); + debug_send_line( ssl, level, file, line, str ); +} +#endif /* MBEDTLS_BIGNUM_C */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +static void debug_print_pk( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_pk_context *pk ) +{ + size_t i; + mbedtls_pk_debug_item items[MBEDTLS_PK_DEBUG_MAX_ITEMS]; + char name[16]; + + memset( items, 0, sizeof( items ) ); + + if( mbedtls_pk_debug( pk, items ) != 0 ) + { + debug_send_line( ssl, level, file, line, + "invalid PK context\n" ); + return; + } + + for( i = 0; i < MBEDTLS_PK_DEBUG_MAX_ITEMS; i++ ) + { + if( items[i].type == MBEDTLS_PK_DEBUG_NONE ) + return; + + mbedtls_snprintf( name, sizeof( name ), "%s%s", text, items[i].name ); + name[sizeof( name ) - 1] = '\0'; + + if( items[i].type == MBEDTLS_PK_DEBUG_MPI ) + mbedtls_debug_print_mpi( ssl, level, file, line, name, items[i].value ); + else +#if defined(MBEDTLS_ECP_C) + if( items[i].type == MBEDTLS_PK_DEBUG_ECP ) + mbedtls_debug_print_ecp( ssl, level, file, line, name, items[i].value ); + else +#endif + debug_send_line( ssl, level, file, line, + "should not happen\n" ); + } +} + +static void debug_print_line_by_line( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, const char *text ) +{ + char str[DEBUG_BUF_SIZE]; + const char *start, *cur; + + start = text; + for( cur = text; *cur != '\0'; cur++ ) + { + if( *cur == '\n' ) + { + size_t len = cur - start + 1; + if( len > DEBUG_BUF_SIZE - 1 ) + len = DEBUG_BUF_SIZE - 1; + + memcpy( str, start, len ); + str[len] = '\0'; + + debug_send_line( ssl, level, file, line, str ); + + start = cur + 1; + } + } +} + +void mbedtls_debug_print_crt( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_x509_crt *crt ) +{ + char str[DEBUG_BUF_SIZE]; + int i = 0; + + if( NULL == ssl || + NULL == ssl->conf || + NULL == ssl->conf->f_dbg || + NULL == crt || + level > debug_threshold ) + { + return; + } + + while( crt != NULL ) + { + char buf[1024]; + + mbedtls_snprintf( str, sizeof( str ), "%s #%d:\n", text, ++i ); + debug_send_line( ssl, level, file, line, str ); + + mbedtls_x509_crt_info( buf, sizeof( buf ) - 1, "", crt ); + debug_print_line_by_line( ssl, level, file, line, buf ); + + debug_print_pk( ssl, level, file, line, "crt->", &crt->pk ); + + crt = crt->next; + } +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_ECDH_C) +static void mbedtls_debug_printf_ecdh_internal( const mbedtls_ssl_context *ssl, + int level, const char *file, + int line, + const mbedtls_ecdh_context *ecdh, + mbedtls_debug_ecdh_attr attr ) +{ +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + const mbedtls_ecdh_context* ctx = ecdh; +#else + const mbedtls_ecdh_context_mbed* ctx = &ecdh->ctx.mbed_ecdh; +#endif + + switch( attr ) + { + case MBEDTLS_DEBUG_ECDH_Q: + mbedtls_debug_print_ecp( ssl, level, file, line, "ECDH: Q", + &ctx->Q ); + break; + case MBEDTLS_DEBUG_ECDH_QP: + mbedtls_debug_print_ecp( ssl, level, file, line, "ECDH: Qp", + &ctx->Qp ); + break; + case MBEDTLS_DEBUG_ECDH_Z: + mbedtls_debug_print_mpi( ssl, level, file, line, "ECDH: z", + &ctx->z ); + break; + default: + break; + } +} + +void mbedtls_debug_printf_ecdh( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const mbedtls_ecdh_context *ecdh, + mbedtls_debug_ecdh_attr attr ) +{ +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + mbedtls_debug_printf_ecdh_internal( ssl, level, file, line, ecdh, attr ); +#else + switch( ecdh->var ) + { + default: + mbedtls_debug_printf_ecdh_internal( ssl, level, file, line, ecdh, + attr ); + } +#endif +} +#endif /* MBEDTLS_ECDH_C */ + +#endif /* MBEDTLS_DEBUG_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/des.c b/Android/Level4/app/src/main/c/mbedtls/library/des.c new file mode 100644 index 0000000..eddf55e --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/des.c @@ -0,0 +1,1058 @@ +/* + * FIPS-46-3 compliant Triple-DES implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ +/* + * DES, on which TDES is based, was originally designed by Horst Feistel + * at IBM in 1974, and was adopted as a standard by NIST (formerly NBS). + * + * http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf + */ + +#include "common.h" + +#if defined(MBEDTLS_DES_C) + +#include "mbedtls/des.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_DES_ALT) + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +/* + * Expanded DES S-boxes + */ +static const uint32_t SB1[64] = +{ + 0x01010400, 0x00000000, 0x00010000, 0x01010404, + 0x01010004, 0x00010404, 0x00000004, 0x00010000, + 0x00000400, 0x01010400, 0x01010404, 0x00000400, + 0x01000404, 0x01010004, 0x01000000, 0x00000004, + 0x00000404, 0x01000400, 0x01000400, 0x00010400, + 0x00010400, 0x01010000, 0x01010000, 0x01000404, + 0x00010004, 0x01000004, 0x01000004, 0x00010004, + 0x00000000, 0x00000404, 0x00010404, 0x01000000, + 0x00010000, 0x01010404, 0x00000004, 0x01010000, + 0x01010400, 0x01000000, 0x01000000, 0x00000400, + 0x01010004, 0x00010000, 0x00010400, 0x01000004, + 0x00000400, 0x00000004, 0x01000404, 0x00010404, + 0x01010404, 0x00010004, 0x01010000, 0x01000404, + 0x01000004, 0x00000404, 0x00010404, 0x01010400, + 0x00000404, 0x01000400, 0x01000400, 0x00000000, + 0x00010004, 0x00010400, 0x00000000, 0x01010004 +}; + +static const uint32_t SB2[64] = +{ + 0x80108020, 0x80008000, 0x00008000, 0x00108020, + 0x00100000, 0x00000020, 0x80100020, 0x80008020, + 0x80000020, 0x80108020, 0x80108000, 0x80000000, + 0x80008000, 0x00100000, 0x00000020, 0x80100020, + 0x00108000, 0x00100020, 0x80008020, 0x00000000, + 0x80000000, 0x00008000, 0x00108020, 0x80100000, + 0x00100020, 0x80000020, 0x00000000, 0x00108000, + 0x00008020, 0x80108000, 0x80100000, 0x00008020, + 0x00000000, 0x00108020, 0x80100020, 0x00100000, + 0x80008020, 0x80100000, 0x80108000, 0x00008000, + 0x80100000, 0x80008000, 0x00000020, 0x80108020, + 0x00108020, 0x00000020, 0x00008000, 0x80000000, + 0x00008020, 0x80108000, 0x00100000, 0x80000020, + 0x00100020, 0x80008020, 0x80000020, 0x00100020, + 0x00108000, 0x00000000, 0x80008000, 0x00008020, + 0x80000000, 0x80100020, 0x80108020, 0x00108000 +}; + +static const uint32_t SB3[64] = +{ + 0x00000208, 0x08020200, 0x00000000, 0x08020008, + 0x08000200, 0x00000000, 0x00020208, 0x08000200, + 0x00020008, 0x08000008, 0x08000008, 0x00020000, + 0x08020208, 0x00020008, 0x08020000, 0x00000208, + 0x08000000, 0x00000008, 0x08020200, 0x00000200, + 0x00020200, 0x08020000, 0x08020008, 0x00020208, + 0x08000208, 0x00020200, 0x00020000, 0x08000208, + 0x00000008, 0x08020208, 0x00000200, 0x08000000, + 0x08020200, 0x08000000, 0x00020008, 0x00000208, + 0x00020000, 0x08020200, 0x08000200, 0x00000000, + 0x00000200, 0x00020008, 0x08020208, 0x08000200, + 0x08000008, 0x00000200, 0x00000000, 0x08020008, + 0x08000208, 0x00020000, 0x08000000, 0x08020208, + 0x00000008, 0x00020208, 0x00020200, 0x08000008, + 0x08020000, 0x08000208, 0x00000208, 0x08020000, + 0x00020208, 0x00000008, 0x08020008, 0x00020200 +}; + +static const uint32_t SB4[64] = +{ + 0x00802001, 0x00002081, 0x00002081, 0x00000080, + 0x00802080, 0x00800081, 0x00800001, 0x00002001, + 0x00000000, 0x00802000, 0x00802000, 0x00802081, + 0x00000081, 0x00000000, 0x00800080, 0x00800001, + 0x00000001, 0x00002000, 0x00800000, 0x00802001, + 0x00000080, 0x00800000, 0x00002001, 0x00002080, + 0x00800081, 0x00000001, 0x00002080, 0x00800080, + 0x00002000, 0x00802080, 0x00802081, 0x00000081, + 0x00800080, 0x00800001, 0x00802000, 0x00802081, + 0x00000081, 0x00000000, 0x00000000, 0x00802000, + 0x00002080, 0x00800080, 0x00800081, 0x00000001, + 0x00802001, 0x00002081, 0x00002081, 0x00000080, + 0x00802081, 0x00000081, 0x00000001, 0x00002000, + 0x00800001, 0x00002001, 0x00802080, 0x00800081, + 0x00002001, 0x00002080, 0x00800000, 0x00802001, + 0x00000080, 0x00800000, 0x00002000, 0x00802080 +}; + +static const uint32_t SB5[64] = +{ + 0x00000100, 0x02080100, 0x02080000, 0x42000100, + 0x00080000, 0x00000100, 0x40000000, 0x02080000, + 0x40080100, 0x00080000, 0x02000100, 0x40080100, + 0x42000100, 0x42080000, 0x00080100, 0x40000000, + 0x02000000, 0x40080000, 0x40080000, 0x00000000, + 0x40000100, 0x42080100, 0x42080100, 0x02000100, + 0x42080000, 0x40000100, 0x00000000, 0x42000000, + 0x02080100, 0x02000000, 0x42000000, 0x00080100, + 0x00080000, 0x42000100, 0x00000100, 0x02000000, + 0x40000000, 0x02080000, 0x42000100, 0x40080100, + 0x02000100, 0x40000000, 0x42080000, 0x02080100, + 0x40080100, 0x00000100, 0x02000000, 0x42080000, + 0x42080100, 0x00080100, 0x42000000, 0x42080100, + 0x02080000, 0x00000000, 0x40080000, 0x42000000, + 0x00080100, 0x02000100, 0x40000100, 0x00080000, + 0x00000000, 0x40080000, 0x02080100, 0x40000100 +}; + +static const uint32_t SB6[64] = +{ + 0x20000010, 0x20400000, 0x00004000, 0x20404010, + 0x20400000, 0x00000010, 0x20404010, 0x00400000, + 0x20004000, 0x00404010, 0x00400000, 0x20000010, + 0x00400010, 0x20004000, 0x20000000, 0x00004010, + 0x00000000, 0x00400010, 0x20004010, 0x00004000, + 0x00404000, 0x20004010, 0x00000010, 0x20400010, + 0x20400010, 0x00000000, 0x00404010, 0x20404000, + 0x00004010, 0x00404000, 0x20404000, 0x20000000, + 0x20004000, 0x00000010, 0x20400010, 0x00404000, + 0x20404010, 0x00400000, 0x00004010, 0x20000010, + 0x00400000, 0x20004000, 0x20000000, 0x00004010, + 0x20000010, 0x20404010, 0x00404000, 0x20400000, + 0x00404010, 0x20404000, 0x00000000, 0x20400010, + 0x00000010, 0x00004000, 0x20400000, 0x00404010, + 0x00004000, 0x00400010, 0x20004010, 0x00000000, + 0x20404000, 0x20000000, 0x00400010, 0x20004010 +}; + +static const uint32_t SB7[64] = +{ + 0x00200000, 0x04200002, 0x04000802, 0x00000000, + 0x00000800, 0x04000802, 0x00200802, 0x04200800, + 0x04200802, 0x00200000, 0x00000000, 0x04000002, + 0x00000002, 0x04000000, 0x04200002, 0x00000802, + 0x04000800, 0x00200802, 0x00200002, 0x04000800, + 0x04000002, 0x04200000, 0x04200800, 0x00200002, + 0x04200000, 0x00000800, 0x00000802, 0x04200802, + 0x00200800, 0x00000002, 0x04000000, 0x00200800, + 0x04000000, 0x00200800, 0x00200000, 0x04000802, + 0x04000802, 0x04200002, 0x04200002, 0x00000002, + 0x00200002, 0x04000000, 0x04000800, 0x00200000, + 0x04200800, 0x00000802, 0x00200802, 0x04200800, + 0x00000802, 0x04000002, 0x04200802, 0x04200000, + 0x00200800, 0x00000000, 0x00000002, 0x04200802, + 0x00000000, 0x00200802, 0x04200000, 0x00000800, + 0x04000002, 0x04000800, 0x00000800, 0x00200002 +}; + +static const uint32_t SB8[64] = +{ + 0x10001040, 0x00001000, 0x00040000, 0x10041040, + 0x10000000, 0x10001040, 0x00000040, 0x10000000, + 0x00040040, 0x10040000, 0x10041040, 0x00041000, + 0x10041000, 0x00041040, 0x00001000, 0x00000040, + 0x10040000, 0x10000040, 0x10001000, 0x00001040, + 0x00041000, 0x00040040, 0x10040040, 0x10041000, + 0x00001040, 0x00000000, 0x00000000, 0x10040040, + 0x10000040, 0x10001000, 0x00041040, 0x00040000, + 0x00041040, 0x00040000, 0x10041000, 0x00001000, + 0x00000040, 0x10040040, 0x00001000, 0x00041040, + 0x10001000, 0x00000040, 0x10000040, 0x10040000, + 0x10040040, 0x10000000, 0x00040000, 0x10001040, + 0x00000000, 0x10041040, 0x00040040, 0x10000040, + 0x10040000, 0x10001000, 0x10001040, 0x00000000, + 0x10041040, 0x00041000, 0x00041000, 0x00001040, + 0x00001040, 0x00040040, 0x10000000, 0x10041000 +}; + +/* + * PC1: left and right halves bit-swap + */ +static const uint32_t LHs[16] = +{ + 0x00000000, 0x00000001, 0x00000100, 0x00000101, + 0x00010000, 0x00010001, 0x00010100, 0x00010101, + 0x01000000, 0x01000001, 0x01000100, 0x01000101, + 0x01010000, 0x01010001, 0x01010100, 0x01010101 +}; + +static const uint32_t RHs[16] = +{ + 0x00000000, 0x01000000, 0x00010000, 0x01010000, + 0x00000100, 0x01000100, 0x00010100, 0x01010100, + 0x00000001, 0x01000001, 0x00010001, 0x01010001, + 0x00000101, 0x01000101, 0x00010101, 0x01010101, +}; + +/* + * Initial Permutation macro + */ +#define DES_IP(X,Y) \ + do \ + { \ + T = (((X) >> 4) ^ (Y)) & 0x0F0F0F0F; (Y) ^= T; (X) ^= (T << 4); \ + T = (((X) >> 16) ^ (Y)) & 0x0000FFFF; (Y) ^= T; (X) ^= (T << 16); \ + T = (((Y) >> 2) ^ (X)) & 0x33333333; (X) ^= T; (Y) ^= (T << 2); \ + T = (((Y) >> 8) ^ (X)) & 0x00FF00FF; (X) ^= T; (Y) ^= (T << 8); \ + (Y) = (((Y) << 1) | ((Y) >> 31)) & 0xFFFFFFFF; \ + T = ((X) ^ (Y)) & 0xAAAAAAAA; (Y) ^= T; (X) ^= T; \ + (X) = (((X) << 1) | ((X) >> 31)) & 0xFFFFFFFF; \ + } while( 0 ) + +/* + * Final Permutation macro + */ +#define DES_FP(X,Y) \ + do \ + { \ + (X) = (((X) << 31) | ((X) >> 1)) & 0xFFFFFFFF; \ + T = ((X) ^ (Y)) & 0xAAAAAAAA; (X) ^= T; (Y) ^= T; \ + (Y) = (((Y) << 31) | ((Y) >> 1)) & 0xFFFFFFFF; \ + T = (((Y) >> 8) ^ (X)) & 0x00FF00FF; (X) ^= T; (Y) ^= (T << 8); \ + T = (((Y) >> 2) ^ (X)) & 0x33333333; (X) ^= T; (Y) ^= (T << 2); \ + T = (((X) >> 16) ^ (Y)) & 0x0000FFFF; (Y) ^= T; (X) ^= (T << 16); \ + T = (((X) >> 4) ^ (Y)) & 0x0F0F0F0F; (Y) ^= T; (X) ^= (T << 4); \ + } while( 0 ) + +/* + * DES round macro + */ +#define DES_ROUND(X,Y) \ + do \ + { \ + T = *SK++ ^ (X); \ + (Y) ^= SB8[ (T ) & 0x3F ] ^ \ + SB6[ (T >> 8) & 0x3F ] ^ \ + SB4[ (T >> 16) & 0x3F ] ^ \ + SB2[ (T >> 24) & 0x3F ]; \ + \ + T = *SK++ ^ (((X) << 28) | ((X) >> 4)); \ + (Y) ^= SB7[ (T ) & 0x3F ] ^ \ + SB5[ (T >> 8) & 0x3F ] ^ \ + SB3[ (T >> 16) & 0x3F ] ^ \ + SB1[ (T >> 24) & 0x3F ]; \ + } while( 0 ) + +#define SWAP(a,b) \ + do \ + { \ + uint32_t t = (a); (a) = (b); (b) = t; t = 0; \ + } while( 0 ) + +void mbedtls_des_init( mbedtls_des_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_des_context ) ); +} + +void mbedtls_des_free( mbedtls_des_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_des_context ) ); +} + +void mbedtls_des3_init( mbedtls_des3_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_des3_context ) ); +} + +void mbedtls_des3_free( mbedtls_des3_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_des3_context ) ); +} + +static const unsigned char odd_parity_table[128] = { 1, 2, 4, 7, 8, + 11, 13, 14, 16, 19, 21, 22, 25, 26, 28, 31, 32, 35, 37, 38, 41, 42, 44, + 47, 49, 50, 52, 55, 56, 59, 61, 62, 64, 67, 69, 70, 73, 74, 76, 79, 81, + 82, 84, 87, 88, 91, 93, 94, 97, 98, 100, 103, 104, 107, 109, 110, 112, + 115, 117, 118, 121, 122, 124, 127, 128, 131, 133, 134, 137, 138, 140, + 143, 145, 146, 148, 151, 152, 155, 157, 158, 161, 162, 164, 167, 168, + 171, 173, 174, 176, 179, 181, 182, 185, 186, 188, 191, 193, 194, 196, + 199, 200, 203, 205, 206, 208, 211, 213, 214, 217, 218, 220, 223, 224, + 227, 229, 230, 233, 234, 236, 239, 241, 242, 244, 247, 248, 251, 253, + 254 }; + +void mbedtls_des_key_set_parity( unsigned char key[MBEDTLS_DES_KEY_SIZE] ) +{ + int i; + + for( i = 0; i < MBEDTLS_DES_KEY_SIZE; i++ ) + key[i] = odd_parity_table[key[i] / 2]; +} + +/* + * Check the given key's parity, returns 1 on failure, 0 on SUCCESS + */ +int mbedtls_des_key_check_key_parity( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) +{ + int i; + + for( i = 0; i < MBEDTLS_DES_KEY_SIZE; i++ ) + if( key[i] != odd_parity_table[key[i] / 2] ) + return( 1 ); + + return( 0 ); +} + +/* + * Table of weak and semi-weak keys + * + * Source: http://en.wikipedia.org/wiki/Weak_key + * + * Weak: + * Alternating ones + zeros (0x0101010101010101) + * Alternating 'F' + 'E' (0xFEFEFEFEFEFEFEFE) + * '0xE0E0E0E0F1F1F1F1' + * '0x1F1F1F1F0E0E0E0E' + * + * Semi-weak: + * 0x011F011F010E010E and 0x1F011F010E010E01 + * 0x01E001E001F101F1 and 0xE001E001F101F101 + * 0x01FE01FE01FE01FE and 0xFE01FE01FE01FE01 + * 0x1FE01FE00EF10EF1 and 0xE01FE01FF10EF10E + * 0x1FFE1FFE0EFE0EFE and 0xFE1FFE1FFE0EFE0E + * 0xE0FEE0FEF1FEF1FE and 0xFEE0FEE0FEF1FEF1 + * + */ + +#define WEAK_KEY_COUNT 16 + +static const unsigned char weak_key_table[WEAK_KEY_COUNT][MBEDTLS_DES_KEY_SIZE] = +{ + { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE }, + { 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E }, + { 0xE0, 0xE0, 0xE0, 0xE0, 0xF1, 0xF1, 0xF1, 0xF1 }, + + { 0x01, 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E }, + { 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E, 0x01 }, + { 0x01, 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1 }, + { 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1, 0x01 }, + { 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE }, + { 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01 }, + { 0x1F, 0xE0, 0x1F, 0xE0, 0x0E, 0xF1, 0x0E, 0xF1 }, + { 0xE0, 0x1F, 0xE0, 0x1F, 0xF1, 0x0E, 0xF1, 0x0E }, + { 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E, 0xFE }, + { 0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E }, + { 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE }, + { 0xFE, 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1 } +}; + +int mbedtls_des_key_check_weak( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) +{ + int i; + + for( i = 0; i < WEAK_KEY_COUNT; i++ ) + if( memcmp( weak_key_table[i], key, MBEDTLS_DES_KEY_SIZE) == 0 ) + return( 1 ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DES_SETKEY_ALT) +void mbedtls_des_setkey( uint32_t SK[32], const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) +{ + int i; + uint32_t X, Y, T; + + GET_UINT32_BE( X, key, 0 ); + GET_UINT32_BE( Y, key, 4 ); + + /* + * Permuted Choice 1 + */ + T = ((Y >> 4) ^ X) & 0x0F0F0F0F; X ^= T; Y ^= (T << 4); + T = ((Y ) ^ X) & 0x10101010; X ^= T; Y ^= (T ); + + X = (LHs[ (X ) & 0xF] << 3) | (LHs[ (X >> 8) & 0xF ] << 2) + | (LHs[ (X >> 16) & 0xF] << 1) | (LHs[ (X >> 24) & 0xF ] ) + | (LHs[ (X >> 5) & 0xF] << 7) | (LHs[ (X >> 13) & 0xF ] << 6) + | (LHs[ (X >> 21) & 0xF] << 5) | (LHs[ (X >> 29) & 0xF ] << 4); + + Y = (RHs[ (Y >> 1) & 0xF] << 3) | (RHs[ (Y >> 9) & 0xF ] << 2) + | (RHs[ (Y >> 17) & 0xF] << 1) | (RHs[ (Y >> 25) & 0xF ] ) + | (RHs[ (Y >> 4) & 0xF] << 7) | (RHs[ (Y >> 12) & 0xF ] << 6) + | (RHs[ (Y >> 20) & 0xF] << 5) | (RHs[ (Y >> 28) & 0xF ] << 4); + + X &= 0x0FFFFFFF; + Y &= 0x0FFFFFFF; + + /* + * calculate subkeys + */ + for( i = 0; i < 16; i++ ) + { + if( i < 2 || i == 8 || i == 15 ) + { + X = ((X << 1) | (X >> 27)) & 0x0FFFFFFF; + Y = ((Y << 1) | (Y >> 27)) & 0x0FFFFFFF; + } + else + { + X = ((X << 2) | (X >> 26)) & 0x0FFFFFFF; + Y = ((Y << 2) | (Y >> 26)) & 0x0FFFFFFF; + } + + *SK++ = ((X << 4) & 0x24000000) | ((X << 28) & 0x10000000) + | ((X << 14) & 0x08000000) | ((X << 18) & 0x02080000) + | ((X << 6) & 0x01000000) | ((X << 9) & 0x00200000) + | ((X >> 1) & 0x00100000) | ((X << 10) & 0x00040000) + | ((X << 2) & 0x00020000) | ((X >> 10) & 0x00010000) + | ((Y >> 13) & 0x00002000) | ((Y >> 4) & 0x00001000) + | ((Y << 6) & 0x00000800) | ((Y >> 1) & 0x00000400) + | ((Y >> 14) & 0x00000200) | ((Y ) & 0x00000100) + | ((Y >> 5) & 0x00000020) | ((Y >> 10) & 0x00000010) + | ((Y >> 3) & 0x00000008) | ((Y >> 18) & 0x00000004) + | ((Y >> 26) & 0x00000002) | ((Y >> 24) & 0x00000001); + + *SK++ = ((X << 15) & 0x20000000) | ((X << 17) & 0x10000000) + | ((X << 10) & 0x08000000) | ((X << 22) & 0x04000000) + | ((X >> 2) & 0x02000000) | ((X << 1) & 0x01000000) + | ((X << 16) & 0x00200000) | ((X << 11) & 0x00100000) + | ((X << 3) & 0x00080000) | ((X >> 6) & 0x00040000) + | ((X << 15) & 0x00020000) | ((X >> 4) & 0x00010000) + | ((Y >> 2) & 0x00002000) | ((Y << 8) & 0x00001000) + | ((Y >> 14) & 0x00000808) | ((Y >> 9) & 0x00000400) + | ((Y ) & 0x00000200) | ((Y << 7) & 0x00000100) + | ((Y >> 7) & 0x00000020) | ((Y >> 3) & 0x00000011) + | ((Y << 2) & 0x00000004) | ((Y >> 21) & 0x00000002); + } +} +#endif /* !MBEDTLS_DES_SETKEY_ALT */ + +/* + * DES key schedule (56-bit, encryption) + */ +int mbedtls_des_setkey_enc( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) +{ + mbedtls_des_setkey( ctx->sk, key ); + + return( 0 ); +} + +/* + * DES key schedule (56-bit, decryption) + */ +int mbedtls_des_setkey_dec( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) +{ + int i; + + mbedtls_des_setkey( ctx->sk, key ); + + for( i = 0; i < 16; i += 2 ) + { + SWAP( ctx->sk[i ], ctx->sk[30 - i] ); + SWAP( ctx->sk[i + 1], ctx->sk[31 - i] ); + } + + return( 0 ); +} + +static void des3_set2key( uint32_t esk[96], + uint32_t dsk[96], + const unsigned char key[MBEDTLS_DES_KEY_SIZE*2] ) +{ + int i; + + mbedtls_des_setkey( esk, key ); + mbedtls_des_setkey( dsk + 32, key + 8 ); + + for( i = 0; i < 32; i += 2 ) + { + dsk[i ] = esk[30 - i]; + dsk[i + 1] = esk[31 - i]; + + esk[i + 32] = dsk[62 - i]; + esk[i + 33] = dsk[63 - i]; + + esk[i + 64] = esk[i ]; + esk[i + 65] = esk[i + 1]; + + dsk[i + 64] = dsk[i ]; + dsk[i + 65] = dsk[i + 1]; + } +} + +/* + * Triple-DES key schedule (112-bit, encryption) + */ +int mbedtls_des3_set2key_enc( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ) +{ + uint32_t sk[96]; + + des3_set2key( ctx->sk, sk, key ); + mbedtls_platform_zeroize( sk, sizeof( sk ) ); + + return( 0 ); +} + +/* + * Triple-DES key schedule (112-bit, decryption) + */ +int mbedtls_des3_set2key_dec( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ) +{ + uint32_t sk[96]; + + des3_set2key( sk, ctx->sk, key ); + mbedtls_platform_zeroize( sk, sizeof( sk ) ); + + return( 0 ); +} + +static void des3_set3key( uint32_t esk[96], + uint32_t dsk[96], + const unsigned char key[24] ) +{ + int i; + + mbedtls_des_setkey( esk, key ); + mbedtls_des_setkey( dsk + 32, key + 8 ); + mbedtls_des_setkey( esk + 64, key + 16 ); + + for( i = 0; i < 32; i += 2 ) + { + dsk[i ] = esk[94 - i]; + dsk[i + 1] = esk[95 - i]; + + esk[i + 32] = dsk[62 - i]; + esk[i + 33] = dsk[63 - i]; + + dsk[i + 64] = esk[30 - i]; + dsk[i + 65] = esk[31 - i]; + } +} + +/* + * Triple-DES key schedule (168-bit, encryption) + */ +int mbedtls_des3_set3key_enc( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ) +{ + uint32_t sk[96]; + + des3_set3key( ctx->sk, sk, key ); + mbedtls_platform_zeroize( sk, sizeof( sk ) ); + + return( 0 ); +} + +/* + * Triple-DES key schedule (168-bit, decryption) + */ +int mbedtls_des3_set3key_dec( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ) +{ + uint32_t sk[96]; + + des3_set3key( sk, ctx->sk, key ); + mbedtls_platform_zeroize( sk, sizeof( sk ) ); + + return( 0 ); +} + +/* + * DES-ECB block encryption/decryption + */ +#if !defined(MBEDTLS_DES_CRYPT_ECB_ALT) +int mbedtls_des_crypt_ecb( mbedtls_des_context *ctx, + const unsigned char input[8], + unsigned char output[8] ) +{ + int i; + uint32_t X, Y, T, *SK; + + SK = ctx->sk; + + GET_UINT32_BE( X, input, 0 ); + GET_UINT32_BE( Y, input, 4 ); + + DES_IP( X, Y ); + + for( i = 0; i < 8; i++ ) + { + DES_ROUND( Y, X ); + DES_ROUND( X, Y ); + } + + DES_FP( Y, X ); + + PUT_UINT32_BE( Y, output, 0 ); + PUT_UINT32_BE( X, output, 4 ); + + return( 0 ); +} +#endif /* !MBEDTLS_DES_CRYPT_ECB_ALT */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/* + * DES-CBC buffer encryption/decryption + */ +int mbedtls_des_crypt_cbc( mbedtls_des_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output ) +{ + int i; + unsigned char temp[8]; + + if( length % 8 ) + return( MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH ); + + if( mode == MBEDTLS_DES_ENCRYPT ) + { + while( length > 0 ) + { + for( i = 0; i < 8; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + mbedtls_des_crypt_ecb( ctx, output, output ); + memcpy( iv, output, 8 ); + + input += 8; + output += 8; + length -= 8; + } + } + else /* MBEDTLS_DES_DECRYPT */ + { + while( length > 0 ) + { + memcpy( temp, input, 8 ); + mbedtls_des_crypt_ecb( ctx, input, output ); + + for( i = 0; i < 8; i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, 8 ); + + input += 8; + output += 8; + length -= 8; + } + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +/* + * 3DES-ECB block encryption/decryption + */ +#if !defined(MBEDTLS_DES3_CRYPT_ECB_ALT) +int mbedtls_des3_crypt_ecb( mbedtls_des3_context *ctx, + const unsigned char input[8], + unsigned char output[8] ) +{ + int i; + uint32_t X, Y, T, *SK; + + SK = ctx->sk; + + GET_UINT32_BE( X, input, 0 ); + GET_UINT32_BE( Y, input, 4 ); + + DES_IP( X, Y ); + + for( i = 0; i < 8; i++ ) + { + DES_ROUND( Y, X ); + DES_ROUND( X, Y ); + } + + for( i = 0; i < 8; i++ ) + { + DES_ROUND( X, Y ); + DES_ROUND( Y, X ); + } + + for( i = 0; i < 8; i++ ) + { + DES_ROUND( Y, X ); + DES_ROUND( X, Y ); + } + + DES_FP( Y, X ); + + PUT_UINT32_BE( Y, output, 0 ); + PUT_UINT32_BE( X, output, 4 ); + + return( 0 ); +} +#endif /* !MBEDTLS_DES3_CRYPT_ECB_ALT */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/* + * 3DES-CBC buffer encryption/decryption + */ +int mbedtls_des3_crypt_cbc( mbedtls_des3_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output ) +{ + int i; + unsigned char temp[8]; + + if( length % 8 ) + return( MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH ); + + if( mode == MBEDTLS_DES_ENCRYPT ) + { + while( length > 0 ) + { + for( i = 0; i < 8; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + mbedtls_des3_crypt_ecb( ctx, output, output ); + memcpy( iv, output, 8 ); + + input += 8; + output += 8; + length -= 8; + } + } + else /* MBEDTLS_DES_DECRYPT */ + { + while( length > 0 ) + { + memcpy( temp, input, 8 ); + mbedtls_des3_crypt_ecb( ctx, input, output ); + + for( i = 0; i < 8; i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, 8 ); + + input += 8; + output += 8; + length -= 8; + } + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#endif /* !MBEDTLS_DES_ALT */ + +#if defined(MBEDTLS_SELF_TEST) +/* + * DES and 3DES test vectors from: + * + * http://csrc.nist.gov/groups/STM/cavp/documents/des/tripledes-vectors.zip + */ +static const unsigned char des3_test_keys[24] = +{ + 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, + 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23 +}; + +static const unsigned char des3_test_buf[8] = +{ + 0x4E, 0x6F, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74 +}; + +static const unsigned char des3_test_ecb_dec[3][8] = +{ + { 0x37, 0x2B, 0x98, 0xBF, 0x52, 0x65, 0xB0, 0x59 }, + { 0xC2, 0x10, 0x19, 0x9C, 0x38, 0x5A, 0x65, 0xA1 }, + { 0xA2, 0x70, 0x56, 0x68, 0x69, 0xE5, 0x15, 0x1D } +}; + +static const unsigned char des3_test_ecb_enc[3][8] = +{ + { 0x1C, 0xD5, 0x97, 0xEA, 0x84, 0x26, 0x73, 0xFB }, + { 0xB3, 0x92, 0x4D, 0xF3, 0xC5, 0xB5, 0x42, 0x93 }, + { 0xDA, 0x37, 0x64, 0x41, 0xBA, 0x6F, 0x62, 0x6F } +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const unsigned char des3_test_iv[8] = +{ + 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, +}; + +static const unsigned char des3_test_cbc_dec[3][8] = +{ + { 0x58, 0xD9, 0x48, 0xEF, 0x85, 0x14, 0x65, 0x9A }, + { 0x5F, 0xC8, 0x78, 0xD4, 0xD7, 0x92, 0xD9, 0x54 }, + { 0x25, 0xF9, 0x75, 0x85, 0xA8, 0x1E, 0x48, 0xBF } +}; + +static const unsigned char des3_test_cbc_enc[3][8] = +{ + { 0x91, 0x1C, 0x6D, 0xCF, 0x48, 0xA7, 0xC3, 0x4D }, + { 0x60, 0x1A, 0x76, 0x8F, 0xA1, 0xF9, 0x66, 0xF1 }, + { 0xA1, 0x50, 0x0F, 0x99, 0xB2, 0xCD, 0x64, 0x76 } +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +/* + * Checkup routine + */ +int mbedtls_des_self_test( int verbose ) +{ + int i, j, u, v, ret = 0; + mbedtls_des_context ctx; + mbedtls_des3_context ctx3; + unsigned char buf[8]; +#if defined(MBEDTLS_CIPHER_MODE_CBC) + unsigned char prv[8]; + unsigned char iv[8]; +#endif + + mbedtls_des_init( &ctx ); + mbedtls_des3_init( &ctx3 ); + /* + * ECB mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + v = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " DES%c-ECB-%3d (%s): ", + ( u == 0 ) ? ' ' : '3', 56 + u * 56, + ( v == MBEDTLS_DES_DECRYPT ) ? "dec" : "enc" ); + + memcpy( buf, des3_test_buf, 8 ); + + switch( i ) + { + case 0: + mbedtls_des_setkey_dec( &ctx, des3_test_keys ); + break; + + case 1: + mbedtls_des_setkey_enc( &ctx, des3_test_keys ); + break; + + case 2: + mbedtls_des3_set2key_dec( &ctx3, des3_test_keys ); + break; + + case 3: + mbedtls_des3_set2key_enc( &ctx3, des3_test_keys ); + break; + + case 4: + mbedtls_des3_set3key_dec( &ctx3, des3_test_keys ); + break; + + case 5: + mbedtls_des3_set3key_enc( &ctx3, des3_test_keys ); + break; + + default: + return( 1 ); + } + + for( j = 0; j < 100; j++ ) + { + if( u == 0 ) + mbedtls_des_crypt_ecb( &ctx, buf, buf ); + else + mbedtls_des3_crypt_ecb( &ctx3, buf, buf ); + } + + if( ( v == MBEDTLS_DES_DECRYPT && + memcmp( buf, des3_test_ecb_dec[u], 8 ) != 0 ) || + ( v != MBEDTLS_DES_DECRYPT && + memcmp( buf, des3_test_ecb_enc[u], 8 ) != 0 ) ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + /* + * CBC mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + v = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " DES%c-CBC-%3d (%s): ", + ( u == 0 ) ? ' ' : '3', 56 + u * 56, + ( v == MBEDTLS_DES_DECRYPT ) ? "dec" : "enc" ); + + memcpy( iv, des3_test_iv, 8 ); + memcpy( prv, des3_test_iv, 8 ); + memcpy( buf, des3_test_buf, 8 ); + + switch( i ) + { + case 0: + mbedtls_des_setkey_dec( &ctx, des3_test_keys ); + break; + + case 1: + mbedtls_des_setkey_enc( &ctx, des3_test_keys ); + break; + + case 2: + mbedtls_des3_set2key_dec( &ctx3, des3_test_keys ); + break; + + case 3: + mbedtls_des3_set2key_enc( &ctx3, des3_test_keys ); + break; + + case 4: + mbedtls_des3_set3key_dec( &ctx3, des3_test_keys ); + break; + + case 5: + mbedtls_des3_set3key_enc( &ctx3, des3_test_keys ); + break; + + default: + return( 1 ); + } + + if( v == MBEDTLS_DES_DECRYPT ) + { + for( j = 0; j < 100; j++ ) + { + if( u == 0 ) + mbedtls_des_crypt_cbc( &ctx, v, 8, iv, buf, buf ); + else + mbedtls_des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf ); + } + } + else + { + for( j = 0; j < 100; j++ ) + { + unsigned char tmp[8]; + + if( u == 0 ) + mbedtls_des_crypt_cbc( &ctx, v, 8, iv, buf, buf ); + else + mbedtls_des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf ); + + memcpy( tmp, prv, 8 ); + memcpy( prv, buf, 8 ); + memcpy( buf, tmp, 8 ); + } + + memcpy( buf, prv, 8 ); + } + + if( ( v == MBEDTLS_DES_DECRYPT && + memcmp( buf, des3_test_cbc_dec[u], 8 ) != 0 ) || + ( v != MBEDTLS_DES_DECRYPT && + memcmp( buf, des3_test_cbc_enc[u], 8 ) != 0 ) ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +exit: + mbedtls_des_free( &ctx ); + mbedtls_des3_free( &ctx3 ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_DES_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/dhm.c b/Android/Level4/app/src/main/c/mbedtls/library/dhm.c new file mode 100644 index 0000000..f796812 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/dhm.c @@ -0,0 +1,735 @@ +/* + * Diffie-Hellman-Merkle key exchange + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ +/* + * The following sources were referenced in the design of this implementation + * of the Diffie-Hellman-Merkle algorithm: + * + * [1] Handbook of Applied Cryptography - 1997, Chapter 12 + * Menezes, van Oorschot and Vanstone + * + */ + +#include "common.h" + +#if defined(MBEDTLS_DHM_C) + +#include "mbedtls/dhm.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_PEM_PARSE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_ASN1_PARSE_C) +#include "mbedtls/asn1.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if !defined(MBEDTLS_DHM_ALT) + +#define DHM_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_DHM_BAD_INPUT_DATA ) +#define DHM_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +/* + * helper to validate the mbedtls_mpi size and import it + */ +static int dhm_read_bignum( mbedtls_mpi *X, + unsigned char **p, + const unsigned char *end ) +{ + int ret, n; + + if( end - *p < 2 ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + + n = ( (*p)[0] << 8 ) | (*p)[1]; + (*p) += 2; + + if( (int)( end - *p ) < n ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_mpi_read_binary( X, *p, n ) ) != 0 ) + return( MBEDTLS_ERR_DHM_READ_PARAMS_FAILED + ret ); + + (*p) += n; + + return( 0 ); +} + +/* + * Verify sanity of parameter with regards to P + * + * Parameter should be: 2 <= public_param <= P - 2 + * + * This means that we need to return an error if + * public_param < 2 or public_param > P-2 + * + * For more information on the attack, see: + * http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf + * http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643 + */ +static int dhm_check_range( const mbedtls_mpi *param, const mbedtls_mpi *P ) +{ + mbedtls_mpi L, U; + int ret = 0; + + mbedtls_mpi_init( &L ); mbedtls_mpi_init( &U ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &L, 2 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &U, P, 2 ) ); + + if( mbedtls_mpi_cmp_mpi( param, &L ) < 0 || + mbedtls_mpi_cmp_mpi( param, &U ) > 0 ) + { + ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA; + } + +cleanup: + mbedtls_mpi_free( &L ); mbedtls_mpi_free( &U ); + return( ret ); +} + +void mbedtls_dhm_init( mbedtls_dhm_context *ctx ) +{ + DHM_VALIDATE( ctx != NULL ); + memset( ctx, 0, sizeof( mbedtls_dhm_context ) ); +} + +/* + * Parse the ServerKeyExchange parameters + */ +int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx, + unsigned char **p, + const unsigned char *end ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + DHM_VALIDATE_RET( ctx != NULL ); + DHM_VALIDATE_RET( p != NULL && *p != NULL ); + DHM_VALIDATE_RET( end != NULL ); + + if( ( ret = dhm_read_bignum( &ctx->P, p, end ) ) != 0 || + ( ret = dhm_read_bignum( &ctx->G, p, end ) ) != 0 || + ( ret = dhm_read_bignum( &ctx->GY, p, end ) ) != 0 ) + return( ret ); + + if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 ) + return( ret ); + + ctx->len = mbedtls_mpi_size( &ctx->P ); + + return( 0 ); +} + +/* + * Setup and write the ServerKeyExchange parameters + */ +int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size, + unsigned char *output, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret, count = 0; + size_t n1, n2, n3; + unsigned char *p; + DHM_VALIDATE_RET( ctx != NULL ); + DHM_VALIDATE_RET( output != NULL ); + DHM_VALIDATE_RET( olen != NULL ); + DHM_VALIDATE_RET( f_rng != NULL ); + + if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + + /* + * Generate X as large as possible ( < P ) + */ + do + { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) ); + + while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) ); + + if( count++ > 10 ) + return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED ); + } + while( dhm_check_range( &ctx->X, &ctx->P ) != 0 ); + + /* + * Calculate GX = G^X mod P + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X, + &ctx->P , &ctx->RP ) ); + + if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 ) + return( ret ); + + /* + * export P, G, GX + */ +#define DHM_MPI_EXPORT( X, n ) \ + do { \ + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( ( X ), \ + p + 2, \ + ( n ) ) ); \ + *p++ = (unsigned char)( ( n ) >> 8 ); \ + *p++ = (unsigned char)( ( n ) ); \ + p += ( n ); \ + } while( 0 ) + + n1 = mbedtls_mpi_size( &ctx->P ); + n2 = mbedtls_mpi_size( &ctx->G ); + n3 = mbedtls_mpi_size( &ctx->GX ); + + p = output; + DHM_MPI_EXPORT( &ctx->P , n1 ); + DHM_MPI_EXPORT( &ctx->G , n2 ); + DHM_MPI_EXPORT( &ctx->GX, n3 ); + + *olen = p - output; + + ctx->len = n1; + +cleanup: + + if( ret != 0 ) + return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED + ret ); + + return( 0 ); +} + +/* + * Set prime modulus and generator + */ +int mbedtls_dhm_set_group( mbedtls_dhm_context *ctx, + const mbedtls_mpi *P, + const mbedtls_mpi *G ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + DHM_VALIDATE_RET( ctx != NULL ); + DHM_VALIDATE_RET( P != NULL ); + DHM_VALIDATE_RET( G != NULL ); + + if( ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 || + ( ret = mbedtls_mpi_copy( &ctx->G, G ) ) != 0 ) + { + return( MBEDTLS_ERR_DHM_SET_GROUP_FAILED + ret ); + } + + ctx->len = mbedtls_mpi_size( &ctx->P ); + return( 0 ); +} + +/* + * Import the peer's public value G^Y + */ +int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx, + const unsigned char *input, size_t ilen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + DHM_VALIDATE_RET( ctx != NULL ); + DHM_VALIDATE_RET( input != NULL ); + + if( ilen < 1 || ilen > ctx->len ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 ) + return( MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED + ret ); + + return( 0 ); +} + +/* + * Create own private value X and export G^X + */ +int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size, + unsigned char *output, size_t olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret, count = 0; + DHM_VALIDATE_RET( ctx != NULL ); + DHM_VALIDATE_RET( output != NULL ); + DHM_VALIDATE_RET( f_rng != NULL ); + + if( olen < 1 || olen > ctx->len ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + + if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + + /* + * generate X and calculate GX = G^X mod P + */ + do + { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) ); + + while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) ); + + if( count++ > 10 ) + return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED ); + } + while( dhm_check_range( &ctx->X, &ctx->P ) != 0 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X, + &ctx->P , &ctx->RP ) ); + + if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 ) + return( ret ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->GX, output, olen ) ); + +cleanup: + + if( ret != 0 ) + return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED + ret ); + + return( 0 ); +} + +/* + * Pick a random R in the range [2, M) for blinding purposes + */ +static int dhm_random_below( mbedtls_mpi *R, const mbedtls_mpi *M, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret, count; + + count = 0; + do + { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( R, mbedtls_mpi_size( M ), f_rng, p_rng ) ); + + while( mbedtls_mpi_cmp_mpi( R, M ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( R, 1 ) ); + + if( count++ > 10 ) + return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); + } + while( mbedtls_mpi_cmp_int( R, 1 ) <= 0 ); + +cleanup: + return( ret ); +} + + +/* + * Use the blinding method and optimisation suggested in section 10 of: + * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA, + * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer + * Berlin Heidelberg, 1996. p. 104-113. + */ +static int dhm_update_blinding( mbedtls_dhm_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret; + mbedtls_mpi R; + + mbedtls_mpi_init( &R ); + + /* + * Don't use any blinding the first time a particular X is used, + * but remember it to use blinding next time. + */ + if( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->pX ) != 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &ctx->pX, &ctx->X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vi, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vf, 1 ) ); + + return( 0 ); + } + + /* + * Ok, we need blinding. Can we re-use existing values? + * If yes, just update them by squaring them. + */ + if( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) != 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->P ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) ); + + return( 0 ); + } + + /* + * We need to generate blinding values from scratch + */ + + /* Vi = random( 2, P-1 ) */ + MBEDTLS_MPI_CHK( dhm_random_below( &ctx->Vi, &ctx->P, f_rng, p_rng ) ); + + /* Vf = Vi^-X mod P + * First compute Vi^-1 = R * (R Vi)^-1, (avoiding leaks from inv_mod), + * then elevate to the Xth power. */ + MBEDTLS_MPI_CHK( dhm_random_below( &R, &ctx->P, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vi, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vf, &ctx->Vf, &ctx->P ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->Vf, &ctx->Vf, &ctx->X, &ctx->P, &ctx->RP ) ); + +cleanup: + mbedtls_mpi_free( &R ); + + return( ret ); +} + +/* + * Derive and export the shared secret (G^Y)^X mod P + */ +int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx, + unsigned char *output, size_t output_size, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi GYb; + DHM_VALIDATE_RET( ctx != NULL ); + DHM_VALIDATE_RET( output != NULL ); + DHM_VALIDATE_RET( olen != NULL ); + + if( output_size < ctx->len ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + + if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 ) + return( ret ); + + mbedtls_mpi_init( &GYb ); + + /* Blind peer's value */ + if( f_rng != NULL ) + { + MBEDTLS_MPI_CHK( dhm_update_blinding( ctx, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &GYb, &ctx->GY, &ctx->Vi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &GYb, &GYb, &ctx->P ) ); + } + else + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &GYb, &ctx->GY ) ); + + /* Do modular exponentiation */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->K, &GYb, &ctx->X, + &ctx->P, &ctx->RP ) ); + + /* Unblind secret value */ + if( f_rng != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->K, &ctx->K, &ctx->Vf ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->K, &ctx->K, &ctx->P ) ); + } + + *olen = mbedtls_mpi_size( &ctx->K ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->K, output, *olen ) ); + +cleanup: + mbedtls_mpi_free( &GYb ); + + if( ret != 0 ) + return( MBEDTLS_ERR_DHM_CALC_SECRET_FAILED + ret ); + + return( 0 ); +} + +/* + * Free the components of a DHM key + */ +void mbedtls_dhm_free( mbedtls_dhm_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_mpi_free( &ctx->pX ); + mbedtls_mpi_free( &ctx->Vf ); + mbedtls_mpi_free( &ctx->Vi ); + mbedtls_mpi_free( &ctx->RP ); + mbedtls_mpi_free( &ctx->K ); + mbedtls_mpi_free( &ctx->GY ); + mbedtls_mpi_free( &ctx->GX ); + mbedtls_mpi_free( &ctx->X ); + mbedtls_mpi_free( &ctx->G ); + mbedtls_mpi_free( &ctx->P ); + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_dhm_context ) ); +} + +#if defined(MBEDTLS_ASN1_PARSE_C) +/* + * Parse DHM parameters + */ +int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin, + size_t dhminlen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + unsigned char *p, *end; +#if defined(MBEDTLS_PEM_PARSE_C) + mbedtls_pem_context pem; +#endif /* MBEDTLS_PEM_PARSE_C */ + + DHM_VALIDATE_RET( dhm != NULL ); + DHM_VALIDATE_RET( dhmin != NULL ); + +#if defined(MBEDTLS_PEM_PARSE_C) + mbedtls_pem_init( &pem ); + + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( dhminlen == 0 || dhmin[dhminlen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN DH PARAMETERS-----", + "-----END DH PARAMETERS-----", + dhmin, NULL, 0, &dhminlen ); + + if( ret == 0 ) + { + /* + * Was PEM encoded + */ + dhminlen = pem.buflen; + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + goto exit; + + p = ( ret == 0 ) ? pem.buf : (unsigned char *) dhmin; +#else + p = (unsigned char *) dhmin; +#endif /* MBEDTLS_PEM_PARSE_C */ + end = p + dhminlen; + + /* + * DHParams ::= SEQUENCE { + * prime INTEGER, -- P + * generator INTEGER, -- g + * privateValueLength INTEGER OPTIONAL + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret; + goto exit; + } + + end = p + len; + + if( ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->P ) ) != 0 || + ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->G ) ) != 0 ) + { + ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret; + goto exit; + } + + if( p != end ) + { + /* This might be the optional privateValueLength. + * If so, we can cleanly discard it */ + mbedtls_mpi rec; + mbedtls_mpi_init( &rec ); + ret = mbedtls_asn1_get_mpi( &p, end, &rec ); + mbedtls_mpi_free( &rec ); + if ( ret != 0 ) + { + ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret; + goto exit; + } + if ( p != end ) + { + ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; + goto exit; + } + } + + ret = 0; + + dhm->len = mbedtls_mpi_size( &dhm->P ); + +exit: +#if defined(MBEDTLS_PEM_PARSE_C) + mbedtls_pem_free( &pem ); +#endif + if( ret != 0 ) + mbedtls_dhm_free( dhm ); + + return( ret ); +} + +#if defined(MBEDTLS_FS_IO) +/* + * Load all data from a file into a given buffer. + * + * The file is expected to contain either PEM or DER encoded data. + * A terminating null byte is always appended. It is included in the announced + * length only if the data looks like it is PEM encoded. + */ +static int load_file( const char *path, unsigned char **buf, size_t *n ) +{ + FILE *f; + long size; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( MBEDTLS_ERR_DHM_FILE_IO_ERROR ); + + fseek( f, 0, SEEK_END ); + if( ( size = ftell( f ) ) == -1 ) + { + fclose( f ); + return( MBEDTLS_ERR_DHM_FILE_IO_ERROR ); + } + fseek( f, 0, SEEK_SET ); + + *n = (size_t) size; + + if( *n + 1 == 0 || + ( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL ) + { + fclose( f ); + return( MBEDTLS_ERR_DHM_ALLOC_FAILED ); + } + + if( fread( *buf, 1, *n, f ) != *n ) + { + fclose( f ); + + mbedtls_platform_zeroize( *buf, *n + 1 ); + mbedtls_free( *buf ); + + return( MBEDTLS_ERR_DHM_FILE_IO_ERROR ); + } + + fclose( f ); + + (*buf)[*n] = '\0'; + + if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL ) + ++*n; + + return( 0 ); +} + +/* + * Load and parse DHM parameters + */ +int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n; + unsigned char *buf; + DHM_VALIDATE_RET( dhm != NULL ); + DHM_VALIDATE_RET( path != NULL ); + + if( ( ret = load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = mbedtls_dhm_parse_dhm( dhm, buf, n ); + + mbedtls_platform_zeroize( buf, n ); + mbedtls_free( buf ); + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ +#endif /* MBEDTLS_ASN1_PARSE_C */ +#endif /* MBEDTLS_DHM_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +#if defined(MBEDTLS_PEM_PARSE_C) +static const char mbedtls_test_dhm_params[] = +"-----BEGIN DH PARAMETERS-----\r\n" +"MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n" +"1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n" +"9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n" +"-----END DH PARAMETERS-----\r\n"; +#else /* MBEDTLS_PEM_PARSE_C */ +static const char mbedtls_test_dhm_params[] = { + 0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0x9e, 0x35, 0xf4, 0x30, 0x44, + 0x3a, 0x09, 0x90, 0x4f, 0x3a, 0x39, 0xa9, 0x79, 0x79, 0x7d, 0x07, 0x0d, + 0xf5, 0x33, 0x78, 0xe7, 0x9c, 0x24, 0x38, 0xbe, 0xf4, 0xe7, 0x61, 0xf3, + 0xc7, 0x14, 0x55, 0x33, 0x28, 0x58, 0x9b, 0x04, 0x1c, 0x80, 0x9b, 0xe1, + 0xd6, 0xc6, 0xb5, 0xf1, 0xfc, 0x9f, 0x47, 0xd3, 0xa2, 0x54, 0x43, 0x18, + 0x82, 0x53, 0xa9, 0x92, 0xa5, 0x68, 0x18, 0xb3, 0x7b, 0xa9, 0xde, 0x5a, + 0x40, 0xd3, 0x62, 0xe5, 0x6e, 0xff, 0x0b, 0xe5, 0x41, 0x74, 0x74, 0xc1, + 0x25, 0xc1, 0x99, 0x27, 0x2c, 0x8f, 0xe4, 0x1d, 0xea, 0x73, 0x3d, 0xf6, + 0xf6, 0x62, 0xc9, 0x2a, 0xe7, 0x65, 0x56, 0xe7, 0x55, 0xd1, 0x0c, 0x64, + 0xe6, 0xa5, 0x09, 0x68, 0xf6, 0x7f, 0xc6, 0xea, 0x73, 0xd0, 0xdc, 0xa8, + 0x56, 0x9b, 0xe2, 0xba, 0x20, 0x4e, 0x23, 0x58, 0x0d, 0x8b, 0xca, 0x2f, + 0x49, 0x75, 0xb3, 0x02, 0x01, 0x02 }; +#endif /* MBEDTLS_PEM_PARSE_C */ + +static const size_t mbedtls_test_dhm_params_len = sizeof( mbedtls_test_dhm_params ); + +/* + * Checkup routine + */ +int mbedtls_dhm_self_test( int verbose ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_dhm_context dhm; + + mbedtls_dhm_init( &dhm ); + + if( verbose != 0 ) + mbedtls_printf( " DHM parameter load: " ); + + if( ( ret = mbedtls_dhm_parse_dhm( &dhm, + (const unsigned char *) mbedtls_test_dhm_params, + mbedtls_test_dhm_params_len ) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n\n" ); + +exit: + mbedtls_dhm_free( &dhm ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_DHM_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/ecdh.c b/Android/Level4/app/src/main/c/mbedtls/library/ecdh.c new file mode 100644 index 0000000..9dfa868 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/ecdh.c @@ -0,0 +1,729 @@ +/* + * Elliptic curve Diffie-Hellman + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ + +/* + * References: + * + * SEC1 http://www.secg.org/index.php?action=secg,docs_secg + * RFC 4492 + */ + +#include "common.h" + +#if defined(MBEDTLS_ECDH_C) + +#include "mbedtls/ecdh.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +/* Parameter validation macros based on platform_util.h */ +#define ECDH_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA ) +#define ECDH_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) +typedef mbedtls_ecdh_context mbedtls_ecdh_context_mbed; +#endif + +static mbedtls_ecp_group_id mbedtls_ecdh_grp_id( + const mbedtls_ecdh_context *ctx ) +{ +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ctx->grp.id ); +#else + return( ctx->grp_id ); +#endif +} + +int mbedtls_ecdh_can_do( mbedtls_ecp_group_id gid ) +{ + /* At this time, all groups support ECDH. */ + (void) gid; + return( 1 ); +} + +#if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT) +/* + * Generate public key (restartable version) + * + * Note: this internal function relies on its caller preserving the value of + * the output parameter 'd' across continuation calls. This would not be + * acceptable for a public function but is OK here as we control call sites. + */ +static int ecdh_gen_public_restartable( mbedtls_ecp_group *grp, + mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* If multiplication is in progress, we already generated a privkey */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx == NULL || rs_ctx->rsm == NULL ) +#endif + MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) ); + + MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, Q, d, &grp->G, + f_rng, p_rng, rs_ctx ) ); + +cleanup: + return( ret ); +} + +/* + * Generate public key + */ +int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + ECDH_VALIDATE_RET( grp != NULL ); + ECDH_VALIDATE_RET( d != NULL ); + ECDH_VALIDATE_RET( Q != NULL ); + ECDH_VALIDATE_RET( f_rng != NULL ); + return( ecdh_gen_public_restartable( grp, d, Q, f_rng, p_rng, NULL ) ); +} +#endif /* !MBEDTLS_ECDH_GEN_PUBLIC_ALT */ + +#if !defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT) +/* + * Compute shared secret (SEC1 3.3.1) + */ +static int ecdh_compute_shared_restartable( mbedtls_ecp_group *grp, + mbedtls_mpi *z, + const mbedtls_ecp_point *Q, const mbedtls_mpi *d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_point P; + + mbedtls_ecp_point_init( &P ); + + MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, &P, d, Q, + f_rng, p_rng, rs_ctx ) ); + + if( mbedtls_ecp_is_zero( &P ) ) + { + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( z, &P.X ) ); + +cleanup: + mbedtls_ecp_point_free( &P ); + + return( ret ); +} + +/* + * Compute shared secret (SEC1 3.3.1) + */ +int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z, + const mbedtls_ecp_point *Q, const mbedtls_mpi *d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + ECDH_VALIDATE_RET( grp != NULL ); + ECDH_VALIDATE_RET( Q != NULL ); + ECDH_VALIDATE_RET( d != NULL ); + ECDH_VALIDATE_RET( z != NULL ); + return( ecdh_compute_shared_restartable( grp, z, Q, d, + f_rng, p_rng, NULL ) ); +} +#endif /* !MBEDTLS_ECDH_COMPUTE_SHARED_ALT */ + +static void ecdh_init_internal( mbedtls_ecdh_context_mbed *ctx ) +{ + mbedtls_ecp_group_init( &ctx->grp ); + mbedtls_mpi_init( &ctx->d ); + mbedtls_ecp_point_init( &ctx->Q ); + mbedtls_ecp_point_init( &ctx->Qp ); + mbedtls_mpi_init( &ctx->z ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_ecp_restart_init( &ctx->rs ); +#endif +} + +/* + * Initialize context + */ +void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx ) +{ + ECDH_VALIDATE( ctx != NULL ); + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + ecdh_init_internal( ctx ); + mbedtls_ecp_point_init( &ctx->Vi ); + mbedtls_ecp_point_init( &ctx->Vf ); + mbedtls_mpi_init( &ctx->_d ); +#else + memset( ctx, 0, sizeof( mbedtls_ecdh_context ) ); + + ctx->var = MBEDTLS_ECDH_VARIANT_NONE; +#endif + ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; +#if defined(MBEDTLS_ECP_RESTARTABLE) + ctx->restart_enabled = 0; +#endif +} + +static int ecdh_setup_internal( mbedtls_ecdh_context_mbed *ctx, + mbedtls_ecp_group_id grp_id ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + ret = mbedtls_ecp_group_load( &ctx->grp, grp_id ); + if( ret != 0 ) + { + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); + } + + return( 0 ); +} + +/* + * Setup context + */ +int mbedtls_ecdh_setup( mbedtls_ecdh_context *ctx, mbedtls_ecp_group_id grp_id ) +{ + ECDH_VALIDATE_RET( ctx != NULL ); + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ecdh_setup_internal( ctx, grp_id ) ); +#else + switch( grp_id ) + { +#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) + case MBEDTLS_ECP_DP_CURVE25519: + ctx->point_format = MBEDTLS_ECP_PF_COMPRESSED; + ctx->var = MBEDTLS_ECDH_VARIANT_EVEREST; + ctx->grp_id = grp_id; + return( mbedtls_everest_setup( &ctx->ctx.everest_ecdh, grp_id ) ); +#endif + default: + ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; + ctx->var = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0; + ctx->grp_id = grp_id; + ecdh_init_internal( &ctx->ctx.mbed_ecdh ); + return( ecdh_setup_internal( &ctx->ctx.mbed_ecdh, grp_id ) ); + } +#endif +} + +static void ecdh_free_internal( mbedtls_ecdh_context_mbed *ctx ) +{ + mbedtls_ecp_group_free( &ctx->grp ); + mbedtls_mpi_free( &ctx->d ); + mbedtls_ecp_point_free( &ctx->Q ); + mbedtls_ecp_point_free( &ctx->Qp ); + mbedtls_mpi_free( &ctx->z ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_ecp_restart_free( &ctx->rs ); +#endif +} + +#if defined(MBEDTLS_ECP_RESTARTABLE) +/* + * Enable restartable operations for context + */ +void mbedtls_ecdh_enable_restart( mbedtls_ecdh_context *ctx ) +{ + ECDH_VALIDATE( ctx != NULL ); + + ctx->restart_enabled = 1; +} +#endif + +/* + * Free context + */ +void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx ) +{ + if( ctx == NULL ) + return; + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + mbedtls_ecp_point_free( &ctx->Vi ); + mbedtls_ecp_point_free( &ctx->Vf ); + mbedtls_mpi_free( &ctx->_d ); + ecdh_free_internal( ctx ); +#else + switch( ctx->var ) + { +#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) + case MBEDTLS_ECDH_VARIANT_EVEREST: + mbedtls_everest_free( &ctx->ctx.everest_ecdh ); + break; +#endif + case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: + ecdh_free_internal( &ctx->ctx.mbed_ecdh ); + break; + default: + break; + } + + ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; + ctx->var = MBEDTLS_ECDH_VARIANT_NONE; + ctx->grp_id = MBEDTLS_ECP_DP_NONE; +#endif +} + +static int ecdh_make_params_internal( mbedtls_ecdh_context_mbed *ctx, + size_t *olen, int point_format, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, + unsigned char *, + size_t), + void *p_rng, + int restart_enabled ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t grp_len, pt_len; +#if defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_ecp_restart_ctx *rs_ctx = NULL; +#endif + + if( ctx->grp.pbits == 0 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( restart_enabled ) + rs_ctx = &ctx->rs; +#else + (void) restart_enabled; +#endif + + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q, + f_rng, p_rng, rs_ctx ) ) != 0 ) + return( ret ); +#else + if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, + f_rng, p_rng ) ) != 0 ) + return( ret ); +#endif /* MBEDTLS_ECP_RESTARTABLE */ + + if( ( ret = mbedtls_ecp_tls_write_group( &ctx->grp, &grp_len, buf, + blen ) ) != 0 ) + return( ret ); + + buf += grp_len; + blen -= grp_len; + + if( ( ret = mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, point_format, + &pt_len, buf, blen ) ) != 0 ) + return( ret ); + + *olen = grp_len + pt_len; + return( 0 ); +} + +/* + * Setup and write the ServerKeyExchange parameters (RFC 4492) + * struct { + * ECParameters curve_params; + * ECPoint public; + * } ServerECDHParams; + */ +int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int restart_enabled = 0; + ECDH_VALIDATE_RET( ctx != NULL ); + ECDH_VALIDATE_RET( olen != NULL ); + ECDH_VALIDATE_RET( buf != NULL ); + ECDH_VALIDATE_RET( f_rng != NULL ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + restart_enabled = ctx->restart_enabled; +#else + (void) restart_enabled; +#endif + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ecdh_make_params_internal( ctx, olen, ctx->point_format, buf, blen, + f_rng, p_rng, restart_enabled ) ); +#else + switch( ctx->var ) + { +#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) + case MBEDTLS_ECDH_VARIANT_EVEREST: + return( mbedtls_everest_make_params( &ctx->ctx.everest_ecdh, olen, + buf, blen, f_rng, p_rng ) ); +#endif + case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: + return( ecdh_make_params_internal( &ctx->ctx.mbed_ecdh, olen, + ctx->point_format, buf, blen, + f_rng, p_rng, + restart_enabled ) ); + default: + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } +#endif +} + +static int ecdh_read_params_internal( mbedtls_ecdh_context_mbed *ctx, + const unsigned char **buf, + const unsigned char *end ) +{ + return( mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, buf, + end - *buf ) ); +} + +/* + * Read the ServerKeyExhange parameters (RFC 4492) + * struct { + * ECParameters curve_params; + * ECPoint public; + * } ServerECDHParams; + */ +int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx, + const unsigned char **buf, + const unsigned char *end ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_group_id grp_id; + ECDH_VALIDATE_RET( ctx != NULL ); + ECDH_VALIDATE_RET( buf != NULL ); + ECDH_VALIDATE_RET( *buf != NULL ); + ECDH_VALIDATE_RET( end != NULL ); + + if( ( ret = mbedtls_ecp_tls_read_group_id( &grp_id, buf, end - *buf ) ) + != 0 ) + return( ret ); + + if( ( ret = mbedtls_ecdh_setup( ctx, grp_id ) ) != 0 ) + return( ret ); + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ecdh_read_params_internal( ctx, buf, end ) ); +#else + switch( ctx->var ) + { +#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) + case MBEDTLS_ECDH_VARIANT_EVEREST: + return( mbedtls_everest_read_params( &ctx->ctx.everest_ecdh, + buf, end) ); +#endif + case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: + return( ecdh_read_params_internal( &ctx->ctx.mbed_ecdh, + buf, end ) ); + default: + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } +#endif +} + +static int ecdh_get_params_internal( mbedtls_ecdh_context_mbed *ctx, + const mbedtls_ecp_keypair *key, + mbedtls_ecdh_side side ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* If it's not our key, just import the public part as Qp */ + if( side == MBEDTLS_ECDH_THEIRS ) + return( mbedtls_ecp_copy( &ctx->Qp, &key->Q ) ); + + /* Our key: import public (as Q) and private parts */ + if( side != MBEDTLS_ECDH_OURS ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_ecp_copy( &ctx->Q, &key->Q ) ) != 0 || + ( ret = mbedtls_mpi_copy( &ctx->d, &key->d ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +/* + * Get parameters from a keypair + */ +int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, + const mbedtls_ecp_keypair *key, + mbedtls_ecdh_side side ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + ECDH_VALIDATE_RET( ctx != NULL ); + ECDH_VALIDATE_RET( key != NULL ); + ECDH_VALIDATE_RET( side == MBEDTLS_ECDH_OURS || + side == MBEDTLS_ECDH_THEIRS ); + + if( mbedtls_ecdh_grp_id( ctx ) == MBEDTLS_ECP_DP_NONE ) + { + /* This is the first call to get_params(). Set up the context + * for use with the group. */ + if( ( ret = mbedtls_ecdh_setup( ctx, key->grp.id ) ) != 0 ) + return( ret ); + } + else + { + /* This is not the first call to get_params(). Check that the + * current key's group is the same as the context's, which was set + * from the first key's group. */ + if( mbedtls_ecdh_grp_id( ctx ) != key->grp.id ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + } + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ecdh_get_params_internal( ctx, key, side ) ); +#else + switch( ctx->var ) + { +#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) + case MBEDTLS_ECDH_VARIANT_EVEREST: + { + mbedtls_everest_ecdh_side s = side == MBEDTLS_ECDH_OURS ? + MBEDTLS_EVEREST_ECDH_OURS : + MBEDTLS_EVEREST_ECDH_THEIRS; + return( mbedtls_everest_get_params( &ctx->ctx.everest_ecdh, + key, s) ); + } +#endif + case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: + return( ecdh_get_params_internal( &ctx->ctx.mbed_ecdh, + key, side ) ); + default: + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } +#endif +} + +static int ecdh_make_public_internal( mbedtls_ecdh_context_mbed *ctx, + size_t *olen, int point_format, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, + unsigned char *, + size_t), + void *p_rng, + int restart_enabled ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; +#if defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_ecp_restart_ctx *rs_ctx = NULL; +#endif + + if( ctx->grp.pbits == 0 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( restart_enabled ) + rs_ctx = &ctx->rs; +#else + (void) restart_enabled; +#endif + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q, + f_rng, p_rng, rs_ctx ) ) != 0 ) + return( ret ); +#else + if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, + f_rng, p_rng ) ) != 0 ) + return( ret ); +#endif /* MBEDTLS_ECP_RESTARTABLE */ + + return mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, point_format, olen, + buf, blen ); +} + +/* + * Setup and export the client public value + */ +int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int restart_enabled = 0; + ECDH_VALIDATE_RET( ctx != NULL ); + ECDH_VALIDATE_RET( olen != NULL ); + ECDH_VALIDATE_RET( buf != NULL ); + ECDH_VALIDATE_RET( f_rng != NULL ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + restart_enabled = ctx->restart_enabled; +#endif + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ecdh_make_public_internal( ctx, olen, ctx->point_format, buf, blen, + f_rng, p_rng, restart_enabled ) ); +#else + switch( ctx->var ) + { +#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) + case MBEDTLS_ECDH_VARIANT_EVEREST: + return( mbedtls_everest_make_public( &ctx->ctx.everest_ecdh, olen, + buf, blen, f_rng, p_rng ) ); +#endif + case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: + return( ecdh_make_public_internal( &ctx->ctx.mbed_ecdh, olen, + ctx->point_format, buf, blen, + f_rng, p_rng, + restart_enabled ) ); + default: + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } +#endif +} + +static int ecdh_read_public_internal( mbedtls_ecdh_context_mbed *ctx, + const unsigned char *buf, size_t blen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const unsigned char *p = buf; + + if( ( ret = mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, &p, + blen ) ) != 0 ) + return( ret ); + + if( (size_t)( p - buf ) != blen ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + return( 0 ); +} + +/* + * Parse and import the client's public value + */ +int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx, + const unsigned char *buf, size_t blen ) +{ + ECDH_VALIDATE_RET( ctx != NULL ); + ECDH_VALIDATE_RET( buf != NULL ); + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ecdh_read_public_internal( ctx, buf, blen ) ); +#else + switch( ctx->var ) + { +#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) + case MBEDTLS_ECDH_VARIANT_EVEREST: + return( mbedtls_everest_read_public( &ctx->ctx.everest_ecdh, + buf, blen ) ); +#endif + case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: + return( ecdh_read_public_internal( &ctx->ctx.mbed_ecdh, + buf, blen ) ); + default: + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } +#endif +} + +static int ecdh_calc_secret_internal( mbedtls_ecdh_context_mbed *ctx, + size_t *olen, unsigned char *buf, + size_t blen, + int (*f_rng)(void *, + unsigned char *, + size_t), + void *p_rng, + int restart_enabled ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; +#if defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_ecp_restart_ctx *rs_ctx = NULL; +#endif + + if( ctx == NULL || ctx->grp.pbits == 0 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( restart_enabled ) + rs_ctx = &ctx->rs; +#else + (void) restart_enabled; +#endif + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( ( ret = ecdh_compute_shared_restartable( &ctx->grp, &ctx->z, &ctx->Qp, + &ctx->d, f_rng, p_rng, + rs_ctx ) ) != 0 ) + { + return( ret ); + } +#else + if( ( ret = mbedtls_ecdh_compute_shared( &ctx->grp, &ctx->z, &ctx->Qp, + &ctx->d, f_rng, p_rng ) ) != 0 ) + { + return( ret ); + } +#endif /* MBEDTLS_ECP_RESTARTABLE */ + + if( mbedtls_mpi_size( &ctx->z ) > blen ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + *olen = ctx->grp.pbits / 8 + ( ( ctx->grp.pbits % 8 ) != 0 ); + + if( mbedtls_ecp_get_type( &ctx->grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY ) + return mbedtls_mpi_write_binary_le( &ctx->z, buf, *olen ); + + return mbedtls_mpi_write_binary( &ctx->z, buf, *olen ); +} + +/* + * Derive and export the shared secret + */ +int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int restart_enabled = 0; + ECDH_VALIDATE_RET( ctx != NULL ); + ECDH_VALIDATE_RET( olen != NULL ); + ECDH_VALIDATE_RET( buf != NULL ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + restart_enabled = ctx->restart_enabled; +#endif + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ecdh_calc_secret_internal( ctx, olen, buf, blen, f_rng, p_rng, + restart_enabled ) ); +#else + switch( ctx->var ) + { +#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) + case MBEDTLS_ECDH_VARIANT_EVEREST: + return( mbedtls_everest_calc_secret( &ctx->ctx.everest_ecdh, olen, + buf, blen, f_rng, p_rng ) ); +#endif + case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: + return( ecdh_calc_secret_internal( &ctx->ctx.mbed_ecdh, olen, buf, + blen, f_rng, p_rng, + restart_enabled ) ); + default: + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + } +#endif +} + +#endif /* MBEDTLS_ECDH_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/ecdsa.c b/Android/Level4/app/src/main/c/mbedtls/library/ecdsa.c new file mode 100644 index 0000000..22fb5e3 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/ecdsa.c @@ -0,0 +1,1002 @@ +/* + * Elliptic curve DSA + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ + +/* + * References: + * + * SEC1 http://www.secg.org/index.php?action=secg,docs_secg + */ + +#include "common.h" + +#if defined(MBEDTLS_ECDSA_C) + +#include "mbedtls/ecdsa.h" +#include "mbedtls/asn1write.h" + +#include + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +#include "mbedtls/hmac_drbg.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +/* Parameter validation macros based on platform_util.h */ +#define ECDSA_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA ) +#define ECDSA_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if defined(MBEDTLS_ECP_RESTARTABLE) + +/* + * Sub-context for ecdsa_verify() + */ +struct mbedtls_ecdsa_restart_ver +{ + mbedtls_mpi u1, u2; /* intermediate values */ + enum { /* what to do next? */ + ecdsa_ver_init = 0, /* getting started */ + ecdsa_ver_muladd, /* muladd step */ + } state; +}; + +/* + * Init verify restart sub-context + */ +static void ecdsa_restart_ver_init( mbedtls_ecdsa_restart_ver_ctx *ctx ) +{ + mbedtls_mpi_init( &ctx->u1 ); + mbedtls_mpi_init( &ctx->u2 ); + ctx->state = ecdsa_ver_init; +} + +/* + * Free the components of a verify restart sub-context + */ +static void ecdsa_restart_ver_free( mbedtls_ecdsa_restart_ver_ctx *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_mpi_free( &ctx->u1 ); + mbedtls_mpi_free( &ctx->u2 ); + + ecdsa_restart_ver_init( ctx ); +} + +/* + * Sub-context for ecdsa_sign() + */ +struct mbedtls_ecdsa_restart_sig +{ + int sign_tries; + int key_tries; + mbedtls_mpi k; /* per-signature random */ + mbedtls_mpi r; /* r value */ + enum { /* what to do next? */ + ecdsa_sig_init = 0, /* getting started */ + ecdsa_sig_mul, /* doing ecp_mul() */ + ecdsa_sig_modn, /* mod N computations */ + } state; +}; + +/* + * Init verify sign sub-context + */ +static void ecdsa_restart_sig_init( mbedtls_ecdsa_restart_sig_ctx *ctx ) +{ + ctx->sign_tries = 0; + ctx->key_tries = 0; + mbedtls_mpi_init( &ctx->k ); + mbedtls_mpi_init( &ctx->r ); + ctx->state = ecdsa_sig_init; +} + +/* + * Free the components of a sign restart sub-context + */ +static void ecdsa_restart_sig_free( mbedtls_ecdsa_restart_sig_ctx *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_mpi_free( &ctx->k ); + mbedtls_mpi_free( &ctx->r ); +} + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +/* + * Sub-context for ecdsa_sign_det() + */ +struct mbedtls_ecdsa_restart_det +{ + mbedtls_hmac_drbg_context rng_ctx; /* DRBG state */ + enum { /* what to do next? */ + ecdsa_det_init = 0, /* getting started */ + ecdsa_det_sign, /* make signature */ + } state; +}; + +/* + * Init verify sign_det sub-context + */ +static void ecdsa_restart_det_init( mbedtls_ecdsa_restart_det_ctx *ctx ) +{ + mbedtls_hmac_drbg_init( &ctx->rng_ctx ); + ctx->state = ecdsa_det_init; +} + +/* + * Free the components of a sign_det restart sub-context + */ +static void ecdsa_restart_det_free( mbedtls_ecdsa_restart_det_ctx *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_hmac_drbg_free( &ctx->rng_ctx ); + + ecdsa_restart_det_init( ctx ); +} +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ + +#define ECDSA_RS_ECP ( rs_ctx == NULL ? NULL : &rs_ctx->ecp ) + +/* Utility macro for checking and updating ops budget */ +#define ECDSA_BUDGET( ops ) \ + MBEDTLS_MPI_CHK( mbedtls_ecp_check_budget( grp, ECDSA_RS_ECP, ops ) ); + +/* Call this when entering a function that needs its own sub-context */ +#define ECDSA_RS_ENTER( SUB ) do { \ + /* reset ops count for this call if top-level */ \ + if( rs_ctx != NULL && rs_ctx->ecp.depth++ == 0 ) \ + rs_ctx->ecp.ops_done = 0; \ + \ + /* set up our own sub-context if needed */ \ + if( mbedtls_ecp_restart_is_enabled() && \ + rs_ctx != NULL && rs_ctx->SUB == NULL ) \ + { \ + rs_ctx->SUB = mbedtls_calloc( 1, sizeof( *rs_ctx->SUB ) ); \ + if( rs_ctx->SUB == NULL ) \ + return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); \ + \ + ecdsa_restart_## SUB ##_init( rs_ctx->SUB ); \ + } \ +} while( 0 ) + +/* Call this when leaving a function that needs its own sub-context */ +#define ECDSA_RS_LEAVE( SUB ) do { \ + /* clear our sub-context when not in progress (done or error) */ \ + if( rs_ctx != NULL && rs_ctx->SUB != NULL && \ + ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) \ + { \ + ecdsa_restart_## SUB ##_free( rs_ctx->SUB ); \ + mbedtls_free( rs_ctx->SUB ); \ + rs_ctx->SUB = NULL; \ + } \ + \ + if( rs_ctx != NULL ) \ + rs_ctx->ecp.depth--; \ +} while( 0 ) + +#else /* MBEDTLS_ECP_RESTARTABLE */ + +#define ECDSA_RS_ECP NULL + +#define ECDSA_BUDGET( ops ) /* no-op; for compatibility */ + +#define ECDSA_RS_ENTER( SUB ) (void) rs_ctx +#define ECDSA_RS_LEAVE( SUB ) (void) rs_ctx + +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +/* + * Derive a suitable integer for group grp from a buffer of length len + * SEC1 4.1.3 step 5 aka SEC1 4.1.4 step 3 + */ +static int derive_mpi( const mbedtls_ecp_group *grp, mbedtls_mpi *x, + const unsigned char *buf, size_t blen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n_size = ( grp->nbits + 7 ) / 8; + size_t use_size = blen > n_size ? n_size : blen; + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( x, buf, use_size ) ); + if( use_size * 8 > grp->nbits ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( x, use_size * 8 - grp->nbits ) ); + + /* While at it, reduce modulo N */ + if( mbedtls_mpi_cmp_mpi( x, &grp->N ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( x, x, &grp->N ) ); + +cleanup: + return( ret ); +} + +#if !defined(MBEDTLS_ECDSA_SIGN_ALT) +/* + * Compute ECDSA signature of a hashed message (SEC1 4.1.3) + * Obviously, compared to SEC1 4.1.3, we skip step 4 (hash message) + */ +static int ecdsa_sign_restartable( mbedtls_ecp_group *grp, + mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + int (*f_rng_blind)(void *, unsigned char *, size_t), + void *p_rng_blind, + mbedtls_ecdsa_restart_ctx *rs_ctx ) +{ + int ret, key_tries, sign_tries; + int *p_sign_tries = &sign_tries, *p_key_tries = &key_tries; + mbedtls_ecp_point R; + mbedtls_mpi k, e, t; + mbedtls_mpi *pk = &k, *pr = r; + + /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */ + if( ! mbedtls_ecdsa_can_do( grp->id ) || grp->N.p == NULL ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* Make sure d is in range 1..n-1 */ + if( mbedtls_mpi_cmp_int( d, 1 ) < 0 || mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + + mbedtls_ecp_point_init( &R ); + mbedtls_mpi_init( &k ); mbedtls_mpi_init( &e ); mbedtls_mpi_init( &t ); + + ECDSA_RS_ENTER( sig ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->sig != NULL ) + { + /* redirect to our context */ + p_sign_tries = &rs_ctx->sig->sign_tries; + p_key_tries = &rs_ctx->sig->key_tries; + pk = &rs_ctx->sig->k; + pr = &rs_ctx->sig->r; + + /* jump to current step */ + if( rs_ctx->sig->state == ecdsa_sig_mul ) + goto mul; + if( rs_ctx->sig->state == ecdsa_sig_modn ) + goto modn; + } +#endif /* MBEDTLS_ECP_RESTARTABLE */ + + *p_sign_tries = 0; + do + { + if( (*p_sign_tries)++ > 10 ) + { + ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; + goto cleanup; + } + + /* + * Steps 1-3: generate a suitable ephemeral keypair + * and set r = xR mod n + */ + *p_key_tries = 0; + do + { + if( (*p_key_tries)++ > 10 ) + { + ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, pk, f_rng, p_rng ) ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->sig != NULL ) + rs_ctx->sig->state = ecdsa_sig_mul; + +mul: +#endif + MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, &R, pk, &grp->G, + f_rng_blind, + p_rng_blind, + ECDSA_RS_ECP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pr, &R.X, &grp->N ) ); + } + while( mbedtls_mpi_cmp_int( pr, 0 ) == 0 ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->sig != NULL ) + rs_ctx->sig->state = ecdsa_sig_modn; + +modn: +#endif + /* + * Accounting for everything up to the end of the loop + * (step 6, but checking now avoids saving e and t) + */ + ECDSA_BUDGET( MBEDTLS_ECP_OPS_INV + 4 ); + + /* + * Step 5: derive MPI from hashed message + */ + MBEDTLS_MPI_CHK( derive_mpi( grp, &e, buf, blen ) ); + + /* + * Generate a random value to blind inv_mod in next step, + * avoiding a potential timing leak. + */ + MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, &t, f_rng_blind, + p_rng_blind ) ); + + /* + * Step 6: compute s = (e + r * d) / k = t (e + rd) / (kt) mod n + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, pr, d ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &e, &e, s ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &e, &e, &t ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pk, pk, &t ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pk, pk, &grp->N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( s, pk, &grp->N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, s, &e ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( s, s, &grp->N ) ); + } + while( mbedtls_mpi_cmp_int( s, 0 ) == 0 ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->sig != NULL ) + mbedtls_mpi_copy( r, pr ); +#endif + +cleanup: + mbedtls_ecp_point_free( &R ); + mbedtls_mpi_free( &k ); mbedtls_mpi_free( &e ); mbedtls_mpi_free( &t ); + + ECDSA_RS_LEAVE( sig ); + + return( ret ); +} + +int mbedtls_ecdsa_can_do( mbedtls_ecp_group_id gid ) +{ + switch( gid ) + { +#ifdef MBEDTLS_ECP_DP_CURVE25519_ENABLED + case MBEDTLS_ECP_DP_CURVE25519: return 0; +#endif +#ifdef MBEDTLS_ECP_DP_CURVE448_ENABLED + case MBEDTLS_ECP_DP_CURVE448: return 0; +#endif + default: return 1; + } +} + +/* + * Compute ECDSA signature of a hashed message + */ +int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + ECDSA_VALIDATE_RET( grp != NULL ); + ECDSA_VALIDATE_RET( r != NULL ); + ECDSA_VALIDATE_RET( s != NULL ); + ECDSA_VALIDATE_RET( d != NULL ); + ECDSA_VALIDATE_RET( f_rng != NULL ); + ECDSA_VALIDATE_RET( buf != NULL || blen == 0 ); + + /* Use the same RNG for both blinding and ephemeral key generation */ + return( ecdsa_sign_restartable( grp, r, s, d, buf, blen, + f_rng, p_rng, f_rng, p_rng, NULL ) ); +} +#endif /* !MBEDTLS_ECDSA_SIGN_ALT */ + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +/* + * Deterministic signature wrapper + */ +static int ecdsa_sign_det_restartable( mbedtls_ecp_group *grp, + mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + mbedtls_md_type_t md_alg, + int (*f_rng_blind)(void *, unsigned char *, size_t), + void *p_rng_blind, + mbedtls_ecdsa_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_hmac_drbg_context rng_ctx; + mbedtls_hmac_drbg_context *p_rng = &rng_ctx; + unsigned char data[2 * MBEDTLS_ECP_MAX_BYTES]; + size_t grp_len = ( grp->nbits + 7 ) / 8; + const mbedtls_md_info_t *md_info; + mbedtls_mpi h; + + if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) == NULL ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &h ); + mbedtls_hmac_drbg_init( &rng_ctx ); + + ECDSA_RS_ENTER( det ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->det != NULL ) + { + /* redirect to our context */ + p_rng = &rs_ctx->det->rng_ctx; + + /* jump to current step */ + if( rs_ctx->det->state == ecdsa_det_sign ) + goto sign; + } +#endif /* MBEDTLS_ECP_RESTARTABLE */ + + /* Use private key and message hash (reduced) to initialize HMAC_DRBG */ + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( d, data, grp_len ) ); + MBEDTLS_MPI_CHK( derive_mpi( grp, &h, buf, blen ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, data + grp_len, grp_len ) ); + mbedtls_hmac_drbg_seed_buf( p_rng, md_info, data, 2 * grp_len ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->det != NULL ) + rs_ctx->det->state = ecdsa_det_sign; + +sign: +#endif +#if defined(MBEDTLS_ECDSA_SIGN_ALT) + ret = mbedtls_ecdsa_sign( grp, r, s, d, buf, blen, + mbedtls_hmac_drbg_random, p_rng ); +#else + if( f_rng_blind != NULL ) + ret = ecdsa_sign_restartable( grp, r, s, d, buf, blen, + mbedtls_hmac_drbg_random, p_rng, + f_rng_blind, p_rng_blind, rs_ctx ); + else + { + mbedtls_hmac_drbg_context *p_rng_blind_det; + +#if !defined(MBEDTLS_ECP_RESTARTABLE) + /* + * To avoid reusing rng_ctx and risking incorrect behavior we seed a + * second HMAC-DRBG with the same seed. We also apply a label to avoid + * reusing the bits of the ephemeral key for blinding and eliminate the + * risk that they leak this way. + */ + const char* blind_label = "BLINDING CONTEXT"; + mbedtls_hmac_drbg_context rng_ctx_blind; + + mbedtls_hmac_drbg_init( &rng_ctx_blind ); + p_rng_blind_det = &rng_ctx_blind; + mbedtls_hmac_drbg_seed_buf( p_rng_blind_det, md_info, + data, 2 * grp_len ); + ret = mbedtls_hmac_drbg_update_ret( p_rng_blind_det, + (const unsigned char*) blind_label, + strlen( blind_label ) ); + if( ret != 0 ) + { + mbedtls_hmac_drbg_free( &rng_ctx_blind ); + goto cleanup; + } +#else + /* + * In the case of restartable computations we would either need to store + * the second RNG in the restart context too or set it up at every + * restart. The first option would penalize the correct application of + * the function and the second would defeat the purpose of the + * restartable feature. + * + * Therefore in this case we reuse the original RNG. This comes with the + * price that the resulting signature might not be a valid deterministic + * ECDSA signature with a very low probability (same magnitude as + * successfully guessing the private key). However even then it is still + * a valid ECDSA signature. + */ + p_rng_blind_det = p_rng; +#endif /* MBEDTLS_ECP_RESTARTABLE */ + + /* + * Since the output of the RNGs is always the same for the same key and + * message, this limits the efficiency of blinding and leaks information + * through side channels. After mbedtls_ecdsa_sign_det() is removed NULL + * won't be a valid value for f_rng_blind anymore. Therefore it should + * be checked by the caller and this branch and check can be removed. + */ + ret = ecdsa_sign_restartable( grp, r, s, d, buf, blen, + mbedtls_hmac_drbg_random, p_rng, + mbedtls_hmac_drbg_random, p_rng_blind_det, + rs_ctx ); + +#if !defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_hmac_drbg_free( &rng_ctx_blind ); +#endif + } +#endif /* MBEDTLS_ECDSA_SIGN_ALT */ + +cleanup: + mbedtls_hmac_drbg_free( &rng_ctx ); + mbedtls_mpi_free( &h ); + + ECDSA_RS_LEAVE( det ); + + return( ret ); +} + +/* + * Deterministic signature wrappers + */ + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, + mbedtls_mpi *s, const mbedtls_mpi *d, + const unsigned char *buf, size_t blen, + mbedtls_md_type_t md_alg ) +{ + ECDSA_VALIDATE_RET( grp != NULL ); + ECDSA_VALIDATE_RET( r != NULL ); + ECDSA_VALIDATE_RET( s != NULL ); + ECDSA_VALIDATE_RET( d != NULL ); + ECDSA_VALIDATE_RET( buf != NULL || blen == 0 ); + + return( ecdsa_sign_det_restartable( grp, r, s, d, buf, blen, md_alg, + NULL, NULL, NULL ) ); +} +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +int mbedtls_ecdsa_sign_det_ext( mbedtls_ecp_group *grp, mbedtls_mpi *r, + mbedtls_mpi *s, const mbedtls_mpi *d, + const unsigned char *buf, size_t blen, + mbedtls_md_type_t md_alg, + int (*f_rng_blind)(void *, unsigned char *, + size_t), + void *p_rng_blind ) +{ + ECDSA_VALIDATE_RET( grp != NULL ); + ECDSA_VALIDATE_RET( r != NULL ); + ECDSA_VALIDATE_RET( s != NULL ); + ECDSA_VALIDATE_RET( d != NULL ); + ECDSA_VALIDATE_RET( buf != NULL || blen == 0 ); + ECDSA_VALIDATE_RET( f_rng_blind != NULL ); + + return( ecdsa_sign_det_restartable( grp, r, s, d, buf, blen, md_alg, + f_rng_blind, p_rng_blind, NULL ) ); +} +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ + +#if !defined(MBEDTLS_ECDSA_VERIFY_ALT) +/* + * Verify ECDSA signature of hashed message (SEC1 4.1.4) + * Obviously, compared to SEC1 4.1.3, we skip step 2 (hash message) + */ +static int ecdsa_verify_restartable( mbedtls_ecp_group *grp, + const unsigned char *buf, size_t blen, + const mbedtls_ecp_point *Q, + const mbedtls_mpi *r, const mbedtls_mpi *s, + mbedtls_ecdsa_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi e, s_inv, u1, u2; + mbedtls_ecp_point R; + mbedtls_mpi *pu1 = &u1, *pu2 = &u2; + + mbedtls_ecp_point_init( &R ); + mbedtls_mpi_init( &e ); mbedtls_mpi_init( &s_inv ); + mbedtls_mpi_init( &u1 ); mbedtls_mpi_init( &u2 ); + + /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */ + if( ! mbedtls_ecdsa_can_do( grp->id ) || grp->N.p == NULL ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + ECDSA_RS_ENTER( ver ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->ver != NULL ) + { + /* redirect to our context */ + pu1 = &rs_ctx->ver->u1; + pu2 = &rs_ctx->ver->u2; + + /* jump to current step */ + if( rs_ctx->ver->state == ecdsa_ver_muladd ) + goto muladd; + } +#endif /* MBEDTLS_ECP_RESTARTABLE */ + + /* + * Step 1: make sure r and s are in range 1..n-1 + */ + if( mbedtls_mpi_cmp_int( r, 1 ) < 0 || mbedtls_mpi_cmp_mpi( r, &grp->N ) >= 0 || + mbedtls_mpi_cmp_int( s, 1 ) < 0 || mbedtls_mpi_cmp_mpi( s, &grp->N ) >= 0 ) + { + ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; + goto cleanup; + } + + /* + * Step 3: derive MPI from hashed message + */ + MBEDTLS_MPI_CHK( derive_mpi( grp, &e, buf, blen ) ); + + /* + * Step 4: u1 = e / s mod n, u2 = r / s mod n + */ + ECDSA_BUDGET( MBEDTLS_ECP_OPS_CHK + MBEDTLS_ECP_OPS_INV + 2 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &s_inv, s, &grp->N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pu1, &e, &s_inv ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pu1, pu1, &grp->N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pu2, r, &s_inv ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pu2, pu2, &grp->N ) ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->ver != NULL ) + rs_ctx->ver->state = ecdsa_ver_muladd; + +muladd: +#endif + /* + * Step 5: R = u1 G + u2 Q + */ + MBEDTLS_MPI_CHK( mbedtls_ecp_muladd_restartable( grp, + &R, pu1, &grp->G, pu2, Q, ECDSA_RS_ECP ) ); + + if( mbedtls_ecp_is_zero( &R ) ) + { + ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; + goto cleanup; + } + + /* + * Step 6: convert xR to an integer (no-op) + * Step 7: reduce xR mod n (gives v) + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &R.X, &R.X, &grp->N ) ); + + /* + * Step 8: check if v (that is, R.X) is equal to r + */ + if( mbedtls_mpi_cmp_mpi( &R.X, r ) != 0 ) + { + ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; + goto cleanup; + } + +cleanup: + mbedtls_ecp_point_free( &R ); + mbedtls_mpi_free( &e ); mbedtls_mpi_free( &s_inv ); + mbedtls_mpi_free( &u1 ); mbedtls_mpi_free( &u2 ); + + ECDSA_RS_LEAVE( ver ); + + return( ret ); +} + +/* + * Verify ECDSA signature of hashed message + */ +int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp, + const unsigned char *buf, size_t blen, + const mbedtls_ecp_point *Q, + const mbedtls_mpi *r, + const mbedtls_mpi *s) +{ + ECDSA_VALIDATE_RET( grp != NULL ); + ECDSA_VALIDATE_RET( Q != NULL ); + ECDSA_VALIDATE_RET( r != NULL ); + ECDSA_VALIDATE_RET( s != NULL ); + ECDSA_VALIDATE_RET( buf != NULL || blen == 0 ); + + return( ecdsa_verify_restartable( grp, buf, blen, Q, r, s, NULL ) ); +} +#endif /* !MBEDTLS_ECDSA_VERIFY_ALT */ + +/* + * Convert a signature (given by context) to ASN.1 + */ +static int ecdsa_signature_to_asn1( const mbedtls_mpi *r, const mbedtls_mpi *s, + unsigned char *sig, size_t *slen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char buf[MBEDTLS_ECDSA_MAX_LEN]; + unsigned char *p = buf + sizeof( buf ); + size_t len = 0; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &p, buf, s ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &p, buf, r ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &p, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &p, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); + + memcpy( sig, p, len ); + *slen = len; + + return( 0 ); +} + +/* + * Compute and write signature + */ +int mbedtls_ecdsa_write_signature_restartable( mbedtls_ecdsa_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_ecdsa_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi r, s; + ECDSA_VALIDATE_RET( ctx != NULL ); + ECDSA_VALIDATE_RET( hash != NULL ); + ECDSA_VALIDATE_RET( sig != NULL ); + ECDSA_VALIDATE_RET( slen != NULL ); + + mbedtls_mpi_init( &r ); + mbedtls_mpi_init( &s ); + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) + MBEDTLS_MPI_CHK( ecdsa_sign_det_restartable( &ctx->grp, &r, &s, &ctx->d, + hash, hlen, md_alg, f_rng, + p_rng, rs_ctx ) ); +#else + (void) md_alg; + +#if defined(MBEDTLS_ECDSA_SIGN_ALT) + MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ctx->grp, &r, &s, &ctx->d, + hash, hlen, f_rng, p_rng ) ); +#else + /* Use the same RNG for both blinding and ephemeral key generation */ + MBEDTLS_MPI_CHK( ecdsa_sign_restartable( &ctx->grp, &r, &s, &ctx->d, + hash, hlen, f_rng, p_rng, f_rng, + p_rng, rs_ctx ) ); +#endif /* MBEDTLS_ECDSA_SIGN_ALT */ +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ + + MBEDTLS_MPI_CHK( ecdsa_signature_to_asn1( &r, &s, sig, slen ) ); + +cleanup: + mbedtls_mpi_free( &r ); + mbedtls_mpi_free( &s ); + + return( ret ); +} + +/* + * Compute and write signature + */ +int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + ECDSA_VALIDATE_RET( ctx != NULL ); + ECDSA_VALIDATE_RET( hash != NULL ); + ECDSA_VALIDATE_RET( sig != NULL ); + ECDSA_VALIDATE_RET( slen != NULL ); + return( mbedtls_ecdsa_write_signature_restartable( + ctx, md_alg, hash, hlen, sig, slen, f_rng, p_rng, NULL ) ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) && \ + defined(MBEDTLS_ECDSA_DETERMINISTIC) +int mbedtls_ecdsa_write_signature_det( mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + mbedtls_md_type_t md_alg ) +{ + ECDSA_VALIDATE_RET( ctx != NULL ); + ECDSA_VALIDATE_RET( hash != NULL ); + ECDSA_VALIDATE_RET( sig != NULL ); + ECDSA_VALIDATE_RET( slen != NULL ); + return( mbedtls_ecdsa_write_signature( ctx, md_alg, hash, hlen, sig, slen, + NULL, NULL ) ); +} +#endif + +/* + * Read and check signature + */ +int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + const unsigned char *sig, size_t slen ) +{ + ECDSA_VALIDATE_RET( ctx != NULL ); + ECDSA_VALIDATE_RET( hash != NULL ); + ECDSA_VALIDATE_RET( sig != NULL ); + return( mbedtls_ecdsa_read_signature_restartable( + ctx, hash, hlen, sig, slen, NULL ) ); +} + +/* + * Restartable read and check signature + */ +int mbedtls_ecdsa_read_signature_restartable( mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + const unsigned char *sig, size_t slen, + mbedtls_ecdsa_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = (unsigned char *) sig; + const unsigned char *end = sig + slen; + size_t len; + mbedtls_mpi r, s; + ECDSA_VALIDATE_RET( ctx != NULL ); + ECDSA_VALIDATE_RET( hash != NULL ); + ECDSA_VALIDATE_RET( sig != NULL ); + + mbedtls_mpi_init( &r ); + mbedtls_mpi_init( &s ); + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } + + if( p + len != end ) + { + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; + goto cleanup; + } + + if( ( ret = mbedtls_asn1_get_mpi( &p, end, &r ) ) != 0 || + ( ret = mbedtls_asn1_get_mpi( &p, end, &s ) ) != 0 ) + { + ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } +#if defined(MBEDTLS_ECDSA_VERIFY_ALT) + if( ( ret = mbedtls_ecdsa_verify( &ctx->grp, hash, hlen, + &ctx->Q, &r, &s ) ) != 0 ) + goto cleanup; +#else + if( ( ret = ecdsa_verify_restartable( &ctx->grp, hash, hlen, + &ctx->Q, &r, &s, rs_ctx ) ) != 0 ) + goto cleanup; +#endif /* MBEDTLS_ECDSA_VERIFY_ALT */ + + /* At this point we know that the buffer starts with a valid signature. + * Return 0 if the buffer just contains the signature, and a specific + * error code if the valid signature is followed by more data. */ + if( p != end ) + ret = MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH; + +cleanup: + mbedtls_mpi_free( &r ); + mbedtls_mpi_free( &s ); + + return( ret ); +} + +#if !defined(MBEDTLS_ECDSA_GENKEY_ALT) +/* + * Generate key pair + */ +int mbedtls_ecdsa_genkey( mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret = 0; + ECDSA_VALIDATE_RET( ctx != NULL ); + ECDSA_VALIDATE_RET( f_rng != NULL ); + + ret = mbedtls_ecp_group_load( &ctx->grp, gid ); + if( ret != 0 ) + return( ret ); + + return( mbedtls_ecp_gen_keypair( &ctx->grp, &ctx->d, + &ctx->Q, f_rng, p_rng ) ); +} +#endif /* !MBEDTLS_ECDSA_GENKEY_ALT */ + +/* + * Set context from an mbedtls_ecp_keypair + */ +int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + ECDSA_VALIDATE_RET( ctx != NULL ); + ECDSA_VALIDATE_RET( key != NULL ); + + if( ( ret = mbedtls_ecp_group_copy( &ctx->grp, &key->grp ) ) != 0 || + ( ret = mbedtls_mpi_copy( &ctx->d, &key->d ) ) != 0 || + ( ret = mbedtls_ecp_copy( &ctx->Q, &key->Q ) ) != 0 ) + { + mbedtls_ecdsa_free( ctx ); + } + + return( ret ); +} + +/* + * Initialize context + */ +void mbedtls_ecdsa_init( mbedtls_ecdsa_context *ctx ) +{ + ECDSA_VALIDATE( ctx != NULL ); + + mbedtls_ecp_keypair_init( ctx ); +} + +/* + * Free context + */ +void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_ecp_keypair_free( ctx ); +} + +#if defined(MBEDTLS_ECP_RESTARTABLE) +/* + * Initialize a restart context + */ +void mbedtls_ecdsa_restart_init( mbedtls_ecdsa_restart_ctx *ctx ) +{ + ECDSA_VALIDATE( ctx != NULL ); + + mbedtls_ecp_restart_init( &ctx->ecp ); + + ctx->ver = NULL; + ctx->sig = NULL; +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) + ctx->det = NULL; +#endif +} + +/* + * Free the components of a restart context + */ +void mbedtls_ecdsa_restart_free( mbedtls_ecdsa_restart_ctx *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_ecp_restart_free( &ctx->ecp ); + + ecdsa_restart_ver_free( ctx->ver ); + mbedtls_free( ctx->ver ); + ctx->ver = NULL; + + ecdsa_restart_sig_free( ctx->sig ); + mbedtls_free( ctx->sig ); + ctx->sig = NULL; + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) + ecdsa_restart_det_free( ctx->det ); + mbedtls_free( ctx->det ); + ctx->det = NULL; +#endif +} +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +#endif /* MBEDTLS_ECDSA_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/ecjpake.c b/Android/Level4/app/src/main/c/mbedtls/library/ecjpake.c new file mode 100644 index 0000000..315da4a --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/ecjpake.c @@ -0,0 +1,1135 @@ +/* + * Elliptic curve J-PAKE + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ + +/* + * References in the code are to the Thread v1.0 Specification, + * available to members of the Thread Group http://threadgroup.org/ + */ + +#include "common.h" + +#if defined(MBEDTLS_ECJPAKE_C) + +#include "mbedtls/ecjpake.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if !defined(MBEDTLS_ECJPAKE_ALT) + +/* Parameter validation macros based on platform_util.h */ +#define ECJPAKE_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA ) +#define ECJPAKE_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +/* + * Convert a mbedtls_ecjpake_role to identifier string + */ +static const char * const ecjpake_id[] = { + "client", + "server" +}; + +#define ID_MINE ( ecjpake_id[ ctx->role ] ) +#define ID_PEER ( ecjpake_id[ 1 - ctx->role ] ) + +/* + * Initialize context + */ +void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx ) +{ + ECJPAKE_VALIDATE( ctx != NULL ); + + ctx->md_info = NULL; + mbedtls_ecp_group_init( &ctx->grp ); + ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; + + mbedtls_ecp_point_init( &ctx->Xm1 ); + mbedtls_ecp_point_init( &ctx->Xm2 ); + mbedtls_ecp_point_init( &ctx->Xp1 ); + mbedtls_ecp_point_init( &ctx->Xp2 ); + mbedtls_ecp_point_init( &ctx->Xp ); + + mbedtls_mpi_init( &ctx->xm1 ); + mbedtls_mpi_init( &ctx->xm2 ); + mbedtls_mpi_init( &ctx->s ); +} + +/* + * Free context + */ +void mbedtls_ecjpake_free( mbedtls_ecjpake_context *ctx ) +{ + if( ctx == NULL ) + return; + + ctx->md_info = NULL; + mbedtls_ecp_group_free( &ctx->grp ); + + mbedtls_ecp_point_free( &ctx->Xm1 ); + mbedtls_ecp_point_free( &ctx->Xm2 ); + mbedtls_ecp_point_free( &ctx->Xp1 ); + mbedtls_ecp_point_free( &ctx->Xp2 ); + mbedtls_ecp_point_free( &ctx->Xp ); + + mbedtls_mpi_free( &ctx->xm1 ); + mbedtls_mpi_free( &ctx->xm2 ); + mbedtls_mpi_free( &ctx->s ); +} + +/* + * Setup context + */ +int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx, + mbedtls_ecjpake_role role, + mbedtls_md_type_t hash, + mbedtls_ecp_group_id curve, + const unsigned char *secret, + size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + ECJPAKE_VALIDATE_RET( ctx != NULL ); + ECJPAKE_VALIDATE_RET( role == MBEDTLS_ECJPAKE_CLIENT || + role == MBEDTLS_ECJPAKE_SERVER ); + ECJPAKE_VALIDATE_RET( secret != NULL || len == 0 ); + + ctx->role = role; + + if( ( ctx->md_info = mbedtls_md_info_from_type( hash ) ) == NULL ) + return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE ); + + MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ctx->grp, curve ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->s, secret, len ) ); + +cleanup: + if( ret != 0 ) + mbedtls_ecjpake_free( ctx ); + + return( ret ); +} + +/* + * Check if context is ready for use + */ +int mbedtls_ecjpake_check( const mbedtls_ecjpake_context *ctx ) +{ + ECJPAKE_VALIDATE_RET( ctx != NULL ); + + if( ctx->md_info == NULL || + ctx->grp.id == MBEDTLS_ECP_DP_NONE || + ctx->s.p == NULL ) + { + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + } + + return( 0 ); +} + +/* + * Write a point plus its length to a buffer + */ +static int ecjpake_write_len_point( unsigned char **p, + const unsigned char *end, + const mbedtls_ecp_group *grp, + const int pf, + const mbedtls_ecp_point *P ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + /* Need at least 4 for length plus 1 for point */ + if( end < *p || end - *p < 5 ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + ret = mbedtls_ecp_point_write_binary( grp, P, pf, + &len, *p + 4, end - ( *p + 4 ) ); + if( ret != 0 ) + return( ret ); + + (*p)[0] = (unsigned char)( ( len >> 24 ) & 0xFF ); + (*p)[1] = (unsigned char)( ( len >> 16 ) & 0xFF ); + (*p)[2] = (unsigned char)( ( len >> 8 ) & 0xFF ); + (*p)[3] = (unsigned char)( ( len ) & 0xFF ); + + *p += 4 + len; + + return( 0 ); +} + +/* + * Size of the temporary buffer for ecjpake_hash: + * 3 EC points plus their length, plus ID and its length (4 + 6 bytes) + */ +#define ECJPAKE_HASH_BUF_LEN ( 3 * ( 4 + MBEDTLS_ECP_MAX_PT_LEN ) + 4 + 6 ) + +/* + * Compute hash for ZKP (7.4.2.2.2.1) + */ +static int ecjpake_hash( const mbedtls_md_info_t *md_info, + const mbedtls_ecp_group *grp, + const int pf, + const mbedtls_ecp_point *G, + const mbedtls_ecp_point *V, + const mbedtls_ecp_point *X, + const char *id, + mbedtls_mpi *h ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char buf[ECJPAKE_HASH_BUF_LEN]; + unsigned char *p = buf; + const unsigned char *end = buf + sizeof( buf ); + const size_t id_len = strlen( id ); + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; + + /* Write things to temporary buffer */ + MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, G ) ); + MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, V ) ); + MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, X ) ); + + if( end - p < 4 ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + *p++ = (unsigned char)( ( id_len >> 24 ) & 0xFF ); + *p++ = (unsigned char)( ( id_len >> 16 ) & 0xFF ); + *p++ = (unsigned char)( ( id_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( id_len ) & 0xFF ); + + if( end < p || (size_t)( end - p ) < id_len ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + memcpy( p, id, id_len ); + p += id_len; + + /* Compute hash */ + MBEDTLS_MPI_CHK( mbedtls_md( md_info, buf, p - buf, hash ) ); + + /* Turn it into an integer mod n */ + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( h, hash, + mbedtls_md_get_size( md_info ) ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( h, h, &grp->N ) ); + +cleanup: + return( ret ); +} + +/* + * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3) + */ +static int ecjpake_zkp_read( const mbedtls_md_info_t *md_info, + const mbedtls_ecp_group *grp, + const int pf, + const mbedtls_ecp_point *G, + const mbedtls_ecp_point *X, + const char *id, + const unsigned char **p, + const unsigned char *end ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_point V, VV; + mbedtls_mpi r, h; + size_t r_len; + + mbedtls_ecp_point_init( &V ); + mbedtls_ecp_point_init( &VV ); + mbedtls_mpi_init( &r ); + mbedtls_mpi_init( &h ); + + /* + * struct { + * ECPoint V; + * opaque r<1..2^8-1>; + * } ECSchnorrZKP; + */ + if( end < *p ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, &V, p, end - *p ) ); + + if( end < *p || (size_t)( end - *p ) < 1 ) + { + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } + + r_len = *(*p)++; + + if( end < *p || (size_t)( end - *p ) < r_len ) + { + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r, *p, r_len ) ); + *p += r_len; + + /* + * Verification + */ + MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( (mbedtls_ecp_group *) grp, + &VV, &h, X, &r, G ) ); + + if( mbedtls_ecp_point_cmp( &VV, &V ) != 0 ) + { + ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; + goto cleanup; + } + +cleanup: + mbedtls_ecp_point_free( &V ); + mbedtls_ecp_point_free( &VV ); + mbedtls_mpi_free( &r ); + mbedtls_mpi_free( &h ); + + return( ret ); +} + +/* + * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2) + */ +static int ecjpake_zkp_write( const mbedtls_md_info_t *md_info, + const mbedtls_ecp_group *grp, + const int pf, + const mbedtls_ecp_point *G, + const mbedtls_mpi *x, + const mbedtls_ecp_point *X, + const char *id, + unsigned char **p, + const unsigned char *end, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_point V; + mbedtls_mpi v; + mbedtls_mpi h; /* later recycled to hold r */ + size_t len; + + if( end < *p ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + mbedtls_ecp_point_init( &V ); + mbedtls_mpi_init( &v ); + mbedtls_mpi_init( &h ); + + /* Compute signature */ + MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp, + G, &v, &V, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &h, &h, x ) ); /* x*h */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &h, &v, &h ) ); /* v - x*h */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &h, &h, &grp->N ) ); /* r */ + + /* Write it out */ + MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, &V, + pf, &len, *p, end - *p ) ); + *p += len; + + len = mbedtls_mpi_size( &h ); /* actually r */ + if( end < *p || (size_t)( end - *p ) < 1 + len || len > 255 ) + { + ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; + goto cleanup; + } + + *(*p)++ = (unsigned char)( len & 0xFF ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, *p, len ) ); /* r */ + *p += len; + +cleanup: + mbedtls_ecp_point_free( &V ); + mbedtls_mpi_free( &v ); + mbedtls_mpi_free( &h ); + + return( ret ); +} + +/* + * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof + * Output: verified public key X + */ +static int ecjpake_kkp_read( const mbedtls_md_info_t *md_info, + const mbedtls_ecp_group *grp, + const int pf, + const mbedtls_ecp_point *G, + mbedtls_ecp_point *X, + const char *id, + const unsigned char **p, + const unsigned char *end ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( end < *p ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * struct { + * ECPoint X; + * ECSchnorrZKP zkp; + * } ECJPAKEKeyKP; + */ + MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, X, p, end - *p ) ); + if( mbedtls_ecp_is_zero( X ) ) + { + ret = MBEDTLS_ERR_ECP_INVALID_KEY; + goto cleanup; + } + + MBEDTLS_MPI_CHK( ecjpake_zkp_read( md_info, grp, pf, G, X, id, p, end ) ); + +cleanup: + return( ret ); +} + +/* + * Generate an ECJPAKEKeyKP + * Output: the serialized structure, plus private/public key pair + */ +static int ecjpake_kkp_write( const mbedtls_md_info_t *md_info, + const mbedtls_ecp_group *grp, + const int pf, + const mbedtls_ecp_point *G, + mbedtls_mpi *x, + mbedtls_ecp_point *X, + const char *id, + unsigned char **p, + const unsigned char *end, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + if( end < *p ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + /* Generate key (7.4.2.3.1) and write it out */ + MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp, G, x, X, + f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, X, + pf, &len, *p, end - *p ) ); + *p += len; + + /* Generate and write proof */ + MBEDTLS_MPI_CHK( ecjpake_zkp_write( md_info, grp, pf, G, x, X, id, + p, end, f_rng, p_rng ) ); + +cleanup: + return( ret ); +} + +/* + * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs + * Ouputs: verified peer public keys Xa, Xb + */ +static int ecjpake_kkpp_read( const mbedtls_md_info_t *md_info, + const mbedtls_ecp_group *grp, + const int pf, + const mbedtls_ecp_point *G, + mbedtls_ecp_point *Xa, + mbedtls_ecp_point *Xb, + const char *id, + const unsigned char *buf, + size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const unsigned char *p = buf; + const unsigned char *end = buf + len; + + /* + * struct { + * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2]; + * } ECJPAKEKeyKPPairList; + */ + MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xa, id, &p, end ) ); + MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xb, id, &p, end ) ); + + if( p != end ) + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + +cleanup: + return( ret ); +} + +/* + * Generate a ECJPAKEKeyKPPairList + * Outputs: the serialized structure, plus two private/public key pairs + */ +static int ecjpake_kkpp_write( const mbedtls_md_info_t *md_info, + const mbedtls_ecp_group *grp, + const int pf, + const mbedtls_ecp_point *G, + mbedtls_mpi *xm1, + mbedtls_ecp_point *Xa, + mbedtls_mpi *xm2, + mbedtls_ecp_point *Xb, + const char *id, + unsigned char *buf, + size_t len, + size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = buf; + const unsigned char *end = buf + len; + + MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm1, Xa, id, + &p, end, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm2, Xb, id, + &p, end, f_rng, p_rng ) ); + + *olen = p - buf; + +cleanup: + return( ret ); +} + +/* + * Read and process the first round message + */ +int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx, + const unsigned char *buf, + size_t len ) +{ + ECJPAKE_VALIDATE_RET( ctx != NULL ); + ECJPAKE_VALIDATE_RET( buf != NULL ); + + return( ecjpake_kkpp_read( ctx->md_info, &ctx->grp, ctx->point_format, + &ctx->grp.G, + &ctx->Xp1, &ctx->Xp2, ID_PEER, + buf, len ) ); +} + +/* + * Generate and write the first round message + */ +int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx, + unsigned char *buf, size_t len, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + ECJPAKE_VALIDATE_RET( ctx != NULL ); + ECJPAKE_VALIDATE_RET( buf != NULL ); + ECJPAKE_VALIDATE_RET( olen != NULL ); + ECJPAKE_VALIDATE_RET( f_rng != NULL ); + + return( ecjpake_kkpp_write( ctx->md_info, &ctx->grp, ctx->point_format, + &ctx->grp.G, + &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2, + ID_MINE, buf, len, olen, f_rng, p_rng ) ); +} + +/* + * Compute the sum of three points R = A + B + C + */ +static int ecjpake_ecp_add3( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_ecp_point *A, + const mbedtls_ecp_point *B, + const mbedtls_ecp_point *C ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi one; + + mbedtls_mpi_init( &one ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, A, &one, B ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, R, &one, C ) ); + +cleanup: + mbedtls_mpi_free( &one ); + + return( ret ); +} + +/* + * Read and process second round message (C: 7.4.2.5, S: 7.4.2.6) + */ +int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx, + const unsigned char *buf, + size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const unsigned char *p = buf; + const unsigned char *end = buf + len; + mbedtls_ecp_group grp; + mbedtls_ecp_point G; /* C: GB, S: GA */ + + ECJPAKE_VALIDATE_RET( ctx != NULL ); + ECJPAKE_VALIDATE_RET( buf != NULL ); + + mbedtls_ecp_group_init( &grp ); + mbedtls_ecp_point_init( &G ); + + /* + * Server: GA = X3 + X4 + X1 (7.4.2.6.1) + * Client: GB = X1 + X2 + X3 (7.4.2.5.1) + * Unified: G = Xm1 + Xm2 + Xp1 + * We need that before parsing in order to check Xp as we read it + */ + MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G, + &ctx->Xm1, &ctx->Xm2, &ctx->Xp1 ) ); + + /* + * struct { + * ECParameters curve_params; // only client reading server msg + * ECJPAKEKeyKP ecjpake_key_kp; + * } Client/ServerECJPAKEParams; + */ + if( ctx->role == MBEDTLS_ECJPAKE_CLIENT ) + { + MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_group( &grp, &p, len ) ); + if( grp.id != ctx->grp.id ) + { + ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; + goto cleanup; + } + } + + MBEDTLS_MPI_CHK( ecjpake_kkp_read( ctx->md_info, &ctx->grp, + ctx->point_format, + &G, &ctx->Xp, ID_PEER, &p, end ) ); + + if( p != end ) + { + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } + +cleanup: + mbedtls_ecp_group_free( &grp ); + mbedtls_ecp_point_free( &G ); + + return( ret ); +} + +/* + * Compute R = +/- X * S mod N, taking care not to leak S + */ +static int ecjpake_mul_secret( mbedtls_mpi *R, int sign, + const mbedtls_mpi *X, + const mbedtls_mpi *S, + const mbedtls_mpi *N, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi b; /* Blinding value, then s + N * blinding */ + + mbedtls_mpi_init( &b ); + + /* b = s + rnd-128-bit * N */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &b, 16, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &b, &b, N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &b, &b, S ) ); + + /* R = sign * X * b mod N */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( R, X, &b ) ); + R->s *= sign; + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( R, R, N ) ); + +cleanup: + mbedtls_mpi_free( &b ); + + return( ret ); +} + +/* + * Generate and write the second round message (S: 7.4.2.5, C: 7.4.2.6) + */ +int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx, + unsigned char *buf, size_t len, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_point G; /* C: GA, S: GB */ + mbedtls_ecp_point Xm; /* C: Xc, S: Xs */ + mbedtls_mpi xm; /* C: xc, S: xs */ + unsigned char *p = buf; + const unsigned char *end = buf + len; + size_t ec_len; + + ECJPAKE_VALIDATE_RET( ctx != NULL ); + ECJPAKE_VALIDATE_RET( buf != NULL ); + ECJPAKE_VALIDATE_RET( olen != NULL ); + ECJPAKE_VALIDATE_RET( f_rng != NULL ); + + mbedtls_ecp_point_init( &G ); + mbedtls_ecp_point_init( &Xm ); + mbedtls_mpi_init( &xm ); + + /* + * First generate private/public key pair (S: 7.4.2.5.1, C: 7.4.2.6.1) + * + * Client: GA = X1 + X3 + X4 | xs = x2 * s | Xc = xc * GA + * Server: GB = X3 + X1 + X2 | xs = x4 * s | Xs = xs * GB + * Unified: G = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G + */ + MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G, + &ctx->Xp1, &ctx->Xp2, &ctx->Xm1 ) ); + MBEDTLS_MPI_CHK( ecjpake_mul_secret( &xm, 1, &ctx->xm2, &ctx->s, + &ctx->grp.N, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &Xm, &xm, &G, f_rng, p_rng ) ); + + /* + * Now write things out + * + * struct { + * ECParameters curve_params; // only server writing its message + * ECJPAKEKeyKP ecjpake_key_kp; + * } Client/ServerECJPAKEParams; + */ + if( ctx->role == MBEDTLS_ECJPAKE_SERVER ) + { + if( end < p ) + { + ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; + goto cleanup; + } + MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_group( &ctx->grp, &ec_len, + p, end - p ) ); + p += ec_len; + } + + if( end < p ) + { + ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; + goto cleanup; + } + MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( &ctx->grp, &Xm, + ctx->point_format, &ec_len, p, end - p ) ); + p += ec_len; + + MBEDTLS_MPI_CHK( ecjpake_zkp_write( ctx->md_info, &ctx->grp, + ctx->point_format, + &G, &xm, &Xm, ID_MINE, + &p, end, f_rng, p_rng ) ); + + *olen = p - buf; + +cleanup: + mbedtls_ecp_point_free( &G ); + mbedtls_ecp_point_free( &Xm ); + mbedtls_mpi_free( &xm ); + + return( ret ); +} + +/* + * Derive PMS (7.4.2.7 / 7.4.2.8) + */ +int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx, + unsigned char *buf, size_t len, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_point K; + mbedtls_mpi m_xm2_s, one; + unsigned char kx[MBEDTLS_ECP_MAX_BYTES]; + size_t x_bytes; + + ECJPAKE_VALIDATE_RET( ctx != NULL ); + ECJPAKE_VALIDATE_RET( buf != NULL ); + ECJPAKE_VALIDATE_RET( olen != NULL ); + ECJPAKE_VALIDATE_RET( f_rng != NULL ); + + *olen = mbedtls_md_get_size( ctx->md_info ); + if( len < *olen ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + mbedtls_ecp_point_init( &K ); + mbedtls_mpi_init( &m_xm2_s ); + mbedtls_mpi_init( &one ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) ); + + /* + * Client: K = ( Xs - X4 * x2 * s ) * x2 + * Server: K = ( Xc - X2 * x4 * s ) * x4 + * Unified: K = ( Xp - Xp2 * xm2 * s ) * xm2 + */ + MBEDTLS_MPI_CHK( ecjpake_mul_secret( &m_xm2_s, -1, &ctx->xm2, &ctx->s, + &ctx->grp.N, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( &ctx->grp, &K, + &one, &ctx->Xp, + &m_xm2_s, &ctx->Xp2 ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &K, &ctx->xm2, &K, + f_rng, p_rng ) ); + + /* PMS = SHA-256( K.X ) */ + x_bytes = ( ctx->grp.pbits + 7 ) / 8; + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &K.X, kx, x_bytes ) ); + MBEDTLS_MPI_CHK( mbedtls_md( ctx->md_info, kx, x_bytes, buf ) ); + +cleanup: + mbedtls_ecp_point_free( &K ); + mbedtls_mpi_free( &m_xm2_s ); + mbedtls_mpi_free( &one ); + + return( ret ); +} + +#undef ID_MINE +#undef ID_PEER + +#endif /* ! MBEDTLS_ECJPAKE_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif + +#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ + !defined(MBEDTLS_SHA256_C) +int mbedtls_ecjpake_self_test( int verbose ) +{ + (void) verbose; + return( 0 ); +} +#else + +static const unsigned char ecjpake_test_password[] = { + 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74, + 0x65, 0x73, 0x74 +}; + +static const unsigned char ecjpake_test_x1[] = { + 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, 0x21 +}; + +static const unsigned char ecjpake_test_x2[] = { + 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, 0x81 +}; + +static const unsigned char ecjpake_test_x3[] = { + 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, 0x81 +}; + +static const unsigned char ecjpake_test_x4[] = { + 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, 0xe1 +}; + +static const unsigned char ecjpake_test_cli_one[] = { + 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19, + 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44, + 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad, + 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62, + 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9, + 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d, + 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e, + 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e, + 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73, + 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22, + 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce, + 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00, + 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b, + 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e, + 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62, + 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5, + 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb, + 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35, + 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0, + 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb, + 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47, + 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39, + 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97, + 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40, + 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d, + 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa, + 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d, + 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0 +}; + +static const unsigned char ecjpake_test_srv_one[] = { + 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, + 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, + 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, + 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, + 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, + 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d, + 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64, + 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36, + 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2, + 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec, + 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16, + 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96, + 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3, + 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19, + 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f, + 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8, + 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7, + 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea, + 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5, + 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6, + 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31, + 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d, + 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8, + 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee, + 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84, + 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f, + 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80, + 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12 +}; + +static const unsigned char ecjpake_test_srv_two[] = { + 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23, + 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c, + 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f, + 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca, + 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26, + 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55, + 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38, + 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6, + 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9, + 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4, + 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2, + 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8, + 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd, + 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c +}; + +static const unsigned char ecjpake_test_cli_two[] = { + 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46, + 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb, + 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72, + 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce, + 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98, + 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31, + 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15, + 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36, + 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8, + 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45, + 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d, + 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58, + 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82, + 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c +}; + +static const unsigned char ecjpake_test_pms[] = { + 0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7, + 0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9, + 0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51 +}; + +/* Load my private keys and generate the corresponding public keys */ +static int ecjpake_test_load( mbedtls_ecjpake_context *ctx, + const unsigned char *xm1, size_t len1, + const unsigned char *xm2, size_t len2 ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm1, xm1, len1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm2, xm2, len2 ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm1, &ctx->xm1, + &ctx->grp.G, NULL, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm2, &ctx->xm2, + &ctx->grp.G, NULL, NULL ) ); + +cleanup: + return( ret ); +} + +/* For tests we don't need a secure RNG; + * use the LGC from Numerical Recipes for simplicity */ +static int ecjpake_lgc( void *p, unsigned char *out, size_t len ) +{ + static uint32_t x = 42; + (void) p; + + while( len > 0 ) + { + size_t use_len = len > 4 ? 4 : len; + x = 1664525 * x + 1013904223; + memcpy( out, &x, use_len ); + out += use_len; + len -= use_len; + } + + return( 0 ); +} + +#define TEST_ASSERT( x ) \ + do { \ + if( x ) \ + ret = 0; \ + else \ + { \ + ret = 1; \ + goto cleanup; \ + } \ + } while( 0 ) + +/* + * Checkup routine + */ +int mbedtls_ecjpake_self_test( int verbose ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecjpake_context cli; + mbedtls_ecjpake_context srv; + unsigned char buf[512], pms[32]; + size_t len, pmslen; + + mbedtls_ecjpake_init( &cli ); + mbedtls_ecjpake_init( &srv ); + + if( verbose != 0 ) + mbedtls_printf( " ECJPAKE test #0 (setup): " ); + + TEST_ASSERT( mbedtls_ecjpake_setup( &cli, MBEDTLS_ECJPAKE_CLIENT, + MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1, + ecjpake_test_password, + sizeof( ecjpake_test_password ) ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_setup( &srv, MBEDTLS_ECJPAKE_SERVER, + MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1, + ecjpake_test_password, + sizeof( ecjpake_test_password ) ) == 0 ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " ECJPAKE test #1 (random handshake): " ); + + TEST_ASSERT( mbedtls_ecjpake_write_round_one( &cli, + buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv, buf, len ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_write_round_one( &srv, + buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli, buf, len ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_write_round_two( &srv, + buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli, buf, len ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli, + pms, sizeof( pms ), &pmslen, ecjpake_lgc, NULL ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_write_round_two( &cli, + buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv, buf, len ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv, + buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); + + TEST_ASSERT( len == pmslen ); + TEST_ASSERT( memcmp( buf, pms, len ) == 0 ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " ECJPAKE test #2 (reference handshake): " ); + + /* Simulate generation of round one */ + MBEDTLS_MPI_CHK( ecjpake_test_load( &cli, + ecjpake_test_x1, sizeof( ecjpake_test_x1 ), + ecjpake_test_x2, sizeof( ecjpake_test_x2 ) ) ); + + MBEDTLS_MPI_CHK( ecjpake_test_load( &srv, + ecjpake_test_x3, sizeof( ecjpake_test_x3 ), + ecjpake_test_x4, sizeof( ecjpake_test_x4 ) ) ); + + /* Read round one */ + TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv, + ecjpake_test_cli_one, + sizeof( ecjpake_test_cli_one ) ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli, + ecjpake_test_srv_one, + sizeof( ecjpake_test_srv_one ) ) == 0 ); + + /* Skip generation of round two, read round two */ + TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli, + ecjpake_test_srv_two, + sizeof( ecjpake_test_srv_two ) ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv, + ecjpake_test_cli_two, + sizeof( ecjpake_test_cli_two ) ) == 0 ); + + /* Server derives PMS */ + TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv, + buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); + + TEST_ASSERT( len == sizeof( ecjpake_test_pms ) ); + TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 ); + + memset( buf, 0, len ); /* Avoid interferences with next step */ + + /* Client derives PMS */ + TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli, + buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); + + TEST_ASSERT( len == sizeof( ecjpake_test_pms ) ); + TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + +cleanup: + mbedtls_ecjpake_free( &cli ); + mbedtls_ecjpake_free( &srv ); + + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( ret ); +} + +#undef TEST_ASSERT + +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */ + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_ECJPAKE_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/ecp.c b/Android/Level4/app/src/main/c/mbedtls/library/ecp.c new file mode 100644 index 0000000..05a0b01 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/ecp.c @@ -0,0 +1,3505 @@ +/* + * Elliptic curves over GF(p): generic functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ + +/* + * References: + * + * SEC1 http://www.secg.org/index.php?action=secg,docs_secg + * GECC = Guide to Elliptic Curve Cryptography - Hankerson, Menezes, Vanstone + * FIPS 186-3 http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf + * RFC 4492 for the related TLS structures and constants + * RFC 7748 for the Curve448 and Curve25519 curve definitions + * + * [Curve25519] http://cr.yp.to/ecdh/curve25519-20060209.pdf + * + * [2] CORON, Jean-S'ebastien. Resistance against differential power analysis + * for elliptic curve cryptosystems. In : Cryptographic Hardware and + * Embedded Systems. Springer Berlin Heidelberg, 1999. p. 292-302. + * + * + * [3] HEDABOU, Mustapha, PINEL, Pierre, et B'EN'ETEAU, Lucien. A comb method to + * render ECC resistant against Side Channel Attacks. IACR Cryptology + * ePrint Archive, 2004, vol. 2004, p. 342. + * + */ + +#include "common.h" + +/** + * \brief Function level alternative implementation. + * + * The MBEDTLS_ECP_INTERNAL_ALT macro enables alternative implementations to + * replace certain functions in this module. The alternative implementations are + * typically hardware accelerators and need to activate the hardware before the + * computation starts and deactivate it after it finishes. The + * mbedtls_internal_ecp_init() and mbedtls_internal_ecp_free() functions serve + * this purpose. + * + * To preserve the correct functionality the following conditions must hold: + * + * - The alternative implementation must be activated by + * mbedtls_internal_ecp_init() before any of the replaceable functions is + * called. + * - mbedtls_internal_ecp_free() must \b only be called when the alternative + * implementation is activated. + * - mbedtls_internal_ecp_init() must \b not be called when the alternative + * implementation is activated. + * - Public functions must not return while the alternative implementation is + * activated. + * - Replaceable functions are guarded by \c MBEDTLS_ECP_XXX_ALT macros and + * before calling them an \code if( mbedtls_internal_ecp_grp_capable( grp ) ) + * \endcode ensures that the alternative implementation supports the current + * group. + */ +#if defined(MBEDTLS_ECP_INTERNAL_ALT) +#endif + +#if defined(MBEDTLS_ECP_C) + +#include "mbedtls/ecp.h" +#include "mbedtls/threading.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if !defined(MBEDTLS_ECP_ALT) + +/* Parameter validation macros based on platform_util.h */ +#define ECP_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA ) +#define ECP_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/ecp_internal.h" + +#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) +#if defined(MBEDTLS_HMAC_DRBG_C) +#include "mbedtls/hmac_drbg.h" +#elif defined(MBEDTLS_CTR_DRBG_C) +#include "mbedtls/ctr_drbg.h" +#else +#error "Invalid configuration detected. Include check_config.h to ensure that the configuration is valid." +#endif +#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */ + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#if defined(MBEDTLS_SELF_TEST) +/* + * Counts of point addition and doubling, and field multiplications. + * Used to test resistance of point multiplication to simple timing attacks. + */ +static unsigned long add_count, dbl_count, mul_count; +#endif + +#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) +/* + * Currently ecp_mul() takes a RNG function as an argument, used for + * side-channel protection, but it can be NULL. The initial reasoning was + * that people will pass non-NULL RNG when they care about side-channels, but + * unfortunately we have some APIs that call ecp_mul() with a NULL RNG, with + * no opportunity for the user to do anything about it. + * + * The obvious strategies for addressing that include: + * - change those APIs so that they take RNG arguments; + * - require a global RNG to be available to all crypto modules. + * + * Unfortunately those would break compatibility. So what we do instead is + * have our own internal DRBG instance, seeded from the secret scalar. + * + * The following is a light-weight abstraction layer for doing that with + * HMAC_DRBG (first choice) or CTR_DRBG. + */ + +#if defined(MBEDTLS_HMAC_DRBG_C) + +/* DRBG context type */ +typedef mbedtls_hmac_drbg_context ecp_drbg_context; + +/* DRBG context init */ +static inline void ecp_drbg_init( ecp_drbg_context *ctx ) +{ + mbedtls_hmac_drbg_init( ctx ); +} + +/* DRBG context free */ +static inline void ecp_drbg_free( ecp_drbg_context *ctx ) +{ + mbedtls_hmac_drbg_free( ctx ); +} + +/* DRBG function */ +static inline int ecp_drbg_random( void *p_rng, + unsigned char *output, size_t output_len ) +{ + return( mbedtls_hmac_drbg_random( p_rng, output, output_len ) ); +} + +/* DRBG context seeding */ +static int ecp_drbg_seed( ecp_drbg_context *ctx, + const mbedtls_mpi *secret, size_t secret_len ) +{ + int ret; + unsigned char secret_bytes[MBEDTLS_ECP_MAX_BYTES]; + /* The list starts with strong hashes */ + const mbedtls_md_type_t md_type = mbedtls_md_list()[0]; + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_type ); + + if( secret_len > MBEDTLS_ECP_MAX_BYTES ) + { + ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( secret, + secret_bytes, secret_len ) ); + + ret = mbedtls_hmac_drbg_seed_buf( ctx, md_info, secret_bytes, secret_len ); + +cleanup: + mbedtls_platform_zeroize( secret_bytes, secret_len ); + + return( ret ); +} + +#elif defined(MBEDTLS_CTR_DRBG_C) + +/* DRBG context type */ +typedef mbedtls_ctr_drbg_context ecp_drbg_context; + +/* DRBG context init */ +static inline void ecp_drbg_init( ecp_drbg_context *ctx ) +{ + mbedtls_ctr_drbg_init( ctx ); +} + +/* DRBG context free */ +static inline void ecp_drbg_free( ecp_drbg_context *ctx ) +{ + mbedtls_ctr_drbg_free( ctx ); +} + +/* DRBG function */ +static inline int ecp_drbg_random( void *p_rng, + unsigned char *output, size_t output_len ) +{ + return( mbedtls_ctr_drbg_random( p_rng, output, output_len ) ); +} + +/* + * Since CTR_DRBG doesn't have a seed_buf() function the way HMAC_DRBG does, + * we need to pass an entropy function when seeding. So we use a dummy + * function for that, and pass the actual entropy as customisation string. + * (During seeding of CTR_DRBG the entropy input and customisation string are + * concatenated before being used to update the secret state.) + */ +static int ecp_ctr_drbg_null_entropy(void *ctx, unsigned char *out, size_t len) +{ + (void) ctx; + memset( out, 0, len ); + return( 0 ); +} + +/* DRBG context seeding */ +static int ecp_drbg_seed( ecp_drbg_context *ctx, + const mbedtls_mpi *secret, size_t secret_len ) +{ + int ret; + unsigned char secret_bytes[MBEDTLS_ECP_MAX_BYTES]; + + if( secret_len > MBEDTLS_ECP_MAX_BYTES ) + { + ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( secret, + secret_bytes, secret_len ) ); + + ret = mbedtls_ctr_drbg_seed( ctx, ecp_ctr_drbg_null_entropy, NULL, + secret_bytes, secret_len ); + +cleanup: + mbedtls_platform_zeroize( secret_bytes, secret_len ); + + return( ret ); +} + +#else +#error "Invalid configuration detected. Include check_config.h to ensure that the configuration is valid." +#endif /* DRBG modules */ +#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */ + +#if defined(MBEDTLS_ECP_RESTARTABLE) +/* + * Maximum number of "basic operations" to be done in a row. + * + * Default value 0 means that ECC operations will not yield. + * Note that regardless of the value of ecp_max_ops, always at + * least one step is performed before yielding. + * + * Setting ecp_max_ops=1 can be suitable for testing purposes + * as it will interrupt computation at all possible points. + */ +static unsigned ecp_max_ops = 0; + +/* + * Set ecp_max_ops + */ +void mbedtls_ecp_set_max_ops( unsigned max_ops ) +{ + ecp_max_ops = max_ops; +} + +/* + * Check if restart is enabled + */ +int mbedtls_ecp_restart_is_enabled( void ) +{ + return( ecp_max_ops != 0 ); +} + +/* + * Restart sub-context for ecp_mul_comb() + */ +struct mbedtls_ecp_restart_mul +{ + mbedtls_ecp_point R; /* current intermediate result */ + size_t i; /* current index in various loops, 0 outside */ + mbedtls_ecp_point *T; /* table for precomputed points */ + unsigned char T_size; /* number of points in table T */ + enum { /* what were we doing last time we returned? */ + ecp_rsm_init = 0, /* nothing so far, dummy initial state */ + ecp_rsm_pre_dbl, /* precompute 2^n multiples */ + ecp_rsm_pre_norm_dbl, /* normalize precomputed 2^n multiples */ + ecp_rsm_pre_add, /* precompute remaining points by adding */ + ecp_rsm_pre_norm_add, /* normalize all precomputed points */ + ecp_rsm_comb_core, /* ecp_mul_comb_core() */ + ecp_rsm_final_norm, /* do the final normalization */ + } state; +#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + ecp_drbg_context drbg_ctx; + unsigned char drbg_seeded; +#endif +}; + +/* + * Init restart_mul sub-context + */ +static void ecp_restart_rsm_init( mbedtls_ecp_restart_mul_ctx *ctx ) +{ + mbedtls_ecp_point_init( &ctx->R ); + ctx->i = 0; + ctx->T = NULL; + ctx->T_size = 0; + ctx->state = ecp_rsm_init; +#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + ecp_drbg_init( &ctx->drbg_ctx ); + ctx->drbg_seeded = 0; +#endif +} + +/* + * Free the components of a restart_mul sub-context + */ +static void ecp_restart_rsm_free( mbedtls_ecp_restart_mul_ctx *ctx ) +{ + unsigned char i; + + if( ctx == NULL ) + return; + + mbedtls_ecp_point_free( &ctx->R ); + + if( ctx->T != NULL ) + { + for( i = 0; i < ctx->T_size; i++ ) + mbedtls_ecp_point_free( ctx->T + i ); + mbedtls_free( ctx->T ); + } + +#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + ecp_drbg_free( &ctx->drbg_ctx ); +#endif + + ecp_restart_rsm_init( ctx ); +} + +/* + * Restart context for ecp_muladd() + */ +struct mbedtls_ecp_restart_muladd +{ + mbedtls_ecp_point mP; /* mP value */ + mbedtls_ecp_point R; /* R intermediate result */ + enum { /* what should we do next? */ + ecp_rsma_mul1 = 0, /* first multiplication */ + ecp_rsma_mul2, /* second multiplication */ + ecp_rsma_add, /* addition */ + ecp_rsma_norm, /* normalization */ + } state; +}; + +/* + * Init restart_muladd sub-context + */ +static void ecp_restart_ma_init( mbedtls_ecp_restart_muladd_ctx *ctx ) +{ + mbedtls_ecp_point_init( &ctx->mP ); + mbedtls_ecp_point_init( &ctx->R ); + ctx->state = ecp_rsma_mul1; +} + +/* + * Free the components of a restart_muladd sub-context + */ +static void ecp_restart_ma_free( mbedtls_ecp_restart_muladd_ctx *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_ecp_point_free( &ctx->mP ); + mbedtls_ecp_point_free( &ctx->R ); + + ecp_restart_ma_init( ctx ); +} + +/* + * Initialize a restart context + */ +void mbedtls_ecp_restart_init( mbedtls_ecp_restart_ctx *ctx ) +{ + ECP_VALIDATE( ctx != NULL ); + ctx->ops_done = 0; + ctx->depth = 0; + ctx->rsm = NULL; + ctx->ma = NULL; +} + +/* + * Free the components of a restart context + */ +void mbedtls_ecp_restart_free( mbedtls_ecp_restart_ctx *ctx ) +{ + if( ctx == NULL ) + return; + + ecp_restart_rsm_free( ctx->rsm ); + mbedtls_free( ctx->rsm ); + + ecp_restart_ma_free( ctx->ma ); + mbedtls_free( ctx->ma ); + + mbedtls_ecp_restart_init( ctx ); +} + +/* + * Check if we can do the next step + */ +int mbedtls_ecp_check_budget( const mbedtls_ecp_group *grp, + mbedtls_ecp_restart_ctx *rs_ctx, + unsigned ops ) +{ + ECP_VALIDATE_RET( grp != NULL ); + + if( rs_ctx != NULL && ecp_max_ops != 0 ) + { + /* scale depending on curve size: the chosen reference is 256-bit, + * and multiplication is quadratic. Round to the closest integer. */ + if( grp->pbits >= 512 ) + ops *= 4; + else if( grp->pbits >= 384 ) + ops *= 2; + + /* Avoid infinite loops: always allow first step. + * Because of that, however, it's not generally true + * that ops_done <= ecp_max_ops, so the check + * ops_done > ecp_max_ops below is mandatory. */ + if( ( rs_ctx->ops_done != 0 ) && + ( rs_ctx->ops_done > ecp_max_ops || + ops > ecp_max_ops - rs_ctx->ops_done ) ) + { + return( MBEDTLS_ERR_ECP_IN_PROGRESS ); + } + + /* update running count */ + rs_ctx->ops_done += ops; + } + + return( 0 ); +} + +/* Call this when entering a function that needs its own sub-context */ +#define ECP_RS_ENTER( SUB ) do { \ + /* reset ops count for this call if top-level */ \ + if( rs_ctx != NULL && rs_ctx->depth++ == 0 ) \ + rs_ctx->ops_done = 0; \ + \ + /* set up our own sub-context if needed */ \ + if( mbedtls_ecp_restart_is_enabled() && \ + rs_ctx != NULL && rs_ctx->SUB == NULL ) \ + { \ + rs_ctx->SUB = mbedtls_calloc( 1, sizeof( *rs_ctx->SUB ) ); \ + if( rs_ctx->SUB == NULL ) \ + return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); \ + \ + ecp_restart_## SUB ##_init( rs_ctx->SUB ); \ + } \ +} while( 0 ) + +/* Call this when leaving a function that needs its own sub-context */ +#define ECP_RS_LEAVE( SUB ) do { \ + /* clear our sub-context when not in progress (done or error) */ \ + if( rs_ctx != NULL && rs_ctx->SUB != NULL && \ + ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) \ + { \ + ecp_restart_## SUB ##_free( rs_ctx->SUB ); \ + mbedtls_free( rs_ctx->SUB ); \ + rs_ctx->SUB = NULL; \ + } \ + \ + if( rs_ctx != NULL ) \ + rs_ctx->depth--; \ +} while( 0 ) + +#else /* MBEDTLS_ECP_RESTARTABLE */ + +#define ECP_RS_ENTER( sub ) (void) rs_ctx; +#define ECP_RS_LEAVE( sub ) (void) rs_ctx; + +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +/* + * List of supported curves: + * - internal ID + * - TLS NamedCurve ID (RFC 4492 sec. 5.1.1, RFC 7071 sec. 2, RFC 8446 sec. 4.2.7) + * - size in bits + * - readable name + * + * Curves are listed in order: largest curves first, and for a given size, + * fastest curves first. This provides the default order for the SSL module. + * + * Reminder: update profiles in x509_crt.c when adding a new curves! + */ +static const mbedtls_ecp_curve_info ecp_supported_curves[] = +{ +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) + { MBEDTLS_ECP_DP_SECP521R1, 25, 521, "secp521r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) + { MBEDTLS_ECP_DP_BP512R1, 28, 512, "brainpoolP512r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + { MBEDTLS_ECP_DP_SECP384R1, 24, 384, "secp384r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) + { MBEDTLS_ECP_DP_BP384R1, 27, 384, "brainpoolP384r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + { MBEDTLS_ECP_DP_SECP256R1, 23, 256, "secp256r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) + { MBEDTLS_ECP_DP_SECP256K1, 22, 256, "secp256k1" }, +#endif +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) + { MBEDTLS_ECP_DP_BP256R1, 26, 256, "brainpoolP256r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) + { MBEDTLS_ECP_DP_SECP224R1, 21, 224, "secp224r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) + { MBEDTLS_ECP_DP_SECP224K1, 20, 224, "secp224k1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + { MBEDTLS_ECP_DP_SECP192R1, 19, 192, "secp192r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) + { MBEDTLS_ECP_DP_SECP192K1, 18, 192, "secp192k1" }, +#endif +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) + { MBEDTLS_ECP_DP_CURVE25519, 29, 256, "x25519" }, +#endif +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) + { MBEDTLS_ECP_DP_CURVE448, 30, 448, "x448" }, +#endif + { MBEDTLS_ECP_DP_NONE, 0, 0, NULL }, +}; + +#define ECP_NB_CURVES sizeof( ecp_supported_curves ) / \ + sizeof( ecp_supported_curves[0] ) + +static mbedtls_ecp_group_id ecp_supported_grp_id[ECP_NB_CURVES]; + +/* + * List of supported curves and associated info + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list( void ) +{ + return( ecp_supported_curves ); +} + +/* + * List of supported curves, group ID only + */ +const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list( void ) +{ + static int init_done = 0; + + if( ! init_done ) + { + size_t i = 0; + const mbedtls_ecp_curve_info *curve_info; + + for( curve_info = mbedtls_ecp_curve_list(); + curve_info->grp_id != MBEDTLS_ECP_DP_NONE; + curve_info++ ) + { + ecp_supported_grp_id[i++] = curve_info->grp_id; + } + ecp_supported_grp_id[i] = MBEDTLS_ECP_DP_NONE; + + init_done = 1; + } + + return( ecp_supported_grp_id ); +} + +/* + * Get the curve info for the internal identifier + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_grp_id( mbedtls_ecp_group_id grp_id ) +{ + const mbedtls_ecp_curve_info *curve_info; + + for( curve_info = mbedtls_ecp_curve_list(); + curve_info->grp_id != MBEDTLS_ECP_DP_NONE; + curve_info++ ) + { + if( curve_info->grp_id == grp_id ) + return( curve_info ); + } + + return( NULL ); +} + +/* + * Get the curve info from the TLS identifier + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id( uint16_t tls_id ) +{ + const mbedtls_ecp_curve_info *curve_info; + + for( curve_info = mbedtls_ecp_curve_list(); + curve_info->grp_id != MBEDTLS_ECP_DP_NONE; + curve_info++ ) + { + if( curve_info->tls_id == tls_id ) + return( curve_info ); + } + + return( NULL ); +} + +/* + * Get the curve info from the name + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name( const char *name ) +{ + const mbedtls_ecp_curve_info *curve_info; + + if( name == NULL ) + return( NULL ); + + for( curve_info = mbedtls_ecp_curve_list(); + curve_info->grp_id != MBEDTLS_ECP_DP_NONE; + curve_info++ ) + { + if( strcmp( curve_info->name, name ) == 0 ) + return( curve_info ); + } + + return( NULL ); +} + +/* + * Get the type of a curve + */ +mbedtls_ecp_curve_type mbedtls_ecp_get_type( const mbedtls_ecp_group *grp ) +{ + if( grp->G.X.p == NULL ) + return( MBEDTLS_ECP_TYPE_NONE ); + + if( grp->G.Y.p == NULL ) + return( MBEDTLS_ECP_TYPE_MONTGOMERY ); + else + return( MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS ); +} + +/* + * Initialize (the components of) a point + */ +void mbedtls_ecp_point_init( mbedtls_ecp_point *pt ) +{ + ECP_VALIDATE( pt != NULL ); + + mbedtls_mpi_init( &pt->X ); + mbedtls_mpi_init( &pt->Y ); + mbedtls_mpi_init( &pt->Z ); +} + +/* + * Initialize (the components of) a group + */ +void mbedtls_ecp_group_init( mbedtls_ecp_group *grp ) +{ + ECP_VALIDATE( grp != NULL ); + + grp->id = MBEDTLS_ECP_DP_NONE; + mbedtls_mpi_init( &grp->P ); + mbedtls_mpi_init( &grp->A ); + mbedtls_mpi_init( &grp->B ); + mbedtls_ecp_point_init( &grp->G ); + mbedtls_mpi_init( &grp->N ); + grp->pbits = 0; + grp->nbits = 0; + grp->h = 0; + grp->modp = NULL; + grp->t_pre = NULL; + grp->t_post = NULL; + grp->t_data = NULL; + grp->T = NULL; + grp->T_size = 0; +} + +/* + * Initialize (the components of) a key pair + */ +void mbedtls_ecp_keypair_init( mbedtls_ecp_keypair *key ) +{ + ECP_VALIDATE( key != NULL ); + + mbedtls_ecp_group_init( &key->grp ); + mbedtls_mpi_init( &key->d ); + mbedtls_ecp_point_init( &key->Q ); +} + +/* + * Unallocate (the components of) a point + */ +void mbedtls_ecp_point_free( mbedtls_ecp_point *pt ) +{ + if( pt == NULL ) + return; + + mbedtls_mpi_free( &( pt->X ) ); + mbedtls_mpi_free( &( pt->Y ) ); + mbedtls_mpi_free( &( pt->Z ) ); +} + +/* + * Unallocate (the components of) a group + */ +void mbedtls_ecp_group_free( mbedtls_ecp_group *grp ) +{ + size_t i; + + if( grp == NULL ) + return; + + if( grp->h != 1 ) + { + mbedtls_mpi_free( &grp->P ); + mbedtls_mpi_free( &grp->A ); + mbedtls_mpi_free( &grp->B ); + mbedtls_ecp_point_free( &grp->G ); + mbedtls_mpi_free( &grp->N ); + } + + if( grp->T != NULL ) + { + for( i = 0; i < grp->T_size; i++ ) + mbedtls_ecp_point_free( &grp->T[i] ); + mbedtls_free( grp->T ); + } + + mbedtls_platform_zeroize( grp, sizeof( mbedtls_ecp_group ) ); +} + +/* + * Unallocate (the components of) a key pair + */ +void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key ) +{ + if( key == NULL ) + return; + + mbedtls_ecp_group_free( &key->grp ); + mbedtls_mpi_free( &key->d ); + mbedtls_ecp_point_free( &key->Q ); +} + +/* + * Copy the contents of a point + */ +int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + ECP_VALIDATE_RET( P != NULL ); + ECP_VALIDATE_RET( Q != NULL ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->X, &Q->X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Y, &Q->Y ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Z, &Q->Z ) ); + +cleanup: + return( ret ); +} + +/* + * Copy the contents of a group object + */ +int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src ) +{ + ECP_VALIDATE_RET( dst != NULL ); + ECP_VALIDATE_RET( src != NULL ); + + return( mbedtls_ecp_group_load( dst, src->id ) ); +} + +/* + * Set point to zero + */ +int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + ECP_VALIDATE_RET( pt != NULL ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->X , 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Y , 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z , 0 ) ); + +cleanup: + return( ret ); +} + +/* + * Tell if a point is zero + */ +int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt ) +{ + ECP_VALIDATE_RET( pt != NULL ); + + return( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 ); +} + +/* + * Compare two points lazily + */ +int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P, + const mbedtls_ecp_point *Q ) +{ + ECP_VALIDATE_RET( P != NULL ); + ECP_VALIDATE_RET( Q != NULL ); + + if( mbedtls_mpi_cmp_mpi( &P->X, &Q->X ) == 0 && + mbedtls_mpi_cmp_mpi( &P->Y, &Q->Y ) == 0 && + mbedtls_mpi_cmp_mpi( &P->Z, &Q->Z ) == 0 ) + { + return( 0 ); + } + + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); +} + +/* + * Import a non-zero point from ASCII strings + */ +int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix, + const char *x, const char *y ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + ECP_VALIDATE_RET( P != NULL ); + ECP_VALIDATE_RET( x != NULL ); + ECP_VALIDATE_RET( y != NULL ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->X, radix, x ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->Y, radix, y ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) ); + +cleanup: + return( ret ); +} + +/* + * Export a point into unsigned binary data (SEC1 2.3.3 and RFC7748) + */ +int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp, + const mbedtls_ecp_point *P, + int format, size_t *olen, + unsigned char *buf, size_t buflen ) +{ + int ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; + size_t plen; + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( P != NULL ); + ECP_VALIDATE_RET( olen != NULL ); + ECP_VALIDATE_RET( buf != NULL ); + ECP_VALIDATE_RET( format == MBEDTLS_ECP_PF_UNCOMPRESSED || + format == MBEDTLS_ECP_PF_COMPRESSED ); + + plen = mbedtls_mpi_size( &grp->P ); + +#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) + (void) format; /* Montgomery curves always use the same point format */ + if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY ) + { + *olen = plen; + if( buflen < *olen ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary_le( &P->X, buf, plen ) ); + } +#endif +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) + if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS ) + { + /* + * Common case: P == 0 + */ + if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 ) + { + if( buflen < 1 ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + buf[0] = 0x00; + *olen = 1; + + return( 0 ); + } + + if( format == MBEDTLS_ECP_PF_UNCOMPRESSED ) + { + *olen = 2 * plen + 1; + + if( buflen < *olen ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + buf[0] = 0x04; + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->Y, buf + 1 + plen, plen ) ); + } + else if( format == MBEDTLS_ECP_PF_COMPRESSED ) + { + *olen = plen + 1; + + if( buflen < *olen ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + buf[0] = 0x02 + mbedtls_mpi_get_bit( &P->Y, 0 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) ); + } + } +#endif + +cleanup: + return( ret ); +} + +/* + * Import a point from unsigned binary data (SEC1 2.3.4 and RFC7748) + */ +int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *pt, + const unsigned char *buf, size_t ilen ) +{ + int ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; + size_t plen; + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( pt != NULL ); + ECP_VALIDATE_RET( buf != NULL ); + + if( ilen < 1 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + plen = mbedtls_mpi_size( &grp->P ); + +#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) + if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY ) + { + if( plen != ilen ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary_le( &pt->X, buf, plen ) ); + mbedtls_mpi_free( &pt->Y ); + + if( grp->id == MBEDTLS_ECP_DP_CURVE25519 ) + /* Set most significant bit to 0 as prescribed in RFC7748 §5 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( &pt->X, plen * 8 - 1, 0 ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) ); + } +#endif +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) + if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS ) + { + if( buf[0] == 0x00 ) + { + if( ilen == 1 ) + return( mbedtls_ecp_set_zero( pt ) ); + else + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + } + + if( buf[0] != 0x04 ) + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); + + if( ilen != 2 * plen + 1 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->X, buf + 1, plen ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->Y, + buf + 1 + plen, plen ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) ); + } +#endif + +cleanup: + return( ret ); +} + +/* + * Import a point from a TLS ECPoint record (RFC 4492) + * struct { + * opaque point <1..2^8-1>; + * } ECPoint; + */ +int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *pt, + const unsigned char **buf, size_t buf_len ) +{ + unsigned char data_len; + const unsigned char *buf_start; + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( pt != NULL ); + ECP_VALIDATE_RET( buf != NULL ); + ECP_VALIDATE_RET( *buf != NULL ); + + /* + * We must have at least two bytes (1 for length, at least one for data) + */ + if( buf_len < 2 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + data_len = *(*buf)++; + if( data_len < 1 || data_len > buf_len - 1 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * Save buffer start for read_binary and update buf + */ + buf_start = *buf; + *buf += data_len; + + return( mbedtls_ecp_point_read_binary( grp, pt, buf_start, data_len ) ); +} + +/* + * Export a point as a TLS ECPoint record (RFC 4492) + * struct { + * opaque point <1..2^8-1>; + * } ECPoint; + */ +int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt, + int format, size_t *olen, + unsigned char *buf, size_t blen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( pt != NULL ); + ECP_VALIDATE_RET( olen != NULL ); + ECP_VALIDATE_RET( buf != NULL ); + ECP_VALIDATE_RET( format == MBEDTLS_ECP_PF_UNCOMPRESSED || + format == MBEDTLS_ECP_PF_COMPRESSED ); + + /* + * buffer length must be at least one, for our length byte + */ + if( blen < 1 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_ecp_point_write_binary( grp, pt, format, + olen, buf + 1, blen - 1) ) != 0 ) + return( ret ); + + /* + * write length to the first byte and update total length + */ + buf[0] = (unsigned char) *olen; + ++*olen; + + return( 0 ); +} + +/* + * Set a group from an ECParameters record (RFC 4492) + */ +int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp, + const unsigned char **buf, size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_group_id grp_id; + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( buf != NULL ); + ECP_VALIDATE_RET( *buf != NULL ); + + if( ( ret = mbedtls_ecp_tls_read_group_id( &grp_id, buf, len ) ) != 0 ) + return( ret ); + + return( mbedtls_ecp_group_load( grp, grp_id ) ); +} + +/* + * Read a group id from an ECParameters record (RFC 4492) and convert it to + * mbedtls_ecp_group_id. + */ +int mbedtls_ecp_tls_read_group_id( mbedtls_ecp_group_id *grp, + const unsigned char **buf, size_t len ) +{ + uint16_t tls_id; + const mbedtls_ecp_curve_info *curve_info; + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( buf != NULL ); + ECP_VALIDATE_RET( *buf != NULL ); + + /* + * We expect at least three bytes (see below) + */ + if( len < 3 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * First byte is curve_type; only named_curve is handled + */ + if( *(*buf)++ != MBEDTLS_ECP_TLS_NAMED_CURVE ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * Next two bytes are the namedcurve value + */ + tls_id = *(*buf)++; + tls_id <<= 8; + tls_id |= *(*buf)++; + + if( ( curve_info = mbedtls_ecp_curve_info_from_tls_id( tls_id ) ) == NULL ) + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); + + *grp = curve_info->grp_id; + + return( 0 ); +} + +/* + * Write the ECParameters record corresponding to a group (RFC 4492) + */ +int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen, + unsigned char *buf, size_t blen ) +{ + const mbedtls_ecp_curve_info *curve_info; + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( buf != NULL ); + ECP_VALIDATE_RET( olen != NULL ); + + if( ( curve_info = mbedtls_ecp_curve_info_from_grp_id( grp->id ) ) == NULL ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * We are going to write 3 bytes (see below) + */ + *olen = 3; + if( blen < *olen ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + /* + * First byte is curve_type, always named_curve + */ + *buf++ = MBEDTLS_ECP_TLS_NAMED_CURVE; + + /* + * Next two bytes are the namedcurve value + */ + buf[0] = curve_info->tls_id >> 8; + buf[1] = curve_info->tls_id & 0xFF; + + return( 0 ); +} + +/* + * Wrapper around fast quasi-modp functions, with fall-back to mbedtls_mpi_mod_mpi. + * See the documentation of struct mbedtls_ecp_group. + * + * This function is in the critial loop for mbedtls_ecp_mul, so pay attention to perf. + */ +static int ecp_modp( mbedtls_mpi *N, const mbedtls_ecp_group *grp ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( grp->modp == NULL ) + return( mbedtls_mpi_mod_mpi( N, N, &grp->P ) ); + + /* N->s < 0 is a much faster test, which fails only if N is 0 */ + if( ( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 ) || + mbedtls_mpi_bitlen( N ) > 2 * grp->pbits ) + { + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + } + + MBEDTLS_MPI_CHK( grp->modp( N ) ); + + /* N->s < 0 is a much faster test, which fails only if N is 0 */ + while( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &grp->P ) ); + + while( mbedtls_mpi_cmp_mpi( N, &grp->P ) >= 0 ) + /* we known P, N and the result are positive */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( N, N, &grp->P ) ); + +cleanup: + return( ret ); +} + +/* + * Fast mod-p functions expect their argument to be in the 0..p^2 range. + * + * In order to guarantee that, we need to ensure that operands of + * mbedtls_mpi_mul_mpi are in the 0..p range. So, after each operation we will + * bring the result back to this range. + * + * The following macros are shortcuts for doing that. + */ + +/* + * Reduce a mbedtls_mpi mod p in-place, general case, to use after mbedtls_mpi_mul_mpi + */ +#if defined(MBEDTLS_SELF_TEST) +#define INC_MUL_COUNT mul_count++; +#else +#define INC_MUL_COUNT +#endif + +#define MOD_MUL( N ) \ + do \ + { \ + MBEDTLS_MPI_CHK( ecp_modp( &(N), grp ) ); \ + INC_MUL_COUNT \ + } while( 0 ) + +static inline int mbedtls_mpi_mul_mod( const mbedtls_ecp_group *grp, + mbedtls_mpi *X, + const mbedtls_mpi *A, + const mbedtls_mpi *B ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( X, A, B ) ); + MOD_MUL( *X ); +cleanup: + return( ret ); +} + +/* + * Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_sub_mpi + * N->s < 0 is a very fast test, which fails only if N is 0 + */ +#define MOD_SUB( N ) \ + while( (N).s < 0 && mbedtls_mpi_cmp_int( &(N), 0 ) != 0 ) \ + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &(N), &(N), &grp->P ) ) + +static inline int mbedtls_mpi_sub_mod( const mbedtls_ecp_group *grp, + mbedtls_mpi *X, + const mbedtls_mpi *A, + const mbedtls_mpi *B ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( X, A, B ) ); + MOD_SUB( *X ); +cleanup: + return( ret ); +} + +/* + * Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_add_mpi and mbedtls_mpi_mul_int. + * We known P, N and the result are positive, so sub_abs is correct, and + * a bit faster. + */ +#define MOD_ADD( N ) \ + while( mbedtls_mpi_cmp_mpi( &(N), &grp->P ) >= 0 ) \ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &(N), &(N), &grp->P ) ) + +static inline int mbedtls_mpi_add_mod( const mbedtls_ecp_group *grp, + mbedtls_mpi *X, + const mbedtls_mpi *A, + const mbedtls_mpi *B ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, A, B ) ); + MOD_ADD( *X ); +cleanup: + return( ret ); +} + +static inline int mbedtls_mpi_shift_l_mod( const mbedtls_ecp_group *grp, + mbedtls_mpi *X, + size_t count ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( X, count ) ); + MOD_ADD( *X ); +cleanup: + return( ret ); +} + +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) +/* + * For curves in short Weierstrass form, we do all the internal operations in + * Jacobian coordinates. + * + * For multiplication, we'll use a comb method with coutermeasueres against + * SPA, hence timing attacks. + */ + +/* + * Normalize jacobian coordinates so that Z == 0 || Z == 1 (GECC 3.2.1) + * Cost: 1N := 1I + 3M + 1S + */ +static int ecp_normalize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi Zi, ZZi; + + if( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 ) + return( 0 ); + +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_normalize_jac( grp, pt ) ); +#endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */ + + mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi ); + + /* + * X = X / Z^2 mod p + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &Zi, &pt->Z, &grp->P ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &ZZi, &Zi, &Zi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &pt->X, &pt->X, &ZZi ) ); + + /* + * Y = Y / Z^3 mod p + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &pt->Y, &pt->Y, &ZZi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &pt->Y, &pt->Y, &Zi ) ); + + /* + * Z = 1 + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) ); + +cleanup: + + mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi ); + + return( ret ); +} + +/* + * Normalize jacobian coordinates of an array of (pointers to) points, + * using Montgomery's trick to perform only one inversion mod P. + * (See for example Cohen's "A Course in Computational Algebraic Number + * Theory", Algorithm 10.3.4.) + * + * Warning: fails (returning an error) if one of the points is zero! + * This should never happen, see choice of w in ecp_mul_comb(). + * + * Cost: 1N(t) := 1I + (6t - 3)M + 1S + */ +static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *T[], size_t T_size ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i; + mbedtls_mpi *c, u, Zi, ZZi; + + if( T_size < 2 ) + return( ecp_normalize_jac( grp, *T ) ); + +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_normalize_jac_many( grp, T, T_size ) ); +#endif + + if( ( c = mbedtls_calloc( T_size, sizeof( mbedtls_mpi ) ) ) == NULL ) + return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); + + for( i = 0; i < T_size; i++ ) + mbedtls_mpi_init( &c[i] ); + + mbedtls_mpi_init( &u ); mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi ); + + /* + * c[i] = Z_0 * ... * Z_i + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &c[0], &T[0]->Z ) ); + for( i = 1; i < T_size; i++ ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &c[i], &c[i-1], &T[i]->Z ) ); + } + + /* + * u = 1 / (Z_0 * ... * Z_n) mod P + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &u, &c[T_size-1], &grp->P ) ); + + for( i = T_size - 1; ; i-- ) + { + /* + * Zi = 1 / Z_i mod p + * u = 1 / (Z_0 * ... * Z_i) mod P + */ + if( i == 0 ) { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Zi, &u ) ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &Zi, &u, &c[i-1] ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &u, &u, &T[i]->Z ) ); + } + + /* + * proceed as in normalize() + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &ZZi, &Zi, &Zi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T[i]->X, &T[i]->X, &ZZi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T[i]->Y, &T[i]->Y, &ZZi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T[i]->Y, &T[i]->Y, &Zi ) ); + + /* + * Post-precessing: reclaim some memory by shrinking coordinates + * - not storing Z (always 1) + * - shrinking other coordinates, but still keeping the same number of + * limbs as P, as otherwise it will too likely be regrown too fast. + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->X, grp->P.n ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->Y, grp->P.n ) ); + mbedtls_mpi_free( &T[i]->Z ); + + if( i == 0 ) + break; + } + +cleanup: + + mbedtls_mpi_free( &u ); mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi ); + for( i = 0; i < T_size; i++ ) + mbedtls_mpi_free( &c[i] ); + mbedtls_free( c ); + + return( ret ); +} + +/* + * Conditional point inversion: Q -> -Q = (Q.X, -Q.Y, Q.Z) without leak. + * "inv" must be 0 (don't invert) or 1 (invert) or the result will be invalid + */ +static int ecp_safe_invert_jac( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *Q, + unsigned char inv ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char nonzero; + mbedtls_mpi mQY; + + mbedtls_mpi_init( &mQY ); + + /* Use the fact that -Q.Y mod P = P - Q.Y unless Q.Y == 0 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mQY, &grp->P, &Q->Y ) ); + nonzero = mbedtls_mpi_cmp_int( &Q->Y, 0 ) != 0; + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &Q->Y, &mQY, inv & nonzero ) ); + +cleanup: + mbedtls_mpi_free( &mQY ); + + return( ret ); +} + +/* + * Point doubling R = 2 P, Jacobian coordinates + * + * Based on http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#doubling-dbl-1998-cmo-2 . + * + * We follow the variable naming fairly closely. The formula variations that trade a MUL for a SQR + * (plus a few ADDs) aren't useful as our bignum implementation doesn't distinguish squaring. + * + * Standard optimizations are applied when curve parameter A is one of { 0, -3 }. + * + * Cost: 1D := 3M + 4S (A == 0) + * 4M + 4S (A == -3) + * 3M + 6S + 1a otherwise + */ +static int ecp_double_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_ecp_point *P ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi M, S, T, U; + +#if defined(MBEDTLS_SELF_TEST) + dbl_count++; +#endif + +#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_double_jac( grp, R, P ) ); +#endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */ + + mbedtls_mpi_init( &M ); mbedtls_mpi_init( &S ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &U ); + + /* Special case for A = -3 */ + if( grp->A.p == NULL ) + { + /* M = 3(X + Z^2)(X - Z^2) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S, &P->Z, &P->Z ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mod( grp, &T, &P->X, &S ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &U, &P->X, &S ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S, &T, &U ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M ); + } + else + { + /* M = 3.X^2 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S, &P->X, &P->X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M ); + + /* Optimize away for "koblitz" curves with A = 0 */ + if( mbedtls_mpi_cmp_int( &grp->A, 0 ) != 0 ) + { + /* M += A.Z^4 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S, &P->Z, &P->Z ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T, &S, &S ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S, &T, &grp->A ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mod( grp, &M, &M, &S ) ); + } + } + + /* S = 4.X.Y^2 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T, &P->Y, &P->Y ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l_mod( grp, &T, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S, &P->X, &T ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l_mod( grp, &S, 1 ) ); + + /* U = 8.Y^4 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &U, &T, &T ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l_mod( grp, &U, 1 ) ); + + /* T = M^2 - 2.S */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T, &M, &M ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &T, &T, &S ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &T, &T, &S ) ); + + /* S = M(S - T) - U */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &S, &S, &T ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S, &S, &M ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &S, &S, &U ) ); + + /* U = 2.Y.Z */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &U, &P->Y, &P->Z ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l_mod( grp, &U, 1 ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &T ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &S ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &U ) ); + +cleanup: + mbedtls_mpi_free( &M ); mbedtls_mpi_free( &S ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &U ); + + return( ret ); +} + +/* + * Addition: R = P + Q, mixed affine-Jacobian coordinates (GECC 3.22) + * + * The coordinates of Q must be normalized (= affine), + * but those of P don't need to. R is not normalized. + * + * Special cases: (1) P or Q is zero, (2) R is zero, (3) P == Q. + * None of these cases can happen as intermediate step in ecp_mul_comb(): + * - at each step, P, Q and R are multiples of the base point, the factor + * being less than its order, so none of them is zero; + * - Q is an odd multiple of the base point, P an even multiple, + * due to the choice of precomputed points in the modified comb method. + * So branches for these cases do not leak secret information. + * + * We accept Q->Z being unset (saving memory in tables) as meaning 1. + * + * Cost: 1A := 8M + 3S + */ +static int ecp_add_mixed( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi T1, T2, T3, T4, X, Y, Z; + +#if defined(MBEDTLS_SELF_TEST) + add_count++; +#endif + +#if defined(MBEDTLS_ECP_ADD_MIXED_ALT) + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_add_mixed( grp, R, P, Q ) ); +#endif /* MBEDTLS_ECP_ADD_MIXED_ALT */ + + /* + * Trivial cases: P == 0 or Q == 0 (case 1) + */ + if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 ) + return( mbedtls_ecp_copy( R, Q ) ); + + if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 0 ) == 0 ) + return( mbedtls_ecp_copy( R, P ) ); + + /* + * Make sure Q coordinates are normalized + */ + if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 1 ) != 0 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); mbedtls_mpi_init( &T3 ); mbedtls_mpi_init( &T4 ); + mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T1, &P->Z, &P->Z ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T2, &T1, &P->Z ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T1, &T1, &Q->X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T2, &T2, &Q->Y ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &T1, &T1, &P->X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &T2, &T2, &P->Y ) ); + + /* Special cases (2) and (3) */ + if( mbedtls_mpi_cmp_int( &T1, 0 ) == 0 ) + { + if( mbedtls_mpi_cmp_int( &T2, 0 ) == 0 ) + { + ret = ecp_double_jac( grp, R, P ); + goto cleanup; + } + else + { + ret = mbedtls_ecp_set_zero( R ); + goto cleanup; + } + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &Z, &P->Z, &T1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T3, &T1, &T1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T4, &T3, &T1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T3, &T3, &P->X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &T3 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l_mod( grp, &T1, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &X, &T2, &T2 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &X, &X, &T1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &X, &X, &T4 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &T3, &T3, &X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T3, &T3, &T2 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T4, &T4, &P->Y ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &Y, &T3, &T4 ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &Y ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &Z ) ); + +cleanup: + + mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); mbedtls_mpi_free( &T3 ); mbedtls_mpi_free( &T4 ); + mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z ); + + return( ret ); +} + +/* + * Randomize jacobian coordinates: + * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l + * This is sort of the reverse operation of ecp_normalize_jac(). + * + * This countermeasure was first suggested in [2]. + */ +static int ecp_randomize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi l, ll; + size_t p_size; + int count = 0; + +#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_randomize_jac( grp, pt, f_rng, p_rng ) ); +#endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */ + + p_size = ( grp->pbits + 7 ) / 8; + mbedtls_mpi_init( &l ); mbedtls_mpi_init( &ll ); + + /* Generate l such that 1 < l < p */ + do + { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) ); + + while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) ); + + if( count++ > 10 ) + { + ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; + goto cleanup; + } + } + while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 ); + + /* Z = l * Z */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &pt->Z, &pt->Z, &l ) ); + + /* X = l^2 * X */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &ll, &l, &l ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &pt->X, &pt->X, &ll ) ); + + /* Y = l^3 * Y */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &ll, &ll, &l ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &pt->Y, &pt->Y, &ll ) ); + +cleanup: + mbedtls_mpi_free( &l ); mbedtls_mpi_free( &ll ); + + return( ret ); +} + +/* + * Check and define parameters used by the comb method (see below for details) + */ +#if MBEDTLS_ECP_WINDOW_SIZE < 2 || MBEDTLS_ECP_WINDOW_SIZE > 7 +#error "MBEDTLS_ECP_WINDOW_SIZE out of bounds" +#endif + +/* d = ceil( n / w ) */ +#define COMB_MAX_D ( MBEDTLS_ECP_MAX_BITS + 1 ) / 2 + +/* number of precomputed points */ +#define COMB_MAX_PRE ( 1 << ( MBEDTLS_ECP_WINDOW_SIZE - 1 ) ) + +/* + * Compute the representation of m that will be used with our comb method. + * + * The basic comb method is described in GECC 3.44 for example. We use a + * modified version that provides resistance to SPA by avoiding zero + * digits in the representation as in [3]. We modify the method further by + * requiring that all K_i be odd, which has the small cost that our + * representation uses one more K_i, due to carries, but saves on the size of + * the precomputed table. + * + * Summary of the comb method and its modifications: + * + * - The goal is to compute m*P for some w*d-bit integer m. + * + * - The basic comb method splits m into the w-bit integers + * x[0] .. x[d-1] where x[i] consists of the bits in m whose + * index has residue i modulo d, and computes m * P as + * S[x[0]] + 2 * S[x[1]] + .. + 2^(d-1) S[x[d-1]], where + * S[i_{w-1} .. i_0] := i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + i_0 P. + * + * - If it happens that, say, x[i+1]=0 (=> S[x[i+1]]=0), one can replace the sum by + * .. + 2^{i-1} S[x[i-1]] - 2^i S[x[i]] + 2^{i+1} S[x[i]] + 2^{i+2} S[x[i+2]] .., + * thereby successively converting it into a form where all summands + * are nonzero, at the cost of negative summands. This is the basic idea of [3]. + * + * - More generally, even if x[i+1] != 0, we can first transform the sum as + * .. - 2^i S[x[i]] + 2^{i+1} ( S[x[i]] + S[x[i+1]] ) + 2^{i+2} S[x[i+2]] .., + * and then replace S[x[i]] + S[x[i+1]] = S[x[i] ^ x[i+1]] + 2 S[x[i] & x[i+1]]. + * Performing and iterating this procedure for those x[i] that are even + * (keeping track of carry), we can transform the original sum into one of the form + * S[x'[0]] +- 2 S[x'[1]] +- .. +- 2^{d-1} S[x'[d-1]] + 2^d S[x'[d]] + * with all x'[i] odd. It is therefore only necessary to know S at odd indices, + * which is why we are only computing half of it in the first place in + * ecp_precompute_comb and accessing it with index abs(i) / 2 in ecp_select_comb. + * + * - For the sake of compactness, only the seven low-order bits of x[i] + * are used to represent its absolute value (K_i in the paper), and the msb + * of x[i] encodes the sign (s_i in the paper): it is set if and only if + * if s_i == -1; + * + * Calling conventions: + * - x is an array of size d + 1 + * - w is the size, ie number of teeth, of the comb, and must be between + * 2 and 7 (in practice, between 2 and MBEDTLS_ECP_WINDOW_SIZE) + * - m is the MPI, expected to be odd and such that bitlength(m) <= w * d + * (the result will be incorrect if these assumptions are not satisfied) + */ +static void ecp_comb_recode_core( unsigned char x[], size_t d, + unsigned char w, const mbedtls_mpi *m ) +{ + size_t i, j; + unsigned char c, cc, adjust; + + memset( x, 0, d+1 ); + + /* First get the classical comb values (except for x_d = 0) */ + for( i = 0; i < d; i++ ) + for( j = 0; j < w; j++ ) + x[i] |= mbedtls_mpi_get_bit( m, i + d * j ) << j; + + /* Now make sure x_1 .. x_d are odd */ + c = 0; + for( i = 1; i <= d; i++ ) + { + /* Add carry and update it */ + cc = x[i] & c; + x[i] = x[i] ^ c; + c = cc; + + /* Adjust if needed, avoiding branches */ + adjust = 1 - ( x[i] & 0x01 ); + c |= x[i] & ( x[i-1] * adjust ); + x[i] = x[i] ^ ( x[i-1] * adjust ); + x[i-1] |= adjust << 7; + } +} + +/* + * Precompute points for the adapted comb method + * + * Assumption: T must be able to hold 2^{w - 1} elements. + * + * Operation: If i = i_{w-1} ... i_1 is the binary representation of i, + * sets T[i] = i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + P. + * + * Cost: d(w-1) D + (2^{w-1} - 1) A + 1 N(w-1) + 1 N(2^{w-1} - 1) + * + * Note: Even comb values (those where P would be omitted from the + * sum defining T[i] above) are not needed in our adaption + * the comb method. See ecp_comb_recode_core(). + * + * This function currently works in four steps: + * (1) [dbl] Computation of intermediate T[i] for 2-power values of i + * (2) [norm_dbl] Normalization of coordinates of these T[i] + * (3) [add] Computation of all T[i] + * (4) [norm_add] Normalization of all T[i] + * + * Step 1 can be interrupted but not the others; together with the final + * coordinate normalization they are the largest steps done at once, depending + * on the window size. Here are operation counts for P-256: + * + * step (2) (3) (4) + * w = 5 142 165 208 + * w = 4 136 77 160 + * w = 3 130 33 136 + * w = 2 124 11 124 + * + * So if ECC operations are blocking for too long even with a low max_ops + * value, it's useful to set MBEDTLS_ECP_WINDOW_SIZE to a lower value in order + * to minimize maximum blocking time. + */ +static int ecp_precompute_comb( const mbedtls_ecp_group *grp, + mbedtls_ecp_point T[], const mbedtls_ecp_point *P, + unsigned char w, size_t d, + mbedtls_ecp_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char i; + size_t j = 0; + const unsigned char T_size = 1U << ( w - 1 ); + mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1]; + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + { + if( rs_ctx->rsm->state == ecp_rsm_pre_dbl ) + goto dbl; + if( rs_ctx->rsm->state == ecp_rsm_pre_norm_dbl ) + goto norm_dbl; + if( rs_ctx->rsm->state == ecp_rsm_pre_add ) + goto add; + if( rs_ctx->rsm->state == ecp_rsm_pre_norm_add ) + goto norm_add; + } +#else + (void) rs_ctx; +#endif + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + { + rs_ctx->rsm->state = ecp_rsm_pre_dbl; + + /* initial state for the loop */ + rs_ctx->rsm->i = 0; + } + +dbl: +#endif + /* + * Set T[0] = P and + * T[2^{l-1}] = 2^{dl} P for l = 1 .. w-1 (this is not the final value) + */ + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &T[0], P ) ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0 ) + j = rs_ctx->rsm->i; + else +#endif + j = 0; + + for( ; j < d * ( w - 1 ); j++ ) + { + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_DBL ); + + i = 1U << ( j / d ); + cur = T + i; + + if( j % d == 0 ) + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( cur, T + ( i >> 1 ) ) ); + + MBEDTLS_MPI_CHK( ecp_double_jac( grp, cur, cur ) ); + } + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + rs_ctx->rsm->state = ecp_rsm_pre_norm_dbl; + +norm_dbl: +#endif + /* + * Normalize current elements in T. As T has holes, + * use an auxiliary array of pointers to elements in T. + */ + j = 0; + for( i = 1; i < T_size; i <<= 1 ) + TT[j++] = T + i; + + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV + 6 * j - 2 ); + + MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + rs_ctx->rsm->state = ecp_rsm_pre_add; + +add: +#endif + /* + * Compute the remaining ones using the minimal number of additions + * Be careful to update T[2^l] only after using it! + */ + MBEDTLS_ECP_BUDGET( ( T_size - 1 ) * MBEDTLS_ECP_OPS_ADD ); + + for( i = 1; i < T_size; i <<= 1 ) + { + j = i; + while( j-- ) + MBEDTLS_MPI_CHK( ecp_add_mixed( grp, &T[i + j], &T[j], &T[i] ) ); + } + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + rs_ctx->rsm->state = ecp_rsm_pre_norm_add; + +norm_add: +#endif + /* + * Normalize final elements in T. Even though there are no holes now, we + * still need the auxiliary array for homogeneity with the previous + * call. Also, skip T[0] which is already normalised, being a copy of P. + */ + for( j = 0; j + 1 < T_size; j++ ) + TT[j] = T + j + 1; + + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV + 6 * j - 2 ); + + MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) ); + +cleanup: +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL && + ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + { + if( rs_ctx->rsm->state == ecp_rsm_pre_dbl ) + rs_ctx->rsm->i = j; + } +#endif + + return( ret ); +} + +/* + * Select precomputed point: R = sign(i) * T[ abs(i) / 2 ] + * + * See ecp_comb_recode_core() for background + */ +static int ecp_select_comb( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_ecp_point T[], unsigned char T_size, + unsigned char i ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char ii, j; + + /* Ignore the "sign" bit and scale down */ + ii = ( i & 0x7Fu ) >> 1; + + /* Read the whole table to thwart cache-based timing attacks */ + for( j = 0; j < T_size; j++ ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->X, &T[j].X, j == ii ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->Y, &T[j].Y, j == ii ) ); + } + + /* Safely invert result if i is "negative" */ + MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, i >> 7 ) ); + +cleanup: + return( ret ); +} + +/* + * Core multiplication algorithm for the (modified) comb method. + * This part is actually common with the basic comb method (GECC 3.44) + * + * Cost: d A + d D + 1 R + */ +static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_ecp_point T[], unsigned char T_size, + const unsigned char x[], size_t d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_point Txi; + size_t i; + + mbedtls_ecp_point_init( &Txi ); + +#if !defined(MBEDTLS_ECP_RESTARTABLE) + (void) rs_ctx; +#endif + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL && + rs_ctx->rsm->state != ecp_rsm_comb_core ) + { + rs_ctx->rsm->i = 0; + rs_ctx->rsm->state = ecp_rsm_comb_core; + } + + /* new 'if' instead of nested for the sake of the 'else' branch */ + if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0 ) + { + /* restore current index (R already pointing to rs_ctx->rsm->R) */ + i = rs_ctx->rsm->i; + } + else +#endif + { + /* Start with a non-zero point and randomize its coordinates */ + i = d; + MBEDTLS_MPI_CHK( ecp_select_comb( grp, R, T, T_size, x[i] ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 1 ) ); +#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + if( f_rng != 0 ) +#endif + MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) ); + } + + while( i != 0 ) + { + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_DBL + MBEDTLS_ECP_OPS_ADD ); + --i; + + MBEDTLS_MPI_CHK( ecp_double_jac( grp, R, R ) ); + MBEDTLS_MPI_CHK( ecp_select_comb( grp, &Txi, T, T_size, x[i] ) ); + MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, R, &Txi ) ); + } + +cleanup: + + mbedtls_ecp_point_free( &Txi ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL && + ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + { + rs_ctx->rsm->i = i; + /* no need to save R, already pointing to rs_ctx->rsm->R */ + } +#endif + + return( ret ); +} + +/* + * Recode the scalar to get constant-time comb multiplication + * + * As the actual scalar recoding needs an odd scalar as a starting point, + * this wrapper ensures that by replacing m by N - m if necessary, and + * informs the caller that the result of multiplication will be negated. + * + * This works because we only support large prime order for Short Weierstrass + * curves, so N is always odd hence either m or N - m is. + * + * See ecp_comb_recode_core() for background. + */ +static int ecp_comb_recode_scalar( const mbedtls_ecp_group *grp, + const mbedtls_mpi *m, + unsigned char k[COMB_MAX_D + 1], + size_t d, + unsigned char w, + unsigned char *parity_trick ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi M, mm; + + mbedtls_mpi_init( &M ); + mbedtls_mpi_init( &mm ); + + /* N is always odd (see above), just make extra sure */ + if( mbedtls_mpi_get_bit( &grp->N, 0 ) != 1 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* do we need the parity trick? */ + *parity_trick = ( mbedtls_mpi_get_bit( m, 0 ) == 0 ); + + /* execute parity fix in constant time */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &M, m ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mm, &grp->N, m ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &M, &mm, *parity_trick ) ); + + /* actual scalar recoding */ + ecp_comb_recode_core( k, d, w, &M ); + +cleanup: + mbedtls_mpi_free( &mm ); + mbedtls_mpi_free( &M ); + + return( ret ); +} + +/* + * Perform comb multiplication (for short Weierstrass curves) + * once the auxiliary table has been pre-computed. + * + * Scalar recoding may use a parity trick that makes us compute -m * P, + * if that is the case we'll need to recover m * P at the end. + */ +static int ecp_mul_comb_after_precomp( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, + const mbedtls_mpi *m, + const mbedtls_ecp_point *T, + unsigned char T_size, + unsigned char w, + size_t d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char parity_trick; + unsigned char k[COMB_MAX_D + 1]; + mbedtls_ecp_point *RR = R; + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + { + RR = &rs_ctx->rsm->R; + + if( rs_ctx->rsm->state == ecp_rsm_final_norm ) + goto final_norm; + } +#endif + + MBEDTLS_MPI_CHK( ecp_comb_recode_scalar( grp, m, k, d, w, + &parity_trick ) ); + MBEDTLS_MPI_CHK( ecp_mul_comb_core( grp, RR, T, T_size, k, d, + f_rng, p_rng, rs_ctx ) ); + MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, RR, parity_trick ) ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + rs_ctx->rsm->state = ecp_rsm_final_norm; + +final_norm: + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV ); +#endif + /* + * Knowledge of the jacobian coordinates may leak the last few bits of the + * scalar [1], and since our MPI implementation isn't constant-flow, + * inversion (used for coordinate normalization) may leak the full value + * of its input via side-channels [2]. + * + * [1] https://eprint.iacr.org/2003/191 + * [2] https://eprint.iacr.org/2020/055 + * + * Avoid the leak by randomizing coordinates before we normalize them. + */ +#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + if( f_rng != 0 ) +#endif + MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, RR, f_rng, p_rng ) ); + + MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, RR ) ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, RR ) ); +#endif + +cleanup: + return( ret ); +} + +/* + * Pick window size based on curve size and whether we optimize for base point + */ +static unsigned char ecp_pick_window_size( const mbedtls_ecp_group *grp, + unsigned char p_eq_g ) +{ + unsigned char w; + + /* + * Minimize the number of multiplications, that is minimize + * 10 * d * w + 18 * 2^(w-1) + 11 * d + 7 * w, with d = ceil( nbits / w ) + * (see costs of the various parts, with 1S = 1M) + */ + w = grp->nbits >= 384 ? 5 : 4; + + /* + * If P == G, pre-compute a bit more, since this may be re-used later. + * Just adding one avoids upping the cost of the first mul too much, + * and the memory cost too. + */ + if( p_eq_g ) + w++; + + /* + * Make sure w is within bounds. + * (The last test is useful only for very small curves in the test suite.) + */ +#if( MBEDTLS_ECP_WINDOW_SIZE < 6 ) + if( w > MBEDTLS_ECP_WINDOW_SIZE ) + w = MBEDTLS_ECP_WINDOW_SIZE; +#endif + if( w >= grp->nbits ) + w = 2; + + return( w ); +} + +/* + * Multiplication using the comb method - for curves in short Weierstrass form + * + * This function is mainly responsible for administrative work: + * - managing the restart context if enabled + * - managing the table of precomputed points (passed between the below two + * functions): allocation, computation, ownership tranfer, freeing. + * + * It delegates the actual arithmetic work to: + * ecp_precompute_comb() and ecp_mul_comb_with_precomp() + * + * See comments on ecp_comb_recode_core() regarding the computation strategy. + */ +static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char w, p_eq_g, i; + size_t d; + unsigned char T_size = 0, T_ok = 0; + mbedtls_ecp_point *T = NULL; +#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + ecp_drbg_context drbg_ctx; + + ecp_drbg_init( &drbg_ctx ); +#endif + + ECP_RS_ENTER( rsm ); + +#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + if( f_rng == NULL ) + { + /* Adjust pointers */ + f_rng = &ecp_drbg_random; +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + p_rng = &rs_ctx->rsm->drbg_ctx; + else +#endif + p_rng = &drbg_ctx; + + /* Initialize internal DRBG if necessary */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx == NULL || rs_ctx->rsm == NULL || + rs_ctx->rsm->drbg_seeded == 0 ) +#endif + { + const size_t m_len = ( grp->nbits + 7 ) / 8; + MBEDTLS_MPI_CHK( ecp_drbg_seed( p_rng, m, m_len ) ); + } +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + rs_ctx->rsm->drbg_seeded = 1; +#endif + } +#endif /* !MBEDTLS_ECP_NO_INTERNAL_RNG */ + + /* Is P the base point ? */ +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 + p_eq_g = ( mbedtls_mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 && + mbedtls_mpi_cmp_mpi( &P->X, &grp->G.X ) == 0 ); +#else + p_eq_g = 0; +#endif + + /* Pick window size and deduce related sizes */ + w = ecp_pick_window_size( grp, p_eq_g ); + T_size = 1U << ( w - 1 ); + d = ( grp->nbits + w - 1 ) / w; + + /* Pre-computed table: do we have it already for the base point? */ + if( p_eq_g && grp->T != NULL ) + { + /* second pointer to the same table, will be deleted on exit */ + T = grp->T; + T_ok = 1; + } + else +#if defined(MBEDTLS_ECP_RESTARTABLE) + /* Pre-computed table: do we have one in progress? complete? */ + if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->T != NULL ) + { + /* transfer ownership of T from rsm to local function */ + T = rs_ctx->rsm->T; + rs_ctx->rsm->T = NULL; + rs_ctx->rsm->T_size = 0; + + /* This effectively jumps to the call to mul_comb_after_precomp() */ + T_ok = rs_ctx->rsm->state >= ecp_rsm_comb_core; + } + else +#endif + /* Allocate table if we didn't have any */ + { + T = mbedtls_calloc( T_size, sizeof( mbedtls_ecp_point ) ); + if( T == NULL ) + { + ret = MBEDTLS_ERR_ECP_ALLOC_FAILED; + goto cleanup; + } + + for( i = 0; i < T_size; i++ ) + mbedtls_ecp_point_init( &T[i] ); + + T_ok = 0; + } + + /* Compute table (or finish computing it) if not done already */ + if( !T_ok ) + { + MBEDTLS_MPI_CHK( ecp_precompute_comb( grp, T, P, w, d, rs_ctx ) ); + + if( p_eq_g ) + { + /* almost transfer ownership of T to the group, but keep a copy of + * the pointer to use for calling the next function more easily */ + grp->T = T; + grp->T_size = T_size; + } + } + + /* Actual comb multiplication using precomputed points */ + MBEDTLS_MPI_CHK( ecp_mul_comb_after_precomp( grp, R, m, + T, T_size, w, d, + f_rng, p_rng, rs_ctx ) ); + +cleanup: + +#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + ecp_drbg_free( &drbg_ctx ); +#endif + + /* does T belong to the group? */ + if( T == grp->T ) + T = NULL; + + /* does T belong to the restart context? */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS && T != NULL ) + { + /* transfer ownership of T from local function to rsm */ + rs_ctx->rsm->T_size = T_size; + rs_ctx->rsm->T = T; + T = NULL; + } +#endif + + /* did T belong to us? then let's destroy it! */ + if( T != NULL ) + { + for( i = 0; i < T_size; i++ ) + mbedtls_ecp_point_free( &T[i] ); + mbedtls_free( T ); + } + + /* don't free R while in progress in case R == P */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) +#endif + /* prevent caller from using invalid value */ + if( ret != 0 ) + mbedtls_ecp_point_free( R ); + + ECP_RS_LEAVE( rsm ); + + return( ret ); +} + +#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ + +#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) +/* + * For Montgomery curves, we do all the internal arithmetic in projective + * coordinates. Import/export of points uses only the x coordinates, which is + * internaly represented as X / Z. + * + * For scalar multiplication, we'll use a Montgomery ladder. + */ + +/* + * Normalize Montgomery x/z coordinates: X = X/Z, Z = 1 + * Cost: 1M + 1I + */ +static int ecp_normalize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + +#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_normalize_mxz( grp, P ) ); +#endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */ + + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &P->Z, &P->Z, &grp->P ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &P->X, &P->X, &P->Z ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) ); + +cleanup: + return( ret ); +} + +/* + * Randomize projective x/z coordinates: + * (X, Z) -> (l X, l Z) for random l + * This is sort of the reverse operation of ecp_normalize_mxz(). + * + * This countermeasure was first suggested in [2]. + * Cost: 2M + */ +static int ecp_randomize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi l; + size_t p_size; + int count = 0; + +#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_randomize_mxz( grp, P, f_rng, p_rng ); +#endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */ + + p_size = ( grp->pbits + 7 ) / 8; + mbedtls_mpi_init( &l ); + + /* Generate l such that 1 < l < p */ + do + { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) ); + + while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) ); + + if( count++ > 10 ) + { + ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; + goto cleanup; + } + } + while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &P->X, &P->X, &l ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &P->Z, &P->Z, &l ) ); + +cleanup: + mbedtls_mpi_free( &l ); + + return( ret ); +} + +/* + * Double-and-add: R = 2P, S = P + Q, with d = X(P - Q), + * for Montgomery curves in x/z coordinates. + * + * http://www.hyperelliptic.org/EFD/g1p/auto-code/montgom/xz/ladder/mladd-1987-m.op3 + * with + * d = X1 + * P = (X2, Z2) + * Q = (X3, Z3) + * R = (X4, Z4) + * S = (X5, Z5) + * and eliminating temporary variables tO, ..., t4. + * + * Cost: 5M + 4S + */ +static int ecp_double_add_mxz( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, mbedtls_ecp_point *S, + const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q, + const mbedtls_mpi *d ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi A, AA, B, BB, E, C, D, DA, CB; + +#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_double_add_mxz( grp, R, S, P, Q, d ) ); +#endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */ + + mbedtls_mpi_init( &A ); mbedtls_mpi_init( &AA ); mbedtls_mpi_init( &B ); + mbedtls_mpi_init( &BB ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &C ); + mbedtls_mpi_init( &D ); mbedtls_mpi_init( &DA ); mbedtls_mpi_init( &CB ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mod( grp, &A, &P->X, &P->Z ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &AA, &A, &A ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &B, &P->X, &P->Z ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &BB, &B, &B ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &E, &AA, &BB ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mod( grp, &C, &Q->X, &Q->Z ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &D, &Q->X, &Q->Z ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &DA, &D, &A ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &CB, &C, &B ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mod( grp, &S->X, &DA, &CB ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S->X, &S->X, &S->X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &S->Z, &DA, &CB ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S->Z, &S->Z, &S->Z ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S->Z, d, &S->Z ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &R->X, &AA, &BB ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &R->Z, &grp->A, &E ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mod( grp, &R->Z, &BB, &R->Z ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &R->Z, &E, &R->Z ) ); + +cleanup: + mbedtls_mpi_free( &A ); mbedtls_mpi_free( &AA ); mbedtls_mpi_free( &B ); + mbedtls_mpi_free( &BB ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &C ); + mbedtls_mpi_free( &D ); mbedtls_mpi_free( &DA ); mbedtls_mpi_free( &CB ); + + return( ret ); +} + +/* + * Multiplication with Montgomery ladder in x/z coordinates, + * for curves in Montgomery form + */ +static int ecp_mul_mxz( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i; + unsigned char b; + mbedtls_ecp_point RP; + mbedtls_mpi PX; +#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + ecp_drbg_context drbg_ctx; + + ecp_drbg_init( &drbg_ctx ); +#endif + mbedtls_ecp_point_init( &RP ); mbedtls_mpi_init( &PX ); + +#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + if( f_rng == NULL ) + { + const size_t m_len = ( grp->nbits + 7 ) / 8; + MBEDTLS_MPI_CHK( ecp_drbg_seed( &drbg_ctx, m, m_len ) ); + f_rng = &ecp_drbg_random; + p_rng = &drbg_ctx; + } +#endif /* !MBEDTLS_ECP_NO_INTERNAL_RNG */ + + /* Save PX and read from P before writing to R, in case P == R */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &PX, &P->X ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &RP, P ) ); + + /* Set R to zero in modified x/z coordinates */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->X, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 0 ) ); + mbedtls_mpi_free( &R->Y ); + + /* RP.X might be sligtly larger than P, so reduce it */ + MOD_ADD( RP.X ); + + /* Randomize coordinates of the starting point */ +#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + if( f_rng != NULL ) +#endif + MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, &RP, f_rng, p_rng ) ); + + /* Loop invariant: R = result so far, RP = R + P */ + i = mbedtls_mpi_bitlen( m ); /* one past the (zero-based) most significant bit */ + while( i-- > 0 ) + { + b = mbedtls_mpi_get_bit( m, i ); + /* + * if (b) R = 2R + P else R = 2R, + * which is: + * if (b) double_add( RP, R, RP, R ) + * else double_add( R, RP, R, RP ) + * but using safe conditional swaps to avoid leaks + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) ); + MBEDTLS_MPI_CHK( ecp_double_add_mxz( grp, R, &RP, R, &RP, &PX ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) ); + } + + /* + * Knowledge of the projective coordinates may leak the last few bits of the + * scalar [1], and since our MPI implementation isn't constant-flow, + * inversion (used for coordinate normalization) may leak the full value + * of its input via side-channels [2]. + * + * [1] https://eprint.iacr.org/2003/191 + * [2] https://eprint.iacr.org/2020/055 + * + * Avoid the leak by randomizing coordinates before we normalize them. + */ +#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + if( f_rng != NULL ) +#endif + MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, R, f_rng, p_rng ) ); + + MBEDTLS_MPI_CHK( ecp_normalize_mxz( grp, R ) ); + +cleanup: +#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + ecp_drbg_free( &drbg_ctx ); +#endif + + mbedtls_ecp_point_free( &RP ); mbedtls_mpi_free( &PX ); + + return( ret ); +} + +#endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */ + +/* + * Restartable multiplication R = m * P + */ +int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + char is_grp_capable = 0; +#endif + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( R != NULL ); + ECP_VALIDATE_RET( m != NULL ); + ECP_VALIDATE_RET( P != NULL ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + /* reset ops count for this call if top-level */ + if( rs_ctx != NULL && rs_ctx->depth++ == 0 ) + rs_ctx->ops_done = 0; +#else + (void) rs_ctx; +#endif + +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + if( ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) ) + MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) ); +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ + +#if defined(MBEDTLS_ECP_RESTARTABLE) + /* skip argument check when restarting */ + if( rs_ctx == NULL || rs_ctx->rsm == NULL ) +#endif + { + /* check_privkey is free */ + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_CHK ); + + /* Common sanity checks */ + MBEDTLS_MPI_CHK( mbedtls_ecp_check_privkey( grp, m ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, P ) ); + } + + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; +#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) + if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY ) + MBEDTLS_MPI_CHK( ecp_mul_mxz( grp, R, m, P, f_rng, p_rng ) ); +#endif +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) + if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS ) + MBEDTLS_MPI_CHK( ecp_mul_comb( grp, R, m, P, f_rng, p_rng, rs_ctx ) ); +#endif + +cleanup: + +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + if( is_grp_capable ) + mbedtls_internal_ecp_free( grp ); +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL ) + rs_ctx->depth--; +#endif + + return( ret ); +} + +/* + * Multiplication R = m * P + */ +int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( R != NULL ); + ECP_VALIDATE_RET( m != NULL ); + ECP_VALIDATE_RET( P != NULL ); + return( mbedtls_ecp_mul_restartable( grp, R, m, P, f_rng, p_rng, NULL ) ); +} + +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) +/* + * Check that an affine point is valid as a public key, + * short weierstrass curves (SEC1 3.2.3.1) + */ +static int ecp_check_pubkey_sw( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi YY, RHS; + + /* pt coordinates must be normalized for our checks */ + if( mbedtls_mpi_cmp_int( &pt->X, 0 ) < 0 || + mbedtls_mpi_cmp_int( &pt->Y, 0 ) < 0 || + mbedtls_mpi_cmp_mpi( &pt->X, &grp->P ) >= 0 || + mbedtls_mpi_cmp_mpi( &pt->Y, &grp->P ) >= 0 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + + mbedtls_mpi_init( &YY ); mbedtls_mpi_init( &RHS ); + + /* + * YY = Y^2 + * RHS = X (X^2 + A) + B = X^3 + A X + B + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &YY, &pt->Y, &pt->Y ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &RHS, &pt->X, &pt->X ) ); + + /* Special case for A = -3 */ + if( grp->A.p == NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &RHS, &RHS, 3 ) ); MOD_SUB( RHS ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mod( grp, &RHS, &RHS, &grp->A ) ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &RHS, &RHS, &pt->X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mod( grp, &RHS, &RHS, &grp->B ) ); + + if( mbedtls_mpi_cmp_mpi( &YY, &RHS ) != 0 ) + ret = MBEDTLS_ERR_ECP_INVALID_KEY; + +cleanup: + + mbedtls_mpi_free( &YY ); mbedtls_mpi_free( &RHS ); + + return( ret ); +} +#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ + +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) +/* + * R = m * P with shortcuts for m == 1 and m == -1 + * NOT constant-time - ONLY for short Weierstrass! + */ +static int mbedtls_ecp_mul_shortcuts( mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, + const mbedtls_mpi *m, + const mbedtls_ecp_point *P, + mbedtls_ecp_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( mbedtls_mpi_cmp_int( m, 1 ) == 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) ); + } + else if( mbedtls_mpi_cmp_int( m, -1 ) == 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) ); + if( mbedtls_mpi_cmp_int( &R->Y, 0 ) != 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &R->Y, &grp->P, &R->Y ) ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, R, m, P, + NULL, NULL, rs_ctx ) ); + } + +cleanup: + return( ret ); +} + +/* + * Restartable linear combination + * NOT constant-time + */ +int mbedtls_ecp_muladd_restartable( + mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + const mbedtls_mpi *n, const mbedtls_ecp_point *Q, + mbedtls_ecp_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_point mP; + mbedtls_ecp_point *pmP = &mP; + mbedtls_ecp_point *pR = R; +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + char is_grp_capable = 0; +#endif + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( R != NULL ); + ECP_VALIDATE_RET( m != NULL ); + ECP_VALIDATE_RET( P != NULL ); + ECP_VALIDATE_RET( n != NULL ); + ECP_VALIDATE_RET( Q != NULL ); + + if( mbedtls_ecp_get_type( grp ) != MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS ) + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); + + mbedtls_ecp_point_init( &mP ); + + ECP_RS_ENTER( ma ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->ma != NULL ) + { + /* redirect intermediate results to restart context */ + pmP = &rs_ctx->ma->mP; + pR = &rs_ctx->ma->R; + + /* jump to next operation */ + if( rs_ctx->ma->state == ecp_rsma_mul2 ) + goto mul2; + if( rs_ctx->ma->state == ecp_rsma_add ) + goto add; + if( rs_ctx->ma->state == ecp_rsma_norm ) + goto norm; + } +#endif /* MBEDTLS_ECP_RESTARTABLE */ + + MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, pmP, m, P, rs_ctx ) ); +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->ma != NULL ) + rs_ctx->ma->state = ecp_rsma_mul2; + +mul2: +#endif + MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, pR, n, Q, rs_ctx ) ); + +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + if( ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) ) + MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) ); +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->ma != NULL ) + rs_ctx->ma->state = ecp_rsma_add; + +add: +#endif + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_ADD ); + MBEDTLS_MPI_CHK( ecp_add_mixed( grp, pR, pmP, pR ) ); +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->ma != NULL ) + rs_ctx->ma->state = ecp_rsma_norm; + +norm: +#endif + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV ); + MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, pR ) ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->ma != NULL ) + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, pR ) ); +#endif + +cleanup: +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + if( is_grp_capable ) + mbedtls_internal_ecp_free( grp ); +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ + + mbedtls_ecp_point_free( &mP ); + + ECP_RS_LEAVE( ma ); + + return( ret ); +} + +/* + * Linear combination + * NOT constant-time + */ +int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + const mbedtls_mpi *n, const mbedtls_ecp_point *Q ) +{ + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( R != NULL ); + ECP_VALIDATE_RET( m != NULL ); + ECP_VALIDATE_RET( P != NULL ); + ECP_VALIDATE_RET( n != NULL ); + ECP_VALIDATE_RET( Q != NULL ); + return( mbedtls_ecp_muladd_restartable( grp, R, m, P, n, Q, NULL ) ); +} +#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ + +#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) +/* + * Check validity of a public key for Montgomery curves with x-only schemes + */ +static int ecp_check_pubkey_mx( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt ) +{ + /* [Curve25519 p. 5] Just check X is the correct number of bytes */ + /* Allow any public value, if it's too big then we'll just reduce it mod p + * (RFC 7748 sec. 5 para. 3). */ + if( mbedtls_mpi_size( &pt->X ) > ( grp->nbits + 7 ) / 8 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + + return( 0 ); +} +#endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */ + +/* + * Check that a point is valid as a public key + */ +int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, + const mbedtls_ecp_point *pt ) +{ + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( pt != NULL ); + + /* Must use affine coordinates */ + if( mbedtls_mpi_cmp_int( &pt->Z, 1 ) != 0 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + +#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) + if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY ) + return( ecp_check_pubkey_mx( grp, pt ) ); +#endif +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) + if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS ) + return( ecp_check_pubkey_sw( grp, pt ) ); +#endif + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); +} + +/* + * Check that an mbedtls_mpi is valid as a private key + */ +int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, + const mbedtls_mpi *d ) +{ + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( d != NULL ); + +#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) + if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY ) + { + /* see RFC 7748 sec. 5 para. 5 */ + if( mbedtls_mpi_get_bit( d, 0 ) != 0 || + mbedtls_mpi_get_bit( d, 1 ) != 0 || + mbedtls_mpi_bitlen( d ) - 1 != grp->nbits ) /* mbedtls_mpi_bitlen is one-based! */ + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + + /* see [Curve25519] page 5 */ + if( grp->nbits == 254 && mbedtls_mpi_get_bit( d, 2 ) != 0 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + + return( 0 ); + } +#endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */ +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) + if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS ) + { + /* see SEC1 3.2 */ + if( mbedtls_mpi_cmp_int( d, 1 ) < 0 || + mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + else + return( 0 ); + } +#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ + + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); +} + +/* + * Generate a private key + */ +int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp, + mbedtls_mpi *d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + size_t n_size; + + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( d != NULL ); + ECP_VALIDATE_RET( f_rng != NULL ); + + n_size = ( grp->nbits + 7 ) / 8; + +#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) + if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY ) + { + /* [M225] page 5 */ + size_t b; + + do { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) ); + } while( mbedtls_mpi_bitlen( d ) == 0); + + /* Make sure the most significant bit is nbits */ + b = mbedtls_mpi_bitlen( d ) - 1; /* mbedtls_mpi_bitlen is one-based */ + if( b > grp->nbits ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, b - grp->nbits ) ); + else + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, grp->nbits, 1 ) ); + + /* Make sure the last two bits are unset for Curve448, three bits for + Curve25519 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 0, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 1, 0 ) ); + if( grp->nbits == 254 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 2, 0 ) ); + } + } +#endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */ + +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) + if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS ) + { + /* SEC1 3.2.1: Generate d such that 1 <= n < N */ + int count = 0; + unsigned cmp = 0; + + /* + * Match the procedure given in RFC 6979 (deterministic ECDSA): + * - use the same byte ordering; + * - keep the leftmost nbits bits of the generated octet string; + * - try until result is in the desired range. + * This also avoids any biais, which is especially important for ECDSA. + */ + do + { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, 8 * n_size - grp->nbits ) ); + + /* + * Each try has at worst a probability 1/2 of failing (the msb has + * a probability 1/2 of being 0, and then the result will be < N), + * so after 30 tries failure probability is a most 2**(-30). + * + * For most curves, 1 try is enough with overwhelming probability, + * since N starts with a lot of 1s in binary, but some curves + * such as secp224k1 are actually very close to the worst case. + */ + if( ++count > 30 ) + { + ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; + goto cleanup; + } + + ret = mbedtls_mpi_lt_mpi_ct( d, &grp->N, &cmp ); + if( ret != 0 ) + { + goto cleanup; + } + } + while( mbedtls_mpi_cmp_int( d, 1 ) < 0 || cmp != 1 ); + } +#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ + +cleanup: + return( ret ); +} + +/* + * Generate a keypair with configurable base point + */ +int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp, + const mbedtls_ecp_point *G, + mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( d != NULL ); + ECP_VALIDATE_RET( G != NULL ); + ECP_VALIDATE_RET( Q != NULL ); + ECP_VALIDATE_RET( f_rng != NULL ); + + MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, Q, d, G, f_rng, p_rng ) ); + +cleanup: + return( ret ); +} + +/* + * Generate key pair, wrapper for conventional base point + */ +int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp, + mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( d != NULL ); + ECP_VALIDATE_RET( Q != NULL ); + ECP_VALIDATE_RET( f_rng != NULL ); + + return( mbedtls_ecp_gen_keypair_base( grp, &grp->G, d, Q, f_rng, p_rng ) ); +} + +/* + * Generate a keypair, prettier wrapper + */ +int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + ECP_VALIDATE_RET( key != NULL ); + ECP_VALIDATE_RET( f_rng != NULL ); + + if( ( ret = mbedtls_ecp_group_load( &key->grp, grp_id ) ) != 0 ) + return( ret ); + + return( mbedtls_ecp_gen_keypair( &key->grp, &key->d, &key->Q, f_rng, p_rng ) ); +} + +#define ECP_CURVE25519_KEY_SIZE 32 +/* + * Read a private key. + */ +int mbedtls_ecp_read_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, + const unsigned char *buf, size_t buflen ) +{ + int ret = 0; + + ECP_VALIDATE_RET( key != NULL ); + ECP_VALIDATE_RET( buf != NULL ); + + if( ( ret = mbedtls_ecp_group_load( &key->grp, grp_id ) ) != 0 ) + return( ret ); + + ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; + +#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) + if( mbedtls_ecp_get_type( &key->grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY ) + { + /* + * If it is Curve25519 curve then mask the key as mandated by RFC7748 + */ + if( grp_id == MBEDTLS_ECP_DP_CURVE25519 ) + { + if( buflen != ECP_CURVE25519_KEY_SIZE ) + return MBEDTLS_ERR_ECP_INVALID_KEY; + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary_le( &key->d, buf, buflen ) ); + + /* Set the three least significant bits to 0 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( &key->d, 0, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( &key->d, 1, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( &key->d, 2, 0 ) ); + + /* Set the most significant bit to 0 */ + MBEDTLS_MPI_CHK( + mbedtls_mpi_set_bit( &key->d, + ECP_CURVE25519_KEY_SIZE * 8 - 1, 0 ) + ); + + /* Set the second most significant bit to 1 */ + MBEDTLS_MPI_CHK( + mbedtls_mpi_set_bit( &key->d, + ECP_CURVE25519_KEY_SIZE * 8 - 2, 1 ) + ); + } + else + ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; + } + +#endif +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) + if( mbedtls_ecp_get_type( &key->grp ) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &key->d, buf, buflen ) ); + + MBEDTLS_MPI_CHK( mbedtls_ecp_check_privkey( &key->grp, &key->d ) ); + } + +#endif +cleanup: + + if( ret != 0 ) + mbedtls_mpi_free( &key->d ); + + return( ret ); +} + +/* + * Write a private key. + */ +int mbedtls_ecp_write_key( mbedtls_ecp_keypair *key, + unsigned char *buf, size_t buflen ) +{ + int ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; + + ECP_VALIDATE_RET( key != NULL ); + ECP_VALIDATE_RET( buf != NULL ); + +#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) + if( mbedtls_ecp_get_type( &key->grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY ) + { + if( key->grp.id == MBEDTLS_ECP_DP_CURVE25519 ) + { + if( buflen < ECP_CURVE25519_KEY_SIZE ) + return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; + + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary_le( &key->d, buf, buflen ) ); + } + else + ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; + } + +#endif +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) + if( mbedtls_ecp_get_type( &key->grp ) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &key->d, buf, buflen ) ); + } + +#endif +cleanup: + + return( ret ); +} + + +/* + * Check a public-private key pair + */ +int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_point Q; + mbedtls_ecp_group grp; + ECP_VALIDATE_RET( pub != NULL ); + ECP_VALIDATE_RET( prv != NULL ); + + if( pub->grp.id == MBEDTLS_ECP_DP_NONE || + pub->grp.id != prv->grp.id || + mbedtls_mpi_cmp_mpi( &pub->Q.X, &prv->Q.X ) || + mbedtls_mpi_cmp_mpi( &pub->Q.Y, &prv->Q.Y ) || + mbedtls_mpi_cmp_mpi( &pub->Q.Z, &prv->Q.Z ) ) + { + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + } + + mbedtls_ecp_point_init( &Q ); + mbedtls_ecp_group_init( &grp ); + + /* mbedtls_ecp_mul() needs a non-const group... */ + mbedtls_ecp_group_copy( &grp, &prv->grp ); + + /* Also checks d is valid */ + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &Q, &prv->d, &prv->grp.G, NULL, NULL ) ); + + if( mbedtls_mpi_cmp_mpi( &Q.X, &prv->Q.X ) || + mbedtls_mpi_cmp_mpi( &Q.Y, &prv->Q.Y ) || + mbedtls_mpi_cmp_mpi( &Q.Z, &prv->Q.Z ) ) + { + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } + +cleanup: + mbedtls_ecp_point_free( &Q ); + mbedtls_ecp_group_free( &grp ); + + return( ret ); +} + +#if defined(MBEDTLS_SELF_TEST) + +/* Adjust the exponent to be a valid private point for the specified curve. + * This is sometimes necessary because we use a single set of exponents + * for all curves but the validity of values depends on the curve. */ +static int self_test_adjust_exponent( const mbedtls_ecp_group *grp, + mbedtls_mpi *m ) +{ + int ret = 0; + switch( grp->id ) + { + /* If Curve25519 is available, then that's what we use for the + * Montgomery test, so we don't need the adjustment code. */ +#if ! defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) + case MBEDTLS_ECP_DP_CURVE448: + /* Move highest bit from 254 to N-1. Setting bit N-1 is + * necessary to enforce the highest-bit-set constraint. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( m, 254, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( m, grp->nbits, 1 ) ); + /* Copy second-highest bit from 253 to N-2. This is not + * necessary but improves the test variety a bit. */ + MBEDTLS_MPI_CHK( + mbedtls_mpi_set_bit( m, grp->nbits - 1, + mbedtls_mpi_get_bit( m, 253 ) ) ); + break; +#endif +#endif /* ! defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) */ + default: + /* Non-Montgomery curves and Curve25519 need no adjustment. */ + (void) grp; + (void) m; + goto cleanup; + } +cleanup: + return( ret ); +} + +/* Calculate R = m.P for each m in exponents. Check that the number of + * basic operations doesn't depend on the value of m. */ +static int self_test_point( int verbose, + mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, + mbedtls_mpi *m, + const mbedtls_ecp_point *P, + const char *const *exponents, + size_t n_exponents ) +{ + int ret = 0; + size_t i = 0; + unsigned long add_c_prev, dbl_c_prev, mul_c_prev; + add_count = 0; + dbl_count = 0; + mul_count = 0; + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( m, 16, exponents[0] ) ); + MBEDTLS_MPI_CHK( self_test_adjust_exponent( grp, m ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, R, m, P, NULL, NULL ) ); + + for( i = 1; i < n_exponents; i++ ) + { + add_c_prev = add_count; + dbl_c_prev = dbl_count; + mul_c_prev = mul_count; + add_count = 0; + dbl_count = 0; + mul_count = 0; + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( m, 16, exponents[i] ) ); + MBEDTLS_MPI_CHK( self_test_adjust_exponent( grp, m ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, R, m, P, NULL, NULL ) ); + + if( add_count != add_c_prev || + dbl_count != dbl_c_prev || + mul_count != mul_c_prev ) + { + ret = 1; + break; + } + } + +cleanup: + if( verbose != 0 ) + { + if( ret != 0 ) + mbedtls_printf( "failed (%u)\n", (unsigned int) i ); + else + mbedtls_printf( "passed\n" ); + } + return( ret ); +} + +/* + * Checkup routine + */ +int mbedtls_ecp_self_test( int verbose ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_group grp; + mbedtls_ecp_point R, P; + mbedtls_mpi m; + +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) + /* Exponents especially adapted for secp192k1, which has the lowest + * order n of all supported curves (secp192r1 is in a slightly larger + * field but the order of its base point is slightly smaller). */ + const char *sw_exponents[] = + { + "000000000000000000000000000000000000000000000001", /* one */ + "FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8C", /* n - 1 */ + "5EA6F389A38B8BC81E767753B15AA5569E1782E30ABE7D25", /* random */ + "400000000000000000000000000000000000000000000000", /* one and zeros */ + "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", /* all ones */ + "555555555555555555555555555555555555555555555555", /* 101010... */ + }; +#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ +#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) + const char *m_exponents[] = + { + /* Valid private values for Curve25519. In a build with Curve448 + * but not Curve25519, they will be adjusted in + * self_test_adjust_exponent(). */ + "4000000000000000000000000000000000000000000000000000000000000000", + "5C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C30", + "5715ECCE24583F7A7023C24164390586842E816D7280A49EF6DF4EAE6B280BF8", + "41A2B017516F6D254E1F002BCCBADD54BE30F8CEC737A0E912B4963B6BA74460", + "5555555555555555555555555555555555555555555555555555555555555550", + "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8", + }; +#endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */ + + mbedtls_ecp_group_init( &grp ); + mbedtls_ecp_point_init( &R ); + mbedtls_ecp_point_init( &P ); + mbedtls_mpi_init( &m ); + +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) + /* Use secp192r1 if available, or any available curve */ +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, MBEDTLS_ECP_DP_SECP192R1 ) ); +#else + MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, mbedtls_ecp_curve_list()->grp_id ) ); +#endif + + if( verbose != 0 ) + mbedtls_printf( " ECP SW test #1 (constant op_count, base point G): " ); + /* Do a dummy multiplication first to trigger precomputation */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &m, 2 ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &P, &m, &grp.G, NULL, NULL ) ); + ret = self_test_point( verbose, + &grp, &R, &m, &grp.G, + sw_exponents, + sizeof( sw_exponents ) / sizeof( sw_exponents[0] )); + if( ret != 0 ) + goto cleanup; + + if( verbose != 0 ) + mbedtls_printf( " ECP SW test #2 (constant op_count, other point): " ); + /* We computed P = 2G last time, use it */ + ret = self_test_point( verbose, + &grp, &R, &m, &P, + sw_exponents, + sizeof( sw_exponents ) / sizeof( sw_exponents[0] )); + if( ret != 0 ) + goto cleanup; + + mbedtls_ecp_group_free( &grp ); + mbedtls_ecp_point_free( &R ); +#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ + +#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) + if( verbose != 0 ) + mbedtls_printf( " ECP Montgomery test (constant op_count): " ); +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) + MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, MBEDTLS_ECP_DP_CURVE25519 ) ); +#elif defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) + MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, MBEDTLS_ECP_DP_CURVE448 ) ); +#else +#error "MBEDTLS_ECP_MONTGOMERY_ENABLED is defined, but no curve is supported for self-test" +#endif + ret = self_test_point( verbose, + &grp, &R, &m, &grp.G, + m_exponents, + sizeof( m_exponents ) / sizeof( m_exponents[0] )); + if( ret != 0 ) + goto cleanup; +#endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */ + +cleanup: + + if( ret < 0 && verbose != 0 ) + mbedtls_printf( "Unexpected error, return code = %08X\n", (unsigned int) ret ); + + mbedtls_ecp_group_free( &grp ); + mbedtls_ecp_point_free( &R ); + mbedtls_ecp_point_free( &P ); + mbedtls_mpi_free( &m ); + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* !MBEDTLS_ECP_ALT */ + +#endif /* MBEDTLS_ECP_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/ecp_curves.c b/Android/Level4/app/src/main/c/mbedtls/library/ecp_curves.c new file mode 100644 index 0000000..05df307 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/ecp_curves.c @@ -0,0 +1,1484 @@ +/* + * Elliptic curves over GF(p): curve-specific data and functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 "common.h" + +#if defined(MBEDTLS_ECP_C) + +#include "mbedtls/ecp.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if !defined(MBEDTLS_ECP_ALT) + +/* Parameter validation macros based on platform_util.h */ +#define ECP_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA ) +#define ECP_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +/* + * Conversion macros for embedded constants: + * build lists of mbedtls_mpi_uint's from lists of unsigned char's grouped by 8, 4 or 2 + */ +#if defined(MBEDTLS_HAVE_INT32) + +#define BYTES_TO_T_UINT_4( a, b, c, d ) \ + ( (mbedtls_mpi_uint) (a) << 0 ) | \ + ( (mbedtls_mpi_uint) (b) << 8 ) | \ + ( (mbedtls_mpi_uint) (c) << 16 ) | \ + ( (mbedtls_mpi_uint) (d) << 24 ) + +#define BYTES_TO_T_UINT_2( a, b ) \ + BYTES_TO_T_UINT_4( a, b, 0, 0 ) + +#define BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \ + BYTES_TO_T_UINT_4( a, b, c, d ), \ + BYTES_TO_T_UINT_4( e, f, g, h ) + +#else /* 64-bits */ + +#define BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \ + ( (mbedtls_mpi_uint) (a) << 0 ) | \ + ( (mbedtls_mpi_uint) (b) << 8 ) | \ + ( (mbedtls_mpi_uint) (c) << 16 ) | \ + ( (mbedtls_mpi_uint) (d) << 24 ) | \ + ( (mbedtls_mpi_uint) (e) << 32 ) | \ + ( (mbedtls_mpi_uint) (f) << 40 ) | \ + ( (mbedtls_mpi_uint) (g) << 48 ) | \ + ( (mbedtls_mpi_uint) (h) << 56 ) + +#define BYTES_TO_T_UINT_4( a, b, c, d ) \ + BYTES_TO_T_UINT_8( a, b, c, d, 0, 0, 0, 0 ) + +#define BYTES_TO_T_UINT_2( a, b ) \ + BYTES_TO_T_UINT_8( a, b, 0, 0, 0, 0, 0, 0 ) + +#endif /* bits in mbedtls_mpi_uint */ + +/* + * Note: the constants are in little-endian order + * to be directly usable in MPIs + */ + +/* + * Domain parameters for secp192r1 + */ +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) +static const mbedtls_mpi_uint secp192r1_p[] = { + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint secp192r1_b[] = { + BYTES_TO_T_UINT_8( 0xB1, 0xB9, 0x46, 0xC1, 0xEC, 0xDE, 0xB8, 0xFE ), + BYTES_TO_T_UINT_8( 0x49, 0x30, 0x24, 0x72, 0xAB, 0xE9, 0xA7, 0x0F ), + BYTES_TO_T_UINT_8( 0xE7, 0x80, 0x9C, 0xE5, 0x19, 0x05, 0x21, 0x64 ), +}; +static const mbedtls_mpi_uint secp192r1_gx[] = { + BYTES_TO_T_UINT_8( 0x12, 0x10, 0xFF, 0x82, 0xFD, 0x0A, 0xFF, 0xF4 ), + BYTES_TO_T_UINT_8( 0x00, 0x88, 0xA1, 0x43, 0xEB, 0x20, 0xBF, 0x7C ), + BYTES_TO_T_UINT_8( 0xF6, 0x90, 0x30, 0xB0, 0x0E, 0xA8, 0x8D, 0x18 ), +}; +static const mbedtls_mpi_uint secp192r1_gy[] = { + BYTES_TO_T_UINT_8( 0x11, 0x48, 0x79, 0x1E, 0xA1, 0x77, 0xF9, 0x73 ), + BYTES_TO_T_UINT_8( 0xD5, 0xCD, 0x24, 0x6B, 0xED, 0x11, 0x10, 0x63 ), + BYTES_TO_T_UINT_8( 0x78, 0xDA, 0xC8, 0xFF, 0x95, 0x2B, 0x19, 0x07 ), +}; +static const mbedtls_mpi_uint secp192r1_n[] = { + BYTES_TO_T_UINT_8( 0x31, 0x28, 0xD2, 0xB4, 0xB1, 0xC9, 0x6B, 0x14 ), + BYTES_TO_T_UINT_8( 0x36, 0xF8, 0xDE, 0x99, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ + +/* + * Domain parameters for secp224r1 + */ +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) +static const mbedtls_mpi_uint secp224r1_p[] = { + BYTES_TO_T_UINT_8( 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), + BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224r1_b[] = { + BYTES_TO_T_UINT_8( 0xB4, 0xFF, 0x55, 0x23, 0x43, 0x39, 0x0B, 0x27 ), + BYTES_TO_T_UINT_8( 0xBA, 0xD8, 0xBF, 0xD7, 0xB7, 0xB0, 0x44, 0x50 ), + BYTES_TO_T_UINT_8( 0x56, 0x32, 0x41, 0xF5, 0xAB, 0xB3, 0x04, 0x0C ), + BYTES_TO_T_UINT_4( 0x85, 0x0A, 0x05, 0xB4 ), +}; +static const mbedtls_mpi_uint secp224r1_gx[] = { + BYTES_TO_T_UINT_8( 0x21, 0x1D, 0x5C, 0x11, 0xD6, 0x80, 0x32, 0x34 ), + BYTES_TO_T_UINT_8( 0x22, 0x11, 0xC2, 0x56, 0xD3, 0xC1, 0x03, 0x4A ), + BYTES_TO_T_UINT_8( 0xB9, 0x90, 0x13, 0x32, 0x7F, 0xBF, 0xB4, 0x6B ), + BYTES_TO_T_UINT_4( 0xBD, 0x0C, 0x0E, 0xB7 ), +}; +static const mbedtls_mpi_uint secp224r1_gy[] = { + BYTES_TO_T_UINT_8( 0x34, 0x7E, 0x00, 0x85, 0x99, 0x81, 0xD5, 0x44 ), + BYTES_TO_T_UINT_8( 0x64, 0x47, 0x07, 0x5A, 0xA0, 0x75, 0x43, 0xCD ), + BYTES_TO_T_UINT_8( 0xE6, 0xDF, 0x22, 0x4C, 0xFB, 0x23, 0xF7, 0xB5 ), + BYTES_TO_T_UINT_4( 0x88, 0x63, 0x37, 0xBD ), +}; +static const mbedtls_mpi_uint secp224r1_n[] = { + BYTES_TO_T_UINT_8( 0x3D, 0x2A, 0x5C, 0x5C, 0x45, 0x29, 0xDD, 0x13 ), + BYTES_TO_T_UINT_8( 0x3E, 0xF0, 0xB8, 0xE0, 0xA2, 0x16, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_4( 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ + +/* + * Domain parameters for secp256r1 + */ +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) +static const mbedtls_mpi_uint secp256r1_p[] = { + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ), + BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), + BYTES_TO_T_UINT_8( 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint secp256r1_b[] = { + BYTES_TO_T_UINT_8( 0x4B, 0x60, 0xD2, 0x27, 0x3E, 0x3C, 0xCE, 0x3B ), + BYTES_TO_T_UINT_8( 0xF6, 0xB0, 0x53, 0xCC, 0xB0, 0x06, 0x1D, 0x65 ), + BYTES_TO_T_UINT_8( 0xBC, 0x86, 0x98, 0x76, 0x55, 0xBD, 0xEB, 0xB3 ), + BYTES_TO_T_UINT_8( 0xE7, 0x93, 0x3A, 0xAA, 0xD8, 0x35, 0xC6, 0x5A ), +}; +static const mbedtls_mpi_uint secp256r1_gx[] = { + BYTES_TO_T_UINT_8( 0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4 ), + BYTES_TO_T_UINT_8( 0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, 0x77 ), + BYTES_TO_T_UINT_8( 0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8 ), + BYTES_TO_T_UINT_8( 0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, 0x17, 0x6B ), +}; +static const mbedtls_mpi_uint secp256r1_gy[] = { + BYTES_TO_T_UINT_8( 0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB ), + BYTES_TO_T_UINT_8( 0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, 0x2B ), + BYTES_TO_T_UINT_8( 0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E ), + BYTES_TO_T_UINT_8( 0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, 0xE3, 0x4F ), +}; +static const mbedtls_mpi_uint secp256r1_n[] = { + BYTES_TO_T_UINT_8( 0x51, 0x25, 0x63, 0xFC, 0xC2, 0xCA, 0xB9, 0xF3 ), + BYTES_TO_T_UINT_8( 0x84, 0x9E, 0x17, 0xA7, 0xAD, 0xFA, 0xE6, 0xBC ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ + +/* + * Domain parameters for secp384r1 + */ +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +static const mbedtls_mpi_uint secp384r1_p[] = { + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ), + BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint secp384r1_b[] = { + BYTES_TO_T_UINT_8( 0xEF, 0x2A, 0xEC, 0xD3, 0xED, 0xC8, 0x85, 0x2A ), + BYTES_TO_T_UINT_8( 0x9D, 0xD1, 0x2E, 0x8A, 0x8D, 0x39, 0x56, 0xC6 ), + BYTES_TO_T_UINT_8( 0x5A, 0x87, 0x13, 0x50, 0x8F, 0x08, 0x14, 0x03 ), + BYTES_TO_T_UINT_8( 0x12, 0x41, 0x81, 0xFE, 0x6E, 0x9C, 0x1D, 0x18 ), + BYTES_TO_T_UINT_8( 0x19, 0x2D, 0xF8, 0xE3, 0x6B, 0x05, 0x8E, 0x98 ), + BYTES_TO_T_UINT_8( 0xE4, 0xE7, 0x3E, 0xE2, 0xA7, 0x2F, 0x31, 0xB3 ), +}; +static const mbedtls_mpi_uint secp384r1_gx[] = { + BYTES_TO_T_UINT_8( 0xB7, 0x0A, 0x76, 0x72, 0x38, 0x5E, 0x54, 0x3A ), + BYTES_TO_T_UINT_8( 0x6C, 0x29, 0x55, 0xBF, 0x5D, 0xF2, 0x02, 0x55 ), + BYTES_TO_T_UINT_8( 0x38, 0x2A, 0x54, 0x82, 0xE0, 0x41, 0xF7, 0x59 ), + BYTES_TO_T_UINT_8( 0x98, 0x9B, 0xA7, 0x8B, 0x62, 0x3B, 0x1D, 0x6E ), + BYTES_TO_T_UINT_8( 0x74, 0xAD, 0x20, 0xF3, 0x1E, 0xC7, 0xB1, 0x8E ), + BYTES_TO_T_UINT_8( 0x37, 0x05, 0x8B, 0xBE, 0x22, 0xCA, 0x87, 0xAA ), +}; +static const mbedtls_mpi_uint secp384r1_gy[] = { + BYTES_TO_T_UINT_8( 0x5F, 0x0E, 0xEA, 0x90, 0x7C, 0x1D, 0x43, 0x7A ), + BYTES_TO_T_UINT_8( 0x9D, 0x81, 0x7E, 0x1D, 0xCE, 0xB1, 0x60, 0x0A ), + BYTES_TO_T_UINT_8( 0xC0, 0xB8, 0xF0, 0xB5, 0x13, 0x31, 0xDA, 0xE9 ), + BYTES_TO_T_UINT_8( 0x7C, 0x14, 0x9A, 0x28, 0xBD, 0x1D, 0xF4, 0xF8 ), + BYTES_TO_T_UINT_8( 0x29, 0xDC, 0x92, 0x92, 0xBF, 0x98, 0x9E, 0x5D ), + BYTES_TO_T_UINT_8( 0x6F, 0x2C, 0x26, 0x96, 0x4A, 0xDE, 0x17, 0x36 ), +}; +static const mbedtls_mpi_uint secp384r1_n[] = { + BYTES_TO_T_UINT_8( 0x73, 0x29, 0xC5, 0xCC, 0x6A, 0x19, 0xEC, 0xEC ), + BYTES_TO_T_UINT_8( 0x7A, 0xA7, 0xB0, 0x48, 0xB2, 0x0D, 0x1A, 0x58 ), + BYTES_TO_T_UINT_8( 0xDF, 0x2D, 0x37, 0xF4, 0x81, 0x4D, 0x63, 0xC7 ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ + +/* + * Domain parameters for secp521r1 + */ +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) +static const mbedtls_mpi_uint secp521r1_p[] = { + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_2( 0xFF, 0x01 ), +}; +static const mbedtls_mpi_uint secp521r1_b[] = { + BYTES_TO_T_UINT_8( 0x00, 0x3F, 0x50, 0x6B, 0xD4, 0x1F, 0x45, 0xEF ), + BYTES_TO_T_UINT_8( 0xF1, 0x34, 0x2C, 0x3D, 0x88, 0xDF, 0x73, 0x35 ), + BYTES_TO_T_UINT_8( 0x07, 0xBF, 0xB1, 0x3B, 0xBD, 0xC0, 0x52, 0x16 ), + BYTES_TO_T_UINT_8( 0x7B, 0x93, 0x7E, 0xEC, 0x51, 0x39, 0x19, 0x56 ), + BYTES_TO_T_UINT_8( 0xE1, 0x09, 0xF1, 0x8E, 0x91, 0x89, 0xB4, 0xB8 ), + BYTES_TO_T_UINT_8( 0xF3, 0x15, 0xB3, 0x99, 0x5B, 0x72, 0xDA, 0xA2 ), + BYTES_TO_T_UINT_8( 0xEE, 0x40, 0x85, 0xB6, 0xA0, 0x21, 0x9A, 0x92 ), + BYTES_TO_T_UINT_8( 0x1F, 0x9A, 0x1C, 0x8E, 0x61, 0xB9, 0x3E, 0x95 ), + BYTES_TO_T_UINT_2( 0x51, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_gx[] = { + BYTES_TO_T_UINT_8( 0x66, 0xBD, 0xE5, 0xC2, 0x31, 0x7E, 0x7E, 0xF9 ), + BYTES_TO_T_UINT_8( 0x9B, 0x42, 0x6A, 0x85, 0xC1, 0xB3, 0x48, 0x33 ), + BYTES_TO_T_UINT_8( 0xDE, 0xA8, 0xFF, 0xA2, 0x27, 0xC1, 0x1D, 0xFE ), + BYTES_TO_T_UINT_8( 0x28, 0x59, 0xE7, 0xEF, 0x77, 0x5E, 0x4B, 0xA1 ), + BYTES_TO_T_UINT_8( 0xBA, 0x3D, 0x4D, 0x6B, 0x60, 0xAF, 0x28, 0xF8 ), + BYTES_TO_T_UINT_8( 0x21, 0xB5, 0x3F, 0x05, 0x39, 0x81, 0x64, 0x9C ), + BYTES_TO_T_UINT_8( 0x42, 0xB4, 0x95, 0x23, 0x66, 0xCB, 0x3E, 0x9E ), + BYTES_TO_T_UINT_8( 0xCD, 0xE9, 0x04, 0x04, 0xB7, 0x06, 0x8E, 0x85 ), + BYTES_TO_T_UINT_2( 0xC6, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_gy[] = { + BYTES_TO_T_UINT_8( 0x50, 0x66, 0xD1, 0x9F, 0x76, 0x94, 0xBE, 0x88 ), + BYTES_TO_T_UINT_8( 0x40, 0xC2, 0x72, 0xA2, 0x86, 0x70, 0x3C, 0x35 ), + BYTES_TO_T_UINT_8( 0x61, 0x07, 0xAD, 0x3F, 0x01, 0xB9, 0x50, 0xC5 ), + BYTES_TO_T_UINT_8( 0x40, 0x26, 0xF4, 0x5E, 0x99, 0x72, 0xEE, 0x97 ), + BYTES_TO_T_UINT_8( 0x2C, 0x66, 0x3E, 0x27, 0x17, 0xBD, 0xAF, 0x17 ), + BYTES_TO_T_UINT_8( 0x68, 0x44, 0x9B, 0x57, 0x49, 0x44, 0xF5, 0x98 ), + BYTES_TO_T_UINT_8( 0xD9, 0x1B, 0x7D, 0x2C, 0xB4, 0x5F, 0x8A, 0x5C ), + BYTES_TO_T_UINT_8( 0x04, 0xC0, 0x3B, 0x9A, 0x78, 0x6A, 0x29, 0x39 ), + BYTES_TO_T_UINT_2( 0x18, 0x01 ), +}; +static const mbedtls_mpi_uint secp521r1_n[] = { + BYTES_TO_T_UINT_8( 0x09, 0x64, 0x38, 0x91, 0x1E, 0xB7, 0x6F, 0xBB ), + BYTES_TO_T_UINT_8( 0xAE, 0x47, 0x9C, 0x89, 0xB8, 0xC9, 0xB5, 0x3B ), + BYTES_TO_T_UINT_8( 0xD0, 0xA5, 0x09, 0xF7, 0x48, 0x01, 0xCC, 0x7F ), + BYTES_TO_T_UINT_8( 0x6B, 0x96, 0x2F, 0xBF, 0x83, 0x87, 0x86, 0x51 ), + BYTES_TO_T_UINT_8( 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_2( 0xFF, 0x01 ), +}; +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) +static const mbedtls_mpi_uint secp192k1_p[] = { + BYTES_TO_T_UINT_8( 0x37, 0xEE, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint secp192k1_a[] = { + BYTES_TO_T_UINT_2( 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp192k1_b[] = { + BYTES_TO_T_UINT_2( 0x03, 0x00 ), +}; +static const mbedtls_mpi_uint secp192k1_gx[] = { + BYTES_TO_T_UINT_8( 0x7D, 0x6C, 0xE0, 0xEA, 0xB1, 0xD1, 0xA5, 0x1D ), + BYTES_TO_T_UINT_8( 0x34, 0xF4, 0xB7, 0x80, 0x02, 0x7D, 0xB0, 0x26 ), + BYTES_TO_T_UINT_8( 0xAE, 0xE9, 0x57, 0xC0, 0x0E, 0xF1, 0x4F, 0xDB ), +}; +static const mbedtls_mpi_uint secp192k1_gy[] = { + BYTES_TO_T_UINT_8( 0x9D, 0x2F, 0x5E, 0xD9, 0x88, 0xAA, 0x82, 0x40 ), + BYTES_TO_T_UINT_8( 0x34, 0x86, 0xBE, 0x15, 0xD0, 0x63, 0x41, 0x84 ), + BYTES_TO_T_UINT_8( 0xA7, 0x28, 0x56, 0x9C, 0x6D, 0x2F, 0x2F, 0x9B ), +}; +static const mbedtls_mpi_uint secp192k1_n[] = { + BYTES_TO_T_UINT_8( 0x8D, 0xFD, 0xDE, 0x74, 0x6A, 0x46, 0x69, 0x0F ), + BYTES_TO_T_UINT_8( 0x17, 0xFC, 0xF2, 0x26, 0xFE, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) +static const mbedtls_mpi_uint secp224k1_p[] = { + BYTES_TO_T_UINT_8( 0x6D, 0xE5, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_4( 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint secp224k1_a[] = { + BYTES_TO_T_UINT_2( 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224k1_b[] = { + BYTES_TO_T_UINT_2( 0x05, 0x00 ), +}; +static const mbedtls_mpi_uint secp224k1_gx[] = { + BYTES_TO_T_UINT_8( 0x5C, 0xA4, 0xB7, 0xB6, 0x0E, 0x65, 0x7E, 0x0F ), + BYTES_TO_T_UINT_8( 0xA9, 0x75, 0x70, 0xE4, 0xE9, 0x67, 0xA4, 0x69 ), + BYTES_TO_T_UINT_8( 0xA1, 0x28, 0xFC, 0x30, 0xDF, 0x99, 0xF0, 0x4D ), + BYTES_TO_T_UINT_4( 0x33, 0x5B, 0x45, 0xA1 ), +}; +static const mbedtls_mpi_uint secp224k1_gy[] = { + BYTES_TO_T_UINT_8( 0xA5, 0x61, 0x6D, 0x55, 0xDB, 0x4B, 0xCA, 0xE2 ), + BYTES_TO_T_UINT_8( 0x59, 0xBD, 0xB0, 0xC0, 0xF7, 0x19, 0xE3, 0xF7 ), + BYTES_TO_T_UINT_8( 0xD6, 0xFB, 0xCA, 0x82, 0x42, 0x34, 0xBA, 0x7F ), + BYTES_TO_T_UINT_4( 0xED, 0x9F, 0x08, 0x7E ), +}; +static const mbedtls_mpi_uint secp224k1_n[] = { + BYTES_TO_T_UINT_8( 0xF7, 0xB1, 0x9F, 0x76, 0x71, 0xA9, 0xF0, 0xCA ), + BYTES_TO_T_UINT_8( 0x84, 0x61, 0xEC, 0xD2, 0xE8, 0xDC, 0x01, 0x00 ), + BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), + BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ), +}; +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +static const mbedtls_mpi_uint secp256k1_p[] = { + BYTES_TO_T_UINT_8( 0x2F, 0xFC, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint secp256k1_a[] = { + BYTES_TO_T_UINT_2( 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp256k1_b[] = { + BYTES_TO_T_UINT_2( 0x07, 0x00 ), +}; +static const mbedtls_mpi_uint secp256k1_gx[] = { + BYTES_TO_T_UINT_8( 0x98, 0x17, 0xF8, 0x16, 0x5B, 0x81, 0xF2, 0x59 ), + BYTES_TO_T_UINT_8( 0xD9, 0x28, 0xCE, 0x2D, 0xDB, 0xFC, 0x9B, 0x02 ), + BYTES_TO_T_UINT_8( 0x07, 0x0B, 0x87, 0xCE, 0x95, 0x62, 0xA0, 0x55 ), + BYTES_TO_T_UINT_8( 0xAC, 0xBB, 0xDC, 0xF9, 0x7E, 0x66, 0xBE, 0x79 ), +}; +static const mbedtls_mpi_uint secp256k1_gy[] = { + BYTES_TO_T_UINT_8( 0xB8, 0xD4, 0x10, 0xFB, 0x8F, 0xD0, 0x47, 0x9C ), + BYTES_TO_T_UINT_8( 0x19, 0x54, 0x85, 0xA6, 0x48, 0xB4, 0x17, 0xFD ), + BYTES_TO_T_UINT_8( 0xA8, 0x08, 0x11, 0x0E, 0xFC, 0xFB, 0xA4, 0x5D ), + BYTES_TO_T_UINT_8( 0x65, 0xC4, 0xA3, 0x26, 0x77, 0xDA, 0x3A, 0x48 ), +}; +static const mbedtls_mpi_uint secp256k1_n[] = { + BYTES_TO_T_UINT_8( 0x41, 0x41, 0x36, 0xD0, 0x8C, 0x5E, 0xD2, 0xBF ), + BYTES_TO_T_UINT_8( 0x3B, 0xA0, 0x48, 0xAF, 0xE6, 0xDC, 0xAE, 0xBA ), + BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ + +/* + * Domain parameters for brainpoolP256r1 (RFC 5639 3.4) + */ +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) +static const mbedtls_mpi_uint brainpoolP256r1_p[] = { + BYTES_TO_T_UINT_8( 0x77, 0x53, 0x6E, 0x1F, 0x1D, 0x48, 0x13, 0x20 ), + BYTES_TO_T_UINT_8( 0x28, 0x20, 0x26, 0xD5, 0x23, 0xF6, 0x3B, 0x6E ), + BYTES_TO_T_UINT_8( 0x72, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E ), + BYTES_TO_T_UINT_8( 0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9 ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_a[] = { + BYTES_TO_T_UINT_8( 0xD9, 0xB5, 0x30, 0xF3, 0x44, 0x4B, 0x4A, 0xE9 ), + BYTES_TO_T_UINT_8( 0x6C, 0x5C, 0xDC, 0x26, 0xC1, 0x55, 0x80, 0xFB ), + BYTES_TO_T_UINT_8( 0xE7, 0xFF, 0x7A, 0x41, 0x30, 0x75, 0xF6, 0xEE ), + BYTES_TO_T_UINT_8( 0x57, 0x30, 0x2C, 0xFC, 0x75, 0x09, 0x5A, 0x7D ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_b[] = { + BYTES_TO_T_UINT_8( 0xB6, 0x07, 0x8C, 0xFF, 0x18, 0xDC, 0xCC, 0x6B ), + BYTES_TO_T_UINT_8( 0xCE, 0xE1, 0xF7, 0x5C, 0x29, 0x16, 0x84, 0x95 ), + BYTES_TO_T_UINT_8( 0xBF, 0x7C, 0xD7, 0xBB, 0xD9, 0xB5, 0x30, 0xF3 ), + BYTES_TO_T_UINT_8( 0x44, 0x4B, 0x4A, 0xE9, 0x6C, 0x5C, 0xDC, 0x26 ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_gx[] = { + BYTES_TO_T_UINT_8( 0x62, 0x32, 0xCE, 0x9A, 0xBD, 0x53, 0x44, 0x3A ), + BYTES_TO_T_UINT_8( 0xC2, 0x23, 0xBD, 0xE3, 0xE1, 0x27, 0xDE, 0xB9 ), + BYTES_TO_T_UINT_8( 0xAF, 0xB7, 0x81, 0xFC, 0x2F, 0x48, 0x4B, 0x2C ), + BYTES_TO_T_UINT_8( 0xCB, 0x57, 0x7E, 0xCB, 0xB9, 0xAE, 0xD2, 0x8B ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_gy[] = { + BYTES_TO_T_UINT_8( 0x97, 0x69, 0x04, 0x2F, 0xC7, 0x54, 0x1D, 0x5C ), + BYTES_TO_T_UINT_8( 0x54, 0x8E, 0xED, 0x2D, 0x13, 0x45, 0x77, 0xC2 ), + BYTES_TO_T_UINT_8( 0xC9, 0x1D, 0x61, 0x14, 0x1A, 0x46, 0xF8, 0x97 ), + BYTES_TO_T_UINT_8( 0xFD, 0xC4, 0xDA, 0xC3, 0x35, 0xF8, 0x7E, 0x54 ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_n[] = { + BYTES_TO_T_UINT_8( 0xA7, 0x56, 0x48, 0x97, 0x82, 0x0E, 0x1E, 0x90 ), + BYTES_TO_T_UINT_8( 0xF7, 0xA6, 0x61, 0xB5, 0xA3, 0x7A, 0x39, 0x8C ), + BYTES_TO_T_UINT_8( 0x71, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E ), + BYTES_TO_T_UINT_8( 0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9 ), +}; +#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ + +/* + * Domain parameters for brainpoolP384r1 (RFC 5639 3.6) + */ +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) +static const mbedtls_mpi_uint brainpoolP384r1_p[] = { + BYTES_TO_T_UINT_8( 0x53, 0xEC, 0x07, 0x31, 0x13, 0x00, 0x47, 0x87 ), + BYTES_TO_T_UINT_8( 0x71, 0x1A, 0x1D, 0x90, 0x29, 0xA7, 0xD3, 0xAC ), + BYTES_TO_T_UINT_8( 0x23, 0x11, 0xB7, 0x7F, 0x19, 0xDA, 0xB1, 0x12 ), + BYTES_TO_T_UINT_8( 0xB4, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15 ), + BYTES_TO_T_UINT_8( 0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F ), + BYTES_TO_T_UINT_8( 0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_a[] = { + BYTES_TO_T_UINT_8( 0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04 ), + BYTES_TO_T_UINT_8( 0xEB, 0xD4, 0x3A, 0x50, 0x4A, 0x81, 0xA5, 0x8A ), + BYTES_TO_T_UINT_8( 0x0F, 0xF9, 0x91, 0xBA, 0xEF, 0x65, 0x91, 0x13 ), + BYTES_TO_T_UINT_8( 0x87, 0x27, 0xB2, 0x4F, 0x8E, 0xA2, 0xBE, 0xC2 ), + BYTES_TO_T_UINT_8( 0xA0, 0xAF, 0x05, 0xCE, 0x0A, 0x08, 0x72, 0x3C ), + BYTES_TO_T_UINT_8( 0x0C, 0x15, 0x8C, 0x3D, 0xC6, 0x82, 0xC3, 0x7B ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_b[] = { + BYTES_TO_T_UINT_8( 0x11, 0x4C, 0x50, 0xFA, 0x96, 0x86, 0xB7, 0x3A ), + BYTES_TO_T_UINT_8( 0x94, 0xC9, 0xDB, 0x95, 0x02, 0x39, 0xB4, 0x7C ), + BYTES_TO_T_UINT_8( 0xD5, 0x62, 0xEB, 0x3E, 0xA5, 0x0E, 0x88, 0x2E ), + BYTES_TO_T_UINT_8( 0xA6, 0xD2, 0xDC, 0x07, 0xE1, 0x7D, 0xB7, 0x2F ), + BYTES_TO_T_UINT_8( 0x7C, 0x44, 0xF0, 0x16, 0x54, 0xB5, 0x39, 0x8B ), + BYTES_TO_T_UINT_8( 0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_gx[] = { + BYTES_TO_T_UINT_8( 0x1E, 0xAF, 0xD4, 0x47, 0xE2, 0xB2, 0x87, 0xEF ), + BYTES_TO_T_UINT_8( 0xAA, 0x46, 0xD6, 0x36, 0x34, 0xE0, 0x26, 0xE8 ), + BYTES_TO_T_UINT_8( 0xE8, 0x10, 0xBD, 0x0C, 0xFE, 0xCA, 0x7F, 0xDB ), + BYTES_TO_T_UINT_8( 0xE3, 0x4F, 0xF1, 0x7E, 0xE7, 0xA3, 0x47, 0x88 ), + BYTES_TO_T_UINT_8( 0x6B, 0x3F, 0xC1, 0xB7, 0x81, 0x3A, 0xA6, 0xA2 ), + BYTES_TO_T_UINT_8( 0xFF, 0x45, 0xCF, 0x68, 0xF0, 0x64, 0x1C, 0x1D ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_gy[] = { + BYTES_TO_T_UINT_8( 0x15, 0x53, 0x3C, 0x26, 0x41, 0x03, 0x82, 0x42 ), + BYTES_TO_T_UINT_8( 0x11, 0x81, 0x91, 0x77, 0x21, 0x46, 0x46, 0x0E ), + BYTES_TO_T_UINT_8( 0x28, 0x29, 0x91, 0xF9, 0x4F, 0x05, 0x9C, 0xE1 ), + BYTES_TO_T_UINT_8( 0x64, 0x58, 0xEC, 0xFE, 0x29, 0x0B, 0xB7, 0x62 ), + BYTES_TO_T_UINT_8( 0x52, 0xD5, 0xCF, 0x95, 0x8E, 0xEB, 0xB1, 0x5C ), + BYTES_TO_T_UINT_8( 0xA4, 0xC2, 0xF9, 0x20, 0x75, 0x1D, 0xBE, 0x8A ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_n[] = { + BYTES_TO_T_UINT_8( 0x65, 0x65, 0x04, 0xE9, 0x02, 0x32, 0x88, 0x3B ), + BYTES_TO_T_UINT_8( 0x10, 0xC3, 0x7F, 0x6B, 0xAF, 0xB6, 0x3A, 0xCF ), + BYTES_TO_T_UINT_8( 0xA7, 0x25, 0x04, 0xAC, 0x6C, 0x6E, 0x16, 0x1F ), + BYTES_TO_T_UINT_8( 0xB3, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15 ), + BYTES_TO_T_UINT_8( 0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F ), + BYTES_TO_T_UINT_8( 0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C ), +}; +#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ + +/* + * Domain parameters for brainpoolP512r1 (RFC 5639 3.7) + */ +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) +static const mbedtls_mpi_uint brainpoolP512r1_p[] = { + BYTES_TO_T_UINT_8( 0xF3, 0x48, 0x3A, 0x58, 0x56, 0x60, 0xAA, 0x28 ), + BYTES_TO_T_UINT_8( 0x85, 0xC6, 0x82, 0x2D, 0x2F, 0xFF, 0x81, 0x28 ), + BYTES_TO_T_UINT_8( 0xE6, 0x80, 0xA3, 0xE6, 0x2A, 0xA1, 0xCD, 0xAE ), + BYTES_TO_T_UINT_8( 0x42, 0x68, 0xC6, 0x9B, 0x00, 0x9B, 0x4D, 0x7D ), + BYTES_TO_T_UINT_8( 0x71, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6 ), + BYTES_TO_T_UINT_8( 0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB ), + BYTES_TO_T_UINT_8( 0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F ), + BYTES_TO_T_UINT_8( 0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_a[] = { + BYTES_TO_T_UINT_8( 0xCA, 0x94, 0xFC, 0x77, 0x4D, 0xAC, 0xC1, 0xE7 ), + BYTES_TO_T_UINT_8( 0xB9, 0xC7, 0xF2, 0x2B, 0xA7, 0x17, 0x11, 0x7F ), + BYTES_TO_T_UINT_8( 0xB5, 0xC8, 0x9A, 0x8B, 0xC9, 0xF1, 0x2E, 0x0A ), + BYTES_TO_T_UINT_8( 0xA1, 0x3A, 0x25, 0xA8, 0x5A, 0x5D, 0xED, 0x2D ), + BYTES_TO_T_UINT_8( 0xBC, 0x63, 0x98, 0xEA, 0xCA, 0x41, 0x34, 0xA8 ), + BYTES_TO_T_UINT_8( 0x10, 0x16, 0xF9, 0x3D, 0x8D, 0xDD, 0xCB, 0x94 ), + BYTES_TO_T_UINT_8( 0xC5, 0x4C, 0x23, 0xAC, 0x45, 0x71, 0x32, 0xE2 ), + BYTES_TO_T_UINT_8( 0x89, 0x3B, 0x60, 0x8B, 0x31, 0xA3, 0x30, 0x78 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_b[] = { + BYTES_TO_T_UINT_8( 0x23, 0xF7, 0x16, 0x80, 0x63, 0xBD, 0x09, 0x28 ), + BYTES_TO_T_UINT_8( 0xDD, 0xE5, 0xBA, 0x5E, 0xB7, 0x50, 0x40, 0x98 ), + BYTES_TO_T_UINT_8( 0x67, 0x3E, 0x08, 0xDC, 0xCA, 0x94, 0xFC, 0x77 ), + BYTES_TO_T_UINT_8( 0x4D, 0xAC, 0xC1, 0xE7, 0xB9, 0xC7, 0xF2, 0x2B ), + BYTES_TO_T_UINT_8( 0xA7, 0x17, 0x11, 0x7F, 0xB5, 0xC8, 0x9A, 0x8B ), + BYTES_TO_T_UINT_8( 0xC9, 0xF1, 0x2E, 0x0A, 0xA1, 0x3A, 0x25, 0xA8 ), + BYTES_TO_T_UINT_8( 0x5A, 0x5D, 0xED, 0x2D, 0xBC, 0x63, 0x98, 0xEA ), + BYTES_TO_T_UINT_8( 0xCA, 0x41, 0x34, 0xA8, 0x10, 0x16, 0xF9, 0x3D ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_gx[] = { + BYTES_TO_T_UINT_8( 0x22, 0xF8, 0xB9, 0xBC, 0x09, 0x22, 0x35, 0x8B ), + BYTES_TO_T_UINT_8( 0x68, 0x5E, 0x6A, 0x40, 0x47, 0x50, 0x6D, 0x7C ), + BYTES_TO_T_UINT_8( 0x5F, 0x7D, 0xB9, 0x93, 0x7B, 0x68, 0xD1, 0x50 ), + BYTES_TO_T_UINT_8( 0x8D, 0xD4, 0xD0, 0xE2, 0x78, 0x1F, 0x3B, 0xFF ), + BYTES_TO_T_UINT_8( 0x8E, 0x09, 0xD0, 0xF4, 0xEE, 0x62, 0x3B, 0xB4 ), + BYTES_TO_T_UINT_8( 0xC1, 0x16, 0xD9, 0xB5, 0x70, 0x9F, 0xED, 0x85 ), + BYTES_TO_T_UINT_8( 0x93, 0x6A, 0x4C, 0x9C, 0x2E, 0x32, 0x21, 0x5A ), + BYTES_TO_T_UINT_8( 0x64, 0xD9, 0x2E, 0xD8, 0xBD, 0xE4, 0xAE, 0x81 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_gy[] = { + BYTES_TO_T_UINT_8( 0x92, 0x08, 0xD8, 0x3A, 0x0F, 0x1E, 0xCD, 0x78 ), + BYTES_TO_T_UINT_8( 0x06, 0x54, 0xF0, 0xA8, 0x2F, 0x2B, 0xCA, 0xD1 ), + BYTES_TO_T_UINT_8( 0xAE, 0x63, 0x27, 0x8A, 0xD8, 0x4B, 0xCA, 0x5B ), + BYTES_TO_T_UINT_8( 0x5E, 0x48, 0x5F, 0x4A, 0x49, 0xDE, 0xDC, 0xB2 ), + BYTES_TO_T_UINT_8( 0x11, 0x81, 0x1F, 0x88, 0x5B, 0xC5, 0x00, 0xA0 ), + BYTES_TO_T_UINT_8( 0x1A, 0x7B, 0xA5, 0x24, 0x00, 0xF7, 0x09, 0xF2 ), + BYTES_TO_T_UINT_8( 0xFD, 0x22, 0x78, 0xCF, 0xA9, 0xBF, 0xEA, 0xC0 ), + BYTES_TO_T_UINT_8( 0xEC, 0x32, 0x63, 0x56, 0x5D, 0x38, 0xDE, 0x7D ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_n[] = { + BYTES_TO_T_UINT_8( 0x69, 0x00, 0xA9, 0x9C, 0x82, 0x96, 0x87, 0xB5 ), + BYTES_TO_T_UINT_8( 0xDD, 0xDA, 0x5D, 0x08, 0x81, 0xD3, 0xB1, 0x1D ), + BYTES_TO_T_UINT_8( 0x47, 0x10, 0xAC, 0x7F, 0x19, 0x61, 0x86, 0x41 ), + BYTES_TO_T_UINT_8( 0x19, 0x26, 0xA9, 0x4C, 0x41, 0x5C, 0x3E, 0x55 ), + BYTES_TO_T_UINT_8( 0x70, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6 ), + BYTES_TO_T_UINT_8( 0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB ), + BYTES_TO_T_UINT_8( 0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F ), + BYTES_TO_T_UINT_8( 0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA ), +}; +#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +/* For these curves, we build the group parameters dynamically. */ +#define ECP_LOAD_GROUP +#endif + +#if defined(ECP_LOAD_GROUP) +/* + * Create an MPI from embedded constants + * (assumes len is an exact multiple of sizeof mbedtls_mpi_uint) + */ +static inline void ecp_mpi_load( mbedtls_mpi *X, const mbedtls_mpi_uint *p, size_t len ) +{ + X->s = 1; + X->n = len / sizeof( mbedtls_mpi_uint ); + X->p = (mbedtls_mpi_uint *) p; +} + +/* + * Set an MPI to static value 1 + */ +static inline void ecp_mpi_set1( mbedtls_mpi *X ) +{ + static mbedtls_mpi_uint one[] = { 1 }; + X->s = 1; + X->n = 1; + X->p = one; +} + +/* + * Make group available from embedded constants + */ +static int ecp_group_load( mbedtls_ecp_group *grp, + const mbedtls_mpi_uint *p, size_t plen, + const mbedtls_mpi_uint *a, size_t alen, + const mbedtls_mpi_uint *b, size_t blen, + const mbedtls_mpi_uint *gx, size_t gxlen, + const mbedtls_mpi_uint *gy, size_t gylen, + const mbedtls_mpi_uint *n, size_t nlen) +{ + ecp_mpi_load( &grp->P, p, plen ); + if( a != NULL ) + ecp_mpi_load( &grp->A, a, alen ); + ecp_mpi_load( &grp->B, b, blen ); + ecp_mpi_load( &grp->N, n, nlen ); + + ecp_mpi_load( &grp->G.X, gx, gxlen ); + ecp_mpi_load( &grp->G.Y, gy, gylen ); + ecp_mpi_set1( &grp->G.Z ); + + grp->pbits = mbedtls_mpi_bitlen( &grp->P ); + grp->nbits = mbedtls_mpi_bitlen( &grp->N ); + + grp->h = 1; + + return( 0 ); +} +#endif /* ECP_LOAD_GROUP */ + +#if defined(MBEDTLS_ECP_NIST_OPTIM) +/* Forward declarations */ +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) +static int ecp_mod_p192( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) +static int ecp_mod_p224( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) +static int ecp_mod_p256( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +static int ecp_mod_p384( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) +static int ecp_mod_p521( mbedtls_mpi * ); +#endif + +#define NIST_MODP( P ) grp->modp = ecp_mod_ ## P; +#else +#define NIST_MODP( P ) +#endif /* MBEDTLS_ECP_NIST_OPTIM */ + +/* Additional forward declarations */ +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) +static int ecp_mod_p255( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) +static int ecp_mod_p448( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) +static int ecp_mod_p192k1( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) +static int ecp_mod_p224k1( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +static int ecp_mod_p256k1( mbedtls_mpi * ); +#endif + +#if defined(ECP_LOAD_GROUP) +#define LOAD_GROUP_A( G ) ecp_group_load( grp, \ + G ## _p, sizeof( G ## _p ), \ + G ## _a, sizeof( G ## _a ), \ + G ## _b, sizeof( G ## _b ), \ + G ## _gx, sizeof( G ## _gx ), \ + G ## _gy, sizeof( G ## _gy ), \ + G ## _n, sizeof( G ## _n ) ) + +#define LOAD_GROUP( G ) ecp_group_load( grp, \ + G ## _p, sizeof( G ## _p ), \ + NULL, 0, \ + G ## _b, sizeof( G ## _b ), \ + G ## _gx, sizeof( G ## _gx ), \ + G ## _gy, sizeof( G ## _gy ), \ + G ## _n, sizeof( G ## _n ) ) +#endif /* ECP_LOAD_GROUP */ + +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) +/* + * Specialized function for creating the Curve25519 group + */ +static int ecp_use_curve25519( mbedtls_ecp_group *grp ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* Actually ( A + 2 ) / 4 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &grp->A, 16, "01DB42" ) ); + + /* P = 2^255 - 19 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &grp->P, 255 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &grp->P, &grp->P, 19 ) ); + grp->pbits = mbedtls_mpi_bitlen( &grp->P ); + + /* N = 2^252 + 27742317777372353535851937790883648493 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &grp->N, 16, + "14DEF9DEA2F79CD65812631A5CF5D3ED" ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( &grp->N, 252, 1 ) ); + + /* Y intentionally not set, since we use x/z coordinates. + * This is used as a marker to identify Montgomery curves! */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->G.X, 9 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->G.Z, 1 ) ); + mbedtls_mpi_free( &grp->G.Y ); + + /* Actually, the required msb for private keys */ + grp->nbits = 254; + +cleanup: + if( ret != 0 ) + mbedtls_ecp_group_free( grp ); + + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) +/* + * Specialized function for creating the Curve448 group + */ +static int ecp_use_curve448( mbedtls_ecp_group *grp ) +{ + mbedtls_mpi Ns; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + mbedtls_mpi_init( &Ns ); + + /* Actually ( A + 2 ) / 4 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &grp->A, 16, "98AA" ) ); + + /* P = 2^448 - 2^224 - 1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &grp->P, 224 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &grp->P, &grp->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &grp->P, 224 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &grp->P, &grp->P, 1 ) ); + grp->pbits = mbedtls_mpi_bitlen( &grp->P ); + + /* Y intentionally not set, since we use x/z coordinates. + * This is used as a marker to identify Montgomery curves! */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->G.X, 5 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->G.Z, 1 ) ); + mbedtls_mpi_free( &grp->G.Y ); + + /* N = 2^446 - 13818066809895115352007386748515426880336692474882178609894547503885 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( &grp->N, 446, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &Ns, 16, + "8335DC163BB124B65129C96FDE933D8D723A70AADC873D6D54A7BB0D" ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &grp->N, &grp->N, &Ns ) ); + + /* Actually, the required msb for private keys */ + grp->nbits = 447; + +cleanup: + mbedtls_mpi_free( &Ns ); + if( ret != 0 ) + mbedtls_ecp_group_free( grp ); + + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ + +/* + * Set a group using well-known domain parameters + */ +int mbedtls_ecp_group_load( mbedtls_ecp_group *grp, mbedtls_ecp_group_id id ) +{ + ECP_VALIDATE_RET( grp != NULL ); + mbedtls_ecp_group_free( grp ); + + grp->id = id; + + switch( id ) + { +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + case MBEDTLS_ECP_DP_SECP192R1: + NIST_MODP( p192 ); + return( LOAD_GROUP( secp192r1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) + case MBEDTLS_ECP_DP_SECP224R1: + NIST_MODP( p224 ); + return( LOAD_GROUP( secp224r1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + case MBEDTLS_ECP_DP_SECP256R1: + NIST_MODP( p256 ); + return( LOAD_GROUP( secp256r1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + case MBEDTLS_ECP_DP_SECP384R1: + NIST_MODP( p384 ); + return( LOAD_GROUP( secp384r1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) + case MBEDTLS_ECP_DP_SECP521R1: + NIST_MODP( p521 ); + return( LOAD_GROUP( secp521r1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) + case MBEDTLS_ECP_DP_SECP192K1: + grp->modp = ecp_mod_p192k1; + return( LOAD_GROUP_A( secp192k1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) + case MBEDTLS_ECP_DP_SECP224K1: + grp->modp = ecp_mod_p224k1; + return( LOAD_GROUP_A( secp224k1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) + case MBEDTLS_ECP_DP_SECP256K1: + grp->modp = ecp_mod_p256k1; + return( LOAD_GROUP_A( secp256k1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) + case MBEDTLS_ECP_DP_BP256R1: + return( LOAD_GROUP_A( brainpoolP256r1 ) ); +#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) + case MBEDTLS_ECP_DP_BP384R1: + return( LOAD_GROUP_A( brainpoolP384r1 ) ); +#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) + case MBEDTLS_ECP_DP_BP512R1: + return( LOAD_GROUP_A( brainpoolP512r1 ) ); +#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) + case MBEDTLS_ECP_DP_CURVE25519: + grp->modp = ecp_mod_p255; + return( ecp_use_curve25519( grp ) ); +#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) + case MBEDTLS_ECP_DP_CURVE448: + grp->modp = ecp_mod_p448; + return( ecp_use_curve448( grp ) ); +#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ + + default: + grp->id = MBEDTLS_ECP_DP_NONE; + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); + } +} + +#if defined(MBEDTLS_ECP_NIST_OPTIM) +/* + * Fast reduction modulo the primes used by the NIST curves. + * + * These functions are critical for speed, but not needed for correct + * operations. So, we make the choice to heavily rely on the internals of our + * bignum library, which creates a tight coupling between these functions and + * our MPI implementation. However, the coupling between the ECP module and + * MPI remains loose, since these functions can be deactivated at will. + */ + +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) +/* + * Compared to the way things are presented in FIPS 186-3 D.2, + * we proceed in columns, from right (least significant chunk) to left, + * adding chunks to N in place, and keeping a carry for the next chunk. + * This avoids moving things around in memory, and uselessly adding zeros, + * compared to the more straightforward, line-oriented approach. + * + * For this prime we need to handle data in chunks of 64 bits. + * Since this is always a multiple of our basic mbedtls_mpi_uint, we can + * use a mbedtls_mpi_uint * to designate such a chunk, and small loops to handle it. + */ + +/* Add 64-bit chunks (dst += src) and update carry */ +static inline void add64( mbedtls_mpi_uint *dst, mbedtls_mpi_uint *src, mbedtls_mpi_uint *carry ) +{ + unsigned char i; + mbedtls_mpi_uint c = 0; + for( i = 0; i < 8 / sizeof( mbedtls_mpi_uint ); i++, dst++, src++ ) + { + *dst += c; c = ( *dst < c ); + *dst += *src; c += ( *dst < *src ); + } + *carry += c; +} + +/* Add carry to a 64-bit chunk and update carry */ +static inline void carry64( mbedtls_mpi_uint *dst, mbedtls_mpi_uint *carry ) +{ + unsigned char i; + for( i = 0; i < 8 / sizeof( mbedtls_mpi_uint ); i++, dst++ ) + { + *dst += *carry; + *carry = ( *dst < *carry ); + } +} + +#define WIDTH 8 / sizeof( mbedtls_mpi_uint ) +#define A( i ) N->p + (i) * WIDTH +#define ADD( i ) add64( p, A( i ), &c ) +#define NEXT p += WIDTH; carry64( p, &c ) +#define LAST p += WIDTH; *p = c; while( ++p < end ) *p = 0 + +/* + * Fast quasi-reduction modulo p192 (FIPS 186-3 D.2.1) + */ +static int ecp_mod_p192( mbedtls_mpi *N ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi_uint c = 0; + mbedtls_mpi_uint *p, *end; + + /* Make sure we have enough blocks so that A(5) is legal */ + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( N, 6 * WIDTH ) ); + + p = N->p; + end = p + N->n; + + ADD( 3 ); ADD( 5 ); NEXT; // A0 += A3 + A5 + ADD( 3 ); ADD( 4 ); ADD( 5 ); NEXT; // A1 += A3 + A4 + A5 + ADD( 4 ); ADD( 5 ); LAST; // A2 += A4 + A5 + +cleanup: + return( ret ); +} + +#undef WIDTH +#undef A +#undef ADD +#undef NEXT +#undef LAST +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +/* + * The reader is advised to first understand ecp_mod_p192() since the same + * general structure is used here, but with additional complications: + * (1) chunks of 32 bits, and (2) subtractions. + */ + +/* + * For these primes, we need to handle data in chunks of 32 bits. + * This makes it more complicated if we use 64 bits limbs in MPI, + * which prevents us from using a uniform access method as for p192. + * + * So, we define a mini abstraction layer to access 32 bit chunks, + * load them in 'cur' for work, and store them back from 'cur' when done. + * + * While at it, also define the size of N in terms of 32-bit chunks. + */ +#define LOAD32 cur = A( i ); + +#if defined(MBEDTLS_HAVE_INT32) /* 32 bit */ + +#define MAX32 N->n +#define A( j ) N->p[j] +#define STORE32 N->p[i] = cur; + +#else /* 64-bit */ + +#define MAX32 N->n * 2 +#define A( j ) (j) % 2 ? (uint32_t)( N->p[(j)/2] >> 32 ) : \ + (uint32_t)( N->p[(j)/2] ) +#define STORE32 \ + if( i % 2 ) { \ + N->p[i/2] &= 0x00000000FFFFFFFF; \ + N->p[i/2] |= ((mbedtls_mpi_uint) cur) << 32; \ + } else { \ + N->p[i/2] &= 0xFFFFFFFF00000000; \ + N->p[i/2] |= (mbedtls_mpi_uint) cur; \ + } + +#endif /* sizeof( mbedtls_mpi_uint ) */ + +/* + * Helpers for addition and subtraction of chunks, with signed carry. + */ +static inline void add32( uint32_t *dst, uint32_t src, signed char *carry ) +{ + *dst += src; + *carry += ( *dst < src ); +} + +static inline void sub32( uint32_t *dst, uint32_t src, signed char *carry ) +{ + *carry -= ( *dst < src ); + *dst -= src; +} + +#define ADD( j ) add32( &cur, A( j ), &c ); +#define SUB( j ) sub32( &cur, A( j ), &c ); + +/* + * Helpers for the main 'loop' + * (see fix_negative for the motivation of C) + */ +#define INIT( b ) \ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; \ + signed char c = 0, cc; \ + uint32_t cur; \ + size_t i = 0, bits = (b); \ + mbedtls_mpi C; \ + mbedtls_mpi_uint Cp[ (b) / 8 / sizeof( mbedtls_mpi_uint) + 1 ]; \ + \ + C.s = 1; \ + C.n = (b) / 8 / sizeof( mbedtls_mpi_uint) + 1; \ + C.p = Cp; \ + memset( Cp, 0, C.n * sizeof( mbedtls_mpi_uint ) ); \ + \ + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( N, (b) * 2 / 8 / \ + sizeof( mbedtls_mpi_uint ) ) ); \ + LOAD32; + +#define NEXT \ + STORE32; i++; LOAD32; \ + cc = c; c = 0; \ + if( cc < 0 ) \ + sub32( &cur, -cc, &c ); \ + else \ + add32( &cur, cc, &c ); \ + +#define LAST \ + STORE32; i++; \ + cur = c > 0 ? c : 0; STORE32; \ + cur = 0; while( ++i < MAX32 ) { STORE32; } \ + if( c < 0 ) fix_negative( N, c, &C, bits ); + +/* + * If the result is negative, we get it in the form + * c * 2^(bits + 32) + N, with c negative and N positive shorter than 'bits' + */ +static inline int fix_negative( mbedtls_mpi *N, signed char c, mbedtls_mpi *C, size_t bits ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* C = - c * 2^(bits + 32) */ +#if !defined(MBEDTLS_HAVE_INT64) + ((void) bits); +#else + if( bits == 224 ) + C->p[ C->n - 1 ] = ((mbedtls_mpi_uint) -c) << 32; + else +#endif + C->p[ C->n - 1 ] = (mbedtls_mpi_uint) -c; + + /* N = - ( C - N ) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( N, C, N ) ); + N->s = -1; + +cleanup: + + return( ret ); +} + +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) +/* + * Fast quasi-reduction modulo p224 (FIPS 186-3 D.2.2) + */ +static int ecp_mod_p224( mbedtls_mpi *N ) +{ + INIT( 224 ); + + SUB( 7 ); SUB( 11 ); NEXT; // A0 += -A7 - A11 + SUB( 8 ); SUB( 12 ); NEXT; // A1 += -A8 - A12 + SUB( 9 ); SUB( 13 ); NEXT; // A2 += -A9 - A13 + SUB( 10 ); ADD( 7 ); ADD( 11 ); NEXT; // A3 += -A10 + A7 + A11 + SUB( 11 ); ADD( 8 ); ADD( 12 ); NEXT; // A4 += -A11 + A8 + A12 + SUB( 12 ); ADD( 9 ); ADD( 13 ); NEXT; // A5 += -A12 + A9 + A13 + SUB( 13 ); ADD( 10 ); LAST; // A6 += -A13 + A10 + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) +/* + * Fast quasi-reduction modulo p256 (FIPS 186-3 D.2.3) + */ +static int ecp_mod_p256( mbedtls_mpi *N ) +{ + INIT( 256 ); + + ADD( 8 ); ADD( 9 ); + SUB( 11 ); SUB( 12 ); SUB( 13 ); SUB( 14 ); NEXT; // A0 + + ADD( 9 ); ADD( 10 ); + SUB( 12 ); SUB( 13 ); SUB( 14 ); SUB( 15 ); NEXT; // A1 + + ADD( 10 ); ADD( 11 ); + SUB( 13 ); SUB( 14 ); SUB( 15 ); NEXT; // A2 + + ADD( 11 ); ADD( 11 ); ADD( 12 ); ADD( 12 ); ADD( 13 ); + SUB( 15 ); SUB( 8 ); SUB( 9 ); NEXT; // A3 + + ADD( 12 ); ADD( 12 ); ADD( 13 ); ADD( 13 ); ADD( 14 ); + SUB( 9 ); SUB( 10 ); NEXT; // A4 + + ADD( 13 ); ADD( 13 ); ADD( 14 ); ADD( 14 ); ADD( 15 ); + SUB( 10 ); SUB( 11 ); NEXT; // A5 + + ADD( 14 ); ADD( 14 ); ADD( 15 ); ADD( 15 ); ADD( 14 ); ADD( 13 ); + SUB( 8 ); SUB( 9 ); NEXT; // A6 + + ADD( 15 ); ADD( 15 ); ADD( 15 ); ADD( 8 ); + SUB( 10 ); SUB( 11 ); SUB( 12 ); SUB( 13 ); LAST; // A7 + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +/* + * Fast quasi-reduction modulo p384 (FIPS 186-3 D.2.4) + */ +static int ecp_mod_p384( mbedtls_mpi *N ) +{ + INIT( 384 ); + + ADD( 12 ); ADD( 21 ); ADD( 20 ); + SUB( 23 ); NEXT; // A0 + + ADD( 13 ); ADD( 22 ); ADD( 23 ); + SUB( 12 ); SUB( 20 ); NEXT; // A2 + + ADD( 14 ); ADD( 23 ); + SUB( 13 ); SUB( 21 ); NEXT; // A2 + + ADD( 15 ); ADD( 12 ); ADD( 20 ); ADD( 21 ); + SUB( 14 ); SUB( 22 ); SUB( 23 ); NEXT; // A3 + + ADD( 21 ); ADD( 21 ); ADD( 16 ); ADD( 13 ); ADD( 12 ); ADD( 20 ); ADD( 22 ); + SUB( 15 ); SUB( 23 ); SUB( 23 ); NEXT; // A4 + + ADD( 22 ); ADD( 22 ); ADD( 17 ); ADD( 14 ); ADD( 13 ); ADD( 21 ); ADD( 23 ); + SUB( 16 ); NEXT; // A5 + + ADD( 23 ); ADD( 23 ); ADD( 18 ); ADD( 15 ); ADD( 14 ); ADD( 22 ); + SUB( 17 ); NEXT; // A6 + + ADD( 19 ); ADD( 16 ); ADD( 15 ); ADD( 23 ); + SUB( 18 ); NEXT; // A7 + + ADD( 20 ); ADD( 17 ); ADD( 16 ); + SUB( 19 ); NEXT; // A8 + + ADD( 21 ); ADD( 18 ); ADD( 17 ); + SUB( 20 ); NEXT; // A9 + + ADD( 22 ); ADD( 19 ); ADD( 18 ); + SUB( 21 ); NEXT; // A10 + + ADD( 23 ); ADD( 20 ); ADD( 19 ); + SUB( 22 ); LAST; // A11 + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ + +#undef A +#undef LOAD32 +#undef STORE32 +#undef MAX32 +#undef INIT +#undef NEXT +#undef LAST + +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED || + MBEDTLS_ECP_DP_SECP256R1_ENABLED || + MBEDTLS_ECP_DP_SECP384R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) +/* + * Here we have an actual Mersenne prime, so things are more straightforward. + * However, chunks are aligned on a 'weird' boundary (521 bits). + */ + +/* Size of p521 in terms of mbedtls_mpi_uint */ +#define P521_WIDTH ( 521 / 8 / sizeof( mbedtls_mpi_uint ) + 1 ) + +/* Bits to keep in the most significant mbedtls_mpi_uint */ +#define P521_MASK 0x01FF + +/* + * Fast quasi-reduction modulo p521 (FIPS 186-3 D.2.5) + * Write N as A1 + 2^521 A0, return A0 + A1 + */ +static int ecp_mod_p521( mbedtls_mpi *N ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i; + mbedtls_mpi M; + mbedtls_mpi_uint Mp[P521_WIDTH + 1]; + /* Worst case for the size of M is when mbedtls_mpi_uint is 16 bits: + * we need to hold bits 513 to 1056, which is 34 limbs, that is + * P521_WIDTH + 1. Otherwise P521_WIDTH is enough. */ + + if( N->n < P521_WIDTH ) + return( 0 ); + + /* M = A1 */ + M.s = 1; + M.n = N->n - ( P521_WIDTH - 1 ); + if( M.n > P521_WIDTH + 1 ) + M.n = P521_WIDTH + 1; + M.p = Mp; + memcpy( Mp, N->p + P521_WIDTH - 1, M.n * sizeof( mbedtls_mpi_uint ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, 521 % ( 8 * sizeof( mbedtls_mpi_uint ) ) ) ); + + /* N = A0 */ + N->p[P521_WIDTH - 1] &= P521_MASK; + for( i = P521_WIDTH; i < N->n; i++ ) + N->p[i] = 0; + + /* N = A0 + A1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( N, N, &M ) ); + +cleanup: + return( ret ); +} + +#undef P521_WIDTH +#undef P521_MASK +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ + +#endif /* MBEDTLS_ECP_NIST_OPTIM */ + +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) + +/* Size of p255 in terms of mbedtls_mpi_uint */ +#define P255_WIDTH ( 255 / 8 / sizeof( mbedtls_mpi_uint ) + 1 ) + +/* + * Fast quasi-reduction modulo p255 = 2^255 - 19 + * Write N as A0 + 2^255 A1, return A0 + 19 * A1 + */ +static int ecp_mod_p255( mbedtls_mpi *N ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i; + mbedtls_mpi M; + mbedtls_mpi_uint Mp[P255_WIDTH + 2]; + + if( N->n < P255_WIDTH ) + return( 0 ); + + /* M = A1 */ + M.s = 1; + M.n = N->n - ( P255_WIDTH - 1 ); + if( M.n > P255_WIDTH + 1 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + M.p = Mp; + memset( Mp, 0, sizeof Mp ); + memcpy( Mp, N->p + P255_WIDTH - 1, M.n * sizeof( mbedtls_mpi_uint ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, 255 % ( 8 * sizeof( mbedtls_mpi_uint ) ) ) ); + M.n++; /* Make room for multiplication by 19 */ + + /* N = A0 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( N, 255, 0 ) ); + for( i = P255_WIDTH; i < N->n; i++ ) + N->p[i] = 0; + + /* N = A0 + 19 * A1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &M, 19 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( N, N, &M ) ); + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) + +/* Size of p448 in terms of mbedtls_mpi_uint */ +#define P448_WIDTH ( 448 / 8 / sizeof( mbedtls_mpi_uint ) ) + +/* Number of limbs fully occupied by 2^224 (max), and limbs used by it (min) */ +#define DIV_ROUND_UP( X, Y ) ( ( ( X ) + ( Y ) - 1 ) / ( Y ) ) +#define P224_WIDTH_MIN ( 28 / sizeof( mbedtls_mpi_uint ) ) +#define P224_WIDTH_MAX DIV_ROUND_UP( 28, sizeof( mbedtls_mpi_uint ) ) +#define P224_UNUSED_BITS ( ( P224_WIDTH_MAX * sizeof( mbedtls_mpi_uint ) * 8 ) - 224 ) + +/* + * Fast quasi-reduction modulo p448 = 2^448 - 2^224 - 1 + * Write N as A0 + 2^448 A1 and A1 as B0 + 2^224 B1, and return + * A0 + A1 + B1 + (B0 + B1) * 2^224. This is different to the reference + * implementation of Curve448, which uses its own special 56-bit limbs rather + * than a generic bignum library. We could squeeze some extra speed out on + * 32-bit machines by splitting N up into 32-bit limbs and doing the + * arithmetic using the limbs directly as we do for the NIST primes above, + * but for 64-bit targets it should use half the number of operations if we do + * the reduction with 224-bit limbs, since mpi_add_mpi will then use 64-bit adds. + */ +static int ecp_mod_p448( mbedtls_mpi *N ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i; + mbedtls_mpi M, Q; + mbedtls_mpi_uint Mp[P448_WIDTH + 1], Qp[P448_WIDTH]; + + if( N->n <= P448_WIDTH ) + return( 0 ); + + /* M = A1 */ + M.s = 1; + M.n = N->n - ( P448_WIDTH ); + if( M.n > P448_WIDTH ) + /* Shouldn't be called with N larger than 2^896! */ + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + M.p = Mp; + memset( Mp, 0, sizeof( Mp ) ); + memcpy( Mp, N->p + P448_WIDTH, M.n * sizeof( mbedtls_mpi_uint ) ); + + /* N = A0 */ + for( i = P448_WIDTH; i < N->n; i++ ) + N->p[i] = 0; + + /* N += A1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &M ) ); + + /* Q = B1, N += B1 */ + Q = M; + Q.p = Qp; + memcpy( Qp, Mp, sizeof( Qp ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Q, 224 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &Q ) ); + + /* M = (B0 + B1) * 2^224, N += M */ + if( sizeof( mbedtls_mpi_uint ) > 4 ) + Mp[P224_WIDTH_MIN] &= ( (mbedtls_mpi_uint)-1 ) >> ( P224_UNUSED_BITS ); + for( i = P224_WIDTH_MAX; i < M.n; ++i ) + Mp[i] = 0; + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &M, &M, &Q ) ); + M.n = P448_WIDTH + 1; /* Make room for shifted carry bit from the addition */ + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &M, 224 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &M ) ); + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +/* + * Fast quasi-reduction modulo P = 2^s - R, + * with R about 33 bits, used by the Koblitz curves. + * + * Write N as A0 + 2^224 A1, return A0 + R * A1. + * Actually do two passes, since R is big. + */ +#define P_KOBLITZ_MAX ( 256 / 8 / sizeof( mbedtls_mpi_uint ) ) // Max limbs in P +#define P_KOBLITZ_R ( 8 / sizeof( mbedtls_mpi_uint ) ) // Limbs in R +static inline int ecp_mod_koblitz( mbedtls_mpi *N, mbedtls_mpi_uint *Rp, size_t p_limbs, + size_t adjust, size_t shift, mbedtls_mpi_uint mask ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i; + mbedtls_mpi M, R; + mbedtls_mpi_uint Mp[P_KOBLITZ_MAX + P_KOBLITZ_R + 1]; + + if( N->n < p_limbs ) + return( 0 ); + + /* Init R */ + R.s = 1; + R.p = Rp; + R.n = P_KOBLITZ_R; + + /* Common setup for M */ + M.s = 1; + M.p = Mp; + + /* M = A1 */ + M.n = N->n - ( p_limbs - adjust ); + if( M.n > p_limbs + adjust ) + M.n = p_limbs + adjust; + memset( Mp, 0, sizeof Mp ); + memcpy( Mp, N->p + p_limbs - adjust, M.n * sizeof( mbedtls_mpi_uint ) ); + if( shift != 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, shift ) ); + M.n += R.n; /* Make room for multiplication by R */ + + /* N = A0 */ + if( mask != 0 ) + N->p[p_limbs - 1] &= mask; + for( i = p_limbs; i < N->n; i++ ) + N->p[i] = 0; + + /* N = A0 + R * A1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &M, &M, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( N, N, &M ) ); + + /* Second pass */ + + /* M = A1 */ + M.n = N->n - ( p_limbs - adjust ); + if( M.n > p_limbs + adjust ) + M.n = p_limbs + adjust; + memset( Mp, 0, sizeof Mp ); + memcpy( Mp, N->p + p_limbs - adjust, M.n * sizeof( mbedtls_mpi_uint ) ); + if( shift != 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, shift ) ); + M.n += R.n; /* Make room for multiplication by R */ + + /* N = A0 */ + if( mask != 0 ) + N->p[p_limbs - 1] &= mask; + for( i = p_limbs; i < N->n; i++ ) + N->p[i] = 0; + + /* N = A0 + R * A1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &M, &M, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( N, N, &M ) ); + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED) || + MBEDTLS_ECP_DP_SECP224K1_ENABLED) || + MBEDTLS_ECP_DP_SECP256K1_ENABLED) */ + +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) +/* + * Fast quasi-reduction modulo p192k1 = 2^192 - R, + * with R = 2^32 + 2^12 + 2^8 + 2^7 + 2^6 + 2^3 + 1 = 0x0100001119 + */ +static int ecp_mod_p192k1( mbedtls_mpi *N ) +{ + static mbedtls_mpi_uint Rp[] = { + BYTES_TO_T_UINT_8( 0xC9, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) }; + + return( ecp_mod_koblitz( N, Rp, 192 / 8 / sizeof( mbedtls_mpi_uint ), 0, 0, 0 ) ); +} +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) +/* + * Fast quasi-reduction modulo p224k1 = 2^224 - R, + * with R = 2^32 + 2^12 + 2^11 + 2^9 + 2^7 + 2^4 + 2 + 1 = 0x0100001A93 + */ +static int ecp_mod_p224k1( mbedtls_mpi *N ) +{ + static mbedtls_mpi_uint Rp[] = { + BYTES_TO_T_UINT_8( 0x93, 0x1A, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) }; + +#if defined(MBEDTLS_HAVE_INT64) + return( ecp_mod_koblitz( N, Rp, 4, 1, 32, 0xFFFFFFFF ) ); +#else + return( ecp_mod_koblitz( N, Rp, 224 / 8 / sizeof( mbedtls_mpi_uint ), 0, 0, 0 ) ); +#endif +} + +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +/* + * Fast quasi-reduction modulo p256k1 = 2^256 - R, + * with R = 2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1 = 0x01000003D1 + */ +static int ecp_mod_p256k1( mbedtls_mpi *N ) +{ + static mbedtls_mpi_uint Rp[] = { + BYTES_TO_T_UINT_8( 0xD1, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) }; + return( ecp_mod_koblitz( N, Rp, 256 / 8 / sizeof( mbedtls_mpi_uint ), 0, 0, 0 ) ); +} +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ + +#endif /* !MBEDTLS_ECP_ALT */ + +#endif /* MBEDTLS_ECP_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/entropy.c b/Android/Level4/app/src/main/c/mbedtls/library/entropy.c new file mode 100644 index 0000000..db61f16 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/entropy.c @@ -0,0 +1,724 @@ +/* + * Entropy accumulator implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 "common.h" + +#if defined(MBEDTLS_ENTROPY_C) + +#if defined(MBEDTLS_TEST_NULL_ENTROPY) +#warning "**** WARNING! MBEDTLS_TEST_NULL_ENTROPY defined! " +#warning "**** THIS BUILD HAS NO DEFINED ENTROPY SOURCES " +#warning "**** THIS BUILD IS *NOT* SUITABLE FOR PRODUCTION USE " +#endif + +#include "mbedtls/entropy.h" +#include "mbedtls/entropy_poll.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +#include "mbedtls/platform.h" +#endif + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if defined(MBEDTLS_HAVEGE_C) +#include "mbedtls/havege.h" +#endif + +#define ENTROPY_MAX_LOOP 256 /**< Maximum amount to loop before error */ + +void mbedtls_entropy_init( mbedtls_entropy_context *ctx ) +{ + ctx->source_count = 0; + memset( ctx->source, 0, sizeof( ctx->source ) ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif + + ctx->accumulator_started = 0; +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + mbedtls_sha512_init( &ctx->accumulator ); +#else + mbedtls_sha256_init( &ctx->accumulator ); +#endif +#if defined(MBEDTLS_HAVEGE_C) + mbedtls_havege_init( &ctx->havege_data ); +#endif + + /* Reminder: Update ENTROPY_HAVE_STRONG in the test files + * when adding more strong entropy sources here. */ + +#if defined(MBEDTLS_TEST_NULL_ENTROPY) + mbedtls_entropy_add_source( ctx, mbedtls_null_entropy_poll, NULL, + 1, MBEDTLS_ENTROPY_SOURCE_STRONG ); +#endif + +#if !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) +#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) + mbedtls_entropy_add_source( ctx, mbedtls_platform_entropy_poll, NULL, + MBEDTLS_ENTROPY_MIN_PLATFORM, + MBEDTLS_ENTROPY_SOURCE_STRONG ); +#endif +#if defined(MBEDTLS_TIMING_C) + mbedtls_entropy_add_source( ctx, mbedtls_hardclock_poll, NULL, + MBEDTLS_ENTROPY_MIN_HARDCLOCK, + MBEDTLS_ENTROPY_SOURCE_WEAK ); +#endif +#if defined(MBEDTLS_HAVEGE_C) + mbedtls_entropy_add_source( ctx, mbedtls_havege_poll, &ctx->havege_data, + MBEDTLS_ENTROPY_MIN_HAVEGE, + MBEDTLS_ENTROPY_SOURCE_STRONG ); +#endif +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) + mbedtls_entropy_add_source( ctx, mbedtls_hardware_poll, NULL, + MBEDTLS_ENTROPY_MIN_HARDWARE, + MBEDTLS_ENTROPY_SOURCE_STRONG ); +#endif +#if defined(MBEDTLS_ENTROPY_NV_SEED) + mbedtls_entropy_add_source( ctx, mbedtls_nv_seed_poll, NULL, + MBEDTLS_ENTROPY_BLOCK_SIZE, + MBEDTLS_ENTROPY_SOURCE_STRONG ); + ctx->initial_entropy_run = 0; +#endif +#endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */ +} + +void mbedtls_entropy_free( mbedtls_entropy_context *ctx ) +{ +#if defined(MBEDTLS_HAVEGE_C) + mbedtls_havege_free( &ctx->havege_data ); +#endif +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free( &ctx->mutex ); +#endif +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + mbedtls_sha512_free( &ctx->accumulator ); +#else + mbedtls_sha256_free( &ctx->accumulator ); +#endif +#if defined(MBEDTLS_ENTROPY_NV_SEED) + ctx->initial_entropy_run = 0; +#endif + ctx->source_count = 0; + mbedtls_platform_zeroize( ctx->source, sizeof( ctx->source ) ); + ctx->accumulator_started = 0; +} + +int mbedtls_entropy_add_source( mbedtls_entropy_context *ctx, + mbedtls_entropy_f_source_ptr f_source, void *p_source, + size_t threshold, int strong ) +{ + int idx, ret = 0; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + idx = ctx->source_count; + if( idx >= MBEDTLS_ENTROPY_MAX_SOURCES ) + { + ret = MBEDTLS_ERR_ENTROPY_MAX_SOURCES; + goto exit; + } + + ctx->source[idx].f_source = f_source; + ctx->source[idx].p_source = p_source; + ctx->source[idx].threshold = threshold; + ctx->source[idx].strong = strong; + + ctx->source_count++; + +exit: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +/* + * Entropy accumulator update + */ +static int entropy_update( mbedtls_entropy_context *ctx, unsigned char source_id, + const unsigned char *data, size_t len ) +{ + unsigned char header[2]; + unsigned char tmp[MBEDTLS_ENTROPY_BLOCK_SIZE]; + size_t use_len = len; + const unsigned char *p = data; + int ret = 0; + + if( use_len > MBEDTLS_ENTROPY_BLOCK_SIZE ) + { +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + if( ( ret = mbedtls_sha512_ret( data, len, tmp, 0 ) ) != 0 ) + goto cleanup; +#else + if( ( ret = mbedtls_sha256_ret( data, len, tmp, 0 ) ) != 0 ) + goto cleanup; +#endif + p = tmp; + use_len = MBEDTLS_ENTROPY_BLOCK_SIZE; + } + + header[0] = source_id; + header[1] = use_len & 0xFF; + + /* + * Start the accumulator if this has not already happened. Note that + * it is sufficient to start the accumulator here only because all calls to + * gather entropy eventually execute this code. + */ +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + if( ctx->accumulator_started == 0 && + ( ret = mbedtls_sha512_starts_ret( &ctx->accumulator, 0 ) ) != 0 ) + goto cleanup; + else + ctx->accumulator_started = 1; + if( ( ret = mbedtls_sha512_update_ret( &ctx->accumulator, header, 2 ) ) != 0 ) + goto cleanup; + ret = mbedtls_sha512_update_ret( &ctx->accumulator, p, use_len ); +#else + if( ctx->accumulator_started == 0 && + ( ret = mbedtls_sha256_starts_ret( &ctx->accumulator, 0 ) ) != 0 ) + goto cleanup; + else + ctx->accumulator_started = 1; + if( ( ret = mbedtls_sha256_update_ret( &ctx->accumulator, header, 2 ) ) != 0 ) + goto cleanup; + ret = mbedtls_sha256_update_ret( &ctx->accumulator, p, use_len ); +#endif + +cleanup: + mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); + + return( ret ); +} + +int mbedtls_entropy_update_manual( mbedtls_entropy_context *ctx, + const unsigned char *data, size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + ret = entropy_update( ctx, MBEDTLS_ENTROPY_SOURCE_MANUAL, data, len ); + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +/* + * Run through the different sources to add entropy to our accumulator + */ +static int entropy_gather_internal( mbedtls_entropy_context *ctx ) +{ + int ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; + int i; + int have_one_strong = 0; + unsigned char buf[MBEDTLS_ENTROPY_MAX_GATHER]; + size_t olen; + + if( ctx->source_count == 0 ) + return( MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED ); + + /* + * Run through our entropy sources + */ + for( i = 0; i < ctx->source_count; i++ ) + { + if( ctx->source[i].strong == MBEDTLS_ENTROPY_SOURCE_STRONG ) + have_one_strong = 1; + + olen = 0; + if( ( ret = ctx->source[i].f_source( ctx->source[i].p_source, + buf, MBEDTLS_ENTROPY_MAX_GATHER, &olen ) ) != 0 ) + { + goto cleanup; + } + + /* + * Add if we actually gathered something + */ + if( olen > 0 ) + { + if( ( ret = entropy_update( ctx, (unsigned char) i, + buf, olen ) ) != 0 ) + return( ret ); + ctx->source[i].size += olen; + } + } + + if( have_one_strong == 0 ) + ret = MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE; + +cleanup: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + + return( ret ); +} + +/* + * Thread-safe wrapper for entropy_gather_internal() + */ +int mbedtls_entropy_gather( mbedtls_entropy_context *ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + ret = entropy_gather_internal( ctx ); + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +int mbedtls_entropy_func( void *data, unsigned char *output, size_t len ) +{ + int ret, count = 0, i, thresholds_reached; + size_t strong_size; + mbedtls_entropy_context *ctx = (mbedtls_entropy_context *) data; + unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; + + if( len > MBEDTLS_ENTROPY_BLOCK_SIZE ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + +#if defined(MBEDTLS_ENTROPY_NV_SEED) + /* Update the NV entropy seed before generating any entropy for outside + * use. + */ + if( ctx->initial_entropy_run == 0 ) + { + ctx->initial_entropy_run = 1; + if( ( ret = mbedtls_entropy_update_nv_seed( ctx ) ) != 0 ) + return( ret ); + } +#endif + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + /* + * Always gather extra entropy before a call + */ + do + { + if( count++ > ENTROPY_MAX_LOOP ) + { + ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; + goto exit; + } + + if( ( ret = entropy_gather_internal( ctx ) ) != 0 ) + goto exit; + + thresholds_reached = 1; + strong_size = 0; + for( i = 0; i < ctx->source_count; i++ ) + { + if( ctx->source[i].size < ctx->source[i].threshold ) + thresholds_reached = 0; + if( ctx->source[i].strong == MBEDTLS_ENTROPY_SOURCE_STRONG ) + strong_size += ctx->source[i].size; + } + } + while( ! thresholds_reached || strong_size < MBEDTLS_ENTROPY_BLOCK_SIZE ); + + memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); + +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + /* + * Note that at this stage it is assumed that the accumulator was started + * in a previous call to entropy_update(). If this is not guaranteed, the + * code below will fail. + */ + if( ( ret = mbedtls_sha512_finish_ret( &ctx->accumulator, buf ) ) != 0 ) + goto exit; + + /* + * Reset accumulator and counters and recycle existing entropy + */ + mbedtls_sha512_free( &ctx->accumulator ); + mbedtls_sha512_init( &ctx->accumulator ); + if( ( ret = mbedtls_sha512_starts_ret( &ctx->accumulator, 0 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_sha512_update_ret( &ctx->accumulator, buf, + MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 ) + goto exit; + + /* + * Perform second SHA-512 on entropy + */ + if( ( ret = mbedtls_sha512_ret( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, + buf, 0 ) ) != 0 ) + goto exit; +#else /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */ + if( ( ret = mbedtls_sha256_finish_ret( &ctx->accumulator, buf ) ) != 0 ) + goto exit; + + /* + * Reset accumulator and counters and recycle existing entropy + */ + mbedtls_sha256_free( &ctx->accumulator ); + mbedtls_sha256_init( &ctx->accumulator ); + if( ( ret = mbedtls_sha256_starts_ret( &ctx->accumulator, 0 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_sha256_update_ret( &ctx->accumulator, buf, + MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 ) + goto exit; + + /* + * Perform second SHA-256 on entropy + */ + if( ( ret = mbedtls_sha256_ret( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, + buf, 0 ) ) != 0 ) + goto exit; +#endif /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */ + + for( i = 0; i < ctx->source_count; i++ ) + ctx->source[i].size = 0; + + memcpy( output, buf, len ); + + ret = 0; + +exit: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +int mbedtls_entropy_update_nv_seed( mbedtls_entropy_context *ctx ) +{ + int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; + unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; + + /* Read new seed and write it to NV */ + if( ( ret = mbedtls_entropy_func( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 ) + return( ret ); + + if( mbedtls_nv_seed_write( buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) < 0 ) + return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR ); + + /* Manually update the remaining stream with a separator value to diverge */ + memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); + ret = mbedtls_entropy_update_manual( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ); + + return( ret ); +} +#endif /* MBEDTLS_ENTROPY_NV_SEED */ + +#if defined(MBEDTLS_FS_IO) +int mbedtls_entropy_write_seed_file( mbedtls_entropy_context *ctx, const char *path ) +{ + int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; + FILE *f; + unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; + + if( ( f = fopen( path, "wb" ) ) == NULL ) + return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR ); + + if( ( ret = mbedtls_entropy_func( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 ) + goto exit; + + if( fwrite( buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f ) != MBEDTLS_ENTROPY_BLOCK_SIZE ) + { + ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; + goto exit; + } + + ret = 0; + +exit: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + + fclose( f ); + return( ret ); +} + +int mbedtls_entropy_update_seed_file( mbedtls_entropy_context *ctx, const char *path ) +{ + int ret = 0; + FILE *f; + size_t n; + unsigned char buf[ MBEDTLS_ENTROPY_MAX_SEED_SIZE ]; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR ); + + fseek( f, 0, SEEK_END ); + n = (size_t) ftell( f ); + fseek( f, 0, SEEK_SET ); + + if( n > MBEDTLS_ENTROPY_MAX_SEED_SIZE ) + n = MBEDTLS_ENTROPY_MAX_SEED_SIZE; + + if( fread( buf, 1, n, f ) != n ) + ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; + else + ret = mbedtls_entropy_update_manual( ctx, buf, n ); + + fclose( f ); + + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + + if( ret != 0 ) + return( ret ); + + return( mbedtls_entropy_write_seed_file( ctx, path ) ); +} +#endif /* MBEDTLS_FS_IO */ + +#if defined(MBEDTLS_SELF_TEST) +#if !defined(MBEDTLS_TEST_NULL_ENTROPY) +/* + * Dummy source function + */ +static int entropy_dummy_source( void *data, unsigned char *output, + size_t len, size_t *olen ) +{ + ((void) data); + + memset( output, 0x2a, len ); + *olen = len; + + return( 0 ); +} +#endif /* !MBEDTLS_TEST_NULL_ENTROPY */ + +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) + +static int mbedtls_entropy_source_self_test_gather( unsigned char *buf, size_t buf_len ) +{ + int ret = 0; + size_t entropy_len = 0; + size_t olen = 0; + size_t attempts = buf_len; + + while( attempts > 0 && entropy_len < buf_len ) + { + if( ( ret = mbedtls_hardware_poll( NULL, buf + entropy_len, + buf_len - entropy_len, &olen ) ) != 0 ) + return( ret ); + + entropy_len += olen; + attempts--; + } + + if( entropy_len < buf_len ) + { + ret = 1; + } + + return( ret ); +} + + +static int mbedtls_entropy_source_self_test_check_bits( const unsigned char *buf, + size_t buf_len ) +{ + unsigned char set= 0xFF; + unsigned char unset = 0x00; + size_t i; + + for( i = 0; i < buf_len; i++ ) + { + set &= buf[i]; + unset |= buf[i]; + } + + return( set == 0xFF || unset == 0x00 ); +} + +/* + * A test to ensure hat the entropy sources are functioning correctly + * and there is no obvious failure. The test performs the following checks: + * - The entropy source is not providing only 0s (all bits unset) or 1s (all + * bits set). + * - The entropy source is not providing values in a pattern. Because the + * hardware could be providing data in an arbitrary length, this check polls + * the hardware entropy source twice and compares the result to ensure they + * are not equal. + * - The error code returned by the entropy source is not an error. + */ +int mbedtls_entropy_source_self_test( int verbose ) +{ + int ret = 0; + unsigned char buf0[2 * sizeof( unsigned long long int )]; + unsigned char buf1[2 * sizeof( unsigned long long int )]; + + if( verbose != 0 ) + mbedtls_printf( " ENTROPY_BIAS test: " ); + + memset( buf0, 0x00, sizeof( buf0 ) ); + memset( buf1, 0x00, sizeof( buf1 ) ); + + if( ( ret = mbedtls_entropy_source_self_test_gather( buf0, sizeof( buf0 ) ) ) != 0 ) + goto cleanup; + if( ( ret = mbedtls_entropy_source_self_test_gather( buf1, sizeof( buf1 ) ) ) != 0 ) + goto cleanup; + + /* Make sure that the returned values are not all 0 or 1 */ + if( ( ret = mbedtls_entropy_source_self_test_check_bits( buf0, sizeof( buf0 ) ) ) != 0 ) + goto cleanup; + if( ( ret = mbedtls_entropy_source_self_test_check_bits( buf1, sizeof( buf1 ) ) ) != 0 ) + goto cleanup; + + /* Make sure that the entropy source is not returning values in a + * pattern */ + ret = memcmp( buf0, buf1, sizeof( buf0 ) ) == 0; + +cleanup: + if( verbose != 0 ) + { + if( ret != 0 ) + mbedtls_printf( "failed\n" ); + else + mbedtls_printf( "passed\n" ); + + mbedtls_printf( "\n" ); + } + + return( ret != 0 ); +} + +#endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ + +/* + * The actual entropy quality is hard to test, but we can at least + * test that the functions don't cause errors and write the correct + * amount of data to buffers. + */ +int mbedtls_entropy_self_test( int verbose ) +{ + int ret = 1; +#if !defined(MBEDTLS_TEST_NULL_ENTROPY) + mbedtls_entropy_context ctx; + unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 }; + unsigned char acc[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 }; + size_t i, j; +#endif /* !MBEDTLS_TEST_NULL_ENTROPY */ + + if( verbose != 0 ) + mbedtls_printf( " ENTROPY test: " ); + +#if !defined(MBEDTLS_TEST_NULL_ENTROPY) + mbedtls_entropy_init( &ctx ); + + /* First do a gather to make sure we have default sources */ + if( ( ret = mbedtls_entropy_gather( &ctx ) ) != 0 ) + goto cleanup; + + ret = mbedtls_entropy_add_source( &ctx, entropy_dummy_source, NULL, 16, + MBEDTLS_ENTROPY_SOURCE_WEAK ); + if( ret != 0 ) + goto cleanup; + + if( ( ret = mbedtls_entropy_update_manual( &ctx, buf, sizeof buf ) ) != 0 ) + goto cleanup; + + /* + * To test that mbedtls_entropy_func writes correct number of bytes: + * - use the whole buffer and rely on ASan to detect overruns + * - collect entropy 8 times and OR the result in an accumulator: + * any byte should then be 0 with probably 2^(-64), so requiring + * each of the 32 or 64 bytes to be non-zero has a false failure rate + * of at most 2^(-58) which is acceptable. + */ + for( i = 0; i < 8; i++ ) + { + if( ( ret = mbedtls_entropy_func( &ctx, buf, sizeof( buf ) ) ) != 0 ) + goto cleanup; + + for( j = 0; j < sizeof( buf ); j++ ) + acc[j] |= buf[j]; + } + + for( j = 0; j < sizeof( buf ); j++ ) + { + if( acc[j] == 0 ) + { + ret = 1; + goto cleanup; + } + } + +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) + if( ( ret = mbedtls_entropy_source_self_test( 0 ) ) != 0 ) + goto cleanup; +#endif + +cleanup: + mbedtls_entropy_free( &ctx ); +#endif /* !MBEDTLS_TEST_NULL_ENTROPY */ + + if( verbose != 0 ) + { + if( ret != 0 ) + mbedtls_printf( "failed\n" ); + else + mbedtls_printf( "passed\n" ); + + mbedtls_printf( "\n" ); + } + + return( ret != 0 ); +} +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_ENTROPY_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/entropy_poll.c b/Android/Level4/app/src/main/c/mbedtls/library/entropy_poll.c new file mode 100644 index 0000000..5250a7b --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/entropy_poll.c @@ -0,0 +1,276 @@ +/* + * Platform-specific and custom entropy polling functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ + +#if defined(__linux__) && !defined(_GNU_SOURCE) +/* Ensure that syscall() is available even when compiling with -std=c99 */ +#define _GNU_SOURCE +#endif + +#include "common.h" + +#include + +#if defined(MBEDTLS_ENTROPY_C) + +#include "mbedtls/entropy.h" +#include "mbedtls/entropy_poll.h" +#include "mbedtls/error.h" + +#if defined(MBEDTLS_TIMING_C) +#include "mbedtls/timing.h" +#endif +#if defined(MBEDTLS_HAVEGE_C) +#include "mbedtls/havege.h" +#endif +#if defined(MBEDTLS_ENTROPY_NV_SEED) +#include "mbedtls/platform.h" +#endif + +#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) + +#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ + !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \ + !defined(__HAIKU__) && !defined(__midipix__) +#error "Platform entropy sources only work on Unix and Windows, see MBEDTLS_NO_PLATFORM_ENTROPY in config.h" +#endif + +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + +#if !defined(_WIN32_WINNT) +#define _WIN32_WINNT 0x0400 +#endif +#include +#include + +int mbedtls_platform_entropy_poll( void *data, unsigned char *output, size_t len, + size_t *olen ) +{ + HCRYPTPROV provider; + ((void) data); + *olen = 0; + + if( CryptAcquireContext( &provider, NULL, NULL, + PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ) == FALSE ) + { + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + } + + if( CryptGenRandom( provider, (DWORD) len, output ) == FALSE ) + { + CryptReleaseContext( provider, 0 ); + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + } + + CryptReleaseContext( provider, 0 ); + *olen = len; + + return( 0 ); +} +#else /* _WIN32 && !EFIX64 && !EFI32 */ + +/* + * Test for Linux getrandom() support. + * Since there is no wrapper in the libc yet, use the generic syscall wrapper + * available in GNU libc and compatible libc's (eg uClibc). + */ +#if ((defined(__linux__) && defined(__GLIBC__)) || defined(__midipix__)) +#include +#include +#if defined(SYS_getrandom) +#define HAVE_GETRANDOM +#include + +static int getrandom_wrapper( void *buf, size_t buflen, unsigned int flags ) +{ + /* MemSan cannot understand that the syscall writes to the buffer */ +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) + memset( buf, 0, buflen ); +#endif +#endif + return( syscall( SYS_getrandom, buf, buflen, flags ) ); +} +#endif /* SYS_getrandom */ +#endif /* __linux__ || __midipix__ */ + +/* + * Some BSD systems provide KERN_ARND. + * This is equivalent to reading from /dev/urandom, only it doesn't require an + * open file descriptor, and provides up to 256 bytes per call (basically the + * same as getentropy(), but with a longer history). + * + * Documentation: https://netbsd.gw.com/cgi-bin/man-cgi?sysctl+7 + */ +#if (defined(__FreeBSD__) || defined(__NetBSD__)) && !defined(HAVE_GETRANDOM) +#include +#include +#if defined(KERN_ARND) +#define HAVE_SYSCTL_ARND + +static int sysctl_arnd_wrapper( unsigned char *buf, size_t buflen ) +{ + int name[2]; + size_t len; + + name[0] = CTL_KERN; + name[1] = KERN_ARND; + + while( buflen > 0 ) + { + len = buflen > 256 ? 256 : buflen; + if( sysctl(name, 2, buf, &len, NULL, 0) == -1 ) + return( -1 ); + buflen -= len; + buf += len; + } + return( 0 ); +} +#endif /* KERN_ARND */ +#endif /* __FreeBSD__ || __NetBSD__ */ + +#include + +int mbedtls_platform_entropy_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + FILE *file; + size_t read_len; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + ((void) data); + +#if defined(HAVE_GETRANDOM) + ret = getrandom_wrapper( output, len, 0 ); + if( ret >= 0 ) + { + *olen = ret; + return( 0 ); + } + else if( errno != ENOSYS ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + /* Fall through if the system call isn't known. */ +#else + ((void) ret); +#endif /* HAVE_GETRANDOM */ + +#if defined(HAVE_SYSCTL_ARND) + ((void) file); + ((void) read_len); + if( sysctl_arnd_wrapper( output, len ) == -1 ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + *olen = len; + return( 0 ); +#else + + *olen = 0; + + file = fopen( "/dev/urandom", "rb" ); + if( file == NULL ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + + read_len = fread( output, 1, len, file ); + if( read_len != len ) + { + fclose( file ); + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + } + + fclose( file ); + *olen = len; + + return( 0 ); +#endif /* HAVE_SYSCTL_ARND */ +} +#endif /* _WIN32 && !EFIX64 && !EFI32 */ +#endif /* !MBEDTLS_NO_PLATFORM_ENTROPY */ + +#if defined(MBEDTLS_TEST_NULL_ENTROPY) +int mbedtls_null_entropy_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + ((void) data); + ((void) output); + *olen = 0; + + if( len < sizeof(unsigned char) ) + return( 0 ); + + *olen = sizeof(unsigned char); + + return( 0 ); +} +#endif + +#if defined(MBEDTLS_TIMING_C) +int mbedtls_hardclock_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + unsigned long timer = mbedtls_timing_hardclock(); + ((void) data); + *olen = 0; + + if( len < sizeof(unsigned long) ) + return( 0 ); + + memcpy( output, &timer, sizeof(unsigned long) ); + *olen = sizeof(unsigned long); + + return( 0 ); +} +#endif /* MBEDTLS_TIMING_C */ + +#if defined(MBEDTLS_HAVEGE_C) +int mbedtls_havege_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + mbedtls_havege_state *hs = (mbedtls_havege_state *) data; + *olen = 0; + + if( mbedtls_havege_random( hs, output, len ) != 0 ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + + *olen = len; + + return( 0 ); +} +#endif /* MBEDTLS_HAVEGE_C */ + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +int mbedtls_nv_seed_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; + size_t use_len = MBEDTLS_ENTROPY_BLOCK_SIZE; + ((void) data); + + memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); + + if( mbedtls_nv_seed_read( buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) < 0 ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + + if( len < use_len ) + use_len = len; + + memcpy( output, buf, use_len ); + *olen = use_len; + + return( 0 ); +} +#endif /* MBEDTLS_ENTROPY_NV_SEED */ + +#endif /* MBEDTLS_ENTROPY_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/error.c b/Android/Level4/app/src/main/c/mbedtls/library/error.c new file mode 100644 index 0000000..cba61e9 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/error.c @@ -0,0 +1,978 @@ +/* + * Error message information + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 "common.h" + +#if defined(MBEDTLS_ERROR_STRERROR_DUMMY) +#include +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#define mbedtls_snprintf snprintf +#define mbedtls_time_t time_t +#endif + +#if defined(MBEDTLS_ERROR_C) + +#include + +#if defined(MBEDTLS_AES_C) +#include "mbedtls/aes.h" +#endif + +#if defined(MBEDTLS_ARC4_C) +#include "mbedtls/arc4.h" +#endif + +#if defined(MBEDTLS_ARIA_C) +#include "mbedtls/aria.h" +#endif + +#if defined(MBEDTLS_ASN1_PARSE_C) +#include "mbedtls/asn1.h" +#endif + +#if defined(MBEDTLS_BASE64_C) +#include "mbedtls/base64.h" +#endif + +#if defined(MBEDTLS_BIGNUM_C) +#include "mbedtls/bignum.h" +#endif + +#if defined(MBEDTLS_BLOWFISH_C) +#include "mbedtls/blowfish.h" +#endif + +#if defined(MBEDTLS_CAMELLIA_C) +#include "mbedtls/camellia.h" +#endif + +#if defined(MBEDTLS_CCM_C) +#include "mbedtls/ccm.h" +#endif + +#if defined(MBEDTLS_CHACHA20_C) +#include "mbedtls/chacha20.h" +#endif + +#if defined(MBEDTLS_CHACHAPOLY_C) +#include "mbedtls/chachapoly.h" +#endif + +#if defined(MBEDTLS_CIPHER_C) +#include "mbedtls/cipher.h" +#endif + +#if defined(MBEDTLS_CMAC_C) +#include "mbedtls/cmac.h" +#endif + +#if defined(MBEDTLS_CTR_DRBG_C) +#include "mbedtls/ctr_drbg.h" +#endif + +#if defined(MBEDTLS_DES_C) +#include "mbedtls/des.h" +#endif + +#if defined(MBEDTLS_DHM_C) +#include "mbedtls/dhm.h" +#endif + +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/ecp.h" +#endif + +#if defined(MBEDTLS_ENTROPY_C) +#include "mbedtls/entropy.h" +#endif + +#if defined(MBEDTLS_ERROR_C) +#include "mbedtls/error.h" +#endif + +#if defined(MBEDTLS_GCM_C) +#include "mbedtls/gcm.h" +#endif + +#if defined(MBEDTLS_HKDF_C) +#include "mbedtls/hkdf.h" +#endif + +#if defined(MBEDTLS_HMAC_DRBG_C) +#include "mbedtls/hmac_drbg.h" +#endif + +#if defined(MBEDTLS_MD_C) +#include "mbedtls/md.h" +#endif + +#if defined(MBEDTLS_MD2_C) +#include "mbedtls/md2.h" +#endif + +#if defined(MBEDTLS_MD4_C) +#include "mbedtls/md4.h" +#endif + +#if defined(MBEDTLS_MD5_C) +#include "mbedtls/md5.h" +#endif + +#if defined(MBEDTLS_NET_C) +#include "mbedtls/net_sockets.h" +#endif + +#if defined(MBEDTLS_OID_C) +#include "mbedtls/oid.h" +#endif + +#if defined(MBEDTLS_PADLOCK_C) +#include "mbedtls/padlock.h" +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_PK_C) +#include "mbedtls/pk.h" +#endif + +#if defined(MBEDTLS_PKCS12_C) +#include "mbedtls/pkcs12.h" +#endif + +#if defined(MBEDTLS_PKCS5_C) +#include "mbedtls/pkcs5.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#endif + +#if defined(MBEDTLS_POLY1305_C) +#include "mbedtls/poly1305.h" +#endif + +#if defined(MBEDTLS_RIPEMD160_C) +#include "mbedtls/ripemd160.h" +#endif + +#if defined(MBEDTLS_RSA_C) +#include "mbedtls/rsa.h" +#endif + +#if defined(MBEDTLS_SHA1_C) +#include "mbedtls/sha1.h" +#endif + +#if defined(MBEDTLS_SHA256_C) +#include "mbedtls/sha256.h" +#endif + +#if defined(MBEDTLS_SHA512_C) +#include "mbedtls/sha512.h" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) +#include "mbedtls/ssl.h" +#endif + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) +#include "mbedtls/x509.h" +#endif + +#if defined(MBEDTLS_XTEA_C) +#include "mbedtls/xtea.h" +#endif + + +const char * mbedtls_high_level_strerr( int error_code ) +{ + int high_level_error_code; + + if( error_code < 0 ) + error_code = -error_code; + + /* Extract the high-level part from the error code. */ + high_level_error_code = error_code & 0xFF80; + + switch( high_level_error_code ) + { + /* Begin Auto-Generated Code. */ +#if defined(MBEDTLS_CIPHER_C) + case -(MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE): + return( "CIPHER - The selected feature is not available" ); + case -(MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA): + return( "CIPHER - Bad input parameters" ); + case -(MBEDTLS_ERR_CIPHER_ALLOC_FAILED): + return( "CIPHER - Failed to allocate memory" ); + case -(MBEDTLS_ERR_CIPHER_INVALID_PADDING): + return( "CIPHER - Input data contains invalid padding and is rejected" ); + case -(MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED): + return( "CIPHER - Decryption of block requires a full block" ); + case -(MBEDTLS_ERR_CIPHER_AUTH_FAILED): + return( "CIPHER - Authentication failed (for AEAD modes)" ); + case -(MBEDTLS_ERR_CIPHER_INVALID_CONTEXT): + return( "CIPHER - The context is invalid. For example, because it was freed" ); + case -(MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED): + return( "CIPHER - Cipher hardware accelerator failed" ); +#endif /* MBEDTLS_CIPHER_C */ + +#if defined(MBEDTLS_DHM_C) + case -(MBEDTLS_ERR_DHM_BAD_INPUT_DATA): + return( "DHM - Bad input parameters" ); + case -(MBEDTLS_ERR_DHM_READ_PARAMS_FAILED): + return( "DHM - Reading of the DHM parameters failed" ); + case -(MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED): + return( "DHM - Making of the DHM parameters failed" ); + case -(MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED): + return( "DHM - Reading of the public values failed" ); + case -(MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED): + return( "DHM - Making of the public value failed" ); + case -(MBEDTLS_ERR_DHM_CALC_SECRET_FAILED): + return( "DHM - Calculation of the DHM secret failed" ); + case -(MBEDTLS_ERR_DHM_INVALID_FORMAT): + return( "DHM - The ASN.1 data is not formatted correctly" ); + case -(MBEDTLS_ERR_DHM_ALLOC_FAILED): + return( "DHM - Allocation of memory failed" ); + case -(MBEDTLS_ERR_DHM_FILE_IO_ERROR): + return( "DHM - Read or write of file failed" ); + case -(MBEDTLS_ERR_DHM_HW_ACCEL_FAILED): + return( "DHM - DHM hardware accelerator failed" ); + case -(MBEDTLS_ERR_DHM_SET_GROUP_FAILED): + return( "DHM - Setting the modulus and generator failed" ); +#endif /* MBEDTLS_DHM_C */ + +#if defined(MBEDTLS_ECP_C) + case -(MBEDTLS_ERR_ECP_BAD_INPUT_DATA): + return( "ECP - Bad input parameters to function" ); + case -(MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL): + return( "ECP - The buffer is too small to write to" ); + case -(MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE): + return( "ECP - The requested feature is not available, for example, the requested curve is not supported" ); + case -(MBEDTLS_ERR_ECP_VERIFY_FAILED): + return( "ECP - The signature is not valid" ); + case -(MBEDTLS_ERR_ECP_ALLOC_FAILED): + return( "ECP - Memory allocation failed" ); + case -(MBEDTLS_ERR_ECP_RANDOM_FAILED): + return( "ECP - Generation of random value, such as ephemeral key, failed" ); + case -(MBEDTLS_ERR_ECP_INVALID_KEY): + return( "ECP - Invalid private or public key" ); + case -(MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH): + return( "ECP - The buffer contains a valid signature followed by more data" ); + case -(MBEDTLS_ERR_ECP_HW_ACCEL_FAILED): + return( "ECP - The ECP hardware accelerator failed" ); + case -(MBEDTLS_ERR_ECP_IN_PROGRESS): + return( "ECP - Operation in progress, call again with the same parameters to continue" ); +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_MD_C) + case -(MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE): + return( "MD - The selected feature is not available" ); + case -(MBEDTLS_ERR_MD_BAD_INPUT_DATA): + return( "MD - Bad input parameters to function" ); + case -(MBEDTLS_ERR_MD_ALLOC_FAILED): + return( "MD - Failed to allocate memory" ); + case -(MBEDTLS_ERR_MD_FILE_IO_ERROR): + return( "MD - Opening or reading of file failed" ); + case -(MBEDTLS_ERR_MD_HW_ACCEL_FAILED): + return( "MD - MD hardware accelerator failed" ); +#endif /* MBEDTLS_MD_C */ + +#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) + case -(MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT): + return( "PEM - No PEM header or footer found" ); + case -(MBEDTLS_ERR_PEM_INVALID_DATA): + return( "PEM - PEM string is not as expected" ); + case -(MBEDTLS_ERR_PEM_ALLOC_FAILED): + return( "PEM - Failed to allocate memory" ); + case -(MBEDTLS_ERR_PEM_INVALID_ENC_IV): + return( "PEM - RSA IV is not in hex-format" ); + case -(MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG): + return( "PEM - Unsupported key encryption algorithm" ); + case -(MBEDTLS_ERR_PEM_PASSWORD_REQUIRED): + return( "PEM - Private key password can't be empty" ); + case -(MBEDTLS_ERR_PEM_PASSWORD_MISMATCH): + return( "PEM - Given private key password does not allow for correct decryption" ); + case -(MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE): + return( "PEM - Unavailable feature, e.g. hashing/encryption combination" ); + case -(MBEDTLS_ERR_PEM_BAD_INPUT_DATA): + return( "PEM - Bad input parameters to function" ); +#endif /* MBEDTLS_PEM_PARSE_C || MBEDTLS_PEM_WRITE_C */ + +#if defined(MBEDTLS_PK_C) + case -(MBEDTLS_ERR_PK_ALLOC_FAILED): + return( "PK - Memory allocation failed" ); + case -(MBEDTLS_ERR_PK_TYPE_MISMATCH): + return( "PK - Type mismatch, eg attempt to encrypt with an ECDSA key" ); + case -(MBEDTLS_ERR_PK_BAD_INPUT_DATA): + return( "PK - Bad input parameters to function" ); + case -(MBEDTLS_ERR_PK_FILE_IO_ERROR): + return( "PK - Read/write of file failed" ); + case -(MBEDTLS_ERR_PK_KEY_INVALID_VERSION): + return( "PK - Unsupported key version" ); + case -(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT): + return( "PK - Invalid key tag or value" ); + case -(MBEDTLS_ERR_PK_UNKNOWN_PK_ALG): + return( "PK - Key algorithm is unsupported (only RSA and EC are supported)" ); + case -(MBEDTLS_ERR_PK_PASSWORD_REQUIRED): + return( "PK - Private key password can't be empty" ); + case -(MBEDTLS_ERR_PK_PASSWORD_MISMATCH): + return( "PK - Given private key password does not allow for correct decryption" ); + case -(MBEDTLS_ERR_PK_INVALID_PUBKEY): + return( "PK - The pubkey tag or value is invalid (only RSA and EC are supported)" ); + case -(MBEDTLS_ERR_PK_INVALID_ALG): + return( "PK - The algorithm tag or value is invalid" ); + case -(MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE): + return( "PK - Elliptic curve is unsupported (only NIST curves are supported)" ); + case -(MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE): + return( "PK - Unavailable feature, e.g. RSA disabled for RSA key" ); + case -(MBEDTLS_ERR_PK_SIG_LEN_MISMATCH): + return( "PK - The buffer contains a valid signature followed by more data" ); + case -(MBEDTLS_ERR_PK_HW_ACCEL_FAILED): + return( "PK - PK hardware accelerator failed" ); +#endif /* MBEDTLS_PK_C */ + +#if defined(MBEDTLS_PKCS12_C) + case -(MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA): + return( "PKCS12 - Bad input parameters to function" ); + case -(MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE): + return( "PKCS12 - Feature not available, e.g. unsupported encryption scheme" ); + case -(MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT): + return( "PKCS12 - PBE ASN.1 data not as expected" ); + case -(MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH): + return( "PKCS12 - Given private key password does not allow for correct decryption" ); +#endif /* MBEDTLS_PKCS12_C */ + +#if defined(MBEDTLS_PKCS5_C) + case -(MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA): + return( "PKCS5 - Bad input parameters to function" ); + case -(MBEDTLS_ERR_PKCS5_INVALID_FORMAT): + return( "PKCS5 - Unexpected ASN.1 data" ); + case -(MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE): + return( "PKCS5 - Requested encryption or digest alg not available" ); + case -(MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH): + return( "PKCS5 - Given private key password does not allow for correct decryption" ); +#endif /* MBEDTLS_PKCS5_C */ + +#if defined(MBEDTLS_RSA_C) + case -(MBEDTLS_ERR_RSA_BAD_INPUT_DATA): + return( "RSA - Bad input parameters to function" ); + case -(MBEDTLS_ERR_RSA_INVALID_PADDING): + return( "RSA - Input data contains invalid padding and is rejected" ); + case -(MBEDTLS_ERR_RSA_KEY_GEN_FAILED): + return( "RSA - Something failed during generation of a key" ); + case -(MBEDTLS_ERR_RSA_KEY_CHECK_FAILED): + return( "RSA - Key failed to pass the validity check of the library" ); + case -(MBEDTLS_ERR_RSA_PUBLIC_FAILED): + return( "RSA - The public key operation failed" ); + case -(MBEDTLS_ERR_RSA_PRIVATE_FAILED): + return( "RSA - The private key operation failed" ); + case -(MBEDTLS_ERR_RSA_VERIFY_FAILED): + return( "RSA - The PKCS#1 verification failed" ); + case -(MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE): + return( "RSA - The output buffer for decryption is not large enough" ); + case -(MBEDTLS_ERR_RSA_RNG_FAILED): + return( "RSA - The random generator failed to generate non-zeros" ); + case -(MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION): + return( "RSA - The implementation does not offer the requested operation, for example, because of security violations or lack of functionality" ); + case -(MBEDTLS_ERR_RSA_HW_ACCEL_FAILED): + return( "RSA - RSA hardware accelerator failed" ); +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_SSL_TLS_C) + case -(MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE): + return( "SSL - The requested feature is not available" ); + case -(MBEDTLS_ERR_SSL_BAD_INPUT_DATA): + return( "SSL - Bad input parameters to function" ); + case -(MBEDTLS_ERR_SSL_INVALID_MAC): + return( "SSL - Verification of the message MAC failed" ); + case -(MBEDTLS_ERR_SSL_INVALID_RECORD): + return( "SSL - An invalid SSL record was received" ); + case -(MBEDTLS_ERR_SSL_CONN_EOF): + return( "SSL - The connection indicated an EOF" ); + case -(MBEDTLS_ERR_SSL_UNKNOWN_CIPHER): + return( "SSL - An unknown cipher was received" ); + case -(MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN): + return( "SSL - The server has no ciphersuites in common with the client" ); + case -(MBEDTLS_ERR_SSL_NO_RNG): + return( "SSL - No RNG was provided to the SSL module" ); + case -(MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE): + return( "SSL - No client certification received from the client, but required by the authentication mode" ); + case -(MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE): + return( "SSL - Our own certificate(s) is/are too large to send in an SSL message" ); + case -(MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED): + return( "SSL - The own certificate is not set, but needed by the server" ); + case -(MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED): + return( "SSL - The own private key or pre-shared key is not set, but needed" ); + case -(MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED): + return( "SSL - No CA Chain is set, but required to operate" ); + case -(MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE): + return( "SSL - An unexpected message was received from our peer" ); + case -(MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE): + return( "SSL - A fatal alert message was received from our peer" ); + case -(MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED): + return( "SSL - Verification of our peer failed" ); + case -(MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY): + return( "SSL - The peer notified us that the connection is going to be closed" ); + case -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO): + return( "SSL - Processing of the ClientHello handshake message failed" ); + case -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO): + return( "SSL - Processing of the ServerHello handshake message failed" ); + case -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE): + return( "SSL - Processing of the Certificate handshake message failed" ); + case -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST): + return( "SSL - Processing of the CertificateRequest handshake message failed" ); + case -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE): + return( "SSL - Processing of the ServerKeyExchange handshake message failed" ); + case -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE): + return( "SSL - Processing of the ServerHelloDone handshake message failed" ); + case -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE): + return( "SSL - Processing of the ClientKeyExchange handshake message failed" ); + case -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP): + return( "SSL - Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Read Public" ); + case -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS): + return( "SSL - Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Calculate Secret" ); + case -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY): + return( "SSL - Processing of the CertificateVerify handshake message failed" ); + case -(MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC): + return( "SSL - Processing of the ChangeCipherSpec handshake message failed" ); + case -(MBEDTLS_ERR_SSL_BAD_HS_FINISHED): + return( "SSL - Processing of the Finished handshake message failed" ); + case -(MBEDTLS_ERR_SSL_ALLOC_FAILED): + return( "SSL - Memory allocation failed" ); + case -(MBEDTLS_ERR_SSL_HW_ACCEL_FAILED): + return( "SSL - Hardware acceleration function returned with error" ); + case -(MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH): + return( "SSL - Hardware acceleration function skipped / left alone data" ); + case -(MBEDTLS_ERR_SSL_COMPRESSION_FAILED): + return( "SSL - Processing of the compression / decompression failed" ); + case -(MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION): + return( "SSL - Handshake protocol not within min/max boundaries" ); + case -(MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET): + return( "SSL - Processing of the NewSessionTicket handshake message failed" ); + case -(MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED): + return( "SSL - Session ticket has expired" ); + case -(MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH): + return( "SSL - Public key type mismatch (eg, asked for RSA key exchange and presented EC key)" ); + case -(MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY): + return( "SSL - Unknown identity received (eg, PSK identity)" ); + case -(MBEDTLS_ERR_SSL_INTERNAL_ERROR): + return( "SSL - Internal error (eg, unexpected failure in lower-level module)" ); + case -(MBEDTLS_ERR_SSL_COUNTER_WRAPPING): + return( "SSL - A counter would wrap (eg, too many messages exchanged)" ); + case -(MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO): + return( "SSL - Unexpected message at ServerHello in renegotiation" ); + case -(MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED): + return( "SSL - DTLS client must retry for hello verification" ); + case -(MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL): + return( "SSL - A buffer is too small to receive or write a message" ); + case -(MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE): + return( "SSL - None of the common ciphersuites is usable (eg, no suitable certificate, see debug messages)" ); + case -(MBEDTLS_ERR_SSL_WANT_READ): + return( "SSL - No data of requested type currently available on underlying transport" ); + case -(MBEDTLS_ERR_SSL_WANT_WRITE): + return( "SSL - Connection requires a write call" ); + case -(MBEDTLS_ERR_SSL_TIMEOUT): + return( "SSL - The operation timed out" ); + case -(MBEDTLS_ERR_SSL_CLIENT_RECONNECT): + return( "SSL - The client initiated a reconnect from the same port" ); + case -(MBEDTLS_ERR_SSL_UNEXPECTED_RECORD): + return( "SSL - Record header looks valid but is not expected" ); + case -(MBEDTLS_ERR_SSL_NON_FATAL): + return( "SSL - The alert message received indicates a non-fatal error" ); + case -(MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH): + return( "SSL - Couldn't set the hash for verifying CertificateVerify" ); + case -(MBEDTLS_ERR_SSL_CONTINUE_PROCESSING): + return( "SSL - Internal-only message signaling that further message-processing should be done" ); + case -(MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS): + return( "SSL - The asynchronous operation is not completed yet" ); + case -(MBEDTLS_ERR_SSL_EARLY_MESSAGE): + return( "SSL - Internal-only message signaling that a message arrived early" ); + case -(MBEDTLS_ERR_SSL_UNEXPECTED_CID): + return( "SSL - An encrypted DTLS-frame with an unexpected CID was received" ); + case -(MBEDTLS_ERR_SSL_VERSION_MISMATCH): + return( "SSL - An operation failed due to an unexpected version or configuration" ); + case -(MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS): + return( "SSL - A cryptographic operation is in progress. Try again later" ); + case -(MBEDTLS_ERR_SSL_BAD_CONFIG): + return( "SSL - Invalid value in SSL config" ); +#endif /* MBEDTLS_SSL_TLS_C */ + +#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) + case -(MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE): + return( "X509 - Unavailable feature, e.g. RSA hashing/encryption combination" ); + case -(MBEDTLS_ERR_X509_UNKNOWN_OID): + return( "X509 - Requested OID is unknown" ); + case -(MBEDTLS_ERR_X509_INVALID_FORMAT): + return( "X509 - The CRT/CRL/CSR format is invalid, e.g. different type expected" ); + case -(MBEDTLS_ERR_X509_INVALID_VERSION): + return( "X509 - The CRT/CRL/CSR version element is invalid" ); + case -(MBEDTLS_ERR_X509_INVALID_SERIAL): + return( "X509 - The serial tag or value is invalid" ); + case -(MBEDTLS_ERR_X509_INVALID_ALG): + return( "X509 - The algorithm tag or value is invalid" ); + case -(MBEDTLS_ERR_X509_INVALID_NAME): + return( "X509 - The name tag or value is invalid" ); + case -(MBEDTLS_ERR_X509_INVALID_DATE): + return( "X509 - The date tag or value is invalid" ); + case -(MBEDTLS_ERR_X509_INVALID_SIGNATURE): + return( "X509 - The signature tag or value invalid" ); + case -(MBEDTLS_ERR_X509_INVALID_EXTENSIONS): + return( "X509 - The extension tag or value is invalid" ); + case -(MBEDTLS_ERR_X509_UNKNOWN_VERSION): + return( "X509 - CRT/CRL/CSR has an unsupported version number" ); + case -(MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG): + return( "X509 - Signature algorithm (oid) is unsupported" ); + case -(MBEDTLS_ERR_X509_SIG_MISMATCH): + return( "X509 - Signature algorithms do not match. (see \\c ::mbedtls_x509_crt sig_oid)" ); + case -(MBEDTLS_ERR_X509_CERT_VERIFY_FAILED): + return( "X509 - Certificate verification failed, e.g. CRL, CA or signature check failed" ); + case -(MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT): + return( "X509 - Format not recognized as DER or PEM" ); + case -(MBEDTLS_ERR_X509_BAD_INPUT_DATA): + return( "X509 - Input invalid" ); + case -(MBEDTLS_ERR_X509_ALLOC_FAILED): + return( "X509 - Allocation of memory failed" ); + case -(MBEDTLS_ERR_X509_FILE_IO_ERROR): + return( "X509 - Read/write of file failed" ); + case -(MBEDTLS_ERR_X509_BUFFER_TOO_SMALL): + return( "X509 - Destination buffer is too small" ); + case -(MBEDTLS_ERR_X509_FATAL_ERROR): + return( "X509 - A fatal error occurred, eg the chain is too long or the vrfy callback failed" ); +#endif /* MBEDTLS_X509_USE_C || MBEDTLS_X509_CREATE_C */ + /* End Auto-Generated Code. */ + + default: + break; + } + + return( NULL ); +} + +const char * mbedtls_low_level_strerr( int error_code ) +{ + int low_level_error_code; + + if( error_code < 0 ) + error_code = -error_code; + + /* Extract the low-level part from the error code. */ + low_level_error_code = error_code & ~0xFF80; + + switch( low_level_error_code ) + { + /* Begin Auto-Generated Code. */ +#if defined(MBEDTLS_AES_C) + case -(MBEDTLS_ERR_AES_INVALID_KEY_LENGTH): + return( "AES - Invalid key length" ); + case -(MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH): + return( "AES - Invalid data input length" ); + case -(MBEDTLS_ERR_AES_BAD_INPUT_DATA): + return( "AES - Invalid input data" ); + case -(MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE): + return( "AES - Feature not available. For example, an unsupported AES key size" ); + case -(MBEDTLS_ERR_AES_HW_ACCEL_FAILED): + return( "AES - AES hardware accelerator failed" ); +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_ARC4_C) + case -(MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED): + return( "ARC4 - ARC4 hardware accelerator failed" ); +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_ARIA_C) + case -(MBEDTLS_ERR_ARIA_BAD_INPUT_DATA): + return( "ARIA - Bad input data" ); + case -(MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH): + return( "ARIA - Invalid data input length" ); + case -(MBEDTLS_ERR_ARIA_FEATURE_UNAVAILABLE): + return( "ARIA - Feature not available. For example, an unsupported ARIA key size" ); + case -(MBEDTLS_ERR_ARIA_HW_ACCEL_FAILED): + return( "ARIA - ARIA hardware accelerator failed" ); +#endif /* MBEDTLS_ARIA_C */ + +#if defined(MBEDTLS_ASN1_PARSE_C) + case -(MBEDTLS_ERR_ASN1_OUT_OF_DATA): + return( "ASN1 - Out of data when parsing an ASN1 data structure" ); + case -(MBEDTLS_ERR_ASN1_UNEXPECTED_TAG): + return( "ASN1 - ASN1 tag was of an unexpected value" ); + case -(MBEDTLS_ERR_ASN1_INVALID_LENGTH): + return( "ASN1 - Error when trying to determine the length or invalid length" ); + case -(MBEDTLS_ERR_ASN1_LENGTH_MISMATCH): + return( "ASN1 - Actual length differs from expected length" ); + case -(MBEDTLS_ERR_ASN1_INVALID_DATA): + return( "ASN1 - Data is invalid" ); + case -(MBEDTLS_ERR_ASN1_ALLOC_FAILED): + return( "ASN1 - Memory allocation failed" ); + case -(MBEDTLS_ERR_ASN1_BUF_TOO_SMALL): + return( "ASN1 - Buffer too small when writing ASN.1 data structure" ); +#endif /* MBEDTLS_ASN1_PARSE_C */ + +#if defined(MBEDTLS_BASE64_C) + case -(MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL): + return( "BASE64 - Output buffer too small" ); + case -(MBEDTLS_ERR_BASE64_INVALID_CHARACTER): + return( "BASE64 - Invalid character in input" ); +#endif /* MBEDTLS_BASE64_C */ + +#if defined(MBEDTLS_BIGNUM_C) + case -(MBEDTLS_ERR_MPI_FILE_IO_ERROR): + return( "BIGNUM - An error occurred while reading from or writing to a file" ); + case -(MBEDTLS_ERR_MPI_BAD_INPUT_DATA): + return( "BIGNUM - Bad input parameters to function" ); + case -(MBEDTLS_ERR_MPI_INVALID_CHARACTER): + return( "BIGNUM - There is an invalid character in the digit string" ); + case -(MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL): + return( "BIGNUM - The buffer is too small to write to" ); + case -(MBEDTLS_ERR_MPI_NEGATIVE_VALUE): + return( "BIGNUM - The input arguments are negative or result in illegal output" ); + case -(MBEDTLS_ERR_MPI_DIVISION_BY_ZERO): + return( "BIGNUM - The input argument for division is zero, which is not allowed" ); + case -(MBEDTLS_ERR_MPI_NOT_ACCEPTABLE): + return( "BIGNUM - The input arguments are not acceptable" ); + case -(MBEDTLS_ERR_MPI_ALLOC_FAILED): + return( "BIGNUM - Memory allocation failed" ); +#endif /* MBEDTLS_BIGNUM_C */ + +#if defined(MBEDTLS_BLOWFISH_C) + case -(MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA): + return( "BLOWFISH - Bad input data" ); + case -(MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH): + return( "BLOWFISH - Invalid data input length" ); + case -(MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED): + return( "BLOWFISH - Blowfish hardware accelerator failed" ); +#endif /* MBEDTLS_BLOWFISH_C */ + +#if defined(MBEDTLS_CAMELLIA_C) + case -(MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA): + return( "CAMELLIA - Bad input data" ); + case -(MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH): + return( "CAMELLIA - Invalid data input length" ); + case -(MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED): + return( "CAMELLIA - Camellia hardware accelerator failed" ); +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_CCM_C) + case -(MBEDTLS_ERR_CCM_BAD_INPUT): + return( "CCM - Bad input parameters to the function" ); + case -(MBEDTLS_ERR_CCM_AUTH_FAILED): + return( "CCM - Authenticated decryption failed" ); + case -(MBEDTLS_ERR_CCM_HW_ACCEL_FAILED): + return( "CCM - CCM hardware accelerator failed" ); +#endif /* MBEDTLS_CCM_C */ + +#if defined(MBEDTLS_CHACHA20_C) + case -(MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA): + return( "CHACHA20 - Invalid input parameter(s)" ); + case -(MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE): + return( "CHACHA20 - Feature not available. For example, s part of the API is not implemented" ); + case -(MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED): + return( "CHACHA20 - Chacha20 hardware accelerator failed" ); +#endif /* MBEDTLS_CHACHA20_C */ + +#if defined(MBEDTLS_CHACHAPOLY_C) + case -(MBEDTLS_ERR_CHACHAPOLY_BAD_STATE): + return( "CHACHAPOLY - The requested operation is not permitted in the current state" ); + case -(MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED): + return( "CHACHAPOLY - Authenticated decryption failed: data was not authentic" ); +#endif /* MBEDTLS_CHACHAPOLY_C */ + +#if defined(MBEDTLS_CMAC_C) + case -(MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED): + return( "CMAC - CMAC hardware accelerator failed" ); +#endif /* MBEDTLS_CMAC_C */ + +#if defined(MBEDTLS_CTR_DRBG_C) + case -(MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED): + return( "CTR_DRBG - The entropy source failed" ); + case -(MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG): + return( "CTR_DRBG - The requested random buffer length is too big" ); + case -(MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG): + return( "CTR_DRBG - The input (entropy + additional data) is too large" ); + case -(MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR): + return( "CTR_DRBG - Read or write error in file" ); +#endif /* MBEDTLS_CTR_DRBG_C */ + +#if defined(MBEDTLS_DES_C) + case -(MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH): + return( "DES - The data input has an invalid length" ); + case -(MBEDTLS_ERR_DES_HW_ACCEL_FAILED): + return( "DES - DES hardware accelerator failed" ); +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ENTROPY_C) + case -(MBEDTLS_ERR_ENTROPY_SOURCE_FAILED): + return( "ENTROPY - Critical entropy source failure" ); + case -(MBEDTLS_ERR_ENTROPY_MAX_SOURCES): + return( "ENTROPY - No more sources can be added" ); + case -(MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED): + return( "ENTROPY - No sources have been added to poll" ); + case -(MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE): + return( "ENTROPY - No strong sources have been added to poll" ); + case -(MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR): + return( "ENTROPY - Read/write error in file" ); +#endif /* MBEDTLS_ENTROPY_C */ + +#if defined(MBEDTLS_ERROR_C) + case -(MBEDTLS_ERR_ERROR_GENERIC_ERROR): + return( "ERROR - Generic error" ); + case -(MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED): + return( "ERROR - This is a bug in the library" ); +#endif /* MBEDTLS_ERROR_C */ + +#if defined(MBEDTLS_GCM_C) + case -(MBEDTLS_ERR_GCM_AUTH_FAILED): + return( "GCM - Authenticated decryption failed" ); + case -(MBEDTLS_ERR_GCM_HW_ACCEL_FAILED): + return( "GCM - GCM hardware accelerator failed" ); + case -(MBEDTLS_ERR_GCM_BAD_INPUT): + return( "GCM - Bad input parameters to function" ); +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_HKDF_C) + case -(MBEDTLS_ERR_HKDF_BAD_INPUT_DATA): + return( "HKDF - Bad input parameters to function" ); +#endif /* MBEDTLS_HKDF_C */ + +#if defined(MBEDTLS_HMAC_DRBG_C) + case -(MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG): + return( "HMAC_DRBG - Too many random requested in single call" ); + case -(MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG): + return( "HMAC_DRBG - Input too large (Entropy + additional)" ); + case -(MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR): + return( "HMAC_DRBG - Read/write error in file" ); + case -(MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED): + return( "HMAC_DRBG - The entropy source failed" ); +#endif /* MBEDTLS_HMAC_DRBG_C */ + +#if defined(MBEDTLS_MD2_C) + case -(MBEDTLS_ERR_MD2_HW_ACCEL_FAILED): + return( "MD2 - MD2 hardware accelerator failed" ); +#endif /* MBEDTLS_MD2_C */ + +#if defined(MBEDTLS_MD4_C) + case -(MBEDTLS_ERR_MD4_HW_ACCEL_FAILED): + return( "MD4 - MD4 hardware accelerator failed" ); +#endif /* MBEDTLS_MD4_C */ + +#if defined(MBEDTLS_MD5_C) + case -(MBEDTLS_ERR_MD5_HW_ACCEL_FAILED): + return( "MD5 - MD5 hardware accelerator failed" ); +#endif /* MBEDTLS_MD5_C */ + +#if defined(MBEDTLS_NET_C) + case -(MBEDTLS_ERR_NET_SOCKET_FAILED): + return( "NET - Failed to open a socket" ); + case -(MBEDTLS_ERR_NET_CONNECT_FAILED): + return( "NET - The connection to the given server / port failed" ); + case -(MBEDTLS_ERR_NET_BIND_FAILED): + return( "NET - Binding of the socket failed" ); + case -(MBEDTLS_ERR_NET_LISTEN_FAILED): + return( "NET - Could not listen on the socket" ); + case -(MBEDTLS_ERR_NET_ACCEPT_FAILED): + return( "NET - Could not accept the incoming connection" ); + case -(MBEDTLS_ERR_NET_RECV_FAILED): + return( "NET - Reading information from the socket failed" ); + case -(MBEDTLS_ERR_NET_SEND_FAILED): + return( "NET - Sending information through the socket failed" ); + case -(MBEDTLS_ERR_NET_CONN_RESET): + return( "NET - Connection was reset by peer" ); + case -(MBEDTLS_ERR_NET_UNKNOWN_HOST): + return( "NET - Failed to get an IP address for the given hostname" ); + case -(MBEDTLS_ERR_NET_BUFFER_TOO_SMALL): + return( "NET - Buffer is too small to hold the data" ); + case -(MBEDTLS_ERR_NET_INVALID_CONTEXT): + return( "NET - The context is invalid, eg because it was free()ed" ); + case -(MBEDTLS_ERR_NET_POLL_FAILED): + return( "NET - Polling the net context failed" ); + case -(MBEDTLS_ERR_NET_BAD_INPUT_DATA): + return( "NET - Input invalid" ); +#endif /* MBEDTLS_NET_C */ + +#if defined(MBEDTLS_OID_C) + case -(MBEDTLS_ERR_OID_NOT_FOUND): + return( "OID - OID is not found" ); + case -(MBEDTLS_ERR_OID_BUF_TOO_SMALL): + return( "OID - output buffer is too small" ); +#endif /* MBEDTLS_OID_C */ + +#if defined(MBEDTLS_PADLOCK_C) + case -(MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED): + return( "PADLOCK - Input data should be aligned" ); +#endif /* MBEDTLS_PADLOCK_C */ + +#if defined(MBEDTLS_PLATFORM_C) + case -(MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED): + return( "PLATFORM - Hardware accelerator failed" ); + case -(MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED): + return( "PLATFORM - The requested feature is not supported by the platform" ); +#endif /* MBEDTLS_PLATFORM_C */ + +#if defined(MBEDTLS_POLY1305_C) + case -(MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA): + return( "POLY1305 - Invalid input parameter(s)" ); + case -(MBEDTLS_ERR_POLY1305_FEATURE_UNAVAILABLE): + return( "POLY1305 - Feature not available. For example, s part of the API is not implemented" ); + case -(MBEDTLS_ERR_POLY1305_HW_ACCEL_FAILED): + return( "POLY1305 - Poly1305 hardware accelerator failed" ); +#endif /* MBEDTLS_POLY1305_C */ + +#if defined(MBEDTLS_RIPEMD160_C) + case -(MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED): + return( "RIPEMD160 - RIPEMD160 hardware accelerator failed" ); +#endif /* MBEDTLS_RIPEMD160_C */ + +#if defined(MBEDTLS_SHA1_C) + case -(MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED): + return( "SHA1 - SHA-1 hardware accelerator failed" ); + case -(MBEDTLS_ERR_SHA1_BAD_INPUT_DATA): + return( "SHA1 - SHA-1 input data was malformed" ); +#endif /* MBEDTLS_SHA1_C */ + +#if defined(MBEDTLS_SHA256_C) + case -(MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED): + return( "SHA256 - SHA-256 hardware accelerator failed" ); + case -(MBEDTLS_ERR_SHA256_BAD_INPUT_DATA): + return( "SHA256 - SHA-256 input data was malformed" ); +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + case -(MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED): + return( "SHA512 - SHA-512 hardware accelerator failed" ); + case -(MBEDTLS_ERR_SHA512_BAD_INPUT_DATA): + return( "SHA512 - SHA-512 input data was malformed" ); +#endif /* MBEDTLS_SHA512_C */ + +#if defined(MBEDTLS_THREADING_C) + case -(MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE): + return( "THREADING - The selected feature is not available" ); + case -(MBEDTLS_ERR_THREADING_BAD_INPUT_DATA): + return( "THREADING - Bad input parameters to function" ); + case -(MBEDTLS_ERR_THREADING_MUTEX_ERROR): + return( "THREADING - Locking / unlocking / free failed with error code" ); +#endif /* MBEDTLS_THREADING_C */ + +#if defined(MBEDTLS_XTEA_C) + case -(MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH): + return( "XTEA - The data input has an invalid length" ); + case -(MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED): + return( "XTEA - XTEA hardware accelerator failed" ); +#endif /* MBEDTLS_XTEA_C */ + /* End Auto-Generated Code. */ + + default: + break; + } + + return( NULL ); +} + +void mbedtls_strerror( int ret, char *buf, size_t buflen ) +{ + size_t len; + int use_ret; + const char * high_level_error_description = NULL; + const char * low_level_error_description = NULL; + + if( buflen == 0 ) + return; + + memset( buf, 0x00, buflen ); + + if( ret < 0 ) + ret = -ret; + + if( ret & 0xFF80 ) + { + use_ret = ret & 0xFF80; + + // Translate high level error code. + high_level_error_description = mbedtls_high_level_strerr( ret ); + + if( high_level_error_description == NULL ) + mbedtls_snprintf( buf, buflen, "UNKNOWN ERROR CODE (%04X)", (unsigned int) use_ret ); + else + mbedtls_snprintf( buf, buflen, "%s", high_level_error_description ); + +#if defined(MBEDTLS_SSL_TLS_C) + // Early return in case of a fatal error - do not try to translate low + // level code. + if(use_ret == -(MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE)) + return; +#endif /* MBEDTLS_SSL_TLS_C */ + } + + use_ret = ret & ~0xFF80; + + if( use_ret == 0 ) + return; + + // If high level code is present, make a concatenation between both + // error strings. + // + len = strlen( buf ); + + if( len > 0 ) + { + if( buflen - len < 5 ) + return; + + mbedtls_snprintf( buf + len, buflen - len, " : " ); + + buf += len + 3; + buflen -= len + 3; + } + + // Translate low level error code. + low_level_error_description = mbedtls_low_level_strerr( ret ); + + if( low_level_error_description == NULL ) + mbedtls_snprintf( buf, buflen, "UNKNOWN ERROR CODE (%04X)", (unsigned int) use_ret ); + else + mbedtls_snprintf( buf, buflen, "%s", low_level_error_description ); +} + +#else /* MBEDTLS_ERROR_C */ + +#if defined(MBEDTLS_ERROR_STRERROR_DUMMY) + +/* + * Provide an non-function in case MBEDTLS_ERROR_C is not defined + */ +void mbedtls_strerror( int ret, char *buf, size_t buflen ) +{ + ((void) ret); + + if( buflen > 0 ) + buf[0] = '\0'; +} + +#endif /* MBEDTLS_ERROR_STRERROR_DUMMY */ + +#endif /* MBEDTLS_ERROR_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/gcm.c b/Android/Level4/app/src/main/c/mbedtls/library/gcm.c new file mode 100644 index 0000000..2363e58 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/gcm.c @@ -0,0 +1,1015 @@ +/* + * NIST SP800-38D compliant GCM implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ + +/* + * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf + * + * See also: + * [MGV] http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf + * + * We use the algorithm described as Shoup's method with 4-bit tables in + * [MGV] 4.1, pp. 12-13, to enhance speed without using too much memory. + */ + +#include "common.h" + +#if defined(MBEDTLS_GCM_C) + +#include "mbedtls/gcm.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_AESNI_C) +#include "mbedtls/aesni.h" +#endif + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +#include "mbedtls/aes.h" +#include "mbedtls/platform.h" +#if !defined(MBEDTLS_PLATFORM_C) +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#if !defined(MBEDTLS_GCM_ALT) + +/* Parameter validation macros */ +#define GCM_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_GCM_BAD_INPUT ) +#define GCM_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +/* + * Initialize a context + */ +void mbedtls_gcm_init( mbedtls_gcm_context *ctx ) +{ + GCM_VALIDATE( ctx != NULL ); + memset( ctx, 0, sizeof( mbedtls_gcm_context ) ); +} + +/* + * Precompute small multiples of H, that is set + * HH[i] || HL[i] = H times i, + * where i is seen as a field element as in [MGV], ie high-order bits + * correspond to low powers of P. The result is stored in the same way, that + * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL + * corresponds to P^127. + */ +static int gcm_gen_table( mbedtls_gcm_context *ctx ) +{ + int ret, i, j; + uint64_t hi, lo; + uint64_t vl, vh; + unsigned char h[16]; + size_t olen = 0; + + memset( h, 0, 16 ); + if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, h, 16, h, &olen ) ) != 0 ) + return( ret ); + + /* pack h as two 64-bits ints, big-endian */ + GET_UINT32_BE( hi, h, 0 ); + GET_UINT32_BE( lo, h, 4 ); + vh = (uint64_t) hi << 32 | lo; + + GET_UINT32_BE( hi, h, 8 ); + GET_UINT32_BE( lo, h, 12 ); + vl = (uint64_t) hi << 32 | lo; + + /* 8 = 1000 corresponds to 1 in GF(2^128) */ + ctx->HL[8] = vl; + ctx->HH[8] = vh; + +#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) + /* With CLMUL support, we need only h, not the rest of the table */ + if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL ) ) + return( 0 ); +#endif + + /* 0 corresponds to 0 in GF(2^128) */ + ctx->HH[0] = 0; + ctx->HL[0] = 0; + + for( i = 4; i > 0; i >>= 1 ) + { + uint32_t T = ( vl & 1 ) * 0xe1000000U; + vl = ( vh << 63 ) | ( vl >> 1 ); + vh = ( vh >> 1 ) ^ ( (uint64_t) T << 32); + + ctx->HL[i] = vl; + ctx->HH[i] = vh; + } + + for( i = 2; i <= 8; i *= 2 ) + { + uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i; + vh = *HiH; + vl = *HiL; + for( j = 1; j < i; j++ ) + { + HiH[j] = vh ^ ctx->HH[j]; + HiL[j] = vl ^ ctx->HL[j]; + } + } + + return( 0 ); +} + +int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const mbedtls_cipher_info_t *cipher_info; + + GCM_VALIDATE_RET( ctx != NULL ); + GCM_VALIDATE_RET( key != NULL ); + GCM_VALIDATE_RET( keybits == 128 || keybits == 192 || keybits == 256 ); + + cipher_info = mbedtls_cipher_info_from_values( cipher, keybits, + MBEDTLS_MODE_ECB ); + if( cipher_info == NULL ) + return( MBEDTLS_ERR_GCM_BAD_INPUT ); + + if( cipher_info->block_size != 16 ) + return( MBEDTLS_ERR_GCM_BAD_INPUT ); + + mbedtls_cipher_free( &ctx->cipher_ctx ); + + if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits, + MBEDTLS_ENCRYPT ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = gcm_gen_table( ctx ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +/* + * Shoup's method for multiplication use this table with + * last4[x] = x times P^128 + * where x and last4[x] are seen as elements of GF(2^128) as in [MGV] + */ +static const uint64_t last4[16] = +{ + 0x0000, 0x1c20, 0x3840, 0x2460, + 0x7080, 0x6ca0, 0x48c0, 0x54e0, + 0xe100, 0xfd20, 0xd940, 0xc560, + 0x9180, 0x8da0, 0xa9c0, 0xb5e0 +}; + +/* + * Sets output to x times H using the precomputed tables. + * x and output are seen as elements of GF(2^128) as in [MGV]. + */ +static void gcm_mult( mbedtls_gcm_context *ctx, const unsigned char x[16], + unsigned char output[16] ) +{ + int i = 0; + unsigned char lo, hi, rem; + uint64_t zh, zl; + +#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) + if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL ) ) { + unsigned char h[16]; + + PUT_UINT32_BE( ctx->HH[8] >> 32, h, 0 ); + PUT_UINT32_BE( ctx->HH[8], h, 4 ); + PUT_UINT32_BE( ctx->HL[8] >> 32, h, 8 ); + PUT_UINT32_BE( ctx->HL[8], h, 12 ); + + mbedtls_aesni_gcm_mult( output, x, h ); + return; + } +#endif /* MBEDTLS_AESNI_C && MBEDTLS_HAVE_X86_64 */ + + lo = x[15] & 0xf; + + zh = ctx->HH[lo]; + zl = ctx->HL[lo]; + + for( i = 15; i >= 0; i-- ) + { + lo = x[i] & 0xf; + hi = ( x[i] >> 4 ) & 0xf; + + if( i != 15 ) + { + rem = (unsigned char) zl & 0xf; + zl = ( zh << 60 ) | ( zl >> 4 ); + zh = ( zh >> 4 ); + zh ^= (uint64_t) last4[rem] << 48; + zh ^= ctx->HH[lo]; + zl ^= ctx->HL[lo]; + + } + + rem = (unsigned char) zl & 0xf; + zl = ( zh << 60 ) | ( zl >> 4 ); + zh = ( zh >> 4 ); + zh ^= (uint64_t) last4[rem] << 48; + zh ^= ctx->HH[hi]; + zl ^= ctx->HL[hi]; + } + + PUT_UINT32_BE( zh >> 32, output, 0 ); + PUT_UINT32_BE( zh, output, 4 ); + PUT_UINT32_BE( zl >> 32, output, 8 ); + PUT_UINT32_BE( zl, output, 12 ); +} + +int mbedtls_gcm_starts( mbedtls_gcm_context *ctx, + int mode, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char work_buf[16]; + size_t i; + const unsigned char *p; + size_t use_len, olen = 0; + + GCM_VALIDATE_RET( ctx != NULL ); + GCM_VALIDATE_RET( iv != NULL ); + GCM_VALIDATE_RET( add_len == 0 || add != NULL ); + + /* IV and AD are limited to 2^64 bits, so 2^61 bytes */ + /* IV is not allowed to be zero length */ + if( iv_len == 0 || + ( (uint64_t) iv_len ) >> 61 != 0 || + ( (uint64_t) add_len ) >> 61 != 0 ) + { + return( MBEDTLS_ERR_GCM_BAD_INPUT ); + } + + memset( ctx->y, 0x00, sizeof(ctx->y) ); + memset( ctx->buf, 0x00, sizeof(ctx->buf) ); + + ctx->mode = mode; + ctx->len = 0; + ctx->add_len = 0; + + if( iv_len == 12 ) + { + memcpy( ctx->y, iv, iv_len ); + ctx->y[15] = 1; + } + else + { + memset( work_buf, 0x00, 16 ); + PUT_UINT32_BE( iv_len * 8, work_buf, 12 ); + + p = iv; + while( iv_len > 0 ) + { + use_len = ( iv_len < 16 ) ? iv_len : 16; + + for( i = 0; i < use_len; i++ ) + ctx->y[i] ^= p[i]; + + gcm_mult( ctx, ctx->y, ctx->y ); + + iv_len -= use_len; + p += use_len; + } + + for( i = 0; i < 16; i++ ) + ctx->y[i] ^= work_buf[i]; + + gcm_mult( ctx, ctx->y, ctx->y ); + } + + if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, + ctx->base_ectr, &olen ) ) != 0 ) + { + return( ret ); + } + + ctx->add_len = add_len; + p = add; + while( add_len > 0 ) + { + use_len = ( add_len < 16 ) ? add_len : 16; + + for( i = 0; i < use_len; i++ ) + ctx->buf[i] ^= p[i]; + + gcm_mult( ctx, ctx->buf, ctx->buf ); + + add_len -= use_len; + p += use_len; + } + + return( 0 ); +} + +int mbedtls_gcm_update( mbedtls_gcm_context *ctx, + size_t length, + const unsigned char *input, + unsigned char *output ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char ectr[16]; + size_t i; + const unsigned char *p; + unsigned char *out_p = output; + size_t use_len, olen = 0; + + GCM_VALIDATE_RET( ctx != NULL ); + GCM_VALIDATE_RET( length == 0 || input != NULL ); + GCM_VALIDATE_RET( length == 0 || output != NULL ); + + if( output > input && (size_t) ( output - input ) < length ) + return( MBEDTLS_ERR_GCM_BAD_INPUT ); + + /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes + * Also check for possible overflow */ + if( ctx->len + length < ctx->len || + (uint64_t) ctx->len + length > 0xFFFFFFFE0ull ) + { + return( MBEDTLS_ERR_GCM_BAD_INPUT ); + } + + ctx->len += length; + + p = input; + while( length > 0 ) + { + use_len = ( length < 16 ) ? length : 16; + + for( i = 16; i > 12; i-- ) + if( ++ctx->y[i - 1] != 0 ) + break; + + if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ectr, + &olen ) ) != 0 ) + { + return( ret ); + } + + for( i = 0; i < use_len; i++ ) + { + if( ctx->mode == MBEDTLS_GCM_DECRYPT ) + ctx->buf[i] ^= p[i]; + out_p[i] = ectr[i] ^ p[i]; + if( ctx->mode == MBEDTLS_GCM_ENCRYPT ) + ctx->buf[i] ^= out_p[i]; + } + + gcm_mult( ctx, ctx->buf, ctx->buf ); + + length -= use_len; + p += use_len; + out_p += use_len; + } + + return( 0 ); +} + +int mbedtls_gcm_finish( mbedtls_gcm_context *ctx, + unsigned char *tag, + size_t tag_len ) +{ + unsigned char work_buf[16]; + size_t i; + uint64_t orig_len; + uint64_t orig_add_len; + + GCM_VALIDATE_RET( ctx != NULL ); + GCM_VALIDATE_RET( tag != NULL ); + + orig_len = ctx->len * 8; + orig_add_len = ctx->add_len * 8; + + if( tag_len > 16 || tag_len < 4 ) + return( MBEDTLS_ERR_GCM_BAD_INPUT ); + + memcpy( tag, ctx->base_ectr, tag_len ); + + if( orig_len || orig_add_len ) + { + memset( work_buf, 0x00, 16 ); + + PUT_UINT32_BE( ( orig_add_len >> 32 ), work_buf, 0 ); + PUT_UINT32_BE( ( orig_add_len ), work_buf, 4 ); + PUT_UINT32_BE( ( orig_len >> 32 ), work_buf, 8 ); + PUT_UINT32_BE( ( orig_len ), work_buf, 12 ); + + for( i = 0; i < 16; i++ ) + ctx->buf[i] ^= work_buf[i]; + + gcm_mult( ctx, ctx->buf, ctx->buf ); + + for( i = 0; i < tag_len; i++ ) + tag[i] ^= ctx->buf[i]; + } + + return( 0 ); +} + +int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx, + int mode, + size_t length, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len, + const unsigned char *input, + unsigned char *output, + size_t tag_len, + unsigned char *tag ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + GCM_VALIDATE_RET( ctx != NULL ); + GCM_VALIDATE_RET( iv != NULL ); + GCM_VALIDATE_RET( add_len == 0 || add != NULL ); + GCM_VALIDATE_RET( length == 0 || input != NULL ); + GCM_VALIDATE_RET( length == 0 || output != NULL ); + GCM_VALIDATE_RET( tag != NULL ); + + if( ( ret = mbedtls_gcm_starts( ctx, mode, iv, iv_len, add, add_len ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_gcm_update( ctx, length, input, output ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_gcm_finish( ctx, tag, tag_len ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx, + size_t length, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len, + const unsigned char *tag, + size_t tag_len, + const unsigned char *input, + unsigned char *output ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char check_tag[16]; + size_t i; + int diff; + + GCM_VALIDATE_RET( ctx != NULL ); + GCM_VALIDATE_RET( iv != NULL ); + GCM_VALIDATE_RET( add_len == 0 || add != NULL ); + GCM_VALIDATE_RET( tag != NULL ); + GCM_VALIDATE_RET( length == 0 || input != NULL ); + GCM_VALIDATE_RET( length == 0 || output != NULL ); + + if( ( ret = mbedtls_gcm_crypt_and_tag( ctx, MBEDTLS_GCM_DECRYPT, length, + iv, iv_len, add, add_len, + input, output, tag_len, check_tag ) ) != 0 ) + { + return( ret ); + } + + /* Check tag in "constant-time" */ + for( diff = 0, i = 0; i < tag_len; i++ ) + diff |= tag[i] ^ check_tag[i]; + + if( diff != 0 ) + { + mbedtls_platform_zeroize( output, length ); + return( MBEDTLS_ERR_GCM_AUTH_FAILED ); + } + + return( 0 ); +} + +void mbedtls_gcm_free( mbedtls_gcm_context *ctx ) +{ + if( ctx == NULL ) + return; + mbedtls_cipher_free( &ctx->cipher_ctx ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_gcm_context ) ); +} + +#endif /* !MBEDTLS_GCM_ALT */ + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +/* + * AES-GCM test vectors from: + * + * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip + */ +#define MAX_TESTS 6 + +static const int key_index_test_data[MAX_TESTS] = + { 0, 0, 1, 1, 1, 1 }; + +static const unsigned char key_test_data[MAX_TESTS][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 }, + { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 }, +}; + +static const size_t iv_len_test_data[MAX_TESTS] = + { 12, 12, 12, 12, 8, 60 }; + +static const int iv_index_test_data[MAX_TESTS] = + { 0, 0, 1, 1, 1, 2 }; + +static const unsigned char iv_test_data[MAX_TESTS][64] = +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }, + { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, + 0xde, 0xca, 0xf8, 0x88 }, + { 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 }, +}; + +static const size_t add_len_test_data[MAX_TESTS] = + { 0, 0, 0, 20, 20, 20 }; + +static const int add_index_test_data[MAX_TESTS] = + { 0, 0, 0, 1, 1, 1 }; + +static const unsigned char additional_test_data[MAX_TESTS][64] = +{ + { 0x00 }, + { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xab, 0xad, 0xda, 0xd2 }, +}; + +static const size_t pt_len_test_data[MAX_TESTS] = + { 0, 16, 64, 60, 60, 60 }; + +static const int pt_index_test_data[MAX_TESTS] = + { 0, 0, 1, 1, 1, 1 }; + +static const unsigned char pt_test_data[MAX_TESTS][64] = +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 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 }, +}; + +static const unsigned char ct_test_data[MAX_TESTS * 3][64] = +{ + { 0x00 }, + { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92, + 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 }, + { 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 }, + { 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 }, + { 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 }, + { 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 }, + { 0x00 }, + { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41, + 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 }, + { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41, + 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57, + 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84, + 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c, + 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25, + 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47, + 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9, + 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 }, + { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41, + 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57, + 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84, + 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c, + 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25, + 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47, + 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9, + 0xcc, 0xda, 0x27, 0x10 }, + { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54, + 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8, + 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f, + 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57, + 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75, + 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9, + 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f, + 0xa0, 0xf0, 0x62, 0xf7 }, + { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c, + 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff, + 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef, + 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45, + 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9, + 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3, + 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7, + 0xe9, 0xb7, 0x37, 0x3b }, + { 0x00 }, + { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e, + 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 }, + { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, + 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d, + 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, + 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa, + 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, + 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, + 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a, + 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad }, + { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, + 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d, + 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, + 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa, + 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, + 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, + 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a, + 0xbc, 0xc9, 0xf6, 0x62 }, + { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32, + 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb, + 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa, + 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0, + 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0, + 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78, + 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99, + 0xf4, 0x7c, 0x9b, 0x1f }, + { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1, + 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20, + 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19, + 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4, + 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45, + 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde, + 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e, + 0x44, 0xae, 0x7e, 0x3f }, +}; + +static const unsigned char tag_test_data[MAX_TESTS * 3][16] = +{ + { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61, + 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a }, + { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd, + 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf }, + { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6, + 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 }, + { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb, + 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 }, + { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85, + 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb }, + { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa, + 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 }, + { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b, + 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 }, + { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab, + 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb }, + { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf, + 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 }, + { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f, + 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c }, + { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24, + 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 }, + { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb, + 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 }, + { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9, + 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b }, + { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0, + 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 }, + { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd, + 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c }, + { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68, + 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b }, + { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4, + 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 }, + { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0, + 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a }, +}; + +int mbedtls_gcm_self_test( int verbose ) +{ + mbedtls_gcm_context ctx; + unsigned char buf[64]; + unsigned char tag_buf[16]; + int i, j, ret; + mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES; + + for( j = 0; j < 3; j++ ) + { + int key_len = 128 + 64 * j; + + for( i = 0; i < MAX_TESTS; i++ ) + { + mbedtls_gcm_init( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( " AES-GCM-%3d #%d (%s): ", + key_len, i, "enc" ); + + ret = mbedtls_gcm_setkey( &ctx, cipher, + key_test_data[key_index_test_data[i]], + key_len ); + /* + * AES-192 is an optional feature that may be unavailable when + * there is an alternative underlying implementation i.e. when + * MBEDTLS_AES_ALT is defined. + */ + if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && key_len == 192 ) + { + mbedtls_printf( "skipped\n" ); + break; + } + else if( ret != 0 ) + { + goto exit; + } + + ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_ENCRYPT, + pt_len_test_data[i], + iv_test_data[iv_index_test_data[i]], + iv_len_test_data[i], + additional_test_data[add_index_test_data[i]], + add_len_test_data[i], + pt_test_data[pt_index_test_data[i]], + buf, 16, tag_buf ); + if( ret != 0 ) + goto exit; + + if ( memcmp( buf, ct_test_data[j * 6 + i], + pt_len_test_data[i] ) != 0 || + memcmp( tag_buf, tag_test_data[j * 6 + i], 16 ) != 0 ) + { + ret = 1; + goto exit; + } + + mbedtls_gcm_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + mbedtls_gcm_init( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( " AES-GCM-%3d #%d (%s): ", + key_len, i, "dec" ); + + ret = mbedtls_gcm_setkey( &ctx, cipher, + key_test_data[key_index_test_data[i]], + key_len ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_DECRYPT, + pt_len_test_data[i], + iv_test_data[iv_index_test_data[i]], + iv_len_test_data[i], + additional_test_data[add_index_test_data[i]], + add_len_test_data[i], + ct_test_data[j * 6 + i], buf, 16, tag_buf ); + + if( ret != 0 ) + goto exit; + + if( memcmp( buf, pt_test_data[pt_index_test_data[i]], + pt_len_test_data[i] ) != 0 || + memcmp( tag_buf, tag_test_data[j * 6 + i], 16 ) != 0 ) + { + ret = 1; + goto exit; + } + + mbedtls_gcm_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + mbedtls_gcm_init( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( " AES-GCM-%3d #%d split (%s): ", + key_len, i, "enc" ); + + ret = mbedtls_gcm_setkey( &ctx, cipher, + key_test_data[key_index_test_data[i]], + key_len ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_ENCRYPT, + iv_test_data[iv_index_test_data[i]], + iv_len_test_data[i], + additional_test_data[add_index_test_data[i]], + add_len_test_data[i] ); + if( ret != 0 ) + goto exit; + + if( pt_len_test_data[i] > 32 ) + { + size_t rest_len = pt_len_test_data[i] - 32; + ret = mbedtls_gcm_update( &ctx, 32, + pt_test_data[pt_index_test_data[i]], + buf ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_gcm_update( &ctx, rest_len, + pt_test_data[pt_index_test_data[i]] + 32, + buf + 32 ); + if( ret != 0 ) + goto exit; + } + else + { + ret = mbedtls_gcm_update( &ctx, pt_len_test_data[i], + pt_test_data[pt_index_test_data[i]], + buf ); + if( ret != 0 ) + goto exit; + } + + ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 ); + if( ret != 0 ) + goto exit; + + if( memcmp( buf, ct_test_data[j * 6 + i], + pt_len_test_data[i] ) != 0 || + memcmp( tag_buf, tag_test_data[j * 6 + i], 16 ) != 0 ) + { + ret = 1; + goto exit; + } + + mbedtls_gcm_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + mbedtls_gcm_init( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( " AES-GCM-%3d #%d split (%s): ", + key_len, i, "dec" ); + + ret = mbedtls_gcm_setkey( &ctx, cipher, + key_test_data[key_index_test_data[i]], + key_len ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_DECRYPT, + iv_test_data[iv_index_test_data[i]], + iv_len_test_data[i], + additional_test_data[add_index_test_data[i]], + add_len_test_data[i] ); + if( ret != 0 ) + goto exit; + + if( pt_len_test_data[i] > 32 ) + { + size_t rest_len = pt_len_test_data[i] - 32; + ret = mbedtls_gcm_update( &ctx, 32, ct_test_data[j * 6 + i], + buf ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_gcm_update( &ctx, rest_len, + ct_test_data[j * 6 + i] + 32, + buf + 32 ); + if( ret != 0 ) + goto exit; + } + else + { + ret = mbedtls_gcm_update( &ctx, pt_len_test_data[i], + ct_test_data[j * 6 + i], + buf ); + if( ret != 0 ) + goto exit; + } + + ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 ); + if( ret != 0 ) + goto exit; + + if( memcmp( buf, pt_test_data[pt_index_test_data[i]], + pt_len_test_data[i] ) != 0 || + memcmp( tag_buf, tag_test_data[j * 6 + i], 16 ) != 0 ) + { + ret = 1; + goto exit; + } + + mbedtls_gcm_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + ret = 0; + +exit: + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + mbedtls_gcm_free( &ctx ); + } + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#endif /* MBEDTLS_GCM_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/havege.c b/Android/Level4/app/src/main/c/mbedtls/library/havege.c new file mode 100644 index 0000000..2a360a1 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/havege.c @@ -0,0 +1,237 @@ +/** + * \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ +/* + * The HAVEGE RNG was designed by Andre Seznec in 2002. + * + * http://www.irisa.fr/caps/projects/hipsor/publi.php + * + * Contact: seznec(at)irisa_dot_fr - orocheco(at)irisa_dot_fr + */ + +#include "common.h" + +#if defined(MBEDTLS_HAVEGE_C) + +#include "mbedtls/havege.h" +#include "mbedtls/timing.h" +#include "mbedtls/platform_util.h" + +#include +#include + +/* ------------------------------------------------------------------------ + * On average, one iteration accesses two 8-word blocks in the havege WALK + * table, and generates 16 words in the RES array. + * + * The data read in the WALK table is updated and permuted after each use. + * The result of the hardware clock counter read is used for this update. + * + * 25 conditional tests are present. The conditional tests are grouped in + * two nested groups of 12 conditional tests and 1 test that controls the + * permutation; on average, there should be 6 tests executed and 3 of them + * should be mispredicted. + * ------------------------------------------------------------------------ + */ + +#define SWAP(X,Y) { uint32_t *T = (X); (X) = (Y); (Y) = T; } + +#define TST1_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1; +#define TST2_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1; + +#define TST1_LEAVE U1++; } +#define TST2_LEAVE U2++; } + +#define ONE_ITERATION \ + \ + PTEST = PT1 >> 20; \ + \ + TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \ + TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \ + TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \ + \ + TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \ + TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \ + TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \ + \ + PTX = (PT1 >> 18) & 7; \ + PT1 &= 0x1FFF; \ + PT2 &= 0x1FFF; \ + CLK = (uint32_t) mbedtls_timing_hardclock(); \ + \ + i = 0; \ + A = &WALK[PT1 ]; RES[i++] ^= *A; \ + B = &WALK[PT2 ]; RES[i++] ^= *B; \ + C = &WALK[PT1 ^ 1]; RES[i++] ^= *C; \ + D = &WALK[PT2 ^ 4]; RES[i++] ^= *D; \ + \ + IN = (*A >> (1)) ^ (*A << (31)) ^ CLK; \ + *A = (*B >> (2)) ^ (*B << (30)) ^ CLK; \ + *B = IN ^ U1; \ + *C = (*C >> (3)) ^ (*C << (29)) ^ CLK; \ + *D = (*D >> (4)) ^ (*D << (28)) ^ CLK; \ + \ + A = &WALK[PT1 ^ 2]; RES[i++] ^= *A; \ + B = &WALK[PT2 ^ 2]; RES[i++] ^= *B; \ + C = &WALK[PT1 ^ 3]; RES[i++] ^= *C; \ + D = &WALK[PT2 ^ 6]; RES[i++] ^= *D; \ + \ + if( PTEST & 1 ) SWAP( A, C ); \ + \ + IN = (*A >> (5)) ^ (*A << (27)) ^ CLK; \ + *A = (*B >> (6)) ^ (*B << (26)) ^ CLK; \ + *B = IN; CLK = (uint32_t) mbedtls_timing_hardclock(); \ + *C = (*C >> (7)) ^ (*C << (25)) ^ CLK; \ + *D = (*D >> (8)) ^ (*D << (24)) ^ CLK; \ + \ + A = &WALK[PT1 ^ 4]; \ + B = &WALK[PT2 ^ 1]; \ + \ + PTEST = PT2 >> 1; \ + \ + PT2 = (RES[(i - 8) ^ PTY] ^ WALK[PT2 ^ PTY ^ 7]); \ + PT2 = ((PT2 & 0x1FFF) & (~8)) ^ ((PT1 ^ 8) & 0x8); \ + PTY = (PT2 >> 10) & 7; \ + \ + TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \ + TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \ + TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \ + \ + TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \ + TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \ + TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \ + \ + C = &WALK[PT1 ^ 5]; \ + D = &WALK[PT2 ^ 5]; \ + \ + RES[i++] ^= *A; \ + RES[i++] ^= *B; \ + RES[i++] ^= *C; \ + RES[i++] ^= *D; \ + \ + IN = (*A >> ( 9)) ^ (*A << (23)) ^ CLK; \ + *A = (*B >> (10)) ^ (*B << (22)) ^ CLK; \ + *B = IN ^ U2; \ + *C = (*C >> (11)) ^ (*C << (21)) ^ CLK; \ + *D = (*D >> (12)) ^ (*D << (20)) ^ CLK; \ + \ + A = &WALK[PT1 ^ 6]; RES[i++] ^= *A; \ + B = &WALK[PT2 ^ 3]; RES[i++] ^= *B; \ + C = &WALK[PT1 ^ 7]; RES[i++] ^= *C; \ + D = &WALK[PT2 ^ 7]; RES[i++] ^= *D; \ + \ + IN = (*A >> (13)) ^ (*A << (19)) ^ CLK; \ + *A = (*B >> (14)) ^ (*B << (18)) ^ CLK; \ + *B = IN; \ + *C = (*C >> (15)) ^ (*C << (17)) ^ CLK; \ + *D = (*D >> (16)) ^ (*D << (16)) ^ CLK; \ + \ + PT1 = ( RES[( i - 8 ) ^ PTX] ^ \ + WALK[PT1 ^ PTX ^ 7] ) & (~1); \ + PT1 ^= (PT2 ^ 0x10) & 0x10; \ + \ + for( n++, i = 0; i < 16; i++ ) \ + hs->pool[n % MBEDTLS_HAVEGE_COLLECT_SIZE] ^= RES[i]; + +/* + * Entropy gathering function + */ +static void havege_fill( mbedtls_havege_state *hs ) +{ + size_t n = 0; + size_t i; + uint32_t U1, U2, *A, *B, *C, *D; + uint32_t PT1, PT2, *WALK, RES[16]; + uint32_t PTX, PTY, CLK, PTEST, IN; + + WALK = hs->WALK; + PT1 = hs->PT1; + PT2 = hs->PT2; + + PTX = U1 = 0; + PTY = U2 = 0; + + (void)PTX; + + memset( RES, 0, sizeof( RES ) ); + + while( n < MBEDTLS_HAVEGE_COLLECT_SIZE * 4 ) + { + ONE_ITERATION + ONE_ITERATION + ONE_ITERATION + ONE_ITERATION + } + + hs->PT1 = PT1; + hs->PT2 = PT2; + + hs->offset[0] = 0; + hs->offset[1] = MBEDTLS_HAVEGE_COLLECT_SIZE / 2; +} + +/* + * HAVEGE initialization + */ +void mbedtls_havege_init( mbedtls_havege_state *hs ) +{ + memset( hs, 0, sizeof( mbedtls_havege_state ) ); + + havege_fill( hs ); +} + +void mbedtls_havege_free( mbedtls_havege_state *hs ) +{ + if( hs == NULL ) + return; + + mbedtls_platform_zeroize( hs, sizeof( mbedtls_havege_state ) ); +} + +/* + * HAVEGE rand function + */ +int mbedtls_havege_random( void *p_rng, unsigned char *buf, size_t len ) +{ + uint32_t val; + size_t use_len; + mbedtls_havege_state *hs = (mbedtls_havege_state *) p_rng; + unsigned char *p = buf; + + while( len > 0 ) + { + use_len = len; + if( use_len > sizeof( val ) ) + use_len = sizeof( val ); + + if( hs->offset[1] >= MBEDTLS_HAVEGE_COLLECT_SIZE ) + havege_fill( hs ); + + val = hs->pool[hs->offset[0]++]; + val ^= hs->pool[hs->offset[1]++]; + + memcpy( p, &val, use_len ); + + len -= use_len; + p += use_len; + } + + return( 0 ); +} + +#endif /* MBEDTLS_HAVEGE_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/hkdf.c b/Android/Level4/app/src/main/c/mbedtls/library/hkdf.c new file mode 100644 index 0000000..5013729 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/hkdf.c @@ -0,0 +1,189 @@ +/* + * HKDF implementation -- RFC 5869 + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 "common.h" + +#if defined(MBEDTLS_HKDF_C) + +#include +#include "mbedtls/hkdf.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +int mbedtls_hkdf( const mbedtls_md_info_t *md, const unsigned char *salt, + size_t salt_len, const unsigned char *ikm, size_t ikm_len, + const unsigned char *info, size_t info_len, + unsigned char *okm, size_t okm_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char prk[MBEDTLS_MD_MAX_SIZE]; + + ret = mbedtls_hkdf_extract( md, salt, salt_len, ikm, ikm_len, prk ); + + if( ret == 0 ) + { + ret = mbedtls_hkdf_expand( md, prk, mbedtls_md_get_size( md ), + info, info_len, okm, okm_len ); + } + + mbedtls_platform_zeroize( prk, sizeof( prk ) ); + + return( ret ); +} + +int mbedtls_hkdf_extract( const mbedtls_md_info_t *md, + const unsigned char *salt, size_t salt_len, + const unsigned char *ikm, size_t ikm_len, + unsigned char *prk ) +{ + unsigned char null_salt[MBEDTLS_MD_MAX_SIZE] = { '\0' }; + + if( salt == NULL ) + { + size_t hash_len; + + if( salt_len != 0 ) + { + return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA; + } + + hash_len = mbedtls_md_get_size( md ); + + if( hash_len == 0 ) + { + return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA; + } + + salt = null_salt; + salt_len = hash_len; + } + + return( mbedtls_md_hmac( md, salt, salt_len, ikm, ikm_len, prk ) ); +} + +int mbedtls_hkdf_expand( const mbedtls_md_info_t *md, const unsigned char *prk, + size_t prk_len, const unsigned char *info, + size_t info_len, unsigned char *okm, size_t okm_len ) +{ + size_t hash_len; + size_t where = 0; + size_t n; + size_t t_len = 0; + size_t i; + int ret = 0; + mbedtls_md_context_t ctx; + unsigned char t[MBEDTLS_MD_MAX_SIZE]; + + if( okm == NULL ) + { + return( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA ); + } + + hash_len = mbedtls_md_get_size( md ); + + if( prk_len < hash_len || hash_len == 0 ) + { + return( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA ); + } + + if( info == NULL ) + { + info = (const unsigned char *) ""; + info_len = 0; + } + + n = okm_len / hash_len; + + if( okm_len % hash_len != 0 ) + { + n++; + } + + /* + * Per RFC 5869 Section 2.3, okm_len must not exceed + * 255 times the hash length + */ + if( n > 255 ) + { + return( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA ); + } + + mbedtls_md_init( &ctx ); + + if( ( ret = mbedtls_md_setup( &ctx, md, 1 ) ) != 0 ) + { + goto exit; + } + + memset( t, 0, hash_len ); + + /* + * Compute T = T(1) | T(2) | T(3) | ... | T(N) + * Where T(N) is defined in RFC 5869 Section 2.3 + */ + for( i = 1; i <= n; i++ ) + { + size_t num_to_copy; + unsigned char c = i & 0xff; + + ret = mbedtls_md_hmac_starts( &ctx, prk, prk_len ); + if( ret != 0 ) + { + goto exit; + } + + ret = mbedtls_md_hmac_update( &ctx, t, t_len ); + if( ret != 0 ) + { + goto exit; + } + + ret = mbedtls_md_hmac_update( &ctx, info, info_len ); + if( ret != 0 ) + { + goto exit; + } + + /* The constant concatenated to the end of each T(n) is a single octet. + * */ + ret = mbedtls_md_hmac_update( &ctx, &c, 1 ); + if( ret != 0 ) + { + goto exit; + } + + ret = mbedtls_md_hmac_finish( &ctx, t ); + if( ret != 0 ) + { + goto exit; + } + + num_to_copy = i != n ? hash_len : okm_len - where; + memcpy( okm + where, t, num_to_copy ); + where += hash_len; + t_len = hash_len; + } + +exit: + mbedtls_md_free( &ctx ); + mbedtls_platform_zeroize( t, sizeof( t ) ); + + return( ret ); +} + +#endif /* MBEDTLS_HKDF_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/hmac_drbg.c b/Android/Level4/app/src/main/c/mbedtls/library/hmac_drbg.c new file mode 100644 index 0000000..aa3e251 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/hmac_drbg.c @@ -0,0 +1,620 @@ +/* + * HMAC_DRBG implementation (NIST SP 800-90) + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ + +/* + * The NIST SP 800-90A DRBGs are described in the following publication. + * http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf + * References below are based on rev. 1 (January 2012). + */ + +#include "common.h" + +#if defined(MBEDTLS_HMAC_DRBG_C) + +#include "mbedtls/hmac_drbg.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_SELF_TEST */ +#endif /* MBEDTLS_PLATFORM_C */ + +/* + * HMAC_DRBG context initialization + */ +void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_hmac_drbg_context ) ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif +} + +/* + * HMAC_DRBG update, using optional additional data (10.1.2.2) + */ +int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, + size_t add_len ) +{ + size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info ); + unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1; + unsigned char sep[1]; + unsigned char K[MBEDTLS_MD_MAX_SIZE]; + int ret = MBEDTLS_ERR_MD_BAD_INPUT_DATA; + + for( sep[0] = 0; sep[0] < rounds; sep[0]++ ) + { + /* Step 1 or 4 */ + if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx, + ctx->V, md_len ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx, + sep, 1 ) ) != 0 ) + goto exit; + if( rounds == 2 ) + { + if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx, + additional, add_len ) ) != 0 ) + goto exit; + } + if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, K ) ) != 0 ) + goto exit; + + /* Step 2 or 5 */ + if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx, + ctx->V, md_len ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 ) + goto exit; + } + +exit: + mbedtls_platform_zeroize( K, sizeof( K ) ); + return( ret ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, + size_t add_len ) +{ + (void) mbedtls_hmac_drbg_update_ret( ctx, additional, add_len ); +} +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/* + * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA) + */ +int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx, + const mbedtls_md_info_t * md_info, + const unsigned char *data, size_t data_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 ) + return( ret ); + + /* + * Set initial working state. + * Use the V memory location, which is currently all 0, to initialize the + * MD context with an all-zero key. Then set V to its initial value. + */ + if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, + mbedtls_md_get_size( md_info ) ) ) != 0 ) + return( ret ); + memset( ctx->V, 0x01, mbedtls_md_get_size( md_info ) ); + + if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, data, data_len ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +/* + * Internal function used both for seeding and reseeding the DRBG. + * Comments starting with arabic numbers refer to section 10.1.2.4 + * of SP800-90A, while roman numbers refer to section 9.2. + */ +static int hmac_drbg_reseed_core( mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, size_t len, + int use_nonce ) +{ + unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT]; + size_t seedlen = 0; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + { + size_t total_entropy_len; + + if( use_nonce == 0 ) + total_entropy_len = ctx->entropy_len; + else + total_entropy_len = ctx->entropy_len * 3 / 2; + + /* III. Check input length */ + if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT || + total_entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT ) + { + return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG ); + } + } + + memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT ); + + /* IV. Gather entropy_len bytes of entropy for the seed */ + if( ( ret = ctx->f_entropy( ctx->p_entropy, + seed, ctx->entropy_len ) ) != 0 ) + { + return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED ); + } + seedlen += ctx->entropy_len; + + /* For initial seeding, allow adding of nonce generated + * from the entropy source. See Sect 8.6.7 in SP800-90A. */ + if( use_nonce ) + { + /* Note: We don't merge the two calls to f_entropy() in order + * to avoid requesting too much entropy from f_entropy() + * at once. Specifically, if the underlying digest is not + * SHA-1, 3 / 2 * entropy_len is at least 36 Bytes, which + * is larger than the maximum of 32 Bytes that our own + * entropy source implementation can emit in a single + * call in configurations disabling SHA-512. */ + if( ( ret = ctx->f_entropy( ctx->p_entropy, + seed + seedlen, + ctx->entropy_len / 2 ) ) != 0 ) + { + return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED ); + } + + seedlen += ctx->entropy_len / 2; + } + + + /* 1. Concatenate entropy and additional data if any */ + if( additional != NULL && len != 0 ) + { + memcpy( seed + seedlen, additional, len ); + seedlen += len; + } + + /* 2. Update state */ + if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, seed, seedlen ) ) != 0 ) + goto exit; + + /* 3. Reset reseed_counter */ + ctx->reseed_counter = 1; + +exit: + /* 4. Done */ + mbedtls_platform_zeroize( seed, seedlen ); + return( ret ); +} + +/* + * HMAC_DRBG reseeding: 10.1.2.4 + 9.2 + */ +int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, size_t len ) +{ + return( hmac_drbg_reseed_core( ctx, additional, len, 0 ) ); +} + +/* + * HMAC_DRBG initialisation (10.1.2.3 + 9.1) + * + * The nonce is not passed as a separate parameter but extracted + * from the entropy source as suggested in 8.6.7. + */ +int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx, + const mbedtls_md_info_t * md_info, + int (*f_entropy)(void *, unsigned char *, size_t), + void *p_entropy, + const unsigned char *custom, + size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t md_size; + + if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 ) + return( ret ); + + md_size = mbedtls_md_get_size( md_info ); + + /* + * Set initial working state. + * Use the V memory location, which is currently all 0, to initialize the + * MD context with an all-zero key. Then set V to its initial value. + */ + if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size ) ) != 0 ) + return( ret ); + memset( ctx->V, 0x01, md_size ); + + ctx->f_entropy = f_entropy; + ctx->p_entropy = p_entropy; + + ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL; + + if( ctx->entropy_len == 0 ) + { + /* + * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by + * each hash function, then according to SP800-90A rev1 10.1 table 2, + * min_entropy_len (in bits) is security_strength. + * + * (This also matches the sizes used in the NIST test vectors.) + */ + ctx->entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */ + md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */ + 32; /* better (256+) -> 256 bits */ + } + + if( ( ret = hmac_drbg_reseed_core( ctx, custom, len, + 1 /* add nonce */ ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} + +/* + * Set prediction resistance + */ +void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx, + int resistance ) +{ + ctx->prediction_resistance = resistance; +} + +/* + * Set entropy length grabbed for seeding + */ +void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len ) +{ + ctx->entropy_len = len; +} + +/* + * Set reseed interval + */ +void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, int interval ) +{ + ctx->reseed_interval = interval; +} + +/* + * HMAC_DRBG random function with optional additional data: + * 10.1.2.5 (arabic) + 9.3 (Roman) + */ +int mbedtls_hmac_drbg_random_with_add( void *p_rng, + unsigned char *output, size_t out_len, + const unsigned char *additional, size_t add_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng; + size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info ); + size_t left = out_len; + unsigned char *out = output; + + /* II. Check request length */ + if( out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST ) + return( MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG ); + + /* III. Check input length */ + if( add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT ) + return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG ); + + /* 1. (aka VII and IX) Check reseed counter and PR */ + if( ctx->f_entropy != NULL && /* For no-reseeding instances */ + ( ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON || + ctx->reseed_counter > ctx->reseed_interval ) ) + { + if( ( ret = mbedtls_hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 ) + return( ret ); + + add_len = 0; /* VII.4 */ + } + + /* 2. Use additional data if any */ + if( additional != NULL && add_len != 0 ) + { + if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, + additional, add_len ) ) != 0 ) + goto exit; + } + + /* 3, 4, 5. Generate bytes */ + while( left != 0 ) + { + size_t use_len = left > md_len ? md_len : left; + + if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx, + ctx->V, md_len ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 ) + goto exit; + + memcpy( out, ctx->V, use_len ); + out += use_len; + left -= use_len; + } + + /* 6. Update */ + if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, + additional, add_len ) ) != 0 ) + goto exit; + + /* 7. Update reseed counter */ + ctx->reseed_counter++; + +exit: + /* 8. Done */ + return( ret ); +} + +/* + * HMAC_DRBG random function + */ +int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + ret = mbedtls_hmac_drbg_random_with_add( ctx, output, out_len, NULL, 0 ); + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +/* + * Free an HMAC_DRBG context + */ +void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx ) +{ + if( ctx == NULL ) + return; + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free( &ctx->mutex ); +#endif + mbedtls_md_free( &ctx->md_ctx ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) ); +} + +#if defined(MBEDTLS_FS_IO) +int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + FILE *f; + unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ]; + + if( ( f = fopen( path, "wb" ) ) == NULL ) + return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR ); + + if( ( ret = mbedtls_hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 ) + goto exit; + + if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) ) + { + ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR; + goto exit; + } + + ret = 0; + +exit: + fclose( f ); + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + + return( ret ); +} + +int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ) +{ + int ret = 0; + FILE *f = NULL; + size_t n; + unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ]; + unsigned char c; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR ); + + n = fread( buf, 1, sizeof( buf ), f ); + if( fread( &c, 1, 1, f ) != 0 ) + { + ret = MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG; + goto exit; + } + if( n == 0 || ferror( f ) ) + { + ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR; + goto exit; + } + fclose( f ); + f = NULL; + + ret = mbedtls_hmac_drbg_update_ret( ctx, buf, n ); + +exit: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + if( f != NULL ) + fclose( f ); + if( ret != 0 ) + return( ret ); + return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) ); +} +#endif /* MBEDTLS_FS_IO */ + + +#if defined(MBEDTLS_SELF_TEST) + +#if !defined(MBEDTLS_SHA1_C) +/* Dummy checkup routine */ +int mbedtls_hmac_drbg_self_test( int verbose ) +{ + (void) verbose; + return( 0 ); +} +#else + +#define OUTPUT_LEN 80 + +/* From a NIST PR=true test vector */ +static const unsigned char entropy_pr[] = { + 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f, + 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11, + 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42, + 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3, + 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 }; +static const unsigned char result_pr[OUTPUT_LEN] = { + 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39, + 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94, + 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54, + 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e, + 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab, + 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3, + 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 }; + +/* From a NIST PR=false test vector */ +static const unsigned char entropy_nopr[] = { + 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66, + 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8, + 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3, + 0xe9, 0x9d, 0xfe, 0xdf }; +static const unsigned char result_nopr[OUTPUT_LEN] = { + 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f, + 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6, + 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a, + 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec, + 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd, + 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49, + 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 }; + +/* "Entropy" from buffer */ +static size_t test_offset; +static int hmac_drbg_self_test_entropy( void *data, + unsigned char *buf, size_t len ) +{ + const unsigned char *p = data; + memcpy( buf, p + test_offset, len ); + test_offset += len; + return( 0 ); +} + +#define CHK( c ) if( (c) != 0 ) \ + { \ + if( verbose != 0 ) \ + mbedtls_printf( "failed\n" ); \ + return( 1 ); \ + } + +/* + * Checkup routine for HMAC_DRBG with SHA-1 + */ +int mbedtls_hmac_drbg_self_test( int verbose ) +{ + mbedtls_hmac_drbg_context ctx; + unsigned char buf[OUTPUT_LEN]; + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ); + + mbedtls_hmac_drbg_init( &ctx ); + + /* + * PR = True + */ + if( verbose != 0 ) + mbedtls_printf( " HMAC_DRBG (PR = True) : " ); + + test_offset = 0; + CHK( mbedtls_hmac_drbg_seed( &ctx, md_info, + hmac_drbg_self_test_entropy, (void *) entropy_pr, + NULL, 0 ) ); + mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON ); + CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); + CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); + CHK( memcmp( buf, result_pr, OUTPUT_LEN ) ); + mbedtls_hmac_drbg_free( &ctx ); + + mbedtls_hmac_drbg_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + /* + * PR = False + */ + if( verbose != 0 ) + mbedtls_printf( " HMAC_DRBG (PR = False) : " ); + + mbedtls_hmac_drbg_init( &ctx ); + + test_offset = 0; + CHK( mbedtls_hmac_drbg_seed( &ctx, md_info, + hmac_drbg_self_test_entropy, (void *) entropy_nopr, + NULL, 0 ) ); + CHK( mbedtls_hmac_drbg_reseed( &ctx, NULL, 0 ) ); + CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); + CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); + CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) ); + mbedtls_hmac_drbg_free( &ctx ); + + mbedtls_hmac_drbg_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_HMAC_DRBG_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/md.c b/Android/Level4/app/src/main/c/mbedtls/library/md.c new file mode 100644 index 0000000..de77b16 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/md.c @@ -0,0 +1,890 @@ +/** + * \file mbedtls_md.c + * + * \brief Generic message digest wrapper for mbed TLS + * + * \author Adriaan de Jong + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 "common.h" + +#if defined(MBEDTLS_MD_C) + +#include "mbedtls/md.h" +#include "mbedtls/md_internal.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include "mbedtls/md2.h" +#include "mbedtls/md4.h" +#include "mbedtls/md5.h" +#include "mbedtls/ripemd160.h" +#include "mbedtls/sha1.h" +#include "mbedtls/sha256.h" +#include "mbedtls/sha512.h" + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +#if defined(MBEDTLS_MD2_C) +const mbedtls_md_info_t mbedtls_md2_info = { + "MD2", + MBEDTLS_MD_MD2, + 16, + 16, +}; +#endif + +#if defined(MBEDTLS_MD4_C) +const mbedtls_md_info_t mbedtls_md4_info = { + "MD4", + MBEDTLS_MD_MD4, + 16, + 64, +}; +#endif + +#if defined(MBEDTLS_MD5_C) +const mbedtls_md_info_t mbedtls_md5_info = { + "MD5", + MBEDTLS_MD_MD5, + 16, + 64, +}; +#endif + +#if defined(MBEDTLS_RIPEMD160_C) +const mbedtls_md_info_t mbedtls_ripemd160_info = { + "RIPEMD160", + MBEDTLS_MD_RIPEMD160, + 20, + 64, +}; +#endif + +#if defined(MBEDTLS_SHA1_C) +const mbedtls_md_info_t mbedtls_sha1_info = { + "SHA1", + MBEDTLS_MD_SHA1, + 20, + 64, +}; +#endif + +#if defined(MBEDTLS_SHA256_C) +const mbedtls_md_info_t mbedtls_sha224_info = { + "SHA224", + MBEDTLS_MD_SHA224, + 28, + 64, +}; + +const mbedtls_md_info_t mbedtls_sha256_info = { + "SHA256", + MBEDTLS_MD_SHA256, + 32, + 64, +}; +#endif + +#if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) +const mbedtls_md_info_t mbedtls_sha384_info = { + "SHA384", + MBEDTLS_MD_SHA384, + 48, + 128, +}; +#endif + +const mbedtls_md_info_t mbedtls_sha512_info = { + "SHA512", + MBEDTLS_MD_SHA512, + 64, + 128, +}; +#endif + +/* + * Reminder: update profiles in x509_crt.c when adding a new hash! + */ +static const int supported_digests[] = { + +#if defined(MBEDTLS_SHA512_C) + MBEDTLS_MD_SHA512, +#if !defined(MBEDTLS_SHA512_NO_SHA384) + MBEDTLS_MD_SHA384, +#endif +#endif + +#if defined(MBEDTLS_SHA256_C) + MBEDTLS_MD_SHA256, + MBEDTLS_MD_SHA224, +#endif + +#if defined(MBEDTLS_SHA1_C) + MBEDTLS_MD_SHA1, +#endif + +#if defined(MBEDTLS_RIPEMD160_C) + MBEDTLS_MD_RIPEMD160, +#endif + +#if defined(MBEDTLS_MD5_C) + MBEDTLS_MD_MD5, +#endif + +#if defined(MBEDTLS_MD4_C) + MBEDTLS_MD_MD4, +#endif + +#if defined(MBEDTLS_MD2_C) + MBEDTLS_MD_MD2, +#endif + + MBEDTLS_MD_NONE +}; + +const int *mbedtls_md_list( void ) +{ + return( supported_digests ); +} + +const mbedtls_md_info_t *mbedtls_md_info_from_string( const char *md_name ) +{ + if( NULL == md_name ) + return( NULL ); + + /* Get the appropriate digest information */ +#if defined(MBEDTLS_MD2_C) + if( !strcmp( "MD2", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_MD2 ); +#endif +#if defined(MBEDTLS_MD4_C) + if( !strcmp( "MD4", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_MD4 ); +#endif +#if defined(MBEDTLS_MD5_C) + if( !strcmp( "MD5", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_MD5 ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + if( !strcmp( "RIPEMD160", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_RIPEMD160 ); +#endif +#if defined(MBEDTLS_SHA1_C) + if( !strcmp( "SHA1", md_name ) || !strcmp( "SHA", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ); +#endif +#if defined(MBEDTLS_SHA256_C) + if( !strcmp( "SHA224", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA224 ); + if( !strcmp( "SHA256", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ); +#endif +#if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) + if( !strcmp( "SHA384", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA384 ); +#endif + if( !strcmp( "SHA512", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA512 ); +#endif + return( NULL ); +} + +const mbedtls_md_info_t *mbedtls_md_info_from_type( mbedtls_md_type_t md_type ) +{ + switch( md_type ) + { +#if defined(MBEDTLS_MD2_C) + case MBEDTLS_MD_MD2: + return( &mbedtls_md2_info ); +#endif +#if defined(MBEDTLS_MD4_C) + case MBEDTLS_MD_MD4: + return( &mbedtls_md4_info ); +#endif +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return( &mbedtls_md5_info ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + return( &mbedtls_ripemd160_info ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return( &mbedtls_sha1_info ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA224: + return( &mbedtls_sha224_info ); + case MBEDTLS_MD_SHA256: + return( &mbedtls_sha256_info ); +#endif +#if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) + case MBEDTLS_MD_SHA384: + return( &mbedtls_sha384_info ); +#endif + case MBEDTLS_MD_SHA512: + return( &mbedtls_sha512_info ); +#endif + default: + return( NULL ); + } +} + +void mbedtls_md_init( mbedtls_md_context_t *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_md_context_t ) ); +} + +void mbedtls_md_free( mbedtls_md_context_t *ctx ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return; + + if( ctx->md_ctx != NULL ) + { + switch( ctx->md_info->type ) + { +#if defined(MBEDTLS_MD2_C) + case MBEDTLS_MD_MD2: + mbedtls_md2_free( ctx->md_ctx ); + break; +#endif +#if defined(MBEDTLS_MD4_C) + case MBEDTLS_MD_MD4: + mbedtls_md4_free( ctx->md_ctx ); + break; +#endif +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + mbedtls_md5_free( ctx->md_ctx ); + break; +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + mbedtls_ripemd160_free( ctx->md_ctx ); + break; +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + mbedtls_sha1_free( ctx->md_ctx ); + break; +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA224: + case MBEDTLS_MD_SHA256: + mbedtls_sha256_free( ctx->md_ctx ); + break; +#endif +#if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) + case MBEDTLS_MD_SHA384: +#endif + case MBEDTLS_MD_SHA512: + mbedtls_sha512_free( ctx->md_ctx ); + break; +#endif + default: + /* Shouldn't happen */ + break; + } + mbedtls_free( ctx->md_ctx ); + } + + if( ctx->hmac_ctx != NULL ) + { + mbedtls_platform_zeroize( ctx->hmac_ctx, + 2 * ctx->md_info->block_size ); + mbedtls_free( ctx->hmac_ctx ); + } + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md_context_t ) ); +} + +int mbedtls_md_clone( mbedtls_md_context_t *dst, + const mbedtls_md_context_t *src ) +{ + if( dst == NULL || dst->md_info == NULL || + src == NULL || src->md_info == NULL || + dst->md_info != src->md_info ) + { + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + } + + switch( src->md_info->type ) + { +#if defined(MBEDTLS_MD2_C) + case MBEDTLS_MD_MD2: + mbedtls_md2_clone( dst->md_ctx, src->md_ctx ); + break; +#endif +#if defined(MBEDTLS_MD4_C) + case MBEDTLS_MD_MD4: + mbedtls_md4_clone( dst->md_ctx, src->md_ctx ); + break; +#endif +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + mbedtls_md5_clone( dst->md_ctx, src->md_ctx ); + break; +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + mbedtls_ripemd160_clone( dst->md_ctx, src->md_ctx ); + break; +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + mbedtls_sha1_clone( dst->md_ctx, src->md_ctx ); + break; +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA224: + case MBEDTLS_MD_SHA256: + mbedtls_sha256_clone( dst->md_ctx, src->md_ctx ); + break; +#endif +#if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) + case MBEDTLS_MD_SHA384: +#endif + case MBEDTLS_MD_SHA512: + mbedtls_sha512_clone( dst->md_ctx, src->md_ctx ); + break; +#endif + default: + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + } + + return( 0 ); +} + +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) +int mbedtls_md_init_ctx( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info ) +{ + return mbedtls_md_setup( ctx, md_info, 1 ); +} +#endif + +#define ALLOC( type ) \ + do { \ + ctx->md_ctx = mbedtls_calloc( 1, sizeof( mbedtls_##type##_context ) ); \ + if( ctx->md_ctx == NULL ) \ + return( MBEDTLS_ERR_MD_ALLOC_FAILED ); \ + mbedtls_##type##_init( ctx->md_ctx ); \ + } \ + while( 0 ) + +int mbedtls_md_setup( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac ) +{ + if( md_info == NULL || ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + ctx->md_info = md_info; + ctx->md_ctx = NULL; + ctx->hmac_ctx = NULL; + + switch( md_info->type ) + { +#if defined(MBEDTLS_MD2_C) + case MBEDTLS_MD_MD2: + ALLOC( md2 ); + break; +#endif +#if defined(MBEDTLS_MD4_C) + case MBEDTLS_MD_MD4: + ALLOC( md4 ); + break; +#endif +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + ALLOC( md5 ); + break; +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + ALLOC( ripemd160 ); + break; +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + ALLOC( sha1 ); + break; +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA224: + case MBEDTLS_MD_SHA256: + ALLOC( sha256 ); + break; +#endif +#if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) + case MBEDTLS_MD_SHA384: +#endif + case MBEDTLS_MD_SHA512: + ALLOC( sha512 ); + break; +#endif + default: + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + } + + if( hmac != 0 ) + { + ctx->hmac_ctx = mbedtls_calloc( 2, md_info->block_size ); + if( ctx->hmac_ctx == NULL ) + { + mbedtls_md_free( ctx ); + return( MBEDTLS_ERR_MD_ALLOC_FAILED ); + } + } + + return( 0 ); +} +#undef ALLOC + +int mbedtls_md_starts( mbedtls_md_context_t *ctx ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + switch( ctx->md_info->type ) + { +#if defined(MBEDTLS_MD2_C) + case MBEDTLS_MD_MD2: + return( mbedtls_md2_starts_ret( ctx->md_ctx ) ); +#endif +#if defined(MBEDTLS_MD4_C) + case MBEDTLS_MD_MD4: + return( mbedtls_md4_starts_ret( ctx->md_ctx ) ); +#endif +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return( mbedtls_md5_starts_ret( ctx->md_ctx ) ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + return( mbedtls_ripemd160_starts_ret( ctx->md_ctx ) ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return( mbedtls_sha1_starts_ret( ctx->md_ctx ) ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA224: + return( mbedtls_sha256_starts_ret( ctx->md_ctx, 1 ) ); + case MBEDTLS_MD_SHA256: + return( mbedtls_sha256_starts_ret( ctx->md_ctx, 0 ) ); +#endif +#if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) + case MBEDTLS_MD_SHA384: + return( mbedtls_sha512_starts_ret( ctx->md_ctx, 1 ) ); +#endif + case MBEDTLS_MD_SHA512: + return( mbedtls_sha512_starts_ret( ctx->md_ctx, 0 ) ); +#endif + default: + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + } +} + +int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + switch( ctx->md_info->type ) + { +#if defined(MBEDTLS_MD2_C) + case MBEDTLS_MD_MD2: + return( mbedtls_md2_update_ret( ctx->md_ctx, input, ilen ) ); +#endif +#if defined(MBEDTLS_MD4_C) + case MBEDTLS_MD_MD4: + return( mbedtls_md4_update_ret( ctx->md_ctx, input, ilen ) ); +#endif +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return( mbedtls_md5_update_ret( ctx->md_ctx, input, ilen ) ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + return( mbedtls_ripemd160_update_ret( ctx->md_ctx, input, ilen ) ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return( mbedtls_sha1_update_ret( ctx->md_ctx, input, ilen ) ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA224: + case MBEDTLS_MD_SHA256: + return( mbedtls_sha256_update_ret( ctx->md_ctx, input, ilen ) ); +#endif +#if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) + case MBEDTLS_MD_SHA384: +#endif + case MBEDTLS_MD_SHA512: + return( mbedtls_sha512_update_ret( ctx->md_ctx, input, ilen ) ); +#endif + default: + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + } +} + +int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + switch( ctx->md_info->type ) + { +#if defined(MBEDTLS_MD2_C) + case MBEDTLS_MD_MD2: + return( mbedtls_md2_finish_ret( ctx->md_ctx, output ) ); +#endif +#if defined(MBEDTLS_MD4_C) + case MBEDTLS_MD_MD4: + return( mbedtls_md4_finish_ret( ctx->md_ctx, output ) ); +#endif +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return( mbedtls_md5_finish_ret( ctx->md_ctx, output ) ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + return( mbedtls_ripemd160_finish_ret( ctx->md_ctx, output ) ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return( mbedtls_sha1_finish_ret( ctx->md_ctx, output ) ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA224: + case MBEDTLS_MD_SHA256: + return( mbedtls_sha256_finish_ret( ctx->md_ctx, output ) ); +#endif +#if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) + case MBEDTLS_MD_SHA384: +#endif + case MBEDTLS_MD_SHA512: + return( mbedtls_sha512_finish_ret( ctx->md_ctx, output ) ); +#endif + default: + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + } +} + +int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + if( md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + switch( md_info->type ) + { +#if defined(MBEDTLS_MD2_C) + case MBEDTLS_MD_MD2: + return( mbedtls_md2_ret( input, ilen, output ) ); +#endif +#if defined(MBEDTLS_MD4_C) + case MBEDTLS_MD_MD4: + return( mbedtls_md4_ret( input, ilen, output ) ); +#endif +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return( mbedtls_md5_ret( input, ilen, output ) ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + return( mbedtls_ripemd160_ret( input, ilen, output ) ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return( mbedtls_sha1_ret( input, ilen, output ) ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA224: + return( mbedtls_sha256_ret( input, ilen, output, 1 ) ); + case MBEDTLS_MD_SHA256: + return( mbedtls_sha256_ret( input, ilen, output, 0 ) ); +#endif +#if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) + case MBEDTLS_MD_SHA384: + return( mbedtls_sha512_ret( input, ilen, output, 1 ) ); +#endif + case MBEDTLS_MD_SHA512: + return( mbedtls_sha512_ret( input, ilen, output, 0 ) ); +#endif + default: + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + } +} + +#if defined(MBEDTLS_FS_IO) +int mbedtls_md_file( const mbedtls_md_info_t *md_info, const char *path, unsigned char *output ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + FILE *f; + size_t n; + mbedtls_md_context_t ctx; + unsigned char buf[1024]; + + if( md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( MBEDTLS_ERR_MD_FILE_IO_ERROR ); + + mbedtls_md_init( &ctx ); + + if( ( ret = mbedtls_md_setup( &ctx, md_info, 0 ) ) != 0 ) + goto cleanup; + + if( ( ret = mbedtls_md_starts( &ctx ) ) != 0 ) + goto cleanup; + + while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) + if( ( ret = mbedtls_md_update( &ctx, buf, n ) ) != 0 ) + goto cleanup; + + if( ferror( f ) != 0 ) + ret = MBEDTLS_ERR_MD_FILE_IO_ERROR; + else + ret = mbedtls_md_finish( &ctx, output ); + +cleanup: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + fclose( f ); + mbedtls_md_free( &ctx ); + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + +int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key, size_t keylen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char sum[MBEDTLS_MD_MAX_SIZE]; + unsigned char *ipad, *opad; + size_t i; + + if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + if( keylen > (size_t) ctx->md_info->block_size ) + { + if( ( ret = mbedtls_md_starts( ctx ) ) != 0 ) + goto cleanup; + if( ( ret = mbedtls_md_update( ctx, key, keylen ) ) != 0 ) + goto cleanup; + if( ( ret = mbedtls_md_finish( ctx, sum ) ) != 0 ) + goto cleanup; + + keylen = ctx->md_info->size; + key = sum; + } + + ipad = (unsigned char *) ctx->hmac_ctx; + opad = (unsigned char *) ctx->hmac_ctx + ctx->md_info->block_size; + + memset( ipad, 0x36, ctx->md_info->block_size ); + memset( opad, 0x5C, ctx->md_info->block_size ); + + for( i = 0; i < keylen; i++ ) + { + ipad[i] = (unsigned char)( ipad[i] ^ key[i] ); + opad[i] = (unsigned char)( opad[i] ^ key[i] ); + } + + if( ( ret = mbedtls_md_starts( ctx ) ) != 0 ) + goto cleanup; + if( ( ret = mbedtls_md_update( ctx, ipad, + ctx->md_info->block_size ) ) != 0 ) + goto cleanup; + +cleanup: + mbedtls_platform_zeroize( sum, sizeof( sum ) ); + + return( ret ); +} + +int mbedtls_md_hmac_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ) +{ + if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + return( mbedtls_md_update( ctx, input, ilen ) ); +} + +int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char tmp[MBEDTLS_MD_MAX_SIZE]; + unsigned char *opad; + + if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + opad = (unsigned char *) ctx->hmac_ctx + ctx->md_info->block_size; + + if( ( ret = mbedtls_md_finish( ctx, tmp ) ) != 0 ) + return( ret ); + if( ( ret = mbedtls_md_starts( ctx ) ) != 0 ) + return( ret ); + if( ( ret = mbedtls_md_update( ctx, opad, + ctx->md_info->block_size ) ) != 0 ) + return( ret ); + if( ( ret = mbedtls_md_update( ctx, tmp, + ctx->md_info->size ) ) != 0 ) + return( ret ); + return( mbedtls_md_finish( ctx, output ) ); +} + +int mbedtls_md_hmac_reset( mbedtls_md_context_t *ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *ipad; + + if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + ipad = (unsigned char *) ctx->hmac_ctx; + + if( ( ret = mbedtls_md_starts( ctx ) ) != 0 ) + return( ret ); + return( mbedtls_md_update( ctx, ipad, ctx->md_info->block_size ) ); +} + +int mbedtls_md_hmac( const mbedtls_md_info_t *md_info, + const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + mbedtls_md_context_t ctx; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + mbedtls_md_init( &ctx ); + + if( ( ret = mbedtls_md_setup( &ctx, md_info, 1 ) ) != 0 ) + goto cleanup; + + if( ( ret = mbedtls_md_hmac_starts( &ctx, key, keylen ) ) != 0 ) + goto cleanup; + if( ( ret = mbedtls_md_hmac_update( &ctx, input, ilen ) ) != 0 ) + goto cleanup; + if( ( ret = mbedtls_md_hmac_finish( &ctx, output ) ) != 0 ) + goto cleanup; + +cleanup: + mbedtls_md_free( &ctx ); + + return( ret ); +} + +int mbedtls_md_process( mbedtls_md_context_t *ctx, const unsigned char *data ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + switch( ctx->md_info->type ) + { +#if defined(MBEDTLS_MD2_C) + case MBEDTLS_MD_MD2: + return( mbedtls_internal_md2_process( ctx->md_ctx ) ); +#endif +#if defined(MBEDTLS_MD4_C) + case MBEDTLS_MD_MD4: + return( mbedtls_internal_md4_process( ctx->md_ctx, data ) ); +#endif +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return( mbedtls_internal_md5_process( ctx->md_ctx, data ) ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + return( mbedtls_internal_ripemd160_process( ctx->md_ctx, data ) ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return( mbedtls_internal_sha1_process( ctx->md_ctx, data ) ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA224: + case MBEDTLS_MD_SHA256: + return( mbedtls_internal_sha256_process( ctx->md_ctx, data ) ); +#endif +#if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) + case MBEDTLS_MD_SHA384: +#endif + case MBEDTLS_MD_SHA512: + return( mbedtls_internal_sha512_process( ctx->md_ctx, data ) ); +#endif + default: + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + } +} + +unsigned char mbedtls_md_get_size( const mbedtls_md_info_t *md_info ) +{ + if( md_info == NULL ) + return( 0 ); + + return md_info->size; +} + +mbedtls_md_type_t mbedtls_md_get_type( const mbedtls_md_info_t *md_info ) +{ + if( md_info == NULL ) + return( MBEDTLS_MD_NONE ); + + return md_info->type; +} + +const char *mbedtls_md_get_name( const mbedtls_md_info_t *md_info ) +{ + if( md_info == NULL ) + return( NULL ); + + return md_info->name; +} + +#endif /* MBEDTLS_MD_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/md2.c b/Android/Level4/app/src/main/c/mbedtls/library/md2.c new file mode 100644 index 0000000..b4f7cc6 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/md2.c @@ -0,0 +1,357 @@ +/* + * RFC 1115/1319 compliant MD2 implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ +/* + * The MD2 algorithm was designed by Ron Rivest in 1989. + * + * http://www.ietf.org/rfc/rfc1115.txt + * http://www.ietf.org/rfc/rfc1319.txt + */ + +#include "common.h" + +#if defined(MBEDTLS_MD2_C) + +#include "mbedtls/md2.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_MD2_ALT) + +static const unsigned char PI_SUBST[256] = +{ + 0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, 0x3D, 0x36, + 0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13, 0x62, 0xA7, 0x05, 0xF3, + 0xC0, 0xC7, 0x73, 0x8C, 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C, + 0x82, 0xCA, 0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16, + 0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12, 0xBE, 0x4E, + 0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49, 0xA0, 0xFB, 0xF5, 0x8E, + 0xBB, 0x2F, 0xEE, 0x7A, 0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2, + 0x07, 0x3F, 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21, + 0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27, 0x35, 0x3E, + 0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03, 0xFF, 0x19, 0x30, 0xB3, + 0x48, 0xA5, 0xB5, 0xD1, 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56, + 0xAA, 0xC6, 0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6, + 0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1, 0x45, 0x9D, + 0x70, 0x59, 0x64, 0x71, 0x87, 0x20, 0x86, 0x5B, 0xCF, 0x65, + 0xE6, 0x2D, 0xA8, 0x02, 0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0, + 0xB9, 0xF6, 0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F, + 0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A, 0xC3, 0x5C, + 0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26, 0x2C, 0x53, 0x0D, 0x6E, + 0x85, 0x28, 0x84, 0x09, 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81, + 0x4D, 0x52, 0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA, + 0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A, 0x78, 0x88, + 0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D, 0xE9, 0xCB, 0xD5, 0xFE, + 0x3B, 0x00, 0x1D, 0x39, 0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58, + 0xD0, 0xE4, 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A, + 0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, 0xDB, 0x99, + 0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14 +}; + +void mbedtls_md2_init( mbedtls_md2_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_md2_context ) ); +} + +void mbedtls_md2_free( mbedtls_md2_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md2_context ) ); +} + +void mbedtls_md2_clone( mbedtls_md2_context *dst, + const mbedtls_md2_context *src ) +{ + *dst = *src; +} + +/* + * MD2 context setup + */ +int mbedtls_md2_starts_ret( mbedtls_md2_context *ctx ) +{ + memset( ctx->cksum, 0, 16 ); + memset( ctx->state, 0, 46 ); + memset( ctx->buffer, 0, 16 ); + ctx->left = 0; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md2_starts( mbedtls_md2_context *ctx ) +{ + mbedtls_md2_starts_ret( ctx ); +} +#endif + +#if !defined(MBEDTLS_MD2_PROCESS_ALT) +int mbedtls_internal_md2_process( mbedtls_md2_context *ctx ) +{ + int i, j; + unsigned char t = 0; + + for( i = 0; i < 16; i++ ) + { + ctx->state[i + 16] = ctx->buffer[i]; + ctx->state[i + 32] = + (unsigned char)( ctx->buffer[i] ^ ctx->state[i]); + } + + for( i = 0; i < 18; i++ ) + { + for( j = 0; j < 48; j++ ) + { + ctx->state[j] = (unsigned char) + ( ctx->state[j] ^ PI_SUBST[t] ); + t = ctx->state[j]; + } + + t = (unsigned char)( t + i ); + } + + t = ctx->cksum[15]; + + for( i = 0; i < 16; i++ ) + { + ctx->cksum[i] = (unsigned char) + ( ctx->cksum[i] ^ PI_SUBST[ctx->buffer[i] ^ t] ); + t = ctx->cksum[i]; + } + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md2_process( mbedtls_md2_context *ctx ) +{ + mbedtls_internal_md2_process( ctx ); +} +#endif +#endif /* !MBEDTLS_MD2_PROCESS_ALT */ + +/* + * MD2 process buffer + */ +int mbedtls_md2_update_ret( mbedtls_md2_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t fill; + + while( ilen > 0 ) + { + if( ilen > 16 - ctx->left ) + fill = 16 - ctx->left; + else + fill = ilen; + + memcpy( ctx->buffer + ctx->left, input, fill ); + + ctx->left += fill; + input += fill; + ilen -= fill; + + if( ctx->left == 16 ) + { + ctx->left = 0; + if( ( ret = mbedtls_internal_md2_process( ctx ) ) != 0 ) + return( ret ); + } + } + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md2_update( mbedtls_md2_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + mbedtls_md2_update_ret( ctx, input, ilen ); +} +#endif + +/* + * MD2 final digest + */ +int mbedtls_md2_finish_ret( mbedtls_md2_context *ctx, + unsigned char output[16] ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i; + unsigned char x; + + x = (unsigned char)( 16 - ctx->left ); + + for( i = ctx->left; i < 16; i++ ) + ctx->buffer[i] = x; + + if( ( ret = mbedtls_internal_md2_process( ctx ) ) != 0 ) + return( ret ); + + memcpy( ctx->buffer, ctx->cksum, 16 ); + if( ( ret = mbedtls_internal_md2_process( ctx ) ) != 0 ) + return( ret ); + + memcpy( output, ctx->state, 16 ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md2_finish( mbedtls_md2_context *ctx, + unsigned char output[16] ) +{ + mbedtls_md2_finish_ret( ctx, output ); +} +#endif + +#endif /* !MBEDTLS_MD2_ALT */ + +/* + * output = MD2( input buffer ) + */ +int mbedtls_md2_ret( const unsigned char *input, + size_t ilen, + unsigned char output[16] ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_md2_context ctx; + + mbedtls_md2_init( &ctx ); + + if( ( ret = mbedtls_md2_starts_ret( &ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md2_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md2_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_md2_free( &ctx ); + + return( ret ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md2( const unsigned char *input, + size_t ilen, + unsigned char output[16] ) +{ + mbedtls_md2_ret( input, ilen, output ); +} +#endif + +#if defined(MBEDTLS_SELF_TEST) + +/* + * RFC 1319 test vectors + */ +static const unsigned char md2_test_str[7][81] = +{ + { "" }, + { "a" }, + { "abc" }, + { "message digest" }, + { "abcdefghijklmnopqrstuvwxyz" }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, + { "12345678901234567890123456789012345678901234567890123456789012345678901234567890" } +}; + +static const size_t md2_test_strlen[7] = +{ + 0, 1, 3, 14, 26, 62, 80 +}; + +static const unsigned char md2_test_sum[7][16] = +{ + { 0x83, 0x50, 0xE5, 0xA3, 0xE2, 0x4C, 0x15, 0x3D, + 0xF2, 0x27, 0x5C, 0x9F, 0x80, 0x69, 0x27, 0x73 }, + { 0x32, 0xEC, 0x01, 0xEC, 0x4A, 0x6D, 0xAC, 0x72, + 0xC0, 0xAB, 0x96, 0xFB, 0x34, 0xC0, 0xB5, 0xD1 }, + { 0xDA, 0x85, 0x3B, 0x0D, 0x3F, 0x88, 0xD9, 0x9B, + 0x30, 0x28, 0x3A, 0x69, 0xE6, 0xDE, 0xD6, 0xBB }, + { 0xAB, 0x4F, 0x49, 0x6B, 0xFB, 0x2A, 0x53, 0x0B, + 0x21, 0x9F, 0xF3, 0x30, 0x31, 0xFE, 0x06, 0xB0 }, + { 0x4E, 0x8D, 0xDF, 0xF3, 0x65, 0x02, 0x92, 0xAB, + 0x5A, 0x41, 0x08, 0xC3, 0xAA, 0x47, 0x94, 0x0B }, + { 0xDA, 0x33, 0xDE, 0xF2, 0xA4, 0x2D, 0xF1, 0x39, + 0x75, 0x35, 0x28, 0x46, 0xC3, 0x03, 0x38, 0xCD }, + { 0xD5, 0x97, 0x6F, 0x79, 0xD8, 0x3D, 0x3A, 0x0D, + 0xC9, 0x80, 0x6C, 0x3C, 0x66, 0xF3, 0xEF, 0xD8 } +}; + +/* + * Checkup routine + */ +int mbedtls_md2_self_test( int verbose ) +{ + int i, ret = 0; + unsigned char md2sum[16]; + + for( i = 0; i < 7; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " MD2 test #%d: ", i + 1 ); + + ret = mbedtls_md2_ret( md2_test_str[i], md2_test_strlen[i], md2sum ); + if( ret != 0 ) + goto fail; + + if( memcmp( md2sum, md2_test_sum[i], 16 ) != 0 ) + { + ret = 1; + goto fail; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_MD2_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/md4.c b/Android/Level4/app/src/main/c/mbedtls/library/md4.c new file mode 100644 index 0000000..1cac0a4 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/md4.c @@ -0,0 +1,478 @@ +/* + * RFC 1186/1320 compliant MD4 implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ +/* + * The MD4 algorithm was designed by Ron Rivest in 1990. + * + * http://www.ietf.org/rfc/rfc1186.txt + * http://www.ietf.org/rfc/rfc1320.txt + */ + +#include "common.h" + +#if defined(MBEDTLS_MD4_C) + +#include "mbedtls/md4.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_MD4_ALT) + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_UINT32_LE +#define GET_UINT32_LE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] ) \ + | ( (uint32_t) (b)[(i) + 1] << 8 ) \ + | ( (uint32_t) (b)[(i) + 2] << 16 ) \ + | ( (uint32_t) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef PUT_UINT32_LE +#define PUT_UINT32_LE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ + (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ + (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ + (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ +} +#endif + +void mbedtls_md4_init( mbedtls_md4_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_md4_context ) ); +} + +void mbedtls_md4_free( mbedtls_md4_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md4_context ) ); +} + +void mbedtls_md4_clone( mbedtls_md4_context *dst, + const mbedtls_md4_context *src ) +{ + *dst = *src; +} + +/* + * MD4 context setup + */ +int mbedtls_md4_starts_ret( mbedtls_md4_context *ctx ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md4_starts( mbedtls_md4_context *ctx ) +{ + mbedtls_md4_starts_ret( ctx ); +} +#endif + +#if !defined(MBEDTLS_MD4_PROCESS_ALT) +int mbedtls_internal_md4_process( mbedtls_md4_context *ctx, + const unsigned char data[64] ) +{ + uint32_t X[16], A, B, C, D; + + GET_UINT32_LE( X[ 0], data, 0 ); + GET_UINT32_LE( X[ 1], data, 4 ); + GET_UINT32_LE( X[ 2], data, 8 ); + GET_UINT32_LE( X[ 3], data, 12 ); + GET_UINT32_LE( X[ 4], data, 16 ); + GET_UINT32_LE( X[ 5], data, 20 ); + GET_UINT32_LE( X[ 6], data, 24 ); + GET_UINT32_LE( X[ 7], data, 28 ); + GET_UINT32_LE( X[ 8], data, 32 ); + GET_UINT32_LE( X[ 9], data, 36 ); + GET_UINT32_LE( X[10], data, 40 ); + GET_UINT32_LE( X[11], data, 44 ); + GET_UINT32_LE( X[12], data, 48 ); + GET_UINT32_LE( X[13], data, 52 ); + GET_UINT32_LE( X[14], data, 56 ); + GET_UINT32_LE( X[15], data, 60 ); + +#define S(x,n) (((x) << (n)) | (((x) & 0xFFFFFFFF) >> (32 - (n)))) + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + +#define F(x, y, z) (((x) & (y)) | ((~(x)) & (z))) +#define P(a,b,c,d,x,s) \ + do \ + { \ + (a) += F((b),(c),(d)) + (x); \ + (a) = S((a),(s)); \ + } while( 0 ) + + + P( A, B, C, D, X[ 0], 3 ); + P( D, A, B, C, X[ 1], 7 ); + P( C, D, A, B, X[ 2], 11 ); + P( B, C, D, A, X[ 3], 19 ); + P( A, B, C, D, X[ 4], 3 ); + P( D, A, B, C, X[ 5], 7 ); + P( C, D, A, B, X[ 6], 11 ); + P( B, C, D, A, X[ 7], 19 ); + P( A, B, C, D, X[ 8], 3 ); + P( D, A, B, C, X[ 9], 7 ); + P( C, D, A, B, X[10], 11 ); + P( B, C, D, A, X[11], 19 ); + P( A, B, C, D, X[12], 3 ); + P( D, A, B, C, X[13], 7 ); + P( C, D, A, B, X[14], 11 ); + P( B, C, D, A, X[15], 19 ); + +#undef P +#undef F + +#define F(x,y,z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) +#define P(a,b,c,d,x,s) \ + do \ + { \ + (a) += F((b),(c),(d)) + (x) + 0x5A827999; \ + (a) = S((a),(s)); \ + } while( 0 ) + + P( A, B, C, D, X[ 0], 3 ); + P( D, A, B, C, X[ 4], 5 ); + P( C, D, A, B, X[ 8], 9 ); + P( B, C, D, A, X[12], 13 ); + P( A, B, C, D, X[ 1], 3 ); + P( D, A, B, C, X[ 5], 5 ); + P( C, D, A, B, X[ 9], 9 ); + P( B, C, D, A, X[13], 13 ); + P( A, B, C, D, X[ 2], 3 ); + P( D, A, B, C, X[ 6], 5 ); + P( C, D, A, B, X[10], 9 ); + P( B, C, D, A, X[14], 13 ); + P( A, B, C, D, X[ 3], 3 ); + P( D, A, B, C, X[ 7], 5 ); + P( C, D, A, B, X[11], 9 ); + P( B, C, D, A, X[15], 13 ); + +#undef P +#undef F + +#define F(x,y,z) ((x) ^ (y) ^ (z)) +#define P(a,b,c,d,x,s) \ + do \ + { \ + (a) += F((b),(c),(d)) + (x) + 0x6ED9EBA1; \ + (a) = S((a),(s)); \ + } while( 0 ) + + P( A, B, C, D, X[ 0], 3 ); + P( D, A, B, C, X[ 8], 9 ); + P( C, D, A, B, X[ 4], 11 ); + P( B, C, D, A, X[12], 15 ); + P( A, B, C, D, X[ 2], 3 ); + P( D, A, B, C, X[10], 9 ); + P( C, D, A, B, X[ 6], 11 ); + P( B, C, D, A, X[14], 15 ); + P( A, B, C, D, X[ 1], 3 ); + P( D, A, B, C, X[ 9], 9 ); + P( C, D, A, B, X[ 5], 11 ); + P( B, C, D, A, X[13], 15 ); + P( A, B, C, D, X[ 3], 3 ); + P( D, A, B, C, X[11], 9 ); + P( C, D, A, B, X[ 7], 11 ); + P( B, C, D, A, X[15], 15 ); + +#undef F +#undef P + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md4_process( mbedtls_md4_context *ctx, + const unsigned char data[64] ) +{ + mbedtls_internal_md4_process( ctx, data ); +} +#endif +#endif /* !MBEDTLS_MD4_PROCESS_ALT */ + +/* + * MD4 process buffer + */ +int mbedtls_md4_update_ret( mbedtls_md4_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t fill; + uint32_t left; + + if( ilen == 0 ) + return( 0 ); + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (uint32_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), + (void *) input, fill ); + + if( ( ret = mbedtls_internal_md4_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + if( ( ret = mbedtls_internal_md4_process( ctx, input ) ) != 0 ) + return( ret ); + + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + { + memcpy( (void *) (ctx->buffer + left), + (void *) input, ilen ); + } + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md4_update( mbedtls_md4_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + mbedtls_md4_update_ret( ctx, input, ilen ); +} +#endif + +static const unsigned char md4_padding[64] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * MD4 final digest + */ +int mbedtls_md4_finish_ret( mbedtls_md4_context *ctx, + unsigned char output[16] ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + uint32_t last, padn; + uint32_t high, low; + unsigned char msglen[8]; + + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT32_LE( low, msglen, 0 ); + PUT_UINT32_LE( high, msglen, 4 ); + + last = ctx->total[0] & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + ret = mbedtls_md4_update_ret( ctx, (unsigned char *)md4_padding, padn ); + if( ret != 0 ) + return( ret ); + + if( ( ret = mbedtls_md4_update_ret( ctx, msglen, 8 ) ) != 0 ) + return( ret ); + + + PUT_UINT32_LE( ctx->state[0], output, 0 ); + PUT_UINT32_LE( ctx->state[1], output, 4 ); + PUT_UINT32_LE( ctx->state[2], output, 8 ); + PUT_UINT32_LE( ctx->state[3], output, 12 ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md4_finish( mbedtls_md4_context *ctx, + unsigned char output[16] ) +{ + mbedtls_md4_finish_ret( ctx, output ); +} +#endif + +#endif /* !MBEDTLS_MD4_ALT */ + +/* + * output = MD4( input buffer ) + */ +int mbedtls_md4_ret( const unsigned char *input, + size_t ilen, + unsigned char output[16] ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_md4_context ctx; + + mbedtls_md4_init( &ctx ); + + if( ( ret = mbedtls_md4_starts_ret( &ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md4_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md4_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_md4_free( &ctx ); + + return( ret ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md4( const unsigned char *input, + size_t ilen, + unsigned char output[16] ) +{ + mbedtls_md4_ret( input, ilen, output ); +} +#endif + +#if defined(MBEDTLS_SELF_TEST) + +/* + * RFC 1320 test vectors + */ +static const unsigned char md4_test_str[7][81] = +{ + { "" }, + { "a" }, + { "abc" }, + { "message digest" }, + { "abcdefghijklmnopqrstuvwxyz" }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, + { "12345678901234567890123456789012345678901234567890123456789012345678901234567890" } +}; + +static const size_t md4_test_strlen[7] = +{ + 0, 1, 3, 14, 26, 62, 80 +}; + +static const unsigned char md4_test_sum[7][16] = +{ + { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31, + 0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 }, + { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46, + 0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 }, + { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52, + 0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D }, + { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8, + 0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B }, + { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD, + 0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 }, + { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35, + 0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 }, + { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19, + 0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 } +}; + +/* + * Checkup routine + */ +int mbedtls_md4_self_test( int verbose ) +{ + int i, ret = 0; + unsigned char md4sum[16]; + + for( i = 0; i < 7; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " MD4 test #%d: ", i + 1 ); + + ret = mbedtls_md4_ret( md4_test_str[i], md4_test_strlen[i], md4sum ); + if( ret != 0 ) + goto fail; + + if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 ) + { + ret = 1; + goto fail; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_MD4_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/md5.c b/Android/Level4/app/src/main/c/mbedtls/library/md5.c new file mode 100644 index 0000000..1e702b4 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/md5.c @@ -0,0 +1,492 @@ +/* + * RFC 1321 compliant MD5 implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ +/* + * The MD5 algorithm was designed by Ron Rivest in 1991. + * + * http://www.ietf.org/rfc/rfc1321.txt + */ + +#include "common.h" + +#if defined(MBEDTLS_MD5_C) + +#include "mbedtls/md5.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_MD5_ALT) + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_UINT32_LE +#define GET_UINT32_LE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] ) \ + | ( (uint32_t) (b)[(i) + 1] << 8 ) \ + | ( (uint32_t) (b)[(i) + 2] << 16 ) \ + | ( (uint32_t) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef PUT_UINT32_LE +#define PUT_UINT32_LE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ + (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ + (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ + (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ +} +#endif + +void mbedtls_md5_init( mbedtls_md5_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_md5_context ) ); +} + +void mbedtls_md5_free( mbedtls_md5_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md5_context ) ); +} + +void mbedtls_md5_clone( mbedtls_md5_context *dst, + const mbedtls_md5_context *src ) +{ + *dst = *src; +} + +/* + * MD5 context setup + */ +int mbedtls_md5_starts_ret( mbedtls_md5_context *ctx ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md5_starts( mbedtls_md5_context *ctx ) +{ + mbedtls_md5_starts_ret( ctx ); +} +#endif + +#if !defined(MBEDTLS_MD5_PROCESS_ALT) +int mbedtls_internal_md5_process( mbedtls_md5_context *ctx, + const unsigned char data[64] ) +{ + uint32_t X[16], A, B, C, D; + + GET_UINT32_LE( X[ 0], data, 0 ); + GET_UINT32_LE( X[ 1], data, 4 ); + GET_UINT32_LE( X[ 2], data, 8 ); + GET_UINT32_LE( X[ 3], data, 12 ); + GET_UINT32_LE( X[ 4], data, 16 ); + GET_UINT32_LE( X[ 5], data, 20 ); + GET_UINT32_LE( X[ 6], data, 24 ); + GET_UINT32_LE( X[ 7], data, 28 ); + GET_UINT32_LE( X[ 8], data, 32 ); + GET_UINT32_LE( X[ 9], data, 36 ); + GET_UINT32_LE( X[10], data, 40 ); + GET_UINT32_LE( X[11], data, 44 ); + GET_UINT32_LE( X[12], data, 48 ); + GET_UINT32_LE( X[13], data, 52 ); + GET_UINT32_LE( X[14], data, 56 ); + GET_UINT32_LE( X[15], data, 60 ); + +#define S(x,n) \ + ( ( (x) << (n) ) | ( ( (x) & 0xFFFFFFFF) >> ( 32 - (n) ) ) ) + +#define P(a,b,c,d,k,s,t) \ + do \ + { \ + (a) += F((b),(c),(d)) + X[(k)] + (t); \ + (a) = S((a),(s)) + (b); \ + } while( 0 ) + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + +#define F(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) + + P( A, B, C, D, 0, 7, 0xD76AA478 ); + P( D, A, B, C, 1, 12, 0xE8C7B756 ); + P( C, D, A, B, 2, 17, 0x242070DB ); + P( B, C, D, A, 3, 22, 0xC1BDCEEE ); + P( A, B, C, D, 4, 7, 0xF57C0FAF ); + P( D, A, B, C, 5, 12, 0x4787C62A ); + P( C, D, A, B, 6, 17, 0xA8304613 ); + P( B, C, D, A, 7, 22, 0xFD469501 ); + P( A, B, C, D, 8, 7, 0x698098D8 ); + P( D, A, B, C, 9, 12, 0x8B44F7AF ); + P( C, D, A, B, 10, 17, 0xFFFF5BB1 ); + P( B, C, D, A, 11, 22, 0x895CD7BE ); + P( A, B, C, D, 12, 7, 0x6B901122 ); + P( D, A, B, C, 13, 12, 0xFD987193 ); + P( C, D, A, B, 14, 17, 0xA679438E ); + P( B, C, D, A, 15, 22, 0x49B40821 ); + +#undef F + +#define F(x,y,z) ((y) ^ ((z) & ((x) ^ (y)))) + + P( A, B, C, D, 1, 5, 0xF61E2562 ); + P( D, A, B, C, 6, 9, 0xC040B340 ); + P( C, D, A, B, 11, 14, 0x265E5A51 ); + P( B, C, D, A, 0, 20, 0xE9B6C7AA ); + P( A, B, C, D, 5, 5, 0xD62F105D ); + P( D, A, B, C, 10, 9, 0x02441453 ); + P( C, D, A, B, 15, 14, 0xD8A1E681 ); + P( B, C, D, A, 4, 20, 0xE7D3FBC8 ); + P( A, B, C, D, 9, 5, 0x21E1CDE6 ); + P( D, A, B, C, 14, 9, 0xC33707D6 ); + P( C, D, A, B, 3, 14, 0xF4D50D87 ); + P( B, C, D, A, 8, 20, 0x455A14ED ); + P( A, B, C, D, 13, 5, 0xA9E3E905 ); + P( D, A, B, C, 2, 9, 0xFCEFA3F8 ); + P( C, D, A, B, 7, 14, 0x676F02D9 ); + P( B, C, D, A, 12, 20, 0x8D2A4C8A ); + +#undef F + +#define F(x,y,z) ((x) ^ (y) ^ (z)) + + P( A, B, C, D, 5, 4, 0xFFFA3942 ); + P( D, A, B, C, 8, 11, 0x8771F681 ); + P( C, D, A, B, 11, 16, 0x6D9D6122 ); + P( B, C, D, A, 14, 23, 0xFDE5380C ); + P( A, B, C, D, 1, 4, 0xA4BEEA44 ); + P( D, A, B, C, 4, 11, 0x4BDECFA9 ); + P( C, D, A, B, 7, 16, 0xF6BB4B60 ); + P( B, C, D, A, 10, 23, 0xBEBFBC70 ); + P( A, B, C, D, 13, 4, 0x289B7EC6 ); + P( D, A, B, C, 0, 11, 0xEAA127FA ); + P( C, D, A, B, 3, 16, 0xD4EF3085 ); + P( B, C, D, A, 6, 23, 0x04881D05 ); + P( A, B, C, D, 9, 4, 0xD9D4D039 ); + P( D, A, B, C, 12, 11, 0xE6DB99E5 ); + P( C, D, A, B, 15, 16, 0x1FA27CF8 ); + P( B, C, D, A, 2, 23, 0xC4AC5665 ); + +#undef F + +#define F(x,y,z) ((y) ^ ((x) | ~(z))) + + P( A, B, C, D, 0, 6, 0xF4292244 ); + P( D, A, B, C, 7, 10, 0x432AFF97 ); + P( C, D, A, B, 14, 15, 0xAB9423A7 ); + P( B, C, D, A, 5, 21, 0xFC93A039 ); + P( A, B, C, D, 12, 6, 0x655B59C3 ); + P( D, A, B, C, 3, 10, 0x8F0CCC92 ); + P( C, D, A, B, 10, 15, 0xFFEFF47D ); + P( B, C, D, A, 1, 21, 0x85845DD1 ); + P( A, B, C, D, 8, 6, 0x6FA87E4F ); + P( D, A, B, C, 15, 10, 0xFE2CE6E0 ); + P( C, D, A, B, 6, 15, 0xA3014314 ); + P( B, C, D, A, 13, 21, 0x4E0811A1 ); + P( A, B, C, D, 4, 6, 0xF7537E82 ); + P( D, A, B, C, 11, 10, 0xBD3AF235 ); + P( C, D, A, B, 2, 15, 0x2AD7D2BB ); + P( B, C, D, A, 9, 21, 0xEB86D391 ); + +#undef F + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md5_process( mbedtls_md5_context *ctx, + const unsigned char data[64] ) +{ + mbedtls_internal_md5_process( ctx, data ); +} +#endif +#endif /* !MBEDTLS_MD5_PROCESS_ALT */ + +/* + * MD5 process buffer + */ +int mbedtls_md5_update_ret( mbedtls_md5_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t fill; + uint32_t left; + + if( ilen == 0 ) + return( 0 ); + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (uint32_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), input, fill ); + if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + if( ( ret = mbedtls_internal_md5_process( ctx, input ) ) != 0 ) + return( ret ); + + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + { + memcpy( (void *) (ctx->buffer + left), input, ilen ); + } + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md5_update( mbedtls_md5_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + mbedtls_md5_update_ret( ctx, input, ilen ); +} +#endif + +/* + * MD5 final digest + */ +int mbedtls_md5_finish_ret( mbedtls_md5_context *ctx, + unsigned char output[16] ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + uint32_t used; + uint32_t high, low; + + /* + * Add padding: 0x80 then 0x00 until 8 bytes remain for the length + */ + used = ctx->total[0] & 0x3F; + + ctx->buffer[used++] = 0x80; + + if( used <= 56 ) + { + /* Enough room for padding + length in current block */ + memset( ctx->buffer + used, 0, 56 - used ); + } + else + { + /* We'll need an extra block */ + memset( ctx->buffer + used, 0, 64 - used ); + + if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + memset( ctx->buffer, 0, 56 ); + } + + /* + * Add message length + */ + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT32_LE( low, ctx->buffer, 56 ); + PUT_UINT32_LE( high, ctx->buffer, 60 ); + + if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + /* + * Output final state + */ + PUT_UINT32_LE( ctx->state[0], output, 0 ); + PUT_UINT32_LE( ctx->state[1], output, 4 ); + PUT_UINT32_LE( ctx->state[2], output, 8 ); + PUT_UINT32_LE( ctx->state[3], output, 12 ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md5_finish( mbedtls_md5_context *ctx, + unsigned char output[16] ) +{ + mbedtls_md5_finish_ret( ctx, output ); +} +#endif + +#endif /* !MBEDTLS_MD5_ALT */ + +/* + * output = MD5( input buffer ) + */ +int mbedtls_md5_ret( const unsigned char *input, + size_t ilen, + unsigned char output[16] ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_md5_context ctx; + + mbedtls_md5_init( &ctx ); + + if( ( ret = mbedtls_md5_starts_ret( &ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md5_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md5_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_md5_free( &ctx ); + + return( ret ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md5( const unsigned char *input, + size_t ilen, + unsigned char output[16] ) +{ + mbedtls_md5_ret( input, ilen, output ); +} +#endif + +#if defined(MBEDTLS_SELF_TEST) +/* + * RFC 1321 test vectors + */ +static const unsigned char md5_test_buf[7][81] = +{ + { "" }, + { "a" }, + { "abc" }, + { "message digest" }, + { "abcdefghijklmnopqrstuvwxyz" }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, + { "12345678901234567890123456789012345678901234567890123456789012345678901234567890" } +}; + +static const size_t md5_test_buflen[7] = +{ + 0, 1, 3, 14, 26, 62, 80 +}; + +static const unsigned char md5_test_sum[7][16] = +{ + { 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04, + 0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E }, + { 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8, + 0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 }, + { 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0, + 0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 }, + { 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D, + 0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 }, + { 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00, + 0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B }, + { 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5, + 0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F }, + { 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55, + 0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A } +}; + +/* + * Checkup routine + */ +int mbedtls_md5_self_test( int verbose ) +{ + int i, ret = 0; + unsigned char md5sum[16]; + + for( i = 0; i < 7; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " MD5 test #%d: ", i + 1 ); + + ret = mbedtls_md5_ret( md5_test_buf[i], md5_test_buflen[i], md5sum ); + if( ret != 0 ) + goto fail; + + if( memcmp( md5sum, md5_test_sum[i], 16 ) != 0 ) + { + ret = 1; + goto fail; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_MD5_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/memory_buffer_alloc.c b/Android/Level4/app/src/main/c/mbedtls/library/memory_buffer_alloc.c new file mode 100644 index 0000000..0d5d27d --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/memory_buffer_alloc.c @@ -0,0 +1,744 @@ +/* + * Buffer-based memory allocator + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 "common.h" + +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) +#include "mbedtls/memory_buffer_alloc.h" + +/* No need for the header guard as MBEDTLS_MEMORY_BUFFER_ALLOC_C + is dependent upon MBEDTLS_PLATFORM_C */ +#include "mbedtls/platform.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_MEMORY_BACKTRACE) +#include +#endif + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +#define MAGIC1 0xFF00AA55 +#define MAGIC2 0xEE119966 +#define MAX_BT 20 + +typedef struct _memory_header memory_header; +struct _memory_header +{ + size_t magic1; + size_t size; + size_t alloc; + memory_header *prev; + memory_header *next; + memory_header *prev_free; + memory_header *next_free; +#if defined(MBEDTLS_MEMORY_BACKTRACE) + char **trace; + size_t trace_count; +#endif + size_t magic2; +}; + +typedef struct +{ + unsigned char *buf; + size_t len; + memory_header *first; + memory_header *first_free; + int verify; +#if defined(MBEDTLS_MEMORY_DEBUG) + size_t alloc_count; + size_t free_count; + size_t total_used; + size_t maximum_used; + size_t header_count; + size_t maximum_header_count; +#endif +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; +#endif +} +buffer_alloc_ctx; + +static buffer_alloc_ctx heap; + +#if defined(MBEDTLS_MEMORY_DEBUG) +static void debug_header( memory_header *hdr ) +{ +#if defined(MBEDTLS_MEMORY_BACKTRACE) + size_t i; +#endif + + mbedtls_fprintf( stderr, "HDR: PTR(%10zu), PREV(%10zu), NEXT(%10zu), " + "ALLOC(%zu), SIZE(%10zu)\n", + (size_t) hdr, (size_t) hdr->prev, (size_t) hdr->next, + hdr->alloc, hdr->size ); + mbedtls_fprintf( stderr, " FPREV(%10zu), FNEXT(%10zu)\n", + (size_t) hdr->prev_free, (size_t) hdr->next_free ); + +#if defined(MBEDTLS_MEMORY_BACKTRACE) + mbedtls_fprintf( stderr, "TRACE: \n" ); + for( i = 0; i < hdr->trace_count; i++ ) + mbedtls_fprintf( stderr, "%s\n", hdr->trace[i] ); + mbedtls_fprintf( stderr, "\n" ); +#endif +} + +static void debug_chain( void ) +{ + memory_header *cur = heap.first; + + mbedtls_fprintf( stderr, "\nBlock list\n" ); + while( cur != NULL ) + { + debug_header( cur ); + cur = cur->next; + } + + mbedtls_fprintf( stderr, "Free list\n" ); + cur = heap.first_free; + + while( cur != NULL ) + { + debug_header( cur ); + cur = cur->next_free; + } +} +#endif /* MBEDTLS_MEMORY_DEBUG */ + +static int verify_header( memory_header *hdr ) +{ + if( hdr->magic1 != MAGIC1 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: MAGIC1 mismatch\n" ); +#endif + return( 1 ); + } + + if( hdr->magic2 != MAGIC2 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: MAGIC2 mismatch\n" ); +#endif + return( 1 ); + } + + if( hdr->alloc > 1 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: alloc has illegal value\n" ); +#endif + return( 1 ); + } + + if( hdr->prev != NULL && hdr->prev == hdr->next ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: prev == next\n" ); +#endif + return( 1 ); + } + + if( hdr->prev_free != NULL && hdr->prev_free == hdr->next_free ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: prev_free == next_free\n" ); +#endif + return( 1 ); + } + + return( 0 ); +} + +static int verify_chain( void ) +{ + memory_header *prv = heap.first, *cur; + + if( prv == NULL || verify_header( prv ) != 0 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: verification of first header " + "failed\n" ); +#endif + return( 1 ); + } + + if( heap.first->prev != NULL ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: verification failed: " + "first->prev != NULL\n" ); +#endif + return( 1 ); + } + + cur = heap.first->next; + + while( cur != NULL ) + { + if( verify_header( cur ) != 0 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: verification of header " + "failed\n" ); +#endif + return( 1 ); + } + + if( cur->prev != prv ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: verification failed: " + "cur->prev != prv\n" ); +#endif + return( 1 ); + } + + prv = cur; + cur = cur->next; + } + + return( 0 ); +} + +static void *buffer_alloc_calloc( size_t n, size_t size ) +{ + memory_header *new, *cur = heap.first_free; + unsigned char *p; + void *ret; + size_t original_len, len; +#if defined(MBEDTLS_MEMORY_BACKTRACE) + void *trace_buffer[MAX_BT]; + size_t trace_cnt; +#endif + + if( heap.buf == NULL || heap.first == NULL ) + return( NULL ); + + original_len = len = n * size; + + if( n == 0 || size == 0 || len / n != size ) + return( NULL ); + else if( len > (size_t)-MBEDTLS_MEMORY_ALIGN_MULTIPLE ) + return( NULL ); + + if( len % MBEDTLS_MEMORY_ALIGN_MULTIPLE ) + { + len -= len % MBEDTLS_MEMORY_ALIGN_MULTIPLE; + len += MBEDTLS_MEMORY_ALIGN_MULTIPLE; + } + + // Find block that fits + // + while( cur != NULL ) + { + if( cur->size >= len ) + break; + + cur = cur->next_free; + } + + if( cur == NULL ) + return( NULL ); + + if( cur->alloc != 0 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: block in free_list but allocated " + "data\n" ); +#endif + mbedtls_exit( 1 ); + } + +#if defined(MBEDTLS_MEMORY_DEBUG) + heap.alloc_count++; +#endif + + // Found location, split block if > memory_header + 4 room left + // + if( cur->size - len < sizeof(memory_header) + + MBEDTLS_MEMORY_ALIGN_MULTIPLE ) + { + cur->alloc = 1; + + // Remove from free_list + // + if( cur->prev_free != NULL ) + cur->prev_free->next_free = cur->next_free; + else + heap.first_free = cur->next_free; + + if( cur->next_free != NULL ) + cur->next_free->prev_free = cur->prev_free; + + cur->prev_free = NULL; + cur->next_free = NULL; + +#if defined(MBEDTLS_MEMORY_DEBUG) + heap.total_used += cur->size; + if( heap.total_used > heap.maximum_used ) + heap.maximum_used = heap.total_used; +#endif +#if defined(MBEDTLS_MEMORY_BACKTRACE) + trace_cnt = backtrace( trace_buffer, MAX_BT ); + cur->trace = backtrace_symbols( trace_buffer, trace_cnt ); + cur->trace_count = trace_cnt; +#endif + + if( ( heap.verify & MBEDTLS_MEMORY_VERIFY_ALLOC ) && verify_chain() != 0 ) + mbedtls_exit( 1 ); + + ret = (unsigned char *) cur + sizeof( memory_header ); + memset( ret, 0, original_len ); + + return( ret ); + } + + p = ( (unsigned char *) cur ) + sizeof(memory_header) + len; + new = (memory_header *) p; + + new->size = cur->size - len - sizeof(memory_header); + new->alloc = 0; + new->prev = cur; + new->next = cur->next; +#if defined(MBEDTLS_MEMORY_BACKTRACE) + new->trace = NULL; + new->trace_count = 0; +#endif + new->magic1 = MAGIC1; + new->magic2 = MAGIC2; + + if( new->next != NULL ) + new->next->prev = new; + + // Replace cur with new in free_list + // + new->prev_free = cur->prev_free; + new->next_free = cur->next_free; + if( new->prev_free != NULL ) + new->prev_free->next_free = new; + else + heap.first_free = new; + + if( new->next_free != NULL ) + new->next_free->prev_free = new; + + cur->alloc = 1; + cur->size = len; + cur->next = new; + cur->prev_free = NULL; + cur->next_free = NULL; + +#if defined(MBEDTLS_MEMORY_DEBUG) + heap.header_count++; + if( heap.header_count > heap.maximum_header_count ) + heap.maximum_header_count = heap.header_count; + heap.total_used += cur->size; + if( heap.total_used > heap.maximum_used ) + heap.maximum_used = heap.total_used; +#endif +#if defined(MBEDTLS_MEMORY_BACKTRACE) + trace_cnt = backtrace( trace_buffer, MAX_BT ); + cur->trace = backtrace_symbols( trace_buffer, trace_cnt ); + cur->trace_count = trace_cnt; +#endif + + if( ( heap.verify & MBEDTLS_MEMORY_VERIFY_ALLOC ) && verify_chain() != 0 ) + mbedtls_exit( 1 ); + + ret = (unsigned char *) cur + sizeof( memory_header ); + memset( ret, 0, original_len ); + + return( ret ); +} + +static void buffer_alloc_free( void *ptr ) +{ + memory_header *hdr, *old = NULL; + unsigned char *p = (unsigned char *) ptr; + + if( ptr == NULL || heap.buf == NULL || heap.first == NULL ) + return; + + if( p < heap.buf || p >= heap.buf + heap.len ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: mbedtls_free() outside of managed " + "space\n" ); +#endif + mbedtls_exit( 1 ); + } + + p -= sizeof(memory_header); + hdr = (memory_header *) p; + + if( verify_header( hdr ) != 0 ) + mbedtls_exit( 1 ); + + if( hdr->alloc != 1 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: mbedtls_free() on unallocated " + "data\n" ); +#endif + mbedtls_exit( 1 ); + } + + hdr->alloc = 0; + +#if defined(MBEDTLS_MEMORY_DEBUG) + heap.free_count++; + heap.total_used -= hdr->size; +#endif + +#if defined(MBEDTLS_MEMORY_BACKTRACE) + free( hdr->trace ); + hdr->trace = NULL; + hdr->trace_count = 0; +#endif + + // Regroup with block before + // + if( hdr->prev != NULL && hdr->prev->alloc == 0 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + heap.header_count--; +#endif + hdr->prev->size += sizeof(memory_header) + hdr->size; + hdr->prev->next = hdr->next; + old = hdr; + hdr = hdr->prev; + + if( hdr->next != NULL ) + hdr->next->prev = hdr; + + memset( old, 0, sizeof(memory_header) ); + } + + // Regroup with block after + // + if( hdr->next != NULL && hdr->next->alloc == 0 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + heap.header_count--; +#endif + hdr->size += sizeof(memory_header) + hdr->next->size; + old = hdr->next; + hdr->next = hdr->next->next; + + if( hdr->prev_free != NULL || hdr->next_free != NULL ) + { + if( hdr->prev_free != NULL ) + hdr->prev_free->next_free = hdr->next_free; + else + heap.first_free = hdr->next_free; + + if( hdr->next_free != NULL ) + hdr->next_free->prev_free = hdr->prev_free; + } + + hdr->prev_free = old->prev_free; + hdr->next_free = old->next_free; + + if( hdr->prev_free != NULL ) + hdr->prev_free->next_free = hdr; + else + heap.first_free = hdr; + + if( hdr->next_free != NULL ) + hdr->next_free->prev_free = hdr; + + if( hdr->next != NULL ) + hdr->next->prev = hdr; + + memset( old, 0, sizeof(memory_header) ); + } + + // Prepend to free_list if we have not merged + // (Does not have to stay in same order as prev / next list) + // + if( old == NULL ) + { + hdr->next_free = heap.first_free; + if( heap.first_free != NULL ) + heap.first_free->prev_free = hdr; + heap.first_free = hdr; + } + + if( ( heap.verify & MBEDTLS_MEMORY_VERIFY_FREE ) && verify_chain() != 0 ) + mbedtls_exit( 1 ); +} + +void mbedtls_memory_buffer_set_verify( int verify ) +{ + heap.verify = verify; +} + +int mbedtls_memory_buffer_alloc_verify( void ) +{ + return verify_chain(); +} + +#if defined(MBEDTLS_MEMORY_DEBUG) +void mbedtls_memory_buffer_alloc_status( void ) +{ + mbedtls_fprintf( stderr, + "Current use: %zu blocks / %zu bytes, max: %zu blocks / " + "%zu bytes (total %zu bytes), alloc / free: %zu / %zu\n", + heap.header_count, heap.total_used, + heap.maximum_header_count, heap.maximum_used, + heap.maximum_header_count * sizeof( memory_header ) + + heap.maximum_used, + heap.alloc_count, heap.free_count ); + + if( heap.first->next == NULL ) + { + mbedtls_fprintf( stderr, "All memory de-allocated in stack buffer\n" ); + } + else + { + mbedtls_fprintf( stderr, "Memory currently allocated:\n" ); + debug_chain(); + } +} + +void mbedtls_memory_buffer_alloc_max_get( size_t *max_used, size_t *max_blocks ) +{ + *max_used = heap.maximum_used; + *max_blocks = heap.maximum_header_count; +} + +void mbedtls_memory_buffer_alloc_max_reset( void ) +{ + heap.maximum_used = 0; + heap.maximum_header_count = 0; +} + +void mbedtls_memory_buffer_alloc_cur_get( size_t *cur_used, size_t *cur_blocks ) +{ + *cur_used = heap.total_used; + *cur_blocks = heap.header_count; +} +#endif /* MBEDTLS_MEMORY_DEBUG */ + +#if defined(MBEDTLS_THREADING_C) +static void *buffer_alloc_calloc_mutexed( size_t n, size_t size ) +{ + void *buf; + if( mbedtls_mutex_lock( &heap.mutex ) != 0 ) + return( NULL ); + buf = buffer_alloc_calloc( n, size ); + if( mbedtls_mutex_unlock( &heap.mutex ) ) + return( NULL ); + return( buf ); +} + +static void buffer_alloc_free_mutexed( void *ptr ) +{ + /* We have to good option here, but corrupting the heap seems + * worse than loosing memory. */ + if( mbedtls_mutex_lock( &heap.mutex ) ) + return; + buffer_alloc_free( ptr ); + (void) mbedtls_mutex_unlock( &heap.mutex ); +} +#endif /* MBEDTLS_THREADING_C */ + +void mbedtls_memory_buffer_alloc_init( unsigned char *buf, size_t len ) +{ + memset( &heap, 0, sizeof( buffer_alloc_ctx ) ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &heap.mutex ); + mbedtls_platform_set_calloc_free( buffer_alloc_calloc_mutexed, + buffer_alloc_free_mutexed ); +#else + mbedtls_platform_set_calloc_free( buffer_alloc_calloc, buffer_alloc_free ); +#endif + + if( len < sizeof( memory_header ) + MBEDTLS_MEMORY_ALIGN_MULTIPLE ) + return; + else if( (size_t)buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE ) + { + /* Adjust len first since buf is used in the computation */ + len -= MBEDTLS_MEMORY_ALIGN_MULTIPLE + - (size_t)buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE; + buf += MBEDTLS_MEMORY_ALIGN_MULTIPLE + - (size_t)buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE; + } + + memset( buf, 0, len ); + + heap.buf = buf; + heap.len = len; + + heap.first = (memory_header *)buf; + heap.first->size = len - sizeof( memory_header ); + heap.first->magic1 = MAGIC1; + heap.first->magic2 = MAGIC2; + heap.first_free = heap.first; +} + +void mbedtls_memory_buffer_alloc_free( void ) +{ +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free( &heap.mutex ); +#endif + mbedtls_platform_zeroize( &heap, sizeof(buffer_alloc_ctx) ); +} + +#if defined(MBEDTLS_SELF_TEST) +static int check_pointer( void *p ) +{ + if( p == NULL ) + return( -1 ); + + if( (size_t) p % MBEDTLS_MEMORY_ALIGN_MULTIPLE != 0 ) + return( -1 ); + + return( 0 ); +} + +static int check_all_free( void ) +{ + if( +#if defined(MBEDTLS_MEMORY_DEBUG) + heap.total_used != 0 || +#endif + heap.first != heap.first_free || + (void *) heap.first != (void *) heap.buf ) + { + return( -1 ); + } + + return( 0 ); +} + +#define TEST_ASSERT( condition ) \ + if( ! (condition) ) \ + { \ + if( verbose != 0 ) \ + mbedtls_printf( "failed\n" ); \ + \ + ret = 1; \ + goto cleanup; \ + } + +int mbedtls_memory_buffer_alloc_self_test( int verbose ) +{ + unsigned char buf[1024]; + unsigned char *p, *q, *r, *end; + int ret = 0; + + if( verbose != 0 ) + mbedtls_printf( " MBA test #1 (basic alloc-free cycle): " ); + + mbedtls_memory_buffer_alloc_init( buf, sizeof( buf ) ); + + p = mbedtls_calloc( 1, 1 ); + q = mbedtls_calloc( 1, 128 ); + r = mbedtls_calloc( 1, 16 ); + + TEST_ASSERT( check_pointer( p ) == 0 && + check_pointer( q ) == 0 && + check_pointer( r ) == 0 ); + + mbedtls_free( r ); + mbedtls_free( q ); + mbedtls_free( p ); + + TEST_ASSERT( check_all_free( ) == 0 ); + + /* Memorize end to compare with the next test */ + end = heap.buf + heap.len; + + mbedtls_memory_buffer_alloc_free( ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " MBA test #2 (buf not aligned): " ); + + mbedtls_memory_buffer_alloc_init( buf + 1, sizeof( buf ) - 1 ); + + TEST_ASSERT( heap.buf + heap.len == end ); + + p = mbedtls_calloc( 1, 1 ); + q = mbedtls_calloc( 1, 128 ); + r = mbedtls_calloc( 1, 16 ); + + TEST_ASSERT( check_pointer( p ) == 0 && + check_pointer( q ) == 0 && + check_pointer( r ) == 0 ); + + mbedtls_free( r ); + mbedtls_free( q ); + mbedtls_free( p ); + + TEST_ASSERT( check_all_free( ) == 0 ); + + mbedtls_memory_buffer_alloc_free( ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " MBA test #3 (full): " ); + + mbedtls_memory_buffer_alloc_init( buf, sizeof( buf ) ); + + p = mbedtls_calloc( 1, sizeof( buf ) - sizeof( memory_header ) ); + + TEST_ASSERT( check_pointer( p ) == 0 ); + TEST_ASSERT( mbedtls_calloc( 1, 1 ) == NULL ); + + mbedtls_free( p ); + + p = mbedtls_calloc( 1, sizeof( buf ) - 2 * sizeof( memory_header ) - 16 ); + q = mbedtls_calloc( 1, 16 ); + + TEST_ASSERT( check_pointer( p ) == 0 && check_pointer( q ) == 0 ); + TEST_ASSERT( mbedtls_calloc( 1, 1 ) == NULL ); + + mbedtls_free( q ); + + TEST_ASSERT( mbedtls_calloc( 1, 17 ) == NULL ); + + mbedtls_free( p ); + + TEST_ASSERT( check_all_free( ) == 0 ); + + mbedtls_memory_buffer_alloc_free( ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + +cleanup: + mbedtls_memory_buffer_alloc_free( ); + + return( ret ); +} +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_MEMORY_BUFFER_ALLOC_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/net_sockets.c b/Android/Level4/app/src/main/c/mbedtls/library/net_sockets.c new file mode 100644 index 0000000..54c2b47 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/net_sockets.c @@ -0,0 +1,680 @@ +/* + * TCP/IP or UDP/IP networking functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ + +/* Enable definition of getaddrinfo() even when compiling with -std=c99. Must + * be set before config.h, which pulls in glibc's features.h indirectly. + * Harmless on other platforms. */ +#define _POSIX_C_SOURCE 200112L +#define _XOPEN_SOURCE 600 /* sockaddr_storage */ + +#include "common.h" + +#if defined(MBEDTLS_NET_C) + +#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ + !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \ + !defined(__HAIKU__) && !defined(__midipix__) +#error "This module only works on Unix and Windows, see MBEDTLS_NET_C in config.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#endif + +#include "mbedtls/net_sockets.h" +#include "mbedtls/error.h" + +#include + +#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \ + !defined(EFI32) + +#define IS_EINTR( ret ) ( ( ret ) == WSAEINTR ) + +#if !defined(_WIN32_WINNT) +/* Enables getaddrinfo() & Co */ +#define _WIN32_WINNT 0x0501 +#endif + +#include + +#include +#include +#if (_WIN32_WINNT < 0x0501) +#include +#endif + +#if defined(_MSC_VER) +#if defined(_WIN32_WCE) +#pragma comment( lib, "ws2.lib" ) +#else +#pragma comment( lib, "ws2_32.lib" ) +#endif +#endif /* _MSC_VER */ + +#define read(fd,buf,len) recv( fd, (char*)( buf ), (int)( len ), 0 ) +#define write(fd,buf,len) send( fd, (char*)( buf ), (int)( len ), 0 ) +#define close(fd) closesocket(fd) + +static int wsa_init_done = 0; + +#else /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IS_EINTR( ret ) ( ( ret ) == EINTR ) + +#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ + +/* Some MS functions want int and MSVC warns if we pass size_t, + * but the standard functions use socklen_t, so cast only for MSVC */ +#if defined(_MSC_VER) +#define MSVC_INT_CAST (int) +#else +#define MSVC_INT_CAST +#endif + +#include + +#include + +#include + +/* + * Prepare for using the sockets interface + */ +static int net_prepare( void ) +{ +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + WSADATA wsaData; + + if( wsa_init_done == 0 ) + { + if( WSAStartup( MAKEWORD(2,0), &wsaData ) != 0 ) + return( MBEDTLS_ERR_NET_SOCKET_FAILED ); + + wsa_init_done = 1; + } +#else +#if !defined(EFIX64) && !defined(EFI32) + signal( SIGPIPE, SIG_IGN ); +#endif +#endif + return( 0 ); +} + +/* + * Initialize a context + */ +void mbedtls_net_init( mbedtls_net_context *ctx ) +{ + ctx->fd = -1; +} + +/* + * Initiate a TCP connection with host:port and the given protocol + */ +int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, + const char *port, int proto ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + struct addrinfo hints, *addr_list, *cur; + + if( ( ret = net_prepare() ) != 0 ) + return( ret ); + + /* Do name resolution with both IPv6 and IPv4 */ + memset( &hints, 0, sizeof( hints ) ); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM; + hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP; + + if( getaddrinfo( host, port, &hints, &addr_list ) != 0 ) + return( MBEDTLS_ERR_NET_UNKNOWN_HOST ); + + /* Try the sockaddrs until a connection succeeds */ + ret = MBEDTLS_ERR_NET_UNKNOWN_HOST; + for( cur = addr_list; cur != NULL; cur = cur->ai_next ) + { + ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype, + cur->ai_protocol ); + if( ctx->fd < 0 ) + { + ret = MBEDTLS_ERR_NET_SOCKET_FAILED; + continue; + } + + if( connect( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) == 0 ) + { + ret = 0; + break; + } + + close( ctx->fd ); + ret = MBEDTLS_ERR_NET_CONNECT_FAILED; + } + + freeaddrinfo( addr_list ); + + return( ret ); +} + +/* + * Create a listening socket on bind_ip:port + */ +int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto ) +{ + int n, ret; + struct addrinfo hints, *addr_list, *cur; + + if( ( ret = net_prepare() ) != 0 ) + return( ret ); + + /* Bind to IPv6 and/or IPv4, but only in the desired protocol */ + memset( &hints, 0, sizeof( hints ) ); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM; + hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP; + if( bind_ip == NULL ) + hints.ai_flags = AI_PASSIVE; + + if( getaddrinfo( bind_ip, port, &hints, &addr_list ) != 0 ) + return( MBEDTLS_ERR_NET_UNKNOWN_HOST ); + + /* Try the sockaddrs until a binding succeeds */ + ret = MBEDTLS_ERR_NET_UNKNOWN_HOST; + for( cur = addr_list; cur != NULL; cur = cur->ai_next ) + { + ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype, + cur->ai_protocol ); + if( ctx->fd < 0 ) + { + ret = MBEDTLS_ERR_NET_SOCKET_FAILED; + continue; + } + + n = 1; + if( setsockopt( ctx->fd, SOL_SOCKET, SO_REUSEADDR, + (const char *) &n, sizeof( n ) ) != 0 ) + { + close( ctx->fd ); + ret = MBEDTLS_ERR_NET_SOCKET_FAILED; + continue; + } + + if( bind( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) != 0 ) + { + close( ctx->fd ); + ret = MBEDTLS_ERR_NET_BIND_FAILED; + continue; + } + + /* Listen only makes sense for TCP */ + if( proto == MBEDTLS_NET_PROTO_TCP ) + { + if( listen( ctx->fd, MBEDTLS_NET_LISTEN_BACKLOG ) != 0 ) + { + close( ctx->fd ); + ret = MBEDTLS_ERR_NET_LISTEN_FAILED; + continue; + } + } + + /* Bind was successful */ + ret = 0; + break; + } + + freeaddrinfo( addr_list ); + + return( ret ); + +} + +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) +/* + * Check if the requested operation would be blocking on a non-blocking socket + * and thus 'failed' with a negative return value. + */ +static int net_would_block( const mbedtls_net_context *ctx ) +{ + ((void) ctx); + return( WSAGetLastError() == WSAEWOULDBLOCK ); +} +#else +/* + * Check if the requested operation would be blocking on a non-blocking socket + * and thus 'failed' with a negative return value. + * + * Note: on a blocking socket this function always returns 0! + */ +static int net_would_block( const mbedtls_net_context *ctx ) +{ + int err = errno; + + /* + * Never return 'WOULD BLOCK' on a blocking socket + */ + if( ( fcntl( ctx->fd, F_GETFL ) & O_NONBLOCK ) != O_NONBLOCK ) + { + errno = err; + return( 0 ); + } + + switch( errno = err ) + { +#if defined EAGAIN + case EAGAIN: +#endif +#if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN + case EWOULDBLOCK: +#endif + return( 1 ); + } + return( 0 ); +} +#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ + +/* + * Accept a connection from a remote client + */ +int mbedtls_net_accept( mbedtls_net_context *bind_ctx, + mbedtls_net_context *client_ctx, + void *client_ip, size_t buf_size, size_t *ip_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + int type; + + struct sockaddr_storage client_addr; + +#if defined(__socklen_t_defined) || defined(_SOCKLEN_T) || \ + defined(_SOCKLEN_T_DECLARED) || defined(__DEFINED_socklen_t) || \ + defined(socklen_t) || (defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L) + socklen_t n = (socklen_t) sizeof( client_addr ); + socklen_t type_len = (socklen_t) sizeof( type ); +#else + int n = (int) sizeof( client_addr ); + int type_len = (int) sizeof( type ); +#endif + + /* Is this a TCP or UDP socket? */ + if( getsockopt( bind_ctx->fd, SOL_SOCKET, SO_TYPE, + (void *) &type, &type_len ) != 0 || + ( type != SOCK_STREAM && type != SOCK_DGRAM ) ) + { + return( MBEDTLS_ERR_NET_ACCEPT_FAILED ); + } + + if( type == SOCK_STREAM ) + { + /* TCP: actual accept() */ + ret = client_ctx->fd = (int) accept( bind_ctx->fd, + (struct sockaddr *) &client_addr, &n ); + } + else + { + /* UDP: wait for a message, but keep it in the queue */ + char buf[1] = { 0 }; + + ret = (int) recvfrom( bind_ctx->fd, buf, sizeof( buf ), MSG_PEEK, + (struct sockaddr *) &client_addr, &n ); + +#if defined(_WIN32) + if( ret == SOCKET_ERROR && + WSAGetLastError() == WSAEMSGSIZE ) + { + /* We know buf is too small, thanks, just peeking here */ + ret = 0; + } +#endif + } + + if( ret < 0 ) + { + if( net_would_block( bind_ctx ) != 0 ) + return( MBEDTLS_ERR_SSL_WANT_READ ); + + return( MBEDTLS_ERR_NET_ACCEPT_FAILED ); + } + + /* UDP: hijack the listening socket to communicate with the client, + * then bind a new socket to accept new connections */ + if( type != SOCK_STREAM ) + { + struct sockaddr_storage local_addr; + int one = 1; + + if( connect( bind_ctx->fd, (struct sockaddr *) &client_addr, n ) != 0 ) + return( MBEDTLS_ERR_NET_ACCEPT_FAILED ); + + client_ctx->fd = bind_ctx->fd; + bind_ctx->fd = -1; /* In case we exit early */ + + n = sizeof( struct sockaddr_storage ); + if( getsockname( client_ctx->fd, + (struct sockaddr *) &local_addr, &n ) != 0 || + ( bind_ctx->fd = (int) socket( local_addr.ss_family, + SOCK_DGRAM, IPPROTO_UDP ) ) < 0 || + setsockopt( bind_ctx->fd, SOL_SOCKET, SO_REUSEADDR, + (const char *) &one, sizeof( one ) ) != 0 ) + { + return( MBEDTLS_ERR_NET_SOCKET_FAILED ); + } + + if( bind( bind_ctx->fd, (struct sockaddr *) &local_addr, n ) != 0 ) + { + return( MBEDTLS_ERR_NET_BIND_FAILED ); + } + } + + if( client_ip != NULL ) + { + if( client_addr.ss_family == AF_INET ) + { + struct sockaddr_in *addr4 = (struct sockaddr_in *) &client_addr; + *ip_len = sizeof( addr4->sin_addr.s_addr ); + + if( buf_size < *ip_len ) + return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL ); + + memcpy( client_ip, &addr4->sin_addr.s_addr, *ip_len ); + } + else + { + struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &client_addr; + *ip_len = sizeof( addr6->sin6_addr.s6_addr ); + + if( buf_size < *ip_len ) + return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL ); + + memcpy( client_ip, &addr6->sin6_addr.s6_addr, *ip_len); + } + } + + return( 0 ); +} + +/* + * Set the socket blocking or non-blocking + */ +int mbedtls_net_set_block( mbedtls_net_context *ctx ) +{ +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + u_long n = 0; + return( ioctlsocket( ctx->fd, FIONBIO, &n ) ); +#else + return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL ) & ~O_NONBLOCK ) ); +#endif +} + +int mbedtls_net_set_nonblock( mbedtls_net_context *ctx ) +{ +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + u_long n = 1; + return( ioctlsocket( ctx->fd, FIONBIO, &n ) ); +#else + return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL ) | O_NONBLOCK ) ); +#endif +} + +/* + * Check if data is available on the socket + */ + +int mbedtls_net_poll( mbedtls_net_context *ctx, uint32_t rw, uint32_t timeout ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + struct timeval tv; + + fd_set read_fds; + fd_set write_fds; + + int fd = ctx->fd; + + if( fd < 0 ) + return( MBEDTLS_ERR_NET_INVALID_CONTEXT ); + +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) + /* Ensure that memory sanitizers consider read_fds and write_fds as + * initialized even on platforms such as Glibc/x86_64 where FD_ZERO + * is implemented in assembly. */ + memset( &read_fds, 0, sizeof( read_fds ) ); + memset( &write_fds, 0, sizeof( write_fds ) ); +#endif +#endif + + FD_ZERO( &read_fds ); + if( rw & MBEDTLS_NET_POLL_READ ) + { + rw &= ~MBEDTLS_NET_POLL_READ; + FD_SET( fd, &read_fds ); + } + + FD_ZERO( &write_fds ); + if( rw & MBEDTLS_NET_POLL_WRITE ) + { + rw &= ~MBEDTLS_NET_POLL_WRITE; + FD_SET( fd, &write_fds ); + } + + if( rw != 0 ) + return( MBEDTLS_ERR_NET_BAD_INPUT_DATA ); + + tv.tv_sec = timeout / 1000; + tv.tv_usec = ( timeout % 1000 ) * 1000; + + do + { + ret = select( fd + 1, &read_fds, &write_fds, NULL, + timeout == (uint32_t) -1 ? NULL : &tv ); + } + while( IS_EINTR( ret ) ); + + if( ret < 0 ) + return( MBEDTLS_ERR_NET_POLL_FAILED ); + + ret = 0; + if( FD_ISSET( fd, &read_fds ) ) + ret |= MBEDTLS_NET_POLL_READ; + if( FD_ISSET( fd, &write_fds ) ) + ret |= MBEDTLS_NET_POLL_WRITE; + + return( ret ); +} + +/* + * Portable usleep helper + */ +void mbedtls_net_usleep( unsigned long usec ) +{ +#if defined(_WIN32) + Sleep( ( usec + 999 ) / 1000 ); +#else + struct timeval tv; + tv.tv_sec = usec / 1000000; +#if defined(__unix__) || defined(__unix) || \ + ( defined(__APPLE__) && defined(__MACH__) ) + tv.tv_usec = (suseconds_t) usec % 1000000; +#else + tv.tv_usec = usec % 1000000; +#endif + select( 0, NULL, NULL, NULL, &tv ); +#endif +} + +/* + * Read at most 'len' characters + */ +int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + int fd = ((mbedtls_net_context *) ctx)->fd; + + if( fd < 0 ) + return( MBEDTLS_ERR_NET_INVALID_CONTEXT ); + + ret = (int) read( fd, buf, len ); + + if( ret < 0 ) + { + if( net_would_block( ctx ) != 0 ) + return( MBEDTLS_ERR_SSL_WANT_READ ); + +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + if( WSAGetLastError() == WSAECONNRESET ) + return( MBEDTLS_ERR_NET_CONN_RESET ); +#else + if( errno == EPIPE || errno == ECONNRESET ) + return( MBEDTLS_ERR_NET_CONN_RESET ); + + if( errno == EINTR ) + return( MBEDTLS_ERR_SSL_WANT_READ ); +#endif + + return( MBEDTLS_ERR_NET_RECV_FAILED ); + } + + return( ret ); +} + +/* + * Read at most 'len' characters, blocking for at most 'timeout' ms + */ +int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, + size_t len, uint32_t timeout ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + struct timeval tv; + fd_set read_fds; + int fd = ((mbedtls_net_context *) ctx)->fd; + + if( fd < 0 ) + return( MBEDTLS_ERR_NET_INVALID_CONTEXT ); + + FD_ZERO( &read_fds ); + FD_SET( fd, &read_fds ); + + tv.tv_sec = timeout / 1000; + tv.tv_usec = ( timeout % 1000 ) * 1000; + + ret = select( fd + 1, &read_fds, NULL, NULL, timeout == 0 ? NULL : &tv ); + + /* Zero fds ready means we timed out */ + if( ret == 0 ) + return( MBEDTLS_ERR_SSL_TIMEOUT ); + + if( ret < 0 ) + { +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + if( WSAGetLastError() == WSAEINTR ) + return( MBEDTLS_ERR_SSL_WANT_READ ); +#else + if( errno == EINTR ) + return( MBEDTLS_ERR_SSL_WANT_READ ); +#endif + + return( MBEDTLS_ERR_NET_RECV_FAILED ); + } + + /* This call will not block */ + return( mbedtls_net_recv( ctx, buf, len ) ); +} + +/* + * Write at most 'len' characters + */ +int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + int fd = ((mbedtls_net_context *) ctx)->fd; + + if( fd < 0 ) + return( MBEDTLS_ERR_NET_INVALID_CONTEXT ); + + ret = (int) write( fd, buf, len ); + + if( ret < 0 ) + { + if( net_would_block( ctx ) != 0 ) + return( MBEDTLS_ERR_SSL_WANT_WRITE ); + +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + if( WSAGetLastError() == WSAECONNRESET ) + return( MBEDTLS_ERR_NET_CONN_RESET ); +#else + if( errno == EPIPE || errno == ECONNRESET ) + return( MBEDTLS_ERR_NET_CONN_RESET ); + + if( errno == EINTR ) + return( MBEDTLS_ERR_SSL_WANT_WRITE ); +#endif + + return( MBEDTLS_ERR_NET_SEND_FAILED ); + } + + return( ret ); +} + +/* + * Close the connection + */ +void mbedtls_net_close( mbedtls_net_context *ctx ) +{ + if( ctx->fd == -1 ) + return; + + close( ctx->fd ); + + ctx->fd = -1; +} + +/* + * Gracefully close the connection + */ +void mbedtls_net_free( mbedtls_net_context *ctx ) +{ + if( ctx->fd == -1 ) + return; + + shutdown( ctx->fd, 2 ); + close( ctx->fd ); + + ctx->fd = -1; +} + +#endif /* MBEDTLS_NET_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/nist_kw.c b/Android/Level4/app/src/main/c/mbedtls/library/nist_kw.c new file mode 100644 index 0000000..04829a0 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/nist_kw.c @@ -0,0 +1,750 @@ +/* + * Implementation of NIST SP 800-38F key wrapping, supporting KW and KWP modes + * only + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ +/* + * Definition of Key Wrapping: + * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf + * RFC 3394 "Advanced Encryption Standard (AES) Key Wrap Algorithm" + * RFC 5649 "Advanced Encryption Standard (AES) Key Wrap with Padding Algorithm" + * + * Note: RFC 3394 defines different methodology for intermediate operations for + * the wrapping and unwrapping operation than the definition in NIST SP 800-38F. + */ + +#include "common.h" + +#if defined(MBEDTLS_NIST_KW_C) + +#include "mbedtls/nist_kw.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include +#include + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#if !defined(MBEDTLS_NIST_KW_ALT) + +#define KW_SEMIBLOCK_LENGTH 8 +#define MIN_SEMIBLOCKS_COUNT 3 + +/* constant-time buffer comparison */ +static inline unsigned char mbedtls_nist_kw_safer_memcmp( const void *a, const void *b, size_t n ) +{ + size_t i; + volatile const unsigned char *A = (volatile const unsigned char *) a; + volatile const unsigned char *B = (volatile const unsigned char *) b; + volatile unsigned char diff = 0; + + for( i = 0; i < n; i++ ) + { + /* Read volatile data in order before computing diff. + * This avoids IAR compiler warning: + * 'the order of volatile accesses is undefined ..' */ + unsigned char x = A[i], y = B[i]; + diff |= x ^ y; + } + + return( diff ); +} + +/*! The 64-bit default integrity check value (ICV) for KW mode. */ +static const unsigned char NIST_KW_ICV1[] = {0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6}; +/*! The 32-bit default integrity check value (ICV) for KWP mode. */ +static const unsigned char NIST_KW_ICV2[] = {0xA6, 0x59, 0x59, 0xA6}; + +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +do { \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} while( 0 ) +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +do { \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} while( 0 ) +#endif + +/* + * Initialize context + */ +void mbedtls_nist_kw_init( mbedtls_nist_kw_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_nist_kw_context ) ); +} + +int mbedtls_nist_kw_setkey( mbedtls_nist_kw_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits, + const int is_wrap ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const mbedtls_cipher_info_t *cipher_info; + + cipher_info = mbedtls_cipher_info_from_values( cipher, + keybits, + MBEDTLS_MODE_ECB ); + if( cipher_info == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( cipher_info->block_size != 16 ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + /* + * SP 800-38F currently defines AES cipher as the only block cipher allowed: + * "For KW and KWP, the underlying block cipher shall be approved, and the + * block size shall be 128 bits. Currently, the AES block cipher, with key + * lengths of 128, 192, or 256 bits, is the only block cipher that fits + * this profile." + * Currently we don't support other 128 bit block ciphers for key wrapping, + * such as Camellia and Aria. + */ + if( cipher != MBEDTLS_CIPHER_ID_AES ) + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + + mbedtls_cipher_free( &ctx->cipher_ctx ); + + if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits, + is_wrap ? MBEDTLS_ENCRYPT : + MBEDTLS_DECRYPT ) + ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} + +/* + * Free context + */ +void mbedtls_nist_kw_free( mbedtls_nist_kw_context *ctx ) +{ + mbedtls_cipher_free( &ctx->cipher_ctx ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_nist_kw_context ) ); +} + +/* + * Helper function for Xoring the uint64_t "t" with the encrypted A. + * Defined in NIST SP 800-38F section 6.1 + */ +static void calc_a_xor_t( unsigned char A[KW_SEMIBLOCK_LENGTH], uint64_t t ) +{ + size_t i = 0; + for( i = 0; i < sizeof( t ); i++ ) + { + A[i] ^= ( t >> ( ( sizeof( t ) - 1 - i ) * 8 ) ) & 0xff; + } +} + +/* + * KW-AE as defined in SP 800-38F section 6.2 + * KWP-AE as defined in SP 800-38F section 6.3 + */ +int mbedtls_nist_kw_wrap( mbedtls_nist_kw_context *ctx, + mbedtls_nist_kw_mode_t mode, + const unsigned char *input, size_t in_len, + unsigned char *output, size_t *out_len, size_t out_size ) +{ + int ret = 0; + size_t semiblocks = 0; + size_t s; + size_t olen, padlen = 0; + uint64_t t = 0; + unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2]; + unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2]; + unsigned char *R2 = output + KW_SEMIBLOCK_LENGTH; + unsigned char *A = output; + + *out_len = 0; + /* + * Generate the String to work on + */ + if( mode == MBEDTLS_KW_MODE_KW ) + { + if( out_size < in_len + KW_SEMIBLOCK_LENGTH ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + /* + * According to SP 800-38F Table 1, the plaintext length for KW + * must be between 2 to 2^54-1 semiblocks inclusive. + */ + if( in_len < 16 || +#if SIZE_MAX > 0x1FFFFFFFFFFFFF8 + in_len > 0x1FFFFFFFFFFFFF8 || +#endif + in_len % KW_SEMIBLOCK_LENGTH != 0 ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + memcpy( output, NIST_KW_ICV1, KW_SEMIBLOCK_LENGTH ); + memmove( output + KW_SEMIBLOCK_LENGTH, input, in_len ); + } + else + { + if( in_len % 8 != 0 ) + { + padlen = ( 8 - ( in_len % 8 ) ); + } + + if( out_size < in_len + KW_SEMIBLOCK_LENGTH + padlen ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + /* + * According to SP 800-38F Table 1, the plaintext length for KWP + * must be between 1 and 2^32-1 octets inclusive. + */ + if( in_len < 1 +#if SIZE_MAX > 0xFFFFFFFF + || in_len > 0xFFFFFFFF +#endif + ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + memcpy( output, NIST_KW_ICV2, KW_SEMIBLOCK_LENGTH / 2 ); + PUT_UINT32_BE( ( in_len & 0xffffffff ), output, + KW_SEMIBLOCK_LENGTH / 2 ); + + memcpy( output + KW_SEMIBLOCK_LENGTH, input, in_len ); + memset( output + KW_SEMIBLOCK_LENGTH + in_len, 0, padlen ); + } + semiblocks = ( ( in_len + padlen ) / KW_SEMIBLOCK_LENGTH ) + 1; + + s = 6 * ( semiblocks - 1 ); + + if( mode == MBEDTLS_KW_MODE_KWP + && in_len <= KW_SEMIBLOCK_LENGTH ) + { + memcpy( inbuff, output, 16 ); + ret = mbedtls_cipher_update( &ctx->cipher_ctx, + inbuff, 16, output, &olen ); + if( ret != 0 ) + goto cleanup; + } + else + { + /* + * Do the wrapping function W, as defined in RFC 3394 section 2.2.1 + */ + if( semiblocks < MIN_SEMIBLOCKS_COUNT ) + { + ret = MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; + goto cleanup; + } + + /* Calculate intermediate values */ + for( t = 1; t <= s; t++ ) + { + memcpy( inbuff, A, KW_SEMIBLOCK_LENGTH ); + memcpy( inbuff + KW_SEMIBLOCK_LENGTH, R2, KW_SEMIBLOCK_LENGTH ); + + ret = mbedtls_cipher_update( &ctx->cipher_ctx, + inbuff, 16, outbuff, &olen ); + if( ret != 0 ) + goto cleanup; + + memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH ); + calc_a_xor_t( A, t ); + + memcpy( R2, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH ); + R2 += KW_SEMIBLOCK_LENGTH; + if( R2 >= output + ( semiblocks * KW_SEMIBLOCK_LENGTH ) ) + R2 = output + KW_SEMIBLOCK_LENGTH; + } + } + + *out_len = semiblocks * KW_SEMIBLOCK_LENGTH; + +cleanup: + + if( ret != 0) + { + memset( output, 0, semiblocks * KW_SEMIBLOCK_LENGTH ); + } + mbedtls_platform_zeroize( inbuff, KW_SEMIBLOCK_LENGTH * 2 ); + mbedtls_platform_zeroize( outbuff, KW_SEMIBLOCK_LENGTH * 2 ); + + return( ret ); +} + +/* + * W-1 function as defined in RFC 3394 section 2.2.2 + * This function assumes the following: + * 1. Output buffer is at least of size ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH. + * 2. The input buffer is of size semiblocks * KW_SEMIBLOCK_LENGTH. + * 3. Minimal number of semiblocks is 3. + * 4. A is a buffer to hold the first semiblock of the input buffer. + */ +static int unwrap( mbedtls_nist_kw_context *ctx, + const unsigned char *input, size_t semiblocks, + unsigned char A[KW_SEMIBLOCK_LENGTH], + unsigned char *output, size_t* out_len ) +{ + int ret = 0; + const size_t s = 6 * ( semiblocks - 1 ); + size_t olen; + uint64_t t = 0; + unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2]; + unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2]; + unsigned char *R = output + ( semiblocks - 2 ) * KW_SEMIBLOCK_LENGTH; + *out_len = 0; + + if( semiblocks < MIN_SEMIBLOCKS_COUNT ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + memcpy( A, input, KW_SEMIBLOCK_LENGTH ); + memmove( output, input + KW_SEMIBLOCK_LENGTH, ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH ); + + /* Calculate intermediate values */ + for( t = s; t >= 1; t-- ) + { + calc_a_xor_t( A, t ); + + memcpy( inbuff, A, KW_SEMIBLOCK_LENGTH ); + memcpy( inbuff + KW_SEMIBLOCK_LENGTH, R, KW_SEMIBLOCK_LENGTH ); + + ret = mbedtls_cipher_update( &ctx->cipher_ctx, + inbuff, 16, outbuff, &olen ); + if( ret != 0 ) + goto cleanup; + + memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH ); + + /* Set R as LSB64 of outbuff */ + memcpy( R, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH ); + + if( R == output ) + R = output + ( semiblocks - 2 ) * KW_SEMIBLOCK_LENGTH; + else + R -= KW_SEMIBLOCK_LENGTH; + } + + *out_len = ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH; + +cleanup: + if( ret != 0) + memset( output, 0, ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH ); + mbedtls_platform_zeroize( inbuff, sizeof( inbuff ) ); + mbedtls_platform_zeroize( outbuff, sizeof( outbuff ) ); + + return( ret ); +} + +/* + * KW-AD as defined in SP 800-38F section 6.2 + * KWP-AD as defined in SP 800-38F section 6.3 + */ +int mbedtls_nist_kw_unwrap( mbedtls_nist_kw_context *ctx, + mbedtls_nist_kw_mode_t mode, + const unsigned char *input, size_t in_len, + unsigned char *output, size_t *out_len, size_t out_size ) +{ + int ret = 0; + size_t i, olen; + unsigned char A[KW_SEMIBLOCK_LENGTH]; + unsigned char diff, bad_padding = 0; + + *out_len = 0; + if( out_size < in_len - KW_SEMIBLOCK_LENGTH ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + if( mode == MBEDTLS_KW_MODE_KW ) + { + /* + * According to SP 800-38F Table 1, the ciphertext length for KW + * must be between 3 to 2^54 semiblocks inclusive. + */ + if( in_len < 24 || +#if SIZE_MAX > 0x200000000000000 + in_len > 0x200000000000000 || +#endif + in_len % KW_SEMIBLOCK_LENGTH != 0 ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + ret = unwrap( ctx, input, in_len / KW_SEMIBLOCK_LENGTH, + A, output, out_len ); + if( ret != 0 ) + goto cleanup; + + /* Check ICV in "constant-time" */ + diff = mbedtls_nist_kw_safer_memcmp( NIST_KW_ICV1, A, KW_SEMIBLOCK_LENGTH ); + + if( diff != 0 ) + { + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + goto cleanup; + } + + } + else if( mode == MBEDTLS_KW_MODE_KWP ) + { + size_t padlen = 0; + uint32_t Plen; + /* + * According to SP 800-38F Table 1, the ciphertext length for KWP + * must be between 2 to 2^29 semiblocks inclusive. + */ + if( in_len < KW_SEMIBLOCK_LENGTH * 2 || +#if SIZE_MAX > 0x100000000 + in_len > 0x100000000 || +#endif + in_len % KW_SEMIBLOCK_LENGTH != 0 ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + if( in_len == KW_SEMIBLOCK_LENGTH * 2 ) + { + unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2]; + ret = mbedtls_cipher_update( &ctx->cipher_ctx, + input, 16, outbuff, &olen ); + if( ret != 0 ) + goto cleanup; + + memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH ); + memcpy( output, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH ); + mbedtls_platform_zeroize( outbuff, sizeof( outbuff ) ); + *out_len = KW_SEMIBLOCK_LENGTH; + } + else + { + /* in_len >= KW_SEMIBLOCK_LENGTH * 3 */ + ret = unwrap( ctx, input, in_len / KW_SEMIBLOCK_LENGTH, + A, output, out_len ); + if( ret != 0 ) + goto cleanup; + } + + /* Check ICV in "constant-time" */ + diff = mbedtls_nist_kw_safer_memcmp( NIST_KW_ICV2, A, KW_SEMIBLOCK_LENGTH / 2 ); + + if( diff != 0 ) + { + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + } + + GET_UINT32_BE( Plen, A, KW_SEMIBLOCK_LENGTH / 2 ); + + /* + * Plen is the length of the plaintext, when the input is valid. + * If Plen is larger than the plaintext and padding, padlen will be + * larger than 8, because of the type wrap around. + */ + padlen = in_len - KW_SEMIBLOCK_LENGTH - Plen; + if ( padlen > 7 ) + { + padlen &= 7; + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + } + + /* Check padding in "constant-time" */ + for( diff = 0, i = 0; i < KW_SEMIBLOCK_LENGTH; i++ ) + { + if( i >= KW_SEMIBLOCK_LENGTH - padlen ) + diff |= output[*out_len - KW_SEMIBLOCK_LENGTH + i]; + else + bad_padding |= output[*out_len - KW_SEMIBLOCK_LENGTH + i]; + } + + if( diff != 0 ) + { + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + } + + if( ret != 0 ) + { + goto cleanup; + } + memset( output + Plen, 0, padlen ); + *out_len = Plen; + } + else + { + ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; + goto cleanup; + } + +cleanup: + if( ret != 0 ) + { + memset( output, 0, *out_len ); + *out_len = 0; + } + + mbedtls_platform_zeroize( &bad_padding, sizeof( bad_padding) ); + mbedtls_platform_zeroize( &diff, sizeof( diff ) ); + mbedtls_platform_zeroize( A, sizeof( A ) ); + + return( ret ); +} + +#endif /* !MBEDTLS_NIST_KW_ALT */ + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) + +#define KW_TESTS 3 + +/* + * Test vectors taken from NIST + * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/CAVP-TESTING-BLOCK-CIPHER-MODES#KW + */ +static const unsigned int key_len[KW_TESTS] = { 16, 24, 32 }; + +static const unsigned char kw_key[KW_TESTS][32] = { + { 0x75, 0x75, 0xda, 0x3a, 0x93, 0x60, 0x7c, 0xc2, + 0xbf, 0xd8, 0xce, 0xc7, 0xaa, 0xdf, 0xd9, 0xa6 }, + { 0x2d, 0x85, 0x26, 0x08, 0x1d, 0x02, 0xfb, 0x5b, + 0x85, 0xf6, 0x9a, 0xc2, 0x86, 0xec, 0xd5, 0x7d, + 0x40, 0xdf, 0x5d, 0xf3, 0x49, 0x47, 0x44, 0xd3 }, + { 0x11, 0x2a, 0xd4, 0x1b, 0x48, 0x56, 0xc7, 0x25, + 0x4a, 0x98, 0x48, 0xd3, 0x0f, 0xdd, 0x78, 0x33, + 0x5b, 0x03, 0x9a, 0x48, 0xa8, 0x96, 0x2c, 0x4d, + 0x1c, 0xb7, 0x8e, 0xab, 0xd5, 0xda, 0xd7, 0x88 } +}; + +static const unsigned char kw_msg[KW_TESTS][40] = { + { 0x42, 0x13, 0x6d, 0x3c, 0x38, 0x4a, 0x3e, 0xea, + 0xc9, 0x5a, 0x06, 0x6f, 0xd2, 0x8f, 0xed, 0x3f }, + { 0x95, 0xc1, 0x1b, 0xf5, 0x35, 0x3a, 0xfe, 0xdb, + 0x98, 0xfd, 0xd6, 0xc8, 0xca, 0x6f, 0xdb, 0x6d, + 0xa5, 0x4b, 0x74, 0xb4, 0x99, 0x0f, 0xdc, 0x45, + 0xc0, 0x9d, 0x15, 0x8f, 0x51, 0xce, 0x62, 0x9d, + 0xe2, 0xaf, 0x26, 0xe3, 0x25, 0x0e, 0x6b, 0x4c }, + { 0x1b, 0x20, 0xbf, 0x19, 0x90, 0xb0, 0x65, 0xd7, + 0x98, 0xe1, 0xb3, 0x22, 0x64, 0xad, 0x50, 0xa8, + 0x74, 0x74, 0x92, 0xba, 0x09, 0xa0, 0x4d, 0xd1 } +}; + +static const size_t kw_msg_len[KW_TESTS] = { 16, 40, 24 }; +static const size_t kw_out_len[KW_TESTS] = { 24, 48, 32 }; +static const unsigned char kw_res[KW_TESTS][48] = { + { 0x03, 0x1f, 0x6b, 0xd7, 0xe6, 0x1e, 0x64, 0x3d, + 0xf6, 0x85, 0x94, 0x81, 0x6f, 0x64, 0xca, 0xa3, + 0xf5, 0x6f, 0xab, 0xea, 0x25, 0x48, 0xf5, 0xfb }, + { 0x44, 0x3c, 0x6f, 0x15, 0x09, 0x83, 0x71, 0x91, + 0x3e, 0x5c, 0x81, 0x4c, 0xa1, 0xa0, 0x42, 0xec, + 0x68, 0x2f, 0x7b, 0x13, 0x6d, 0x24, 0x3a, 0x4d, + 0x6c, 0x42, 0x6f, 0xc6, 0x97, 0x15, 0x63, 0xe8, + 0xa1, 0x4a, 0x55, 0x8e, 0x09, 0x64, 0x16, 0x19, + 0xbf, 0x03, 0xfc, 0xaf, 0x90, 0xb1, 0xfc, 0x2d }, + { 0xba, 0x8a, 0x25, 0x9a, 0x47, 0x1b, 0x78, 0x7d, + 0xd5, 0xd5, 0x40, 0xec, 0x25, 0xd4, 0x3d, 0x87, + 0x20, 0x0f, 0xda, 0xdc, 0x6d, 0x1f, 0x05, 0xd9, + 0x16, 0x58, 0x4f, 0xa9, 0xf6, 0xcb, 0xf5, 0x12 } +}; + +static const unsigned char kwp_key[KW_TESTS][32] = { + { 0x78, 0x65, 0xe2, 0x0f, 0x3c, 0x21, 0x65, 0x9a, + 0xb4, 0x69, 0x0b, 0x62, 0x9c, 0xdf, 0x3c, 0xc4 }, + { 0xf5, 0xf8, 0x96, 0xa3, 0xbd, 0x2f, 0x4a, 0x98, + 0x23, 0xef, 0x16, 0x2b, 0x00, 0xb8, 0x05, 0xd7, + 0xde, 0x1e, 0xa4, 0x66, 0x26, 0x96, 0xa2, 0x58 }, + { 0x95, 0xda, 0x27, 0x00, 0xca, 0x6f, 0xd9, 0xa5, + 0x25, 0x54, 0xee, 0x2a, 0x8d, 0xf1, 0x38, 0x6f, + 0x5b, 0x94, 0xa1, 0xa6, 0x0e, 0xd8, 0xa4, 0xae, + 0xf6, 0x0a, 0x8d, 0x61, 0xab, 0x5f, 0x22, 0x5a } +}; + +static const unsigned char kwp_msg[KW_TESTS][31] = { + { 0xbd, 0x68, 0x43, 0xd4, 0x20, 0x37, 0x8d, 0xc8, + 0x96 }, + { 0x6c, 0xcd, 0xd5, 0x85, 0x18, 0x40, 0x97, 0xeb, + 0xd5, 0xc3, 0xaf, 0x3e, 0x47, 0xd0, 0x2c, 0x19, + 0x14, 0x7b, 0x4d, 0x99, 0x5f, 0x96, 0x43, 0x66, + 0x91, 0x56, 0x75, 0x8c, 0x13, 0x16, 0x8f }, + { 0xd1 } +}; +static const size_t kwp_msg_len[KW_TESTS] = { 9, 31, 1 }; + +static const unsigned char kwp_res[KW_TESTS][48] = { + { 0x41, 0xec, 0xa9, 0x56, 0xd4, 0xaa, 0x04, 0x7e, + 0xb5, 0xcf, 0x4e, 0xfe, 0x65, 0x96, 0x61, 0xe7, + 0x4d, 0xb6, 0xf8, 0xc5, 0x64, 0xe2, 0x35, 0x00 }, + { 0x4e, 0x9b, 0xc2, 0xbc, 0xbc, 0x6c, 0x1e, 0x13, + 0xd3, 0x35, 0xbc, 0xc0, 0xf7, 0x73, 0x6a, 0x88, + 0xfa, 0x87, 0x53, 0x66, 0x15, 0xbb, 0x8e, 0x63, + 0x8b, 0xcc, 0x81, 0x66, 0x84, 0x68, 0x17, 0x90, + 0x67, 0xcf, 0xa9, 0x8a, 0x9d, 0x0e, 0x33, 0x26 }, + { 0x06, 0xba, 0x7a, 0xe6, 0xf3, 0x24, 0x8c, 0xfd, + 0xcf, 0x26, 0x75, 0x07, 0xfa, 0x00, 0x1b, 0xc4 } +}; +static const size_t kwp_out_len[KW_TESTS] = { 24, 40, 16 }; + +int mbedtls_nist_kw_self_test( int verbose ) +{ + mbedtls_nist_kw_context ctx; + unsigned char out[48]; + size_t olen; + int i; + int ret = 0; + mbedtls_nist_kw_init( &ctx ); + + for( i = 0; i < KW_TESTS; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " KW-AES-%u ", (unsigned int) key_len[i] * 8 ); + + ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, + kw_key[i], key_len[i] * 8, 1 ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( " KW: setup failed " ); + + goto end; + } + + ret = mbedtls_nist_kw_wrap( &ctx, MBEDTLS_KW_MODE_KW, kw_msg[i], + kw_msg_len[i], out, &olen, sizeof( out ) ); + if( ret != 0 || kw_out_len[i] != olen || + memcmp( out, kw_res[i], kw_out_len[i] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed. "); + + ret = 1; + goto end; + } + + if( ( ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, + kw_key[i], key_len[i] * 8, 0 ) ) + != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( " KW: setup failed "); + + goto end; + } + + ret = mbedtls_nist_kw_unwrap( &ctx, MBEDTLS_KW_MODE_KW, + out, olen, out, &olen, sizeof( out ) ); + + if( ret != 0 || olen != kw_msg_len[i] || + memcmp( out, kw_msg[i], kw_msg_len[i] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto end; + } + + if( verbose != 0 ) + mbedtls_printf( " passed\n" ); + } + + for( i = 0; i < KW_TESTS; i++ ) + { + olen = sizeof( out ); + if( verbose != 0 ) + mbedtls_printf( " KWP-AES-%u ", (unsigned int) key_len[i] * 8 ); + + ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, kwp_key[i], + key_len[i] * 8, 1 ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( " KWP: setup failed " ); + + goto end; + } + ret = mbedtls_nist_kw_wrap( &ctx, MBEDTLS_KW_MODE_KWP, kwp_msg[i], + kwp_msg_len[i], out, &olen, sizeof( out ) ); + + if( ret != 0 || kwp_out_len[i] != olen || + memcmp( out, kwp_res[i], kwp_out_len[i] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed. "); + + ret = 1; + goto end; + } + + if( ( ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, + kwp_key[i], key_len[i] * 8, 0 ) ) + != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( " KWP: setup failed "); + + goto end; + } + + ret = mbedtls_nist_kw_unwrap( &ctx, MBEDTLS_KW_MODE_KWP, out, + olen, out, &olen, sizeof( out ) ); + + if( ret != 0 || olen != kwp_msg_len[i] || + memcmp( out, kwp_msg[i], kwp_msg_len[i] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed. "); + + ret = 1; + goto end; + } + + if( verbose != 0 ) + mbedtls_printf( " passed\n" ); + } +end: + mbedtls_nist_kw_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#endif /* MBEDTLS_NIST_KW_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/oid.c b/Android/Level4/app/src/main/c/mbedtls/library/oid.c new file mode 100644 index 0000000..19c8ac2 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/oid.c @@ -0,0 +1,767 @@ +/** + * \file oid.c + * + * \brief Object Identifier (OID) database + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 "common.h" + +#if defined(MBEDTLS_OID_C) + +#include "mbedtls/oid.h" +#include "mbedtls/rsa.h" +#include "mbedtls/error.h" + +#include +#include + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#define mbedtls_snprintf snprintf +#endif + +/* + * Macro to automatically add the size of #define'd OIDs + */ +#define ADD_LEN(s) s, MBEDTLS_OID_SIZE(s) + +/* + * Macro to generate an internal function for oid_XXX_from_asn1() (used by + * the other functions) + */ +#define FN_OID_TYPED_FROM_ASN1( TYPE_T, NAME, LIST ) \ + static const TYPE_T * oid_ ## NAME ## _from_asn1( \ + const mbedtls_asn1_buf *oid ) \ + { \ + const TYPE_T *p = (LIST); \ + const mbedtls_oid_descriptor_t *cur = \ + (const mbedtls_oid_descriptor_t *) p; \ + if( p == NULL || oid == NULL ) return( NULL ); \ + while( cur->asn1 != NULL ) { \ + if( cur->asn1_len == oid->len && \ + memcmp( cur->asn1, oid->p, oid->len ) == 0 ) { \ + return( p ); \ + } \ + p++; \ + cur = (const mbedtls_oid_descriptor_t *) p; \ + } \ + return( NULL ); \ + } + +/* + * Macro to generate a function for retrieving a single attribute from the + * descriptor of an mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_DESCRIPTOR_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \ +int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1 ) \ +{ \ + const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \ + if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND ); \ + *ATTR1 = data->descriptor.ATTR1; \ + return( 0 ); \ +} + +/* + * Macro to generate a function for retrieving a single attribute from an + * mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \ +int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1 ) \ +{ \ + const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \ + if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND ); \ + *ATTR1 = data->ATTR1; \ + return( 0 ); \ +} + +/* + * Macro to generate a function for retrieving two attributes from an + * mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_ATTR2(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1, \ + ATTR2_TYPE, ATTR2) \ +int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1, \ + ATTR2_TYPE * ATTR2 ) \ +{ \ + const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \ + if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND ); \ + *(ATTR1) = data->ATTR1; \ + *(ATTR2) = data->ATTR2; \ + return( 0 ); \ +} + +/* + * Macro to generate a function for retrieving the OID based on a single + * attribute from a mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_OID_BY_ATTR1(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1) \ +int FN_NAME( ATTR1_TYPE ATTR1, const char **oid, size_t *olen ) \ +{ \ + const TYPE_T *cur = (LIST); \ + while( cur->descriptor.asn1 != NULL ) { \ + if( cur->ATTR1 == (ATTR1) ) { \ + *oid = cur->descriptor.asn1; \ + *olen = cur->descriptor.asn1_len; \ + return( 0 ); \ + } \ + cur++; \ + } \ + return( MBEDTLS_ERR_OID_NOT_FOUND ); \ +} + +/* + * Macro to generate a function for retrieving the OID based on two + * attributes from a mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_OID_BY_ATTR2(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1, \ + ATTR2_TYPE, ATTR2) \ +int FN_NAME( ATTR1_TYPE ATTR1, ATTR2_TYPE ATTR2, const char **oid , \ + size_t *olen ) \ +{ \ + const TYPE_T *cur = (LIST); \ + while( cur->descriptor.asn1 != NULL ) { \ + if( cur->ATTR1 == (ATTR1) && cur->ATTR2 == (ATTR2) ) { \ + *oid = cur->descriptor.asn1; \ + *olen = cur->descriptor.asn1_len; \ + return( 0 ); \ + } \ + cur++; \ + } \ + return( MBEDTLS_ERR_OID_NOT_FOUND ); \ +} + +/* + * For X520 attribute types + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + const char *short_name; +} oid_x520_attr_t; + +static const oid_x520_attr_t oid_x520_attr_type[] = +{ + { + { ADD_LEN( MBEDTLS_OID_AT_CN ), "id-at-commonName", "Common Name" }, + "CN", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_COUNTRY ), "id-at-countryName", "Country" }, + "C", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_LOCALITY ), "id-at-locality", "Locality" }, + "L", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_STATE ), "id-at-state", "State" }, + "ST", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_ORGANIZATION ),"id-at-organizationName", "Organization" }, + "O", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_ORG_UNIT ), "id-at-organizationalUnitName", "Org Unit" }, + "OU", + }, + { + { ADD_LEN( MBEDTLS_OID_PKCS9_EMAIL ), "emailAddress", "E-mail address" }, + "emailAddress", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_SERIAL_NUMBER ),"id-at-serialNumber", "Serial number" }, + "serialNumber", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_POSTAL_ADDRESS ),"id-at-postalAddress", "Postal address" }, + "postalAddress", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_POSTAL_CODE ), "id-at-postalCode", "Postal code" }, + "postalCode", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_SUR_NAME ), "id-at-surName", "Surname" }, + "SN", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_GIVEN_NAME ), "id-at-givenName", "Given name" }, + "GN", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_INITIALS ), "id-at-initials", "Initials" }, + "initials", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_GENERATION_QUALIFIER ), "id-at-generationQualifier", "Generation qualifier" }, + "generationQualifier", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_TITLE ), "id-at-title", "Title" }, + "title", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_DN_QUALIFIER ),"id-at-dnQualifier", "Distinguished Name qualifier" }, + "dnQualifier", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_PSEUDONYM ), "id-at-pseudonym", "Pseudonym" }, + "pseudonym", + }, + { + { ADD_LEN( MBEDTLS_OID_DOMAIN_COMPONENT ), "id-domainComponent", "Domain component" }, + "DC", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_UNIQUE_IDENTIFIER ), "id-at-uniqueIdentifier", "Unique Identifier" }, + "uniqueIdentifier", + }, + { + { NULL, 0, NULL, NULL }, + NULL, + } +}; + +FN_OID_TYPED_FROM_ASN1(oid_x520_attr_t, x520_attr, oid_x520_attr_type) +FN_OID_GET_ATTR1(mbedtls_oid_get_attr_short_name, oid_x520_attr_t, x520_attr, const char *, short_name) + +/* + * For X509 extensions + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + int ext_type; +} oid_x509_ext_t; + +static const oid_x509_ext_t oid_x509_ext[] = +{ + { + { ADD_LEN( MBEDTLS_OID_BASIC_CONSTRAINTS ), "id-ce-basicConstraints", "Basic Constraints" }, + MBEDTLS_OID_X509_EXT_BASIC_CONSTRAINTS, + }, + { + { ADD_LEN( MBEDTLS_OID_KEY_USAGE ), "id-ce-keyUsage", "Key Usage" }, + MBEDTLS_OID_X509_EXT_KEY_USAGE, + }, + { + { ADD_LEN( MBEDTLS_OID_EXTENDED_KEY_USAGE ), "id-ce-extKeyUsage", "Extended Key Usage" }, + MBEDTLS_OID_X509_EXT_EXTENDED_KEY_USAGE, + }, + { + { ADD_LEN( MBEDTLS_OID_SUBJECT_ALT_NAME ), "id-ce-subjectAltName", "Subject Alt Name" }, + MBEDTLS_OID_X509_EXT_SUBJECT_ALT_NAME, + }, + { + { ADD_LEN( MBEDTLS_OID_NS_CERT_TYPE ), "id-netscape-certtype", "Netscape Certificate Type" }, + MBEDTLS_OID_X509_EXT_NS_CERT_TYPE, + }, + { + { ADD_LEN( MBEDTLS_OID_CERTIFICATE_POLICIES ), "id-ce-certificatePolicies", "Certificate Policies" }, + MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES, + }, + { + { NULL, 0, NULL, NULL }, + 0, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_x509_ext_t, x509_ext, oid_x509_ext) +FN_OID_GET_ATTR1(mbedtls_oid_get_x509_ext_type, oid_x509_ext_t, x509_ext, int, ext_type) + +static const mbedtls_oid_descriptor_t oid_ext_key_usage[] = +{ + { ADD_LEN( MBEDTLS_OID_SERVER_AUTH ), "id-kp-serverAuth", "TLS Web Server Authentication" }, + { ADD_LEN( MBEDTLS_OID_CLIENT_AUTH ), "id-kp-clientAuth", "TLS Web Client Authentication" }, + { ADD_LEN( MBEDTLS_OID_CODE_SIGNING ), "id-kp-codeSigning", "Code Signing" }, + { ADD_LEN( MBEDTLS_OID_EMAIL_PROTECTION ), "id-kp-emailProtection", "E-mail Protection" }, + { ADD_LEN( MBEDTLS_OID_TIME_STAMPING ), "id-kp-timeStamping", "Time Stamping" }, + { ADD_LEN( MBEDTLS_OID_OCSP_SIGNING ), "id-kp-OCSPSigning", "OCSP Signing" }, + { ADD_LEN( MBEDTLS_OID_WISUN_FAN ), "id-kp-wisun-fan-device", "Wi-SUN Alliance Field Area Network (FAN)" }, + { NULL, 0, NULL, NULL }, +}; + +FN_OID_TYPED_FROM_ASN1(mbedtls_oid_descriptor_t, ext_key_usage, oid_ext_key_usage) +FN_OID_GET_ATTR1(mbedtls_oid_get_extended_key_usage, mbedtls_oid_descriptor_t, ext_key_usage, const char *, description) + +static const mbedtls_oid_descriptor_t oid_certificate_policies[] = +{ + { ADD_LEN( MBEDTLS_OID_ANY_POLICY ), "anyPolicy", "Any Policy" }, + { NULL, 0, NULL, NULL }, +}; + +FN_OID_TYPED_FROM_ASN1(mbedtls_oid_descriptor_t, certificate_policies, oid_certificate_policies) +FN_OID_GET_ATTR1(mbedtls_oid_get_certificate_policies, mbedtls_oid_descriptor_t, certificate_policies, const char *, description) + +#if defined(MBEDTLS_MD_C) +/* + * For SignatureAlgorithmIdentifier + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_md_type_t md_alg; + mbedtls_pk_type_t pk_alg; +} oid_sig_alg_t; + +static const oid_sig_alg_t oid_sig_alg[] = +{ +#if defined(MBEDTLS_RSA_C) +#if defined(MBEDTLS_MD2_C) + { + { ADD_LEN( MBEDTLS_OID_PKCS1_MD2 ), "md2WithRSAEncryption", "RSA with MD2" }, + MBEDTLS_MD_MD2, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_MD2_C */ +#if defined(MBEDTLS_MD4_C) + { + { ADD_LEN( MBEDTLS_OID_PKCS1_MD4 ), "md4WithRSAEncryption", "RSA with MD4" }, + MBEDTLS_MD_MD4, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_MD4_C */ +#if defined(MBEDTLS_MD5_C) + { + { ADD_LEN( MBEDTLS_OID_PKCS1_MD5 ), "md5WithRSAEncryption", "RSA with MD5" }, + MBEDTLS_MD_MD5, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_MD5_C */ +#if defined(MBEDTLS_SHA1_C) + { + { ADD_LEN( MBEDTLS_OID_PKCS1_SHA1 ), "sha-1WithRSAEncryption", "RSA with SHA1" }, + MBEDTLS_MD_SHA1, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) + { + { ADD_LEN( MBEDTLS_OID_PKCS1_SHA224 ), "sha224WithRSAEncryption", "RSA with SHA-224" }, + MBEDTLS_MD_SHA224, MBEDTLS_PK_RSA, + }, + { + { ADD_LEN( MBEDTLS_OID_PKCS1_SHA256 ), "sha256WithRSAEncryption", "RSA with SHA-256" }, + MBEDTLS_MD_SHA256, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { + { ADD_LEN( MBEDTLS_OID_PKCS1_SHA384 ), "sha384WithRSAEncryption", "RSA with SHA-384" }, + MBEDTLS_MD_SHA384, MBEDTLS_PK_RSA, + }, + { + { ADD_LEN( MBEDTLS_OID_PKCS1_SHA512 ), "sha512WithRSAEncryption", "RSA with SHA-512" }, + MBEDTLS_MD_SHA512, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_SHA512_C */ +#if defined(MBEDTLS_SHA1_C) + { + { ADD_LEN( MBEDTLS_OID_RSA_SHA_OBS ), "sha-1WithRSAEncryption", "RSA with SHA1" }, + MBEDTLS_MD_SHA1, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECDSA_C) +#if defined(MBEDTLS_SHA1_C) + { + { ADD_LEN( MBEDTLS_OID_ECDSA_SHA1 ), "ecdsa-with-SHA1", "ECDSA with SHA1" }, + MBEDTLS_MD_SHA1, MBEDTLS_PK_ECDSA, + }, +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) + { + { ADD_LEN( MBEDTLS_OID_ECDSA_SHA224 ), "ecdsa-with-SHA224", "ECDSA with SHA224" }, + MBEDTLS_MD_SHA224, MBEDTLS_PK_ECDSA, + }, + { + { ADD_LEN( MBEDTLS_OID_ECDSA_SHA256 ), "ecdsa-with-SHA256", "ECDSA with SHA256" }, + MBEDTLS_MD_SHA256, MBEDTLS_PK_ECDSA, + }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { + { ADD_LEN( MBEDTLS_OID_ECDSA_SHA384 ), "ecdsa-with-SHA384", "ECDSA with SHA384" }, + MBEDTLS_MD_SHA384, MBEDTLS_PK_ECDSA, + }, + { + { ADD_LEN( MBEDTLS_OID_ECDSA_SHA512 ), "ecdsa-with-SHA512", "ECDSA with SHA512" }, + MBEDTLS_MD_SHA512, MBEDTLS_PK_ECDSA, + }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_ECDSA_C */ +#if defined(MBEDTLS_RSA_C) + { + { ADD_LEN( MBEDTLS_OID_RSASSA_PSS ), "RSASSA-PSS", "RSASSA-PSS" }, + MBEDTLS_MD_NONE, MBEDTLS_PK_RSASSA_PSS, + }, +#endif /* MBEDTLS_RSA_C */ + { + { NULL, 0, NULL, NULL }, + MBEDTLS_MD_NONE, MBEDTLS_PK_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_sig_alg_t, sig_alg, oid_sig_alg) +FN_OID_GET_DESCRIPTOR_ATTR1(mbedtls_oid_get_sig_alg_desc, oid_sig_alg_t, sig_alg, const char *, description) +FN_OID_GET_ATTR2(mbedtls_oid_get_sig_alg, oid_sig_alg_t, sig_alg, mbedtls_md_type_t, md_alg, mbedtls_pk_type_t, pk_alg) +FN_OID_GET_OID_BY_ATTR2(mbedtls_oid_get_oid_by_sig_alg, oid_sig_alg_t, oid_sig_alg, mbedtls_pk_type_t, pk_alg, mbedtls_md_type_t, md_alg) +#endif /* MBEDTLS_MD_C */ + +/* + * For PublicKeyInfo (PKCS1, RFC 5480) + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_pk_type_t pk_alg; +} oid_pk_alg_t; + +static const oid_pk_alg_t oid_pk_alg[] = +{ + { + { ADD_LEN( MBEDTLS_OID_PKCS1_RSA ), "rsaEncryption", "RSA" }, + MBEDTLS_PK_RSA, + }, + { + { ADD_LEN( MBEDTLS_OID_EC_ALG_UNRESTRICTED ), "id-ecPublicKey", "Generic EC key" }, + MBEDTLS_PK_ECKEY, + }, + { + { ADD_LEN( MBEDTLS_OID_EC_ALG_ECDH ), "id-ecDH", "EC key for ECDH" }, + MBEDTLS_PK_ECKEY_DH, + }, + { + { NULL, 0, NULL, NULL }, + MBEDTLS_PK_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_pk_alg_t, pk_alg, oid_pk_alg) +FN_OID_GET_ATTR1(mbedtls_oid_get_pk_alg, oid_pk_alg_t, pk_alg, mbedtls_pk_type_t, pk_alg) +FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_pk_alg, oid_pk_alg_t, oid_pk_alg, mbedtls_pk_type_t, pk_alg) + +#if defined(MBEDTLS_ECP_C) +/* + * For namedCurve (RFC 5480) + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_ecp_group_id grp_id; +} oid_ecp_grp_t; + +static const oid_ecp_grp_t oid_ecp_grp[] = +{ +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP192R1 ), "secp192r1", "secp192r1" }, + MBEDTLS_ECP_DP_SECP192R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP224R1 ), "secp224r1", "secp224r1" }, + MBEDTLS_ECP_DP_SECP224R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP256R1 ), "secp256r1", "secp256r1" }, + MBEDTLS_ECP_DP_SECP256R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP384R1 ), "secp384r1", "secp384r1" }, + MBEDTLS_ECP_DP_SECP384R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP521R1 ), "secp521r1", "secp521r1" }, + MBEDTLS_ECP_DP_SECP521R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP192K1 ), "secp192k1", "secp192k1" }, + MBEDTLS_ECP_DP_SECP192K1, + }, +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP224K1 ), "secp224k1", "secp224k1" }, + MBEDTLS_ECP_DP_SECP224K1, + }, +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP256K1 ), "secp256k1", "secp256k1" }, + MBEDTLS_ECP_DP_SECP256K1, + }, +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_BP256R1 ), "brainpoolP256r1","brainpool256r1" }, + MBEDTLS_ECP_DP_BP256R1, + }, +#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_BP384R1 ), "brainpoolP384r1","brainpool384r1" }, + MBEDTLS_ECP_DP_BP384R1, + }, +#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_BP512R1 ), "brainpoolP512r1","brainpool512r1" }, + MBEDTLS_ECP_DP_BP512R1, + }, +#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ + { + { NULL, 0, NULL, NULL }, + MBEDTLS_ECP_DP_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_ecp_grp_t, grp_id, oid_ecp_grp) +FN_OID_GET_ATTR1(mbedtls_oid_get_ec_grp, oid_ecp_grp_t, grp_id, mbedtls_ecp_group_id, grp_id) +FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_ec_grp, oid_ecp_grp_t, oid_ecp_grp, mbedtls_ecp_group_id, grp_id) +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_CIPHER_C) +/* + * For PKCS#5 PBES2 encryption algorithm + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_cipher_type_t cipher_alg; +} oid_cipher_alg_t; + +static const oid_cipher_alg_t oid_cipher_alg[] = +{ + { + { ADD_LEN( MBEDTLS_OID_DES_CBC ), "desCBC", "DES-CBC" }, + MBEDTLS_CIPHER_DES_CBC, + }, + { + { ADD_LEN( MBEDTLS_OID_DES_EDE3_CBC ), "des-ede3-cbc", "DES-EDE3-CBC" }, + MBEDTLS_CIPHER_DES_EDE3_CBC, + }, + { + { NULL, 0, NULL, NULL }, + MBEDTLS_CIPHER_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_cipher_alg_t, cipher_alg, oid_cipher_alg) +FN_OID_GET_ATTR1(mbedtls_oid_get_cipher_alg, oid_cipher_alg_t, cipher_alg, mbedtls_cipher_type_t, cipher_alg) +#endif /* MBEDTLS_CIPHER_C */ + +#if defined(MBEDTLS_MD_C) +/* + * For digestAlgorithm + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_md_type_t md_alg; +} oid_md_alg_t; + +static const oid_md_alg_t oid_md_alg[] = +{ +#if defined(MBEDTLS_MD2_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_MD2 ), "id-md2", "MD2" }, + MBEDTLS_MD_MD2, + }, +#endif /* MBEDTLS_MD2_C */ +#if defined(MBEDTLS_MD4_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_MD4 ), "id-md4", "MD4" }, + MBEDTLS_MD_MD4, + }, +#endif /* MBEDTLS_MD4_C */ +#if defined(MBEDTLS_MD5_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_MD5 ), "id-md5", "MD5" }, + MBEDTLS_MD_MD5, + }, +#endif /* MBEDTLS_MD5_C */ +#if defined(MBEDTLS_SHA1_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA1 ), "id-sha1", "SHA-1" }, + MBEDTLS_MD_SHA1, + }, +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA224 ), "id-sha224", "SHA-224" }, + MBEDTLS_MD_SHA224, + }, + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA256 ), "id-sha256", "SHA-256" }, + MBEDTLS_MD_SHA256, + }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA384 ), "id-sha384", "SHA-384" }, + MBEDTLS_MD_SHA384, + }, + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA512 ), "id-sha512", "SHA-512" }, + MBEDTLS_MD_SHA512, + }, +#endif /* MBEDTLS_SHA512_C */ +#if defined(MBEDTLS_RIPEMD160_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_RIPEMD160 ), "id-ripemd160", "RIPEMD-160" }, + MBEDTLS_MD_RIPEMD160, + }, +#endif /* MBEDTLS_RIPEMD160_C */ + { + { NULL, 0, NULL, NULL }, + MBEDTLS_MD_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_md_alg_t, md_alg, oid_md_alg) +FN_OID_GET_ATTR1(mbedtls_oid_get_md_alg, oid_md_alg_t, md_alg, mbedtls_md_type_t, md_alg) +FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_md, oid_md_alg_t, oid_md_alg, mbedtls_md_type_t, md_alg) + +/* + * For HMAC digestAlgorithm + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_md_type_t md_hmac; +} oid_md_hmac_t; + +static const oid_md_hmac_t oid_md_hmac[] = +{ +#if defined(MBEDTLS_SHA1_C) + { + { ADD_LEN( MBEDTLS_OID_HMAC_SHA1 ), "hmacSHA1", "HMAC-SHA-1" }, + MBEDTLS_MD_SHA1, + }, +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) + { + { ADD_LEN( MBEDTLS_OID_HMAC_SHA224 ), "hmacSHA224", "HMAC-SHA-224" }, + MBEDTLS_MD_SHA224, + }, + { + { ADD_LEN( MBEDTLS_OID_HMAC_SHA256 ), "hmacSHA256", "HMAC-SHA-256" }, + MBEDTLS_MD_SHA256, + }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { + { ADD_LEN( MBEDTLS_OID_HMAC_SHA384 ), "hmacSHA384", "HMAC-SHA-384" }, + MBEDTLS_MD_SHA384, + }, + { + { ADD_LEN( MBEDTLS_OID_HMAC_SHA512 ), "hmacSHA512", "HMAC-SHA-512" }, + MBEDTLS_MD_SHA512, + }, +#endif /* MBEDTLS_SHA512_C */ + { + { NULL, 0, NULL, NULL }, + MBEDTLS_MD_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_md_hmac_t, md_hmac, oid_md_hmac) +FN_OID_GET_ATTR1(mbedtls_oid_get_md_hmac, oid_md_hmac_t, md_hmac, mbedtls_md_type_t, md_hmac) +#endif /* MBEDTLS_MD_C */ + +#if defined(MBEDTLS_PKCS12_C) +/* + * For PKCS#12 PBEs + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_md_type_t md_alg; + mbedtls_cipher_type_t cipher_alg; +} oid_pkcs12_pbe_alg_t; + +static const oid_pkcs12_pbe_alg_t oid_pkcs12_pbe_alg[] = +{ + { + { ADD_LEN( MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC ), "pbeWithSHAAnd3-KeyTripleDES-CBC", "PBE with SHA1 and 3-Key 3DES" }, + MBEDTLS_MD_SHA1, MBEDTLS_CIPHER_DES_EDE3_CBC, + }, + { + { ADD_LEN( MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC ), "pbeWithSHAAnd2-KeyTripleDES-CBC", "PBE with SHA1 and 2-Key 3DES" }, + MBEDTLS_MD_SHA1, MBEDTLS_CIPHER_DES_EDE_CBC, + }, + { + { NULL, 0, NULL, NULL }, + MBEDTLS_MD_NONE, MBEDTLS_CIPHER_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_pkcs12_pbe_alg_t, pkcs12_pbe_alg, oid_pkcs12_pbe_alg) +FN_OID_GET_ATTR2(mbedtls_oid_get_pkcs12_pbe_alg, oid_pkcs12_pbe_alg_t, pkcs12_pbe_alg, mbedtls_md_type_t, md_alg, mbedtls_cipher_type_t, cipher_alg) +#endif /* MBEDTLS_PKCS12_C */ + +#define OID_SAFE_SNPRINTF \ + do { \ + if( ret < 0 || (size_t) ret >= n ) \ + return( MBEDTLS_ERR_OID_BUF_TOO_SMALL ); \ + \ + n -= (size_t) ret; \ + p += (size_t) ret; \ + } while( 0 ) + +/* Return the x.y.z.... style numeric string for the given OID */ +int mbedtls_oid_get_numeric_string( char *buf, size_t size, + const mbedtls_asn1_buf *oid ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i, n; + unsigned int value; + char *p; + + p = buf; + n = size; + + /* First byte contains first two dots */ + if( oid->len > 0 ) + { + ret = mbedtls_snprintf( p, n, "%d.%d", oid->p[0] / 40, oid->p[0] % 40 ); + OID_SAFE_SNPRINTF; + } + + value = 0; + for( i = 1; i < oid->len; i++ ) + { + /* Prevent overflow in value. */ + if( ( ( value << 7 ) >> 7 ) != value ) + return( MBEDTLS_ERR_OID_BUF_TOO_SMALL ); + + value <<= 7; + value += oid->p[i] & 0x7F; + + if( !( oid->p[i] & 0x80 ) ) + { + /* Last byte */ + ret = mbedtls_snprintf( p, n, ".%u", value ); + OID_SAFE_SNPRINTF; + value = 0; + } + } + + return( (int) ( size - n ) ); +} + +#endif /* MBEDTLS_OID_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/padlock.c b/Android/Level4/app/src/main/c/mbedtls/library/padlock.c new file mode 100644 index 0000000..8373374 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/padlock.c @@ -0,0 +1,164 @@ +/* + * VIA PadLock support functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 implementation is based on the VIA PadLock Programming Guide: + * + * http://www.via.com.tw/en/downloads/whitepapers/initiatives/padlock/ + * programming_guide.pdf + */ + +#include "common.h" + +#if defined(MBEDTLS_PADLOCK_C) + +#include "mbedtls/padlock.h" + +#include + +#ifndef asm +#define asm __asm +#endif + +#if defined(MBEDTLS_HAVE_X86) + +/* + * PadLock detection routine + */ +int mbedtls_padlock_has_support( int feature ) +{ + static int flags = -1; + int ebx = 0, edx = 0; + + if( flags == -1 ) + { + asm( "movl %%ebx, %0 \n\t" + "movl $0xC0000000, %%eax \n\t" + "cpuid \n\t" + "cmpl $0xC0000001, %%eax \n\t" + "movl $0, %%edx \n\t" + "jb 1f \n\t" + "movl $0xC0000001, %%eax \n\t" + "cpuid \n\t" + "1: \n\t" + "movl %%edx, %1 \n\t" + "movl %2, %%ebx \n\t" + : "=m" (ebx), "=m" (edx) + : "m" (ebx) + : "eax", "ecx", "edx" ); + + flags = edx; + } + + return( flags & feature ); +} + +/* + * PadLock AES-ECB block en(de)cryption + */ +int mbedtls_padlock_xcryptecb( mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ) +{ + int ebx = 0; + uint32_t *rk; + uint32_t *blk; + uint32_t *ctrl; + unsigned char buf[256]; + + rk = ctx->rk; + blk = MBEDTLS_PADLOCK_ALIGN16( buf ); + memcpy( blk, input, 16 ); + + ctrl = blk + 4; + *ctrl = 0x80 | ctx->nr | ( ( ctx->nr + ( mode^1 ) - 10 ) << 9 ); + + asm( "pushfl \n\t" + "popfl \n\t" + "movl %%ebx, %0 \n\t" + "movl $1, %%ecx \n\t" + "movl %2, %%edx \n\t" + "movl %3, %%ebx \n\t" + "movl %4, %%esi \n\t" + "movl %4, %%edi \n\t" + ".byte 0xf3,0x0f,0xa7,0xc8 \n\t" + "movl %1, %%ebx \n\t" + : "=m" (ebx) + : "m" (ebx), "m" (ctrl), "m" (rk), "m" (blk) + : "memory", "ecx", "edx", "esi", "edi" ); + + memcpy( output, blk, 16 ); + + return( 0 ); +} + +/* + * PadLock AES-CBC buffer en(de)cryption + */ +int mbedtls_padlock_xcryptcbc( mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int ebx = 0; + size_t count; + uint32_t *rk; + uint32_t *iw; + uint32_t *ctrl; + unsigned char buf[256]; + + if( ( (long) input & 15 ) != 0 || + ( (long) output & 15 ) != 0 ) + return( MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED ); + + rk = ctx->rk; + iw = MBEDTLS_PADLOCK_ALIGN16( buf ); + memcpy( iw, iv, 16 ); + + ctrl = iw + 4; + *ctrl = 0x80 | ctx->nr | ( ( ctx->nr + ( mode ^ 1 ) - 10 ) << 9 ); + + count = ( length + 15 ) >> 4; + + asm( "pushfl \n\t" + "popfl \n\t" + "movl %%ebx, %0 \n\t" + "movl %2, %%ecx \n\t" + "movl %3, %%edx \n\t" + "movl %4, %%ebx \n\t" + "movl %5, %%esi \n\t" + "movl %6, %%edi \n\t" + "movl %7, %%eax \n\t" + ".byte 0xf3,0x0f,0xa7,0xd0 \n\t" + "movl %1, %%ebx \n\t" + : "=m" (ebx) + : "m" (ebx), "m" (count), "m" (ctrl), + "m" (rk), "m" (input), "m" (output), "m" (iw) + : "memory", "eax", "ecx", "edx", "esi", "edi" ); + + memcpy( iv, iw, 16 ); + + return( 0 ); +} + +#endif /* MBEDTLS_HAVE_X86 */ + +#endif /* MBEDTLS_PADLOCK_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/pem.c b/Android/Level4/app/src/main/c/mbedtls/library/pem.c new file mode 100644 index 0000000..534d071 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/pem.c @@ -0,0 +1,485 @@ +/* + * Privacy Enhanced Mail (PEM) decoding + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 "common.h" + +#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) + +#include "mbedtls/pem.h" +#include "mbedtls/base64.h" +#include "mbedtls/des.h" +#include "mbedtls/aes.h" +#include "mbedtls/md5.h" +#include "mbedtls/cipher.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) +void mbedtls_pem_init( mbedtls_pem_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_pem_context ) ); +} + +#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) +/* + * Read a 16-byte hex string and convert it to binary + */ +static int pem_get_iv( const unsigned char *s, unsigned char *iv, + size_t iv_len ) +{ + size_t i, j, k; + + memset( iv, 0, iv_len ); + + for( i = 0; i < iv_len * 2; i++, s++ ) + { + if( *s >= '0' && *s <= '9' ) j = *s - '0'; else + if( *s >= 'A' && *s <= 'F' ) j = *s - '7'; else + if( *s >= 'a' && *s <= 'f' ) j = *s - 'W'; else + return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); + + k = ( ( i & 1 ) != 0 ) ? j : j << 4; + + iv[i >> 1] = (unsigned char)( iv[i >> 1] | k ); + } + + return( 0 ); +} + +static int pem_pbkdf1( unsigned char *key, size_t keylen, + unsigned char *iv, + const unsigned char *pwd, size_t pwdlen ) +{ + mbedtls_md5_context md5_ctx; + unsigned char md5sum[16]; + size_t use_len; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + mbedtls_md5_init( &md5_ctx ); + + /* + * key[ 0..15] = MD5(pwd || IV) + */ + if( ( ret = mbedtls_md5_starts_ret( &md5_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update_ret( &md5_ctx, pwd, pwdlen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update_ret( &md5_ctx, iv, 8 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_finish_ret( &md5_ctx, md5sum ) ) != 0 ) + goto exit; + + if( keylen <= 16 ) + { + memcpy( key, md5sum, keylen ); + goto exit; + } + + memcpy( key, md5sum, 16 ); + + /* + * key[16..23] = MD5(key[ 0..15] || pwd || IV]) + */ + if( ( ret = mbedtls_md5_starts_ret( &md5_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update_ret( &md5_ctx, md5sum, 16 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update_ret( &md5_ctx, pwd, pwdlen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update_ret( &md5_ctx, iv, 8 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_finish_ret( &md5_ctx, md5sum ) ) != 0 ) + goto exit; + + use_len = 16; + if( keylen < 32 ) + use_len = keylen - 16; + + memcpy( key + 16, md5sum, use_len ); + +exit: + mbedtls_md5_free( &md5_ctx ); + mbedtls_platform_zeroize( md5sum, 16 ); + + return( ret ); +} + +#if defined(MBEDTLS_DES_C) +/* + * Decrypt with DES-CBC, using PBKDF1 for key derivation + */ +static int pem_des_decrypt( unsigned char des_iv[8], + unsigned char *buf, size_t buflen, + const unsigned char *pwd, size_t pwdlen ) +{ + mbedtls_des_context des_ctx; + unsigned char des_key[8]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + mbedtls_des_init( &des_ctx ); + + if( ( ret = pem_pbkdf1( des_key, 8, des_iv, pwd, pwdlen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_des_setkey_dec( &des_ctx, des_key ) ) != 0 ) + goto exit; + ret = mbedtls_des_crypt_cbc( &des_ctx, MBEDTLS_DES_DECRYPT, buflen, + des_iv, buf, buf ); + +exit: + mbedtls_des_free( &des_ctx ); + mbedtls_platform_zeroize( des_key, 8 ); + + return( ret ); +} + +/* + * Decrypt with 3DES-CBC, using PBKDF1 for key derivation + */ +static int pem_des3_decrypt( unsigned char des3_iv[8], + unsigned char *buf, size_t buflen, + const unsigned char *pwd, size_t pwdlen ) +{ + mbedtls_des3_context des3_ctx; + unsigned char des3_key[24]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + mbedtls_des3_init( &des3_ctx ); + + if( ( ret = pem_pbkdf1( des3_key, 24, des3_iv, pwd, pwdlen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_des3_set3key_dec( &des3_ctx, des3_key ) ) != 0 ) + goto exit; + ret = mbedtls_des3_crypt_cbc( &des3_ctx, MBEDTLS_DES_DECRYPT, buflen, + des3_iv, buf, buf ); + +exit: + mbedtls_des3_free( &des3_ctx ); + mbedtls_platform_zeroize( des3_key, 24 ); + + return( ret ); +} +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_AES_C) +/* + * Decrypt with AES-XXX-CBC, using PBKDF1 for key derivation + */ +static int pem_aes_decrypt( unsigned char aes_iv[16], unsigned int keylen, + unsigned char *buf, size_t buflen, + const unsigned char *pwd, size_t pwdlen ) +{ + mbedtls_aes_context aes_ctx; + unsigned char aes_key[32]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + mbedtls_aes_init( &aes_ctx ); + + if( ( ret = pem_pbkdf1( aes_key, keylen, aes_iv, pwd, pwdlen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_aes_setkey_dec( &aes_ctx, aes_key, keylen * 8 ) ) != 0 ) + goto exit; + ret = mbedtls_aes_crypt_cbc( &aes_ctx, MBEDTLS_AES_DECRYPT, buflen, + aes_iv, buf, buf ); + +exit: + mbedtls_aes_free( &aes_ctx ); + mbedtls_platform_zeroize( aes_key, keylen ); + + return( ret ); +} +#endif /* MBEDTLS_AES_C */ + +#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && + ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ + +int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const char *footer, + const unsigned char *data, const unsigned char *pwd, + size_t pwdlen, size_t *use_len ) +{ + int ret, enc; + size_t len; + unsigned char *buf; + const unsigned char *s1, *s2, *end; +#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) + unsigned char pem_iv[16]; + mbedtls_cipher_type_t enc_alg = MBEDTLS_CIPHER_NONE; +#else + ((void) pwd); + ((void) pwdlen); +#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && + ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ + + if( ctx == NULL ) + return( MBEDTLS_ERR_PEM_BAD_INPUT_DATA ); + + s1 = (unsigned char *) strstr( (const char *) data, header ); + + if( s1 == NULL ) + return( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ); + + s2 = (unsigned char *) strstr( (const char *) data, footer ); + + if( s2 == NULL || s2 <= s1 ) + return( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ); + + s1 += strlen( header ); + if( *s1 == ' ' ) s1++; + if( *s1 == '\r' ) s1++; + if( *s1 == '\n' ) s1++; + else return( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ); + + end = s2; + end += strlen( footer ); + if( *end == ' ' ) end++; + if( *end == '\r' ) end++; + if( *end == '\n' ) end++; + *use_len = end - data; + + enc = 0; + + if( s2 - s1 >= 22 && memcmp( s1, "Proc-Type: 4,ENCRYPTED", 22 ) == 0 ) + { +#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) + enc++; + + s1 += 22; + if( *s1 == '\r' ) s1++; + if( *s1 == '\n' ) s1++; + else return( MBEDTLS_ERR_PEM_INVALID_DATA ); + + +#if defined(MBEDTLS_DES_C) + if( s2 - s1 >= 23 && memcmp( s1, "DEK-Info: DES-EDE3-CBC,", 23 ) == 0 ) + { + enc_alg = MBEDTLS_CIPHER_DES_EDE3_CBC; + + s1 += 23; + if( s2 - s1 < 16 || pem_get_iv( s1, pem_iv, 8 ) != 0 ) + return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); + + s1 += 16; + } + else if( s2 - s1 >= 18 && memcmp( s1, "DEK-Info: DES-CBC,", 18 ) == 0 ) + { + enc_alg = MBEDTLS_CIPHER_DES_CBC; + + s1 += 18; + if( s2 - s1 < 16 || pem_get_iv( s1, pem_iv, 8) != 0 ) + return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); + + s1 += 16; + } +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_AES_C) + if( s2 - s1 >= 14 && memcmp( s1, "DEK-Info: AES-", 14 ) == 0 ) + { + if( s2 - s1 < 22 ) + return( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG ); + else if( memcmp( s1, "DEK-Info: AES-128-CBC,", 22 ) == 0 ) + enc_alg = MBEDTLS_CIPHER_AES_128_CBC; + else if( memcmp( s1, "DEK-Info: AES-192-CBC,", 22 ) == 0 ) + enc_alg = MBEDTLS_CIPHER_AES_192_CBC; + else if( memcmp( s1, "DEK-Info: AES-256-CBC,", 22 ) == 0 ) + enc_alg = MBEDTLS_CIPHER_AES_256_CBC; + else + return( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG ); + + s1 += 22; + if( s2 - s1 < 32 || pem_get_iv( s1, pem_iv, 16 ) != 0 ) + return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); + + s1 += 32; + } +#endif /* MBEDTLS_AES_C */ + + if( enc_alg == MBEDTLS_CIPHER_NONE ) + return( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG ); + + if( *s1 == '\r' ) s1++; + if( *s1 == '\n' ) s1++; + else return( MBEDTLS_ERR_PEM_INVALID_DATA ); +#else + return( MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE ); +#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && + ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ + } + + if( s1 >= s2 ) + return( MBEDTLS_ERR_PEM_INVALID_DATA ); + + ret = mbedtls_base64_decode( NULL, 0, &len, s1, s2 - s1 ); + + if( ret == MBEDTLS_ERR_BASE64_INVALID_CHARACTER ) + return( MBEDTLS_ERR_PEM_INVALID_DATA + ret ); + + if( ( buf = mbedtls_calloc( 1, len ) ) == NULL ) + return( MBEDTLS_ERR_PEM_ALLOC_FAILED ); + + if( ( ret = mbedtls_base64_decode( buf, len, &len, s1, s2 - s1 ) ) != 0 ) + { + mbedtls_platform_zeroize( buf, len ); + mbedtls_free( buf ); + return( MBEDTLS_ERR_PEM_INVALID_DATA + ret ); + } + + if( enc != 0 ) + { +#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) + if( pwd == NULL ) + { + mbedtls_platform_zeroize( buf, len ); + mbedtls_free( buf ); + return( MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ); + } + + ret = 0; + +#if defined(MBEDTLS_DES_C) + if( enc_alg == MBEDTLS_CIPHER_DES_EDE3_CBC ) + ret = pem_des3_decrypt( pem_iv, buf, len, pwd, pwdlen ); + else if( enc_alg == MBEDTLS_CIPHER_DES_CBC ) + ret = pem_des_decrypt( pem_iv, buf, len, pwd, pwdlen ); +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_AES_C) + if( enc_alg == MBEDTLS_CIPHER_AES_128_CBC ) + ret = pem_aes_decrypt( pem_iv, 16, buf, len, pwd, pwdlen ); + else if( enc_alg == MBEDTLS_CIPHER_AES_192_CBC ) + ret = pem_aes_decrypt( pem_iv, 24, buf, len, pwd, pwdlen ); + else if( enc_alg == MBEDTLS_CIPHER_AES_256_CBC ) + ret = pem_aes_decrypt( pem_iv, 32, buf, len, pwd, pwdlen ); +#endif /* MBEDTLS_AES_C */ + + if( ret != 0 ) + { + mbedtls_free( buf ); + return( ret ); + } + + /* + * The result will be ASN.1 starting with a SEQUENCE tag, with 1 to 3 + * length bytes (allow 4 to be sure) in all known use cases. + * + * Use that as a heuristic to try to detect password mismatches. + */ + if( len <= 2 || buf[0] != 0x30 || buf[1] > 0x83 ) + { + mbedtls_platform_zeroize( buf, len ); + mbedtls_free( buf ); + return( MBEDTLS_ERR_PEM_PASSWORD_MISMATCH ); + } +#else + mbedtls_platform_zeroize( buf, len ); + mbedtls_free( buf ); + return( MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE ); +#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && + ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ + } + + ctx->buf = buf; + ctx->buflen = len; + + return( 0 ); +} + +void mbedtls_pem_free( mbedtls_pem_context *ctx ) +{ + if ( ctx->buf != NULL ) + { + mbedtls_platform_zeroize( ctx->buf, ctx->buflen ); + mbedtls_free( ctx->buf ); + } + mbedtls_free( ctx->info ); + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_pem_context ) ); +} +#endif /* MBEDTLS_PEM_PARSE_C */ + +#if defined(MBEDTLS_PEM_WRITE_C) +int mbedtls_pem_write_buffer( const char *header, const char *footer, + const unsigned char *der_data, size_t der_len, + unsigned char *buf, size_t buf_len, size_t *olen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *encode_buf = NULL, *c, *p = buf; + size_t len = 0, use_len, add_len = 0; + + mbedtls_base64_encode( NULL, 0, &use_len, der_data, der_len ); + add_len = strlen( header ) + strlen( footer ) + ( use_len / 64 ) + 1; + + if( use_len + add_len > buf_len ) + { + *olen = use_len + add_len; + return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); + } + + if( use_len != 0 && + ( ( encode_buf = mbedtls_calloc( 1, use_len ) ) == NULL ) ) + return( MBEDTLS_ERR_PEM_ALLOC_FAILED ); + + if( ( ret = mbedtls_base64_encode( encode_buf, use_len, &use_len, der_data, + der_len ) ) != 0 ) + { + mbedtls_free( encode_buf ); + return( ret ); + } + + memcpy( p, header, strlen( header ) ); + p += strlen( header ); + c = encode_buf; + + while( use_len ) + { + len = ( use_len > 64 ) ? 64 : use_len; + memcpy( p, c, len ); + use_len -= len; + p += len; + c += len; + *p++ = '\n'; + } + + memcpy( p, footer, strlen( footer ) ); + p += strlen( footer ); + + *p++ = '\0'; + *olen = p - buf; + + mbedtls_free( encode_buf ); + return( 0 ); +} +#endif /* MBEDTLS_PEM_WRITE_C */ +#endif /* MBEDTLS_PEM_PARSE_C || MBEDTLS_PEM_WRITE_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/pk.c b/Android/Level4/app/src/main/c/mbedtls/library/pk.c new file mode 100644 index 0000000..9a3bcb0 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/pk.c @@ -0,0 +1,638 @@ +/* + * Public Key abstraction layer + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 "common.h" + +#if defined(MBEDTLS_PK_C) +#include "mbedtls/pk.h" +#include "mbedtls/pk_internal.h" + +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#if defined(MBEDTLS_RSA_C) +#include "mbedtls/rsa.h" +#endif +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/ecp.h" +#endif +#if defined(MBEDTLS_ECDSA_C) +#include "mbedtls/ecdsa.h" +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "mbedtls/psa_util.h" +#endif + +#include +#include + +/* Parameter validation macros based on platform_util.h */ +#define PK_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA ) +#define PK_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +/* + * Initialise a mbedtls_pk_context + */ +void mbedtls_pk_init( mbedtls_pk_context *ctx ) +{ + PK_VALIDATE( ctx != NULL ); + + ctx->pk_info = NULL; + ctx->pk_ctx = NULL; +} + +/* + * Free (the components of) a mbedtls_pk_context + */ +void mbedtls_pk_free( mbedtls_pk_context *ctx ) +{ + if( ctx == NULL ) + return; + + if ( ctx->pk_info != NULL ) + ctx->pk_info->ctx_free_func( ctx->pk_ctx ); + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_pk_context ) ); +} + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +/* + * Initialize a restart context + */ +void mbedtls_pk_restart_init( mbedtls_pk_restart_ctx *ctx ) +{ + PK_VALIDATE( ctx != NULL ); + ctx->pk_info = NULL; + ctx->rs_ctx = NULL; +} + +/* + * Free the components of a restart context + */ +void mbedtls_pk_restart_free( mbedtls_pk_restart_ctx *ctx ) +{ + if( ctx == NULL || ctx->pk_info == NULL || + ctx->pk_info->rs_free_func == NULL ) + { + return; + } + + ctx->pk_info->rs_free_func( ctx->rs_ctx ); + + ctx->pk_info = NULL; + ctx->rs_ctx = NULL; +} +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + +/* + * Get pk_info structure from type + */ +const mbedtls_pk_info_t * mbedtls_pk_info_from_type( mbedtls_pk_type_t pk_type ) +{ + switch( pk_type ) { +#if defined(MBEDTLS_RSA_C) + case MBEDTLS_PK_RSA: + return( &mbedtls_rsa_info ); +#endif +#if defined(MBEDTLS_ECP_C) + case MBEDTLS_PK_ECKEY: + return( &mbedtls_eckey_info ); + case MBEDTLS_PK_ECKEY_DH: + return( &mbedtls_eckeydh_info ); +#endif +#if defined(MBEDTLS_ECDSA_C) + case MBEDTLS_PK_ECDSA: + return( &mbedtls_ecdsa_info ); +#endif + /* MBEDTLS_PK_RSA_ALT omitted on purpose */ + default: + return( NULL ); + } +} + +/* + * Initialise context + */ +int mbedtls_pk_setup( mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info ) +{ + PK_VALIDATE_RET( ctx != NULL ); + if( info == NULL || ctx->pk_info != NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL ) + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + + ctx->pk_info = info; + + return( 0 ); +} + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/* + * Initialise a PSA-wrapping context + */ +int mbedtls_pk_setup_opaque( mbedtls_pk_context *ctx, const psa_key_handle_t key ) +{ + const mbedtls_pk_info_t * const info = &mbedtls_pk_opaque_info; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_key_handle_t *pk_ctx; + psa_key_type_t type; + + if( ctx == NULL || ctx->pk_info != NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( PSA_SUCCESS != psa_get_key_attributes( key, &attributes ) ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + type = psa_get_key_type( &attributes ); + psa_reset_key_attributes( &attributes ); + + /* Current implementation of can_do() relies on this. */ + if( ! PSA_KEY_TYPE_IS_ECC_KEY_PAIR( type ) ) + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE) ; + + if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL ) + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + + ctx->pk_info = info; + + pk_ctx = (psa_key_handle_t *) ctx->pk_ctx; + *pk_ctx = key; + + return( 0 ); +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/* + * Initialize an RSA-alt context + */ +int mbedtls_pk_setup_rsa_alt( mbedtls_pk_context *ctx, void * key, + mbedtls_pk_rsa_alt_decrypt_func decrypt_func, + mbedtls_pk_rsa_alt_sign_func sign_func, + mbedtls_pk_rsa_alt_key_len_func key_len_func ) +{ + mbedtls_rsa_alt_context *rsa_alt; + const mbedtls_pk_info_t *info = &mbedtls_rsa_alt_info; + + PK_VALIDATE_RET( ctx != NULL ); + if( ctx->pk_info != NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL ) + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + + ctx->pk_info = info; + + rsa_alt = (mbedtls_rsa_alt_context *) ctx->pk_ctx; + + rsa_alt->key = key; + rsa_alt->decrypt_func = decrypt_func; + rsa_alt->sign_func = sign_func; + rsa_alt->key_len_func = key_len_func; + + return( 0 ); +} +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ + +/* + * Tell if a PK can do the operations of the given type + */ +int mbedtls_pk_can_do( const mbedtls_pk_context *ctx, mbedtls_pk_type_t type ) +{ + /* A context with null pk_info is not set up yet and can't do anything. + * For backward compatibility, also accept NULL instead of a context + * pointer. */ + if( ctx == NULL || ctx->pk_info == NULL ) + return( 0 ); + + return( ctx->pk_info->can_do( type ) ); +} + +/* + * Helper for mbedtls_pk_sign and mbedtls_pk_verify + */ +static inline int pk_hashlen_helper( mbedtls_md_type_t md_alg, size_t *hash_len ) +{ + const mbedtls_md_info_t *md_info; + + if( *hash_len != 0 ) + return( 0 ); + + if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) == NULL ) + return( -1 ); + + *hash_len = mbedtls_md_get_size( md_info ); + return( 0 ); +} + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +/* + * Helper to set up a restart context if needed + */ +static int pk_restart_setup( mbedtls_pk_restart_ctx *ctx, + const mbedtls_pk_info_t *info ) +{ + /* Don't do anything if already set up or invalid */ + if( ctx == NULL || ctx->pk_info != NULL ) + return( 0 ); + + /* Should never happen when we're called */ + if( info->rs_alloc_func == NULL || info->rs_free_func == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ( ctx->rs_ctx = info->rs_alloc_func() ) == NULL ) + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + + ctx->pk_info = info; + + return( 0 ); +} +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + +/* + * Verify a signature (restartable) + */ +int mbedtls_pk_verify_restartable( mbedtls_pk_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + mbedtls_pk_restart_ctx *rs_ctx ) +{ + PK_VALIDATE_RET( ctx != NULL ); + PK_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && hash_len == 0 ) || + hash != NULL ); + PK_VALIDATE_RET( sig != NULL ); + + if( ctx->pk_info == NULL || + pk_hashlen_helper( md_alg, &hash_len ) != 0 ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /* optimization: use non-restartable version if restart disabled */ + if( rs_ctx != NULL && + mbedtls_ecp_restart_is_enabled() && + ctx->pk_info->verify_rs_func != NULL ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ( ret = pk_restart_setup( rs_ctx, ctx->pk_info ) ) != 0 ) + return( ret ); + + ret = ctx->pk_info->verify_rs_func( ctx->pk_ctx, + md_alg, hash, hash_len, sig, sig_len, rs_ctx->rs_ctx ); + + if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) + mbedtls_pk_restart_free( rs_ctx ); + + return( ret ); + } +#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + (void) rs_ctx; +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + + if( ctx->pk_info->verify_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + return( ctx->pk_info->verify_func( ctx->pk_ctx, md_alg, hash, hash_len, + sig, sig_len ) ); +} + +/* + * Verify a signature + */ +int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + return( mbedtls_pk_verify_restartable( ctx, md_alg, hash, hash_len, + sig, sig_len, NULL ) ); +} + +/* + * Verify a signature with options + */ +int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options, + mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + PK_VALIDATE_RET( ctx != NULL ); + PK_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && hash_len == 0 ) || + hash != NULL ); + PK_VALIDATE_RET( sig != NULL ); + + if( ctx->pk_info == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ! mbedtls_pk_can_do( ctx, type ) ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + if( type == MBEDTLS_PK_RSASSA_PSS ) + { +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21) + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const mbedtls_pk_rsassa_pss_options *pss_opts; + +#if SIZE_MAX > UINT_MAX + if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#endif /* SIZE_MAX > UINT_MAX */ + + if( options == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + pss_opts = (const mbedtls_pk_rsassa_pss_options *) options; + + if( sig_len < mbedtls_pk_get_len( ctx ) ) + return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); + + ret = mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_pk_rsa( *ctx ), + NULL, NULL, MBEDTLS_RSA_PUBLIC, + md_alg, (unsigned int) hash_len, hash, + pss_opts->mgf1_hash_id, + pss_opts->expected_salt_len, + sig ); + if( ret != 0 ) + return( ret ); + + if( sig_len > mbedtls_pk_get_len( ctx ) ) + return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); + + return( 0 ); +#else + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); +#endif /* MBEDTLS_RSA_C && MBEDTLS_PKCS1_V21 */ + } + + /* General case: no options */ + if( options != NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + return( mbedtls_pk_verify( ctx, md_alg, hash, hash_len, sig, sig_len ) ); +} + +/* + * Make a signature (restartable) + */ +int mbedtls_pk_sign_restartable( mbedtls_pk_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_pk_restart_ctx *rs_ctx ) +{ + PK_VALIDATE_RET( ctx != NULL ); + PK_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && hash_len == 0 ) || + hash != NULL ); + PK_VALIDATE_RET( sig != NULL ); + + if( ctx->pk_info == NULL || + pk_hashlen_helper( md_alg, &hash_len ) != 0 ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /* optimization: use non-restartable version if restart disabled */ + if( rs_ctx != NULL && + mbedtls_ecp_restart_is_enabled() && + ctx->pk_info->sign_rs_func != NULL ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ( ret = pk_restart_setup( rs_ctx, ctx->pk_info ) ) != 0 ) + return( ret ); + + ret = ctx->pk_info->sign_rs_func( ctx->pk_ctx, md_alg, + hash, hash_len, sig, sig_len, f_rng, p_rng, rs_ctx->rs_ctx ); + + if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) + mbedtls_pk_restart_free( rs_ctx ); + + return( ret ); + } +#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + (void) rs_ctx; +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + + if( ctx->pk_info->sign_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + return( ctx->pk_info->sign_func( ctx->pk_ctx, md_alg, hash, hash_len, + sig, sig_len, f_rng, p_rng ) ); +} + +/* + * Make a signature + */ +int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + return( mbedtls_pk_sign_restartable( ctx, md_alg, hash, hash_len, + sig, sig_len, f_rng, p_rng, NULL ) ); +} + +/* + * Decrypt message + */ +int mbedtls_pk_decrypt( mbedtls_pk_context *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + PK_VALIDATE_RET( ctx != NULL ); + PK_VALIDATE_RET( input != NULL || ilen == 0 ); + PK_VALIDATE_RET( output != NULL || osize == 0 ); + PK_VALIDATE_RET( olen != NULL ); + + if( ctx->pk_info == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ctx->pk_info->decrypt_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + return( ctx->pk_info->decrypt_func( ctx->pk_ctx, input, ilen, + output, olen, osize, f_rng, p_rng ) ); +} + +/* + * Encrypt message + */ +int mbedtls_pk_encrypt( mbedtls_pk_context *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + PK_VALIDATE_RET( ctx != NULL ); + PK_VALIDATE_RET( input != NULL || ilen == 0 ); + PK_VALIDATE_RET( output != NULL || osize == 0 ); + PK_VALIDATE_RET( olen != NULL ); + + if( ctx->pk_info == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ctx->pk_info->encrypt_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + return( ctx->pk_info->encrypt_func( ctx->pk_ctx, input, ilen, + output, olen, osize, f_rng, p_rng ) ); +} + +/* + * Check public-private key pair + */ +int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, const mbedtls_pk_context *prv ) +{ + PK_VALIDATE_RET( pub != NULL ); + PK_VALIDATE_RET( prv != NULL ); + + if( pub->pk_info == NULL || + prv->pk_info == NULL ) + { + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + } + + if( prv->pk_info->check_pair_func == NULL ) + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + + if( prv->pk_info->type == MBEDTLS_PK_RSA_ALT ) + { + if( pub->pk_info->type != MBEDTLS_PK_RSA ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + } + else + { + if( pub->pk_info != prv->pk_info ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + } + + return( prv->pk_info->check_pair_func( pub->pk_ctx, prv->pk_ctx ) ); +} + +/* + * Get key size in bits + */ +size_t mbedtls_pk_get_bitlen( const mbedtls_pk_context *ctx ) +{ + /* For backward compatibility, accept NULL or a context that + * isn't set up yet, and return a fake value that should be safe. */ + if( ctx == NULL || ctx->pk_info == NULL ) + return( 0 ); + + return( ctx->pk_info->get_bitlen( ctx->pk_ctx ) ); +} + +/* + * Export debug information + */ +int mbedtls_pk_debug( const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items ) +{ + PK_VALIDATE_RET( ctx != NULL ); + if( ctx->pk_info == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ctx->pk_info->debug_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + ctx->pk_info->debug_func( ctx->pk_ctx, items ); + return( 0 ); +} + +/* + * Access the PK type name + */ +const char *mbedtls_pk_get_name( const mbedtls_pk_context *ctx ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( "invalid PK" ); + + return( ctx->pk_info->name ); +} + +/* + * Access the PK type + */ +mbedtls_pk_type_t mbedtls_pk_get_type( const mbedtls_pk_context *ctx ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( MBEDTLS_PK_NONE ); + + return( ctx->pk_info->type ); +} + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/* + * Load the key to a PSA key slot, + * then turn the PK context into a wrapper for that key slot. + * + * Currently only works for EC private keys. + */ +int mbedtls_pk_wrap_as_opaque( mbedtls_pk_context *pk, + psa_key_handle_t *handle, + psa_algorithm_t hash_alg ) +{ +#if !defined(MBEDTLS_ECP_C) + ((void) pk); + ((void) handle); + ((void) hash_alg); + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); +#else + const mbedtls_ecp_keypair *ec; + unsigned char d[MBEDTLS_ECP_MAX_BYTES]; + size_t d_len; + psa_ecc_family_t curve_id; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_key_type_t key_type; + size_t bits; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* export the private key material in the format PSA wants */ + if( mbedtls_pk_get_type( pk ) != MBEDTLS_PK_ECKEY ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + ec = mbedtls_pk_ec( *pk ); + d_len = ( ec->grp.nbits + 7 ) / 8; + if( ( ret = mbedtls_mpi_write_binary( &ec->d, d, d_len ) ) != 0 ) + return( ret ); + + curve_id = mbedtls_ecc_group_to_psa( ec->grp.id, &bits ); + key_type = PSA_KEY_TYPE_ECC_KEY_PAIR( curve_id ); + + /* prepare the key attributes */ + psa_set_key_type( &attributes, key_type ); + psa_set_key_bits( &attributes, bits ); + psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_SIGN_HASH ); + psa_set_key_algorithm( &attributes, PSA_ALG_ECDSA(hash_alg) ); + + /* import private key into PSA */ + if( PSA_SUCCESS != psa_import_key( &attributes, d, d_len, handle ) ) + return( MBEDTLS_ERR_PK_HW_ACCEL_FAILED ); + + /* make PK context wrap the key slot */ + mbedtls_pk_free( pk ); + mbedtls_pk_init( pk ); + + return( mbedtls_pk_setup_opaque( pk, *handle ) ); +#endif /* MBEDTLS_ECP_C */ +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#endif /* MBEDTLS_PK_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/pk_wrap.c b/Android/Level4/app/src/main/c/mbedtls/library/pk_wrap.c new file mode 100644 index 0000000..903c53b --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/pk_wrap.c @@ -0,0 +1,1069 @@ +/* + * Public Key abstraction layer: wrapper functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 "common.h" + +#if defined(MBEDTLS_PK_C) +#include "mbedtls/pk_internal.h" +#include "mbedtls/error.h" + +/* Even if RSA not activated, for the sake of RSA-alt */ +#include "mbedtls/rsa.h" + +#include + +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/ecp.h" +#endif + +#if defined(MBEDTLS_ECDSA_C) +#include "mbedtls/ecdsa.h" +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "mbedtls/asn1write.h" +#endif + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +#include "mbedtls/platform_util.h" +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#include "mbedtls/psa_util.h" +#include "mbedtls/asn1.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include +#include + +#if defined(MBEDTLS_RSA_C) +static int rsa_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_RSA || + type == MBEDTLS_PK_RSASSA_PSS ); +} + +static size_t rsa_get_bitlen( const void *ctx ) +{ + const mbedtls_rsa_context * rsa = (const mbedtls_rsa_context *) ctx; + return( 8 * mbedtls_rsa_get_len( rsa ) ); +} + +static int rsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx; + size_t rsa_len = mbedtls_rsa_get_len( rsa ); + +#if SIZE_MAX > UINT_MAX + if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#endif /* SIZE_MAX > UINT_MAX */ + + if( sig_len < rsa_len ) + return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); + + if( ( ret = mbedtls_rsa_pkcs1_verify( rsa, NULL, NULL, + MBEDTLS_RSA_PUBLIC, md_alg, + (unsigned int) hash_len, hash, sig ) ) != 0 ) + return( ret ); + + /* The buffer contains a valid signature followed by extra data. + * We have a special error code for that so that so that callers can + * use mbedtls_pk_verify() to check "Does the buffer start with a + * valid signature?" and not just "Does the buffer contain a valid + * signature?". */ + if( sig_len > rsa_len ) + return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); + + return( 0 ); +} + +static int rsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx; + +#if SIZE_MAX > UINT_MAX + if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#endif /* SIZE_MAX > UINT_MAX */ + + *sig_len = mbedtls_rsa_get_len( rsa ); + + return( mbedtls_rsa_pkcs1_sign( rsa, f_rng, p_rng, MBEDTLS_RSA_PRIVATE, + md_alg, (unsigned int) hash_len, hash, sig ) ); +} + +static int rsa_decrypt_wrap( void *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx; + + if( ilen != mbedtls_rsa_get_len( rsa ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + return( mbedtls_rsa_pkcs1_decrypt( rsa, f_rng, p_rng, + MBEDTLS_RSA_PRIVATE, olen, input, output, osize ) ); +} + +static int rsa_encrypt_wrap( void *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx; + *olen = mbedtls_rsa_get_len( rsa ); + + if( *olen > osize ) + return( MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE ); + + return( mbedtls_rsa_pkcs1_encrypt( rsa, f_rng, p_rng, MBEDTLS_RSA_PUBLIC, + ilen, input, output ) ); +} + +static int rsa_check_pair_wrap( const void *pub, const void *prv ) +{ + return( mbedtls_rsa_check_pub_priv( (const mbedtls_rsa_context *) pub, + (const mbedtls_rsa_context *) prv ) ); +} + +static void *rsa_alloc_wrap( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_rsa_context ) ); + + if( ctx != NULL ) + mbedtls_rsa_init( (mbedtls_rsa_context *) ctx, 0, 0 ); + + return( ctx ); +} + +static void rsa_free_wrap( void *ctx ) +{ + mbedtls_rsa_free( (mbedtls_rsa_context *) ctx ); + mbedtls_free( ctx ); +} + +static void rsa_debug( const void *ctx, mbedtls_pk_debug_item *items ) +{ + items->type = MBEDTLS_PK_DEBUG_MPI; + items->name = "rsa.N"; + items->value = &( ((mbedtls_rsa_context *) ctx)->N ); + + items++; + + items->type = MBEDTLS_PK_DEBUG_MPI; + items->name = "rsa.E"; + items->value = &( ((mbedtls_rsa_context *) ctx)->E ); +} + +const mbedtls_pk_info_t mbedtls_rsa_info = { + MBEDTLS_PK_RSA, + "RSA", + rsa_get_bitlen, + rsa_can_do, + rsa_verify_wrap, + rsa_sign_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif + rsa_decrypt_wrap, + rsa_encrypt_wrap, + rsa_check_pair_wrap, + rsa_alloc_wrap, + rsa_free_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif + rsa_debug, +}; +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) +/* + * Generic EC key + */ +static int eckey_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_ECKEY || + type == MBEDTLS_PK_ECKEY_DH || + type == MBEDTLS_PK_ECDSA ); +} + +static size_t eckey_get_bitlen( const void *ctx ) +{ + return( ((mbedtls_ecp_keypair *) ctx)->grp.pbits ); +} + +#if defined(MBEDTLS_ECDSA_C) +/* Forward declarations */ +static int ecdsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ); + +static int ecdsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +static int eckey_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecdsa_context ecdsa; + + mbedtls_ecdsa_init( &ecdsa ); + + if( ( ret = mbedtls_ecdsa_from_keypair( &ecdsa, ctx ) ) == 0 ) + ret = ecdsa_verify_wrap( &ecdsa, md_alg, hash, hash_len, sig, sig_len ); + + mbedtls_ecdsa_free( &ecdsa ); + + return( ret ); +} + +static int eckey_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecdsa_context ecdsa; + + mbedtls_ecdsa_init( &ecdsa ); + + if( ( ret = mbedtls_ecdsa_from_keypair( &ecdsa, ctx ) ) == 0 ) + ret = ecdsa_sign_wrap( &ecdsa, md_alg, hash, hash_len, sig, sig_len, + f_rng, p_rng ); + + mbedtls_ecdsa_free( &ecdsa ); + + return( ret ); +} + +#if defined(MBEDTLS_ECP_RESTARTABLE) +/* Forward declarations */ +static int ecdsa_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + void *rs_ctx ); + +static int ecdsa_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + void *rs_ctx ); + +/* + * Restart context for ECDSA operations with ECKEY context + * + * We need to store an actual ECDSA context, as we need to pass the same to + * the underlying ecdsa function, so we can't create it on the fly every time. + */ +typedef struct +{ + mbedtls_ecdsa_restart_ctx ecdsa_rs; + mbedtls_ecdsa_context ecdsa_ctx; +} eckey_restart_ctx; + +static void *eckey_rs_alloc( void ) +{ + eckey_restart_ctx *rs_ctx; + + void *ctx = mbedtls_calloc( 1, sizeof( eckey_restart_ctx ) ); + + if( ctx != NULL ) + { + rs_ctx = ctx; + mbedtls_ecdsa_restart_init( &rs_ctx->ecdsa_rs ); + mbedtls_ecdsa_init( &rs_ctx->ecdsa_ctx ); + } + + return( ctx ); +} + +static void eckey_rs_free( void *ctx ) +{ + eckey_restart_ctx *rs_ctx; + + if( ctx == NULL) + return; + + rs_ctx = ctx; + mbedtls_ecdsa_restart_free( &rs_ctx->ecdsa_rs ); + mbedtls_ecdsa_free( &rs_ctx->ecdsa_ctx ); + + mbedtls_free( ctx ); +} + +static int eckey_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + void *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + eckey_restart_ctx *rs = rs_ctx; + + /* Should never happen */ + if( rs == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + /* set up our own sub-context if needed (that is, on first run) */ + if( rs->ecdsa_ctx.grp.pbits == 0 ) + MBEDTLS_MPI_CHK( mbedtls_ecdsa_from_keypair( &rs->ecdsa_ctx, ctx ) ); + + MBEDTLS_MPI_CHK( ecdsa_verify_rs_wrap( &rs->ecdsa_ctx, + md_alg, hash, hash_len, + sig, sig_len, &rs->ecdsa_rs ) ); + +cleanup: + return( ret ); +} + +static int eckey_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + void *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + eckey_restart_ctx *rs = rs_ctx; + + /* Should never happen */ + if( rs == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + /* set up our own sub-context if needed (that is, on first run) */ + if( rs->ecdsa_ctx.grp.pbits == 0 ) + MBEDTLS_MPI_CHK( mbedtls_ecdsa_from_keypair( &rs->ecdsa_ctx, ctx ) ); + + MBEDTLS_MPI_CHK( ecdsa_sign_rs_wrap( &rs->ecdsa_ctx, md_alg, + hash, hash_len, sig, sig_len, + f_rng, p_rng, &rs->ecdsa_rs ) ); + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_RESTARTABLE */ +#endif /* MBEDTLS_ECDSA_C */ + +static int eckey_check_pair( const void *pub, const void *prv ) +{ + return( mbedtls_ecp_check_pub_priv( (const mbedtls_ecp_keypair *) pub, + (const mbedtls_ecp_keypair *) prv ) ); +} + +static void *eckey_alloc_wrap( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecp_keypair ) ); + + if( ctx != NULL ) + mbedtls_ecp_keypair_init( ctx ); + + return( ctx ); +} + +static void eckey_free_wrap( void *ctx ) +{ + mbedtls_ecp_keypair_free( (mbedtls_ecp_keypair *) ctx ); + mbedtls_free( ctx ); +} + +static void eckey_debug( const void *ctx, mbedtls_pk_debug_item *items ) +{ + items->type = MBEDTLS_PK_DEBUG_ECP; + items->name = "eckey.Q"; + items->value = &( ((mbedtls_ecp_keypair *) ctx)->Q ); +} + +const mbedtls_pk_info_t mbedtls_eckey_info = { + MBEDTLS_PK_ECKEY, + "EC", + eckey_get_bitlen, + eckey_can_do, +#if defined(MBEDTLS_ECDSA_C) + eckey_verify_wrap, + eckey_sign_wrap, +#if defined(MBEDTLS_ECP_RESTARTABLE) + eckey_verify_rs_wrap, + eckey_sign_rs_wrap, +#endif +#else /* MBEDTLS_ECDSA_C */ + NULL, + NULL, +#endif /* MBEDTLS_ECDSA_C */ + NULL, + NULL, + eckey_check_pair, + eckey_alloc_wrap, + eckey_free_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + eckey_rs_alloc, + eckey_rs_free, +#endif + eckey_debug, +}; + +/* + * EC key restricted to ECDH + */ +static int eckeydh_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_ECKEY || + type == MBEDTLS_PK_ECKEY_DH ); +} + +const mbedtls_pk_info_t mbedtls_eckeydh_info = { + MBEDTLS_PK_ECKEY_DH, + "EC_DH", + eckey_get_bitlen, /* Same underlying key structure */ + eckeydh_can_do, + NULL, + NULL, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif + NULL, + NULL, + eckey_check_pair, + eckey_alloc_wrap, /* Same underlying key structure */ + eckey_free_wrap, /* Same underlying key structure */ +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif + eckey_debug, /* Same underlying key structure */ +}; +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_ECDSA_C) +static int ecdsa_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_ECDSA ); +} + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/* + * An ASN.1 encoded signature is a sequence of two ASN.1 integers. Parse one of + * those integers and convert it to the fixed-length encoding expected by PSA. + */ +static int extract_ecdsa_sig_int( unsigned char **from, const unsigned char *end, + unsigned char *to, size_t to_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t unpadded_len, padding_len; + + if( ( ret = mbedtls_asn1_get_tag( from, end, &unpadded_len, + MBEDTLS_ASN1_INTEGER ) ) != 0 ) + { + return( ret ); + } + + while( unpadded_len > 0 && **from == 0x00 ) + { + ( *from )++; + unpadded_len--; + } + + if( unpadded_len > to_len || unpadded_len == 0 ) + return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + padding_len = to_len - unpadded_len; + memset( to, 0x00, padding_len ); + memcpy( to + padding_len, *from, unpadded_len ); + ( *from ) += unpadded_len; + + return( 0 ); +} + +/* + * Convert a signature from an ASN.1 sequence of two integers + * to a raw {r,s} buffer. Note: the provided sig buffer must be at least + * twice as big as int_size. + */ +static int extract_ecdsa_sig( unsigned char **p, const unsigned char *end, + unsigned char *sig, size_t int_size ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t tmp_size; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &tmp_size, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( ret ); + + /* Extract r */ + if( ( ret = extract_ecdsa_sig_int( p, end, sig, int_size ) ) != 0 ) + return( ret ); + /* Extract s */ + if( ( ret = extract_ecdsa_sig_int( p, end, sig + int_size, int_size ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +static int ecdsa_verify_wrap( void *ctx_arg, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + mbedtls_ecdsa_context *ctx = ctx_arg; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_key_handle_t key_handle = 0; + psa_status_t status; + mbedtls_pk_context key; + int key_len; + /* see ECP_PUB_DER_MAX_BYTES in pkwrite.c */ + unsigned char buf[30 + 2 * MBEDTLS_ECP_MAX_BYTES]; + unsigned char *p; + mbedtls_pk_info_t pk_info = mbedtls_eckey_info; + psa_algorithm_t psa_sig_md = PSA_ALG_ECDSA_ANY; + size_t curve_bits; + psa_ecc_family_t curve = + mbedtls_ecc_group_to_psa( ctx->grp.id, &curve_bits ); + const size_t signature_part_size = ( ctx->grp.nbits + 7 ) / 8; + ((void) md_alg); + + if( curve == 0 ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + /* mbedtls_pk_write_pubkey() expects a full PK context; + * re-construct one to make it happy */ + key.pk_info = &pk_info; + key.pk_ctx = ctx; + p = buf + sizeof( buf ); + key_len = mbedtls_pk_write_pubkey( &p, buf, &key ); + if( key_len <= 0 ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + psa_set_key_type( &attributes, PSA_KEY_TYPE_ECC_PUBLIC_KEY( curve ) ); + psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_VERIFY_HASH ); + psa_set_key_algorithm( &attributes, psa_sig_md ); + + status = psa_import_key( &attributes, + buf + sizeof( buf ) - key_len, key_len, + &key_handle ); + if( status != PSA_SUCCESS ) + { + ret = mbedtls_psa_err_translate_pk( status ); + goto cleanup; + } + + /* We don't need the exported key anymore and can + * reuse its buffer for signature extraction. */ + if( 2 * signature_part_size > sizeof( buf ) ) + { + ret = MBEDTLS_ERR_PK_BAD_INPUT_DATA; + goto cleanup; + } + + p = (unsigned char*) sig; + if( ( ret = extract_ecdsa_sig( &p, sig + sig_len, buf, + signature_part_size ) ) != 0 ) + { + goto cleanup; + } + + if( psa_verify_hash( key_handle, psa_sig_md, + hash, hash_len, + buf, 2 * signature_part_size ) + != PSA_SUCCESS ) + { + ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; + goto cleanup; + } + + if( p != sig + sig_len ) + { + ret = MBEDTLS_ERR_PK_SIG_LEN_MISMATCH; + goto cleanup; + } + ret = 0; + +cleanup: + psa_destroy_key( key_handle ); + return( ret ); +} +#else /* MBEDTLS_USE_PSA_CRYPTO */ +static int ecdsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + ((void) md_alg); + + ret = mbedtls_ecdsa_read_signature( (mbedtls_ecdsa_context *) ctx, + hash, hash_len, sig, sig_len ); + + if( ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH ) + return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); + + return( ret ); +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +static int ecdsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + return( mbedtls_ecdsa_write_signature( (mbedtls_ecdsa_context *) ctx, + md_alg, hash, hash_len, sig, sig_len, f_rng, p_rng ) ); +} + +#if defined(MBEDTLS_ECP_RESTARTABLE) +static int ecdsa_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + void *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + ((void) md_alg); + + ret = mbedtls_ecdsa_read_signature_restartable( + (mbedtls_ecdsa_context *) ctx, + hash, hash_len, sig, sig_len, + (mbedtls_ecdsa_restart_ctx *) rs_ctx ); + + if( ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH ) + return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); + + return( ret ); +} + +static int ecdsa_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + void *rs_ctx ) +{ + return( mbedtls_ecdsa_write_signature_restartable( + (mbedtls_ecdsa_context *) ctx, + md_alg, hash, hash_len, sig, sig_len, f_rng, p_rng, + (mbedtls_ecdsa_restart_ctx *) rs_ctx ) ); + +} +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +static void *ecdsa_alloc_wrap( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecdsa_context ) ); + + if( ctx != NULL ) + mbedtls_ecdsa_init( (mbedtls_ecdsa_context *) ctx ); + + return( ctx ); +} + +static void ecdsa_free_wrap( void *ctx ) +{ + mbedtls_ecdsa_free( (mbedtls_ecdsa_context *) ctx ); + mbedtls_free( ctx ); +} + +#if defined(MBEDTLS_ECP_RESTARTABLE) +static void *ecdsa_rs_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecdsa_restart_ctx ) ); + + if( ctx != NULL ) + mbedtls_ecdsa_restart_init( ctx ); + + return( ctx ); +} + +static void ecdsa_rs_free( void *ctx ) +{ + mbedtls_ecdsa_restart_free( ctx ); + mbedtls_free( ctx ); +} +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +const mbedtls_pk_info_t mbedtls_ecdsa_info = { + MBEDTLS_PK_ECDSA, + "ECDSA", + eckey_get_bitlen, /* Compatible key structures */ + ecdsa_can_do, + ecdsa_verify_wrap, + ecdsa_sign_wrap, +#if defined(MBEDTLS_ECP_RESTARTABLE) + ecdsa_verify_rs_wrap, + ecdsa_sign_rs_wrap, +#endif + NULL, + NULL, + eckey_check_pair, /* Compatible key structures */ + ecdsa_alloc_wrap, + ecdsa_free_wrap, +#if defined(MBEDTLS_ECP_RESTARTABLE) + ecdsa_rs_alloc, + ecdsa_rs_free, +#endif + eckey_debug, /* Compatible key structures */ +}; +#endif /* MBEDTLS_ECDSA_C */ + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/* + * Support for alternative RSA-private implementations + */ + +static int rsa_alt_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_RSA ); +} + +static size_t rsa_alt_get_bitlen( const void *ctx ) +{ + const mbedtls_rsa_alt_context *rsa_alt = (const mbedtls_rsa_alt_context *) ctx; + + return( 8 * rsa_alt->key_len_func( rsa_alt->key ) ); +} + +static int rsa_alt_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + mbedtls_rsa_alt_context *rsa_alt = (mbedtls_rsa_alt_context *) ctx; + +#if SIZE_MAX > UINT_MAX + if( UINT_MAX < hash_len ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#endif /* SIZE_MAX > UINT_MAX */ + + *sig_len = rsa_alt->key_len_func( rsa_alt->key ); + if( *sig_len > MBEDTLS_PK_SIGNATURE_MAX_SIZE ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + return( rsa_alt->sign_func( rsa_alt->key, f_rng, p_rng, MBEDTLS_RSA_PRIVATE, + md_alg, (unsigned int) hash_len, hash, sig ) ); +} + +static int rsa_alt_decrypt_wrap( void *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + mbedtls_rsa_alt_context *rsa_alt = (mbedtls_rsa_alt_context *) ctx; + + ((void) f_rng); + ((void) p_rng); + + if( ilen != rsa_alt->key_len_func( rsa_alt->key ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + return( rsa_alt->decrypt_func( rsa_alt->key, + MBEDTLS_RSA_PRIVATE, olen, input, output, osize ) ); +} + +#if defined(MBEDTLS_RSA_C) +static int rsa_alt_check_pair( const void *pub, const void *prv ) +{ + unsigned char sig[MBEDTLS_MPI_MAX_SIZE]; + unsigned char hash[32]; + size_t sig_len = 0; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( rsa_alt_get_bitlen( prv ) != rsa_get_bitlen( pub ) ) + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + + memset( hash, 0x2a, sizeof( hash ) ); + + if( ( ret = rsa_alt_sign_wrap( (void *) prv, MBEDTLS_MD_NONE, + hash, sizeof( hash ), + sig, &sig_len, NULL, NULL ) ) != 0 ) + { + return( ret ); + } + + if( rsa_verify_wrap( (void *) pub, MBEDTLS_MD_NONE, + hash, sizeof( hash ), sig, sig_len ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + return( 0 ); +} +#endif /* MBEDTLS_RSA_C */ + +static void *rsa_alt_alloc_wrap( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_rsa_alt_context ) ); + + if( ctx != NULL ) + memset( ctx, 0, sizeof( mbedtls_rsa_alt_context ) ); + + return( ctx ); +} + +static void rsa_alt_free_wrap( void *ctx ) +{ + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_rsa_alt_context ) ); + mbedtls_free( ctx ); +} + +const mbedtls_pk_info_t mbedtls_rsa_alt_info = { + MBEDTLS_PK_RSA_ALT, + "RSA-alt", + rsa_alt_get_bitlen, + rsa_alt_can_do, + NULL, + rsa_alt_sign_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif + rsa_alt_decrypt_wrap, + NULL, +#if defined(MBEDTLS_RSA_C) + rsa_alt_check_pair, +#else + NULL, +#endif + rsa_alt_alloc_wrap, + rsa_alt_free_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif + NULL, +}; + +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + +static void *pk_opaque_alloc_wrap( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( psa_key_handle_t ) ); + + /* no _init() function to call, an calloc() already zeroized */ + + return( ctx ); +} + +static void pk_opaque_free_wrap( void *ctx ) +{ + mbedtls_platform_zeroize( ctx, sizeof( psa_key_handle_t ) ); + mbedtls_free( ctx ); +} + +static size_t pk_opaque_get_bitlen( const void *ctx ) +{ + const psa_key_handle_t *key = (const psa_key_handle_t *) ctx; + size_t bits; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + + if( PSA_SUCCESS != psa_get_key_attributes( *key, &attributes ) ) + return( 0 ); + + bits = psa_get_key_bits( &attributes ); + psa_reset_key_attributes( &attributes ); + return( bits ); +} + +static int pk_opaque_can_do( mbedtls_pk_type_t type ) +{ + /* For now opaque PSA keys can only wrap ECC keypairs, + * as checked by setup_psa(). + * Also, ECKEY_DH does not really make sense with the current API. */ + return( type == MBEDTLS_PK_ECKEY || + type == MBEDTLS_PK_ECDSA ); +} + +#if defined(MBEDTLS_ECDSA_C) + +/* + * Simultaneously convert and move raw MPI from the beginning of a buffer + * to an ASN.1 MPI at the end of the buffer. + * See also mbedtls_asn1_write_mpi(). + * + * p: pointer to the end of the output buffer + * start: start of the output buffer, and also of the mpi to write at the end + * n_len: length of the mpi to read from start + */ +static int asn1_write_mpibuf( unsigned char **p, unsigned char *start, + size_t n_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + if( (size_t)( *p - start ) < n_len ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + len = n_len; + *p -= len; + memmove( *p, start, len ); + + /* ASN.1 DER encoding requires minimal length, so skip leading 0s. + * Neither r nor s should be 0, but as a failsafe measure, still detect + * that rather than overflowing the buffer in case of a PSA error. */ + while( len > 0 && **p == 0x00 ) + { + ++(*p); + --len; + } + + /* this is only reached if the signature was invalid */ + if( len == 0 ) + return( MBEDTLS_ERR_PK_HW_ACCEL_FAILED ); + + /* if the msb is 1, ASN.1 requires that we prepend a 0. + * Neither r nor s can be 0, so we can assume len > 0 at all times. */ + if( **p & 0x80 ) + { + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = 0x00; + len += 1; + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, + MBEDTLS_ASN1_INTEGER ) ); + + return( (int) len ); +} + +/* Transcode signature from PSA format to ASN.1 sequence. + * See ecdsa_signature_to_asn1 in ecdsa.c, but with byte buffers instead of + * MPIs, and in-place. + * + * [in/out] sig: the signature pre- and post-transcoding + * [in/out] sig_len: signature length pre- and post-transcoding + * [int] buf_len: the available size the in/out buffer + */ +static int pk_ecdsa_sig_asn1_from_psa( unsigned char *sig, size_t *sig_len, + size_t buf_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + const size_t rs_len = *sig_len / 2; + unsigned char *p = sig + buf_len; + + MBEDTLS_ASN1_CHK_ADD( len, asn1_write_mpibuf( &p, sig + rs_len, rs_len ) ); + MBEDTLS_ASN1_CHK_ADD( len, asn1_write_mpibuf( &p, sig, rs_len ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &p, sig, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &p, sig, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); + + memmove( sig, p, len ); + *sig_len = len; + + return( 0 ); +} + +#endif /* MBEDTLS_ECDSA_C */ + +static int pk_opaque_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ +#if !defined(MBEDTLS_ECDSA_C) + ((void) ctx); + ((void) md_alg); + ((void) hash); + ((void) hash_len); + ((void) sig); + ((void) sig_len); + ((void) f_rng); + ((void) p_rng); + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); +#else /* !MBEDTLS_ECDSA_C */ + const psa_key_handle_t *key = (const psa_key_handle_t *) ctx; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_algorithm_t alg = PSA_ALG_ECDSA( mbedtls_psa_translate_md( md_alg ) ); + size_t buf_len; + psa_status_t status; + + /* PSA has its own RNG */ + (void) f_rng; + (void) p_rng; + + /* PSA needs an output buffer of known size, but our API doesn't provide + * that information. Assume that the buffer is large enough for a + * maximal-length signature with that key (otherwise the application is + * buggy anyway). */ + status = psa_get_key_attributes( *key, &attributes ); + if( status != PSA_SUCCESS ) + return( mbedtls_psa_err_translate_pk( status ) ); + buf_len = MBEDTLS_ECDSA_MAX_SIG_LEN( psa_get_key_bits( &attributes ) ); + psa_reset_key_attributes( &attributes ); + if( buf_len > MBEDTLS_PK_SIGNATURE_MAX_SIZE ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + /* make the signature */ + status = psa_sign_hash( *key, alg, hash, hash_len, + sig, buf_len, sig_len ); + if( status != PSA_SUCCESS ) + return( mbedtls_psa_err_translate_pk( status ) ); + + /* transcode it to ASN.1 sequence */ + return( pk_ecdsa_sig_asn1_from_psa( sig, sig_len, buf_len ) ); +#endif /* !MBEDTLS_ECDSA_C */ +} + +const mbedtls_pk_info_t mbedtls_pk_opaque_info = { + MBEDTLS_PK_OPAQUE, + "Opaque", + pk_opaque_get_bitlen, + pk_opaque_can_do, + NULL, /* verify - will be done later */ + pk_opaque_sign_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, /* restartable verify - not relevant */ + NULL, /* restartable sign - not relevant */ +#endif + NULL, /* decrypt - will be done later */ + NULL, /* encrypt - will be done later */ + NULL, /* check_pair - could be done later or left NULL */ + pk_opaque_alloc_wrap, + pk_opaque_free_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, /* restart alloc - not relevant */ + NULL, /* restart free - not relevant */ +#endif + NULL, /* debug - could be done later, or even left NULL */ +}; + +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#endif /* MBEDTLS_PK_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/pkcs11.c b/Android/Level4/app/src/main/c/mbedtls/library/pkcs11.c new file mode 100644 index 0000000..4deccf3 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/pkcs11.c @@ -0,0 +1,238 @@ +/** + * \file pkcs11.c + * + * \brief Wrapper for PKCS#11 library libpkcs11-helper + * + * \author Adriaan de Jong + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 "mbedtls/pkcs11.h" + +#if defined(MBEDTLS_PKCS11_C) + +#include "mbedtls/md.h" +#include "mbedtls/oid.h" +#include "mbedtls/x509_crt.h" + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include + +void mbedtls_pkcs11_init( mbedtls_pkcs11_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_pkcs11_context ) ); +} + +int mbedtls_pkcs11_x509_cert_bind( mbedtls_x509_crt *cert, pkcs11h_certificate_t pkcs11_cert ) +{ + int ret = 1; + unsigned char *cert_blob = NULL; + size_t cert_blob_size = 0; + + if( cert == NULL ) + { + ret = 2; + goto cleanup; + } + + if( pkcs11h_certificate_getCertificateBlob( pkcs11_cert, NULL, + &cert_blob_size ) != CKR_OK ) + { + ret = 3; + goto cleanup; + } + + cert_blob = mbedtls_calloc( 1, cert_blob_size ); + if( NULL == cert_blob ) + { + ret = 4; + goto cleanup; + } + + if( pkcs11h_certificate_getCertificateBlob( pkcs11_cert, cert_blob, + &cert_blob_size ) != CKR_OK ) + { + ret = 5; + goto cleanup; + } + + if( 0 != mbedtls_x509_crt_parse( cert, cert_blob, cert_blob_size ) ) + { + ret = 6; + goto cleanup; + } + + ret = 0; + +cleanup: + if( NULL != cert_blob ) + mbedtls_free( cert_blob ); + + return( ret ); +} + + +int mbedtls_pkcs11_priv_key_bind( mbedtls_pkcs11_context *priv_key, + pkcs11h_certificate_t pkcs11_cert ) +{ + int ret = 1; + mbedtls_x509_crt cert; + + mbedtls_x509_crt_init( &cert ); + + if( priv_key == NULL ) + goto cleanup; + + if( 0 != mbedtls_pkcs11_x509_cert_bind( &cert, pkcs11_cert ) ) + goto cleanup; + + priv_key->len = mbedtls_pk_get_len( &cert.pk ); + priv_key->pkcs11h_cert = pkcs11_cert; + + ret = 0; + +cleanup: + mbedtls_x509_crt_free( &cert ); + + return( ret ); +} + +void mbedtls_pkcs11_priv_key_free( mbedtls_pkcs11_context *priv_key ) +{ + if( NULL != priv_key ) + pkcs11h_certificate_freeCertificate( priv_key->pkcs11h_cert ); +} + +int mbedtls_pkcs11_decrypt( mbedtls_pkcs11_context *ctx, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ) +{ + size_t input_len, output_len; + + if( NULL == ctx ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( MBEDTLS_RSA_PRIVATE != mode ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + output_len = input_len = ctx->len; + + if( input_len < 16 || input_len > output_max_len ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* Determine size of output buffer */ + if( pkcs11h_certificate_decryptAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, input, + input_len, NULL, &output_len ) != CKR_OK ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + if( output_len > output_max_len ) + return( MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE ); + + if( pkcs11h_certificate_decryptAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, input, + input_len, output, &output_len ) != CKR_OK ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + *olen = output_len; + return( 0 ); +} + +int mbedtls_pkcs11_sign( mbedtls_pkcs11_context *ctx, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ) +{ + size_t sig_len = 0, asn_len = 0, oid_size = 0; + unsigned char *p = sig; + const char *oid; + + if( NULL == ctx ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( MBEDTLS_RSA_PRIVATE != mode ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( md_alg != MBEDTLS_MD_NONE ) + { + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( mbedtls_oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hashlen = mbedtls_md_get_size( md_info ); + asn_len = 10 + oid_size; + } + + sig_len = ctx->len; + if( hashlen > sig_len || asn_len > sig_len || + hashlen + asn_len > sig_len ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + if( md_alg != MBEDTLS_MD_NONE ) + { + /* + * DigestInfo ::= SEQUENCE { + * digestAlgorithm DigestAlgorithmIdentifier, + * digest Digest } + * + * DigestAlgorithmIdentifier ::= AlgorithmIdentifier + * + * Digest ::= OCTET STRING + */ + *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; + *p++ = (unsigned char) ( 0x08 + oid_size + hashlen ); + *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; + *p++ = (unsigned char) ( 0x04 + oid_size ); + *p++ = MBEDTLS_ASN1_OID; + *p++ = oid_size & 0xFF; + memcpy( p, oid, oid_size ); + p += oid_size; + *p++ = MBEDTLS_ASN1_NULL; + *p++ = 0x00; + *p++ = MBEDTLS_ASN1_OCTET_STRING; + *p++ = hashlen; + } + + memcpy( p, hash, hashlen ); + + if( pkcs11h_certificate_signAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, sig, + asn_len + hashlen, sig, &sig_len ) != CKR_OK ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + return( 0 ); +} + +#endif /* defined(MBEDTLS_PKCS11_C) */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/pkcs12.c b/Android/Level4/app/src/main/c/mbedtls/library/pkcs12.c new file mode 100644 index 0000000..4bdeb68 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/pkcs12.c @@ -0,0 +1,360 @@ +/* + * PKCS#12 Personal Information Exchange Syntax + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ +/* + * The PKCS #12 Personal Information Exchange Syntax Standard v1.1 + * + * http://www.rsa.com/rsalabs/pkcs/files/h11301-wp-pkcs-12v1-1-personal-information-exchange-syntax.pdf + * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12v1-1.asn + */ + +#include "common.h" + +#if defined(MBEDTLS_PKCS12_C) + +#include "mbedtls/pkcs12.h" +#include "mbedtls/asn1.h" +#include "mbedtls/cipher.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_ARC4_C) +#include "mbedtls/arc4.h" +#endif + +#if defined(MBEDTLS_DES_C) +#include "mbedtls/des.h" +#endif + +#if defined(MBEDTLS_ASN1_PARSE_C) + +static int pkcs12_parse_pbe_params( mbedtls_asn1_buf *params, + mbedtls_asn1_buf *salt, int *iterations ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char **p = ¶ms->p; + const unsigned char *end = params->p + params->len; + + /* + * pkcs-12PbeParams ::= SEQUENCE { + * salt OCTET STRING, + * iterations INTEGER + * } + * + */ + if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) + return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + if( ( ret = mbedtls_asn1_get_tag( p, end, &salt->len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT + ret ); + + salt->p = *p; + *p += salt->len; + + if( ( ret = mbedtls_asn1_get_int( p, end, iterations ) ) != 0 ) + return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT + ret ); + + if( *p != end ) + return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +#define PKCS12_MAX_PWDLEN 128 + +static int pkcs12_pbe_derive_key_iv( mbedtls_asn1_buf *pbe_params, mbedtls_md_type_t md_type, + const unsigned char *pwd, size_t pwdlen, + unsigned char *key, size_t keylen, + unsigned char *iv, size_t ivlen ) +{ + int ret, iterations = 0; + mbedtls_asn1_buf salt; + size_t i; + unsigned char unipwd[PKCS12_MAX_PWDLEN * 2 + 2]; + + if( pwdlen > PKCS12_MAX_PWDLEN ) + return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA ); + + memset( &salt, 0, sizeof(mbedtls_asn1_buf) ); + memset( &unipwd, 0, sizeof(unipwd) ); + + if( ( ret = pkcs12_parse_pbe_params( pbe_params, &salt, + &iterations ) ) != 0 ) + return( ret ); + + for( i = 0; i < pwdlen; i++ ) + unipwd[i * 2 + 1] = pwd[i]; + + if( ( ret = mbedtls_pkcs12_derivation( key, keylen, unipwd, pwdlen * 2 + 2, + salt.p, salt.len, md_type, + MBEDTLS_PKCS12_DERIVE_KEY, iterations ) ) != 0 ) + { + return( ret ); + } + + if( iv == NULL || ivlen == 0 ) + return( 0 ); + + if( ( ret = mbedtls_pkcs12_derivation( iv, ivlen, unipwd, pwdlen * 2 + 2, + salt.p, salt.len, md_type, + MBEDTLS_PKCS12_DERIVE_IV, iterations ) ) != 0 ) + { + return( ret ); + } + return( 0 ); +} + +#undef PKCS12_MAX_PWDLEN + +int mbedtls_pkcs12_pbe_sha1_rc4_128( mbedtls_asn1_buf *pbe_params, int mode, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *data, size_t len, + unsigned char *output ) +{ +#if !defined(MBEDTLS_ARC4_C) + ((void) pbe_params); + ((void) mode); + ((void) pwd); + ((void) pwdlen); + ((void) data); + ((void) len); + ((void) output); + return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE ); +#else + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char key[16]; + mbedtls_arc4_context ctx; + ((void) mode); + + mbedtls_arc4_init( &ctx ); + + if( ( ret = pkcs12_pbe_derive_key_iv( pbe_params, MBEDTLS_MD_SHA1, + pwd, pwdlen, + key, 16, NULL, 0 ) ) != 0 ) + { + return( ret ); + } + + mbedtls_arc4_setup( &ctx, key, 16 ); + if( ( ret = mbedtls_arc4_crypt( &ctx, len, data, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_platform_zeroize( key, sizeof( key ) ); + mbedtls_arc4_free( &ctx ); + + return( ret ); +#endif /* MBEDTLS_ARC4_C */ +} + +int mbedtls_pkcs12_pbe( mbedtls_asn1_buf *pbe_params, int mode, + mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *data, size_t len, + unsigned char *output ) +{ + int ret, keylen = 0; + unsigned char key[32]; + unsigned char iv[16]; + const mbedtls_cipher_info_t *cipher_info; + mbedtls_cipher_context_t cipher_ctx; + size_t olen = 0; + + cipher_info = mbedtls_cipher_info_from_type( cipher_type ); + if( cipher_info == NULL ) + return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE ); + + keylen = cipher_info->key_bitlen / 8; + + if( ( ret = pkcs12_pbe_derive_key_iv( pbe_params, md_type, pwd, pwdlen, + key, keylen, + iv, cipher_info->iv_size ) ) != 0 ) + { + return( ret ); + } + + mbedtls_cipher_init( &cipher_ctx ); + + if( ( ret = mbedtls_cipher_setup( &cipher_ctx, cipher_info ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_cipher_setkey( &cipher_ctx, key, 8 * keylen, (mbedtls_operation_t) mode ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_cipher_set_iv( &cipher_ctx, iv, cipher_info->iv_size ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_cipher_reset( &cipher_ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_cipher_update( &cipher_ctx, data, len, + output, &olen ) ) != 0 ) + { + goto exit; + } + + if( ( ret = mbedtls_cipher_finish( &cipher_ctx, output + olen, &olen ) ) != 0 ) + ret = MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH; + +exit: + mbedtls_platform_zeroize( key, sizeof( key ) ); + mbedtls_platform_zeroize( iv, sizeof( iv ) ); + mbedtls_cipher_free( &cipher_ctx ); + + return( ret ); +} + +#endif /* MBEDTLS_ASN1_PARSE_C */ + +static void pkcs12_fill_buffer( unsigned char *data, size_t data_len, + const unsigned char *filler, size_t fill_len ) +{ + unsigned char *p = data; + size_t use_len; + + while( data_len > 0 ) + { + use_len = ( data_len > fill_len ) ? fill_len : data_len; + memcpy( p, filler, use_len ); + p += use_len; + data_len -= use_len; + } +} + +int mbedtls_pkcs12_derivation( unsigned char *data, size_t datalen, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *salt, size_t saltlen, + mbedtls_md_type_t md_type, int id, int iterations ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned int j; + + unsigned char diversifier[128]; + unsigned char salt_block[128], pwd_block[128], hash_block[128]; + unsigned char hash_output[MBEDTLS_MD_MAX_SIZE]; + unsigned char *p; + unsigned char c; + + size_t hlen, use_len, v, i; + + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + + // This version only allows max of 64 bytes of password or salt + if( datalen > 128 || pwdlen > 64 || saltlen > 64 ) + return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA ); + + md_info = mbedtls_md_info_from_type( md_type ); + if( md_info == NULL ) + return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE ); + + mbedtls_md_init( &md_ctx ); + + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) + return( ret ); + hlen = mbedtls_md_get_size( md_info ); + + if( hlen <= 32 ) + v = 64; + else + v = 128; + + memset( diversifier, (unsigned char) id, v ); + + pkcs12_fill_buffer( salt_block, v, salt, saltlen ); + pkcs12_fill_buffer( pwd_block, v, pwd, pwdlen ); + + p = data; + while( datalen > 0 ) + { + // Calculate hash( diversifier || salt_block || pwd_block ) + if( ( ret = mbedtls_md_starts( &md_ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md_update( &md_ctx, diversifier, v ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md_update( &md_ctx, salt_block, v ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md_update( &md_ctx, pwd_block, v ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md_finish( &md_ctx, hash_output ) ) != 0 ) + goto exit; + + // Perform remaining ( iterations - 1 ) recursive hash calculations + for( i = 1; i < (size_t) iterations; i++ ) + { + if( ( ret = mbedtls_md( md_info, hash_output, hlen, hash_output ) ) != 0 ) + goto exit; + } + + use_len = ( datalen > hlen ) ? hlen : datalen; + memcpy( p, hash_output, use_len ); + datalen -= use_len; + p += use_len; + + if( datalen == 0 ) + break; + + // Concatenating copies of hash_output into hash_block (B) + pkcs12_fill_buffer( hash_block, v, hash_output, hlen ); + + // B += 1 + for( i = v; i > 0; i-- ) + if( ++hash_block[i - 1] != 0 ) + break; + + // salt_block += B + c = 0; + for( i = v; i > 0; i-- ) + { + j = salt_block[i - 1] + hash_block[i - 1] + c; + c = (unsigned char) (j >> 8); + salt_block[i - 1] = j & 0xFF; + } + + // pwd_block += B + c = 0; + for( i = v; i > 0; i-- ) + { + j = pwd_block[i - 1] + hash_block[i - 1] + c; + c = (unsigned char) (j >> 8); + pwd_block[i - 1] = j & 0xFF; + } + } + + ret = 0; + +exit: + mbedtls_platform_zeroize( salt_block, sizeof( salt_block ) ); + mbedtls_platform_zeroize( pwd_block, sizeof( pwd_block ) ); + mbedtls_platform_zeroize( hash_block, sizeof( hash_block ) ); + mbedtls_platform_zeroize( hash_output, sizeof( hash_output ) ); + + mbedtls_md_free( &md_ctx ); + + return( ret ); +} + +#endif /* MBEDTLS_PKCS12_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/pkcs5.c b/Android/Level4/app/src/main/c/mbedtls/library/pkcs5.c new file mode 100644 index 0000000..f89cc64 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/pkcs5.c @@ -0,0 +1,414 @@ +/** + * \file pkcs5.c + * + * \brief PKCS#5 functions + * + * \author Mathias Olsson + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ +/* + * PKCS#5 includes PBKDF2 and more + * + * http://tools.ietf.org/html/rfc2898 (Specification) + * http://tools.ietf.org/html/rfc6070 (Test vectors) + */ + +#include "common.h" + +#if defined(MBEDTLS_PKCS5_C) + +#include "mbedtls/pkcs5.h" +#include "mbedtls/error.h" + +#if defined(MBEDTLS_ASN1_PARSE_C) +#include "mbedtls/asn1.h" +#include "mbedtls/cipher.h" +#include "mbedtls/oid.h" +#endif /* MBEDTLS_ASN1_PARSE_C */ + +#include + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif + +#if defined(MBEDTLS_ASN1_PARSE_C) +static int pkcs5_parse_pbkdf2_params( const mbedtls_asn1_buf *params, + mbedtls_asn1_buf *salt, int *iterations, + int *keylen, mbedtls_md_type_t *md_type ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_asn1_buf prf_alg_oid; + unsigned char *p = params->p; + const unsigned char *end = params->p + params->len; + + if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + /* + * PBKDF2-params ::= SEQUENCE { + * salt OCTET STRING, + * iterationCount INTEGER, + * keyLength INTEGER OPTIONAL + * prf AlgorithmIdentifier DEFAULT algid-hmacWithSHA1 + * } + * + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &salt->len, + MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); + + salt->p = p; + p += salt->len; + + if( ( ret = mbedtls_asn1_get_int( &p, end, iterations ) ) != 0 ) + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); + + if( p == end ) + return( 0 ); + + if( ( ret = mbedtls_asn1_get_int( &p, end, keylen ) ) != 0 ) + { + if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); + } + + if( p == end ) + return( 0 ); + + if( ( ret = mbedtls_asn1_get_alg_null( &p, end, &prf_alg_oid ) ) != 0 ) + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); + + if( mbedtls_oid_get_md_hmac( &prf_alg_oid, md_type ) != 0 ) + return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); + + if( p != end ) + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +int mbedtls_pkcs5_pbes2( const mbedtls_asn1_buf *pbe_params, int mode, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *data, size_t datalen, + unsigned char *output ) +{ + int ret, iterations = 0, keylen = 0; + unsigned char *p, *end; + mbedtls_asn1_buf kdf_alg_oid, enc_scheme_oid, kdf_alg_params, enc_scheme_params; + mbedtls_asn1_buf salt; + mbedtls_md_type_t md_type = MBEDTLS_MD_SHA1; + unsigned char key[32], iv[32]; + size_t olen = 0; + const mbedtls_md_info_t *md_info; + const mbedtls_cipher_info_t *cipher_info; + mbedtls_md_context_t md_ctx; + mbedtls_cipher_type_t cipher_alg; + mbedtls_cipher_context_t cipher_ctx; + + p = pbe_params->p; + end = p + pbe_params->len; + + /* + * PBES2-params ::= SEQUENCE { + * keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}}, + * encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} + * } + */ + if( pbe_params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + if( ( ret = mbedtls_asn1_get_alg( &p, end, &kdf_alg_oid, + &kdf_alg_params ) ) != 0 ) + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); + + // Only PBKDF2 supported at the moment + // + if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS5_PBKDF2, &kdf_alg_oid ) != 0 ) + return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); + + if( ( ret = pkcs5_parse_pbkdf2_params( &kdf_alg_params, + &salt, &iterations, &keylen, + &md_type ) ) != 0 ) + { + return( ret ); + } + + md_info = mbedtls_md_info_from_type( md_type ); + if( md_info == NULL ) + return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); + + if( ( ret = mbedtls_asn1_get_alg( &p, end, &enc_scheme_oid, + &enc_scheme_params ) ) != 0 ) + { + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); + } + + if( mbedtls_oid_get_cipher_alg( &enc_scheme_oid, &cipher_alg ) != 0 ) + return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); + + cipher_info = mbedtls_cipher_info_from_type( cipher_alg ); + if( cipher_info == NULL ) + return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); + + /* + * The value of keylen from pkcs5_parse_pbkdf2_params() is ignored + * since it is optional and we don't know if it was set or not + */ + keylen = cipher_info->key_bitlen / 8; + + if( enc_scheme_params.tag != MBEDTLS_ASN1_OCTET_STRING || + enc_scheme_params.len != cipher_info->iv_size ) + { + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT ); + } + + mbedtls_md_init( &md_ctx ); + mbedtls_cipher_init( &cipher_ctx ); + + memcpy( iv, enc_scheme_params.p, enc_scheme_params.len ); + + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_pkcs5_pbkdf2_hmac( &md_ctx, pwd, pwdlen, salt.p, salt.len, + iterations, keylen, key ) ) != 0 ) + { + goto exit; + } + + if( ( ret = mbedtls_cipher_setup( &cipher_ctx, cipher_info ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_cipher_setkey( &cipher_ctx, key, 8 * keylen, + (mbedtls_operation_t) mode ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_cipher_crypt( &cipher_ctx, iv, enc_scheme_params.len, + data, datalen, output, &olen ) ) != 0 ) + ret = MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH; + +exit: + mbedtls_md_free( &md_ctx ); + mbedtls_cipher_free( &cipher_ctx ); + + return( ret ); +} +#endif /* MBEDTLS_ASN1_PARSE_C */ + +int mbedtls_pkcs5_pbkdf2_hmac( mbedtls_md_context_t *ctx, + const unsigned char *password, + size_t plen, const unsigned char *salt, size_t slen, + unsigned int iteration_count, + uint32_t key_length, unsigned char *output ) +{ + int ret, j; + unsigned int i; + unsigned char md1[MBEDTLS_MD_MAX_SIZE]; + unsigned char work[MBEDTLS_MD_MAX_SIZE]; + unsigned char md_size = mbedtls_md_get_size( ctx->md_info ); + size_t use_len; + unsigned char *out_p = output; + unsigned char counter[4]; + + memset( counter, 0, 4 ); + counter[3] = 1; + +#if UINT_MAX > 0xFFFFFFFF + if( iteration_count > 0xFFFFFFFF ) + return( MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA ); +#endif + + if( ( ret = mbedtls_md_hmac_starts( ctx, password, plen ) ) != 0 ) + return( ret ); + while( key_length ) + { + // U1 ends up in work + // + if( ( ret = mbedtls_md_hmac_update( ctx, salt, slen ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_md_hmac_update( ctx, counter, 4 ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_md_hmac_finish( ctx, work ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_md_hmac_reset( ctx ) ) != 0 ) + return( ret ); + + memcpy( md1, work, md_size ); + + for( i = 1; i < iteration_count; i++ ) + { + // U2 ends up in md1 + // + if( ( ret = mbedtls_md_hmac_update( ctx, md1, md_size ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_md_hmac_finish( ctx, md1 ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_md_hmac_reset( ctx ) ) != 0 ) + return( ret ); + + // U1 xor U2 + // + for( j = 0; j < md_size; j++ ) + work[j] ^= md1[j]; + } + + use_len = ( key_length < md_size ) ? key_length : md_size; + memcpy( out_p, work, use_len ); + + key_length -= (uint32_t) use_len; + out_p += use_len; + + for( i = 4; i > 0; i-- ) + if( ++counter[i - 1] != 0 ) + break; + } + + return( 0 ); +} + +#if defined(MBEDTLS_SELF_TEST) + +#if !defined(MBEDTLS_SHA1_C) +int mbedtls_pkcs5_self_test( int verbose ) +{ + if( verbose != 0 ) + mbedtls_printf( " PBKDF2 (SHA1): skipped\n\n" ); + + return( 0 ); +} +#else + +#define MAX_TESTS 6 + +static const size_t plen_test_data[MAX_TESTS] = + { 8, 8, 8, 24, 9 }; + +static const unsigned char password_test_data[MAX_TESTS][32] = +{ + "password", + "password", + "password", + "passwordPASSWORDpassword", + "pass\0word", +}; + +static const size_t slen_test_data[MAX_TESTS] = + { 4, 4, 4, 36, 5 }; + +static const unsigned char salt_test_data[MAX_TESTS][40] = +{ + "salt", + "salt", + "salt", + "saltSALTsaltSALTsaltSALTsaltSALTsalt", + "sa\0lt", +}; + +static const uint32_t it_cnt_test_data[MAX_TESTS] = + { 1, 2, 4096, 4096, 4096 }; + +static const uint32_t key_len_test_data[MAX_TESTS] = + { 20, 20, 20, 25, 16 }; + +static const unsigned char result_key_test_data[MAX_TESTS][32] = +{ + { 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71, + 0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06, + 0x2f, 0xe0, 0x37, 0xa6 }, + { 0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c, + 0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0, + 0xd8, 0xde, 0x89, 0x57 }, + { 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a, + 0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0, + 0x65, 0xa4, 0x29, 0xc1 }, + { 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 }, + { 0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d, + 0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3 }, +}; + +int mbedtls_pkcs5_self_test( int verbose ) +{ + mbedtls_md_context_t sha1_ctx; + const mbedtls_md_info_t *info_sha1; + int ret, i; + unsigned char key[64]; + + mbedtls_md_init( &sha1_ctx ); + + info_sha1 = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ); + if( info_sha1 == NULL ) + { + ret = 1; + goto exit; + } + + if( ( ret = mbedtls_md_setup( &sha1_ctx, info_sha1, 1 ) ) != 0 ) + { + ret = 1; + goto exit; + } + + for( i = 0; i < MAX_TESTS; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " PBKDF2 (SHA1) #%d: ", i ); + + ret = mbedtls_pkcs5_pbkdf2_hmac( &sha1_ctx, password_test_data[i], + plen_test_data[i], salt_test_data[i], + slen_test_data[i], it_cnt_test_data[i], + key_len_test_data[i], key ); + if( ret != 0 || + memcmp( result_key_test_data[i], key, key_len_test_data[i] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +exit: + mbedtls_md_free( &sha1_ctx ); + + return( ret ); +} +#endif /* MBEDTLS_SHA1_C */ + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_PKCS5_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/pkparse.c b/Android/Level4/app/src/main/c/mbedtls/library/pkparse.c new file mode 100644 index 0000000..0590f2b --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/pkparse.c @@ -0,0 +1,1533 @@ +/* + * Public Key layer for parsing key files and structures + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 "common.h" + +#if defined(MBEDTLS_PK_PARSE_C) + +#include "mbedtls/pk.h" +#include "mbedtls/asn1.h" +#include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_RSA_C) +#include "mbedtls/rsa.h" +#endif +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/ecp.h" +#endif +#if defined(MBEDTLS_ECDSA_C) +#include "mbedtls/ecdsa.h" +#endif +#if defined(MBEDTLS_PEM_PARSE_C) +#include "mbedtls/pem.h" +#endif +#if defined(MBEDTLS_PKCS5_C) +#include "mbedtls/pkcs5.h" +#endif +#if defined(MBEDTLS_PKCS12_C) +#include "mbedtls/pkcs12.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +/* Parameter validation macros based on platform_util.h */ +#define PK_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA ) +#define PK_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if defined(MBEDTLS_FS_IO) +/* + * Load all data from a file into a given buffer. + * + * The file is expected to contain either PEM or DER encoded data. + * A terminating null byte is always appended. It is included in the announced + * length only if the data looks like it is PEM encoded. + */ +int mbedtls_pk_load_file( const char *path, unsigned char **buf, size_t *n ) +{ + FILE *f; + long size; + + PK_VALIDATE_RET( path != NULL ); + PK_VALIDATE_RET( buf != NULL ); + PK_VALIDATE_RET( n != NULL ); + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( MBEDTLS_ERR_PK_FILE_IO_ERROR ); + + fseek( f, 0, SEEK_END ); + if( ( size = ftell( f ) ) == -1 ) + { + fclose( f ); + return( MBEDTLS_ERR_PK_FILE_IO_ERROR ); + } + fseek( f, 0, SEEK_SET ); + + *n = (size_t) size; + + if( *n + 1 == 0 || + ( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL ) + { + fclose( f ); + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + } + + if( fread( *buf, 1, *n, f ) != *n ) + { + fclose( f ); + + mbedtls_platform_zeroize( *buf, *n ); + mbedtls_free( *buf ); + + return( MBEDTLS_ERR_PK_FILE_IO_ERROR ); + } + + fclose( f ); + + (*buf)[*n] = '\0'; + + if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL ) + ++*n; + + return( 0 ); +} + +/* + * Load and parse a private key + */ +int mbedtls_pk_parse_keyfile( mbedtls_pk_context *ctx, + const char *path, const char *pwd ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n; + unsigned char *buf; + + PK_VALIDATE_RET( ctx != NULL ); + PK_VALIDATE_RET( path != NULL ); + + if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + if( pwd == NULL ) + ret = mbedtls_pk_parse_key( ctx, buf, n, NULL, 0 ); + else + ret = mbedtls_pk_parse_key( ctx, buf, n, + (const unsigned char *) pwd, strlen( pwd ) ); + + mbedtls_platform_zeroize( buf, n ); + mbedtls_free( buf ); + + return( ret ); +} + +/* + * Load and parse a public key + */ +int mbedtls_pk_parse_public_keyfile( mbedtls_pk_context *ctx, const char *path ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n; + unsigned char *buf; + + PK_VALIDATE_RET( ctx != NULL ); + PK_VALIDATE_RET( path != NULL ); + + if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = mbedtls_pk_parse_public_key( ctx, buf, n ); + + mbedtls_platform_zeroize( buf, n ); + mbedtls_free( buf ); + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + +#if defined(MBEDTLS_ECP_C) +/* Minimally parse an ECParameters buffer to and mbedtls_asn1_buf + * + * ECParameters ::= CHOICE { + * namedCurve OBJECT IDENTIFIER + * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... } + * -- implicitCurve NULL + * } + */ +static int pk_get_ecparams( unsigned char **p, const unsigned char *end, + mbedtls_asn1_buf *params ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if ( end - *p < 1 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + /* Tag may be either OID or SEQUENCE */ + params->tag = **p; + if( params->tag != MBEDTLS_ASN1_OID +#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) + && params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) +#endif + ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + } + + if( ( ret = mbedtls_asn1_get_tag( p, end, ¶ms->len, params->tag ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + params->p = *p; + *p += params->len; + + if( *p != end ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) +/* + * Parse a SpecifiedECDomain (SEC 1 C.2) and (mostly) fill the group with it. + * WARNING: the resulting group should only be used with + * pk_group_id_from_specified(), since its base point may not be set correctly + * if it was encoded compressed. + * + * SpecifiedECDomain ::= SEQUENCE { + * version SpecifiedECDomainVersion(ecdpVer1 | ecdpVer2 | ecdpVer3, ...), + * fieldID FieldID {{FieldTypes}}, + * curve Curve, + * base ECPoint, + * order INTEGER, + * cofactor INTEGER OPTIONAL, + * hash HashAlgorithm OPTIONAL, + * ... + * } + * + * We only support prime-field as field type, and ignore hash and cofactor. + */ +static int pk_group_from_specified( const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = params->p; + const unsigned char * const end = params->p + params->len; + const unsigned char *end_field, *end_curve; + size_t len; + int ver; + + /* SpecifiedECDomainVersion ::= INTEGER { 1, 2, 3 } */ + if( ( ret = mbedtls_asn1_get_int( &p, end, &ver ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( ver < 1 || ver > 3 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + + /* + * FieldID { FIELD-ID:IOSet } ::= SEQUENCE { -- Finite field + * fieldType FIELD-ID.&id({IOSet}), + * parameters FIELD-ID.&Type({IOSet}{@fieldType}) + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( ret ); + + end_field = p + len; + + /* + * FIELD-ID ::= TYPE-IDENTIFIER + * FieldTypes FIELD-ID ::= { + * { Prime-p IDENTIFIED BY prime-field } | + * { Characteristic-two IDENTIFIED BY characteristic-two-field } + * } + * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end_field, &len, MBEDTLS_ASN1_OID ) ) != 0 ) + return( ret ); + + if( len != MBEDTLS_OID_SIZE( MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD ) || + memcmp( p, MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD, len ) != 0 ) + { + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + } + + p += len; + + /* Prime-p ::= INTEGER -- Field of size p. */ + if( ( ret = mbedtls_asn1_get_mpi( &p, end_field, &grp->P ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + grp->pbits = mbedtls_mpi_bitlen( &grp->P ); + + if( p != end_field ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + /* + * Curve ::= SEQUENCE { + * a FieldElement, + * b FieldElement, + * seed BIT STRING OPTIONAL + * -- Shall be present if used in SpecifiedECDomain + * -- with version equal to ecdpVer2 or ecdpVer3 + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( ret ); + + end_curve = p + len; + + /* + * FieldElement ::= OCTET STRING + * containing an integer in the case of a prime field + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 || + ( ret = mbedtls_mpi_read_binary( &grp->A, p, len ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + p += len; + + if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 || + ( ret = mbedtls_mpi_read_binary( &grp->B, p, len ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + p += len; + + /* Ignore seed BIT STRING OPTIONAL */ + if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_BIT_STRING ) ) == 0 ) + p += len; + + if( p != end_curve ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + /* + * ECPoint ::= OCTET STRING + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( ( ret = mbedtls_ecp_point_read_binary( grp, &grp->G, + ( const unsigned char *) p, len ) ) != 0 ) + { + /* + * If we can't read the point because it's compressed, cheat by + * reading only the X coordinate and the parity bit of Y. + */ + if( ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE || + ( p[0] != 0x02 && p[0] != 0x03 ) || + len != mbedtls_mpi_size( &grp->P ) + 1 || + mbedtls_mpi_read_binary( &grp->G.X, p + 1, len - 1 ) != 0 || + mbedtls_mpi_lset( &grp->G.Y, p[0] - 2 ) != 0 || + mbedtls_mpi_lset( &grp->G.Z, 1 ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + } + } + + p += len; + + /* + * order INTEGER + */ + if( ( ret = mbedtls_asn1_get_mpi( &p, end, &grp->N ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + grp->nbits = mbedtls_mpi_bitlen( &grp->N ); + + /* + * Allow optional elements by purposefully not enforcing p == end here. + */ + + return( 0 ); +} + +/* + * Find the group id associated with an (almost filled) group as generated by + * pk_group_from_specified(), or return an error if unknown. + */ +static int pk_group_id_from_group( const mbedtls_ecp_group *grp, mbedtls_ecp_group_id *grp_id ) +{ + int ret = 0; + mbedtls_ecp_group ref; + const mbedtls_ecp_group_id *id; + + mbedtls_ecp_group_init( &ref ); + + for( id = mbedtls_ecp_grp_id_list(); *id != MBEDTLS_ECP_DP_NONE; id++ ) + { + /* Load the group associated to that id */ + mbedtls_ecp_group_free( &ref ); + MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ref, *id ) ); + + /* Compare to the group we were given, starting with easy tests */ + if( grp->pbits == ref.pbits && grp->nbits == ref.nbits && + mbedtls_mpi_cmp_mpi( &grp->P, &ref.P ) == 0 && + mbedtls_mpi_cmp_mpi( &grp->A, &ref.A ) == 0 && + mbedtls_mpi_cmp_mpi( &grp->B, &ref.B ) == 0 && + mbedtls_mpi_cmp_mpi( &grp->N, &ref.N ) == 0 && + mbedtls_mpi_cmp_mpi( &grp->G.X, &ref.G.X ) == 0 && + mbedtls_mpi_cmp_mpi( &grp->G.Z, &ref.G.Z ) == 0 && + /* For Y we may only know the parity bit, so compare only that */ + mbedtls_mpi_get_bit( &grp->G.Y, 0 ) == mbedtls_mpi_get_bit( &ref.G.Y, 0 ) ) + { + break; + } + + } + +cleanup: + mbedtls_ecp_group_free( &ref ); + + *grp_id = *id; + + if( ret == 0 && *id == MBEDTLS_ECP_DP_NONE ) + ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; + + return( ret ); +} + +/* + * Parse a SpecifiedECDomain (SEC 1 C.2) and find the associated group ID + */ +static int pk_group_id_from_specified( const mbedtls_asn1_buf *params, + mbedtls_ecp_group_id *grp_id ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_group grp; + + mbedtls_ecp_group_init( &grp ); + + if( ( ret = pk_group_from_specified( params, &grp ) ) != 0 ) + goto cleanup; + + ret = pk_group_id_from_group( &grp, grp_id ); + +cleanup: + mbedtls_ecp_group_free( &grp ); + + return( ret ); +} +#endif /* MBEDTLS_PK_PARSE_EC_EXTENDED */ + +/* + * Use EC parameters to initialise an EC group + * + * ECParameters ::= CHOICE { + * namedCurve OBJECT IDENTIFIER + * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... } + * -- implicitCurve NULL + */ +static int pk_use_ecparams( const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_group_id grp_id; + + if( params->tag == MBEDTLS_ASN1_OID ) + { + if( mbedtls_oid_get_ec_grp( params, &grp_id ) != 0 ) + return( MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE ); + } + else + { +#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) + if( ( ret = pk_group_id_from_specified( params, &grp_id ) ) != 0 ) + return( ret ); +#else + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); +#endif + } + + /* + * grp may already be initilialized; if so, make sure IDs match + */ + if( grp->id != MBEDTLS_ECP_DP_NONE && grp->id != grp_id ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + + if( ( ret = mbedtls_ecp_group_load( grp, grp_id ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +/* + * EC public key is an EC point + * + * The caller is responsible for clearing the structure upon failure if + * desired. Take care to pass along the possible ECP_FEATURE_UNAVAILABLE + * return code of mbedtls_ecp_point_read_binary() and leave p in a usable state. + */ +static int pk_get_ecpubkey( unsigned char **p, const unsigned char *end, + mbedtls_ecp_keypair *key ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ( ret = mbedtls_ecp_point_read_binary( &key->grp, &key->Q, + (const unsigned char *) *p, end - *p ) ) == 0 ) + { + ret = mbedtls_ecp_check_pubkey( &key->grp, &key->Q ); + } + + /* + * We know mbedtls_ecp_point_read_binary consumed all bytes or failed + */ + *p = (unsigned char *) end; + + return( ret ); +} +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_RSA_C) +/* + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER -- e + * } + */ +static int pk_get_rsapubkey( unsigned char **p, + const unsigned char *end, + mbedtls_rsa_context *rsa ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret ); + + if( *p + len != end ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + /* Import N */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret ); + + if( ( ret = mbedtls_rsa_import_raw( rsa, *p, len, NULL, 0, NULL, 0, + NULL, 0, NULL, 0 ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY ); + + *p += len; + + /* Import E */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret ); + + if( ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, NULL, 0, NULL, 0, + NULL, 0, *p, len ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY ); + + *p += len; + + if( mbedtls_rsa_complete( rsa ) != 0 || + mbedtls_rsa_check_pubkey( rsa ) != 0 ) + { + return( MBEDTLS_ERR_PK_INVALID_PUBKEY ); + } + + if( *p != end ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} +#endif /* MBEDTLS_RSA_C */ + +/* Get a PK algorithm identifier + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL } + */ +static int pk_get_pk_alg( unsigned char **p, + const unsigned char *end, + mbedtls_pk_type_t *pk_alg, mbedtls_asn1_buf *params ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_asn1_buf alg_oid; + + memset( params, 0, sizeof(mbedtls_asn1_buf) ); + + if( ( ret = mbedtls_asn1_get_alg( p, end, &alg_oid, params ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_ALG + ret ); + + if( mbedtls_oid_get_pk_alg( &alg_oid, pk_alg ) != 0 ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + /* + * No parameters with RSA (only for EC) + */ + if( *pk_alg == MBEDTLS_PK_RSA && + ( ( params->tag != MBEDTLS_ASN1_NULL && params->tag != 0 ) || + params->len != 0 ) ) + { + return( MBEDTLS_ERR_PK_INVALID_ALG ); + } + + return( 0 ); +} + +/* + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING } + */ +int mbedtls_pk_parse_subpubkey( unsigned char **p, const unsigned char *end, + mbedtls_pk_context *pk ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + mbedtls_asn1_buf alg_params; + mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; + const mbedtls_pk_info_t *pk_info; + + PK_VALIDATE_RET( p != NULL ); + PK_VALIDATE_RET( *p != NULL ); + PK_VALIDATE_RET( end != NULL ); + PK_VALIDATE_RET( pk != NULL ); + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + end = *p + len; + + if( ( ret = pk_get_pk_alg( p, end, &pk_alg, &alg_params ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_asn1_get_bitstring_null( p, end, &len ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret ); + + if( *p + len != end ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + if( ( pk_info = mbedtls_pk_info_from_type( pk_alg ) ) == NULL ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ) + return( ret ); + +#if defined(MBEDTLS_RSA_C) + if( pk_alg == MBEDTLS_PK_RSA ) + { + ret = pk_get_rsapubkey( p, end, mbedtls_pk_rsa( *pk ) ); + } else +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECP_C) + if( pk_alg == MBEDTLS_PK_ECKEY_DH || pk_alg == MBEDTLS_PK_ECKEY ) + { + ret = pk_use_ecparams( &alg_params, &mbedtls_pk_ec( *pk )->grp ); + if( ret == 0 ) + ret = pk_get_ecpubkey( p, end, mbedtls_pk_ec( *pk ) ); + } else +#endif /* MBEDTLS_ECP_C */ + ret = MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; + + if( ret == 0 && *p != end ) + ret = MBEDTLS_ERR_PK_INVALID_PUBKEY + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; + + if( ret != 0 ) + mbedtls_pk_free( pk ); + + return( ret ); +} + +#if defined(MBEDTLS_RSA_C) +/* + * Wrapper around mbedtls_asn1_get_mpi() that rejects zero. + * + * The value zero is: + * - never a valid value for an RSA parameter + * - interpreted as "omitted, please reconstruct" by mbedtls_rsa_complete(). + * + * Since values can't be omitted in PKCS#1, passing a zero value to + * rsa_complete() would be incorrect, so reject zero values early. + */ +static int asn1_get_nonzero_mpi( unsigned char **p, + const unsigned char *end, + mbedtls_mpi *X ) +{ + int ret; + + ret = mbedtls_asn1_get_mpi( p, end, X ); + if( ret != 0 ) + return( ret ); + + if( mbedtls_mpi_cmp_int( X, 0 ) == 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + + return( 0 ); +} + +/* + * Parse a PKCS#1 encoded private RSA key + */ +static int pk_parse_key_pkcs1_der( mbedtls_rsa_context *rsa, + const unsigned char *key, + size_t keylen ) +{ + int ret, version; + size_t len; + unsigned char *p, *end; + + mbedtls_mpi T; + mbedtls_mpi_init( &T ); + + p = (unsigned char *) key; + end = p + keylen; + + /* + * This function parses the RSAPrivateKey (PKCS#1) + * + * RSAPrivateKey ::= SEQUENCE { + * version Version, + * modulus INTEGER, -- n + * publicExponent INTEGER, -- e + * privateExponent INTEGER, -- d + * prime1 INTEGER, -- p + * prime2 INTEGER, -- q + * exponent1 INTEGER, -- d mod (p-1) + * exponent2 INTEGER, -- d mod (q-1) + * coefficient INTEGER, -- (inverse of q) mod p + * otherPrimeInfos OtherPrimeInfos OPTIONAL + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + end = p + len; + + if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + if( version != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION ); + } + + /* Import N */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_rsa_import( rsa, &T, NULL, NULL, + NULL, NULL ) ) != 0 ) + goto cleanup; + + /* Import E */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_rsa_import( rsa, NULL, NULL, NULL, + NULL, &T ) ) != 0 ) + goto cleanup; + + /* Import D */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_rsa_import( rsa, NULL, NULL, NULL, + &T, NULL ) ) != 0 ) + goto cleanup; + + /* Import P */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_rsa_import( rsa, NULL, &T, NULL, + NULL, NULL ) ) != 0 ) + goto cleanup; + + /* Import Q */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_rsa_import( rsa, NULL, NULL, &T, + NULL, NULL ) ) != 0 ) + goto cleanup; + +#if !defined(MBEDTLS_RSA_NO_CRT) && !defined(MBEDTLS_RSA_ALT) + /* + * The RSA CRT parameters DP, DQ and QP are nominally redundant, in + * that they can be easily recomputed from D, P and Q. However by + * parsing them from the PKCS1 structure it is possible to avoid + * recalculating them which both reduces the overhead of loading + * RSA private keys into memory and also avoids side channels which + * can arise when computing those values, since all of D, P, and Q + * are secret. See https://eprint.iacr.org/2020/055 for a + * description of one such attack. + */ + + /* Import DP */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_mpi_copy( &rsa->DP, &T ) ) != 0 ) + goto cleanup; + + /* Import DQ */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_mpi_copy( &rsa->DQ, &T ) ) != 0 ) + goto cleanup; + + /* Import QP */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_mpi_copy( &rsa->QP, &T ) ) != 0 ) + goto cleanup; + +#else + /* Verify existance of the CRT params */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ) + goto cleanup; +#endif + + /* rsa_complete() doesn't complete anything with the default + * implementation but is still called: + * - for the benefit of alternative implementation that may want to + * pre-compute stuff beyond what's provided (eg Montgomery factors) + * - as is also sanity-checks the key + * + * Furthermore, we also check the public part for consistency with + * mbedtls_pk_parse_pubkey(), as it includes size minima for example. + */ + if( ( ret = mbedtls_rsa_complete( rsa ) ) != 0 || + ( ret = mbedtls_rsa_check_pubkey( rsa ) ) != 0 ) + { + goto cleanup; + } + + if( p != end ) + { + ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ; + } + +cleanup: + + mbedtls_mpi_free( &T ); + + if( ret != 0 ) + { + /* Wrap error code if it's coming from a lower level */ + if( ( ret & 0xff80 ) == 0 ) + ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret; + else + ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; + + mbedtls_rsa_free( rsa ); + } + + return( ret ); +} +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) +/* + * Parse a SEC1 encoded private EC key + */ +static int pk_parse_key_sec1_der( mbedtls_ecp_keypair *eck, + const unsigned char *key, + size_t keylen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + int version, pubkey_done; + size_t len; + mbedtls_asn1_buf params; + unsigned char *p = (unsigned char *) key; + unsigned char *end = p + keylen; + unsigned char *end2; + + /* + * RFC 5915, or SEC1 Appendix C.4 + * + * ECPrivateKey ::= SEQUENCE { + * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), + * privateKey OCTET STRING, + * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, + * publicKey [1] BIT STRING OPTIONAL + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + end = p + len; + + if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( version != 1 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION ); + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( ( ret = mbedtls_mpi_read_binary( &eck->d, p, len ) ) != 0 ) + { + mbedtls_ecp_keypair_free( eck ); + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + p += len; + + pubkey_done = 0; + if( p != end ) + { + /* + * Is 'parameters' present? + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) == 0 ) + { + if( ( ret = pk_get_ecparams( &p, p + len, ¶ms) ) != 0 || + ( ret = pk_use_ecparams( ¶ms, &eck->grp ) ) != 0 ) + { + mbedtls_ecp_keypair_free( eck ); + return( ret ); + } + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + { + mbedtls_ecp_keypair_free( eck ); + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + } + + if( p != end ) + { + /* + * Is 'publickey' present? If not, or if we can't read it (eg because it + * is compressed), create it from the private key. + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) ) == 0 ) + { + end2 = p + len; + + if( ( ret = mbedtls_asn1_get_bitstring_null( &p, end2, &len ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( p + len != end2 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + if( ( ret = pk_get_ecpubkey( &p, end2, eck ) ) == 0 ) + pubkey_done = 1; + else + { + /* + * The only acceptable failure mode of pk_get_ecpubkey() above + * is if the point format is not recognized. + */ + if( ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + } + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + { + mbedtls_ecp_keypair_free( eck ); + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + } + + if( ! pubkey_done && + ( ret = mbedtls_ecp_mul( &eck->grp, &eck->Q, &eck->d, &eck->grp.G, + NULL, NULL ) ) != 0 ) + { + mbedtls_ecp_keypair_free( eck ); + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + if( ( ret = mbedtls_ecp_check_privkey( &eck->grp, &eck->d ) ) != 0 ) + { + mbedtls_ecp_keypair_free( eck ); + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_ECP_C */ + +/* + * Parse an unencrypted PKCS#8 encoded private key + * + * Notes: + * + * - This function does not own the key buffer. It is the + * responsibility of the caller to take care of zeroizing + * and freeing it after use. + * + * - The function is responsible for freeing the provided + * PK context on failure. + * + */ +static int pk_parse_key_pkcs8_unencrypted_der( + mbedtls_pk_context *pk, + const unsigned char* key, + size_t keylen ) +{ + int ret, version; + size_t len; + mbedtls_asn1_buf params; + unsigned char *p = (unsigned char *) key; + unsigned char *end = p + keylen; + mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; + const mbedtls_pk_info_t *pk_info; + + /* + * This function parses the PrivateKeyInfo object (PKCS#8 v1.2 = RFC 5208) + * + * PrivateKeyInfo ::= SEQUENCE { + * version Version, + * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, + * privateKey PrivateKey, + * attributes [0] IMPLICIT Attributes OPTIONAL } + * + * Version ::= INTEGER + * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier + * PrivateKey ::= OCTET STRING + * + * The PrivateKey OCTET STRING is a SEC1 ECPrivateKey + */ + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + end = p + len; + + if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( version != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION + ret ); + + if( ( ret = pk_get_pk_alg( &p, end, &pk_alg, ¶ms ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( len < 1 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + if( ( pk_info = mbedtls_pk_info_from_type( pk_alg ) ) == NULL ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ) + return( ret ); + +#if defined(MBEDTLS_RSA_C) + if( pk_alg == MBEDTLS_PK_RSA ) + { + if( ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), p, len ) ) != 0 ) + { + mbedtls_pk_free( pk ); + return( ret ); + } + } else +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECP_C) + if( pk_alg == MBEDTLS_PK_ECKEY || pk_alg == MBEDTLS_PK_ECKEY_DH ) + { + if( ( ret = pk_use_ecparams( ¶ms, &mbedtls_pk_ec( *pk )->grp ) ) != 0 || + ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), p, len ) ) != 0 ) + { + mbedtls_pk_free( pk ); + return( ret ); + } + } else +#endif /* MBEDTLS_ECP_C */ + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + return( 0 ); +} + +/* + * Parse an encrypted PKCS#8 encoded private key + * + * To save space, the decryption happens in-place on the given key buffer. + * Also, while this function may modify the keybuffer, it doesn't own it, + * and instead it is the responsibility of the caller to zeroize and properly + * free it after use. + * + */ +#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) +static int pk_parse_key_pkcs8_encrypted_der( + mbedtls_pk_context *pk, + unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen ) +{ + int ret, decrypted = 0; + size_t len; + unsigned char *buf; + unsigned char *p, *end; + mbedtls_asn1_buf pbe_alg_oid, pbe_params; +#if defined(MBEDTLS_PKCS12_C) + mbedtls_cipher_type_t cipher_alg; + mbedtls_md_type_t md_alg; +#endif + + p = key; + end = p + keylen; + + if( pwdlen == 0 ) + return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ); + + /* + * This function parses the EncryptedPrivateKeyInfo object (PKCS#8) + * + * EncryptedPrivateKeyInfo ::= SEQUENCE { + * encryptionAlgorithm EncryptionAlgorithmIdentifier, + * encryptedData EncryptedData + * } + * + * EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier + * + * EncryptedData ::= OCTET STRING + * + * The EncryptedData OCTET STRING is a PKCS#8 PrivateKeyInfo + * + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + end = p + len; + + if( ( ret = mbedtls_asn1_get_alg( &p, end, &pbe_alg_oid, &pbe_params ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + buf = p; + + /* + * Decrypt EncryptedData with appropriate PBE + */ +#if defined(MBEDTLS_PKCS12_C) + if( mbedtls_oid_get_pkcs12_pbe_alg( &pbe_alg_oid, &md_alg, &cipher_alg ) == 0 ) + { + if( ( ret = mbedtls_pkcs12_pbe( &pbe_params, MBEDTLS_PKCS12_PBE_DECRYPT, + cipher_alg, md_alg, + pwd, pwdlen, p, len, buf ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH ) + return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); + + return( ret ); + } + + decrypted = 1; + } + else if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_128, &pbe_alg_oid ) == 0 ) + { + if( ( ret = mbedtls_pkcs12_pbe_sha1_rc4_128( &pbe_params, + MBEDTLS_PKCS12_PBE_DECRYPT, + pwd, pwdlen, + p, len, buf ) ) != 0 ) + { + return( ret ); + } + + // Best guess for password mismatch when using RC4. If first tag is + // not MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE + // + if( *buf != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) + return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); + + decrypted = 1; + } + else +#endif /* MBEDTLS_PKCS12_C */ +#if defined(MBEDTLS_PKCS5_C) + if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS5_PBES2, &pbe_alg_oid ) == 0 ) + { + if( ( ret = mbedtls_pkcs5_pbes2( &pbe_params, MBEDTLS_PKCS5_DECRYPT, pwd, pwdlen, + p, len, buf ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH ) + return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); + + return( ret ); + } + + decrypted = 1; + } + else +#endif /* MBEDTLS_PKCS5_C */ + { + ((void) pwd); + } + + if( decrypted == 0 ) + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + + return( pk_parse_key_pkcs8_unencrypted_der( pk, buf, len ) ); +} +#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ + +/* + * Parse a private key + */ +int mbedtls_pk_parse_key( mbedtls_pk_context *pk, + const unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const mbedtls_pk_info_t *pk_info; +#if defined(MBEDTLS_PEM_PARSE_C) + size_t len; + mbedtls_pem_context pem; +#endif + + PK_VALIDATE_RET( pk != NULL ); + if( keylen == 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + PK_VALIDATE_RET( key != NULL ); + +#if defined(MBEDTLS_PEM_PARSE_C) + mbedtls_pem_init( &pem ); + +#if defined(MBEDTLS_RSA_C) + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN RSA PRIVATE KEY-----", + "-----END RSA PRIVATE KEY-----", + key, pwd, pwdlen, &len ); + + if( ret == 0 ) + { + pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ); + if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || + ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), + pem.buf, pem.buflen ) ) != 0 ) + { + mbedtls_pk_free( pk ); + } + + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH ) + return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); + else if( ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ) + return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ); + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN EC PRIVATE KEY-----", + "-----END EC PRIVATE KEY-----", + key, pwd, pwdlen, &len ); + if( ret == 0 ) + { + pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ); + + if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || + ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), + pem.buf, pem.buflen ) ) != 0 ) + { + mbedtls_pk_free( pk ); + } + + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH ) + return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); + else if( ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ) + return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ); + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); +#endif /* MBEDTLS_ECP_C */ + + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN PRIVATE KEY-----", + "-----END PRIVATE KEY-----", + key, NULL, 0, &len ); + if( ret == 0 ) + { + if( ( ret = pk_parse_key_pkcs8_unencrypted_der( pk, + pem.buf, pem.buflen ) ) != 0 ) + { + mbedtls_pk_free( pk ); + } + + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); + +#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN ENCRYPTED PRIVATE KEY-----", + "-----END ENCRYPTED PRIVATE KEY-----", + key, NULL, 0, &len ); + if( ret == 0 ) + { + if( ( ret = pk_parse_key_pkcs8_encrypted_der( pk, + pem.buf, pem.buflen, + pwd, pwdlen ) ) != 0 ) + { + mbedtls_pk_free( pk ); + } + + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); +#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ +#else + ((void) pwd); + ((void) pwdlen); +#endif /* MBEDTLS_PEM_PARSE_C */ + + /* + * At this point we only know it's not a PEM formatted key. Could be any + * of the known DER encoded private key formats + * + * We try the different DER format parsers to see if one passes without + * error + */ +#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) + { + unsigned char *key_copy; + + if( ( key_copy = mbedtls_calloc( 1, keylen ) ) == NULL ) + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + + memcpy( key_copy, key, keylen ); + + ret = pk_parse_key_pkcs8_encrypted_der( pk, key_copy, keylen, + pwd, pwdlen ); + + mbedtls_platform_zeroize( key_copy, keylen ); + mbedtls_free( key_copy ); + } + + if( ret == 0 ) + return( 0 ); + + mbedtls_pk_free( pk ); + mbedtls_pk_init( pk ); + + if( ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH ) + { + return( ret ); + } +#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ + + if( ( ret = pk_parse_key_pkcs8_unencrypted_der( pk, key, keylen ) ) == 0 ) + return( 0 ); + + mbedtls_pk_free( pk ); + mbedtls_pk_init( pk ); + +#if defined(MBEDTLS_RSA_C) + + pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ); + if( mbedtls_pk_setup( pk, pk_info ) == 0 && + pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), key, keylen ) == 0 ) + { + return( 0 ); + } + + mbedtls_pk_free( pk ); + mbedtls_pk_init( pk ); +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) + pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ); + if( mbedtls_pk_setup( pk, pk_info ) == 0 && + pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), + key, keylen ) == 0 ) + { + return( 0 ); + } + mbedtls_pk_free( pk ); +#endif /* MBEDTLS_ECP_C */ + + /* If MBEDTLS_RSA_C is defined but MBEDTLS_ECP_C isn't, + * it is ok to leave the PK context initialized but not + * freed: It is the caller's responsibility to call pk_init() + * before calling this function, and to call pk_free() + * when it fails. If MBEDTLS_ECP_C is defined but MBEDTLS_RSA_C + * isn't, this leads to mbedtls_pk_free() being called + * twice, once here and once by the caller, but this is + * also ok and in line with the mbedtls_pk_free() calls + * on failed PEM parsing attempts. */ + + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); +} + +/* + * Parse a public key + */ +int mbedtls_pk_parse_public_key( mbedtls_pk_context *ctx, + const unsigned char *key, size_t keylen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p; +#if defined(MBEDTLS_RSA_C) + const mbedtls_pk_info_t *pk_info; +#endif +#if defined(MBEDTLS_PEM_PARSE_C) + size_t len; + mbedtls_pem_context pem; +#endif + + PK_VALIDATE_RET( ctx != NULL ); + if( keylen == 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + PK_VALIDATE_RET( key != NULL || keylen == 0 ); + +#if defined(MBEDTLS_PEM_PARSE_C) + mbedtls_pem_init( &pem ); +#if defined(MBEDTLS_RSA_C) + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN RSA PUBLIC KEY-----", + "-----END RSA PUBLIC KEY-----", + key, NULL, 0, &len ); + + if( ret == 0 ) + { + p = pem.buf; + if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = mbedtls_pk_setup( ctx, pk_info ) ) != 0 ) + return( ret ); + + if ( ( ret = pk_get_rsapubkey( &p, p + pem.buflen, mbedtls_pk_rsa( *ctx ) ) ) != 0 ) + mbedtls_pk_free( ctx ); + + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + mbedtls_pem_free( &pem ); + return( ret ); + } +#endif /* MBEDTLS_RSA_C */ + + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN PUBLIC KEY-----", + "-----END PUBLIC KEY-----", + key, NULL, 0, &len ); + + if( ret == 0 ) + { + /* + * Was PEM encoded + */ + p = pem.buf; + + ret = mbedtls_pk_parse_subpubkey( &p, p + pem.buflen, ctx ); + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + mbedtls_pem_free( &pem ); + return( ret ); + } + mbedtls_pem_free( &pem ); +#endif /* MBEDTLS_PEM_PARSE_C */ + +#if defined(MBEDTLS_RSA_C) + if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = mbedtls_pk_setup( ctx, pk_info ) ) != 0 ) + return( ret ); + + p = (unsigned char *)key; + ret = pk_get_rsapubkey( &p, p + keylen, mbedtls_pk_rsa( *ctx ) ); + if( ret == 0 ) + { + return( ret ); + } + mbedtls_pk_free( ctx ); + if( ret != ( MBEDTLS_ERR_PK_INVALID_PUBKEY + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ) + { + return( ret ); + } +#endif /* MBEDTLS_RSA_C */ + p = (unsigned char *) key; + + ret = mbedtls_pk_parse_subpubkey( &p, p + keylen, ctx ); + + return( ret ); +} + +#endif /* MBEDTLS_PK_PARSE_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/pkwrite.c b/Android/Level4/app/src/main/c/mbedtls/library/pkwrite.c new file mode 100644 index 0000000..b317ccf --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/pkwrite.c @@ -0,0 +1,623 @@ +/* + * Public Key layer for writing key files and structures + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 "common.h" + +#if defined(MBEDTLS_PK_WRITE_C) + +#include "mbedtls/pk.h" +#include "mbedtls/asn1write.h" +#include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_RSA_C) +#include "mbedtls/rsa.h" +#endif +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/bignum.h" +#include "mbedtls/ecp.h" +#include "mbedtls/platform_util.h" +#endif +#if defined(MBEDTLS_ECDSA_C) +#include "mbedtls/ecdsa.h" +#endif +#if defined(MBEDTLS_PEM_WRITE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#include "mbedtls/psa_util.h" +#endif +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +/* Parameter validation macros based on platform_util.h */ +#define PK_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA ) +#define PK_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if defined(MBEDTLS_RSA_C) +/* + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER -- e + * } + */ +static int pk_write_rsa_pubkey( unsigned char **p, unsigned char *start, + mbedtls_rsa_context *rsa ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + mbedtls_mpi T; + + mbedtls_mpi_init( &T ); + + /* Export E */ + if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL, NULL, NULL, &T ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( p, start, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export N */ + if ( ( ret = mbedtls_rsa_export( rsa, &T, NULL, NULL, NULL, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( p, start, &T ) ) < 0 ) + goto end_of_export; + len += ret; + +end_of_export: + + mbedtls_mpi_free( &T ); + if( ret < 0 ) + return( ret ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + return( (int) len ); +} +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) +/* + * EC public key is an EC point + */ +static int pk_write_ec_pubkey( unsigned char **p, unsigned char *start, + mbedtls_ecp_keypair *ec ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + unsigned char buf[MBEDTLS_ECP_MAX_PT_LEN]; + + if( ( ret = mbedtls_ecp_point_write_binary( &ec->grp, &ec->Q, + MBEDTLS_ECP_PF_UNCOMPRESSED, + &len, buf, sizeof( buf ) ) ) != 0 ) + { + return( ret ); + } + + if( *p < start || (size_t)( *p - start ) < len ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *p -= len; + memcpy( *p, buf, len ); + + return( (int) len ); +} + +/* + * ECParameters ::= CHOICE { + * namedCurve OBJECT IDENTIFIER + * } + */ +static int pk_write_ec_param( unsigned char **p, unsigned char *start, + mbedtls_ecp_keypair *ec ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + const char *oid; + size_t oid_len; + + if( ( ret = mbedtls_oid_get_oid_by_ec_grp( ec->grp.id, &oid, &oid_len ) ) != 0 ) + return( ret ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) ); + + return( (int) len ); +} + +/* + * privateKey OCTET STRING -- always of length ceil(log2(n)/8) + */ +static int pk_write_ec_private( unsigned char **p, unsigned char *start, + mbedtls_ecp_keypair *ec ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t byte_length = ( ec->grp.pbits + 7 ) / 8; + unsigned char tmp[MBEDTLS_ECP_MAX_BYTES]; + + ret = mbedtls_ecp_write_key( ec, tmp, byte_length ); + if( ret != 0 ) + goto exit; + ret = mbedtls_asn1_write_octet_string( p, start, tmp, byte_length ); + +exit: + mbedtls_platform_zeroize( tmp, byte_length ); + return( ret ); +} +#endif /* MBEDTLS_ECP_C */ + +int mbedtls_pk_write_pubkey( unsigned char **p, unsigned char *start, + const mbedtls_pk_context *key ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + PK_VALIDATE_RET( p != NULL ); + PK_VALIDATE_RET( *p != NULL ); + PK_VALIDATE_RET( start != NULL ); + PK_VALIDATE_RET( key != NULL ); + +#if defined(MBEDTLS_RSA_C) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA ) + MBEDTLS_ASN1_CHK_ADD( len, pk_write_rsa_pubkey( p, start, mbedtls_pk_rsa( *key ) ) ); + else +#endif +#if defined(MBEDTLS_ECP_C) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY ) + MBEDTLS_ASN1_CHK_ADD( len, pk_write_ec_pubkey( p, start, mbedtls_pk_ec( *key ) ) ); + else +#endif +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_OPAQUE ) + { + size_t buffer_size; + psa_key_handle_t* key_slot = (psa_key_handle_t*) key->pk_ctx; + + if ( *p < start ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + buffer_size = (size_t)( *p - start ); + if ( psa_export_public_key( *key_slot, start, buffer_size, &len ) + != PSA_SUCCESS ) + { + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + } + else + { + *p -= len; + memmove( *p, start, len ); + } + } + else +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + + return( (int) len ); +} + +int mbedtls_pk_write_pubkey_der( mbedtls_pk_context *key, unsigned char *buf, size_t size ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *c; + size_t len = 0, par_len = 0, oid_len; + mbedtls_pk_type_t pk_type; + const char *oid; + + PK_VALIDATE_RET( key != NULL ); + if( size == 0 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + PK_VALIDATE_RET( buf != NULL ); + + c = buf + size; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, key ) ); + + if( c - buf < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + /* + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING } + */ + *--c = 0; + len += 1; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_BIT_STRING ) ); + + pk_type = mbedtls_pk_get_type( key ); +#if defined(MBEDTLS_ECP_C) + if( pk_type == MBEDTLS_PK_ECKEY ) + { + MBEDTLS_ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, mbedtls_pk_ec( *key ) ) ); + } +#endif +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( pk_type == MBEDTLS_PK_OPAQUE ) + { + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_key_type_t key_type; + psa_key_handle_t handle; + psa_ecc_family_t curve; + size_t bits; + + handle = *((psa_key_handle_t*) key->pk_ctx ); + if( PSA_SUCCESS != psa_get_key_attributes( handle, &attributes ) ) + return( MBEDTLS_ERR_PK_HW_ACCEL_FAILED ); + key_type = psa_get_key_type( &attributes ); + bits = psa_get_key_bits( &attributes ); + psa_reset_key_attributes( &attributes ); + + curve = PSA_KEY_TYPE_ECC_GET_FAMILY( key_type ); + if( curve == 0 ) + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + + ret = mbedtls_psa_get_ecc_oid_from_id( curve, bits, &oid, &oid_len ); + if( ret != 0 ) + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + + /* Write EC algorithm parameters; that's akin + * to pk_write_ec_param() above. */ + MBEDTLS_ASN1_CHK_ADD( par_len, mbedtls_asn1_write_oid( &c, buf, + oid, oid_len ) ); + + /* The rest of the function works as for legacy EC contexts. */ + pk_type = MBEDTLS_PK_ECKEY; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + if( ( ret = mbedtls_oid_get_oid_by_pk_alg( pk_type, &oid, + &oid_len ) ) != 0 ) + { + return( ret ); + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( &c, buf, oid, oid_len, + par_len ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + return( (int) len ); +} + +int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_t size ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *c; + size_t len = 0; + + PK_VALIDATE_RET( key != NULL ); + if( size == 0 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + PK_VALIDATE_RET( buf != NULL ); + + c = buf + size; + +#if defined(MBEDTLS_RSA_C) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA ) + { + mbedtls_mpi T; /* Temporary holding the exported parameters */ + mbedtls_rsa_context *rsa = mbedtls_pk_rsa( *key ); + + /* + * Export the parameters one after another to avoid simultaneous copies. + */ + + mbedtls_mpi_init( &T ); + + /* Export QP */ + if( ( ret = mbedtls_rsa_export_crt( rsa, NULL, NULL, &T ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export DQ */ + if( ( ret = mbedtls_rsa_export_crt( rsa, NULL, &T, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export DP */ + if( ( ret = mbedtls_rsa_export_crt( rsa, &T, NULL, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export Q */ + if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL, + &T, NULL, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export P */ + if ( ( ret = mbedtls_rsa_export( rsa, NULL, &T, + NULL, NULL, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export D */ + if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL, + NULL, &T, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export E */ + if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL, + NULL, NULL, &T ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export N */ + if ( ( ret = mbedtls_rsa_export( rsa, &T, NULL, + NULL, NULL, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + end_of_export: + + mbedtls_mpi_free( &T ); + if( ret < 0 ) + return( ret ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 0 ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, + buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + } + else +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECP_C) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY ) + { + mbedtls_ecp_keypair *ec = mbedtls_pk_ec( *key ); + size_t pub_len = 0, par_len = 0; + + /* + * RFC 5915, or SEC1 Appendix C.4 + * + * ECPrivateKey ::= SEQUENCE { + * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), + * privateKey OCTET STRING, + * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, + * publicKey [1] BIT STRING OPTIONAL + * } + */ + + /* publicKey */ + MBEDTLS_ASN1_CHK_ADD( pub_len, pk_write_ec_pubkey( &c, buf, ec ) ); + + if( c - buf < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + *--c = 0; + pub_len += 1; + + MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_len( &c, buf, pub_len ) ); + MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_BIT_STRING ) ); + + MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_len( &c, buf, pub_len ) ); + MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_tag( &c, buf, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) ); + len += pub_len; + + /* parameters */ + MBEDTLS_ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, ec ) ); + + MBEDTLS_ASN1_CHK_ADD( par_len, mbedtls_asn1_write_len( &c, buf, par_len ) ); + MBEDTLS_ASN1_CHK_ADD( par_len, mbedtls_asn1_write_tag( &c, buf, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ); + len += par_len; + + /* privateKey */ + MBEDTLS_ASN1_CHK_ADD( len, pk_write_ec_private( &c, buf, ec ) ); + + /* version */ + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 1 ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + } + else +#endif /* MBEDTLS_ECP_C */ + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + + return( (int) len ); +} + +#if defined(MBEDTLS_PEM_WRITE_C) + +#define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----\n" +#define PEM_END_PUBLIC_KEY "-----END PUBLIC KEY-----\n" + +#define PEM_BEGIN_PRIVATE_KEY_RSA "-----BEGIN RSA PRIVATE KEY-----\n" +#define PEM_END_PRIVATE_KEY_RSA "-----END RSA PRIVATE KEY-----\n" +#define PEM_BEGIN_PRIVATE_KEY_EC "-----BEGIN EC PRIVATE KEY-----\n" +#define PEM_END_PRIVATE_KEY_EC "-----END EC PRIVATE KEY-----\n" + +/* + * Max sizes of key per types. Shown as tag + len (+ content). + */ + +#if defined(MBEDTLS_RSA_C) +/* + * RSA public keys: + * SubjectPublicKeyInfo ::= SEQUENCE { 1 + 3 + * algorithm AlgorithmIdentifier, 1 + 1 (sequence) + * + 1 + 1 + 9 (rsa oid) + * + 1 + 1 (params null) + * subjectPublicKey BIT STRING } 1 + 3 + (1 + below) + * RSAPublicKey ::= SEQUENCE { 1 + 3 + * modulus INTEGER, -- n 1 + 3 + MPI_MAX + 1 + * publicExponent INTEGER -- e 1 + 3 + MPI_MAX + 1 + * } + */ +#define RSA_PUB_DER_MAX_BYTES 38 + 2 * MBEDTLS_MPI_MAX_SIZE + +/* + * RSA private keys: + * RSAPrivateKey ::= SEQUENCE { 1 + 3 + * version Version, 1 + 1 + 1 + * modulus INTEGER, 1 + 3 + MPI_MAX + 1 + * publicExponent INTEGER, 1 + 3 + MPI_MAX + 1 + * privateExponent INTEGER, 1 + 3 + MPI_MAX + 1 + * prime1 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 + * prime2 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 + * exponent1 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 + * exponent2 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 + * coefficient INTEGER, 1 + 3 + MPI_MAX / 2 + 1 + * otherPrimeInfos OtherPrimeInfos OPTIONAL 0 (not supported) + * } + */ +#define MPI_MAX_SIZE_2 MBEDTLS_MPI_MAX_SIZE / 2 + \ + MBEDTLS_MPI_MAX_SIZE % 2 +#define RSA_PRV_DER_MAX_BYTES 47 + 3 * MBEDTLS_MPI_MAX_SIZE \ + + 5 * MPI_MAX_SIZE_2 + +#else /* MBEDTLS_RSA_C */ + +#define RSA_PUB_DER_MAX_BYTES 0 +#define RSA_PRV_DER_MAX_BYTES 0 + +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) +/* + * EC public keys: + * SubjectPublicKeyInfo ::= SEQUENCE { 1 + 2 + * algorithm AlgorithmIdentifier, 1 + 1 (sequence) + * + 1 + 1 + 7 (ec oid) + * + 1 + 1 + 9 (namedCurve oid) + * subjectPublicKey BIT STRING 1 + 2 + 1 [1] + * + 1 (point format) [1] + * + 2 * ECP_MAX (coords) [1] + * } + */ +#define ECP_PUB_DER_MAX_BYTES 30 + 2 * MBEDTLS_ECP_MAX_BYTES + +/* + * EC private keys: + * ECPrivateKey ::= SEQUENCE { 1 + 2 + * version INTEGER , 1 + 1 + 1 + * privateKey OCTET STRING, 1 + 1 + ECP_MAX + * parameters [0] ECParameters OPTIONAL, 1 + 1 + (1 + 1 + 9) + * publicKey [1] BIT STRING OPTIONAL 1 + 2 + [1] above + * } + */ +#define ECP_PRV_DER_MAX_BYTES 29 + 3 * MBEDTLS_ECP_MAX_BYTES + +#else /* MBEDTLS_ECP_C */ + +#define ECP_PUB_DER_MAX_BYTES 0 +#define ECP_PRV_DER_MAX_BYTES 0 + +#endif /* MBEDTLS_ECP_C */ + +#define PUB_DER_MAX_BYTES RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \ + RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES +#define PRV_DER_MAX_BYTES RSA_PRV_DER_MAX_BYTES > ECP_PRV_DER_MAX_BYTES ? \ + RSA_PRV_DER_MAX_BYTES : ECP_PRV_DER_MAX_BYTES + +int mbedtls_pk_write_pubkey_pem( mbedtls_pk_context *key, unsigned char *buf, size_t size ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char output_buf[PUB_DER_MAX_BYTES]; + size_t olen = 0; + + PK_VALIDATE_RET( key != NULL ); + PK_VALIDATE_RET( buf != NULL || size == 0 ); + + if( ( ret = mbedtls_pk_write_pubkey_der( key, output_buf, + sizeof(output_buf) ) ) < 0 ) + { + return( ret ); + } + + if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY, + output_buf + sizeof(output_buf) - ret, + ret, buf, size, &olen ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} + +int mbedtls_pk_write_key_pem( mbedtls_pk_context *key, unsigned char *buf, size_t size ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char output_buf[PRV_DER_MAX_BYTES]; + const char *begin, *end; + size_t olen = 0; + + PK_VALIDATE_RET( key != NULL ); + PK_VALIDATE_RET( buf != NULL || size == 0 ); + + if( ( ret = mbedtls_pk_write_key_der( key, output_buf, sizeof(output_buf) ) ) < 0 ) + return( ret ); + +#if defined(MBEDTLS_RSA_C) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA ) + { + begin = PEM_BEGIN_PRIVATE_KEY_RSA; + end = PEM_END_PRIVATE_KEY_RSA; + } + else +#endif +#if defined(MBEDTLS_ECP_C) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY ) + { + begin = PEM_BEGIN_PRIVATE_KEY_EC; + end = PEM_END_PRIVATE_KEY_EC; + } + else +#endif + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + + if( ( ret = mbedtls_pem_write_buffer( begin, end, + output_buf + sizeof(output_buf) - ret, + ret, buf, size, &olen ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_PEM_WRITE_C */ + +#endif /* MBEDTLS_PK_WRITE_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/platform.c b/Android/Level4/app/src/main/c/mbedtls/library/platform.c new file mode 100644 index 0000000..e742fde --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/platform.c @@ -0,0 +1,386 @@ +/* + * Platform abstraction layer + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 "common.h" + +#if defined(MBEDTLS_PLATFORM_C) + +#include "mbedtls/platform.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +/* The compile time configuration of memory allocation via the macros + * MBEDTLS_PLATFORM_{FREE/CALLOC}_MACRO takes precedence over the runtime + * configuration via mbedtls_platform_set_calloc_free(). So, omit everything + * related to the latter if MBEDTLS_PLATFORM_{FREE/CALLOC}_MACRO are defined. */ +#if defined(MBEDTLS_PLATFORM_MEMORY) && \ + !( defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && \ + defined(MBEDTLS_PLATFORM_FREE_MACRO) ) + +#if !defined(MBEDTLS_PLATFORM_STD_CALLOC) +static void *platform_calloc_uninit( size_t n, size_t size ) +{ + ((void) n); + ((void) size); + return( NULL ); +} + +#define MBEDTLS_PLATFORM_STD_CALLOC platform_calloc_uninit +#endif /* !MBEDTLS_PLATFORM_STD_CALLOC */ + +#if !defined(MBEDTLS_PLATFORM_STD_FREE) +static void platform_free_uninit( void *ptr ) +{ + ((void) ptr); +} + +#define MBEDTLS_PLATFORM_STD_FREE platform_free_uninit +#endif /* !MBEDTLS_PLATFORM_STD_FREE */ + +static void * (*mbedtls_calloc_func)( size_t, size_t ) = MBEDTLS_PLATFORM_STD_CALLOC; +static void (*mbedtls_free_func)( void * ) = MBEDTLS_PLATFORM_STD_FREE; + +void * mbedtls_calloc( size_t nmemb, size_t size ) +{ + return (*mbedtls_calloc_func)( nmemb, size ); +} + +void mbedtls_free( void * ptr ) +{ + (*mbedtls_free_func)( ptr ); +} + +int mbedtls_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ), + void (*free_func)( void * ) ) +{ + mbedtls_calloc_func = calloc_func; + mbedtls_free_func = free_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_MEMORY && + !( defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && + defined(MBEDTLS_PLATFORM_FREE_MACRO) ) */ + +#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_SNPRINTF) +#include +int mbedtls_platform_win32_snprintf( char *s, size_t n, const char *fmt, ... ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + va_list argp; + + va_start( argp, fmt ); + ret = mbedtls_vsnprintf( s, n, fmt, argp ); + va_end( argp ); + + return( ret ); +} +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_SNPRINTF) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_snprintf_uninit( char * s, size_t n, + const char * format, ... ) +{ + ((void) s); + ((void) n); + ((void) format); + return( 0 ); +} + +#define MBEDTLS_PLATFORM_STD_SNPRINTF platform_snprintf_uninit +#endif /* !MBEDTLS_PLATFORM_STD_SNPRINTF */ + +int (*mbedtls_snprintf)( char * s, size_t n, + const char * format, + ... ) = MBEDTLS_PLATFORM_STD_SNPRINTF; + +int mbedtls_platform_set_snprintf( int (*snprintf_func)( char * s, size_t n, + const char * format, + ... ) ) +{ + mbedtls_snprintf = snprintf_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ + +#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_VSNPRINTF) +#include +int mbedtls_platform_win32_vsnprintf( char *s, size_t n, const char *fmt, va_list arg ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* Avoid calling the invalid parameter handler by checking ourselves */ + if( s == NULL || n == 0 || fmt == NULL ) + return( -1 ); + +#if defined(_TRUNCATE) + ret = vsnprintf_s( s, n, _TRUNCATE, fmt, arg ); +#else + ret = vsnprintf( s, n, fmt, arg ); + if( ret < 0 || (size_t) ret == n ) + { + s[n-1] = '\0'; + ret = -1; + } +#endif + + return( ret ); +} +#endif + +#if defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_VSNPRINTF) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_vsnprintf_uninit( char * s, size_t n, + const char * format, va_list arg ) +{ + ((void) s); + ((void) n); + ((void) format); + ((void) arg); + return( -1 ); +} + +#define MBEDTLS_PLATFORM_STD_VSNPRINTF platform_vsnprintf_uninit +#endif /* !MBEDTLS_PLATFORM_STD_VSNPRINTF */ + +int (*mbedtls_vsnprintf)( char * s, size_t n, + const char * format, + va_list arg ) = MBEDTLS_PLATFORM_STD_VSNPRINTF; + +int mbedtls_platform_set_vsnprintf( int (*vsnprintf_func)( char * s, size_t n, + const char * format, + va_list arg ) ) +{ + mbedtls_vsnprintf = vsnprintf_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_VSNPRINTF_ALT */ + +#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_PRINTF) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_printf_uninit( const char *format, ... ) +{ + ((void) format); + return( 0 ); +} + +#define MBEDTLS_PLATFORM_STD_PRINTF platform_printf_uninit +#endif /* !MBEDTLS_PLATFORM_STD_PRINTF */ + +int (*mbedtls_printf)( const char *, ... ) = MBEDTLS_PLATFORM_STD_PRINTF; + +int mbedtls_platform_set_printf( int (*printf_func)( const char *, ... ) ) +{ + mbedtls_printf = printf_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_PRINTF_ALT */ + +#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_FPRINTF) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_fprintf_uninit( FILE *stream, const char *format, ... ) +{ + ((void) stream); + ((void) format); + return( 0 ); +} + +#define MBEDTLS_PLATFORM_STD_FPRINTF platform_fprintf_uninit +#endif /* !MBEDTLS_PLATFORM_STD_FPRINTF */ + +int (*mbedtls_fprintf)( FILE *, const char *, ... ) = + MBEDTLS_PLATFORM_STD_FPRINTF; + +int mbedtls_platform_set_fprintf( int (*fprintf_func)( FILE *, const char *, ... ) ) +{ + mbedtls_fprintf = fprintf_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */ + +#if defined(MBEDTLS_PLATFORM_EXIT_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_EXIT) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static void platform_exit_uninit( int status ) +{ + ((void) status); +} + +#define MBEDTLS_PLATFORM_STD_EXIT platform_exit_uninit +#endif /* !MBEDTLS_PLATFORM_STD_EXIT */ + +void (*mbedtls_exit)( int status ) = MBEDTLS_PLATFORM_STD_EXIT; + +int mbedtls_platform_set_exit( void (*exit_func)( int status ) ) +{ + mbedtls_exit = exit_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_EXIT_ALT */ + +#if defined(MBEDTLS_HAVE_TIME) + +#if defined(MBEDTLS_PLATFORM_TIME_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_TIME) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static mbedtls_time_t platform_time_uninit( mbedtls_time_t* timer ) +{ + ((void) timer); + return( 0 ); +} + +#define MBEDTLS_PLATFORM_STD_TIME platform_time_uninit +#endif /* !MBEDTLS_PLATFORM_STD_TIME */ + +mbedtls_time_t (*mbedtls_time)( mbedtls_time_t* timer ) = MBEDTLS_PLATFORM_STD_TIME; + +int mbedtls_platform_set_time( mbedtls_time_t (*time_func)( mbedtls_time_t* timer ) ) +{ + mbedtls_time = time_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_TIME_ALT */ + +#endif /* MBEDTLS_HAVE_TIME */ + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) && defined(MBEDTLS_FS_IO) +/* Default implementations for the platform independent seed functions use + * standard libc file functions to read from and write to a pre-defined filename + */ +int mbedtls_platform_std_nv_seed_read( unsigned char *buf, size_t buf_len ) +{ + FILE *file; + size_t n; + + if( ( file = fopen( MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "rb" ) ) == NULL ) + return( -1 ); + + if( ( n = fread( buf, 1, buf_len, file ) ) != buf_len ) + { + fclose( file ); + mbedtls_platform_zeroize( buf, buf_len ); + return( -1 ); + } + + fclose( file ); + return( (int)n ); +} + +int mbedtls_platform_std_nv_seed_write( unsigned char *buf, size_t buf_len ) +{ + FILE *file; + size_t n; + + if( ( file = fopen( MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "w" ) ) == NULL ) + return -1; + + if( ( n = fwrite( buf, 1, buf_len, file ) ) != buf_len ) + { + fclose( file ); + return -1; + } + + fclose( file ); + return( (int)n ); +} +#endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ + +#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_nv_seed_read_uninit( unsigned char *buf, size_t buf_len ) +{ + ((void) buf); + ((void) buf_len); + return( -1 ); +} + +#define MBEDTLS_PLATFORM_STD_NV_SEED_READ platform_nv_seed_read_uninit +#endif /* !MBEDTLS_PLATFORM_STD_NV_SEED_READ */ + +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_nv_seed_write_uninit( unsigned char *buf, size_t buf_len ) +{ + ((void) buf); + ((void) buf_len); + return( -1 ); +} + +#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE platform_nv_seed_write_uninit +#endif /* !MBEDTLS_PLATFORM_STD_NV_SEED_WRITE */ + +int (*mbedtls_nv_seed_read)( unsigned char *buf, size_t buf_len ) = + MBEDTLS_PLATFORM_STD_NV_SEED_READ; +int (*mbedtls_nv_seed_write)( unsigned char *buf, size_t buf_len ) = + MBEDTLS_PLATFORM_STD_NV_SEED_WRITE; + +int mbedtls_platform_set_nv_seed( + int (*nv_seed_read_func)( unsigned char *buf, size_t buf_len ), + int (*nv_seed_write_func)( unsigned char *buf, size_t buf_len ) ) +{ + mbedtls_nv_seed_read = nv_seed_read_func; + mbedtls_nv_seed_write = nv_seed_write_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */ +#endif /* MBEDTLS_ENTROPY_NV_SEED */ + +#if !defined(MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT) +/* + * Placeholder platform setup that does nothing by default + */ +int mbedtls_platform_setup( mbedtls_platform_context *ctx ) +{ + (void)ctx; + + return( 0 ); +} + +/* + * Placeholder platform teardown that does nothing by default + */ +void mbedtls_platform_teardown( mbedtls_platform_context *ctx ) +{ + (void)ctx; +} +#endif /* MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT */ + +#endif /* MBEDTLS_PLATFORM_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/platform_util.c b/Android/Level4/app/src/main/c/mbedtls/library/platform_util.c new file mode 100644 index 0000000..4e1d617 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/platform_util.c @@ -0,0 +1,133 @@ +/* + * Common and shared functions used by multiple modules in the Mbed TLS + * library. + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ + +/* + * Ensure gmtime_r is available even with -std=c99; must be defined before + * config.h, which pulls in glibc's features.h. Harmless on other platforms. + */ +#if !defined(_POSIX_C_SOURCE) +#define _POSIX_C_SOURCE 200112L +#endif + +#include "common.h" + +#include "mbedtls/platform_util.h" +#include "mbedtls/platform.h" +#include "mbedtls/threading.h" + +#include +#include + +#if !defined(MBEDTLS_PLATFORM_ZEROIZE_ALT) +/* + * This implementation should never be optimized out by the compiler + * + * This implementation for mbedtls_platform_zeroize() was inspired from Colin + * Percival's blog article at: + * + * http://www.daemonology.net/blog/2014-09-04-how-to-zero-a-buffer.html + * + * It uses a volatile function pointer to the standard memset(). Because the + * pointer is volatile the compiler expects it to change at + * any time and will not optimize out the call that could potentially perform + * other operations on the input buffer instead of just setting it to 0. + * Nevertheless, as pointed out by davidtgoldblatt on Hacker News + * (refer to http://www.daemonology.net/blog/2014-09-05-erratum.html for + * details), optimizations of the following form are still possible: + * + * if( memset_func != memset ) + * memset_func( buf, 0, len ); + * + * Note that it is extremely difficult to guarantee that + * mbedtls_platform_zeroize() will not be optimized out by aggressive compilers + * in a portable way. For this reason, Mbed TLS also provides the configuration + * option MBEDTLS_PLATFORM_ZEROIZE_ALT, which allows users to configure + * mbedtls_platform_zeroize() to use a suitable implementation for their + * platform and needs. + */ +static void * (* const volatile memset_func)( void *, int, size_t ) = memset; + +void mbedtls_platform_zeroize( void *buf, size_t len ) +{ + MBEDTLS_INTERNAL_VALIDATE( len == 0 || buf != NULL ); + + if( len > 0 ) + memset_func( buf, 0, len ); +} +#endif /* MBEDTLS_PLATFORM_ZEROIZE_ALT */ + +#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT) +#include +#if !defined(_WIN32) && (defined(unix) || \ + defined(__unix) || defined(__unix__) || (defined(__APPLE__) && \ + defined(__MACH__))) +#include +#endif /* !_WIN32 && (unix || __unix || __unix__ || + * (__APPLE__ && __MACH__)) */ + +#if !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \ + ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \ + _POSIX_THREAD_SAFE_FUNCTIONS >= 20112L ) ) +/* + * This is a convenience shorthand macro to avoid checking the long + * preprocessor conditions above. Ideally, we could expose this macro in + * platform_util.h and simply use it in platform_util.c, threading.c and + * threading.h. However, this macro is not part of the Mbed TLS public API, so + * we keep it private by only defining it in this file + */ +#if ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) +#define PLATFORM_UTIL_USE_GMTIME +#endif /* ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) */ + +#endif /* !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \ + ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \ + _POSIX_THREAD_SAFE_FUNCTIONS >= 20112L ) ) */ + +struct tm *mbedtls_platform_gmtime_r( const mbedtls_time_t *tt, + struct tm *tm_buf ) +{ +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + return( ( gmtime_s( tm_buf, tt ) == 0 ) ? tm_buf : NULL ); +#elif !defined(PLATFORM_UTIL_USE_GMTIME) + return( gmtime_r( tt, tm_buf ) ); +#else + struct tm *lt; + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_lock( &mbedtls_threading_gmtime_mutex ) != 0 ) + return( NULL ); +#endif /* MBEDTLS_THREADING_C */ + + lt = gmtime( tt ); + + if( lt != NULL ) + { + memcpy( tm_buf, lt, sizeof( struct tm ) ); + } + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &mbedtls_threading_gmtime_mutex ) != 0 ) + return( NULL ); +#endif /* MBEDTLS_THREADING_C */ + + return( ( lt == NULL ) ? NULL : tm_buf ); +#endif /* _WIN32 && !EFIX64 && !EFI32 */ +} +#endif /* MBEDTLS_HAVE_TIME_DATE && MBEDTLS_PLATFORM_GMTIME_R_ALT */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/poly1305.c b/Android/Level4/app/src/main/c/mbedtls/library/poly1305.c new file mode 100644 index 0000000..492d145 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/poly1305.c @@ -0,0 +1,557 @@ +/** + * \file poly1305.c + * + * \brief Poly1305 authentication algorithm. + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 "common.h" + +#if defined(MBEDTLS_POLY1305_C) + +#include "mbedtls/poly1305.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_POLY1305_ALT) + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +/* Parameter validation macros */ +#define POLY1305_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ) +#define POLY1305_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#define POLY1305_BLOCK_SIZE_BYTES ( 16U ) + +#define BYTES_TO_U32_LE( data, offset ) \ + ( (uint32_t) (data)[offset] \ + | (uint32_t) ( (uint32_t) (data)[( offset ) + 1] << 8 ) \ + | (uint32_t) ( (uint32_t) (data)[( offset ) + 2] << 16 ) \ + | (uint32_t) ( (uint32_t) (data)[( offset ) + 3] << 24 ) \ + ) + +/* + * Our implementation is tuned for 32-bit platforms with a 64-bit multiplier. + * However we provided an alternative for platforms without such a multiplier. + */ +#if defined(MBEDTLS_NO_64BIT_MULTIPLICATION) +static uint64_t mul64( uint32_t a, uint32_t b ) +{ + /* a = al + 2**16 ah, b = bl + 2**16 bh */ + const uint16_t al = (uint16_t) a; + const uint16_t bl = (uint16_t) b; + const uint16_t ah = a >> 16; + const uint16_t bh = b >> 16; + + /* ab = al*bl + 2**16 (ah*bl + bl*bh) + 2**32 ah*bh */ + const uint32_t lo = (uint32_t) al * bl; + const uint64_t me = (uint64_t)( (uint32_t) ah * bl ) + (uint32_t) al * bh; + const uint32_t hi = (uint32_t) ah * bh; + + return( lo + ( me << 16 ) + ( (uint64_t) hi << 32 ) ); +} +#else +static inline uint64_t mul64( uint32_t a, uint32_t b ) +{ + return( (uint64_t) a * b ); +} +#endif + + +/** + * \brief Process blocks with Poly1305. + * + * \param ctx The Poly1305 context. + * \param nblocks Number of blocks to process. Note that this + * function only processes full blocks. + * \param input Buffer containing the input block(s). + * \param needs_padding Set to 0 if the padding bit has already been + * applied to the input data before calling this + * function. Otherwise, set this parameter to 1. + */ +static void poly1305_process( mbedtls_poly1305_context *ctx, + size_t nblocks, + const unsigned char *input, + uint32_t needs_padding ) +{ + uint64_t d0, d1, d2, d3; + uint32_t acc0, acc1, acc2, acc3, acc4; + uint32_t r0, r1, r2, r3; + uint32_t rs1, rs2, rs3; + size_t offset = 0U; + size_t i; + + r0 = ctx->r[0]; + r1 = ctx->r[1]; + r2 = ctx->r[2]; + r3 = ctx->r[3]; + + rs1 = r1 + ( r1 >> 2U ); + rs2 = r2 + ( r2 >> 2U ); + rs3 = r3 + ( r3 >> 2U ); + + acc0 = ctx->acc[0]; + acc1 = ctx->acc[1]; + acc2 = ctx->acc[2]; + acc3 = ctx->acc[3]; + acc4 = ctx->acc[4]; + + /* Process full blocks */ + for( i = 0U; i < nblocks; i++ ) + { + /* The input block is treated as a 128-bit little-endian integer */ + d0 = BYTES_TO_U32_LE( input, offset + 0 ); + d1 = BYTES_TO_U32_LE( input, offset + 4 ); + d2 = BYTES_TO_U32_LE( input, offset + 8 ); + d3 = BYTES_TO_U32_LE( input, offset + 12 ); + + /* Compute: acc += (padded) block as a 130-bit integer */ + d0 += (uint64_t) acc0; + d1 += (uint64_t) acc1 + ( d0 >> 32U ); + d2 += (uint64_t) acc2 + ( d1 >> 32U ); + d3 += (uint64_t) acc3 + ( d2 >> 32U ); + acc0 = (uint32_t) d0; + acc1 = (uint32_t) d1; + acc2 = (uint32_t) d2; + acc3 = (uint32_t) d3; + acc4 += (uint32_t) ( d3 >> 32U ) + needs_padding; + + /* Compute: acc *= r */ + d0 = mul64( acc0, r0 ) + + mul64( acc1, rs3 ) + + mul64( acc2, rs2 ) + + mul64( acc3, rs1 ); + d1 = mul64( acc0, r1 ) + + mul64( acc1, r0 ) + + mul64( acc2, rs3 ) + + mul64( acc3, rs2 ) + + mul64( acc4, rs1 ); + d2 = mul64( acc0, r2 ) + + mul64( acc1, r1 ) + + mul64( acc2, r0 ) + + mul64( acc3, rs3 ) + + mul64( acc4, rs2 ); + d3 = mul64( acc0, r3 ) + + mul64( acc1, r2 ) + + mul64( acc2, r1 ) + + mul64( acc3, r0 ) + + mul64( acc4, rs3 ); + acc4 *= r0; + + /* Compute: acc %= (2^130 - 5) (partial remainder) */ + d1 += ( d0 >> 32 ); + d2 += ( d1 >> 32 ); + d3 += ( d2 >> 32 ); + acc0 = (uint32_t) d0; + acc1 = (uint32_t) d1; + acc2 = (uint32_t) d2; + acc3 = (uint32_t) d3; + acc4 = (uint32_t) ( d3 >> 32 ) + acc4; + + d0 = (uint64_t) acc0 + ( acc4 >> 2 ) + ( acc4 & 0xFFFFFFFCU ); + acc4 &= 3U; + acc0 = (uint32_t) d0; + d0 = (uint64_t) acc1 + ( d0 >> 32U ); + acc1 = (uint32_t) d0; + d0 = (uint64_t) acc2 + ( d0 >> 32U ); + acc2 = (uint32_t) d0; + d0 = (uint64_t) acc3 + ( d0 >> 32U ); + acc3 = (uint32_t) d0; + d0 = (uint64_t) acc4 + ( d0 >> 32U ); + acc4 = (uint32_t) d0; + + offset += POLY1305_BLOCK_SIZE_BYTES; + } + + ctx->acc[0] = acc0; + ctx->acc[1] = acc1; + ctx->acc[2] = acc2; + ctx->acc[3] = acc3; + ctx->acc[4] = acc4; +} + +/** + * \brief Compute the Poly1305 MAC + * + * \param ctx The Poly1305 context. + * \param mac The buffer to where the MAC is written. Must be + * big enough to contain the 16-byte MAC. + */ +static void poly1305_compute_mac( const mbedtls_poly1305_context *ctx, + unsigned char mac[16] ) +{ + uint64_t d; + uint32_t g0, g1, g2, g3, g4; + uint32_t acc0, acc1, acc2, acc3, acc4; + uint32_t mask; + uint32_t mask_inv; + + acc0 = ctx->acc[0]; + acc1 = ctx->acc[1]; + acc2 = ctx->acc[2]; + acc3 = ctx->acc[3]; + acc4 = ctx->acc[4]; + + /* Before adding 's' we ensure that the accumulator is mod 2^130 - 5. + * We do this by calculating acc - (2^130 - 5), then checking if + * the 131st bit is set. If it is, then reduce: acc -= (2^130 - 5) + */ + + /* Calculate acc + -(2^130 - 5) */ + d = ( (uint64_t) acc0 + 5U ); + g0 = (uint32_t) d; + d = ( (uint64_t) acc1 + ( d >> 32 ) ); + g1 = (uint32_t) d; + d = ( (uint64_t) acc2 + ( d >> 32 ) ); + g2 = (uint32_t) d; + d = ( (uint64_t) acc3 + ( d >> 32 ) ); + g3 = (uint32_t) d; + g4 = acc4 + (uint32_t) ( d >> 32U ); + + /* mask == 0xFFFFFFFF if 131st bit is set, otherwise mask == 0 */ + mask = (uint32_t) 0U - ( g4 >> 2U ); + mask_inv = ~mask; + + /* If 131st bit is set then acc=g, otherwise, acc is unmodified */ + acc0 = ( acc0 & mask_inv ) | ( g0 & mask ); + acc1 = ( acc1 & mask_inv ) | ( g1 & mask ); + acc2 = ( acc2 & mask_inv ) | ( g2 & mask ); + acc3 = ( acc3 & mask_inv ) | ( g3 & mask ); + + /* Add 's' */ + d = (uint64_t) acc0 + ctx->s[0]; + acc0 = (uint32_t) d; + d = (uint64_t) acc1 + ctx->s[1] + ( d >> 32U ); + acc1 = (uint32_t) d; + d = (uint64_t) acc2 + ctx->s[2] + ( d >> 32U ); + acc2 = (uint32_t) d; + acc3 += ctx->s[3] + (uint32_t) ( d >> 32U ); + + /* Compute MAC (128 least significant bits of the accumulator) */ + mac[ 0] = (unsigned char)( acc0 ); + mac[ 1] = (unsigned char)( acc0 >> 8 ); + mac[ 2] = (unsigned char)( acc0 >> 16 ); + mac[ 3] = (unsigned char)( acc0 >> 24 ); + mac[ 4] = (unsigned char)( acc1 ); + mac[ 5] = (unsigned char)( acc1 >> 8 ); + mac[ 6] = (unsigned char)( acc1 >> 16 ); + mac[ 7] = (unsigned char)( acc1 >> 24 ); + mac[ 8] = (unsigned char)( acc2 ); + mac[ 9] = (unsigned char)( acc2 >> 8 ); + mac[10] = (unsigned char)( acc2 >> 16 ); + mac[11] = (unsigned char)( acc2 >> 24 ); + mac[12] = (unsigned char)( acc3 ); + mac[13] = (unsigned char)( acc3 >> 8 ); + mac[14] = (unsigned char)( acc3 >> 16 ); + mac[15] = (unsigned char)( acc3 >> 24 ); +} + +void mbedtls_poly1305_init( mbedtls_poly1305_context *ctx ) +{ + POLY1305_VALIDATE( ctx != NULL ); + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_poly1305_context ) ); +} + +void mbedtls_poly1305_free( mbedtls_poly1305_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_poly1305_context ) ); +} + +int mbedtls_poly1305_starts( mbedtls_poly1305_context *ctx, + const unsigned char key[32] ) +{ + POLY1305_VALIDATE_RET( ctx != NULL ); + POLY1305_VALIDATE_RET( key != NULL ); + + /* r &= 0x0ffffffc0ffffffc0ffffffc0fffffff */ + ctx->r[0] = BYTES_TO_U32_LE( key, 0 ) & 0x0FFFFFFFU; + ctx->r[1] = BYTES_TO_U32_LE( key, 4 ) & 0x0FFFFFFCU; + ctx->r[2] = BYTES_TO_U32_LE( key, 8 ) & 0x0FFFFFFCU; + ctx->r[3] = BYTES_TO_U32_LE( key, 12 ) & 0x0FFFFFFCU; + + ctx->s[0] = BYTES_TO_U32_LE( key, 16 ); + ctx->s[1] = BYTES_TO_U32_LE( key, 20 ); + ctx->s[2] = BYTES_TO_U32_LE( key, 24 ); + ctx->s[3] = BYTES_TO_U32_LE( key, 28 ); + + /* Initial accumulator state */ + ctx->acc[0] = 0U; + ctx->acc[1] = 0U; + ctx->acc[2] = 0U; + ctx->acc[3] = 0U; + ctx->acc[4] = 0U; + + /* Queue initially empty */ + mbedtls_platform_zeroize( ctx->queue, sizeof( ctx->queue ) ); + ctx->queue_len = 0U; + + return( 0 ); +} + +int mbedtls_poly1305_update( mbedtls_poly1305_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + size_t offset = 0U; + size_t remaining = ilen; + size_t queue_free_len; + size_t nblocks; + POLY1305_VALIDATE_RET( ctx != NULL ); + POLY1305_VALIDATE_RET( ilen == 0 || input != NULL ); + + if( ( remaining > 0U ) && ( ctx->queue_len > 0U ) ) + { + queue_free_len = ( POLY1305_BLOCK_SIZE_BYTES - ctx->queue_len ); + + if( ilen < queue_free_len ) + { + /* Not enough data to complete the block. + * Store this data with the other leftovers. + */ + memcpy( &ctx->queue[ctx->queue_len], + input, + ilen ); + + ctx->queue_len += ilen; + + remaining = 0U; + } + else + { + /* Enough data to produce a complete block */ + memcpy( &ctx->queue[ctx->queue_len], + input, + queue_free_len ); + + ctx->queue_len = 0U; + + poly1305_process( ctx, 1U, ctx->queue, 1U ); /* add padding bit */ + + offset += queue_free_len; + remaining -= queue_free_len; + } + } + + if( remaining >= POLY1305_BLOCK_SIZE_BYTES ) + { + nblocks = remaining / POLY1305_BLOCK_SIZE_BYTES; + + poly1305_process( ctx, nblocks, &input[offset], 1U ); + + offset += nblocks * POLY1305_BLOCK_SIZE_BYTES; + remaining %= POLY1305_BLOCK_SIZE_BYTES; + } + + if( remaining > 0U ) + { + /* Store partial block */ + ctx->queue_len = remaining; + memcpy( ctx->queue, &input[offset], remaining ); + } + + return( 0 ); +} + +int mbedtls_poly1305_finish( mbedtls_poly1305_context *ctx, + unsigned char mac[16] ) +{ + POLY1305_VALIDATE_RET( ctx != NULL ); + POLY1305_VALIDATE_RET( mac != NULL ); + + /* Process any leftover data */ + if( ctx->queue_len > 0U ) + { + /* Add padding bit */ + ctx->queue[ctx->queue_len] = 1U; + ctx->queue_len++; + + /* Pad with zeroes */ + memset( &ctx->queue[ctx->queue_len], + 0, + POLY1305_BLOCK_SIZE_BYTES - ctx->queue_len ); + + poly1305_process( ctx, 1U, /* Process 1 block */ + ctx->queue, 0U ); /* Already padded above */ + } + + poly1305_compute_mac( ctx, mac ); + + return( 0 ); +} + +int mbedtls_poly1305_mac( const unsigned char key[32], + const unsigned char *input, + size_t ilen, + unsigned char mac[16] ) +{ + mbedtls_poly1305_context ctx; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + POLY1305_VALIDATE_RET( key != NULL ); + POLY1305_VALIDATE_RET( mac != NULL ); + POLY1305_VALIDATE_RET( ilen == 0 || input != NULL ); + + mbedtls_poly1305_init( &ctx ); + + ret = mbedtls_poly1305_starts( &ctx, key ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_poly1305_update( &ctx, input, ilen ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_poly1305_finish( &ctx, mac ); + +cleanup: + mbedtls_poly1305_free( &ctx ); + return( ret ); +} + +#endif /* MBEDTLS_POLY1305_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +static const unsigned char test_keys[2][32] = +{ + { + 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 + }, + { + 0x1c, 0x92, 0x40, 0xa5, 0xeb, 0x55, 0xd3, 0x8a, + 0xf3, 0x33, 0x88, 0x86, 0x04, 0xf6, 0xb5, 0xf0, + 0x47, 0x39, 0x17, 0xc1, 0x40, 0x2b, 0x80, 0x09, + 0x9d, 0xca, 0x5c, 0xbc, 0x20, 0x70, 0x75, 0xc0 + } +}; + +static const unsigned char test_data[2][127] = +{ + { + 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x67, 0x72, + 0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x46, 0x6f, + 0x72, 0x75, 0x6d, 0x20, 0x52, 0x65, 0x73, 0x65, + 0x61, 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6f, + 0x75, 0x70 + }, + { + 0x27, 0x54, 0x77, 0x61, 0x73, 0x20, 0x62, 0x72, + 0x69, 0x6c, 0x6c, 0x69, 0x67, 0x2c, 0x20, 0x61, + 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, + 0x6c, 0x69, 0x74, 0x68, 0x79, 0x20, 0x74, 0x6f, + 0x76, 0x65, 0x73, 0x0a, 0x44, 0x69, 0x64, 0x20, + 0x67, 0x79, 0x72, 0x65, 0x20, 0x61, 0x6e, 0x64, + 0x20, 0x67, 0x69, 0x6d, 0x62, 0x6c, 0x65, 0x20, + 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, + 0x61, 0x62, 0x65, 0x3a, 0x0a, 0x41, 0x6c, 0x6c, + 0x20, 0x6d, 0x69, 0x6d, 0x73, 0x79, 0x20, 0x77, + 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x62, 0x6f, 0x72, 0x6f, 0x67, 0x6f, 0x76, 0x65, + 0x73, 0x2c, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x6d, 0x65, 0x20, + 0x72, 0x61, 0x74, 0x68, 0x73, 0x20, 0x6f, 0x75, + 0x74, 0x67, 0x72, 0x61, 0x62, 0x65, 0x2e + } +}; + +static const size_t test_data_len[2] = +{ + 34U, + 127U +}; + +static const unsigned char test_mac[2][16] = +{ + { + 0xa8, 0x06, 0x1d, 0xc1, 0x30, 0x51, 0x36, 0xc6, + 0xc2, 0x2b, 0x8b, 0xaf, 0x0c, 0x01, 0x27, 0xa9 + }, + { + 0x45, 0x41, 0x66, 0x9a, 0x7e, 0xaa, 0xee, 0x61, + 0xe7, 0x08, 0xdc, 0x7c, 0xbc, 0xc5, 0xeb, 0x62 + } +}; + +/* Make sure no other definition is already present. */ +#undef ASSERT + +#define ASSERT( cond, args ) \ + do \ + { \ + if( ! ( cond ) ) \ + { \ + if( verbose != 0 ) \ + mbedtls_printf args; \ + \ + return( -1 ); \ + } \ + } \ + while( 0 ) + +int mbedtls_poly1305_self_test( int verbose ) +{ + unsigned char mac[16]; + unsigned i; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + for( i = 0U; i < 2U; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " Poly1305 test %u ", i ); + + ret = mbedtls_poly1305_mac( test_keys[i], + test_data[i], + test_data_len[i], + mac ); + ASSERT( 0 == ret, ( "error code: %i\n", ret ) ); + + ASSERT( 0 == memcmp( mac, test_mac[i], 16U ), ( "failed (mac)\n" ) ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_POLY1305_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/psa_crypto.c b/Android/Level4/app/src/main/c/mbedtls/library/psa_crypto.c new file mode 100644 index 0000000..ab4e47a --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/psa_crypto.c @@ -0,0 +1,6363 @@ +/* + * PSA crypto layer on top of Mbed TLS crypto + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 "common.h" + +#if defined(MBEDTLS_PSA_CRYPTO_C) + +#include "psa_crypto_service_integration.h" +#include "psa/crypto.h" + +#include "psa_crypto_core.h" +#include "psa_crypto_invasive.h" +#include "psa_crypto_driver_wrappers.h" +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) +#include "psa_crypto_se.h" +#endif +#include "psa_crypto_slot_management.h" +/* Include internal declarations that are useful for implementing persistently + * stored keys. */ +#include "psa_crypto_storage.h" + +#include +#include +#include +#include "mbedtls/platform.h" +#if !defined(MBEDTLS_PLATFORM_C) +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/arc4.h" +#include "mbedtls/asn1.h" +#include "mbedtls/asn1write.h" +#include "mbedtls/bignum.h" +#include "mbedtls/blowfish.h" +#include "mbedtls/camellia.h" +#include "mbedtls/chacha20.h" +#include "mbedtls/chachapoly.h" +#include "mbedtls/cipher.h" +#include "mbedtls/ccm.h" +#include "mbedtls/cmac.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/des.h" +#include "mbedtls/ecdh.h" +#include "mbedtls/ecp.h" +#include "mbedtls/entropy.h" +#include "mbedtls/error.h" +#include "mbedtls/gcm.h" +#include "mbedtls/md2.h" +#include "mbedtls/md4.h" +#include "mbedtls/md5.h" +#include "mbedtls/md.h" +#include "mbedtls/md_internal.h" +#include "mbedtls/pk.h" +#include "mbedtls/pk_internal.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" +#include "mbedtls/ripemd160.h" +#include "mbedtls/rsa.h" +#include "mbedtls/sha1.h" +#include "mbedtls/sha256.h" +#include "mbedtls/sha512.h" +#include "mbedtls/xtea.h" + +#define ARRAY_LENGTH( array ) ( sizeof( array ) / sizeof( *( array ) ) ) + +/* constant-time buffer comparison */ +static inline int safer_memcmp( const uint8_t *a, const uint8_t *b, size_t n ) +{ + size_t i; + unsigned char diff = 0; + + for( i = 0; i < n; i++ ) + diff |= a[i] ^ b[i]; + + return( diff ); +} + + + +/****************************************************************/ +/* Global data, support functions and library management */ +/****************************************************************/ + +static int key_type_is_raw_bytes( psa_key_type_t type ) +{ + return( PSA_KEY_TYPE_IS_UNSTRUCTURED( type ) ); +} + +/* Values for psa_global_data_t::rng_state */ +#define RNG_NOT_INITIALIZED 0 +#define RNG_INITIALIZED 1 +#define RNG_SEEDED 2 + +typedef struct +{ + void (* entropy_init )( mbedtls_entropy_context *ctx ); + void (* entropy_free )( mbedtls_entropy_context *ctx ); + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + unsigned initialized : 1; + unsigned rng_state : 2; +} psa_global_data_t; + +static psa_global_data_t global_data; + +#define GUARD_MODULE_INITIALIZED \ + if( global_data.initialized == 0 ) \ + return( PSA_ERROR_BAD_STATE ); + +psa_status_t mbedtls_to_psa_error( int ret ) +{ + /* If there's both a high-level code and low-level code, dispatch on + * the high-level code. */ + switch( ret < -0x7f ? - ( -ret & 0x7f80 ) : ret ) + { + case 0: + return( PSA_SUCCESS ); + + case MBEDTLS_ERR_AES_INVALID_KEY_LENGTH: + case MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH: + case MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE: + return( PSA_ERROR_NOT_SUPPORTED ); + case MBEDTLS_ERR_AES_HW_ACCEL_FAILED: + return( PSA_ERROR_HARDWARE_FAILURE ); + + case MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED: + return( PSA_ERROR_HARDWARE_FAILURE ); + + case MBEDTLS_ERR_ASN1_OUT_OF_DATA: + case MBEDTLS_ERR_ASN1_UNEXPECTED_TAG: + case MBEDTLS_ERR_ASN1_INVALID_LENGTH: + case MBEDTLS_ERR_ASN1_LENGTH_MISMATCH: + case MBEDTLS_ERR_ASN1_INVALID_DATA: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_ASN1_ALLOC_FAILED: + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + case MBEDTLS_ERR_ASN1_BUF_TOO_SMALL: + return( PSA_ERROR_BUFFER_TOO_SMALL ); + +#if defined(MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA) + case MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA: +#elif defined(MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH) + case MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH: +#endif + case MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH: + return( PSA_ERROR_NOT_SUPPORTED ); + case MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED: + return( PSA_ERROR_HARDWARE_FAILURE ); + +#if defined(MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA) + case MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA: +#elif defined(MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH) + case MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH: +#endif + case MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH: + return( PSA_ERROR_NOT_SUPPORTED ); + case MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED: + return( PSA_ERROR_HARDWARE_FAILURE ); + + case MBEDTLS_ERR_CCM_BAD_INPUT: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_CCM_AUTH_FAILED: + return( PSA_ERROR_INVALID_SIGNATURE ); + case MBEDTLS_ERR_CCM_HW_ACCEL_FAILED: + return( PSA_ERROR_HARDWARE_FAILURE ); + + case MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA: + return( PSA_ERROR_INVALID_ARGUMENT ); + + case MBEDTLS_ERR_CHACHAPOLY_BAD_STATE: + return( PSA_ERROR_BAD_STATE ); + case MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED: + return( PSA_ERROR_INVALID_SIGNATURE ); + + case MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE: + return( PSA_ERROR_NOT_SUPPORTED ); + case MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_CIPHER_ALLOC_FAILED: + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + case MBEDTLS_ERR_CIPHER_INVALID_PADDING: + return( PSA_ERROR_INVALID_PADDING ); + case MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_CIPHER_AUTH_FAILED: + return( PSA_ERROR_INVALID_SIGNATURE ); + case MBEDTLS_ERR_CIPHER_INVALID_CONTEXT: + return( PSA_ERROR_CORRUPTION_DETECTED ); + case MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED: + return( PSA_ERROR_HARDWARE_FAILURE ); + + case MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED: + return( PSA_ERROR_HARDWARE_FAILURE ); + + case MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED: + return( PSA_ERROR_INSUFFICIENT_ENTROPY ); + case MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG: + case MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG: + return( PSA_ERROR_NOT_SUPPORTED ); + case MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR: + return( PSA_ERROR_INSUFFICIENT_ENTROPY ); + + case MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH: + return( PSA_ERROR_NOT_SUPPORTED ); + case MBEDTLS_ERR_DES_HW_ACCEL_FAILED: + return( PSA_ERROR_HARDWARE_FAILURE ); + + case MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED: + case MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE: + case MBEDTLS_ERR_ENTROPY_SOURCE_FAILED: + return( PSA_ERROR_INSUFFICIENT_ENTROPY ); + + case MBEDTLS_ERR_GCM_AUTH_FAILED: + return( PSA_ERROR_INVALID_SIGNATURE ); + case MBEDTLS_ERR_GCM_BAD_INPUT: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_GCM_HW_ACCEL_FAILED: + return( PSA_ERROR_HARDWARE_FAILURE ); + + case MBEDTLS_ERR_MD2_HW_ACCEL_FAILED: + case MBEDTLS_ERR_MD4_HW_ACCEL_FAILED: + case MBEDTLS_ERR_MD5_HW_ACCEL_FAILED: + return( PSA_ERROR_HARDWARE_FAILURE ); + + case MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE: + return( PSA_ERROR_NOT_SUPPORTED ); + case MBEDTLS_ERR_MD_BAD_INPUT_DATA: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_MD_ALLOC_FAILED: + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + case MBEDTLS_ERR_MD_FILE_IO_ERROR: + return( PSA_ERROR_STORAGE_FAILURE ); + case MBEDTLS_ERR_MD_HW_ACCEL_FAILED: + return( PSA_ERROR_HARDWARE_FAILURE ); + + case MBEDTLS_ERR_MPI_FILE_IO_ERROR: + return( PSA_ERROR_STORAGE_FAILURE ); + case MBEDTLS_ERR_MPI_BAD_INPUT_DATA: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_MPI_INVALID_CHARACTER: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL: + return( PSA_ERROR_BUFFER_TOO_SMALL ); + case MBEDTLS_ERR_MPI_NEGATIVE_VALUE: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_MPI_DIVISION_BY_ZERO: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_MPI_ALLOC_FAILED: + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + + case MBEDTLS_ERR_PK_ALLOC_FAILED: + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + case MBEDTLS_ERR_PK_TYPE_MISMATCH: + case MBEDTLS_ERR_PK_BAD_INPUT_DATA: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_PK_FILE_IO_ERROR: + return( PSA_ERROR_STORAGE_FAILURE ); + case MBEDTLS_ERR_PK_KEY_INVALID_VERSION: + case MBEDTLS_ERR_PK_KEY_INVALID_FORMAT: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_PK_UNKNOWN_PK_ALG: + return( PSA_ERROR_NOT_SUPPORTED ); + case MBEDTLS_ERR_PK_PASSWORD_REQUIRED: + case MBEDTLS_ERR_PK_PASSWORD_MISMATCH: + return( PSA_ERROR_NOT_PERMITTED ); + case MBEDTLS_ERR_PK_INVALID_PUBKEY: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_PK_INVALID_ALG: + case MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE: + case MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE: + return( PSA_ERROR_NOT_SUPPORTED ); + case MBEDTLS_ERR_PK_SIG_LEN_MISMATCH: + return( PSA_ERROR_INVALID_SIGNATURE ); + case MBEDTLS_ERR_PK_HW_ACCEL_FAILED: + return( PSA_ERROR_HARDWARE_FAILURE ); + + case MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED: + return( PSA_ERROR_HARDWARE_FAILURE ); + case MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED: + return( PSA_ERROR_NOT_SUPPORTED ); + + case MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED: + return( PSA_ERROR_HARDWARE_FAILURE ); + + case MBEDTLS_ERR_RSA_BAD_INPUT_DATA: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_RSA_INVALID_PADDING: + return( PSA_ERROR_INVALID_PADDING ); + case MBEDTLS_ERR_RSA_KEY_GEN_FAILED: + return( PSA_ERROR_HARDWARE_FAILURE ); + case MBEDTLS_ERR_RSA_KEY_CHECK_FAILED: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_RSA_PUBLIC_FAILED: + case MBEDTLS_ERR_RSA_PRIVATE_FAILED: + return( PSA_ERROR_CORRUPTION_DETECTED ); + case MBEDTLS_ERR_RSA_VERIFY_FAILED: + return( PSA_ERROR_INVALID_SIGNATURE ); + case MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE: + return( PSA_ERROR_BUFFER_TOO_SMALL ); + case MBEDTLS_ERR_RSA_RNG_FAILED: + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + case MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION: + return( PSA_ERROR_NOT_SUPPORTED ); + case MBEDTLS_ERR_RSA_HW_ACCEL_FAILED: + return( PSA_ERROR_HARDWARE_FAILURE ); + + case MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED: + case MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED: + case MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED: + return( PSA_ERROR_HARDWARE_FAILURE ); + + case MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED: + return( PSA_ERROR_HARDWARE_FAILURE ); + + case MBEDTLS_ERR_ECP_BAD_INPUT_DATA: + case MBEDTLS_ERR_ECP_INVALID_KEY: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL: + return( PSA_ERROR_BUFFER_TOO_SMALL ); + case MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE: + return( PSA_ERROR_NOT_SUPPORTED ); + case MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH: + case MBEDTLS_ERR_ECP_VERIFY_FAILED: + return( PSA_ERROR_INVALID_SIGNATURE ); + case MBEDTLS_ERR_ECP_ALLOC_FAILED: + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + case MBEDTLS_ERR_ECP_HW_ACCEL_FAILED: + return( PSA_ERROR_HARDWARE_FAILURE ); + case MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED: + return( PSA_ERROR_CORRUPTION_DETECTED ); + + default: + return( PSA_ERROR_GENERIC_ERROR ); + } +} + + + + +/****************************************************************/ +/* Key management */ +/****************************************************************/ + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) +static inline int psa_key_slot_is_external( const psa_key_slot_t *slot ) +{ + return( psa_key_lifetime_is_external( slot->attr.lifetime ) ); +} +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + +#if defined(MBEDTLS_ECP_C) +mbedtls_ecp_group_id mbedtls_ecc_group_of_psa( psa_ecc_family_t curve, + size_t byte_length ) +{ + switch( curve ) + { + case PSA_ECC_FAMILY_SECP_R1: + switch( byte_length ) + { + case PSA_BITS_TO_BYTES( 192 ): + return( MBEDTLS_ECP_DP_SECP192R1 ); + case PSA_BITS_TO_BYTES( 224 ): + return( MBEDTLS_ECP_DP_SECP224R1 ); + case PSA_BITS_TO_BYTES( 256 ): + return( MBEDTLS_ECP_DP_SECP256R1 ); + case PSA_BITS_TO_BYTES( 384 ): + return( MBEDTLS_ECP_DP_SECP384R1 ); + case PSA_BITS_TO_BYTES( 521 ): + return( MBEDTLS_ECP_DP_SECP521R1 ); + default: + return( MBEDTLS_ECP_DP_NONE ); + } + break; + + case PSA_ECC_FAMILY_BRAINPOOL_P_R1: + switch( byte_length ) + { + case PSA_BITS_TO_BYTES( 256 ): + return( MBEDTLS_ECP_DP_BP256R1 ); + case PSA_BITS_TO_BYTES( 384 ): + return( MBEDTLS_ECP_DP_BP384R1 ); + case PSA_BITS_TO_BYTES( 512 ): + return( MBEDTLS_ECP_DP_BP512R1 ); + default: + return( MBEDTLS_ECP_DP_NONE ); + } + break; + + case PSA_ECC_FAMILY_MONTGOMERY: + switch( byte_length ) + { + case PSA_BITS_TO_BYTES( 255 ): + return( MBEDTLS_ECP_DP_CURVE25519 ); + case PSA_BITS_TO_BYTES( 448 ): + return( MBEDTLS_ECP_DP_CURVE448 ); + default: + return( MBEDTLS_ECP_DP_NONE ); + } + break; + + case PSA_ECC_FAMILY_SECP_K1: + switch( byte_length ) + { + case PSA_BITS_TO_BYTES( 192 ): + return( MBEDTLS_ECP_DP_SECP192K1 ); + case PSA_BITS_TO_BYTES( 224 ): + return( MBEDTLS_ECP_DP_SECP224K1 ); + case PSA_BITS_TO_BYTES( 256 ): + return( MBEDTLS_ECP_DP_SECP256K1 ); + default: + return( MBEDTLS_ECP_DP_NONE ); + } + break; + + default: + return( MBEDTLS_ECP_DP_NONE ); + } +} +#endif /* defined(MBEDTLS_ECP_C) */ + +static psa_status_t validate_unstructured_key_bit_size( psa_key_type_t type, + size_t bits ) +{ + /* Check that the bit size is acceptable for the key type */ + switch( type ) + { + case PSA_KEY_TYPE_RAW_DATA: +#if defined(MBEDTLS_MD_C) + case PSA_KEY_TYPE_HMAC: +#endif + case PSA_KEY_TYPE_DERIVE: + break; +#if defined(MBEDTLS_AES_C) + case PSA_KEY_TYPE_AES: + if( bits != 128 && bits != 192 && bits != 256 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + break; +#endif +#if defined(MBEDTLS_CAMELLIA_C) + case PSA_KEY_TYPE_CAMELLIA: + if( bits != 128 && bits != 192 && bits != 256 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + break; +#endif +#if defined(MBEDTLS_DES_C) + case PSA_KEY_TYPE_DES: + if( bits != 64 && bits != 128 && bits != 192 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + break; +#endif +#if defined(MBEDTLS_ARC4_C) + case PSA_KEY_TYPE_ARC4: + if( bits < 8 || bits > 2048 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + break; +#endif +#if defined(MBEDTLS_CHACHA20_C) + case PSA_KEY_TYPE_CHACHA20: + if( bits != 256 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + break; +#endif + default: + return( PSA_ERROR_NOT_SUPPORTED ); + } + if( bits % 8 != 0 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + return( PSA_SUCCESS ); +} + +#if defined(MBEDTLS_RSA_C) + +#if defined(MBEDTLS_PK_PARSE_C) +/* Mbed TLS doesn't support non-byte-aligned key sizes (i.e. key sizes + * that are not a multiple of 8) well. For example, there is only + * mbedtls_rsa_get_len(), which returns a number of bytes, and no + * way to return the exact bit size of a key. + * To keep things simple, reject non-byte-aligned key sizes. */ +static psa_status_t psa_check_rsa_key_byte_aligned( + const mbedtls_rsa_context *rsa ) +{ + mbedtls_mpi n; + psa_status_t status; + mbedtls_mpi_init( &n ); + status = mbedtls_to_psa_error( + mbedtls_rsa_export( rsa, &n, NULL, NULL, NULL, NULL ) ); + if( status == PSA_SUCCESS ) + { + if( mbedtls_mpi_bitlen( &n ) % 8 != 0 ) + status = PSA_ERROR_NOT_SUPPORTED; + } + mbedtls_mpi_free( &n ); + return( status ); +} +#endif /* MBEDTLS_PK_PARSE_C */ + +/** Load the contents of a key buffer into an internal RSA representation + * + * \param[in] type The type of key contained in \p data. + * \param[in] data The buffer from which to load the representation. + * \param[in] data_length The size in bytes of \p data. + * \param[out] p_rsa Returns a pointer to an RSA context on success. + * The caller is responsible for freeing both the + * contents of the context and the context itself + * when done. + */ +static psa_status_t psa_load_rsa_representation( psa_key_type_t type, + const uint8_t *data, + size_t data_length, + mbedtls_rsa_context **p_rsa ) +{ +#if defined(MBEDTLS_PK_PARSE_C) + psa_status_t status; + mbedtls_pk_context ctx; + size_t bits; + mbedtls_pk_init( &ctx ); + + /* Parse the data. */ + if( PSA_KEY_TYPE_IS_KEY_PAIR( type ) ) + status = mbedtls_to_psa_error( + mbedtls_pk_parse_key( &ctx, data, data_length, NULL, 0 ) ); + else + status = mbedtls_to_psa_error( + mbedtls_pk_parse_public_key( &ctx, data, data_length ) ); + if( status != PSA_SUCCESS ) + goto exit; + + /* We have something that the pkparse module recognizes. If it is a + * valid RSA key, store it. */ + if( mbedtls_pk_get_type( &ctx ) != MBEDTLS_PK_RSA ) + { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + /* The size of an RSA key doesn't have to be a multiple of 8. Mbed TLS + * supports non-byte-aligned key sizes, but not well. For example, + * mbedtls_rsa_get_len() returns the key size in bytes, not in bits. */ + bits = PSA_BYTES_TO_BITS( mbedtls_rsa_get_len( mbedtls_pk_rsa( ctx ) ) ); + if( bits > PSA_VENDOR_RSA_MAX_KEY_BITS ) + { + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } + status = psa_check_rsa_key_byte_aligned( mbedtls_pk_rsa( ctx ) ); + if( status != PSA_SUCCESS ) + goto exit; + + /* Copy out the pointer to the RSA context, and reset the PK context + * such that pk_free doesn't free the RSA context we just grabbed. */ + *p_rsa = mbedtls_pk_rsa( ctx ); + ctx.pk_info = NULL; + +exit: + mbedtls_pk_free( &ctx ); + return( status ); +#else + (void) data; + (void) data_length; + (void) type; + (void) rsa; + return( PSA_ERROR_NOT_SUPPORTED ); +#endif /* MBEDTLS_PK_PARSE_C */ +} + +/** Export an RSA key to export representation + * + * \param[in] type The type of key (public/private) to export + * \param[in] rsa The internal RSA representation from which to export + * \param[out] data The buffer to export to + * \param[in] data_size The length of the buffer to export to + * \param[out] data_length The amount of bytes written to \p data + */ +static psa_status_t psa_export_rsa_key( psa_key_type_t type, + mbedtls_rsa_context *rsa, + uint8_t *data, + size_t data_size, + size_t *data_length ) +{ +#if defined(MBEDTLS_PK_WRITE_C) + int ret; + mbedtls_pk_context pk; + uint8_t *pos = data + data_size; + + mbedtls_pk_init( &pk ); + pk.pk_info = &mbedtls_rsa_info; + pk.pk_ctx = rsa; + + /* PSA Crypto API defines the format of an RSA key as a DER-encoded + * representation of the non-encrypted PKCS#1 RSAPrivateKey for a + * private key and of the RFC3279 RSAPublicKey for a public key. */ + if( PSA_KEY_TYPE_IS_KEY_PAIR( type ) ) + ret = mbedtls_pk_write_key_der( &pk, data, data_size ); + else + ret = mbedtls_pk_write_pubkey( &pos, data, &pk ); + + if( ret < 0 ) + { + /* Clean up in case pk_write failed halfway through. */ + memset( data, 0, data_size ); + return( mbedtls_to_psa_error( ret ) ); + } + + /* The mbedtls_pk_xxx functions write to the end of the buffer. + * Move the data to the beginning and erase remaining data + * at the original location. */ + if( 2 * (size_t) ret <= data_size ) + { + memcpy( data, data + data_size - ret, ret ); + memset( data + data_size - ret, 0, ret ); + } + else if( (size_t) ret < data_size ) + { + memmove( data, data + data_size - ret, ret ); + memset( data + ret, 0, data_size - ret ); + } + + *data_length = ret; + return( PSA_SUCCESS ); +#else + (void) type; + (void) rsa; + (void) data; + (void) data_size; + (void) data_length; + return( PSA_ERROR_NOT_SUPPORTED ); +#endif /* MBEDTLS_PK_WRITE_C */ +} + +/** Import an RSA key from import representation to a slot + * + * \param[in,out] slot The slot where to store the export representation to + * \param[in] data The buffer containing the import representation + * \param[in] data_length The amount of bytes in \p data + */ +static psa_status_t psa_import_rsa_key( psa_key_slot_t *slot, + const uint8_t *data, + size_t data_length ) +{ + psa_status_t status; + uint8_t* output = NULL; + mbedtls_rsa_context *rsa = NULL; + + /* Parse input */ + status = psa_load_rsa_representation( slot->attr.type, + data, + data_length, + &rsa ); + if( status != PSA_SUCCESS ) + goto exit; + + slot->attr.bits = (psa_key_bits_t) PSA_BYTES_TO_BITS( + mbedtls_rsa_get_len( rsa ) ); + + /* Re-export the data to PSA export format, such that we can store export + * representation in the key slot. Export representation in case of RSA is + * the smallest representation that's allowed as input, so a straight-up + * allocation of the same size as the input buffer will be large enough. */ + output = mbedtls_calloc( 1, data_length ); + if( output == NULL ) + { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto exit; + } + + status = psa_export_rsa_key( slot->attr.type, + rsa, + output, + data_length, + &data_length); +exit: + /* Always free the RSA object */ + mbedtls_rsa_free( rsa ); + mbedtls_free( rsa ); + + /* Free the allocated buffer only on error. */ + if( status != PSA_SUCCESS ) + { + mbedtls_free( output ); + return( status ); + } + + /* On success, store the allocated export-formatted key. */ + slot->data.key.data = output; + slot->data.key.bytes = data_length; + + return( PSA_SUCCESS ); +} +#endif /* defined(MBEDTLS_RSA_C) */ + +#if defined(MBEDTLS_ECP_C) +/** Load the contents of a key buffer into an internal ECP representation + * + * \param[in] type The type of key contained in \p data. + * \param[in] data The buffer from which to load the representation. + * \param[in] data_length The size in bytes of \p data. + * \param[out] p_ecp Returns a pointer to an ECP context on success. + * The caller is responsible for freeing both the + * contents of the context and the context itself + * when done. + */ +static psa_status_t psa_load_ecp_representation( psa_key_type_t type, + const uint8_t *data, + size_t data_length, + mbedtls_ecp_keypair **p_ecp ) +{ + mbedtls_ecp_group_id grp_id = MBEDTLS_ECP_DP_NONE; + psa_status_t status; + mbedtls_ecp_keypair *ecp = NULL; + size_t curve_size = data_length; + + if( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) && + PSA_KEY_TYPE_ECC_GET_FAMILY( type ) != PSA_ECC_FAMILY_MONTGOMERY ) + { + /* A Weierstrass public key is represented as: + * - The byte 0x04; + * - `x_P` as a `ceiling(m/8)`-byte string, big-endian; + * - `y_P` as a `ceiling(m/8)`-byte string, big-endian. + * So its data length is 2m+1 where m is the curve size in bits. + */ + if( ( data_length & 1 ) == 0 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + curve_size = data_length / 2; + + /* Montgomery public keys are represented in compressed format, meaning + * their curve_size is equal to the amount of input. */ + + /* Private keys are represented in uncompressed private random integer + * format, meaning their curve_size is equal to the amount of input. */ + } + + /* Allocate and initialize a key representation. */ + ecp = mbedtls_calloc( 1, sizeof( mbedtls_ecp_keypair ) ); + if( ecp == NULL ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + mbedtls_ecp_keypair_init( ecp ); + + /* Load the group. */ + grp_id = mbedtls_ecc_group_of_psa( PSA_KEY_TYPE_ECC_GET_FAMILY( type ), + curve_size ); + if( grp_id == MBEDTLS_ECP_DP_NONE ) + { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + status = mbedtls_to_psa_error( + mbedtls_ecp_group_load( &ecp->grp, grp_id ) ); + if( status != PSA_SUCCESS ) + goto exit; + + /* Load the key material. */ + if( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) ) + { + /* Load the public value. */ + status = mbedtls_to_psa_error( + mbedtls_ecp_point_read_binary( &ecp->grp, &ecp->Q, + data, + data_length ) ); + if( status != PSA_SUCCESS ) + goto exit; + + /* Check that the point is on the curve. */ + status = mbedtls_to_psa_error( + mbedtls_ecp_check_pubkey( &ecp->grp, &ecp->Q ) ); + if( status != PSA_SUCCESS ) + goto exit; + } + else + { + /* Load and validate the secret value. */ + status = mbedtls_to_psa_error( + mbedtls_ecp_read_key( ecp->grp.id, + ecp, + data, + data_length ) ); + if( status != PSA_SUCCESS ) + goto exit; + } + + *p_ecp = ecp; +exit: + if( status != PSA_SUCCESS ) + { + mbedtls_ecp_keypair_free( ecp ); + mbedtls_free( ecp ); + } + + return( status ); +} + +/** Export an ECP key to export representation + * + * \param[in] type The type of key (public/private) to export + * \param[in] ecp The internal ECP representation from which to export + * \param[out] data The buffer to export to + * \param[in] data_size The length of the buffer to export to + * \param[out] data_length The amount of bytes written to \p data + */ +static psa_status_t psa_export_ecp_key( psa_key_type_t type, + mbedtls_ecp_keypair *ecp, + uint8_t *data, + size_t data_size, + size_t *data_length ) +{ + psa_status_t status; + + if( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) ) + { + /* Check whether the public part is loaded */ + if( mbedtls_ecp_is_zero( &ecp->Q ) ) + { + /* Calculate the public key */ + status = mbedtls_to_psa_error( + mbedtls_ecp_mul( &ecp->grp, &ecp->Q, &ecp->d, &ecp->grp.G, + mbedtls_ctr_drbg_random, &global_data.ctr_drbg ) ); + if( status != PSA_SUCCESS ) + return( status ); + } + + status = mbedtls_to_psa_error( + mbedtls_ecp_point_write_binary( &ecp->grp, &ecp->Q, + MBEDTLS_ECP_PF_UNCOMPRESSED, + data_length, + data, + data_size ) ); + if( status != PSA_SUCCESS ) + memset( data, 0, data_size ); + + return( status ); + } + else + { + if( data_size < PSA_BITS_TO_BYTES( ecp->grp.nbits ) ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); + + status = mbedtls_to_psa_error( + mbedtls_ecp_write_key( ecp, + data, + PSA_BITS_TO_BYTES( ecp->grp.nbits ) ) ); + if( status == PSA_SUCCESS ) + *data_length = PSA_BITS_TO_BYTES( ecp->grp.nbits ); + else + memset( data, 0, data_size ); + + return( status ); + } +} + +/** Import an ECP key from import representation to a slot + * + * \param[in,out] slot The slot where to store the export representation to + * \param[in] data The buffer containing the import representation + * \param[in] data_length The amount of bytes in \p data + */ +static psa_status_t psa_import_ecp_key( psa_key_slot_t *slot, + const uint8_t *data, + size_t data_length ) +{ + psa_status_t status; + uint8_t* output = NULL; + mbedtls_ecp_keypair *ecp = NULL; + + /* Parse input */ + status = psa_load_ecp_representation( slot->attr.type, + data, + data_length, + &ecp ); + if( status != PSA_SUCCESS ) + goto exit; + + if( PSA_KEY_TYPE_ECC_GET_FAMILY( slot->attr.type ) == PSA_ECC_FAMILY_MONTGOMERY) + slot->attr.bits = (psa_key_bits_t) ecp->grp.nbits + 1; + else + slot->attr.bits = (psa_key_bits_t) ecp->grp.nbits; + + /* Re-export the data to PSA export format. There is currently no support + * for other input formats then the export format, so this is a 1-1 + * copy operation. */ + output = mbedtls_calloc( 1, data_length ); + if( output == NULL ) + { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto exit; + } + + status = psa_export_ecp_key( slot->attr.type, + ecp, + output, + data_length, + &data_length); +exit: + /* Always free the PK object (will also free contained ECP context) */ + mbedtls_ecp_keypair_free( ecp ); + mbedtls_free( ecp ); + + /* Free the allocated buffer only on error. */ + if( status != PSA_SUCCESS ) + { + mbedtls_free( output ); + return( status ); + } + + /* On success, store the allocated export-formatted key. */ + slot->data.key.data = output; + slot->data.key.bytes = data_length; + + return( PSA_SUCCESS ); +} +#endif /* defined(MBEDTLS_ECP_C) */ + +/** Return the size of the key in the given slot, in bits. + * + * \param[in] slot A key slot. + * + * \return The key size in bits, read from the metadata in the slot. + */ +static inline size_t psa_get_key_slot_bits( const psa_key_slot_t *slot ) +{ + return( slot->attr.bits ); +} + +/** Try to allocate a buffer to an empty key slot. + * + * \param[in,out] slot Key slot to attach buffer to. + * \param[in] buffer_length Requested size of the buffer. + * + * \retval #PSA_SUCCESS + * The buffer has been successfully allocated. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * Not enough memory was available for allocation. + * \retval #PSA_ERROR_ALREADY_EXISTS + * Trying to allocate a buffer to a non-empty key slot. + */ +static psa_status_t psa_allocate_buffer_to_slot( psa_key_slot_t *slot, + size_t buffer_length ) +{ + if( slot->data.key.data != NULL ) + return( PSA_ERROR_ALREADY_EXISTS ); + + slot->data.key.data = mbedtls_calloc( 1, buffer_length ); + if( slot->data.key.data == NULL ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + + slot->data.key.bytes = buffer_length; + return( PSA_SUCCESS ); +} + +psa_status_t psa_copy_key_material_into_slot( psa_key_slot_t *slot, + const uint8_t* data, + size_t data_length ) +{ + psa_status_t status = psa_allocate_buffer_to_slot( slot, + data_length ); + if( status != PSA_SUCCESS ) + return( status ); + + memcpy( slot->data.key.data, data, data_length ); + return( PSA_SUCCESS ); +} + +/** Import key data into a slot. + * + * `slot->type` must have been set previously. + * This function assumes that the slot does not contain any key material yet. + * On failure, the slot content is unchanged. + * + * Persistent storage is not affected. + * + * \param[in,out] slot The key slot to import data into. + * Its `type` field must have previously been set to + * the desired key type. + * It must not contain any key material yet. + * \param[in] data Buffer containing the key material to parse and import. + * \param data_length Size of \p data in bytes. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + */ +static psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot, + const uint8_t *data, + size_t data_length ) +{ + psa_status_t status = PSA_SUCCESS; + size_t bit_size; + + /* zero-length keys are never supported. */ + if( data_length == 0 ) + return( PSA_ERROR_NOT_SUPPORTED ); + + if( key_type_is_raw_bytes( slot->attr.type ) ) + { + bit_size = PSA_BYTES_TO_BITS( data_length ); + + /* Ensure that the bytes-to-bits conversion hasn't overflown. */ + if( data_length > SIZE_MAX / 8 ) + return( PSA_ERROR_NOT_SUPPORTED ); + + /* Enforce a size limit, and in particular ensure that the bit + * size fits in its representation type. */ + if( bit_size > PSA_MAX_KEY_BITS ) + return( PSA_ERROR_NOT_SUPPORTED ); + + status = validate_unstructured_key_bit_size( slot->attr.type, bit_size ); + if( status != PSA_SUCCESS ) + return( status ); + + /* Allocate memory for the key */ + status = psa_copy_key_material_into_slot( slot, data, data_length ); + if( status != PSA_SUCCESS ) + return( status ); + + /* Write the actual key size to the slot. + * psa_start_key_creation() wrote the size declared by the + * caller, which may be 0 (meaning unspecified) or wrong. */ + slot->attr.bits = (psa_key_bits_t) bit_size; + + return( PSA_SUCCESS ); + } + else if( PSA_KEY_TYPE_IS_ASYMMETRIC( slot->attr.type ) ) + { + /* Try validation through accelerators first. */ + bit_size = slot->attr.bits; + psa_key_attributes_t attributes = { + .core = slot->attr + }; + status = psa_driver_wrapper_validate_key( &attributes, + data, + data_length, + &bit_size ); + if( status == PSA_SUCCESS ) + { + /* Key has been validated successfully by an accelerator. + * Copy key material into slot. */ + status = psa_copy_key_material_into_slot( slot, data, data_length ); + if( status != PSA_SUCCESS ) + return( status ); + + slot->attr.bits = (psa_key_bits_t) bit_size; + return( PSA_SUCCESS ); + } + else if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); + + /* Key format is not supported by any accelerator, try software fallback + * if present. */ +#if defined(MBEDTLS_ECP_C) + if( PSA_KEY_TYPE_IS_ECC( slot->attr.type ) ) + { + return( psa_import_ecp_key( slot, data, data_length ) ); + } +#endif /* defined(MBEDTLS_ECP_C) */ +#if defined(MBEDTLS_RSA_C) + if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) ) + { + return( psa_import_rsa_key( slot, data, data_length ) ); + } +#endif /* defined(MBEDTLS_RSA_C) */ + + /* Fell through the fallback as well, so have nothing else to try. */ + return( PSA_ERROR_NOT_SUPPORTED ); + } + else + { + /* Unknown key type */ + return( PSA_ERROR_NOT_SUPPORTED ); + } +} + +/** Calculate the intersection of two algorithm usage policies. + * + * Return 0 (which allows no operation) on incompatibility. + */ +static psa_algorithm_t psa_key_policy_algorithm_intersection( + psa_algorithm_t alg1, + psa_algorithm_t alg2 ) +{ + /* Common case: both sides actually specify the same policy. */ + if( alg1 == alg2 ) + return( alg1 ); + /* If the policies are from the same hash-and-sign family, check + * if one is a wildcard. If so the other has the specific algorithm. */ + if( PSA_ALG_IS_HASH_AND_SIGN( alg1 ) && + PSA_ALG_IS_HASH_AND_SIGN( alg2 ) && + ( alg1 & ~PSA_ALG_HASH_MASK ) == ( alg2 & ~PSA_ALG_HASH_MASK ) ) + { + if( PSA_ALG_SIGN_GET_HASH( alg1 ) == PSA_ALG_ANY_HASH ) + return( alg2 ); + if( PSA_ALG_SIGN_GET_HASH( alg2 ) == PSA_ALG_ANY_HASH ) + return( alg1 ); + } + /* If the policies are incompatible, allow nothing. */ + return( 0 ); +} + +static int psa_key_algorithm_permits( psa_algorithm_t policy_alg, + psa_algorithm_t requested_alg ) +{ + /* Common case: the policy only allows requested_alg. */ + if( requested_alg == policy_alg ) + return( 1 ); + /* If policy_alg is a hash-and-sign with a wildcard for the hash, + * and requested_alg is the same hash-and-sign family with any hash, + * then requested_alg is compliant with policy_alg. */ + if( PSA_ALG_IS_HASH_AND_SIGN( requested_alg ) && + PSA_ALG_SIGN_GET_HASH( policy_alg ) == PSA_ALG_ANY_HASH ) + { + return( ( policy_alg & ~PSA_ALG_HASH_MASK ) == + ( requested_alg & ~PSA_ALG_HASH_MASK ) ); + } + /* If policy_alg is a generic key agreement operation, then using it for + * a key derivation with that key agreement should also be allowed. This + * behaviour is expected to be defined in a future specification version. */ + if( PSA_ALG_IS_RAW_KEY_AGREEMENT( policy_alg ) && + PSA_ALG_IS_KEY_AGREEMENT( requested_alg ) ) + { + return( PSA_ALG_KEY_AGREEMENT_GET_BASE( requested_alg ) == + policy_alg ); + } + /* If it isn't permitted, it's forbidden. */ + return( 0 ); +} + +/** Test whether a policy permits an algorithm. + * + * The caller must test usage flags separately. + */ +static int psa_key_policy_permits( const psa_key_policy_t *policy, + psa_algorithm_t alg ) +{ + return( psa_key_algorithm_permits( policy->alg, alg ) || + psa_key_algorithm_permits( policy->alg2, alg ) ); +} + +/** Restrict a key policy based on a constraint. + * + * \param[in,out] policy The policy to restrict. + * \param[in] constraint The policy constraint to apply. + * + * \retval #PSA_SUCCESS + * \c *policy contains the intersection of the original value of + * \c *policy and \c *constraint. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c *policy and \c *constraint are incompatible. + * \c *policy is unchanged. + */ +static psa_status_t psa_restrict_key_policy( + psa_key_policy_t *policy, + const psa_key_policy_t *constraint ) +{ + psa_algorithm_t intersection_alg = + psa_key_policy_algorithm_intersection( policy->alg, constraint->alg ); + psa_algorithm_t intersection_alg2 = + psa_key_policy_algorithm_intersection( policy->alg2, constraint->alg2 ); + if( intersection_alg == 0 && policy->alg != 0 && constraint->alg != 0 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + if( intersection_alg2 == 0 && policy->alg2 != 0 && constraint->alg2 != 0 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + policy->usage &= constraint->usage; + policy->alg = intersection_alg; + policy->alg2 = intersection_alg2; + return( PSA_SUCCESS ); +} + +/** Retrieve a slot which must contain a key. The key must have allow all the + * usage flags set in \p usage. If \p alg is nonzero, the key must allow + * operations with this algorithm. */ +static psa_status_t psa_get_key_from_slot( psa_key_handle_t handle, + psa_key_slot_t **p_slot, + psa_key_usage_t usage, + psa_algorithm_t alg ) +{ + psa_status_t status; + psa_key_slot_t *slot = NULL; + + *p_slot = NULL; + + status = psa_get_key_slot( handle, &slot ); + if( status != PSA_SUCCESS ) + return( status ); + + /* Enforce that usage policy for the key slot contains all the flags + * required by the usage parameter. There is one exception: public + * keys can always be exported, so we treat public key objects as + * if they had the export flag. */ + if( PSA_KEY_TYPE_IS_PUBLIC_KEY( slot->attr.type ) ) + usage &= ~PSA_KEY_USAGE_EXPORT; + if( ( slot->attr.policy.usage & usage ) != usage ) + return( PSA_ERROR_NOT_PERMITTED ); + + /* Enforce that the usage policy permits the requested algortihm. */ + if( alg != 0 && ! psa_key_policy_permits( &slot->attr.policy, alg ) ) + return( PSA_ERROR_NOT_PERMITTED ); + + *p_slot = slot; + return( PSA_SUCCESS ); +} + +/** Retrieve a slot which must contain a transparent key. + * + * A transparent key is a key for which the key material is directly + * available, as opposed to a key in a secure element. + * + * This is a temporary function to use instead of psa_get_key_from_slot() + * until secure element support is fully implemented. + */ +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) +static psa_status_t psa_get_transparent_key( psa_key_handle_t handle, + psa_key_slot_t **p_slot, + psa_key_usage_t usage, + psa_algorithm_t alg ) +{ + psa_status_t status = psa_get_key_from_slot( handle, p_slot, usage, alg ); + if( status != PSA_SUCCESS ) + return( status ); + if( psa_key_slot_is_external( *p_slot ) ) + { + *p_slot = NULL; + return( PSA_ERROR_NOT_SUPPORTED ); + } + return( PSA_SUCCESS ); +} +#else /* MBEDTLS_PSA_CRYPTO_SE_C */ +/* With no secure element support, all keys are transparent. */ +#define psa_get_transparent_key( handle, p_slot, usage, alg ) \ + psa_get_key_from_slot( handle, p_slot, usage, alg ) +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + +/** Wipe key data from a slot. Preserve metadata such as the policy. */ +static psa_status_t psa_remove_key_data_from_memory( psa_key_slot_t *slot ) +{ +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + if( psa_key_slot_is_external( slot ) ) + { + /* No key material to clean. */ + } + else +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + { + /* Data pointer will always be either a valid pointer or NULL in an + * initialized slot, so we can just free it. */ + if( slot->data.key.data != NULL ) + mbedtls_platform_zeroize( slot->data.key.data, slot->data.key.bytes); + mbedtls_free( slot->data.key.data ); + slot->data.key.data = NULL; + slot->data.key.bytes = 0; + } + + return( PSA_SUCCESS ); +} + +/** Completely wipe a slot in memory, including its policy. + * Persistent storage is not affected. */ +psa_status_t psa_wipe_key_slot( psa_key_slot_t *slot ) +{ + psa_status_t status = psa_remove_key_data_from_memory( slot ); + /* Multipart operations may still be using the key. This is safe + * because all multipart operation objects are independent from + * the key slot: if they need to access the key after the setup + * phase, they have a copy of the key. Note that this means that + * key material can linger until all operations are completed. */ + /* At this point, key material and other type-specific content has + * been wiped. Clear remaining metadata. We can call memset and not + * zeroize because the metadata is not particularly sensitive. */ + memset( slot, 0, sizeof( *slot ) ); + return( status ); +} + +psa_status_t psa_destroy_key( psa_key_handle_t handle ) +{ + psa_key_slot_t *slot; + psa_status_t status; /* status of the last operation */ + psa_status_t overall_status = PSA_SUCCESS; +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + psa_se_drv_table_entry_t *driver; +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + + if( handle == 0 ) + return( PSA_SUCCESS ); + + status = psa_get_key_slot( handle, &slot ); + if( status != PSA_SUCCESS ) + return( status ); + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + driver = psa_get_se_driver_entry( slot->attr.lifetime ); + if( driver != NULL ) + { + /* For a key in a secure element, we need to do three things: + * remove the key file in internal storage, destroy the + * key inside the secure element, and update the driver's + * persistent data. Start a transaction that will encompass these + * three actions. */ + psa_crypto_prepare_transaction( PSA_CRYPTO_TRANSACTION_DESTROY_KEY ); + psa_crypto_transaction.key.lifetime = slot->attr.lifetime; + psa_crypto_transaction.key.slot = slot->data.se.slot_number; + psa_crypto_transaction.key.id = slot->attr.id; + status = psa_crypto_save_transaction( ); + if( status != PSA_SUCCESS ) + { + (void) psa_crypto_stop_transaction( ); + /* We should still try to destroy the key in the secure + * element and the key metadata in storage. This is especially + * important if the error is that the storage is full. + * But how to do it exactly without risking an inconsistent + * state after a reset? + * https://github.com/ARMmbed/mbed-crypto/issues/215 + */ + overall_status = status; + goto exit; + } + + status = psa_destroy_se_key( driver, slot->data.se.slot_number ); + if( overall_status == PSA_SUCCESS ) + overall_status = status; + } +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + +#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) + if( slot->attr.lifetime != PSA_KEY_LIFETIME_VOLATILE ) + { + status = psa_destroy_persistent_key( slot->attr.id ); + if( overall_status == PSA_SUCCESS ) + overall_status = status; + + /* TODO: other slots may have a copy of the same key. We should + * invalidate them. + * https://github.com/ARMmbed/mbed-crypto/issues/214 + */ + } +#endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + if( driver != NULL ) + { + status = psa_save_se_persistent_data( driver ); + if( overall_status == PSA_SUCCESS ) + overall_status = status; + status = psa_crypto_stop_transaction( ); + if( overall_status == PSA_SUCCESS ) + overall_status = status; + } +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) +exit: +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + status = psa_wipe_key_slot( slot ); + /* Prioritize CORRUPTION_DETECTED from wiping over a storage error */ + if( overall_status == PSA_SUCCESS ) + overall_status = status; + return( overall_status ); +} + +void psa_reset_key_attributes( psa_key_attributes_t *attributes ) +{ + mbedtls_free( attributes->domain_parameters ); + memset( attributes, 0, sizeof( *attributes ) ); +} + +psa_status_t psa_set_key_domain_parameters( psa_key_attributes_t *attributes, + psa_key_type_t type, + const uint8_t *data, + size_t data_length ) +{ + uint8_t *copy = NULL; + + if( data_length != 0 ) + { + copy = mbedtls_calloc( 1, data_length ); + if( copy == NULL ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + memcpy( copy, data, data_length ); + } + /* After this point, this function is guaranteed to succeed, so it + * can start modifying `*attributes`. */ + + if( attributes->domain_parameters != NULL ) + { + mbedtls_free( attributes->domain_parameters ); + attributes->domain_parameters = NULL; + attributes->domain_parameters_size = 0; + } + + attributes->domain_parameters = copy; + attributes->domain_parameters_size = data_length; + attributes->core.type = type; + return( PSA_SUCCESS ); +} + +psa_status_t psa_get_key_domain_parameters( + const psa_key_attributes_t *attributes, + uint8_t *data, size_t data_size, size_t *data_length ) +{ + if( attributes->domain_parameters_size > data_size ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); + *data_length = attributes->domain_parameters_size; + if( attributes->domain_parameters_size != 0 ) + memcpy( data, attributes->domain_parameters, + attributes->domain_parameters_size ); + return( PSA_SUCCESS ); +} + +#if defined(MBEDTLS_RSA_C) +static psa_status_t psa_get_rsa_public_exponent( + const mbedtls_rsa_context *rsa, + psa_key_attributes_t *attributes ) +{ + mbedtls_mpi mpi; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + uint8_t *buffer = NULL; + size_t buflen; + mbedtls_mpi_init( &mpi ); + + ret = mbedtls_rsa_export( rsa, NULL, NULL, NULL, NULL, &mpi ); + if( ret != 0 ) + goto exit; + if( mbedtls_mpi_cmp_int( &mpi, 65537 ) == 0 ) + { + /* It's the default value, which is reported as an empty string, + * so there's nothing to do. */ + goto exit; + } + + buflen = mbedtls_mpi_size( &mpi ); + buffer = mbedtls_calloc( 1, buflen ); + if( buffer == NULL ) + { + ret = MBEDTLS_ERR_MPI_ALLOC_FAILED; + goto exit; + } + ret = mbedtls_mpi_write_binary( &mpi, buffer, buflen ); + if( ret != 0 ) + goto exit; + attributes->domain_parameters = buffer; + attributes->domain_parameters_size = buflen; + +exit: + mbedtls_mpi_free( &mpi ); + if( ret != 0 ) + mbedtls_free( buffer ); + return( mbedtls_to_psa_error( ret ) ); +} +#endif /* MBEDTLS_RSA_C */ + +/** Retrieve all the publicly-accessible attributes of a key. + */ +psa_status_t psa_get_key_attributes( psa_key_handle_t handle, + psa_key_attributes_t *attributes ) +{ + psa_key_slot_t *slot; + psa_status_t status; + + psa_reset_key_attributes( attributes ); + + status = psa_get_key_from_slot( handle, &slot, 0, 0 ); + if( status != PSA_SUCCESS ) + return( status ); + + attributes->core = slot->attr; + attributes->core.flags &= ( MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY | + MBEDTLS_PSA_KA_MASK_DUAL_USE ); + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + if( psa_key_slot_is_external( slot ) ) + psa_set_key_slot_number( attributes, slot->data.se.slot_number ); +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + + switch( slot->attr.type ) + { +#if defined(MBEDTLS_RSA_C) + case PSA_KEY_TYPE_RSA_KEY_PAIR: + case PSA_KEY_TYPE_RSA_PUBLIC_KEY: +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + /* TODO: reporting the public exponent for opaque keys + * is not yet implemented. + * https://github.com/ARMmbed/mbed-crypto/issues/216 + */ + if( psa_key_slot_is_external( slot ) ) + break; +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + { + mbedtls_rsa_context *rsa = NULL; + + status = psa_load_rsa_representation( slot->attr.type, + slot->data.key.data, + slot->data.key.bytes, + &rsa ); + if( status != PSA_SUCCESS ) + break; + + status = psa_get_rsa_public_exponent( rsa, + attributes ); + mbedtls_rsa_free( rsa ); + mbedtls_free( rsa ); + } + break; +#endif /* MBEDTLS_RSA_C */ + default: + /* Nothing else to do. */ + break; + } + + if( status != PSA_SUCCESS ) + psa_reset_key_attributes( attributes ); + return( status ); +} + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) +psa_status_t psa_get_key_slot_number( + const psa_key_attributes_t *attributes, + psa_key_slot_number_t *slot_number ) +{ + if( attributes->core.flags & MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER ) + { + *slot_number = attributes->slot_number; + return( PSA_SUCCESS ); + } + else + return( PSA_ERROR_INVALID_ARGUMENT ); +} +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + +static psa_status_t psa_internal_export_key_buffer( const psa_key_slot_t *slot, + uint8_t *data, + size_t data_size, + size_t *data_length ) +{ + if( slot->data.key.bytes > data_size ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); + memcpy( data, slot->data.key.data, slot->data.key.bytes ); + memset( data + slot->data.key.bytes, 0, + data_size - slot->data.key.bytes ); + *data_length = slot->data.key.bytes; + return( PSA_SUCCESS ); +} + +static psa_status_t psa_internal_export_key( const psa_key_slot_t *slot, + uint8_t *data, + size_t data_size, + size_t *data_length, + int export_public_key ) +{ +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + const psa_drv_se_t *drv; + psa_drv_se_context_t *drv_context; +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + + *data_length = 0; + + if( export_public_key && ! PSA_KEY_TYPE_IS_ASYMMETRIC( slot->attr.type ) ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + /* Reject a zero-length output buffer now, since this can never be a + * valid key representation. This way we know that data must be a valid + * pointer and we can do things like memset(data, ..., data_size). */ + if( data_size == 0 ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + if( psa_get_se_driver( slot->attr.lifetime, &drv, &drv_context ) ) + { + psa_drv_se_export_key_t method; + if( drv->key_management == NULL ) + return( PSA_ERROR_NOT_SUPPORTED ); + method = ( export_public_key ? + drv->key_management->p_export_public : + drv->key_management->p_export ); + if( method == NULL ) + return( PSA_ERROR_NOT_SUPPORTED ); + return( method( drv_context, + slot->data.se.slot_number, + data, data_size, data_length ) ); + } +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + + if( key_type_is_raw_bytes( slot->attr.type ) ) + { + return( psa_internal_export_key_buffer( slot, data, data_size, data_length ) ); + } + else if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) || + PSA_KEY_TYPE_IS_ECC( slot->attr.type ) ) + { + if( PSA_KEY_TYPE_IS_PUBLIC_KEY( slot->attr.type ) ) + { + /* Exporting public -> public */ + return( psa_internal_export_key_buffer( slot, data, data_size, data_length ) ); + } + else if( !export_public_key ) + { + /* Exporting private -> private */ + return( psa_internal_export_key_buffer( slot, data, data_size, data_length ) ); + } + /* Need to export the public part of a private key, + * so conversion is needed */ + if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) ) + { +#if defined(MBEDTLS_RSA_C) + mbedtls_rsa_context *rsa = NULL; + psa_status_t status = psa_load_rsa_representation( + slot->attr.type, + slot->data.key.data, + slot->data.key.bytes, + &rsa ); + if( status != PSA_SUCCESS ) + return( status ); + + status = psa_export_rsa_key( PSA_KEY_TYPE_RSA_PUBLIC_KEY, + rsa, + data, + data_size, + data_length ); + + mbedtls_rsa_free( rsa ); + mbedtls_free( rsa ); + + return( status ); +#else + /* We don't know how to convert a private RSA key to public. */ + return( PSA_ERROR_NOT_SUPPORTED ); +#endif + } + else + { +#if defined(MBEDTLS_ECP_C) + mbedtls_ecp_keypair *ecp = NULL; + psa_status_t status = psa_load_ecp_representation( + slot->attr.type, + slot->data.key.data, + slot->data.key.bytes, + &ecp ); + if( status != PSA_SUCCESS ) + return( status ); + + status = psa_export_ecp_key( PSA_KEY_TYPE_ECC_PUBLIC_KEY( + PSA_KEY_TYPE_ECC_GET_FAMILY( + slot->attr.type ) ), + ecp, + data, + data_size, + data_length ); + + mbedtls_ecp_keypair_free( ecp ); + mbedtls_free( ecp ); + return( status ); +#else + /* We don't know how to convert a private ECC key to public */ + return( PSA_ERROR_NOT_SUPPORTED ); +#endif + } + } + else + { + /* This shouldn't happen in the reference implementation, but + it is valid for a special-purpose implementation to omit + support for exporting certain key types. */ + return( PSA_ERROR_NOT_SUPPORTED ); + } +} + +psa_status_t psa_export_key( psa_key_handle_t handle, + uint8_t *data, + size_t data_size, + size_t *data_length ) +{ + psa_key_slot_t *slot; + psa_status_t status; + + /* Set the key to empty now, so that even when there are errors, we always + * set data_length to a value between 0 and data_size. On error, setting + * the key to empty is a good choice because an empty key representation is + * unlikely to be accepted anywhere. */ + *data_length = 0; + + /* Export requires the EXPORT flag. There is an exception for public keys, + * which don't require any flag, but psa_get_key_from_slot takes + * care of this. */ + status = psa_get_key_from_slot( handle, &slot, PSA_KEY_USAGE_EXPORT, 0 ); + if( status != PSA_SUCCESS ) + return( status ); + return( psa_internal_export_key( slot, data, data_size, + data_length, 0 ) ); +} + +psa_status_t psa_export_public_key( psa_key_handle_t handle, + uint8_t *data, + size_t data_size, + size_t *data_length ) +{ + psa_key_slot_t *slot; + psa_status_t status; + + /* Set the key to empty now, so that even when there are errors, we always + * set data_length to a value between 0 and data_size. On error, setting + * the key to empty is a good choice because an empty key representation is + * unlikely to be accepted anywhere. */ + *data_length = 0; + + /* Exporting a public key doesn't require a usage flag. */ + status = psa_get_key_from_slot( handle, &slot, 0, 0 ); + if( status != PSA_SUCCESS ) + return( status ); + return( psa_internal_export_key( slot, data, data_size, + data_length, 1 ) ); +} + +#if defined(static_assert) +static_assert( ( MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY & MBEDTLS_PSA_KA_MASK_DUAL_USE ) == 0, + "One or more key attribute flag is listed as both external-only and dual-use" ); +static_assert( ( PSA_KA_MASK_INTERNAL_ONLY & MBEDTLS_PSA_KA_MASK_DUAL_USE ) == 0, + "One or more key attribute flag is listed as both internal-only and dual-use" ); +static_assert( ( PSA_KA_MASK_INTERNAL_ONLY & MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY ) == 0, + "One or more key attribute flag is listed as both internal-only and external-only" ); +#endif + +/** Validate that a key policy is internally well-formed. + * + * This function only rejects invalid policies. It does not validate the + * consistency of the policy with respect to other attributes of the key + * such as the key type. + */ +static psa_status_t psa_validate_key_policy( const psa_key_policy_t *policy ) +{ + if( ( policy->usage & ~( PSA_KEY_USAGE_EXPORT | + PSA_KEY_USAGE_COPY | + PSA_KEY_USAGE_ENCRYPT | + PSA_KEY_USAGE_DECRYPT | + PSA_KEY_USAGE_SIGN_HASH | + PSA_KEY_USAGE_VERIFY_HASH | + PSA_KEY_USAGE_DERIVE ) ) != 0 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + return( PSA_SUCCESS ); +} + +/** Validate the internal consistency of key attributes. + * + * This function only rejects invalid attribute values. If does not + * validate the consistency of the attributes with any key data that may + * be involved in the creation of the key. + * + * Call this function early in the key creation process. + * + * \param[in] attributes Key attributes for the new key. + * \param[out] p_drv On any return, the driver for the key, if any. + * NULL for a transparent key. + * + */ +static psa_status_t psa_validate_key_attributes( + const psa_key_attributes_t *attributes, + psa_se_drv_table_entry_t **p_drv ) +{ + psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; + + status = psa_validate_key_location( psa_get_key_lifetime( attributes ), + p_drv ); + if( status != PSA_SUCCESS ) + return( status ); + + status = psa_validate_key_persistence( psa_get_key_lifetime( attributes ), + psa_get_key_id( attributes ) ); + if( status != PSA_SUCCESS ) + return( status ); + + status = psa_validate_key_policy( &attributes->core.policy ); + if( status != PSA_SUCCESS ) + return( status ); + + /* Refuse to create overly large keys. + * Note that this doesn't trigger on import if the attributes don't + * explicitly specify a size (so psa_get_key_bits returns 0), so + * psa_import_key() needs its own checks. */ + if( psa_get_key_bits( attributes ) > PSA_MAX_KEY_BITS ) + return( PSA_ERROR_NOT_SUPPORTED ); + + /* Reject invalid flags. These should not be reachable through the API. */ + if( attributes->core.flags & ~ ( MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY | + MBEDTLS_PSA_KA_MASK_DUAL_USE ) ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + return( PSA_SUCCESS ); +} + +/** Prepare a key slot to receive key material. + * + * This function allocates a key slot and sets its metadata. + * + * If this function fails, call psa_fail_key_creation(). + * + * This function is intended to be used as follows: + * -# Call psa_start_key_creation() to allocate a key slot, prepare + * it with the specified attributes, and assign it a handle. + * -# Populate the slot with the key material. + * -# Call psa_finish_key_creation() to finalize the creation of the slot. + * In case of failure at any step, stop the sequence and call + * psa_fail_key_creation(). + * + * \param method An identification of the calling function. + * \param[in] attributes Key attributes for the new key. + * \param[out] handle On success, a handle for the allocated slot. + * \param[out] p_slot On success, a pointer to the prepared slot. + * \param[out] p_drv On any return, the driver for the key, if any. + * NULL for a transparent key. + * + * \retval #PSA_SUCCESS + * The key slot is ready to receive key material. + * \return If this function fails, the key slot is an invalid state. + * You must call psa_fail_key_creation() to wipe and free the slot. + */ +static psa_status_t psa_start_key_creation( + psa_key_creation_method_t method, + const psa_key_attributes_t *attributes, + psa_key_handle_t *handle, + psa_key_slot_t **p_slot, + psa_se_drv_table_entry_t **p_drv ) +{ + psa_status_t status; + psa_key_slot_t *slot; + + (void) method; + *p_drv = NULL; + + status = psa_validate_key_attributes( attributes, p_drv ); + if( status != PSA_SUCCESS ) + return( status ); + + status = psa_get_empty_key_slot( handle, p_slot ); + if( status != PSA_SUCCESS ) + return( status ); + slot = *p_slot; + + /* We're storing the declared bit-size of the key. It's up to each + * creation mechanism to verify that this information is correct. + * It's automatically correct for mechanisms that use the bit-size as + * an input (generate, device) but not for those where the bit-size + * is optional (import, copy). */ + + slot->attr = attributes->core; + + /* Erase external-only flags from the internal copy. To access + * external-only flags, query `attributes`. Thanks to the check + * in psa_validate_key_attributes(), this leaves the dual-use + * flags and any internal flag that psa_get_empty_key_slot() + * may have set. */ + slot->attr.flags &= ~MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY; + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + /* For a key in a secure element, we need to do three things + * when creating or registering a persistent key: + * create the key file in internal storage, create the + * key inside the secure element, and update the driver's + * persistent data. This is done by starting a transaction that will + * encompass these three actions. + * For registering a volatile key, we just need to find an appropriate + * slot number inside the SE. Since the key is designated volatile, creating + * a transaction is not required. */ + /* The first thing to do is to find a slot number for the new key. + * We save the slot number in persistent storage as part of the + * transaction data. It will be needed to recover if the power + * fails during the key creation process, to clean up on the secure + * element side after restarting. Obtaining a slot number from the + * secure element driver updates its persistent state, but we do not yet + * save the driver's persistent state, so that if the power fails, + * we can roll back to a state where the key doesn't exist. */ + if( *p_drv != NULL ) + { + status = psa_find_se_slot_for_key( attributes, method, *p_drv, + &slot->data.se.slot_number ); + if( status != PSA_SUCCESS ) + return( status ); + + if( ! PSA_KEY_LIFETIME_IS_VOLATILE( attributes->core.lifetime ) ) + { + psa_crypto_prepare_transaction( PSA_CRYPTO_TRANSACTION_CREATE_KEY ); + psa_crypto_transaction.key.lifetime = slot->attr.lifetime; + psa_crypto_transaction.key.slot = slot->data.se.slot_number; + psa_crypto_transaction.key.id = slot->attr.id; + status = psa_crypto_save_transaction( ); + if( status != PSA_SUCCESS ) + { + (void) psa_crypto_stop_transaction( ); + return( status ); + } + } + } + + if( *p_drv == NULL && method == PSA_KEY_CREATION_REGISTER ) + { + /* Key registration only makes sense with a secure element. */ + return( PSA_ERROR_INVALID_ARGUMENT ); + } +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + + return( status ); +} + +/** Finalize the creation of a key once its key material has been set. + * + * This entails writing the key to persistent storage. + * + * If this function fails, call psa_fail_key_creation(). + * See the documentation of psa_start_key_creation() for the intended use + * of this function. + * + * \param[in,out] slot Pointer to the slot with key material. + * \param[in] driver The secure element driver for the key, + * or NULL for a transparent key. + * + * \retval #PSA_SUCCESS + * The key was successfully created. The handle is now valid. + * \return If this function fails, the key slot is an invalid state. + * You must call psa_fail_key_creation() to wipe and free the slot. + */ +static psa_status_t psa_finish_key_creation( + psa_key_slot_t *slot, + psa_se_drv_table_entry_t *driver ) +{ + psa_status_t status = PSA_SUCCESS; + (void) slot; + (void) driver; + +#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) + if( ! PSA_KEY_LIFETIME_IS_VOLATILE( slot->attr.lifetime ) ) + { +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + if( driver != NULL ) + { + psa_se_key_data_storage_t data; +#if defined(static_assert) + static_assert( sizeof( slot->data.se.slot_number ) == + sizeof( data.slot_number ), + "Slot number size does not match psa_se_key_data_storage_t" ); +#endif + memcpy( &data.slot_number, &slot->data.se.slot_number, + sizeof( slot->data.se.slot_number ) ); + status = psa_save_persistent_key( &slot->attr, + (uint8_t*) &data, + sizeof( data ) ); + } + else +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + { + /* Key material is saved in export representation in the slot, so + * just pass the slot buffer for storage. */ + status = psa_save_persistent_key( &slot->attr, + slot->data.key.data, + slot->data.key.bytes ); + } + } +#endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + /* Finish the transaction for a key creation. This does not + * happen when registering an existing key. Detect this case + * by checking whether a transaction is in progress (actual + * creation of a persistent key in a secure element requires a transaction, + * but registration or volatile key creation doesn't use one). */ + if( driver != NULL && + psa_crypto_transaction.unknown.type == PSA_CRYPTO_TRANSACTION_CREATE_KEY ) + { + status = psa_save_se_persistent_data( driver ); + if( status != PSA_SUCCESS ) + { + psa_destroy_persistent_key( slot->attr.id ); + return( status ); + } + status = psa_crypto_stop_transaction( ); + if( status != PSA_SUCCESS ) + return( status ); + } +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + + return( status ); +} + +/** Abort the creation of a key. + * + * You may call this function after calling psa_start_key_creation(), + * or after psa_finish_key_creation() fails. In other circumstances, this + * function may not clean up persistent storage. + * See the documentation of psa_start_key_creation() for the intended use + * of this function. + * + * \param[in,out] slot Pointer to the slot with key material. + * \param[in] driver The secure element driver for the key, + * or NULL for a transparent key. + */ +static void psa_fail_key_creation( psa_key_slot_t *slot, + psa_se_drv_table_entry_t *driver ) +{ + (void) driver; + + if( slot == NULL ) + return; + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + /* TODO: If the key has already been created in the secure + * element, and the failure happened later (when saving metadata + * to internal storage), we need to destroy the key in the secure + * element. + * https://github.com/ARMmbed/mbed-crypto/issues/217 + */ + + /* Abort the ongoing transaction if any (there may not be one if + * the creation process failed before starting one, or if the + * key creation is a registration of a key in a secure element). + * Earlier functions must already have done what it takes to undo any + * partial creation. All that's left is to update the transaction data + * itself. */ + (void) psa_crypto_stop_transaction( ); +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + + psa_wipe_key_slot( slot ); +} + +/** Validate optional attributes during key creation. + * + * Some key attributes are optional during key creation. If they are + * specified in the attributes structure, check that they are consistent + * with the data in the slot. + * + * This function should be called near the end of key creation, after + * the slot in memory is fully populated but before saving persistent data. + */ +static psa_status_t psa_validate_optional_attributes( + const psa_key_slot_t *slot, + const psa_key_attributes_t *attributes ) +{ + if( attributes->core.type != 0 ) + { + if( attributes->core.type != slot->attr.type ) + return( PSA_ERROR_INVALID_ARGUMENT ); + } + + if( attributes->domain_parameters_size != 0 ) + { +#if defined(MBEDTLS_RSA_C) + if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) ) + { + mbedtls_rsa_context *rsa = NULL; + mbedtls_mpi actual, required; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + psa_status_t status = psa_load_rsa_representation( + slot->attr.type, + slot->data.key.data, + slot->data.key.bytes, + &rsa ); + if( status != PSA_SUCCESS ) + return( status ); + + mbedtls_mpi_init( &actual ); + mbedtls_mpi_init( &required ); + ret = mbedtls_rsa_export( rsa, + NULL, NULL, NULL, NULL, &actual ); + mbedtls_rsa_free( rsa ); + mbedtls_free( rsa ); + if( ret != 0 ) + goto rsa_exit; + ret = mbedtls_mpi_read_binary( &required, + attributes->domain_parameters, + attributes->domain_parameters_size ); + if( ret != 0 ) + goto rsa_exit; + if( mbedtls_mpi_cmp_mpi( &actual, &required ) != 0 ) + ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + rsa_exit: + mbedtls_mpi_free( &actual ); + mbedtls_mpi_free( &required ); + if( ret != 0) + return( mbedtls_to_psa_error( ret ) ); + } + else +#endif + { + return( PSA_ERROR_INVALID_ARGUMENT ); + } + } + + if( attributes->core.bits != 0 ) + { + if( attributes->core.bits != slot->attr.bits ) + return( PSA_ERROR_INVALID_ARGUMENT ); + } + + return( PSA_SUCCESS ); +} + +psa_status_t psa_import_key( const psa_key_attributes_t *attributes, + const uint8_t *data, + size_t data_length, + psa_key_handle_t *handle ) +{ + psa_status_t status; + psa_key_slot_t *slot = NULL; + psa_se_drv_table_entry_t *driver = NULL; + + /* Reject zero-length symmetric keys (including raw data key objects). + * This also rejects any key which might be encoded as an empty string, + * which is never valid. */ + if( data_length == 0 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + status = psa_start_key_creation( PSA_KEY_CREATION_IMPORT, attributes, + handle, &slot, &driver ); + if( status != PSA_SUCCESS ) + goto exit; + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + if( driver != NULL ) + { + const psa_drv_se_t *drv = psa_get_se_driver_methods( driver ); + /* The driver should set the number of key bits, however in + * case it doesn't, we initialize bits to an invalid value. */ + size_t bits = PSA_MAX_KEY_BITS + 1; + if( drv->key_management == NULL || + drv->key_management->p_import == NULL ) + { + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } + status = drv->key_management->p_import( + psa_get_se_driver_context( driver ), + slot->data.se.slot_number, attributes, data, data_length, + &bits ); + if( status != PSA_SUCCESS ) + goto exit; + if( bits > PSA_MAX_KEY_BITS ) + { + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } + slot->attr.bits = (psa_key_bits_t) bits; + } + else +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + { + status = psa_import_key_into_slot( slot, data, data_length ); + if( status != PSA_SUCCESS ) + goto exit; + } + status = psa_validate_optional_attributes( slot, attributes ); + if( status != PSA_SUCCESS ) + goto exit; + + status = psa_finish_key_creation( slot, driver ); +exit: + if( status != PSA_SUCCESS ) + { + psa_fail_key_creation( slot, driver ); + *handle = 0; + } + return( status ); +} + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) +psa_status_t mbedtls_psa_register_se_key( + const psa_key_attributes_t *attributes ) +{ + psa_status_t status; + psa_key_slot_t *slot = NULL; + psa_se_drv_table_entry_t *driver = NULL; + psa_key_handle_t handle = 0; + + /* Leaving attributes unspecified is not currently supported. + * It could make sense to query the key type and size from the + * secure element, but not all secure elements support this + * and the driver HAL doesn't currently support it. */ + if( psa_get_key_type( attributes ) == PSA_KEY_TYPE_NONE ) + return( PSA_ERROR_NOT_SUPPORTED ); + if( psa_get_key_bits( attributes ) == 0 ) + return( PSA_ERROR_NOT_SUPPORTED ); + + status = psa_start_key_creation( PSA_KEY_CREATION_REGISTER, attributes, + &handle, &slot, &driver ); + if( status != PSA_SUCCESS ) + goto exit; + + status = psa_finish_key_creation( slot, driver ); + +exit: + if( status != PSA_SUCCESS ) + { + psa_fail_key_creation( slot, driver ); + } + /* Registration doesn't keep the key in RAM. */ + psa_close_key( handle ); + return( status ); +} +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + +static psa_status_t psa_copy_key_material( const psa_key_slot_t *source, + psa_key_slot_t *target ) +{ + psa_status_t status = psa_copy_key_material_into_slot( target, + source->data.key.data, + source->data.key.bytes ); + if( status != PSA_SUCCESS ) + return( status ); + + target->attr.type = source->attr.type; + target->attr.bits = source->attr.bits; + + return( PSA_SUCCESS ); +} + +psa_status_t psa_copy_key( psa_key_handle_t source_handle, + const psa_key_attributes_t *specified_attributes, + psa_key_handle_t *target_handle ) +{ + psa_status_t status; + psa_key_slot_t *source_slot = NULL; + psa_key_slot_t *target_slot = NULL; + psa_key_attributes_t actual_attributes = *specified_attributes; + psa_se_drv_table_entry_t *driver = NULL; + + status = psa_get_transparent_key( source_handle, &source_slot, + PSA_KEY_USAGE_COPY, 0 ); + if( status != PSA_SUCCESS ) + goto exit; + + status = psa_validate_optional_attributes( source_slot, + specified_attributes ); + if( status != PSA_SUCCESS ) + goto exit; + + status = psa_restrict_key_policy( &actual_attributes.core.policy, + &source_slot->attr.policy ); + if( status != PSA_SUCCESS ) + goto exit; + + status = psa_start_key_creation( PSA_KEY_CREATION_COPY, + &actual_attributes, + target_handle, &target_slot, &driver ); + if( status != PSA_SUCCESS ) + goto exit; + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + if( driver != NULL ) + { + /* Copying to a secure element is not implemented yet. */ + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + + status = psa_copy_key_material( source_slot, target_slot ); + if( status != PSA_SUCCESS ) + goto exit; + + status = psa_finish_key_creation( target_slot, driver ); +exit: + if( status != PSA_SUCCESS ) + { + psa_fail_key_creation( target_slot, driver ); + *target_handle = 0; + } + return( status ); +} + + + +/****************************************************************/ +/* Message digests */ +/****************************************************************/ + +#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) +static const mbedtls_md_info_t *mbedtls_md_info_from_psa( psa_algorithm_t alg ) +{ + switch( alg ) + { +#if defined(MBEDTLS_MD2_C) + case PSA_ALG_MD2: + return( &mbedtls_md2_info ); +#endif +#if defined(MBEDTLS_MD4_C) + case PSA_ALG_MD4: + return( &mbedtls_md4_info ); +#endif +#if defined(MBEDTLS_MD5_C) + case PSA_ALG_MD5: + return( &mbedtls_md5_info ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case PSA_ALG_RIPEMD160: + return( &mbedtls_ripemd160_info ); +#endif +#if defined(MBEDTLS_SHA1_C) + case PSA_ALG_SHA_1: + return( &mbedtls_sha1_info ); +#endif +#if defined(MBEDTLS_SHA256_C) + case PSA_ALG_SHA_224: + return( &mbedtls_sha224_info ); + case PSA_ALG_SHA_256: + return( &mbedtls_sha256_info ); +#endif +#if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) + case PSA_ALG_SHA_384: + return( &mbedtls_sha384_info ); +#endif + case PSA_ALG_SHA_512: + return( &mbedtls_sha512_info ); +#endif + default: + return( NULL ); + } +} +#endif /* defined(MBEDTLS_RSA_C) || defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */ + +psa_status_t psa_hash_abort( psa_hash_operation_t *operation ) +{ + switch( operation->alg ) + { + case 0: + /* The object has (apparently) been initialized but it is not + * in use. It's ok to call abort on such an object, and there's + * nothing to do. */ + break; +#if defined(MBEDTLS_MD2_C) + case PSA_ALG_MD2: + mbedtls_md2_free( &operation->ctx.md2 ); + break; +#endif +#if defined(MBEDTLS_MD4_C) + case PSA_ALG_MD4: + mbedtls_md4_free( &operation->ctx.md4 ); + break; +#endif +#if defined(MBEDTLS_MD5_C) + case PSA_ALG_MD5: + mbedtls_md5_free( &operation->ctx.md5 ); + break; +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case PSA_ALG_RIPEMD160: + mbedtls_ripemd160_free( &operation->ctx.ripemd160 ); + break; +#endif +#if defined(MBEDTLS_SHA1_C) + case PSA_ALG_SHA_1: + mbedtls_sha1_free( &operation->ctx.sha1 ); + break; +#endif +#if defined(MBEDTLS_SHA256_C) + case PSA_ALG_SHA_224: + case PSA_ALG_SHA_256: + mbedtls_sha256_free( &operation->ctx.sha256 ); + break; +#endif +#if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) + case PSA_ALG_SHA_384: +#endif + case PSA_ALG_SHA_512: + mbedtls_sha512_free( &operation->ctx.sha512 ); + break; +#endif + default: + return( PSA_ERROR_BAD_STATE ); + } + operation->alg = 0; + return( PSA_SUCCESS ); +} + +psa_status_t psa_hash_setup( psa_hash_operation_t *operation, + psa_algorithm_t alg ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* A context must be freshly initialized before it can be set up. */ + if( operation->alg != 0 ) + { + return( PSA_ERROR_BAD_STATE ); + } + + switch( alg ) + { +#if defined(MBEDTLS_MD2_C) + case PSA_ALG_MD2: + mbedtls_md2_init( &operation->ctx.md2 ); + ret = mbedtls_md2_starts_ret( &operation->ctx.md2 ); + break; +#endif +#if defined(MBEDTLS_MD4_C) + case PSA_ALG_MD4: + mbedtls_md4_init( &operation->ctx.md4 ); + ret = mbedtls_md4_starts_ret( &operation->ctx.md4 ); + break; +#endif +#if defined(MBEDTLS_MD5_C) + case PSA_ALG_MD5: + mbedtls_md5_init( &operation->ctx.md5 ); + ret = mbedtls_md5_starts_ret( &operation->ctx.md5 ); + break; +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case PSA_ALG_RIPEMD160: + mbedtls_ripemd160_init( &operation->ctx.ripemd160 ); + ret = mbedtls_ripemd160_starts_ret( &operation->ctx.ripemd160 ); + break; +#endif +#if defined(MBEDTLS_SHA1_C) + case PSA_ALG_SHA_1: + mbedtls_sha1_init( &operation->ctx.sha1 ); + ret = mbedtls_sha1_starts_ret( &operation->ctx.sha1 ); + break; +#endif +#if defined(MBEDTLS_SHA256_C) + case PSA_ALG_SHA_224: + mbedtls_sha256_init( &operation->ctx.sha256 ); + ret = mbedtls_sha256_starts_ret( &operation->ctx.sha256, 1 ); + break; + case PSA_ALG_SHA_256: + mbedtls_sha256_init( &operation->ctx.sha256 ); + ret = mbedtls_sha256_starts_ret( &operation->ctx.sha256, 0 ); + break; +#endif +#if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) + case PSA_ALG_SHA_384: + mbedtls_sha512_init( &operation->ctx.sha512 ); + ret = mbedtls_sha512_starts_ret( &operation->ctx.sha512, 1 ); + break; +#endif + case PSA_ALG_SHA_512: + mbedtls_sha512_init( &operation->ctx.sha512 ); + ret = mbedtls_sha512_starts_ret( &operation->ctx.sha512, 0 ); + break; +#endif + default: + return( PSA_ALG_IS_HASH( alg ) ? + PSA_ERROR_NOT_SUPPORTED : + PSA_ERROR_INVALID_ARGUMENT ); + } + if( ret == 0 ) + operation->alg = alg; + else + psa_hash_abort( operation ); + return( mbedtls_to_psa_error( ret ) ); +} + +psa_status_t psa_hash_update( psa_hash_operation_t *operation, + const uint8_t *input, + size_t input_length ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* Don't require hash implementations to behave correctly on a + * zero-length input, which may have an invalid pointer. */ + if( input_length == 0 ) + return( PSA_SUCCESS ); + + switch( operation->alg ) + { +#if defined(MBEDTLS_MD2_C) + case PSA_ALG_MD2: + ret = mbedtls_md2_update_ret( &operation->ctx.md2, + input, input_length ); + break; +#endif +#if defined(MBEDTLS_MD4_C) + case PSA_ALG_MD4: + ret = mbedtls_md4_update_ret( &operation->ctx.md4, + input, input_length ); + break; +#endif +#if defined(MBEDTLS_MD5_C) + case PSA_ALG_MD5: + ret = mbedtls_md5_update_ret( &operation->ctx.md5, + input, input_length ); + break; +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case PSA_ALG_RIPEMD160: + ret = mbedtls_ripemd160_update_ret( &operation->ctx.ripemd160, + input, input_length ); + break; +#endif +#if defined(MBEDTLS_SHA1_C) + case PSA_ALG_SHA_1: + ret = mbedtls_sha1_update_ret( &operation->ctx.sha1, + input, input_length ); + break; +#endif +#if defined(MBEDTLS_SHA256_C) + case PSA_ALG_SHA_224: + case PSA_ALG_SHA_256: + ret = mbedtls_sha256_update_ret( &operation->ctx.sha256, + input, input_length ); + break; +#endif +#if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) + case PSA_ALG_SHA_384: +#endif + case PSA_ALG_SHA_512: + ret = mbedtls_sha512_update_ret( &operation->ctx.sha512, + input, input_length ); + break; +#endif + default: + return( PSA_ERROR_BAD_STATE ); + } + + if( ret != 0 ) + psa_hash_abort( operation ); + return( mbedtls_to_psa_error( ret ) ); +} + +psa_status_t psa_hash_finish( psa_hash_operation_t *operation, + uint8_t *hash, + size_t hash_size, + size_t *hash_length ) +{ + psa_status_t status; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t actual_hash_length = PSA_HASH_SIZE( operation->alg ); + + /* Fill the output buffer with something that isn't a valid hash + * (barring an attack on the hash and deliberately-crafted input), + * in case the caller doesn't check the return status properly. */ + *hash_length = hash_size; + /* If hash_size is 0 then hash may be NULL and then the + * call to memset would have undefined behavior. */ + if( hash_size != 0 ) + memset( hash, '!', hash_size ); + + if( hash_size < actual_hash_length ) + { + status = PSA_ERROR_BUFFER_TOO_SMALL; + goto exit; + } + + switch( operation->alg ) + { +#if defined(MBEDTLS_MD2_C) + case PSA_ALG_MD2: + ret = mbedtls_md2_finish_ret( &operation->ctx.md2, hash ); + break; +#endif +#if defined(MBEDTLS_MD4_C) + case PSA_ALG_MD4: + ret = mbedtls_md4_finish_ret( &operation->ctx.md4, hash ); + break; +#endif +#if defined(MBEDTLS_MD5_C) + case PSA_ALG_MD5: + ret = mbedtls_md5_finish_ret( &operation->ctx.md5, hash ); + break; +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case PSA_ALG_RIPEMD160: + ret = mbedtls_ripemd160_finish_ret( &operation->ctx.ripemd160, hash ); + break; +#endif +#if defined(MBEDTLS_SHA1_C) + case PSA_ALG_SHA_1: + ret = mbedtls_sha1_finish_ret( &operation->ctx.sha1, hash ); + break; +#endif +#if defined(MBEDTLS_SHA256_C) + case PSA_ALG_SHA_224: + case PSA_ALG_SHA_256: + ret = mbedtls_sha256_finish_ret( &operation->ctx.sha256, hash ); + break; +#endif +#if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) + case PSA_ALG_SHA_384: +#endif + case PSA_ALG_SHA_512: + ret = mbedtls_sha512_finish_ret( &operation->ctx.sha512, hash ); + break; +#endif + default: + return( PSA_ERROR_BAD_STATE ); + } + status = mbedtls_to_psa_error( ret ); + +exit: + if( status == PSA_SUCCESS ) + { + *hash_length = actual_hash_length; + return( psa_hash_abort( operation ) ); + } + else + { + psa_hash_abort( operation ); + return( status ); + } +} + +psa_status_t psa_hash_verify( psa_hash_operation_t *operation, + const uint8_t *hash, + size_t hash_length ) +{ + uint8_t actual_hash[MBEDTLS_MD_MAX_SIZE]; + size_t actual_hash_length; + psa_status_t status = psa_hash_finish( operation, + actual_hash, sizeof( actual_hash ), + &actual_hash_length ); + if( status != PSA_SUCCESS ) + return( status ); + if( actual_hash_length != hash_length ) + return( PSA_ERROR_INVALID_SIGNATURE ); + if( safer_memcmp( hash, actual_hash, actual_hash_length ) != 0 ) + return( PSA_ERROR_INVALID_SIGNATURE ); + return( PSA_SUCCESS ); +} + +psa_status_t psa_hash_compute( psa_algorithm_t alg, + const uint8_t *input, size_t input_length, + uint8_t *hash, size_t hash_size, + size_t *hash_length ) +{ + psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + *hash_length = hash_size; + status = psa_hash_setup( &operation, alg ); + if( status != PSA_SUCCESS ) + goto exit; + status = psa_hash_update( &operation, input, input_length ); + if( status != PSA_SUCCESS ) + goto exit; + status = psa_hash_finish( &operation, hash, hash_size, hash_length ); + if( status != PSA_SUCCESS ) + goto exit; + +exit: + if( status == PSA_SUCCESS ) + status = psa_hash_abort( &operation ); + else + psa_hash_abort( &operation ); + return( status ); +} + +psa_status_t psa_hash_compare( psa_algorithm_t alg, + const uint8_t *input, size_t input_length, + const uint8_t *hash, size_t hash_length ) +{ + psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + status = psa_hash_setup( &operation, alg ); + if( status != PSA_SUCCESS ) + goto exit; + status = psa_hash_update( &operation, input, input_length ); + if( status != PSA_SUCCESS ) + goto exit; + status = psa_hash_verify( &operation, hash, hash_length ); + if( status != PSA_SUCCESS ) + goto exit; + +exit: + if( status == PSA_SUCCESS ) + status = psa_hash_abort( &operation ); + else + psa_hash_abort( &operation ); + return( status ); +} + +psa_status_t psa_hash_clone( const psa_hash_operation_t *source_operation, + psa_hash_operation_t *target_operation ) +{ + if( target_operation->alg != 0 ) + return( PSA_ERROR_BAD_STATE ); + + switch( source_operation->alg ) + { + case 0: + return( PSA_ERROR_BAD_STATE ); +#if defined(MBEDTLS_MD2_C) + case PSA_ALG_MD2: + mbedtls_md2_clone( &target_operation->ctx.md2, + &source_operation->ctx.md2 ); + break; +#endif +#if defined(MBEDTLS_MD4_C) + case PSA_ALG_MD4: + mbedtls_md4_clone( &target_operation->ctx.md4, + &source_operation->ctx.md4 ); + break; +#endif +#if defined(MBEDTLS_MD5_C) + case PSA_ALG_MD5: + mbedtls_md5_clone( &target_operation->ctx.md5, + &source_operation->ctx.md5 ); + break; +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case PSA_ALG_RIPEMD160: + mbedtls_ripemd160_clone( &target_operation->ctx.ripemd160, + &source_operation->ctx.ripemd160 ); + break; +#endif +#if defined(MBEDTLS_SHA1_C) + case PSA_ALG_SHA_1: + mbedtls_sha1_clone( &target_operation->ctx.sha1, + &source_operation->ctx.sha1 ); + break; +#endif +#if defined(MBEDTLS_SHA256_C) + case PSA_ALG_SHA_224: + case PSA_ALG_SHA_256: + mbedtls_sha256_clone( &target_operation->ctx.sha256, + &source_operation->ctx.sha256 ); + break; +#endif +#if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) + case PSA_ALG_SHA_384: +#endif + case PSA_ALG_SHA_512: + mbedtls_sha512_clone( &target_operation->ctx.sha512, + &source_operation->ctx.sha512 ); + break; +#endif + default: + return( PSA_ERROR_NOT_SUPPORTED ); + } + + target_operation->alg = source_operation->alg; + return( PSA_SUCCESS ); +} + + +/****************************************************************/ +/* MAC */ +/****************************************************************/ + +static const mbedtls_cipher_info_t *mbedtls_cipher_info_from_psa( + psa_algorithm_t alg, + psa_key_type_t key_type, + size_t key_bits, + mbedtls_cipher_id_t* cipher_id ) +{ + mbedtls_cipher_mode_t mode; + mbedtls_cipher_id_t cipher_id_tmp; + + if( PSA_ALG_IS_AEAD( alg ) ) + alg = PSA_ALG_AEAD_WITH_TAG_LENGTH( alg, 0 ); + + if( PSA_ALG_IS_CIPHER( alg ) || PSA_ALG_IS_AEAD( alg ) ) + { + switch( alg ) + { + case PSA_ALG_ARC4: + case PSA_ALG_CHACHA20: + mode = MBEDTLS_MODE_STREAM; + break; + case PSA_ALG_CTR: + mode = MBEDTLS_MODE_CTR; + break; + case PSA_ALG_CFB: + mode = MBEDTLS_MODE_CFB; + break; + case PSA_ALG_OFB: + mode = MBEDTLS_MODE_OFB; + break; + case PSA_ALG_ECB_NO_PADDING: + mode = MBEDTLS_MODE_ECB; + break; + case PSA_ALG_CBC_NO_PADDING: + mode = MBEDTLS_MODE_CBC; + break; + case PSA_ALG_CBC_PKCS7: + mode = MBEDTLS_MODE_CBC; + break; + case PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_CCM, 0 ): + mode = MBEDTLS_MODE_CCM; + break; + case PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_GCM, 0 ): + mode = MBEDTLS_MODE_GCM; + break; + case PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_CHACHA20_POLY1305, 0 ): + mode = MBEDTLS_MODE_CHACHAPOLY; + break; + default: + return( NULL ); + } + } + else if( alg == PSA_ALG_CMAC ) + mode = MBEDTLS_MODE_ECB; + else + return( NULL ); + + switch( key_type ) + { + case PSA_KEY_TYPE_AES: + cipher_id_tmp = MBEDTLS_CIPHER_ID_AES; + break; + case PSA_KEY_TYPE_DES: + /* key_bits is 64 for Single-DES, 128 for two-key Triple-DES, + * and 192 for three-key Triple-DES. */ + if( key_bits == 64 ) + cipher_id_tmp = MBEDTLS_CIPHER_ID_DES; + else + cipher_id_tmp = MBEDTLS_CIPHER_ID_3DES; + /* mbedtls doesn't recognize two-key Triple-DES as an algorithm, + * but two-key Triple-DES is functionally three-key Triple-DES + * with K1=K3, so that's how we present it to mbedtls. */ + if( key_bits == 128 ) + key_bits = 192; + break; + case PSA_KEY_TYPE_CAMELLIA: + cipher_id_tmp = MBEDTLS_CIPHER_ID_CAMELLIA; + break; + case PSA_KEY_TYPE_ARC4: + cipher_id_tmp = MBEDTLS_CIPHER_ID_ARC4; + break; + case PSA_KEY_TYPE_CHACHA20: + cipher_id_tmp = MBEDTLS_CIPHER_ID_CHACHA20; + break; + default: + return( NULL ); + } + if( cipher_id != NULL ) + *cipher_id = cipher_id_tmp; + + return( mbedtls_cipher_info_from_values( cipher_id_tmp, + (int) key_bits, mode ) ); +} + +#if defined(MBEDTLS_MD_C) +static size_t psa_get_hash_block_size( psa_algorithm_t alg ) +{ + switch( alg ) + { + case PSA_ALG_MD2: + return( 16 ); + case PSA_ALG_MD4: + return( 64 ); + case PSA_ALG_MD5: + return( 64 ); + case PSA_ALG_RIPEMD160: + return( 64 ); + case PSA_ALG_SHA_1: + return( 64 ); + case PSA_ALG_SHA_224: + return( 64 ); + case PSA_ALG_SHA_256: + return( 64 ); + case PSA_ALG_SHA_384: + return( 128 ); + case PSA_ALG_SHA_512: + return( 128 ); + default: + return( 0 ); + } +} +#endif /* MBEDTLS_MD_C */ + +/* Initialize the MAC operation structure. Once this function has been + * called, psa_mac_abort can run and will do the right thing. */ +static psa_status_t psa_mac_init( psa_mac_operation_t *operation, + psa_algorithm_t alg ) +{ + psa_status_t status = PSA_ERROR_NOT_SUPPORTED; + + operation->alg = alg; + operation->key_set = 0; + operation->iv_set = 0; + operation->iv_required = 0; + operation->has_input = 0; + operation->is_sign = 0; + +#if defined(MBEDTLS_CMAC_C) + if( alg == PSA_ALG_CMAC ) + { + operation->iv_required = 0; + mbedtls_cipher_init( &operation->ctx.cmac ); + status = PSA_SUCCESS; + } + else +#endif /* MBEDTLS_CMAC_C */ +#if defined(MBEDTLS_MD_C) + if( PSA_ALG_IS_HMAC( operation->alg ) ) + { + /* We'll set up the hash operation later in psa_hmac_setup_internal. */ + operation->ctx.hmac.hash_ctx.alg = 0; + status = PSA_SUCCESS; + } + else +#endif /* MBEDTLS_MD_C */ + { + if( ! PSA_ALG_IS_MAC( alg ) ) + status = PSA_ERROR_INVALID_ARGUMENT; + } + + if( status != PSA_SUCCESS ) + memset( operation, 0, sizeof( *operation ) ); + return( status ); +} + +#if defined(MBEDTLS_MD_C) +static psa_status_t psa_hmac_abort_internal( psa_hmac_internal_data *hmac ) +{ + mbedtls_platform_zeroize( hmac->opad, sizeof( hmac->opad ) ); + return( psa_hash_abort( &hmac->hash_ctx ) ); +} +#endif /* MBEDTLS_MD_C */ + +psa_status_t psa_mac_abort( psa_mac_operation_t *operation ) +{ + if( operation->alg == 0 ) + { + /* The object has (apparently) been initialized but it is not + * in use. It's ok to call abort on such an object, and there's + * nothing to do. */ + return( PSA_SUCCESS ); + } + else +#if defined(MBEDTLS_CMAC_C) + if( operation->alg == PSA_ALG_CMAC ) + { + mbedtls_cipher_free( &operation->ctx.cmac ); + } + else +#endif /* MBEDTLS_CMAC_C */ +#if defined(MBEDTLS_MD_C) + if( PSA_ALG_IS_HMAC( operation->alg ) ) + { + psa_hmac_abort_internal( &operation->ctx.hmac ); + } + else +#endif /* MBEDTLS_MD_C */ + { + /* Sanity check (shouldn't happen: operation->alg should + * always have been initialized to a valid value). */ + goto bad_state; + } + + operation->alg = 0; + operation->key_set = 0; + operation->iv_set = 0; + operation->iv_required = 0; + operation->has_input = 0; + operation->is_sign = 0; + + return( PSA_SUCCESS ); + +bad_state: + /* If abort is called on an uninitialized object, we can't trust + * anything. Wipe the object in case it contains confidential data. + * This may result in a memory leak if a pointer gets overwritten, + * but it's too late to do anything about this. */ + memset( operation, 0, sizeof( *operation ) ); + return( PSA_ERROR_BAD_STATE ); +} + +#if defined(MBEDTLS_CMAC_C) +static int psa_cmac_setup( psa_mac_operation_t *operation, + size_t key_bits, + psa_key_slot_t *slot, + const mbedtls_cipher_info_t *cipher_info ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + operation->mac_size = cipher_info->block_size; + + ret = mbedtls_cipher_setup( &operation->ctx.cmac, cipher_info ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_cipher_cmac_starts( &operation->ctx.cmac, + slot->data.key.data, + key_bits ); + return( ret ); +} +#endif /* MBEDTLS_CMAC_C */ + +#if defined(MBEDTLS_MD_C) +static psa_status_t psa_hmac_setup_internal( psa_hmac_internal_data *hmac, + const uint8_t *key, + size_t key_length, + psa_algorithm_t hash_alg ) +{ + uint8_t ipad[PSA_HMAC_MAX_HASH_BLOCK_SIZE]; + size_t i; + size_t hash_size = PSA_HASH_SIZE( hash_alg ); + size_t block_size = psa_get_hash_block_size( hash_alg ); + psa_status_t status; + + /* Sanity checks on block_size, to guarantee that there won't be a buffer + * overflow below. This should never trigger if the hash algorithm + * is implemented correctly. */ + /* The size checks against the ipad and opad buffers cannot be written + * `block_size > sizeof( ipad ) || block_size > sizeof( hmac->opad )` + * because that triggers -Wlogical-op on GCC 7.3. */ + if( block_size > sizeof( ipad ) ) + return( PSA_ERROR_NOT_SUPPORTED ); + if( block_size > sizeof( hmac->opad ) ) + return( PSA_ERROR_NOT_SUPPORTED ); + if( block_size < hash_size ) + return( PSA_ERROR_NOT_SUPPORTED ); + + if( key_length > block_size ) + { + status = psa_hash_compute( hash_alg, key, key_length, + ipad, sizeof( ipad ), &key_length ); + if( status != PSA_SUCCESS ) + goto cleanup; + } + /* A 0-length key is not commonly used in HMAC when used as a MAC, + * but it is permitted. It is common when HMAC is used in HKDF, for + * example. Don't call `memcpy` in the 0-length because `key` could be + * an invalid pointer which would make the behavior undefined. */ + else if( key_length != 0 ) + memcpy( ipad, key, key_length ); + + /* ipad contains the key followed by garbage. Xor and fill with 0x36 + * to create the ipad value. */ + for( i = 0; i < key_length; i++ ) + ipad[i] ^= 0x36; + memset( ipad + key_length, 0x36, block_size - key_length ); + + /* Copy the key material from ipad to opad, flipping the requisite bits, + * and filling the rest of opad with the requisite constant. */ + for( i = 0; i < key_length; i++ ) + hmac->opad[i] = ipad[i] ^ 0x36 ^ 0x5C; + memset( hmac->opad + key_length, 0x5C, block_size - key_length ); + + status = psa_hash_setup( &hmac->hash_ctx, hash_alg ); + if( status != PSA_SUCCESS ) + goto cleanup; + + status = psa_hash_update( &hmac->hash_ctx, ipad, block_size ); + +cleanup: + mbedtls_platform_zeroize( ipad, sizeof( ipad ) ); + + return( status ); +} +#endif /* MBEDTLS_MD_C */ + +static psa_status_t psa_mac_setup( psa_mac_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg, + int is_sign ) +{ + psa_status_t status; + psa_key_slot_t *slot; + size_t key_bits; + psa_key_usage_t usage = + is_sign ? PSA_KEY_USAGE_SIGN_HASH : PSA_KEY_USAGE_VERIFY_HASH; + uint8_t truncated = PSA_MAC_TRUNCATED_LENGTH( alg ); + psa_algorithm_t full_length_alg = PSA_ALG_FULL_LENGTH_MAC( alg ); + + /* A context must be freshly initialized before it can be set up. */ + if( operation->alg != 0 ) + { + return( PSA_ERROR_BAD_STATE ); + } + + status = psa_mac_init( operation, full_length_alg ); + if( status != PSA_SUCCESS ) + return( status ); + if( is_sign ) + operation->is_sign = 1; + + status = psa_get_transparent_key( handle, &slot, usage, alg ); + if( status != PSA_SUCCESS ) + goto exit; + key_bits = psa_get_key_slot_bits( slot ); + +#if defined(MBEDTLS_CMAC_C) + if( full_length_alg == PSA_ALG_CMAC ) + { + const mbedtls_cipher_info_t *cipher_info = + mbedtls_cipher_info_from_psa( full_length_alg, + slot->attr.type, key_bits, NULL ); + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + if( cipher_info == NULL ) + { + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } + operation->mac_size = cipher_info->block_size; + ret = psa_cmac_setup( operation, key_bits, slot, cipher_info ); + status = mbedtls_to_psa_error( ret ); + } + else +#endif /* MBEDTLS_CMAC_C */ +#if defined(MBEDTLS_MD_C) + if( PSA_ALG_IS_HMAC( full_length_alg ) ) + { + psa_algorithm_t hash_alg = PSA_ALG_HMAC_GET_HASH( alg ); + if( hash_alg == 0 ) + { + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } + + operation->mac_size = PSA_HASH_SIZE( hash_alg ); + /* Sanity check. This shouldn't fail on a valid configuration. */ + if( operation->mac_size == 0 || + operation->mac_size > sizeof( operation->ctx.hmac.opad ) ) + { + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } + + if( slot->attr.type != PSA_KEY_TYPE_HMAC ) + { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + status = psa_hmac_setup_internal( &operation->ctx.hmac, + slot->data.key.data, + slot->data.key.bytes, + hash_alg ); + } + else +#endif /* MBEDTLS_MD_C */ + { + (void) key_bits; + status = PSA_ERROR_NOT_SUPPORTED; + } + + if( truncated == 0 ) + { + /* The "normal" case: untruncated algorithm. Nothing to do. */ + } + else if( truncated < 4 ) + { + /* A very short MAC is too short for security since it can be + * brute-forced. Ancient protocols with 32-bit MACs do exist, + * so we make this our minimum, even though 32 bits is still + * too small for security. */ + status = PSA_ERROR_NOT_SUPPORTED; + } + else if( truncated > operation->mac_size ) + { + /* It's impossible to "truncate" to a larger length. */ + status = PSA_ERROR_INVALID_ARGUMENT; + } + else + operation->mac_size = truncated; + +exit: + if( status != PSA_SUCCESS ) + { + psa_mac_abort( operation ); + } + else + { + operation->key_set = 1; + } + return( status ); +} + +psa_status_t psa_mac_sign_setup( psa_mac_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg ) +{ + return( psa_mac_setup( operation, handle, alg, 1 ) ); +} + +psa_status_t psa_mac_verify_setup( psa_mac_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg ) +{ + return( psa_mac_setup( operation, handle, alg, 0 ) ); +} + +psa_status_t psa_mac_update( psa_mac_operation_t *operation, + const uint8_t *input, + size_t input_length ) +{ + psa_status_t status = PSA_ERROR_BAD_STATE; + if( ! operation->key_set ) + return( PSA_ERROR_BAD_STATE ); + if( operation->iv_required && ! operation->iv_set ) + return( PSA_ERROR_BAD_STATE ); + operation->has_input = 1; + +#if defined(MBEDTLS_CMAC_C) + if( operation->alg == PSA_ALG_CMAC ) + { + int ret = mbedtls_cipher_cmac_update( &operation->ctx.cmac, + input, input_length ); + status = mbedtls_to_psa_error( ret ); + } + else +#endif /* MBEDTLS_CMAC_C */ +#if defined(MBEDTLS_MD_C) + if( PSA_ALG_IS_HMAC( operation->alg ) ) + { + status = psa_hash_update( &operation->ctx.hmac.hash_ctx, input, + input_length ); + } + else +#endif /* MBEDTLS_MD_C */ + { + /* This shouldn't happen if `operation` was initialized by + * a setup function. */ + return( PSA_ERROR_BAD_STATE ); + } + + if( status != PSA_SUCCESS ) + psa_mac_abort( operation ); + return( status ); +} + +#if defined(MBEDTLS_MD_C) +static psa_status_t psa_hmac_finish_internal( psa_hmac_internal_data *hmac, + uint8_t *mac, + size_t mac_size ) +{ + uint8_t tmp[MBEDTLS_MD_MAX_SIZE]; + psa_algorithm_t hash_alg = hmac->hash_ctx.alg; + size_t hash_size = 0; + size_t block_size = psa_get_hash_block_size( hash_alg ); + psa_status_t status; + + status = psa_hash_finish( &hmac->hash_ctx, tmp, sizeof( tmp ), &hash_size ); + if( status != PSA_SUCCESS ) + return( status ); + /* From here on, tmp needs to be wiped. */ + + status = psa_hash_setup( &hmac->hash_ctx, hash_alg ); + if( status != PSA_SUCCESS ) + goto exit; + + status = psa_hash_update( &hmac->hash_ctx, hmac->opad, block_size ); + if( status != PSA_SUCCESS ) + goto exit; + + status = psa_hash_update( &hmac->hash_ctx, tmp, hash_size ); + if( status != PSA_SUCCESS ) + goto exit; + + status = psa_hash_finish( &hmac->hash_ctx, tmp, sizeof( tmp ), &hash_size ); + if( status != PSA_SUCCESS ) + goto exit; + + memcpy( mac, tmp, mac_size ); + +exit: + mbedtls_platform_zeroize( tmp, hash_size ); + return( status ); +} +#endif /* MBEDTLS_MD_C */ + +static psa_status_t psa_mac_finish_internal( psa_mac_operation_t *operation, + uint8_t *mac, + size_t mac_size ) +{ + if( ! operation->key_set ) + return( PSA_ERROR_BAD_STATE ); + if( operation->iv_required && ! operation->iv_set ) + return( PSA_ERROR_BAD_STATE ); + + if( mac_size < operation->mac_size ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); + +#if defined(MBEDTLS_CMAC_C) + if( operation->alg == PSA_ALG_CMAC ) + { + uint8_t tmp[PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE]; + int ret = mbedtls_cipher_cmac_finish( &operation->ctx.cmac, tmp ); + if( ret == 0 ) + memcpy( mac, tmp, operation->mac_size ); + mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); + return( mbedtls_to_psa_error( ret ) ); + } + else +#endif /* MBEDTLS_CMAC_C */ +#if defined(MBEDTLS_MD_C) + if( PSA_ALG_IS_HMAC( operation->alg ) ) + { + return( psa_hmac_finish_internal( &operation->ctx.hmac, + mac, operation->mac_size ) ); + } + else +#endif /* MBEDTLS_MD_C */ + { + /* This shouldn't happen if `operation` was initialized by + * a setup function. */ + return( PSA_ERROR_BAD_STATE ); + } +} + +psa_status_t psa_mac_sign_finish( psa_mac_operation_t *operation, + uint8_t *mac, + size_t mac_size, + size_t *mac_length ) +{ + psa_status_t status; + + if( operation->alg == 0 ) + { + return( PSA_ERROR_BAD_STATE ); + } + + /* Fill the output buffer with something that isn't a valid mac + * (barring an attack on the mac and deliberately-crafted input), + * in case the caller doesn't check the return status properly. */ + *mac_length = mac_size; + /* If mac_size is 0 then mac may be NULL and then the + * call to memset would have undefined behavior. */ + if( mac_size != 0 ) + memset( mac, '!', mac_size ); + + if( ! operation->is_sign ) + { + return( PSA_ERROR_BAD_STATE ); + } + + status = psa_mac_finish_internal( operation, mac, mac_size ); + + if( status == PSA_SUCCESS ) + { + status = psa_mac_abort( operation ); + if( status == PSA_SUCCESS ) + *mac_length = operation->mac_size; + else + memset( mac, '!', mac_size ); + } + else + psa_mac_abort( operation ); + return( status ); +} + +psa_status_t psa_mac_verify_finish( psa_mac_operation_t *operation, + const uint8_t *mac, + size_t mac_length ) +{ + uint8_t actual_mac[PSA_MAC_MAX_SIZE]; + psa_status_t status; + + if( operation->alg == 0 ) + { + return( PSA_ERROR_BAD_STATE ); + } + + if( operation->is_sign ) + { + return( PSA_ERROR_BAD_STATE ); + } + if( operation->mac_size != mac_length ) + { + status = PSA_ERROR_INVALID_SIGNATURE; + goto cleanup; + } + + status = psa_mac_finish_internal( operation, + actual_mac, sizeof( actual_mac ) ); + if( status != PSA_SUCCESS ) + goto cleanup; + + if( safer_memcmp( mac, actual_mac, mac_length ) != 0 ) + status = PSA_ERROR_INVALID_SIGNATURE; + +cleanup: + if( status == PSA_SUCCESS ) + status = psa_mac_abort( operation ); + else + psa_mac_abort( operation ); + + mbedtls_platform_zeroize( actual_mac, sizeof( actual_mac ) ); + + return( status ); +} + + + +/****************************************************************/ +/* Asymmetric cryptography */ +/****************************************************************/ + +#if defined(MBEDTLS_RSA_C) +/* Decode the hash algorithm from alg and store the mbedtls encoding in + * md_alg. Verify that the hash length is acceptable. */ +static psa_status_t psa_rsa_decode_md_type( psa_algorithm_t alg, + size_t hash_length, + mbedtls_md_type_t *md_alg ) +{ + psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH( alg ); + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_psa( hash_alg ); + *md_alg = mbedtls_md_get_type( md_info ); + + /* The Mbed TLS RSA module uses an unsigned int for hash length + * parameters. Validate that it fits so that we don't risk an + * overflow later. */ +#if SIZE_MAX > UINT_MAX + if( hash_length > UINT_MAX ) + return( PSA_ERROR_INVALID_ARGUMENT ); +#endif + +#if defined(MBEDTLS_PKCS1_V15) + /* For PKCS#1 v1.5 signature, if using a hash, the hash length + * must be correct. */ + if( PSA_ALG_IS_RSA_PKCS1V15_SIGN( alg ) && + alg != PSA_ALG_RSA_PKCS1V15_SIGN_RAW ) + { + if( md_info == NULL ) + return( PSA_ERROR_NOT_SUPPORTED ); + if( mbedtls_md_get_size( md_info ) != hash_length ) + return( PSA_ERROR_INVALID_ARGUMENT ); + } +#endif /* MBEDTLS_PKCS1_V15 */ + +#if defined(MBEDTLS_PKCS1_V21) + /* PSS requires a hash internally. */ + if( PSA_ALG_IS_RSA_PSS( alg ) ) + { + if( md_info == NULL ) + return( PSA_ERROR_NOT_SUPPORTED ); + } +#endif /* MBEDTLS_PKCS1_V21 */ + + return( PSA_SUCCESS ); +} + +static psa_status_t psa_rsa_sign( mbedtls_rsa_context *rsa, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + uint8_t *signature, + size_t signature_size, + size_t *signature_length ) +{ + psa_status_t status; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_md_type_t md_alg; + + status = psa_rsa_decode_md_type( alg, hash_length, &md_alg ); + if( status != PSA_SUCCESS ) + return( status ); + + if( signature_size < mbedtls_rsa_get_len( rsa ) ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); + +#if defined(MBEDTLS_PKCS1_V15) + if( PSA_ALG_IS_RSA_PKCS1V15_SIGN( alg ) ) + { + mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V15, + MBEDTLS_MD_NONE ); + ret = mbedtls_rsa_pkcs1_sign( rsa, + mbedtls_ctr_drbg_random, + &global_data.ctr_drbg, + MBEDTLS_RSA_PRIVATE, + md_alg, + (unsigned int) hash_length, + hash, + signature ); + } + else +#endif /* MBEDTLS_PKCS1_V15 */ +#if defined(MBEDTLS_PKCS1_V21) + if( PSA_ALG_IS_RSA_PSS( alg ) ) + { + mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V21, md_alg ); + ret = mbedtls_rsa_rsassa_pss_sign( rsa, + mbedtls_ctr_drbg_random, + &global_data.ctr_drbg, + MBEDTLS_RSA_PRIVATE, + MBEDTLS_MD_NONE, + (unsigned int) hash_length, + hash, + signature ); + } + else +#endif /* MBEDTLS_PKCS1_V21 */ + { + return( PSA_ERROR_INVALID_ARGUMENT ); + } + + if( ret == 0 ) + *signature_length = mbedtls_rsa_get_len( rsa ); + return( mbedtls_to_psa_error( ret ) ); +} + +static psa_status_t psa_rsa_verify( mbedtls_rsa_context *rsa, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + const uint8_t *signature, + size_t signature_length ) +{ + psa_status_t status; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_md_type_t md_alg; + + status = psa_rsa_decode_md_type( alg, hash_length, &md_alg ); + if( status != PSA_SUCCESS ) + return( status ); + + if( signature_length != mbedtls_rsa_get_len( rsa ) ) + return( PSA_ERROR_INVALID_SIGNATURE ); + +#if defined(MBEDTLS_PKCS1_V15) + if( PSA_ALG_IS_RSA_PKCS1V15_SIGN( alg ) ) + { + mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V15, + MBEDTLS_MD_NONE ); + ret = mbedtls_rsa_pkcs1_verify( rsa, + mbedtls_ctr_drbg_random, + &global_data.ctr_drbg, + MBEDTLS_RSA_PUBLIC, + md_alg, + (unsigned int) hash_length, + hash, + signature ); + } + else +#endif /* MBEDTLS_PKCS1_V15 */ +#if defined(MBEDTLS_PKCS1_V21) + if( PSA_ALG_IS_RSA_PSS( alg ) ) + { + mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V21, md_alg ); + ret = mbedtls_rsa_rsassa_pss_verify( rsa, + mbedtls_ctr_drbg_random, + &global_data.ctr_drbg, + MBEDTLS_RSA_PUBLIC, + MBEDTLS_MD_NONE, + (unsigned int) hash_length, + hash, + signature ); + } + else +#endif /* MBEDTLS_PKCS1_V21 */ + { + return( PSA_ERROR_INVALID_ARGUMENT ); + } + + /* Mbed TLS distinguishes "invalid padding" from "valid padding but + * the rest of the signature is invalid". This has little use in + * practice and PSA doesn't report this distinction. */ + if( ret == MBEDTLS_ERR_RSA_INVALID_PADDING ) + return( PSA_ERROR_INVALID_SIGNATURE ); + return( mbedtls_to_psa_error( ret ) ); +} +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) +/* `ecp` cannot be const because `ecp->grp` needs to be non-const + * for mbedtls_ecdsa_sign() and mbedtls_ecdsa_sign_det() + * (even though these functions don't modify it). */ +static psa_status_t psa_ecdsa_sign( mbedtls_ecp_keypair *ecp, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + uint8_t *signature, + size_t signature_size, + size_t *signature_length ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi r, s; + size_t curve_bytes = PSA_BITS_TO_BYTES( ecp->grp.pbits ); + mbedtls_mpi_init( &r ); + mbedtls_mpi_init( &s ); + + if( signature_size < 2 * curve_bytes ) + { + ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; + goto cleanup; + } + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) + if( PSA_ALG_DSA_IS_DETERMINISTIC( alg ) ) + { + psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH( alg ); + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_psa( hash_alg ); + mbedtls_md_type_t md_alg = mbedtls_md_get_type( md_info ); + MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign_det_ext( &ecp->grp, &r, &s, + &ecp->d, hash, + hash_length, md_alg, + mbedtls_ctr_drbg_random, + &global_data.ctr_drbg ) ); + } + else +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */ + { + (void) alg; + MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ecp->grp, &r, &s, &ecp->d, + hash, hash_length, + mbedtls_ctr_drbg_random, + &global_data.ctr_drbg ) ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &r, + signature, + curve_bytes ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &s, + signature + curve_bytes, + curve_bytes ) ); + +cleanup: + mbedtls_mpi_free( &r ); + mbedtls_mpi_free( &s ); + if( ret == 0 ) + *signature_length = 2 * curve_bytes; + return( mbedtls_to_psa_error( ret ) ); +} + +static psa_status_t psa_ecdsa_verify( mbedtls_ecp_keypair *ecp, + const uint8_t *hash, + size_t hash_length, + const uint8_t *signature, + size_t signature_length ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi r, s; + size_t curve_bytes = PSA_BITS_TO_BYTES( ecp->grp.pbits ); + mbedtls_mpi_init( &r ); + mbedtls_mpi_init( &s ); + + if( signature_length != 2 * curve_bytes ) + return( PSA_ERROR_INVALID_SIGNATURE ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r, + signature, + curve_bytes ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &s, + signature + curve_bytes, + curve_bytes ) ); + + /* Check whether the public part is loaded. If not, load it. */ + if( mbedtls_ecp_is_zero( &ecp->Q ) ) + { + MBEDTLS_MPI_CHK( + mbedtls_ecp_mul( &ecp->grp, &ecp->Q, &ecp->d, &ecp->grp.G, + mbedtls_ctr_drbg_random, &global_data.ctr_drbg ) ); + } + + ret = mbedtls_ecdsa_verify( &ecp->grp, hash, hash_length, + &ecp->Q, &r, &s ); + +cleanup: + mbedtls_mpi_free( &r ); + mbedtls_mpi_free( &s ); + return( mbedtls_to_psa_error( ret ) ); +} +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA */ + +psa_status_t psa_sign_hash( psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + uint8_t *signature, + size_t signature_size, + size_t *signature_length ) +{ + psa_key_slot_t *slot; + psa_status_t status; + + *signature_length = signature_size; + /* Immediately reject a zero-length signature buffer. This guarantees + * that signature must be a valid pointer. (On the other hand, the hash + * buffer can in principle be empty since it doesn't actually have + * to be a hash.) */ + if( signature_size == 0 ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); + + status = psa_get_key_from_slot( handle, &slot, PSA_KEY_USAGE_SIGN_HASH, alg ); + if( status != PSA_SUCCESS ) + goto exit; + if( ! PSA_KEY_TYPE_IS_KEY_PAIR( slot->attr.type ) ) + { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + /* Try any of the available accelerators first */ + status = psa_driver_wrapper_sign_hash( slot, + alg, + hash, + hash_length, + signature, + signature_size, + signature_length ); + if( status != PSA_ERROR_NOT_SUPPORTED || + psa_key_lifetime_is_external( slot->attr.lifetime ) ) + goto exit; + + /* If the operation was not supported by any accelerator, try fallback. */ +#if defined(MBEDTLS_RSA_C) + if( slot->attr.type == PSA_KEY_TYPE_RSA_KEY_PAIR ) + { + mbedtls_rsa_context *rsa = NULL; + + status = psa_load_rsa_representation( slot->attr.type, + slot->data.key.data, + slot->data.key.bytes, + &rsa ); + if( status != PSA_SUCCESS ) + goto exit; + + status = psa_rsa_sign( rsa, + alg, + hash, hash_length, + signature, signature_size, + signature_length ); + + mbedtls_rsa_free( rsa ); + mbedtls_free( rsa ); + } + else +#endif /* defined(MBEDTLS_RSA_C) */ +#if defined(MBEDTLS_ECP_C) + if( PSA_KEY_TYPE_IS_ECC( slot->attr.type ) ) + { +#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) + if( +#if defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) + PSA_ALG_IS_ECDSA( alg ) +#else + PSA_ALG_IS_RANDOMIZED_ECDSA( alg ) +#endif + ) + { + mbedtls_ecp_keypair *ecp = NULL; + status = psa_load_ecp_representation( slot->attr.type, + slot->data.key.data, + slot->data.key.bytes, + &ecp ); + if( status != PSA_SUCCESS ) + goto exit; + status = psa_ecdsa_sign( ecp, + alg, + hash, hash_length, + signature, signature_size, + signature_length ); + mbedtls_ecp_keypair_free( ecp ); + mbedtls_free( ecp ); + } + else +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) */ + { + status = PSA_ERROR_INVALID_ARGUMENT; + } + } + else +#endif /* defined(MBEDTLS_ECP_C) */ + { + status = PSA_ERROR_NOT_SUPPORTED; + } + +exit: + /* Fill the unused part of the output buffer (the whole buffer on error, + * the trailing part on success) with something that isn't a valid mac + * (barring an attack on the mac and deliberately-crafted input), + * in case the caller doesn't check the return status properly. */ + if( status == PSA_SUCCESS ) + memset( signature + *signature_length, '!', + signature_size - *signature_length ); + else + memset( signature, '!', signature_size ); + /* If signature_size is 0 then we have nothing to do. We must not call + * memset because signature may be NULL in this case. */ + return( status ); +} + +psa_status_t psa_verify_hash( psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + const uint8_t *signature, + size_t signature_length ) +{ + psa_key_slot_t *slot; + psa_status_t status; + + status = psa_get_key_from_slot( handle, &slot, PSA_KEY_USAGE_VERIFY_HASH, alg ); + if( status != PSA_SUCCESS ) + return( status ); + + /* Try any of the available accelerators first */ + status = psa_driver_wrapper_verify_hash( slot, + alg, + hash, + hash_length, + signature, + signature_length ); + if( status != PSA_ERROR_NOT_SUPPORTED || + psa_key_lifetime_is_external( slot->attr.lifetime ) ) + return status; + +#if defined(MBEDTLS_RSA_C) + if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) ) + { + mbedtls_rsa_context *rsa = NULL; + + status = psa_load_rsa_representation( slot->attr.type, + slot->data.key.data, + slot->data.key.bytes, + &rsa ); + if( status != PSA_SUCCESS ) + return( status ); + + status = psa_rsa_verify( rsa, + alg, + hash, hash_length, + signature, signature_length ); + mbedtls_rsa_free( rsa ); + mbedtls_free( rsa ); + return( status ); + } + else +#endif /* defined(MBEDTLS_RSA_C) */ +#if defined(MBEDTLS_ECP_C) + if( PSA_KEY_TYPE_IS_ECC( slot->attr.type ) ) + { +#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) + if( PSA_ALG_IS_ECDSA( alg ) ) + { + mbedtls_ecp_keypair *ecp = NULL; + status = psa_load_ecp_representation( slot->attr.type, + slot->data.key.data, + slot->data.key.bytes, + &ecp ); + if( status != PSA_SUCCESS ) + return( status ); + status = psa_ecdsa_verify( ecp, + hash, hash_length, + signature, signature_length ); + mbedtls_ecp_keypair_free( ecp ); + mbedtls_free( ecp ); + return( status ); + } + else +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */ + { + return( PSA_ERROR_INVALID_ARGUMENT ); + } + } + else +#endif /* defined(MBEDTLS_ECP_C) */ + { + return( PSA_ERROR_NOT_SUPPORTED ); + } +} + +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21) +static void psa_rsa_oaep_set_padding_mode( psa_algorithm_t alg, + mbedtls_rsa_context *rsa ) +{ + psa_algorithm_t hash_alg = PSA_ALG_RSA_OAEP_GET_HASH( alg ); + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_psa( hash_alg ); + mbedtls_md_type_t md_alg = mbedtls_md_get_type( md_info ); + mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V21, md_alg ); +} +#endif /* defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21) */ + +psa_status_t psa_asymmetric_encrypt( psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *salt, + size_t salt_length, + uint8_t *output, + size_t output_size, + size_t *output_length ) +{ + psa_key_slot_t *slot; + psa_status_t status; + + (void) input; + (void) input_length; + (void) salt; + (void) output; + (void) output_size; + + *output_length = 0; + + if( ! PSA_ALG_IS_RSA_OAEP( alg ) && salt_length != 0 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + status = psa_get_transparent_key( handle, &slot, PSA_KEY_USAGE_ENCRYPT, alg ); + if( status != PSA_SUCCESS ) + return( status ); + if( ! ( PSA_KEY_TYPE_IS_PUBLIC_KEY( slot->attr.type ) || + PSA_KEY_TYPE_IS_KEY_PAIR( slot->attr.type ) ) ) + return( PSA_ERROR_INVALID_ARGUMENT ); + +#if defined(MBEDTLS_RSA_C) + if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) ) + { + mbedtls_rsa_context *rsa = NULL; + status = psa_load_rsa_representation( slot->attr.type, + slot->data.key.data, + slot->data.key.bytes, + &rsa ); + if( status != PSA_SUCCESS ) + goto rsa_exit; + + if( output_size < mbedtls_rsa_get_len( rsa ) ) + { + status = PSA_ERROR_BUFFER_TOO_SMALL; + goto rsa_exit; + } +#if defined(MBEDTLS_PKCS1_V15) + if( alg == PSA_ALG_RSA_PKCS1V15_CRYPT ) + { + status = mbedtls_to_psa_error( + mbedtls_rsa_pkcs1_encrypt( rsa, + mbedtls_ctr_drbg_random, + &global_data.ctr_drbg, + MBEDTLS_RSA_PUBLIC, + input_length, + input, + output ) ); + } + else +#endif /* MBEDTLS_PKCS1_V15 */ +#if defined(MBEDTLS_PKCS1_V21) + if( PSA_ALG_IS_RSA_OAEP( alg ) ) + { + psa_rsa_oaep_set_padding_mode( alg, rsa ); + status = mbedtls_to_psa_error( + mbedtls_rsa_rsaes_oaep_encrypt( rsa, + mbedtls_ctr_drbg_random, + &global_data.ctr_drbg, + MBEDTLS_RSA_PUBLIC, + salt, salt_length, + input_length, + input, + output ) ); + } + else +#endif /* MBEDTLS_PKCS1_V21 */ + { + status = PSA_ERROR_INVALID_ARGUMENT; + goto rsa_exit; + } +rsa_exit: + if( status == PSA_SUCCESS ) + *output_length = mbedtls_rsa_get_len( rsa ); + + mbedtls_rsa_free( rsa ); + mbedtls_free( rsa ); + return( status ); + } + else +#endif /* defined(MBEDTLS_RSA_C) */ + { + return( PSA_ERROR_NOT_SUPPORTED ); + } +} + +psa_status_t psa_asymmetric_decrypt( psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *salt, + size_t salt_length, + uint8_t *output, + size_t output_size, + size_t *output_length ) +{ + psa_key_slot_t *slot; + psa_status_t status; + + (void) input; + (void) input_length; + (void) salt; + (void) output; + (void) output_size; + + *output_length = 0; + + if( ! PSA_ALG_IS_RSA_OAEP( alg ) && salt_length != 0 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + status = psa_get_transparent_key( handle, &slot, PSA_KEY_USAGE_DECRYPT, alg ); + if( status != PSA_SUCCESS ) + return( status ); + if( ! PSA_KEY_TYPE_IS_KEY_PAIR( slot->attr.type ) ) + return( PSA_ERROR_INVALID_ARGUMENT ); + +#if defined(MBEDTLS_RSA_C) + if( slot->attr.type == PSA_KEY_TYPE_RSA_KEY_PAIR ) + { + mbedtls_rsa_context *rsa = NULL; + status = psa_load_rsa_representation( slot->attr.type, + slot->data.key.data, + slot->data.key.bytes, + &rsa ); + if( status != PSA_SUCCESS ) + return( status ); + + if( input_length != mbedtls_rsa_get_len( rsa ) ) + { + status = PSA_ERROR_INVALID_ARGUMENT; + goto rsa_exit; + } + +#if defined(MBEDTLS_PKCS1_V15) + if( alg == PSA_ALG_RSA_PKCS1V15_CRYPT ) + { + status = mbedtls_to_psa_error( + mbedtls_rsa_pkcs1_decrypt( rsa, + mbedtls_ctr_drbg_random, + &global_data.ctr_drbg, + MBEDTLS_RSA_PRIVATE, + output_length, + input, + output, + output_size ) ); + } + else +#endif /* MBEDTLS_PKCS1_V15 */ +#if defined(MBEDTLS_PKCS1_V21) + if( PSA_ALG_IS_RSA_OAEP( alg ) ) + { + psa_rsa_oaep_set_padding_mode( alg, rsa ); + status = mbedtls_to_psa_error( + mbedtls_rsa_rsaes_oaep_decrypt( rsa, + mbedtls_ctr_drbg_random, + &global_data.ctr_drbg, + MBEDTLS_RSA_PRIVATE, + salt, salt_length, + output_length, + input, + output, + output_size ) ); + } + else +#endif /* MBEDTLS_PKCS1_V21 */ + { + status = PSA_ERROR_INVALID_ARGUMENT; + } + +rsa_exit: + mbedtls_rsa_free( rsa ); + mbedtls_free( rsa ); + return( status ); + } + else +#endif /* defined(MBEDTLS_RSA_C) */ + { + return( PSA_ERROR_NOT_SUPPORTED ); + } +} + + + +/****************************************************************/ +/* Symmetric cryptography */ +/****************************************************************/ + +static psa_status_t psa_cipher_setup( psa_cipher_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg, + mbedtls_operation_t cipher_operation ) +{ + int ret = 0; + psa_status_t status = PSA_ERROR_GENERIC_ERROR; + psa_key_slot_t *slot; + size_t key_bits; + const mbedtls_cipher_info_t *cipher_info = NULL; + psa_key_usage_t usage = ( cipher_operation == MBEDTLS_ENCRYPT ? + PSA_KEY_USAGE_ENCRYPT : + PSA_KEY_USAGE_DECRYPT ); + + /* A context must be freshly initialized before it can be set up. */ + if( operation->alg != 0 ) + return( PSA_ERROR_BAD_STATE ); + + /* The requested algorithm must be one that can be processed by cipher. */ + if( ! PSA_ALG_IS_CIPHER( alg ) ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + /* Fetch key material from key storage. */ + status = psa_get_key_from_slot( handle, &slot, usage, alg ); + if( status != PSA_SUCCESS ) + goto exit; + + /* Initialize the operation struct members, except for alg. The alg member + * is used to indicate to psa_cipher_abort that there are resources to free, + * so we only set it after resources have been allocated/initialized. */ + operation->key_set = 0; + operation->iv_set = 0; + operation->mbedtls_in_use = 0; + operation->iv_size = 0; + operation->block_size = 0; + if( alg == PSA_ALG_ECB_NO_PADDING ) + operation->iv_required = 0; + else + operation->iv_required = 1; + + /* Try doing the operation through a driver before using software fallback. */ + if( cipher_operation == MBEDTLS_ENCRYPT ) + status = psa_driver_wrapper_cipher_encrypt_setup( &operation->ctx.driver, + slot, + alg ); + else + status = psa_driver_wrapper_cipher_decrypt_setup( &operation->ctx.driver, + slot, + alg ); + + if( status == PSA_SUCCESS ) + { + /* Once the driver context is initialised, it needs to be freed using + * psa_cipher_abort. Indicate this through setting alg. */ + operation->alg = alg; + } + + if( status != PSA_ERROR_NOT_SUPPORTED || + psa_key_lifetime_is_external( slot->attr.lifetime ) ) + goto exit; + + /* Proceed with initializing an mbed TLS cipher context if no driver is + * available for the given algorithm & key. */ + mbedtls_cipher_init( &operation->ctx.cipher ); + + /* Once the cipher context is initialised, it needs to be freed using + * psa_cipher_abort. Indicate there is something to be freed through setting + * alg, and indicate the operation is being done using mbedtls crypto through + * setting mbedtls_in_use. */ + operation->alg = alg; + operation->mbedtls_in_use = 1; + + key_bits = psa_get_key_slot_bits( slot ); + cipher_info = mbedtls_cipher_info_from_psa( alg, slot->attr.type, key_bits, NULL ); + if( cipher_info == NULL ) + { + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } + + ret = mbedtls_cipher_setup( &operation->ctx.cipher, cipher_info ); + if( ret != 0 ) + goto exit; + +#if defined(MBEDTLS_DES_C) + if( slot->attr.type == PSA_KEY_TYPE_DES && key_bits == 128 ) + { + /* Two-key Triple-DES is 3-key Triple-DES with K1=K3 */ + uint8_t keys[24]; + memcpy( keys, slot->data.key.data, 16 ); + memcpy( keys + 16, slot->data.key.data, 8 ); + ret = mbedtls_cipher_setkey( &operation->ctx.cipher, + keys, + 192, cipher_operation ); + } + else +#endif + { + ret = mbedtls_cipher_setkey( &operation->ctx.cipher, + slot->data.key.data, + (int) key_bits, cipher_operation ); + } + if( ret != 0 ) + goto exit; + +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) + switch( alg ) + { + case PSA_ALG_CBC_NO_PADDING: + ret = mbedtls_cipher_set_padding_mode( &operation->ctx.cipher, + MBEDTLS_PADDING_NONE ); + break; + case PSA_ALG_CBC_PKCS7: + ret = mbedtls_cipher_set_padding_mode( &operation->ctx.cipher, + MBEDTLS_PADDING_PKCS7 ); + break; + default: + /* The algorithm doesn't involve padding. */ + ret = 0; + break; + } + if( ret != 0 ) + goto exit; +#endif //MBEDTLS_CIPHER_MODE_WITH_PADDING + + operation->block_size = ( PSA_ALG_IS_STREAM_CIPHER( alg ) ? 1 : + PSA_BLOCK_CIPHER_BLOCK_SIZE( slot->attr.type ) ); + if( ( alg & PSA_ALG_CIPHER_FROM_BLOCK_FLAG ) != 0 && + alg != PSA_ALG_ECB_NO_PADDING ) + { + operation->iv_size = PSA_BLOCK_CIPHER_BLOCK_SIZE( slot->attr.type ); + } +#if defined(MBEDTLS_CHACHA20_C) + else + if( alg == PSA_ALG_CHACHA20 ) + operation->iv_size = 12; +#endif + + status = PSA_SUCCESS; + +exit: + if( ret != 0 ) + status = mbedtls_to_psa_error( ret ); + if( status == PSA_SUCCESS ) + { + /* Update operation flags for both driver and software implementations */ + operation->key_set = 1; + } + else + psa_cipher_abort( operation ); + return( status ); +} + +psa_status_t psa_cipher_encrypt_setup( psa_cipher_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg ) +{ + return( psa_cipher_setup( operation, handle, alg, MBEDTLS_ENCRYPT ) ); +} + +psa_status_t psa_cipher_decrypt_setup( psa_cipher_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg ) +{ + return( psa_cipher_setup( operation, handle, alg, MBEDTLS_DECRYPT ) ); +} + +psa_status_t psa_cipher_generate_iv( psa_cipher_operation_t *operation, + uint8_t *iv, + size_t iv_size, + size_t *iv_length ) +{ + psa_status_t status; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + if( operation->iv_set || ! operation->iv_required ) + { + return( PSA_ERROR_BAD_STATE ); + } + + if( operation->mbedtls_in_use == 0 ) + { + status = psa_driver_wrapper_cipher_generate_iv( &operation->ctx.driver, + iv, + iv_size, + iv_length ); + goto exit; + } + + if( iv_size < operation->iv_size ) + { + status = PSA_ERROR_BUFFER_TOO_SMALL; + goto exit; + } + ret = mbedtls_ctr_drbg_random( &global_data.ctr_drbg, + iv, operation->iv_size ); + if( ret != 0 ) + { + status = mbedtls_to_psa_error( ret ); + goto exit; + } + + *iv_length = operation->iv_size; + status = psa_cipher_set_iv( operation, iv, *iv_length ); + +exit: + if( status == PSA_SUCCESS ) + operation->iv_set = 1; + else + psa_cipher_abort( operation ); + return( status ); +} + +psa_status_t psa_cipher_set_iv( psa_cipher_operation_t *operation, + const uint8_t *iv, + size_t iv_length ) +{ + psa_status_t status; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + if( operation->iv_set || ! operation->iv_required ) + { + return( PSA_ERROR_BAD_STATE ); + } + + if( operation->mbedtls_in_use == 0 ) + { + status = psa_driver_wrapper_cipher_set_iv( &operation->ctx.driver, + iv, + iv_length ); + goto exit; + } + + if( iv_length != operation->iv_size ) + { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + ret = mbedtls_cipher_set_iv( &operation->ctx.cipher, iv, iv_length ); + status = mbedtls_to_psa_error( ret ); +exit: + if( status == PSA_SUCCESS ) + operation->iv_set = 1; + else + psa_cipher_abort( operation ); + return( status ); +} + +/* Process input for which the algorithm is set to ECB mode. This requires + * manual processing, since the PSA API is defined as being able to process + * arbitrary-length calls to psa_cipher_update() with ECB mode, but the + * underlying mbedtls_cipher_update only takes full blocks. */ +static psa_status_t psa_cipher_update_ecb_internal( + mbedtls_cipher_context_t *ctx, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + size_t block_size = ctx->cipher_info->block_size; + size_t internal_output_length = 0; + *output_length = 0; + + if( input_length == 0 ) + { + status = PSA_SUCCESS; + goto exit; + } + + if( ctx->unprocessed_len > 0 ) + { + /* Fill up to block size, and run the block if there's a full one. */ + size_t bytes_to_copy = block_size - ctx->unprocessed_len; + + if( input_length < bytes_to_copy ) + bytes_to_copy = input_length; + + memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), + input, bytes_to_copy ); + input_length -= bytes_to_copy; + input += bytes_to_copy; + ctx->unprocessed_len += bytes_to_copy; + + if( ctx->unprocessed_len == block_size ) + { + status = mbedtls_to_psa_error( + mbedtls_cipher_update( ctx, + ctx->unprocessed_data, + block_size, + output, &internal_output_length ) ); + + if( status != PSA_SUCCESS ) + goto exit; + + output += internal_output_length; + output_size -= internal_output_length; + *output_length += internal_output_length; + ctx->unprocessed_len = 0; + } + } + + while( input_length >= block_size ) + { + /* Run all full blocks we have, one by one */ + status = mbedtls_to_psa_error( + mbedtls_cipher_update( ctx, input, + block_size, + output, &internal_output_length ) ); + + if( status != PSA_SUCCESS ) + goto exit; + + input_length -= block_size; + input += block_size; + + output += internal_output_length; + output_size -= internal_output_length; + *output_length += internal_output_length; + } + + if( input_length > 0 ) + { + /* Save unprocessed bytes for later processing */ + memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), + input, input_length ); + ctx->unprocessed_len += input_length; + } + + status = PSA_SUCCESS; + +exit: + return( status ); +} + +psa_status_t psa_cipher_update( psa_cipher_operation_t *operation, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + size_t expected_output_size; + if( operation->alg == 0 ) + { + return( PSA_ERROR_BAD_STATE ); + } + if( operation->iv_required && ! operation->iv_set ) + { + return( PSA_ERROR_BAD_STATE ); + } + + if( operation->mbedtls_in_use == 0 ) + { + status = psa_driver_wrapper_cipher_update( &operation->ctx.driver, + input, + input_length, + output, + output_size, + output_length ); + goto exit; + } + + if( ! PSA_ALG_IS_STREAM_CIPHER( operation->alg ) ) + { + /* Take the unprocessed partial block left over from previous + * update calls, if any, plus the input to this call. Remove + * the last partial block, if any. You get the data that will be + * output in this call. */ + expected_output_size = + ( operation->ctx.cipher.unprocessed_len + input_length ) + / operation->block_size * operation->block_size; + } + else + { + expected_output_size = input_length; + } + + if( output_size < expected_output_size ) + { + status = PSA_ERROR_BUFFER_TOO_SMALL; + goto exit; + } + + if( operation->alg == PSA_ALG_ECB_NO_PADDING ) + { + /* mbedtls_cipher_update has an API inconsistency: it will only + * process a single block at a time in ECB mode. Abstract away that + * inconsistency here to match the PSA API behaviour. */ + status = psa_cipher_update_ecb_internal( &operation->ctx.cipher, + input, + input_length, + output, + output_size, + output_length ); + } + else + { + status = mbedtls_to_psa_error( + mbedtls_cipher_update( &operation->ctx.cipher, input, + input_length, output, output_length ) ); + } +exit: + if( status != PSA_SUCCESS ) + psa_cipher_abort( operation ); + return( status ); +} + +psa_status_t psa_cipher_finish( psa_cipher_operation_t *operation, + uint8_t *output, + size_t output_size, + size_t *output_length ) +{ + psa_status_t status = PSA_ERROR_GENERIC_ERROR; + uint8_t temp_output_buffer[MBEDTLS_MAX_BLOCK_LENGTH]; + if( operation->alg == 0 ) + { + return( PSA_ERROR_BAD_STATE ); + } + if( operation->iv_required && ! operation->iv_set ) + { + return( PSA_ERROR_BAD_STATE ); + } + + if( operation->mbedtls_in_use == 0 ) + { + status = psa_driver_wrapper_cipher_finish( &operation->ctx.driver, + output, + output_size, + output_length ); + goto exit; + } + + if( operation->ctx.cipher.unprocessed_len != 0 ) + { + if( operation->alg == PSA_ALG_ECB_NO_PADDING || + operation->alg == PSA_ALG_CBC_NO_PADDING ) + { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + } + + status = mbedtls_to_psa_error( + mbedtls_cipher_finish( &operation->ctx.cipher, + temp_output_buffer, + output_length ) ); + if( status != PSA_SUCCESS ) + goto exit; + + if( *output_length == 0 ) + ; /* Nothing to copy. Note that output may be NULL in this case. */ + else if( output_size >= *output_length ) + memcpy( output, temp_output_buffer, *output_length ); + else + status = PSA_ERROR_BUFFER_TOO_SMALL; + +exit: + if( operation->mbedtls_in_use == 1 ) + mbedtls_platform_zeroize( temp_output_buffer, sizeof( temp_output_buffer ) ); + + if( status == PSA_SUCCESS ) + return( psa_cipher_abort( operation ) ); + else + { + *output_length = 0; + (void) psa_cipher_abort( operation ); + + return( status ); + } +} + +psa_status_t psa_cipher_abort( psa_cipher_operation_t *operation ) +{ + if( operation->alg == 0 ) + { + /* The object has (apparently) been initialized but it is not (yet) + * in use. It's ok to call abort on such an object, and there's + * nothing to do. */ + return( PSA_SUCCESS ); + } + + /* Sanity check (shouldn't happen: operation->alg should + * always have been initialized to a valid value). */ + if( ! PSA_ALG_IS_CIPHER( operation->alg ) ) + return( PSA_ERROR_BAD_STATE ); + + if( operation->mbedtls_in_use == 0 ) + psa_driver_wrapper_cipher_abort( &operation->ctx.driver ); + else + mbedtls_cipher_free( &operation->ctx.cipher ); + + operation->alg = 0; + operation->key_set = 0; + operation->iv_set = 0; + operation->mbedtls_in_use = 0; + operation->iv_size = 0; + operation->block_size = 0; + operation->iv_required = 0; + + return( PSA_SUCCESS ); +} + + + + +/****************************************************************/ +/* AEAD */ +/****************************************************************/ + +typedef struct +{ + psa_key_slot_t *slot; + const mbedtls_cipher_info_t *cipher_info; + union + { +#if defined(MBEDTLS_CCM_C) + mbedtls_ccm_context ccm; +#endif /* MBEDTLS_CCM_C */ +#if defined(MBEDTLS_GCM_C) + mbedtls_gcm_context gcm; +#endif /* MBEDTLS_GCM_C */ +#if defined(MBEDTLS_CHACHAPOLY_C) + mbedtls_chachapoly_context chachapoly; +#endif /* MBEDTLS_CHACHAPOLY_C */ + } ctx; + psa_algorithm_t core_alg; + uint8_t full_tag_length; + uint8_t tag_length; +} aead_operation_t; + +static void psa_aead_abort_internal( aead_operation_t *operation ) +{ + switch( operation->core_alg ) + { +#if defined(MBEDTLS_CCM_C) + case PSA_ALG_CCM: + mbedtls_ccm_free( &operation->ctx.ccm ); + break; +#endif /* MBEDTLS_CCM_C */ +#if defined(MBEDTLS_GCM_C) + case PSA_ALG_GCM: + mbedtls_gcm_free( &operation->ctx.gcm ); + break; +#endif /* MBEDTLS_GCM_C */ + } +} + +static psa_status_t psa_aead_setup( aead_operation_t *operation, + psa_key_handle_t handle, + psa_key_usage_t usage, + psa_algorithm_t alg ) +{ + psa_status_t status; + size_t key_bits; + mbedtls_cipher_id_t cipher_id; + + status = psa_get_transparent_key( handle, &operation->slot, usage, alg ); + if( status != PSA_SUCCESS ) + return( status ); + + key_bits = psa_get_key_slot_bits( operation->slot ); + + operation->cipher_info = + mbedtls_cipher_info_from_psa( alg, operation->slot->attr.type, key_bits, + &cipher_id ); + if( operation->cipher_info == NULL ) + return( PSA_ERROR_NOT_SUPPORTED ); + + switch( PSA_ALG_AEAD_WITH_TAG_LENGTH( alg, 0 ) ) + { +#if defined(MBEDTLS_CCM_C) + case PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_CCM, 0 ): + operation->core_alg = PSA_ALG_CCM; + operation->full_tag_length = 16; + /* CCM allows the following tag lengths: 4, 6, 8, 10, 12, 14, 16. + * The call to mbedtls_ccm_encrypt_and_tag or + * mbedtls_ccm_auth_decrypt will validate the tag length. */ + if( PSA_BLOCK_CIPHER_BLOCK_SIZE( operation->slot->attr.type ) != 16 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + mbedtls_ccm_init( &operation->ctx.ccm ); + status = mbedtls_to_psa_error( + mbedtls_ccm_setkey( &operation->ctx.ccm, cipher_id, + operation->slot->data.key.data, + (unsigned int) key_bits ) ); + if( status != 0 ) + goto cleanup; + break; +#endif /* MBEDTLS_CCM_C */ + +#if defined(MBEDTLS_GCM_C) + case PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_GCM, 0 ): + operation->core_alg = PSA_ALG_GCM; + operation->full_tag_length = 16; + /* GCM allows the following tag lengths: 4, 8, 12, 13, 14, 15, 16. + * The call to mbedtls_gcm_crypt_and_tag or + * mbedtls_gcm_auth_decrypt will validate the tag length. */ + if( PSA_BLOCK_CIPHER_BLOCK_SIZE( operation->slot->attr.type ) != 16 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + mbedtls_gcm_init( &operation->ctx.gcm ); + status = mbedtls_to_psa_error( + mbedtls_gcm_setkey( &operation->ctx.gcm, cipher_id, + operation->slot->data.key.data, + (unsigned int) key_bits ) ); + if( status != 0 ) + goto cleanup; + break; +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CHACHAPOLY_C) + case PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_CHACHA20_POLY1305, 0 ): + operation->core_alg = PSA_ALG_CHACHA20_POLY1305; + operation->full_tag_length = 16; + /* We only support the default tag length. */ + if( alg != PSA_ALG_CHACHA20_POLY1305 ) + return( PSA_ERROR_NOT_SUPPORTED ); + mbedtls_chachapoly_init( &operation->ctx.chachapoly ); + status = mbedtls_to_psa_error( + mbedtls_chachapoly_setkey( &operation->ctx.chachapoly, + operation->slot->data.key.data ) ); + if( status != 0 ) + goto cleanup; + break; +#endif /* MBEDTLS_CHACHAPOLY_C */ + + default: + return( PSA_ERROR_NOT_SUPPORTED ); + } + + if( PSA_AEAD_TAG_LENGTH( alg ) > operation->full_tag_length ) + { + status = PSA_ERROR_INVALID_ARGUMENT; + goto cleanup; + } + operation->tag_length = PSA_AEAD_TAG_LENGTH( alg ); + + return( PSA_SUCCESS ); + +cleanup: + psa_aead_abort_internal( operation ); + return( status ); +} + +psa_status_t psa_aead_encrypt( psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *nonce, + size_t nonce_length, + const uint8_t *additional_data, + size_t additional_data_length, + const uint8_t *plaintext, + size_t plaintext_length, + uint8_t *ciphertext, + size_t ciphertext_size, + size_t *ciphertext_length ) +{ + psa_status_t status; + aead_operation_t operation; + uint8_t *tag; + + *ciphertext_length = 0; + + status = psa_aead_setup( &operation, handle, PSA_KEY_USAGE_ENCRYPT, alg ); + if( status != PSA_SUCCESS ) + return( status ); + + /* For all currently supported modes, the tag is at the end of the + * ciphertext. */ + if( ciphertext_size < ( plaintext_length + operation.tag_length ) ) + { + status = PSA_ERROR_BUFFER_TOO_SMALL; + goto exit; + } + tag = ciphertext + plaintext_length; + +#if defined(MBEDTLS_GCM_C) + if( operation.core_alg == PSA_ALG_GCM ) + { + status = mbedtls_to_psa_error( + mbedtls_gcm_crypt_and_tag( &operation.ctx.gcm, + MBEDTLS_GCM_ENCRYPT, + plaintext_length, + nonce, nonce_length, + additional_data, additional_data_length, + plaintext, ciphertext, + operation.tag_length, tag ) ); + } + else +#endif /* MBEDTLS_GCM_C */ +#if defined(MBEDTLS_CCM_C) + if( operation.core_alg == PSA_ALG_CCM ) + { + status = mbedtls_to_psa_error( + mbedtls_ccm_encrypt_and_tag( &operation.ctx.ccm, + plaintext_length, + nonce, nonce_length, + additional_data, + additional_data_length, + plaintext, ciphertext, + tag, operation.tag_length ) ); + } + else +#endif /* MBEDTLS_CCM_C */ +#if defined(MBEDTLS_CHACHAPOLY_C) + if( operation.core_alg == PSA_ALG_CHACHA20_POLY1305 ) + { + if( nonce_length != 12 || operation.tag_length != 16 ) + { + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } + status = mbedtls_to_psa_error( + mbedtls_chachapoly_encrypt_and_tag( &operation.ctx.chachapoly, + plaintext_length, + nonce, + additional_data, + additional_data_length, + plaintext, + ciphertext, + tag ) ); + } + else +#endif /* MBEDTLS_CHACHAPOLY_C */ + { + return( PSA_ERROR_NOT_SUPPORTED ); + } + + if( status != PSA_SUCCESS && ciphertext_size != 0 ) + memset( ciphertext, 0, ciphertext_size ); + +exit: + psa_aead_abort_internal( &operation ); + if( status == PSA_SUCCESS ) + *ciphertext_length = plaintext_length + operation.tag_length; + return( status ); +} + +/* Locate the tag in a ciphertext buffer containing the encrypted data + * followed by the tag. Return the length of the part preceding the tag in + * *plaintext_length. This is the size of the plaintext in modes where + * the encrypted data has the same size as the plaintext, such as + * CCM and GCM. */ +static psa_status_t psa_aead_unpadded_locate_tag( size_t tag_length, + const uint8_t *ciphertext, + size_t ciphertext_length, + size_t plaintext_size, + const uint8_t **p_tag ) +{ + size_t payload_length; + if( tag_length > ciphertext_length ) + return( PSA_ERROR_INVALID_ARGUMENT ); + payload_length = ciphertext_length - tag_length; + if( payload_length > plaintext_size ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); + *p_tag = ciphertext + payload_length; + return( PSA_SUCCESS ); +} + +psa_status_t psa_aead_decrypt( psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *nonce, + size_t nonce_length, + const uint8_t *additional_data, + size_t additional_data_length, + const uint8_t *ciphertext, + size_t ciphertext_length, + uint8_t *plaintext, + size_t plaintext_size, + size_t *plaintext_length ) +{ + psa_status_t status; + aead_operation_t operation; + const uint8_t *tag = NULL; + + *plaintext_length = 0; + + status = psa_aead_setup( &operation, handle, PSA_KEY_USAGE_DECRYPT, alg ); + if( status != PSA_SUCCESS ) + return( status ); + + status = psa_aead_unpadded_locate_tag( operation.tag_length, + ciphertext, ciphertext_length, + plaintext_size, &tag ); + if( status != PSA_SUCCESS ) + goto exit; + +#if defined(MBEDTLS_GCM_C) + if( operation.core_alg == PSA_ALG_GCM ) + { + status = mbedtls_to_psa_error( + mbedtls_gcm_auth_decrypt( &operation.ctx.gcm, + ciphertext_length - operation.tag_length, + nonce, nonce_length, + additional_data, + additional_data_length, + tag, operation.tag_length, + ciphertext, plaintext ) ); + } + else +#endif /* MBEDTLS_GCM_C */ +#if defined(MBEDTLS_CCM_C) + if( operation.core_alg == PSA_ALG_CCM ) + { + status = mbedtls_to_psa_error( + mbedtls_ccm_auth_decrypt( &operation.ctx.ccm, + ciphertext_length - operation.tag_length, + nonce, nonce_length, + additional_data, + additional_data_length, + ciphertext, plaintext, + tag, operation.tag_length ) ); + } + else +#endif /* MBEDTLS_CCM_C */ +#if defined(MBEDTLS_CHACHAPOLY_C) + if( operation.core_alg == PSA_ALG_CHACHA20_POLY1305 ) + { + if( nonce_length != 12 || operation.tag_length != 16 ) + { + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } + status = mbedtls_to_psa_error( + mbedtls_chachapoly_auth_decrypt( &operation.ctx.chachapoly, + ciphertext_length - operation.tag_length, + nonce, + additional_data, + additional_data_length, + tag, + ciphertext, + plaintext ) ); + } + else +#endif /* MBEDTLS_CHACHAPOLY_C */ + { + return( PSA_ERROR_NOT_SUPPORTED ); + } + + if( status != PSA_SUCCESS && plaintext_size != 0 ) + memset( plaintext, 0, plaintext_size ); + +exit: + psa_aead_abort_internal( &operation ); + if( status == PSA_SUCCESS ) + *plaintext_length = ciphertext_length - operation.tag_length; + return( status ); +} + + + +/****************************************************************/ +/* Generators */ +/****************************************************************/ + +#define HKDF_STATE_INIT 0 /* no input yet */ +#define HKDF_STATE_STARTED 1 /* got salt */ +#define HKDF_STATE_KEYED 2 /* got key */ +#define HKDF_STATE_OUTPUT 3 /* output started */ + +static psa_algorithm_t psa_key_derivation_get_kdf_alg( + const psa_key_derivation_operation_t *operation ) +{ + if ( PSA_ALG_IS_KEY_AGREEMENT( operation->alg ) ) + return( PSA_ALG_KEY_AGREEMENT_GET_KDF( operation->alg ) ); + else + return( operation->alg ); +} + + +psa_status_t psa_key_derivation_abort( psa_key_derivation_operation_t *operation ) +{ + psa_status_t status = PSA_SUCCESS; + psa_algorithm_t kdf_alg = psa_key_derivation_get_kdf_alg( operation ); + if( kdf_alg == 0 ) + { + /* The object has (apparently) been initialized but it is not + * in use. It's ok to call abort on such an object, and there's + * nothing to do. */ + } + else +#if defined(MBEDTLS_MD_C) + if( PSA_ALG_IS_HKDF( kdf_alg ) ) + { + mbedtls_free( operation->ctx.hkdf.info ); + status = psa_hmac_abort_internal( &operation->ctx.hkdf.hmac ); + } + else if( PSA_ALG_IS_TLS12_PRF( kdf_alg ) || + /* TLS-1.2 PSK-to-MS KDF uses the same core as TLS-1.2 PRF */ + PSA_ALG_IS_TLS12_PSK_TO_MS( kdf_alg ) ) + { + if( operation->ctx.tls12_prf.seed != NULL ) + { + mbedtls_platform_zeroize( operation->ctx.tls12_prf.seed, + operation->ctx.tls12_prf.seed_length ); + mbedtls_free( operation->ctx.tls12_prf.seed ); + } + + if( operation->ctx.tls12_prf.label != NULL ) + { + mbedtls_platform_zeroize( operation->ctx.tls12_prf.label, + operation->ctx.tls12_prf.label_length ); + mbedtls_free( operation->ctx.tls12_prf.label ); + } + + status = psa_hmac_abort_internal( &operation->ctx.tls12_prf.hmac ); + + /* We leave the fields Ai and output_block to be erased safely by the + * mbedtls_platform_zeroize() in the end of this function. */ + } + else +#endif /* MBEDTLS_MD_C */ + { + status = PSA_ERROR_BAD_STATE; + } + mbedtls_platform_zeroize( operation, sizeof( *operation ) ); + return( status ); +} + +psa_status_t psa_key_derivation_get_capacity(const psa_key_derivation_operation_t *operation, + size_t *capacity) +{ + if( operation->alg == 0 ) + { + /* This is a blank key derivation operation. */ + return( PSA_ERROR_BAD_STATE ); + } + + *capacity = operation->capacity; + return( PSA_SUCCESS ); +} + +psa_status_t psa_key_derivation_set_capacity( psa_key_derivation_operation_t *operation, + size_t capacity ) +{ + if( operation->alg == 0 ) + return( PSA_ERROR_BAD_STATE ); + if( capacity > operation->capacity ) + return( PSA_ERROR_INVALID_ARGUMENT ); + operation->capacity = capacity; + return( PSA_SUCCESS ); +} + +#if defined(MBEDTLS_MD_C) +/* Read some bytes from an HKDF-based operation. This performs a chunk + * of the expand phase of the HKDF algorithm. */ +static psa_status_t psa_key_derivation_hkdf_read( psa_hkdf_key_derivation_t *hkdf, + psa_algorithm_t hash_alg, + uint8_t *output, + size_t output_length ) +{ + uint8_t hash_length = PSA_HASH_SIZE( hash_alg ); + psa_status_t status; + + if( hkdf->state < HKDF_STATE_KEYED || ! hkdf->info_set ) + return( PSA_ERROR_BAD_STATE ); + hkdf->state = HKDF_STATE_OUTPUT; + + while( output_length != 0 ) + { + /* Copy what remains of the current block */ + uint8_t n = hash_length - hkdf->offset_in_block; + if( n > output_length ) + n = (uint8_t) output_length; + memcpy( output, hkdf->output_block + hkdf->offset_in_block, n ); + output += n; + output_length -= n; + hkdf->offset_in_block += n; + if( output_length == 0 ) + break; + /* We can't be wanting more output after block 0xff, otherwise + * the capacity check in psa_key_derivation_output_bytes() would have + * prevented this call. It could happen only if the operation + * object was corrupted or if this function is called directly + * inside the library. */ + if( hkdf->block_number == 0xff ) + return( PSA_ERROR_BAD_STATE ); + + /* We need a new block */ + ++hkdf->block_number; + hkdf->offset_in_block = 0; + status = psa_hmac_setup_internal( &hkdf->hmac, + hkdf->prk, hash_length, + hash_alg ); + if( status != PSA_SUCCESS ) + return( status ); + if( hkdf->block_number != 1 ) + { + status = psa_hash_update( &hkdf->hmac.hash_ctx, + hkdf->output_block, + hash_length ); + if( status != PSA_SUCCESS ) + return( status ); + } + status = psa_hash_update( &hkdf->hmac.hash_ctx, + hkdf->info, + hkdf->info_length ); + if( status != PSA_SUCCESS ) + return( status ); + status = psa_hash_update( &hkdf->hmac.hash_ctx, + &hkdf->block_number, 1 ); + if( status != PSA_SUCCESS ) + return( status ); + status = psa_hmac_finish_internal( &hkdf->hmac, + hkdf->output_block, + sizeof( hkdf->output_block ) ); + if( status != PSA_SUCCESS ) + return( status ); + } + + return( PSA_SUCCESS ); +} + +static psa_status_t psa_key_derivation_tls12_prf_generate_next_block( + psa_tls12_prf_key_derivation_t *tls12_prf, + psa_algorithm_t alg ) +{ + psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH( alg ); + uint8_t hash_length = PSA_HASH_SIZE( hash_alg ); + psa_hash_operation_t backup = PSA_HASH_OPERATION_INIT; + psa_status_t status, cleanup_status; + + /* We can't be wanting more output after block 0xff, otherwise + * the capacity check in psa_key_derivation_output_bytes() would have + * prevented this call. It could happen only if the operation + * object was corrupted or if this function is called directly + * inside the library. */ + if( tls12_prf->block_number == 0xff ) + return( PSA_ERROR_CORRUPTION_DETECTED ); + + /* We need a new block */ + ++tls12_prf->block_number; + tls12_prf->left_in_block = hash_length; + + /* Recall the definition of the TLS-1.2-PRF from RFC 5246: + * + * PRF(secret, label, seed) = P_(secret, label + seed) + * + * P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) + + * HMAC_hash(secret, A(2) + seed) + + * HMAC_hash(secret, A(3) + seed) + ... + * + * A(0) = seed + * A(i) = HMAC_hash(secret, A(i-1)) + * + * The `psa_tls12_prf_key_derivation` structure saves the block + * `HMAC_hash(secret, A(i) + seed)` from which the output + * is currently extracted as `output_block` and where i is + * `block_number`. + */ + + /* Save the hash context before using it, to preserve the hash state with + * only the inner padding in it. We need this, because inner padding depends + * on the key (secret in the RFC's terminology). */ + status = psa_hash_clone( &tls12_prf->hmac.hash_ctx, &backup ); + if( status != PSA_SUCCESS ) + goto cleanup; + + /* Calculate A(i) where i = tls12_prf->block_number. */ + if( tls12_prf->block_number == 1 ) + { + /* A(1) = HMAC_hash(secret, A(0)), where A(0) = seed. (The RFC overloads + * the variable seed and in this instance means it in the context of the + * P_hash function, where seed = label + seed.) */ + status = psa_hash_update( &tls12_prf->hmac.hash_ctx, + tls12_prf->label, tls12_prf->label_length ); + if( status != PSA_SUCCESS ) + goto cleanup; + status = psa_hash_update( &tls12_prf->hmac.hash_ctx, + tls12_prf->seed, tls12_prf->seed_length ); + if( status != PSA_SUCCESS ) + goto cleanup; + } + else + { + /* A(i) = HMAC_hash(secret, A(i-1)) */ + status = psa_hash_update( &tls12_prf->hmac.hash_ctx, + tls12_prf->Ai, hash_length ); + if( status != PSA_SUCCESS ) + goto cleanup; + } + + status = psa_hmac_finish_internal( &tls12_prf->hmac, + tls12_prf->Ai, hash_length ); + if( status != PSA_SUCCESS ) + goto cleanup; + status = psa_hash_clone( &backup, &tls12_prf->hmac.hash_ctx ); + if( status != PSA_SUCCESS ) + goto cleanup; + + /* Calculate HMAC_hash(secret, A(i) + label + seed). */ + status = psa_hash_update( &tls12_prf->hmac.hash_ctx, + tls12_prf->Ai, hash_length ); + if( status != PSA_SUCCESS ) + goto cleanup; + status = psa_hash_update( &tls12_prf->hmac.hash_ctx, + tls12_prf->label, tls12_prf->label_length ); + if( status != PSA_SUCCESS ) + goto cleanup; + status = psa_hash_update( &tls12_prf->hmac.hash_ctx, + tls12_prf->seed, tls12_prf->seed_length ); + if( status != PSA_SUCCESS ) + goto cleanup; + status = psa_hmac_finish_internal( &tls12_prf->hmac, + tls12_prf->output_block, hash_length ); + if( status != PSA_SUCCESS ) + goto cleanup; + status = psa_hash_clone( &backup, &tls12_prf->hmac.hash_ctx ); + if( status != PSA_SUCCESS ) + goto cleanup; + + +cleanup: + + cleanup_status = psa_hash_abort( &backup ); + if( status == PSA_SUCCESS && cleanup_status != PSA_SUCCESS ) + status = cleanup_status; + + return( status ); +} + +static psa_status_t psa_key_derivation_tls12_prf_read( + psa_tls12_prf_key_derivation_t *tls12_prf, + psa_algorithm_t alg, + uint8_t *output, + size_t output_length ) +{ + psa_algorithm_t hash_alg = PSA_ALG_TLS12_PRF_GET_HASH( alg ); + uint8_t hash_length = PSA_HASH_SIZE( hash_alg ); + psa_status_t status; + uint8_t offset, length; + + while( output_length != 0 ) + { + /* Check if we have fully processed the current block. */ + if( tls12_prf->left_in_block == 0 ) + { + status = psa_key_derivation_tls12_prf_generate_next_block( tls12_prf, + alg ); + if( status != PSA_SUCCESS ) + return( status ); + + continue; + } + + if( tls12_prf->left_in_block > output_length ) + length = (uint8_t) output_length; + else + length = tls12_prf->left_in_block; + + offset = hash_length - tls12_prf->left_in_block; + memcpy( output, tls12_prf->output_block + offset, length ); + output += length; + output_length -= length; + tls12_prf->left_in_block -= length; + } + + return( PSA_SUCCESS ); +} +#endif /* MBEDTLS_MD_C */ + +psa_status_t psa_key_derivation_output_bytes( + psa_key_derivation_operation_t *operation, + uint8_t *output, + size_t output_length ) +{ + psa_status_t status; + psa_algorithm_t kdf_alg = psa_key_derivation_get_kdf_alg( operation ); + + if( operation->alg == 0 ) + { + /* This is a blank operation. */ + return( PSA_ERROR_BAD_STATE ); + } + + if( output_length > operation->capacity ) + { + operation->capacity = 0; + /* Go through the error path to wipe all confidential data now + * that the operation object is useless. */ + status = PSA_ERROR_INSUFFICIENT_DATA; + goto exit; + } + if( output_length == 0 && operation->capacity == 0 ) + { + /* Edge case: this is a finished operation, and 0 bytes + * were requested. The right error in this case could + * be either INSUFFICIENT_CAPACITY or BAD_STATE. Return + * INSUFFICIENT_CAPACITY, which is right for a finished + * operation, for consistency with the case when + * output_length > 0. */ + return( PSA_ERROR_INSUFFICIENT_DATA ); + } + operation->capacity -= output_length; + +#if defined(MBEDTLS_MD_C) + if( PSA_ALG_IS_HKDF( kdf_alg ) ) + { + psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH( kdf_alg ); + status = psa_key_derivation_hkdf_read( &operation->ctx.hkdf, hash_alg, + output, output_length ); + } + else + if( PSA_ALG_IS_TLS12_PRF( kdf_alg ) || + PSA_ALG_IS_TLS12_PSK_TO_MS( kdf_alg ) ) + { + status = psa_key_derivation_tls12_prf_read( &operation->ctx.tls12_prf, + kdf_alg, output, + output_length ); + } + else +#endif /* MBEDTLS_MD_C */ + { + return( PSA_ERROR_BAD_STATE ); + } + +exit: + if( status != PSA_SUCCESS ) + { + /* Preserve the algorithm upon errors, but clear all sensitive state. + * This allows us to differentiate between exhausted operations and + * blank operations, so we can return PSA_ERROR_BAD_STATE on blank + * operations. */ + psa_algorithm_t alg = operation->alg; + psa_key_derivation_abort( operation ); + operation->alg = alg; + memset( output, '!', output_length ); + } + return( status ); +} + +#if defined(MBEDTLS_DES_C) +static void psa_des_set_key_parity( uint8_t *data, size_t data_size ) +{ + if( data_size >= 8 ) + mbedtls_des_key_set_parity( data ); + if( data_size >= 16 ) + mbedtls_des_key_set_parity( data + 8 ); + if( data_size >= 24 ) + mbedtls_des_key_set_parity( data + 16 ); +} +#endif /* MBEDTLS_DES_C */ + +static psa_status_t psa_generate_derived_key_internal( + psa_key_slot_t *slot, + size_t bits, + psa_key_derivation_operation_t *operation ) +{ + uint8_t *data = NULL; + size_t bytes = PSA_BITS_TO_BYTES( bits ); + psa_status_t status; + + if( ! key_type_is_raw_bytes( slot->attr.type ) ) + return( PSA_ERROR_INVALID_ARGUMENT ); + if( bits % 8 != 0 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + data = mbedtls_calloc( 1, bytes ); + if( data == NULL ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + + status = psa_key_derivation_output_bytes( operation, data, bytes ); + if( status != PSA_SUCCESS ) + goto exit; +#if defined(MBEDTLS_DES_C) + if( slot->attr.type == PSA_KEY_TYPE_DES ) + psa_des_set_key_parity( data, bytes ); +#endif /* MBEDTLS_DES_C */ + status = psa_import_key_into_slot( slot, data, bytes ); + +exit: + mbedtls_free( data ); + return( status ); +} + +psa_status_t psa_key_derivation_output_key( const psa_key_attributes_t *attributes, + psa_key_derivation_operation_t *operation, + psa_key_handle_t *handle ) +{ + psa_status_t status; + psa_key_slot_t *slot = NULL; + psa_se_drv_table_entry_t *driver = NULL; + + /* Reject any attempt to create a zero-length key so that we don't + * risk tripping up later, e.g. on a malloc(0) that returns NULL. */ + if( psa_get_key_bits( attributes ) == 0 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + if( ! operation->can_output_key ) + return( PSA_ERROR_NOT_PERMITTED ); + + status = psa_start_key_creation( PSA_KEY_CREATION_DERIVE, + attributes, handle, &slot, &driver ); +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + if( driver != NULL ) + { + /* Deriving a key in a secure element is not implemented yet. */ + status = PSA_ERROR_NOT_SUPPORTED; + } +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + if( status == PSA_SUCCESS ) + { + status = psa_generate_derived_key_internal( slot, + attributes->core.bits, + operation ); + } + if( status == PSA_SUCCESS ) + status = psa_finish_key_creation( slot, driver ); + if( status != PSA_SUCCESS ) + { + psa_fail_key_creation( slot, driver ); + *handle = 0; + } + return( status ); +} + + + +/****************************************************************/ +/* Key derivation */ +/****************************************************************/ + +static psa_status_t psa_key_derivation_setup_kdf( + psa_key_derivation_operation_t *operation, + psa_algorithm_t kdf_alg ) +{ + /* Make sure that operation->ctx is properly zero-initialised. (Macro + * initialisers for this union leave some bytes unspecified.) */ + memset( &operation->ctx, 0, sizeof( operation->ctx ) ); + + /* Make sure that kdf_alg is a supported key derivation algorithm. */ +#if defined(MBEDTLS_MD_C) + if( PSA_ALG_IS_HKDF( kdf_alg ) || + PSA_ALG_IS_TLS12_PRF( kdf_alg ) || + PSA_ALG_IS_TLS12_PSK_TO_MS( kdf_alg ) ) + { + psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH( kdf_alg ); + size_t hash_size = PSA_HASH_SIZE( hash_alg ); + if( hash_size == 0 ) + return( PSA_ERROR_NOT_SUPPORTED ); + if( ( PSA_ALG_IS_TLS12_PRF( kdf_alg ) || + PSA_ALG_IS_TLS12_PSK_TO_MS( kdf_alg ) ) && + ! ( hash_alg == PSA_ALG_SHA_256 || hash_alg == PSA_ALG_SHA_384 ) ) + { + return( PSA_ERROR_NOT_SUPPORTED ); + } + operation->capacity = 255 * hash_size; + return( PSA_SUCCESS ); + } +#endif /* MBEDTLS_MD_C */ + else + return( PSA_ERROR_NOT_SUPPORTED ); +} + +psa_status_t psa_key_derivation_setup( psa_key_derivation_operation_t *operation, + psa_algorithm_t alg ) +{ + psa_status_t status; + + if( operation->alg != 0 ) + return( PSA_ERROR_BAD_STATE ); + + if( PSA_ALG_IS_RAW_KEY_AGREEMENT( alg ) ) + return( PSA_ERROR_INVALID_ARGUMENT ); + else if( PSA_ALG_IS_KEY_AGREEMENT( alg ) ) + { + psa_algorithm_t kdf_alg = PSA_ALG_KEY_AGREEMENT_GET_KDF( alg ); + status = psa_key_derivation_setup_kdf( operation, kdf_alg ); + } + else if( PSA_ALG_IS_KEY_DERIVATION( alg ) ) + { + status = psa_key_derivation_setup_kdf( operation, alg ); + } + else + return( PSA_ERROR_INVALID_ARGUMENT ); + + if( status == PSA_SUCCESS ) + operation->alg = alg; + return( status ); +} + +#if defined(MBEDTLS_MD_C) +static psa_status_t psa_hkdf_input( psa_hkdf_key_derivation_t *hkdf, + psa_algorithm_t hash_alg, + psa_key_derivation_step_t step, + const uint8_t *data, + size_t data_length ) +{ + psa_status_t status; + switch( step ) + { + case PSA_KEY_DERIVATION_INPUT_SALT: + if( hkdf->state != HKDF_STATE_INIT ) + return( PSA_ERROR_BAD_STATE ); + status = psa_hmac_setup_internal( &hkdf->hmac, + data, data_length, + hash_alg ); + if( status != PSA_SUCCESS ) + return( status ); + hkdf->state = HKDF_STATE_STARTED; + return( PSA_SUCCESS ); + case PSA_KEY_DERIVATION_INPUT_SECRET: + /* If no salt was provided, use an empty salt. */ + if( hkdf->state == HKDF_STATE_INIT ) + { + status = psa_hmac_setup_internal( &hkdf->hmac, + NULL, 0, + hash_alg ); + if( status != PSA_SUCCESS ) + return( status ); + hkdf->state = HKDF_STATE_STARTED; + } + if( hkdf->state != HKDF_STATE_STARTED ) + return( PSA_ERROR_BAD_STATE ); + status = psa_hash_update( &hkdf->hmac.hash_ctx, + data, data_length ); + if( status != PSA_SUCCESS ) + return( status ); + status = psa_hmac_finish_internal( &hkdf->hmac, + hkdf->prk, + sizeof( hkdf->prk ) ); + if( status != PSA_SUCCESS ) + return( status ); + hkdf->offset_in_block = PSA_HASH_SIZE( hash_alg ); + hkdf->block_number = 0; + hkdf->state = HKDF_STATE_KEYED; + return( PSA_SUCCESS ); + case PSA_KEY_DERIVATION_INPUT_INFO: + if( hkdf->state == HKDF_STATE_OUTPUT ) + return( PSA_ERROR_BAD_STATE ); + if( hkdf->info_set ) + return( PSA_ERROR_BAD_STATE ); + hkdf->info_length = data_length; + if( data_length != 0 ) + { + hkdf->info = mbedtls_calloc( 1, data_length ); + if( hkdf->info == NULL ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + memcpy( hkdf->info, data, data_length ); + } + hkdf->info_set = 1; + return( PSA_SUCCESS ); + default: + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} + +static psa_status_t psa_tls12_prf_set_seed( psa_tls12_prf_key_derivation_t *prf, + const uint8_t *data, + size_t data_length ) +{ + if( prf->state != TLS12_PRF_STATE_INIT ) + return( PSA_ERROR_BAD_STATE ); + + if( data_length != 0 ) + { + prf->seed = mbedtls_calloc( 1, data_length ); + if( prf->seed == NULL ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + + memcpy( prf->seed, data, data_length ); + prf->seed_length = data_length; + } + + prf->state = TLS12_PRF_STATE_SEED_SET; + + return( PSA_SUCCESS ); +} + +static psa_status_t psa_tls12_prf_set_key( psa_tls12_prf_key_derivation_t *prf, + psa_algorithm_t hash_alg, + const uint8_t *data, + size_t data_length ) +{ + psa_status_t status; + if( prf->state != TLS12_PRF_STATE_SEED_SET ) + return( PSA_ERROR_BAD_STATE ); + + status = psa_hmac_setup_internal( &prf->hmac, data, data_length, hash_alg ); + if( status != PSA_SUCCESS ) + return( status ); + + prf->state = TLS12_PRF_STATE_KEY_SET; + + return( PSA_SUCCESS ); +} + +static psa_status_t psa_tls12_prf_psk_to_ms_set_key( + psa_tls12_prf_key_derivation_t *prf, + psa_algorithm_t hash_alg, + const uint8_t *data, + size_t data_length ) +{ + psa_status_t status; + uint8_t pms[ 4 + 2 * PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN ]; + uint8_t *cur = pms; + + if( data_length > PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + /* Quoting RFC 4279, Section 2: + * + * The premaster secret is formed as follows: if the PSK is N octets + * long, concatenate a uint16 with the value N, N zero octets, a second + * uint16 with the value N, and the PSK itself. + */ + + *cur++ = ( data_length >> 8 ) & 0xff; + *cur++ = ( data_length >> 0 ) & 0xff; + memset( cur, 0, data_length ); + cur += data_length; + *cur++ = pms[0]; + *cur++ = pms[1]; + memcpy( cur, data, data_length ); + cur += data_length; + + status = psa_tls12_prf_set_key( prf, hash_alg, pms, cur - pms ); + + mbedtls_platform_zeroize( pms, sizeof( pms ) ); + return( status ); +} + +static psa_status_t psa_tls12_prf_set_label( psa_tls12_prf_key_derivation_t *prf, + const uint8_t *data, + size_t data_length ) +{ + if( prf->state != TLS12_PRF_STATE_KEY_SET ) + return( PSA_ERROR_BAD_STATE ); + + if( data_length != 0 ) + { + prf->label = mbedtls_calloc( 1, data_length ); + if( prf->label == NULL ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + + memcpy( prf->label, data, data_length ); + prf->label_length = data_length; + } + + prf->state = TLS12_PRF_STATE_LABEL_SET; + + return( PSA_SUCCESS ); +} + +static psa_status_t psa_tls12_prf_input( psa_tls12_prf_key_derivation_t *prf, + psa_algorithm_t hash_alg, + psa_key_derivation_step_t step, + const uint8_t *data, + size_t data_length ) +{ + switch( step ) + { + case PSA_KEY_DERIVATION_INPUT_SEED: + return( psa_tls12_prf_set_seed( prf, data, data_length ) ); + case PSA_KEY_DERIVATION_INPUT_SECRET: + return( psa_tls12_prf_set_key( prf, hash_alg, data, data_length ) ); + case PSA_KEY_DERIVATION_INPUT_LABEL: + return( psa_tls12_prf_set_label( prf, data, data_length ) ); + default: + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} + +static psa_status_t psa_tls12_prf_psk_to_ms_input( + psa_tls12_prf_key_derivation_t *prf, + psa_algorithm_t hash_alg, + psa_key_derivation_step_t step, + const uint8_t *data, + size_t data_length ) +{ + if( step == PSA_KEY_DERIVATION_INPUT_SECRET ) + { + return( psa_tls12_prf_psk_to_ms_set_key( prf, hash_alg, + data, data_length ) ); + } + + return( psa_tls12_prf_input( prf, hash_alg, step, data, data_length ) ); +} +#endif /* MBEDTLS_MD_C */ + +/** Check whether the given key type is acceptable for the given + * input step of a key derivation. + * + * Secret inputs must have the type #PSA_KEY_TYPE_DERIVE. + * Non-secret inputs must have the type #PSA_KEY_TYPE_RAW_DATA. + * Both secret and non-secret inputs can alternatively have the type + * #PSA_KEY_TYPE_NONE, which is never the type of a key object, meaning + * that the input was passed as a buffer rather than via a key object. + */ +static int psa_key_derivation_check_input_type( + psa_key_derivation_step_t step, + psa_key_type_t key_type ) +{ + switch( step ) + { + case PSA_KEY_DERIVATION_INPUT_SECRET: + if( key_type == PSA_KEY_TYPE_DERIVE ) + return( PSA_SUCCESS ); + if( key_type == PSA_KEY_TYPE_NONE ) + return( PSA_SUCCESS ); + break; + case PSA_KEY_DERIVATION_INPUT_LABEL: + case PSA_KEY_DERIVATION_INPUT_SALT: + case PSA_KEY_DERIVATION_INPUT_INFO: + case PSA_KEY_DERIVATION_INPUT_SEED: + if( key_type == PSA_KEY_TYPE_RAW_DATA ) + return( PSA_SUCCESS ); + if( key_type == PSA_KEY_TYPE_NONE ) + return( PSA_SUCCESS ); + break; + } + return( PSA_ERROR_INVALID_ARGUMENT ); +} + +static psa_status_t psa_key_derivation_input_internal( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + psa_key_type_t key_type, + const uint8_t *data, + size_t data_length ) +{ + psa_status_t status; + psa_algorithm_t kdf_alg = psa_key_derivation_get_kdf_alg( operation ); + + status = psa_key_derivation_check_input_type( step, key_type ); + if( status != PSA_SUCCESS ) + goto exit; + +#if defined(MBEDTLS_MD_C) + if( PSA_ALG_IS_HKDF( kdf_alg ) ) + { + status = psa_hkdf_input( &operation->ctx.hkdf, + PSA_ALG_HKDF_GET_HASH( kdf_alg ), + step, data, data_length ); + } + else if( PSA_ALG_IS_TLS12_PRF( kdf_alg ) ) + { + status = psa_tls12_prf_input( &operation->ctx.tls12_prf, + PSA_ALG_HKDF_GET_HASH( kdf_alg ), + step, data, data_length ); + } + else if( PSA_ALG_IS_TLS12_PSK_TO_MS( kdf_alg ) ) + { + status = psa_tls12_prf_psk_to_ms_input( &operation->ctx.tls12_prf, + PSA_ALG_HKDF_GET_HASH( kdf_alg ), + step, data, data_length ); + } + else +#endif /* MBEDTLS_MD_C */ + { + /* This can't happen unless the operation object was not initialized */ + return( PSA_ERROR_BAD_STATE ); + } + +exit: + if( status != PSA_SUCCESS ) + psa_key_derivation_abort( operation ); + return( status ); +} + +psa_status_t psa_key_derivation_input_bytes( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + const uint8_t *data, + size_t data_length ) +{ + return( psa_key_derivation_input_internal( operation, step, + PSA_KEY_TYPE_NONE, + data, data_length ) ); +} + +psa_status_t psa_key_derivation_input_key( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + psa_key_handle_t handle ) +{ + psa_key_slot_t *slot; + psa_status_t status; + + status = psa_get_transparent_key( handle, &slot, + PSA_KEY_USAGE_DERIVE, + operation->alg ); + if( status != PSA_SUCCESS ) + { + psa_key_derivation_abort( operation ); + return( status ); + } + + /* Passing a key object as a SECRET input unlocks the permission + * to output to a key object. */ + if( step == PSA_KEY_DERIVATION_INPUT_SECRET ) + operation->can_output_key = 1; + + return( psa_key_derivation_input_internal( operation, + step, slot->attr.type, + slot->data.key.data, + slot->data.key.bytes ) ); +} + + + +/****************************************************************/ +/* Key agreement */ +/****************************************************************/ + +#if defined(MBEDTLS_ECDH_C) +static psa_status_t psa_key_agreement_ecdh( const uint8_t *peer_key, + size_t peer_key_length, + const mbedtls_ecp_keypair *our_key, + uint8_t *shared_secret, + size_t shared_secret_size, + size_t *shared_secret_length ) +{ + mbedtls_ecp_keypair *their_key = NULL; + mbedtls_ecdh_context ecdh; + psa_status_t status; + size_t bits = 0; + psa_ecc_family_t curve = mbedtls_ecc_group_to_psa( our_key->grp.id, &bits ); + mbedtls_ecdh_init( &ecdh ); + + status = psa_load_ecp_representation( PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve), + peer_key, + peer_key_length, + &their_key ); + if( status != PSA_SUCCESS ) + goto exit; + + status = mbedtls_to_psa_error( + mbedtls_ecdh_get_params( &ecdh, their_key, MBEDTLS_ECDH_THEIRS ) ); + if( status != PSA_SUCCESS ) + goto exit; + status = mbedtls_to_psa_error( + mbedtls_ecdh_get_params( &ecdh, our_key, MBEDTLS_ECDH_OURS ) ); + if( status != PSA_SUCCESS ) + goto exit; + + status = mbedtls_to_psa_error( + mbedtls_ecdh_calc_secret( &ecdh, + shared_secret_length, + shared_secret, shared_secret_size, + mbedtls_ctr_drbg_random, + &global_data.ctr_drbg ) ); + if( status != PSA_SUCCESS ) + goto exit; + if( PSA_BITS_TO_BYTES( bits ) != *shared_secret_length ) + status = PSA_ERROR_CORRUPTION_DETECTED; + +exit: + if( status != PSA_SUCCESS ) + mbedtls_platform_zeroize( shared_secret, shared_secret_size ); + mbedtls_ecdh_free( &ecdh ); + mbedtls_ecp_keypair_free( their_key ); + mbedtls_free( their_key ); + + return( status ); +} +#endif /* MBEDTLS_ECDH_C */ + +#define PSA_KEY_AGREEMENT_MAX_SHARED_SECRET_SIZE MBEDTLS_ECP_MAX_BYTES + +static psa_status_t psa_key_agreement_raw_internal( psa_algorithm_t alg, + psa_key_slot_t *private_key, + const uint8_t *peer_key, + size_t peer_key_length, + uint8_t *shared_secret, + size_t shared_secret_size, + size_t *shared_secret_length ) +{ + switch( alg ) + { +#if defined(MBEDTLS_ECDH_C) + case PSA_ALG_ECDH: + if( ! PSA_KEY_TYPE_IS_ECC_KEY_PAIR( private_key->attr.type ) ) + return( PSA_ERROR_INVALID_ARGUMENT ); + mbedtls_ecp_keypair *ecp = NULL; + psa_status_t status = psa_load_ecp_representation( + private_key->attr.type, + private_key->data.key.data, + private_key->data.key.bytes, + &ecp ); + if( status != PSA_SUCCESS ) + return( status ); + status = psa_key_agreement_ecdh( peer_key, peer_key_length, + ecp, + shared_secret, shared_secret_size, + shared_secret_length ); + mbedtls_ecp_keypair_free( ecp ); + mbedtls_free( ecp ); + return( status ); +#endif /* MBEDTLS_ECDH_C */ + default: + (void) private_key; + (void) peer_key; + (void) peer_key_length; + (void) shared_secret; + (void) shared_secret_size; + (void) shared_secret_length; + return( PSA_ERROR_NOT_SUPPORTED ); + } +} + +/* Note that if this function fails, you must call psa_key_derivation_abort() + * to potentially free embedded data structures and wipe confidential data. + */ +static psa_status_t psa_key_agreement_internal( psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + psa_key_slot_t *private_key, + const uint8_t *peer_key, + size_t peer_key_length ) +{ + psa_status_t status; + uint8_t shared_secret[PSA_KEY_AGREEMENT_MAX_SHARED_SECRET_SIZE]; + size_t shared_secret_length = 0; + psa_algorithm_t ka_alg = PSA_ALG_KEY_AGREEMENT_GET_BASE( operation->alg ); + + /* Step 1: run the secret agreement algorithm to generate the shared + * secret. */ + status = psa_key_agreement_raw_internal( ka_alg, + private_key, + peer_key, peer_key_length, + shared_secret, + sizeof( shared_secret ), + &shared_secret_length ); + if( status != PSA_SUCCESS ) + goto exit; + + /* Step 2: set up the key derivation to generate key material from + * the shared secret. A shared secret is permitted wherever a key + * of type DERIVE is permitted. */ + status = psa_key_derivation_input_internal( operation, step, + PSA_KEY_TYPE_DERIVE, + shared_secret, + shared_secret_length ); +exit: + mbedtls_platform_zeroize( shared_secret, shared_secret_length ); + return( status ); +} + +psa_status_t psa_key_derivation_key_agreement( psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + psa_key_handle_t private_key, + const uint8_t *peer_key, + size_t peer_key_length ) +{ + psa_key_slot_t *slot; + psa_status_t status; + if( ! PSA_ALG_IS_KEY_AGREEMENT( operation->alg ) ) + return( PSA_ERROR_INVALID_ARGUMENT ); + status = psa_get_transparent_key( private_key, &slot, + PSA_KEY_USAGE_DERIVE, operation->alg ); + if( status != PSA_SUCCESS ) + return( status ); + status = psa_key_agreement_internal( operation, step, + slot, + peer_key, peer_key_length ); + if( status != PSA_SUCCESS ) + psa_key_derivation_abort( operation ); + else + { + /* If a private key has been added as SECRET, we allow the derived + * key material to be used as a key in PSA Crypto. */ + if( step == PSA_KEY_DERIVATION_INPUT_SECRET ) + operation->can_output_key = 1; + } + return( status ); +} + +psa_status_t psa_raw_key_agreement( psa_algorithm_t alg, + psa_key_handle_t private_key, + const uint8_t *peer_key, + size_t peer_key_length, + uint8_t *output, + size_t output_size, + size_t *output_length ) +{ + psa_key_slot_t *slot; + psa_status_t status; + + if( ! PSA_ALG_IS_KEY_AGREEMENT( alg ) ) + { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + status = psa_get_transparent_key( private_key, &slot, + PSA_KEY_USAGE_DERIVE, alg ); + if( status != PSA_SUCCESS ) + goto exit; + + status = psa_key_agreement_raw_internal( alg, slot, + peer_key, peer_key_length, + output, output_size, + output_length ); + +exit: + if( status != PSA_SUCCESS ) + { + /* If an error happens and is not handled properly, the output + * may be used as a key to protect sensitive data. Arrange for such + * a key to be random, which is likely to result in decryption or + * verification errors. This is better than filling the buffer with + * some constant data such as zeros, which would result in the data + * being protected with a reproducible, easily knowable key. + */ + psa_generate_random( output, output_size ); + *output_length = output_size; + } + return( status ); +} + + +/****************************************************************/ +/* Random generation */ +/****************************************************************/ + +psa_status_t psa_generate_random( uint8_t *output, + size_t output_size ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + GUARD_MODULE_INITIALIZED; + + while( output_size > MBEDTLS_CTR_DRBG_MAX_REQUEST ) + { + ret = mbedtls_ctr_drbg_random( &global_data.ctr_drbg, + output, + MBEDTLS_CTR_DRBG_MAX_REQUEST ); + if( ret != 0 ) + return( mbedtls_to_psa_error( ret ) ); + output += MBEDTLS_CTR_DRBG_MAX_REQUEST; + output_size -= MBEDTLS_CTR_DRBG_MAX_REQUEST; + } + + ret = mbedtls_ctr_drbg_random( &global_data.ctr_drbg, output, output_size ); + return( mbedtls_to_psa_error( ret ) ); +} + +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) +#include "mbedtls/entropy_poll.h" + +psa_status_t mbedtls_psa_inject_entropy( const uint8_t *seed, + size_t seed_size ) +{ + if( global_data.initialized ) + return( PSA_ERROR_NOT_PERMITTED ); + + if( ( ( seed_size < MBEDTLS_ENTROPY_MIN_PLATFORM ) || + ( seed_size < MBEDTLS_ENTROPY_BLOCK_SIZE ) ) || + ( seed_size > MBEDTLS_ENTROPY_MAX_SEED_SIZE ) ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + return( mbedtls_psa_storage_inject_entropy( seed, seed_size ) ); +} +#endif /* MBEDTLS_PSA_INJECT_ENTROPY */ + +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_GENPRIME) +static psa_status_t psa_read_rsa_exponent( const uint8_t *domain_parameters, + size_t domain_parameters_size, + int *exponent ) +{ + size_t i; + uint32_t acc = 0; + + if( domain_parameters_size == 0 ) + { + *exponent = 65537; + return( PSA_SUCCESS ); + } + + /* Mbed TLS encodes the public exponent as an int. For simplicity, only + * support values that fit in a 32-bit integer, which is larger than + * int on just about every platform anyway. */ + if( domain_parameters_size > sizeof( acc ) ) + return( PSA_ERROR_NOT_SUPPORTED ); + for( i = 0; i < domain_parameters_size; i++ ) + acc = ( acc << 8 ) | domain_parameters[i]; + if( acc > INT_MAX ) + return( PSA_ERROR_NOT_SUPPORTED ); + *exponent = acc; + return( PSA_SUCCESS ); +} +#endif /* MBEDTLS_RSA_C && MBEDTLS_GENPRIME */ + +static psa_status_t psa_generate_key_internal( + psa_key_slot_t *slot, size_t bits, + const uint8_t *domain_parameters, size_t domain_parameters_size ) +{ + psa_key_type_t type = slot->attr.type; + + if( domain_parameters == NULL && domain_parameters_size != 0 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + if( key_type_is_raw_bytes( type ) ) + { + psa_status_t status; + + status = validate_unstructured_key_bit_size( slot->attr.type, bits ); + if( status != PSA_SUCCESS ) + return( status ); + + /* Allocate memory for the key */ + status = psa_allocate_buffer_to_slot( slot, PSA_BITS_TO_BYTES( bits ) ); + if( status != PSA_SUCCESS ) + return( status ); + + status = psa_generate_random( slot->data.key.data, + slot->data.key.bytes ); + if( status != PSA_SUCCESS ) + return( status ); + + slot->attr.bits = (psa_key_bits_t) bits; +#if defined(MBEDTLS_DES_C) + if( type == PSA_KEY_TYPE_DES ) + psa_des_set_key_parity( slot->data.key.data, + slot->data.key.bytes ); +#endif /* MBEDTLS_DES_C */ + } + else + +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_GENPRIME) + if ( type == PSA_KEY_TYPE_RSA_KEY_PAIR ) + { + mbedtls_rsa_context rsa; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + int exponent; + psa_status_t status; + if( bits > PSA_VENDOR_RSA_MAX_KEY_BITS ) + return( PSA_ERROR_NOT_SUPPORTED ); + /* Accept only byte-aligned keys, for the same reasons as + * in psa_import_rsa_key(). */ + if( bits % 8 != 0 ) + return( PSA_ERROR_NOT_SUPPORTED ); + status = psa_read_rsa_exponent( domain_parameters, + domain_parameters_size, + &exponent ); + if( status != PSA_SUCCESS ) + return( status ); + mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_NONE ); + ret = mbedtls_rsa_gen_key( &rsa, + mbedtls_ctr_drbg_random, + &global_data.ctr_drbg, + (unsigned int) bits, + exponent ); + if( ret != 0 ) + return( mbedtls_to_psa_error( ret ) ); + + /* Make sure to always have an export representation available */ + size_t bytes = PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE( bits ); + + status = psa_allocate_buffer_to_slot( slot, bytes ); + if( status != PSA_SUCCESS ) + { + mbedtls_rsa_free( &rsa ); + return( status ); + } + + status = psa_export_rsa_key( type, + &rsa, + slot->data.key.data, + bytes, + &slot->data.key.bytes ); + mbedtls_rsa_free( &rsa ); + if( status != PSA_SUCCESS ) + psa_remove_key_data_from_memory( slot ); + return( status ); + } + else +#endif /* MBEDTLS_RSA_C && MBEDTLS_GENPRIME */ + +#if defined(MBEDTLS_ECP_C) + if ( PSA_KEY_TYPE_IS_ECC( type ) && PSA_KEY_TYPE_IS_KEY_PAIR( type ) ) + { + psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY( type ); + mbedtls_ecp_group_id grp_id = + mbedtls_ecc_group_of_psa( curve, PSA_BITS_TO_BYTES( bits ) ); + const mbedtls_ecp_curve_info *curve_info = + mbedtls_ecp_curve_info_from_grp_id( grp_id ); + mbedtls_ecp_keypair ecp; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + if( domain_parameters_size != 0 ) + return( PSA_ERROR_NOT_SUPPORTED ); + if( grp_id == MBEDTLS_ECP_DP_NONE || curve_info == NULL ) + return( PSA_ERROR_NOT_SUPPORTED ); + mbedtls_ecp_keypair_init( &ecp ); + ret = mbedtls_ecp_gen_key( grp_id, &ecp, + mbedtls_ctr_drbg_random, + &global_data.ctr_drbg ); + if( ret != 0 ) + { + mbedtls_ecp_keypair_free( &ecp ); + return( mbedtls_to_psa_error( ret ) ); + } + + + /* Make sure to always have an export representation available */ + size_t bytes = PSA_BITS_TO_BYTES( bits ); + psa_status_t status = psa_allocate_buffer_to_slot( slot, bytes ); + if( status != PSA_SUCCESS ) + { + mbedtls_ecp_keypair_free( &ecp ); + return( status ); + } + + status = mbedtls_to_psa_error( + mbedtls_ecp_write_key( &ecp, slot->data.key.data, bytes ) ); + + mbedtls_ecp_keypair_free( &ecp ); + if( status != PSA_SUCCESS ) { + memset( slot->data.key.data, 0, bytes ); + psa_remove_key_data_from_memory( slot ); + } + return( status ); + } + else +#endif /* MBEDTLS_ECP_C */ + { + return( PSA_ERROR_NOT_SUPPORTED ); + } + + return( PSA_SUCCESS ); +} + +psa_status_t psa_generate_key( const psa_key_attributes_t *attributes, + psa_key_handle_t *handle ) +{ + psa_status_t status; + psa_key_slot_t *slot = NULL; + psa_se_drv_table_entry_t *driver = NULL; + + /* Reject any attempt to create a zero-length key so that we don't + * risk tripping up later, e.g. on a malloc(0) that returns NULL. */ + if( psa_get_key_bits( attributes ) == 0 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + status = psa_start_key_creation( PSA_KEY_CREATION_GENERATE, + attributes, handle, &slot, &driver ); + if( status != PSA_SUCCESS ) + goto exit; + + status = psa_driver_wrapper_generate_key( attributes, + slot ); + if( status != PSA_ERROR_NOT_SUPPORTED || + psa_key_lifetime_is_external( attributes->core.lifetime ) ) + goto exit; + + status = psa_generate_key_internal( + slot, attributes->core.bits, + attributes->domain_parameters, attributes->domain_parameters_size ); + +exit: + if( status == PSA_SUCCESS ) + status = psa_finish_key_creation( slot, driver ); + if( status != PSA_SUCCESS ) + { + psa_fail_key_creation( slot, driver ); + *handle = 0; + } + return( status ); +} + + + +/****************************************************************/ +/* Module setup */ +/****************************************************************/ + +psa_status_t mbedtls_psa_crypto_configure_entropy_sources( + void (* entropy_init )( mbedtls_entropy_context *ctx ), + void (* entropy_free )( mbedtls_entropy_context *ctx ) ) +{ + if( global_data.rng_state != RNG_NOT_INITIALIZED ) + return( PSA_ERROR_BAD_STATE ); + global_data.entropy_init = entropy_init; + global_data.entropy_free = entropy_free; + return( PSA_SUCCESS ); +} + +void mbedtls_psa_crypto_free( void ) +{ + psa_wipe_all_key_slots( ); + if( global_data.rng_state != RNG_NOT_INITIALIZED ) + { + mbedtls_ctr_drbg_free( &global_data.ctr_drbg ); + global_data.entropy_free( &global_data.entropy ); + } + /* Wipe all remaining data, including configuration. + * In particular, this sets all state indicator to the value + * indicating "uninitialized". */ + mbedtls_platform_zeroize( &global_data, sizeof( global_data ) ); +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + /* Unregister all secure element drivers, so that we restart from + * a pristine state. */ + psa_unregister_all_se_drivers( ); +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ +} + +#if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) +/** Recover a transaction that was interrupted by a power failure. + * + * This function is called during initialization, before psa_crypto_init() + * returns. If this function returns a failure status, the initialization + * fails. + */ +static psa_status_t psa_crypto_recover_transaction( + const psa_crypto_transaction_t *transaction ) +{ + switch( transaction->unknown.type ) + { + case PSA_CRYPTO_TRANSACTION_CREATE_KEY: + case PSA_CRYPTO_TRANSACTION_DESTROY_KEY: + /* TODO - fall through to the failure case until this + * is implemented. + * https://github.com/ARMmbed/mbed-crypto/issues/218 + */ + default: + /* We found an unsupported transaction in the storage. + * We don't know what state the storage is in. Give up. */ + return( PSA_ERROR_STORAGE_FAILURE ); + } +} +#endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */ + +psa_status_t psa_crypto_init( void ) +{ + psa_status_t status; + const unsigned char drbg_seed[] = "PSA"; + + /* Double initialization is explicitly allowed. */ + if( global_data.initialized != 0 ) + return( PSA_SUCCESS ); + + /* Set default configuration if + * mbedtls_psa_crypto_configure_entropy_sources() hasn't been called. */ + if( global_data.entropy_init == NULL ) + global_data.entropy_init = mbedtls_entropy_init; + if( global_data.entropy_free == NULL ) + global_data.entropy_free = mbedtls_entropy_free; + + /* Initialize the random generator. */ + global_data.entropy_init( &global_data.entropy ); +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) && \ + defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) + /* The PSA entropy injection feature depends on using NV seed as an entropy + * source. Add NV seed as an entropy source for PSA entropy injection. */ + mbedtls_entropy_add_source( &global_data.entropy, + mbedtls_nv_seed_poll, NULL, + MBEDTLS_ENTROPY_BLOCK_SIZE, + MBEDTLS_ENTROPY_SOURCE_STRONG ); +#endif + mbedtls_ctr_drbg_init( &global_data.ctr_drbg ); + global_data.rng_state = RNG_INITIALIZED; + status = mbedtls_to_psa_error( + mbedtls_ctr_drbg_seed( &global_data.ctr_drbg, + mbedtls_entropy_func, + &global_data.entropy, + drbg_seed, sizeof( drbg_seed ) - 1 ) ); + if( status != PSA_SUCCESS ) + goto exit; + global_data.rng_state = RNG_SEEDED; + + status = psa_initialize_key_slots( ); + if( status != PSA_SUCCESS ) + goto exit; + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + status = psa_init_all_se_drivers( ); + if( status != PSA_SUCCESS ) + goto exit; +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + +#if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) + status = psa_crypto_load_transaction( ); + if( status == PSA_SUCCESS ) + { + status = psa_crypto_recover_transaction( &psa_crypto_transaction ); + if( status != PSA_SUCCESS ) + goto exit; + status = psa_crypto_stop_transaction( ); + } + else if( status == PSA_ERROR_DOES_NOT_EXIST ) + { + /* There's no transaction to complete. It's all good. */ + status = PSA_SUCCESS; + } +#endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */ + + /* All done. */ + global_data.initialized = 1; + +exit: + if( status != PSA_SUCCESS ) + mbedtls_psa_crypto_free( ); + return( status ); +} + +#endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/psa_crypto_core.h b/Android/Level4/app/src/main/c/mbedtls/library/psa_crypto_core.h new file mode 100644 index 0000000..8d1f1bb --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/psa_crypto_core.h @@ -0,0 +1,172 @@ +/* + * PSA crypto core internal interfaces + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 PSA_CRYPTO_CORE_H +#define PSA_CRYPTO_CORE_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "psa/crypto.h" +#include "psa/crypto_se_driver.h" + +/** The data structure representing a key slot, containing key material + * and metadata for one key. + */ +typedef struct +{ + psa_core_key_attributes_t attr; + union + { + /* Dynamically allocated key data buffer. + * Format as specified in psa_export_key(). */ + struct key_data + { + uint8_t *data; + size_t bytes; + } key; +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + /* Any key type in a secure element */ + struct se + { + psa_key_slot_number_t slot_number; + } se; +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + } data; +} psa_key_slot_t; + +/* A mask of key attribute flags used only internally. + * Currently there aren't any. */ +#define PSA_KA_MASK_INTERNAL_ONLY ( \ + 0 ) + +/** Test whether a key slot is occupied. + * + * A key slot is occupied iff the key type is nonzero. This works because + * no valid key can have 0 as its key type. + * + * \param[in] slot The key slot to test. + * + * \return 1 if the slot is occupied, 0 otherwise. + */ +static inline int psa_is_key_slot_occupied( const psa_key_slot_t *slot ) +{ + return( slot->attr.type != 0 ); +} + +/** Retrieve flags from psa_key_slot_t::attr::core::flags. + * + * \param[in] slot The key slot to query. + * \param mask The mask of bits to extract. + * + * \return The key attribute flags in the given slot, + * bitwise-anded with \p mask. + */ +static inline uint16_t psa_key_slot_get_flags( const psa_key_slot_t *slot, + uint16_t mask ) +{ + return( slot->attr.flags & mask ); +} + +/** Set flags in psa_key_slot_t::attr::core::flags. + * + * \param[in,out] slot The key slot to modify. + * \param mask The mask of bits to modify. + * \param value The new value of the selected bits. + */ +static inline void psa_key_slot_set_flags( psa_key_slot_t *slot, + uint16_t mask, + uint16_t value ) +{ + slot->attr.flags = ( ( ~mask & slot->attr.flags ) | + ( mask & value ) ); +} + +/** Turn on flags in psa_key_slot_t::attr::core::flags. + * + * \param[in,out] slot The key slot to modify. + * \param mask The mask of bits to set. + */ +static inline void psa_key_slot_set_bits_in_flags( psa_key_slot_t *slot, + uint16_t mask ) +{ + slot->attr.flags |= mask; +} + +/** Turn off flags in psa_key_slot_t::attr::core::flags. + * + * \param[in,out] slot The key slot to modify. + * \param mask The mask of bits to clear. + */ +static inline void psa_key_slot_clear_bits( psa_key_slot_t *slot, + uint16_t mask ) +{ + slot->attr.flags &= ~mask; +} + +/** Completely wipe a slot in memory, including its policy. + * + * Persistent storage is not affected. + * + * \param[in,out] slot The key slot to wipe. + * + * \retval PSA_SUCCESS + * Success. This includes the case of a key slot that was + * already fully wiped. + * \retval PSA_ERROR_CORRUPTION_DETECTED + */ +psa_status_t psa_wipe_key_slot( psa_key_slot_t *slot ); + +/** Copy key data (in export format) into an empty key slot. + * + * This function assumes that the slot does not contain + * any key material yet. On failure, the slot content is unchanged. + * + * \param[in,out] slot Key slot to copy the key into. + * \param[in] data Buffer containing the key material. + * \param data_length Size of the key buffer. + * + * \retval #PSA_SUCCESS + * The key has been copied successfully. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * Not enough memory was available for allocation of the + * copy buffer. + * \retval #PSA_ERROR_ALREADY_EXISTS + * There was other key material already present in the slot. + */ +psa_status_t psa_copy_key_material_into_slot( psa_key_slot_t *slot, + const uint8_t *data, + size_t data_length ); + +/** Convert an mbed TLS error code to a PSA error code + * + * \note This function is provided solely for the convenience of + * Mbed TLS and may be removed at any time without notice. + * + * \param ret An mbed TLS-thrown error code + * + * \return The corresponding PSA error code + */ +psa_status_t mbedtls_to_psa_error( int ret ); + +#endif /* PSA_CRYPTO_CORE_H */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/psa_crypto_driver_wrappers.c b/Android/Level4/app/src/main/c/mbedtls/library/psa_crypto_driver_wrappers.c new file mode 100644 index 0000000..4040b36 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/psa_crypto_driver_wrappers.c @@ -0,0 +1,940 @@ +/* + * Functions to delegate cryptographic operations to an available + * and appropriate accelerator. + * Warning: This file will be auto-generated in the future. + */ +/* Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 "psa_crypto_core.h" +#include "psa_crypto_driver_wrappers.h" +#include "mbedtls/platform.h" + +#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS) + +/* Include test driver definition when running tests */ +#if defined(PSA_CRYPTO_DRIVER_TEST) +#ifndef PSA_CRYPTO_DRIVER_PRESENT +#define PSA_CRYPTO_DRIVER_PRESENT +#endif +#ifndef PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT +#define PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT +#endif +#include "test/drivers/test_driver.h" +#endif /* PSA_CRYPTO_DRIVER_TEST */ + +/* Repeat above block for each JSON-declared driver during autogeneration */ + +/* Auto-generated values depending on which drivers are registered. ID 0 is + * reserved for unallocated operations. */ +#if defined(PSA_CRYPTO_DRIVER_TEST) +#define PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID (1) +#define PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID (2) +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* MBEDTLS_PSA_CRYPTO_DRIVERS */ + +/* Support the 'old' SE interface when asked to */ +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) +/* PSA_CRYPTO_DRIVER_PRESENT is defined when either a new-style or old-style + * SE driver is present, to avoid unused argument errors at compile time. */ +#ifndef PSA_CRYPTO_DRIVER_PRESENT +#define PSA_CRYPTO_DRIVER_PRESENT +#endif +#include "psa_crypto_se.h" +#endif + +/* Start delegation functions */ +psa_status_t psa_driver_wrapper_sign_hash( psa_key_slot_t *slot, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + uint8_t *signature, + size_t signature_size, + size_t *signature_length ) +{ +#if defined(PSA_CRYPTO_DRIVER_PRESENT) + /* Try dynamically-registered SE interface first */ +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + const psa_drv_se_t *drv; + psa_drv_se_context_t *drv_context; + + if( psa_get_se_driver( slot->attr.lifetime, &drv, &drv_context ) ) + { + if( drv->asymmetric == NULL || + drv->asymmetric->p_sign == NULL ) + { + /* Key is defined in SE, but we have no way to exercise it */ + return( PSA_ERROR_NOT_SUPPORTED ); + } + return( drv->asymmetric->p_sign( drv_context, + slot->data.se.slot_number, + alg, + hash, hash_length, + signature, signature_size, + signature_length ) ); + } +#endif /* PSA_CRYPTO_SE_C */ + + /* Then try accelerator API */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) + psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; + psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(slot->attr.lifetime); + psa_key_attributes_t attributes = { + .core = slot->attr + }; + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ +#if defined(PSA_CRYPTO_DRIVER_TEST) + status = test_transparent_signature_sign_hash( &attributes, + slot->data.key.data, + slot->data.key.bytes, + alg, + hash, + hash_length, + signature, + signature_size, + signature_length ); + /* Declared with fallback == true */ + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ + /* Fell through, meaning no accelerator supports this operation */ + return( PSA_ERROR_NOT_SUPPORTED ); + /* Add cases for opaque driver here */ +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LIFETIME: + return( test_opaque_signature_sign_hash( &attributes, + slot->data.key.data, + slot->data.key.bytes, + alg, + hash, + hash_length, + signature, + signature_size, + signature_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ + default: + /* Key is declared with a lifetime not known to us */ + return( status ); + } +#else /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + return( PSA_ERROR_NOT_SUPPORTED ); +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ +#else /* PSA_CRYPTO_DRIVER_PRESENT */ + (void)slot; + (void)alg; + (void)hash; + (void)hash_length; + (void)signature; + (void)signature_size; + (void)signature_length; + + return( PSA_ERROR_NOT_SUPPORTED ); +#endif /* PSA_CRYPTO_DRIVER_PRESENT */ +} + +psa_status_t psa_driver_wrapper_verify_hash( psa_key_slot_t *slot, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + const uint8_t *signature, + size_t signature_length ) +{ +#if defined(PSA_CRYPTO_DRIVER_PRESENT) + /* Try dynamically-registered SE interface first */ +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + const psa_drv_se_t *drv; + psa_drv_se_context_t *drv_context; + + if( psa_get_se_driver( slot->attr.lifetime, &drv, &drv_context ) ) + { + if( drv->asymmetric == NULL || + drv->asymmetric->p_verify == NULL ) + { + /* Key is defined in SE, but we have no way to exercise it */ + return( PSA_ERROR_NOT_SUPPORTED ); + } + return( drv->asymmetric->p_verify( drv_context, + slot->data.se.slot_number, + alg, + hash, hash_length, + signature, signature_length ) ); + } +#endif /* PSA_CRYPTO_SE_C */ + + /* Then try accelerator API */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) + psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; + psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(slot->attr.lifetime); + psa_key_attributes_t attributes = { + .core = slot->attr + }; + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ +#if defined(PSA_CRYPTO_DRIVER_TEST) + status = test_transparent_signature_verify_hash( &attributes, + slot->data.key.data, + slot->data.key.bytes, + alg, + hash, + hash_length, + signature, + signature_length ); + /* Declared with fallback == true */ + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ + /* Fell through, meaning no accelerator supports this operation */ + return( PSA_ERROR_NOT_SUPPORTED ); + /* Add cases for opaque driver here */ +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LIFETIME: + return( test_opaque_signature_verify_hash( &attributes, + slot->data.key.data, + slot->data.key.bytes, + alg, + hash, + hash_length, + signature, + signature_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ + default: + /* Key is declared with a lifetime not known to us */ + return( status ); + } +#else /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + return( PSA_ERROR_NOT_SUPPORTED ); +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ +#else /* PSA_CRYPTO_DRIVER_PRESENT */ + (void)slot; + (void)alg; + (void)hash; + (void)hash_length; + (void)signature; + (void)signature_length; + + return( PSA_ERROR_NOT_SUPPORTED ); +#endif /* PSA_CRYPTO_DRIVER_PRESENT */ +} + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +/** Calculate the size to allocate for buffering a key with given attributes. + * + * This function provides a way to get the expected size for storing a key with + * the given attributes. This will be the size of the export representation for + * cleartext keys, and a driver-defined size for keys stored by opaque drivers. + * + * \param[in] attributes The key attribute structure of the key to store. + * \param[out] expected_size On success, a byte size large enough to contain + * the declared key. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_NOT_SUPPORTED + */ +static psa_status_t get_expected_key_size( const psa_key_attributes_t *attributes, + size_t *expected_size ) +{ + size_t buffer_size = 0; + psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime ); + psa_key_type_t key_type = attributes->core.type; + size_t key_bits = attributes->core.bits; + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + buffer_size = PSA_KEY_EXPORT_MAX_SIZE( key_type, key_bits ); + + if( buffer_size == 0 ) + return( PSA_ERROR_NOT_SUPPORTED ); + + *expected_size = buffer_size; + return( PSA_SUCCESS ); + +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LIFETIME: +#ifdef TEST_DRIVER_KEY_CONTEXT_SIZE_FUNCTION + *expected_size = test_size_function( key_type, key_bits ); + return( PSA_SUCCESS ); +#else /* TEST_DRIVER_KEY_CONTEXT_SIZE_FUNCTION */ + if( PSA_KEY_TYPE_IS_KEY_PAIR( key_type ) ) + { + int public_key_overhead = ( ( TEST_DRIVER_KEY_CONTEXT_STORE_PUBLIC_KEY == 1 ) ? + PSA_KEY_EXPORT_MAX_SIZE( key_type, key_bits ) : 0 ); + *expected_size = TEST_DRIVER_KEY_CONTEXT_BASE_SIZE + + TEST_DRIVER_KEY_CONTEXT_PUBLIC_KEY_SIZE + + public_key_overhead; + } + else if( PSA_KEY_TYPE_IS_PUBLIC_KEY( attributes->core.type ) ) + { + *expected_size = TEST_DRIVER_KEY_CONTEXT_BASE_SIZE + + TEST_DRIVER_KEY_CONTEXT_PUBLIC_KEY_SIZE; + } + else if ( !PSA_KEY_TYPE_IS_KEY_PAIR( key_type ) && + !PSA_KEY_TYPE_IS_PUBLIC_KEY ( attributes->core.type ) ) + { + *expected_size = TEST_DRIVER_KEY_CONTEXT_BASE_SIZE + + TEST_DRIVER_KEY_CONTEXT_SYMMETRIC_FACTOR + * ( ( key_bits + 7 ) / 8 ); + } + else + { + return( PSA_ERROR_NOT_SUPPORTED ); + } + return( PSA_SUCCESS ); +#endif /* TEST_DRIVER_KEY_CONTEXT_SIZE_FUNCTION */ +#endif /* PSA_CRYPTO_DRIVER_TEST */ + + default: + return( PSA_ERROR_NOT_SUPPORTED ); + } +} +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + +psa_status_t psa_driver_wrapper_generate_key( const psa_key_attributes_t *attributes, + psa_key_slot_t *slot ) +{ +#if defined(PSA_CRYPTO_DRIVER_PRESENT) + /* Try dynamically-registered SE interface first */ +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + const psa_drv_se_t *drv; + psa_drv_se_context_t *drv_context; + + if( psa_get_se_driver( slot->attr.lifetime, &drv, &drv_context ) ) + { + size_t pubkey_length = 0; /* We don't support this feature yet */ + if( drv->key_management == NULL || + drv->key_management->p_generate == NULL ) + { + /* Key is defined as being in SE, but we have no way to generate it */ + return( PSA_ERROR_NOT_SUPPORTED ); + } + return( drv->key_management->p_generate( + drv_context, + slot->data.se.slot_number, attributes, + NULL, 0, &pubkey_length ) ); + } +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + + /* Then try accelerator API */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) + psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; + psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(slot->attr.lifetime); + size_t export_size = 0; + + status = get_expected_key_size( attributes, &export_size ); + if( status != PSA_SUCCESS ) + return( status ); + + slot->data.key.data = mbedtls_calloc(1, export_size); + if( slot->data.key.data == NULL ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + slot->data.key.bytes = export_size; + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ + + /* Transparent drivers are limited to generating asymmetric keys */ + if( ! PSA_KEY_TYPE_IS_ASYMMETRIC( slot->attr.type ) ) + { + status = PSA_ERROR_NOT_SUPPORTED; + break; + } +#if defined(PSA_CRYPTO_DRIVER_TEST) + status = test_transparent_generate_key( attributes, + slot->data.key.data, + slot->data.key.bytes, + &slot->data.key.bytes ); + /* Declared with fallback == true */ + if( status != PSA_ERROR_NOT_SUPPORTED ) + break; +#endif /* PSA_CRYPTO_DRIVER_TEST */ + /* Fell through, meaning no accelerator supports this operation */ + status = PSA_ERROR_NOT_SUPPORTED; + break; + /* Add cases for opaque driver here */ +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LIFETIME: + status = test_opaque_generate_key( attributes, + slot->data.key.data, + slot->data.key.bytes, + &slot->data.key.bytes ); + break; +#endif /* PSA_CRYPTO_DRIVER_TEST */ + default: + /* Key is declared with a lifetime not known to us */ + status = PSA_ERROR_INVALID_ARGUMENT; + break; + } + + if( status != PSA_SUCCESS ) + { + /* free allocated buffer */ + mbedtls_free( slot->data.key.data ); + slot->data.key.data = NULL; + slot->data.key.bytes = 0; + } + + return( status ); +#else /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + return( PSA_ERROR_NOT_SUPPORTED ); +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ +#else /* PSA_CRYPTO_DRIVER_PRESENT */ + (void) attributes; + (void) slot; + + return( PSA_ERROR_NOT_SUPPORTED ); +#endif /* PSA_CRYPTO_DRIVER_PRESENT */ +} + +psa_status_t psa_driver_wrapper_validate_key( const psa_key_attributes_t *attributes, + const uint8_t *data, + size_t data_length, + size_t *bits ) +{ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + /* Try accelerators in turn */ +#if defined(PSA_CRYPTO_DRIVER_TEST) + status = test_transparent_validate_key( attributes, + data, + data_length, + bits ); + /* Declared with fallback == true */ + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ + + return( PSA_ERROR_NOT_SUPPORTED ); +#else /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + (void) attributes; + (void) data; + (void) data_length; + (void) bits; + return( PSA_ERROR_NOT_SUPPORTED ); +#endif /* PSA_CRYPTO_DRIVER_PRESENT */ +} + +/* + * Cipher functions + */ +psa_status_t psa_driver_wrapper_cipher_encrypt( + psa_key_slot_t *slot, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length ) +{ +#if defined(PSA_CRYPTO_DRIVER_PRESENT) && defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) + psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; + psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(slot->attr.lifetime); + psa_key_attributes_t attributes = { + .core = slot->attr + }; + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ +#if defined(PSA_CRYPTO_DRIVER_TEST) + status = test_transparent_cipher_encrypt( &attributes, + slot->data.key.data, + slot->data.key.bytes, + alg, + input, + input_length, + output, + output_size, + output_length ); + /* Declared with fallback == true */ + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ + /* Fell through, meaning no accelerator supports this operation */ + return( PSA_ERROR_NOT_SUPPORTED ); + /* Add cases for opaque driver here */ +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LIFETIME: + return( test_opaque_cipher_encrypt( &attributes, + slot->data.key.data, + slot->data.key.bytes, + alg, + input, + input_length, + output, + output_size, + output_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ + default: + /* Key is declared with a lifetime not known to us */ + return( status ); + } +#else /* PSA_CRYPTO_DRIVER_PRESENT */ + (void) slot; + (void) alg; + (void) input; + (void) input_length; + (void) output; + (void) output_size; + (void) output_length; + + return( PSA_ERROR_NOT_SUPPORTED ); +#endif /* PSA_CRYPTO_DRIVER_PRESENT */ +} + +psa_status_t psa_driver_wrapper_cipher_decrypt( + psa_key_slot_t *slot, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length ) +{ +#if defined(PSA_CRYPTO_DRIVER_PRESENT) && defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) + psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; + psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(slot->attr.lifetime); + psa_key_attributes_t attributes = { + .core = slot->attr + }; + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ +#if defined(PSA_CRYPTO_DRIVER_TEST) + status = test_transparent_cipher_decrypt( &attributes, + slot->data.key.data, + slot->data.key.bytes, + alg, + input, + input_length, + output, + output_size, + output_length ); + /* Declared with fallback == true */ + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ + /* Fell through, meaning no accelerator supports this operation */ + return( PSA_ERROR_NOT_SUPPORTED ); + /* Add cases for opaque driver here */ +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LIFETIME: + return( test_opaque_cipher_decrypt( &attributes, + slot->data.key.data, + slot->data.key.bytes, + alg, + input, + input_length, + output, + output_size, + output_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ + default: + /* Key is declared with a lifetime not known to us */ + return( status ); + } +#else /* PSA_CRYPTO_DRIVER_PRESENT */ + (void) slot; + (void) alg; + (void) input; + (void) input_length; + (void) output; + (void) output_size; + (void) output_length; + + return( PSA_ERROR_NOT_SUPPORTED ); +#endif /* PSA_CRYPTO_DRIVER_PRESENT */ +} + +psa_status_t psa_driver_wrapper_cipher_encrypt_setup( + psa_operation_driver_context_t *operation, + psa_key_slot_t *slot, + psa_algorithm_t alg ) +{ +#if defined(PSA_CRYPTO_DRIVER_PRESENT) && defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) + psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; + psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(slot->attr.lifetime); + psa_key_attributes_t attributes = { + .core = slot->attr + }; + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ +#if defined(PSA_CRYPTO_DRIVER_TEST) + operation->ctx = mbedtls_calloc( 1, sizeof(test_transparent_cipher_operation_t) ); + if( operation->ctx == NULL ) + return PSA_ERROR_INSUFFICIENT_MEMORY; + + status = test_transparent_cipher_encrypt_setup( operation->ctx, + &attributes, + slot->data.key.data, + slot->data.key.bytes, + alg ); + /* Declared with fallback == true */ + if( status == PSA_SUCCESS ) + operation->id = PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID; + else + { + mbedtls_platform_zeroize( + operation->ctx, + sizeof( test_transparent_cipher_operation_t ) ); + mbedtls_free( operation->ctx ); + operation->ctx = NULL; + } + + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ + /* Fell through, meaning no accelerator supports this operation */ + return( PSA_ERROR_NOT_SUPPORTED ); + /* Add cases for opaque driver here */ +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LIFETIME: + operation->ctx = mbedtls_calloc( 1, sizeof(test_opaque_cipher_operation_t) ); + if( operation->ctx == NULL ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + + status = test_opaque_cipher_encrypt_setup( operation->ctx, + &attributes, + slot->data.key.data, + slot->data.key.bytes, + alg ); + if( status == PSA_SUCCESS ) + operation->id = PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID; + else + { + mbedtls_platform_zeroize( + operation->ctx, + sizeof( test_opaque_cipher_operation_t ) ); + mbedtls_free( operation->ctx ); + operation->ctx = NULL; + } + + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ + default: + /* Key is declared with a lifetime not known to us */ + return( PSA_ERROR_NOT_SUPPORTED ); + } +#else /* PSA_CRYPTO_DRIVER_PRESENT */ + (void)slot; + (void)alg; + (void)operation; + + return( PSA_ERROR_NOT_SUPPORTED ); +#endif /* PSA_CRYPTO_DRIVER_PRESENT */ +} + +psa_status_t psa_driver_wrapper_cipher_decrypt_setup( + psa_operation_driver_context_t *operation, + psa_key_slot_t *slot, + psa_algorithm_t alg ) +{ +#if defined(PSA_CRYPTO_DRIVER_PRESENT) && defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) + psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; + psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(slot->attr.lifetime); + psa_key_attributes_t attributes = { + .core = slot->attr + }; + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ +#if defined(PSA_CRYPTO_DRIVER_TEST) + operation->ctx = mbedtls_calloc( 1, sizeof(test_transparent_cipher_operation_t) ); + if( operation->ctx == NULL ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + + status = test_transparent_cipher_decrypt_setup( operation->ctx, + &attributes, + slot->data.key.data, + slot->data.key.bytes, + alg ); + /* Declared with fallback == true */ + if( status == PSA_SUCCESS ) + operation->id = PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID; + else + { + mbedtls_platform_zeroize( + operation->ctx, + sizeof( test_transparent_cipher_operation_t ) ); + mbedtls_free( operation->ctx ); + operation->ctx = NULL; + } + + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ + /* Fell through, meaning no accelerator supports this operation */ + return( PSA_ERROR_NOT_SUPPORTED ); + /* Add cases for opaque driver here */ +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LIFETIME: + operation->ctx = mbedtls_calloc( 1, sizeof(test_opaque_cipher_operation_t) ); + if( operation->ctx == NULL ) + return PSA_ERROR_INSUFFICIENT_MEMORY; + + status = test_opaque_cipher_decrypt_setup( operation->ctx, + &attributes, + slot->data.key.data, + slot->data.key.bytes, + alg ); + if( status == PSA_SUCCESS ) + operation->id = PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID; + else + { + mbedtls_platform_zeroize( + operation->ctx, + sizeof( test_opaque_cipher_operation_t ) ); + mbedtls_free( operation->ctx ); + operation->ctx = NULL; + } + + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ + default: + /* Key is declared with a lifetime not known to us */ + return( PSA_ERROR_NOT_SUPPORTED ); + } +#else /* PSA_CRYPTO_DRIVER_PRESENT */ + (void)slot; + (void)alg; + (void)operation; + + return( PSA_ERROR_NOT_SUPPORTED ); +#endif /* PSA_CRYPTO_DRIVER_PRESENT */ +} + +psa_status_t psa_driver_wrapper_cipher_generate_iv( + psa_operation_driver_context_t *operation, + uint8_t *iv, + size_t iv_size, + size_t *iv_length ) +{ +#if defined(PSA_CRYPTO_DRIVER_PRESENT) && defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) + switch( operation->id ) + { +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID: + return( test_transparent_cipher_generate_iv( operation->ctx, + iv, + iv_size, + iv_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID: + return( test_opaque_cipher_generate_iv( operation->ctx, + iv, + iv_size, + iv_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ + default: + /* Key is attached to a driver not known to us */ + return( PSA_ERROR_BAD_STATE ); + } +#else /* PSA_CRYPTO_DRIVER_PRESENT */ + (void) operation; + (void) iv; + (void) iv_size; + (void) iv_length; + + return( PSA_ERROR_NOT_SUPPORTED ); +#endif /* PSA_CRYPTO_DRIVER_PRESENT */ +} + +psa_status_t psa_driver_wrapper_cipher_set_iv( + psa_operation_driver_context_t *operation, + const uint8_t *iv, + size_t iv_length ) +{ +#if defined(PSA_CRYPTO_DRIVER_PRESENT) && defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) + switch( operation->id ) + { +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID: + return( test_transparent_cipher_set_iv( operation->ctx, + iv, + iv_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID: + return( test_opaque_cipher_set_iv( operation->ctx, + iv, + iv_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ + default: + /* Key is attached to a driver not known to us */ + return( PSA_ERROR_BAD_STATE ); + } +#else /* PSA_CRYPTO_DRIVER_PRESENT */ + (void) operation; + (void) iv; + (void) iv_length; + + return( PSA_ERROR_NOT_SUPPORTED ); +#endif /* PSA_CRYPTO_DRIVER_PRESENT */ +} + +psa_status_t psa_driver_wrapper_cipher_update( + psa_operation_driver_context_t *operation, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length ) +{ +#if defined(PSA_CRYPTO_DRIVER_PRESENT) && defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) + switch( operation->id ) + { +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID: + return( test_transparent_cipher_update( operation->ctx, + input, + input_length, + output, + output_size, + output_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID: + return( test_opaque_cipher_update( operation->ctx, + input, + input_length, + output, + output_size, + output_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ + default: + /* Key is attached to a driver not known to us */ + return( PSA_ERROR_BAD_STATE ); + } +#else /* PSA_CRYPTO_DRIVER_PRESENT */ + (void) operation; + (void) input; + (void) input_length; + (void) output; + (void) output_length; + (void) output_size; + + return( PSA_ERROR_NOT_SUPPORTED ); +#endif /* PSA_CRYPTO_DRIVER_PRESENT */ +} + +psa_status_t psa_driver_wrapper_cipher_finish( + psa_operation_driver_context_t *operation, + uint8_t *output, + size_t output_size, + size_t *output_length ) +{ +#if defined(PSA_CRYPTO_DRIVER_PRESENT) && defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) + switch( operation->id ) + { +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID: + return( test_transparent_cipher_finish( operation->ctx, + output, + output_size, + output_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID: + return( test_opaque_cipher_finish( operation->ctx, + output, + output_size, + output_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ + default: + /* Key is attached to a driver not known to us */ + return( PSA_ERROR_BAD_STATE ); + } +#else /* PSA_CRYPTO_DRIVER_PRESENT */ + (void) operation; + (void) output; + (void) output_size; + (void) output_length; + + return( PSA_ERROR_NOT_SUPPORTED ); +#endif /* PSA_CRYPTO_DRIVER_PRESENT */ +} + +psa_status_t psa_driver_wrapper_cipher_abort( + psa_operation_driver_context_t *operation ) +{ +#if defined(PSA_CRYPTO_DRIVER_PRESENT) && defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) + psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; + + /* The object has (apparently) been initialized but it is not in use. It's + * ok to call abort on such an object, and there's nothing to do. */ + if( operation->ctx == NULL && operation->id == 0 ) + return( PSA_SUCCESS ); + + switch( operation->id ) + { +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID: + status = test_transparent_cipher_abort( operation->ctx ); + mbedtls_platform_zeroize( + operation->ctx, + sizeof( test_transparent_cipher_operation_t ) ); + mbedtls_free( operation->ctx ); + operation->ctx = NULL; + operation->id = 0; + + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID: + status = test_opaque_cipher_abort( operation->ctx ); + mbedtls_platform_zeroize( + operation->ctx, + sizeof( test_opaque_cipher_operation_t ) ); + mbedtls_free( operation->ctx ); + operation->ctx = NULL; + operation->id = 0; + + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ + default: + /* Operation is attached to a driver not known to us */ + return( PSA_ERROR_BAD_STATE ); + } +#else /* PSA_CRYPTO_DRIVER_PRESENT */ + (void)operation; + + return( PSA_ERROR_NOT_SUPPORTED ); +#endif /* PSA_CRYPTO_DRIVER_PRESENT */ +} + +/* End of automatically generated file. */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/psa_crypto_driver_wrappers.h b/Android/Level4/app/src/main/c/mbedtls/library/psa_crypto_driver_wrappers.h new file mode 100644 index 0000000..b0b483b --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/psa_crypto_driver_wrappers.h @@ -0,0 +1,119 @@ +/* + * Function signatures for functionality that can be provided by + * cryptographic accelerators. + * Warning: This file will be auto-generated in the future. + */ +/* Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 PSA_CRYPTO_DRIVER_WRAPPERS_H +#define PSA_CRYPTO_DRIVER_WRAPPERS_H + +#include "psa/crypto.h" +#include "psa/crypto_driver_common.h" + +/* + * Signature functions + */ +psa_status_t psa_driver_wrapper_sign_hash( psa_key_slot_t *slot, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + uint8_t *signature, + size_t signature_size, + size_t *signature_length ); + +psa_status_t psa_driver_wrapper_verify_hash( psa_key_slot_t *slot, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + const uint8_t *signature, + size_t signature_length ); + +/* + * Key handling functions + */ + +psa_status_t psa_driver_wrapper_generate_key( const psa_key_attributes_t *attributes, + psa_key_slot_t *slot ); + +psa_status_t psa_driver_wrapper_validate_key( const psa_key_attributes_t *attributes, + const uint8_t *data, + size_t data_length, + size_t *bits ); + +/* + * Cipher functions + */ +psa_status_t psa_driver_wrapper_cipher_encrypt( + psa_key_slot_t *slot, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length ); + +psa_status_t psa_driver_wrapper_cipher_decrypt( + psa_key_slot_t *slot, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length ); + +psa_status_t psa_driver_wrapper_cipher_encrypt_setup( + psa_operation_driver_context_t *operation, + psa_key_slot_t *slot, + psa_algorithm_t alg ); + +psa_status_t psa_driver_wrapper_cipher_decrypt_setup( + psa_operation_driver_context_t *operation, + psa_key_slot_t *slot, + psa_algorithm_t alg ); + +psa_status_t psa_driver_wrapper_cipher_generate_iv( + psa_operation_driver_context_t *operation, + uint8_t *iv, + size_t iv_size, + size_t *iv_length ); + +psa_status_t psa_driver_wrapper_cipher_set_iv( + psa_operation_driver_context_t *operation, + const uint8_t *iv, + size_t iv_length ); + +psa_status_t psa_driver_wrapper_cipher_update( + psa_operation_driver_context_t *operation, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length ); + +psa_status_t psa_driver_wrapper_cipher_finish( + psa_operation_driver_context_t *operation, + uint8_t *output, + size_t output_size, + size_t *output_length ); + +psa_status_t psa_driver_wrapper_cipher_abort( + psa_operation_driver_context_t *operation ); + +#endif /* PSA_CRYPTO_DRIVER_WRAPPERS_H */ + +/* End of automatically generated file. */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/psa_crypto_invasive.h b/Android/Level4/app/src/main/c/mbedtls/library/psa_crypto_invasive.h new file mode 100644 index 0000000..c609c77 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/psa_crypto_invasive.h @@ -0,0 +1,77 @@ +/** + * \file psa_crypto_invasive.h + * + * \brief PSA cryptography module: invasive interfaces for test only. + * + * The interfaces in this file are intended for testing purposes only. + * They MUST NOT be made available to clients over IPC in integrations + * with isolation, and they SHOULD NOT be made available in library + * integrations except when building the library for testing. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 PSA_CRYPTO_INVASIVE_H +#define PSA_CRYPTO_INVASIVE_H + +#if defined(MBEDTLS_CONFIG_FILE) +#include MBEDTLS_CONFIG_FILE +#else +#include "mbedtls/config.h" +#endif + +#include "psa/crypto.h" + +#include "mbedtls/entropy.h" + +/** \brief Configure entropy sources. + * + * This function may only be called before a call to psa_crypto_init(), + * or after a call to mbedtls_psa_crypto_free() and before any + * subsequent call to psa_crypto_init(). + * + * This function is only intended for test purposes. The functionality + * it provides is also useful for system integrators, but + * system integrators should configure entropy drivers instead of + * breaking through to the Mbed TLS API. + * + * \param entropy_init Function to initialize the entropy context + * and set up the desired entropy sources. + * It is called by psa_crypto_init(). + * By default this is mbedtls_entropy_init(). + * This function cannot report failures directly. + * To indicate a failure, set the entropy context + * to a state where mbedtls_entropy_func() will + * return an error. + * \param entropy_free Function to free the entropy context + * and associated resources. + * It is called by mbedtls_psa_crypto_free(). + * By default this is mbedtls_entropy_free(). + * + * \retval PSA_SUCCESS + * Success. + * \retval PSA_ERROR_NOT_PERMITTED + * The caller does not have the permission to configure + * entropy sources. + * \retval PSA_ERROR_BAD_STATE + * The library has already been initialized. + */ +psa_status_t mbedtls_psa_crypto_configure_entropy_sources( + void (* entropy_init )( mbedtls_entropy_context *ctx ), + void (* entropy_free )( mbedtls_entropy_context *ctx ) ); + +#endif /* PSA_CRYPTO_INVASIVE_H */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/psa_crypto_its.h b/Android/Level4/app/src/main/c/mbedtls/library/psa_crypto_its.h new file mode 100644 index 0000000..b671d63 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/psa_crypto_its.h @@ -0,0 +1,149 @@ +/** \file psa_crypto_its.h + * \brief Interface of trusted storage that crypto is built on. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 PSA_CRYPTO_ITS_H +#define PSA_CRYPTO_ITS_H + +#include +#include + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** \brief Flags used when creating a data entry + */ +typedef uint32_t psa_storage_create_flags_t; + +/** \brief A type for UIDs used for identifying data + */ +typedef uint64_t psa_storage_uid_t; + +#define PSA_STORAGE_FLAG_NONE 0 /**< No flags to pass */ +#define PSA_STORAGE_FLAG_WRITE_ONCE (1 << 0) /**< The data associated with the uid will not be able to be modified or deleted. Intended to be used to set bits in `psa_storage_create_flags_t`*/ + +/** + * \brief A container for metadata associated with a specific uid + */ +struct psa_storage_info_t +{ + uint32_t size; /**< The size of the data associated with a uid **/ + psa_storage_create_flags_t flags; /**< The flags set when the uid was created **/ +}; + +/** Flag indicating that \ref psa_storage_create and \ref psa_storage_set_extended are supported */ +#define PSA_STORAGE_SUPPORT_SET_EXTENDED (1 << 0) + +/** \brief PSA storage specific error codes + */ +#define PSA_ERROR_INVALID_SIGNATURE ((psa_status_t)-149) +#define PSA_ERROR_DATA_CORRUPT ((psa_status_t)-152) + +#define PSA_ITS_API_VERSION_MAJOR 1 /**< The major version number of the PSA ITS API. It will be incremented on significant updates that may include breaking changes */ +#define PSA_ITS_API_VERSION_MINOR 1 /**< The minor version number of the PSA ITS API. It will be incremented in small updates that are unlikely to include breaking changes */ + +/** + * \brief create a new or modify an existing uid/value pair + * + * \param[in] uid the identifier for the data + * \param[in] data_length The size in bytes of the data in `p_data` + * \param[in] p_data A buffer containing the data + * \param[in] create_flags The flags that the data will be stored with + * + * \return A status indicating the success/failure of the operation + * + * \retval PSA_SUCCESS The operation completed successfully + * \retval PSA_ERROR_NOT_PERMITTED The operation failed because the provided `uid` value was already created with PSA_STORAGE_WRITE_ONCE_FLAG + * \retval PSA_ERROR_NOT_SUPPORTED The operation failed because one or more of the flags provided in `create_flags` is not supported or is not valid + * \retval PSA_ERROR_INSUFFICIENT_STORAGE The operation failed because there was insufficient space on the storage medium + * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) + * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the provided pointers(`p_data`) + * is invalid, for example is `NULL` or references memory the caller cannot access + */ +psa_status_t psa_its_set(psa_storage_uid_t uid, + uint32_t data_length, + const void *p_data, + psa_storage_create_flags_t create_flags); + +/** + * \brief Retrieve the value associated with a provided uid + * + * \param[in] uid The uid value + * \param[in] data_offset The starting offset of the data requested + * \param[in] data_length the amount of data requested (and the minimum allocated size of the `p_data` buffer) + * \param[out] p_data The buffer where the data will be placed upon successful completion + * \param[out] p_data_length The amount of data returned in the p_data buffer + * + * + * \return A status indicating the success/failure of the operation + * + * \retval PSA_SUCCESS The operation completed successfully + * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided `uid` value was not found in the storage + * \retval PSA_ERROR_INVALID_SIZE The operation failed because the data associated with provided uid is larger than `data_size` + * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) + * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the provided pointers(`p_data`, `p_data_length`) + * is invalid. For example is `NULL` or references memory the caller cannot access. + * In addition, this can also happen if an invalid offset was provided. + */ +psa_status_t psa_its_get(psa_storage_uid_t uid, + uint32_t data_offset, + uint32_t data_length, + void *p_data, + size_t *p_data_length ); + +/** + * \brief Retrieve the metadata about the provided uid + * + * \param[in] uid The uid value + * \param[out] p_info A pointer to the `psa_storage_info_t` struct that will be populated with the metadata + * + * \return A status indicating the success/failure of the operation + * + * \retval PSA_SUCCESS The operation completed successfully + * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided uid value was not found in the storage + * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) + * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the provided pointers(`p_info`) + * is invalid, for example is `NULL` or references memory the caller cannot access + */ +psa_status_t psa_its_get_info(psa_storage_uid_t uid, + struct psa_storage_info_t *p_info); + +/** + * \brief Remove the provided key and its associated data from the storage + * + * \param[in] uid The uid value + * + * \return A status indicating the success/failure of the operation + * + * \retval PSA_SUCCESS The operation completed successfully + * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided key value was not found in the storage + * \retval PSA_ERROR_NOT_PERMITTED The operation failed because the provided key value was created with PSA_STORAGE_WRITE_ONCE_FLAG + * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) + */ +psa_status_t psa_its_remove(psa_storage_uid_t uid); + +#ifdef __cplusplus +} +#endif + +#endif /* PSA_CRYPTO_ITS_H */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/psa_crypto_se.c b/Android/Level4/app/src/main/c/mbedtls/library/psa_crypto_se.c new file mode 100644 index 0000000..56678d6 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/psa_crypto_se.c @@ -0,0 +1,383 @@ +/* + * PSA crypto support for secure element drivers + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 "common.h" + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + +#include +#include +#include + +#include "psa/crypto_se_driver.h" + +#include "psa_crypto_se.h" + +#if defined(MBEDTLS_PSA_ITS_FILE_C) +#include "psa_crypto_its.h" +#else /* Native ITS implementation */ +#include "psa/error.h" +#include "psa/internal_trusted_storage.h" +#endif + +#include "mbedtls/platform.h" +#if !defined(MBEDTLS_PLATFORM_C) +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + + + +/****************************************************************/ +/* Driver lookup */ +/****************************************************************/ + +/* This structure is identical to psa_drv_se_context_t declared in + * `crypto_se_driver.h`, except that some parts are writable here + * (non-const, or pointer to non-const). */ +typedef struct +{ + void *persistent_data; + size_t persistent_data_size; + uintptr_t transient_data; +} psa_drv_se_internal_context_t; + +struct psa_se_drv_table_entry_s +{ + psa_key_location_t location; + const psa_drv_se_t *methods; + union + { + psa_drv_se_internal_context_t internal; + psa_drv_se_context_t context; + } u; +}; + +static psa_se_drv_table_entry_t driver_table[PSA_MAX_SE_DRIVERS]; + +psa_se_drv_table_entry_t *psa_get_se_driver_entry( + psa_key_lifetime_t lifetime ) +{ + size_t i; + psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( lifetime ); + /* In the driver table, location=0 means an entry that isn't used. + * No driver has a location of 0 because it's a reserved value + * (which designates transparent keys). Make sure we never return + * a driver entry for location 0. */ + if( location == 0 ) + return( NULL ); + for( i = 0; i < PSA_MAX_SE_DRIVERS; i++ ) + { + if( driver_table[i].location == location ) + return( &driver_table[i] ); + } + return( NULL ); +} + +const psa_drv_se_t *psa_get_se_driver_methods( + const psa_se_drv_table_entry_t *driver ) +{ + return( driver->methods ); +} + +psa_drv_se_context_t *psa_get_se_driver_context( + psa_se_drv_table_entry_t *driver ) +{ + return( &driver->u.context ); +} + +int psa_get_se_driver( psa_key_lifetime_t lifetime, + const psa_drv_se_t **p_methods, + psa_drv_se_context_t **p_drv_context) +{ + psa_se_drv_table_entry_t *driver = psa_get_se_driver_entry( lifetime ); + if( p_methods != NULL ) + *p_methods = ( driver ? driver->methods : NULL ); + if( p_drv_context != NULL ) + *p_drv_context = ( driver ? &driver->u.context : NULL ); + return( driver != NULL ); +} + + + +/****************************************************************/ +/* Persistent data management */ +/****************************************************************/ + +static psa_status_t psa_get_se_driver_its_file_uid( + const psa_se_drv_table_entry_t *driver, + psa_storage_uid_t *uid ) +{ + if( driver->location > PSA_MAX_SE_LOCATION ) + return( PSA_ERROR_NOT_SUPPORTED ); + +#if SIZE_MAX > UINT32_MAX + /* ITS file sizes are limited to 32 bits. */ + if( driver->u.internal.persistent_data_size > UINT32_MAX ) + return( PSA_ERROR_NOT_SUPPORTED ); +#endif + + /* See the documentation of PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE. */ + *uid = PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE + driver->location; + return( PSA_SUCCESS ); +} + +psa_status_t psa_load_se_persistent_data( + const psa_se_drv_table_entry_t *driver ) +{ + psa_status_t status; + psa_storage_uid_t uid; + size_t length; + + status = psa_get_se_driver_its_file_uid( driver, &uid ); + if( status != PSA_SUCCESS ) + return( status ); + + /* Read the amount of persistent data that the driver requests. + * If the data in storage is larger, it is truncated. If the data + * in storage is smaller, silently keep what is already at the end + * of the output buffer. */ + /* psa_get_se_driver_its_file_uid ensures that the size_t + * persistent_data_size is in range, but compilers don't know that, + * so cast to reassure them. */ + return( psa_its_get( uid, 0, + (uint32_t) driver->u.internal.persistent_data_size, + driver->u.internal.persistent_data, + &length ) ); +} + +psa_status_t psa_save_se_persistent_data( + const psa_se_drv_table_entry_t *driver ) +{ + psa_status_t status; + psa_storage_uid_t uid; + + status = psa_get_se_driver_its_file_uid( driver, &uid ); + if( status != PSA_SUCCESS ) + return( status ); + + /* psa_get_se_driver_its_file_uid ensures that the size_t + * persistent_data_size is in range, but compilers don't know that, + * so cast to reassure them. */ + return( psa_its_set( uid, + (uint32_t) driver->u.internal.persistent_data_size, + driver->u.internal.persistent_data, + 0 ) ); +} + +psa_status_t psa_destroy_se_persistent_data( psa_key_location_t location ) +{ + psa_storage_uid_t uid; + if( location > PSA_MAX_SE_LOCATION ) + return( PSA_ERROR_NOT_SUPPORTED ); + uid = PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE + location; + return( psa_its_remove( uid ) ); +} + +psa_status_t psa_find_se_slot_for_key( + const psa_key_attributes_t *attributes, + psa_key_creation_method_t method, + psa_se_drv_table_entry_t *driver, + psa_key_slot_number_t *slot_number ) +{ + psa_status_t status; + psa_key_location_t key_location = + PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime( attributes ) ); + + /* If the location is wrong, it's a bug in the library. */ + if( driver->location != key_location ) + return( PSA_ERROR_CORRUPTION_DETECTED ); + + /* If the driver doesn't support key creation in any way, give up now. */ + if( driver->methods->key_management == NULL ) + return( PSA_ERROR_NOT_SUPPORTED ); + + if( psa_get_key_slot_number( attributes, slot_number ) == PSA_SUCCESS ) + { + /* The application wants to use a specific slot. Allow it if + * the driver supports it. On a system with isolation, + * the crypto service must check that the application is + * permitted to request this slot. */ + psa_drv_se_validate_slot_number_t p_validate_slot_number = + driver->methods->key_management->p_validate_slot_number; + if( p_validate_slot_number == NULL ) + return( PSA_ERROR_NOT_SUPPORTED ); + status = p_validate_slot_number( &driver->u.context, + driver->u.internal.persistent_data, + attributes, method, + *slot_number ); + } + else if( method == PSA_KEY_CREATION_REGISTER ) + { + /* The application didn't specify a slot number. This doesn't + * make sense when registering a slot. */ + return( PSA_ERROR_INVALID_ARGUMENT ); + } + else + { + /* The application didn't tell us which slot to use. Let the driver + * choose. This is the normal case. */ + psa_drv_se_allocate_key_t p_allocate = + driver->methods->key_management->p_allocate; + if( p_allocate == NULL ) + return( PSA_ERROR_NOT_SUPPORTED ); + status = p_allocate( &driver->u.context, + driver->u.internal.persistent_data, + attributes, method, + slot_number ); + } + return( status ); +} + +psa_status_t psa_destroy_se_key( psa_se_drv_table_entry_t *driver, + psa_key_slot_number_t slot_number ) +{ + psa_status_t status; + psa_status_t storage_status; + /* Normally a missing method would mean that the action is not + * supported. But psa_destroy_key() is not supposed to return + * PSA_ERROR_NOT_SUPPORTED: if you can create a key, you should + * be able to destroy it. The only use case for a driver that + * does not have a way to destroy keys at all is if the keys are + * locked in a read-only state: we can use the keys but not + * destroy them. Hence, if the driver doesn't support destroying + * keys, it's really a lack of permission. */ + if( driver->methods->key_management == NULL || + driver->methods->key_management->p_destroy == NULL ) + return( PSA_ERROR_NOT_PERMITTED ); + status = driver->methods->key_management->p_destroy( + &driver->u.context, + driver->u.internal.persistent_data, + slot_number ); + storage_status = psa_save_se_persistent_data( driver ); + return( status == PSA_SUCCESS ? storage_status : status ); +} + +psa_status_t psa_init_all_se_drivers( void ) +{ + size_t i; + for( i = 0; i < PSA_MAX_SE_DRIVERS; i++ ) + { + psa_se_drv_table_entry_t *driver = &driver_table[i]; + if( driver->location == 0 ) + continue; /* skipping unused entry */ + const psa_drv_se_t *methods = psa_get_se_driver_methods( driver ); + if( methods->p_init != NULL ) + { + psa_status_t status = methods->p_init( + &driver->u.context, + driver->u.internal.persistent_data, + driver->location ); + if( status != PSA_SUCCESS ) + return( status ); + status = psa_save_se_persistent_data( driver ); + if( status != PSA_SUCCESS ) + return( status ); + } + } + return( PSA_SUCCESS ); +} + + + +/****************************************************************/ +/* Driver registration */ +/****************************************************************/ + +psa_status_t psa_register_se_driver( + psa_key_location_t location, + const psa_drv_se_t *methods) +{ + size_t i; + psa_status_t status; + + if( methods->hal_version != PSA_DRV_SE_HAL_VERSION ) + return( PSA_ERROR_NOT_SUPPORTED ); + /* Driver table entries are 0-initialized. 0 is not a valid driver + * location because it means a transparent key. */ +#if defined(static_assert) + static_assert( PSA_KEY_LOCATION_LOCAL_STORAGE == 0, + "Secure element support requires 0 to mean a local key" ); +#endif + if( location == PSA_KEY_LOCATION_LOCAL_STORAGE ) + return( PSA_ERROR_INVALID_ARGUMENT ); + if( location > PSA_MAX_SE_LOCATION ) + return( PSA_ERROR_NOT_SUPPORTED ); + + for( i = 0; i < PSA_MAX_SE_DRIVERS; i++ ) + { + if( driver_table[i].location == 0 ) + break; + /* Check that location isn't already in use up to the first free + * entry. Since entries are created in order and never deleted, + * there can't be a used entry after the first free entry. */ + if( driver_table[i].location == location ) + return( PSA_ERROR_ALREADY_EXISTS ); + } + if( i == PSA_MAX_SE_DRIVERS ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + + driver_table[i].location = location; + driver_table[i].methods = methods; + driver_table[i].u.internal.persistent_data_size = + methods->persistent_data_size; + + if( methods->persistent_data_size != 0 ) + { + driver_table[i].u.internal.persistent_data = + mbedtls_calloc( 1, methods->persistent_data_size ); + if( driver_table[i].u.internal.persistent_data == NULL ) + { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto error; + } + /* Load the driver's persistent data. On first use, the persistent + * data does not exist in storage, and is initialized to + * all-bits-zero by the calloc call just above. */ + status = psa_load_se_persistent_data( &driver_table[i] ); + if( status != PSA_SUCCESS && status != PSA_ERROR_DOES_NOT_EXIST ) + goto error; + } + + return( PSA_SUCCESS ); + +error: + memset( &driver_table[i], 0, sizeof( driver_table[i] ) ); + return( status ); +} + +void psa_unregister_all_se_drivers( void ) +{ + size_t i; + for( i = 0; i < PSA_MAX_SE_DRIVERS; i++ ) + { + if( driver_table[i].u.internal.persistent_data != NULL ) + mbedtls_free( driver_table[i].u.internal.persistent_data ); + } + memset( driver_table, 0, sizeof( driver_table ) ); +} + + + +/****************************************************************/ +/* The end */ +/****************************************************************/ + +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/psa_crypto_se.h b/Android/Level4/app/src/main/c/mbedtls/library/psa_crypto_se.h new file mode 100644 index 0000000..67fadf8 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/psa_crypto_se.h @@ -0,0 +1,187 @@ +/* + * PSA crypto support for secure element drivers + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 PSA_CRYPTO_SE_H +#define PSA_CRYPTO_SE_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "psa/crypto.h" +#include "psa/crypto_se_driver.h" + +/** The maximum location value that this implementation supports + * for a secure element. + * + * This is not a characteristic that each PSA implementation has, but a + * limitation of the current implementation due to the constraints imposed + * by storage. See #PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE. + * + * The minimum location value for a secure element is 1, like on any + * PSA implementation (0 means a transparent key). + */ +#define PSA_MAX_SE_LOCATION 255 + +/** The base of the range of ITS file identifiers for secure element + * driver persistent data. + * + * We use a slice of the implementation reserved range 0xffff0000..0xffffffff, + * specifically the range 0xfffffe00..0xfffffeff. The length of this range + * drives the value of #PSA_MAX_SE_LOCATION. The identifier 0xfffffe00 is + * actually not used since it corresponds to #PSA_KEY_LOCATION_LOCAL_STORAGE + * which doesn't have a driver. + */ +#define PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE ( (psa_key_id_t) 0xfffffe00 ) + +/** The maximum number of registered secure element driver locations. */ +#define PSA_MAX_SE_DRIVERS 4 + +/** Unregister all secure element drivers. + * + * \warning Do not call this function while the library is in the initialized + * state. This function is only intended to be called at the end + * of mbedtls_psa_crypto_free(). + */ +void psa_unregister_all_se_drivers( void ); + +/** Initialize all secure element drivers. + * + * Called from psa_crypto_init(). + */ +psa_status_t psa_init_all_se_drivers( void ); + +/** A structure that describes a registered secure element driver. + * + * A secure element driver table entry contains a pointer to the + * driver's method table as well as the driver context structure. + */ +typedef struct psa_se_drv_table_entry_s psa_se_drv_table_entry_t; + +/** Return the secure element driver information for a lifetime value. + * + * \param lifetime The lifetime value to query. + * \param[out] p_methods On output, if there is a driver, + * \c *methods points to its method table. + * Otherwise \c *methods is \c NULL. + * \param[out] p_drv_context On output, if there is a driver, + * \c *drv_context points to its context + * structure. + * Otherwise \c *drv_context is \c NULL. + * + * \retval 1 + * \p lifetime corresponds to a registered driver. + * \retval 0 + * \p lifetime does not correspond to a registered driver. + */ +int psa_get_se_driver( psa_key_lifetime_t lifetime, + const psa_drv_se_t **p_methods, + psa_drv_se_context_t **p_drv_context); + +/** Return the secure element driver table entry for a lifetime value. + * + * \param lifetime The lifetime value to query. + * + * \return The driver table entry for \p lifetime, or + * \p NULL if \p lifetime does not correspond to a registered driver. + */ +psa_se_drv_table_entry_t *psa_get_se_driver_entry( + psa_key_lifetime_t lifetime ); + +/** Return the method table for a secure element driver. + * + * \param[in] driver The driver table entry to access, or \c NULL. + * + * \return The driver's method table. + * \c NULL if \p driver is \c NULL. + */ +const psa_drv_se_t *psa_get_se_driver_methods( + const psa_se_drv_table_entry_t *driver ); + +/** Return the context of a secure element driver. + * + * \param[in] driver The driver table entry to access, or \c NULL. + * + * \return A pointer to the driver context. + * \c NULL if \p driver is \c NULL. + */ +psa_drv_se_context_t *psa_get_se_driver_context( + psa_se_drv_table_entry_t *driver ); + +/** Find a free slot for a key that is to be created. + * + * This function calls the relevant method in the driver to find a suitable + * slot for a key with the given attributes. + * + * \param[in] attributes Metadata about the key that is about to be created. + * \param[in] driver The driver table entry to query. + * \param[out] slot_number On success, a slot number that is free in this + * secure element. + */ +psa_status_t psa_find_se_slot_for_key( + const psa_key_attributes_t *attributes, + psa_key_creation_method_t method, + psa_se_drv_table_entry_t *driver, + psa_key_slot_number_t *slot_number ); + +/** Destoy a key in a secure element. + * + * This function calls the relevant driver method to destroy a key + * and updates the driver's persistent data. + */ +psa_status_t psa_destroy_se_key( psa_se_drv_table_entry_t *driver, + psa_key_slot_number_t slot_number ); + +/** Load the persistent data of a secure element driver. + * + * \param driver The driver table entry containing the persistent + * data to load from storage. + */ +psa_status_t psa_load_se_persistent_data( + const psa_se_drv_table_entry_t *driver ); + +/** Save the persistent data of a secure element driver. + * + * \param[in] driver The driver table entry containing the persistent + * data to save to storage. + */ +psa_status_t psa_save_se_persistent_data( + const psa_se_drv_table_entry_t *driver ); + +/** Destroy the persistent data of a secure element driver. + * + * This is currently only used for testing. + * + * \param[in] location The location identifier for the driver whose + * persistent data is to be erased. + */ +psa_status_t psa_destroy_se_persistent_data( psa_key_location_t location ); + + +/** The storage representation of a key whose data is in a secure element. + */ +typedef struct +{ + uint8_t slot_number[sizeof( psa_key_slot_number_t )]; +} psa_se_key_data_storage_t; + +#endif /* PSA_CRYPTO_SE_H */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/psa_crypto_service_integration.h b/Android/Level4/app/src/main/c/mbedtls/library/psa_crypto_service_integration.h new file mode 100644 index 0000000..87889af --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/psa_crypto_service_integration.h @@ -0,0 +1,39 @@ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 PSA_CRYPTO_SERVICE_INTEGRATION_H +#define PSA_CRYPTO_SERVICE_INTEGRATION_H + +/* + * When MBEDTLS_PSA_CRYPTO_SPM is defined, the code is being built for SPM + * (Secure Partition Manager) integration which separates the code into two + * parts: NSPE (Non-Secure Processing Environment) and SPE (Secure Processing + * Environment). When building for the SPE, an additional header file should be + * included. + */ +#if defined(MBEDTLS_PSA_CRYPTO_SPM) +/* + * PSA_CRYPTO_SECURE means that the file which included this file is being + * compiled for SPE. The files crypto_structs.h and crypto_types.h have + * different implementations for NSPE and SPE and are compiled according to this + * flag. + */ +#define PSA_CRYPTO_SECURE 1 +#include "crypto_spe.h" +#endif // MBEDTLS_PSA_CRYPTO_SPM + +#endif // PSA_CRYPTO_SERVICE_INTEGRATION_H diff --git a/Android/Level4/app/src/main/c/mbedtls/library/psa_crypto_slot_management.c b/Android/Level4/app/src/main/c/mbedtls/library/psa_crypto_slot_management.c new file mode 100644 index 0000000..5140772 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/psa_crypto_slot_management.c @@ -0,0 +1,308 @@ +/* + * PSA crypto layer on top of Mbed TLS crypto + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 "common.h" + +#if defined(MBEDTLS_PSA_CRYPTO_C) + +#include "psa_crypto_service_integration.h" +#include "psa/crypto.h" + +#include "psa_crypto_core.h" +#include "psa_crypto_slot_management.h" +#include "psa_crypto_storage.h" +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) +#include "psa_crypto_se.h" +#endif + +#include +#include +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#define ARRAY_LENGTH( array ) ( sizeof( array ) / sizeof( *( array ) ) ) + +typedef struct +{ + psa_key_slot_t key_slots[PSA_KEY_SLOT_COUNT]; + unsigned key_slots_initialized : 1; +} psa_global_data_t; + +static psa_global_data_t global_data; + +/* Access a key slot at the given handle. The handle of a key slot is + * the index of the slot in the global slot array, plus one so that handles + * start at 1 and not 0. */ +psa_status_t psa_get_key_slot( psa_key_handle_t handle, + psa_key_slot_t **p_slot ) +{ + psa_key_slot_t *slot = NULL; + + if( ! global_data.key_slots_initialized ) + return( PSA_ERROR_BAD_STATE ); + + /* 0 is not a valid handle under any circumstance. This + * implementation provides slots number 1 to N where N is the + * number of available slots. */ + if( handle == 0 || handle > ARRAY_LENGTH( global_data.key_slots ) ) + return( PSA_ERROR_INVALID_HANDLE ); + slot = &global_data.key_slots[handle - 1]; + + /* If the slot isn't occupied, the handle is invalid. */ + if( ! psa_is_key_slot_occupied( slot ) ) + return( PSA_ERROR_INVALID_HANDLE ); + + *p_slot = slot; + return( PSA_SUCCESS ); +} + +psa_status_t psa_initialize_key_slots( void ) +{ + /* Nothing to do: program startup and psa_wipe_all_key_slots() both + * guarantee that the key slots are initialized to all-zero, which + * means that all the key slots are in a valid, empty state. */ + global_data.key_slots_initialized = 1; + return( PSA_SUCCESS ); +} + +void psa_wipe_all_key_slots( void ) +{ + psa_key_handle_t key; + for( key = 1; key <= PSA_KEY_SLOT_COUNT; key++ ) + { + psa_key_slot_t *slot = &global_data.key_slots[key - 1]; + (void) psa_wipe_key_slot( slot ); + } + global_data.key_slots_initialized = 0; +} + +psa_status_t psa_get_empty_key_slot( psa_key_handle_t *handle, + psa_key_slot_t **p_slot ) +{ + if( ! global_data.key_slots_initialized ) + return( PSA_ERROR_BAD_STATE ); + + for( *handle = PSA_KEY_SLOT_COUNT; *handle != 0; --( *handle ) ) + { + *p_slot = &global_data.key_slots[*handle - 1]; + if( ! psa_is_key_slot_occupied( *p_slot ) ) + return( PSA_SUCCESS ); + } + *p_slot = NULL; + return( PSA_ERROR_INSUFFICIENT_MEMORY ); +} + +#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) +static psa_status_t psa_load_persistent_key_into_slot( psa_key_slot_t *slot ) +{ + psa_status_t status = PSA_SUCCESS; + uint8_t *key_data = NULL; + size_t key_data_length = 0; + + status = psa_load_persistent_key( &slot->attr, + &key_data, &key_data_length ); + if( status != PSA_SUCCESS ) + goto exit; + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + if( psa_key_lifetime_is_external( slot->attr.lifetime ) ) + { + psa_se_key_data_storage_t *data; + if( key_data_length != sizeof( *data ) ) + { + status = PSA_ERROR_STORAGE_FAILURE; + goto exit; + } + data = (psa_se_key_data_storage_t *) key_data; + memcpy( &slot->data.se.slot_number, &data->slot_number, + sizeof( slot->data.se.slot_number ) ); + } + else +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + { + status = psa_copy_key_material_into_slot( slot, key_data, key_data_length ); + if( status != PSA_SUCCESS ) + goto exit; + } + +exit: + psa_free_persistent_key_data( key_data, key_data_length ); + return( status ); +} + +/** Check whether a key identifier is acceptable. + * + * For backward compatibility, key identifiers that were valid in a + * past released version must remain valid, unless a migration path + * is provided. + * + * \param key The key identifier to check. + * \param vendor_ok Nonzero to allow key ids in the vendor range. + * 0 to allow only key ids in the application range. + * + * \return 1 if \p key is acceptable, otherwise 0. + */ +static int psa_is_key_id_valid( mbedtls_svc_key_id_t key, int vendor_ok ) +{ + psa_key_id_t key_id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID( key ); + if( PSA_KEY_ID_USER_MIN <= key_id && key_id <= PSA_KEY_ID_USER_MAX ) + return( 1 ); + else if( vendor_ok && + PSA_KEY_ID_VENDOR_MIN <= key_id && + key_id <= PSA_KEY_ID_VENDOR_MAX ) + return( 1 ); + else + return( 0 ); +} +#endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ + +psa_status_t psa_validate_key_location( psa_key_lifetime_t lifetime, + psa_se_drv_table_entry_t **p_drv ) +{ + if ( psa_key_lifetime_is_external( lifetime ) ) + { +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + psa_se_drv_table_entry_t *driver = psa_get_se_driver_entry( lifetime ); + if( driver == NULL ) + return( PSA_ERROR_INVALID_ARGUMENT ); + else + { + if (p_drv != NULL) + *p_drv = driver; + return( PSA_SUCCESS ); + } +#else + (void) p_drv; + return( PSA_ERROR_INVALID_ARGUMENT ); +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + } + else + /* Local/internal keys are always valid */ + return( PSA_SUCCESS ); +} + +psa_status_t psa_validate_key_persistence( psa_key_lifetime_t lifetime, + mbedtls_svc_key_id_t key ) +{ + if ( PSA_KEY_LIFETIME_IS_VOLATILE( lifetime ) ) + { + /* Volatile keys are always supported */ + return( PSA_SUCCESS ); + } + else + { + /* Persistent keys require storage support */ +#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) + if( psa_is_key_id_valid( key, + psa_key_lifetime_is_external( lifetime ) ) ) + return( PSA_SUCCESS ); + else + return( PSA_ERROR_INVALID_ARGUMENT ); +#else /* MBEDTLS_PSA_CRYPTO_STORAGE_C */ + (void) key; + return( PSA_ERROR_NOT_SUPPORTED ); +#endif /* !MBEDTLS_PSA_CRYPTO_STORAGE_C */ + } +} + +psa_status_t psa_open_key( mbedtls_svc_key_id_t key, psa_key_handle_t *handle ) +{ +#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) + psa_status_t status; + psa_key_slot_t *slot; + + *handle = 0; + + if( ! psa_is_key_id_valid( key, 1 ) ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + status = psa_get_empty_key_slot( handle, &slot ); + if( status != PSA_SUCCESS ) + return( status ); + + slot->attr.lifetime = PSA_KEY_LIFETIME_PERSISTENT; + slot->attr.id = key; + + status = psa_load_persistent_key_into_slot( slot ); + if( status != PSA_SUCCESS ) + { + psa_wipe_key_slot( slot ); + *handle = 0; + } + return( status ); + +#else /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ + (void) key; + *handle = 0; + return( PSA_ERROR_NOT_SUPPORTED ); +#endif /* !defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ +} + +psa_status_t psa_close_key( psa_key_handle_t handle ) +{ + psa_status_t status; + psa_key_slot_t *slot; + + if( handle == 0 ) + return( PSA_SUCCESS ); + + status = psa_get_key_slot( handle, &slot ); + if( status != PSA_SUCCESS ) + return( status ); + + return( psa_wipe_key_slot( slot ) ); +} + +void mbedtls_psa_get_stats( mbedtls_psa_stats_t *stats ) +{ + psa_key_handle_t key; + memset( stats, 0, sizeof( *stats ) ); + for( key = 1; key <= PSA_KEY_SLOT_COUNT; key++ ) + { + const psa_key_slot_t *slot = &global_data.key_slots[key - 1]; + if( ! psa_is_key_slot_occupied( slot ) ) + { + ++stats->empty_slots; + continue; + } + if( slot->attr.lifetime == PSA_KEY_LIFETIME_VOLATILE ) + ++stats->volatile_slots; + else if( slot->attr.lifetime == PSA_KEY_LIFETIME_PERSISTENT ) + { + psa_key_id_t id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID( slot->attr.id ); + ++stats->persistent_slots; + if( id > stats->max_open_internal_key_id ) + stats->max_open_internal_key_id = id; + } + else + { + psa_key_id_t id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID( slot->attr.id ); + ++stats->external_slots; + if( id > stats->max_open_external_key_id ) + stats->max_open_external_key_id = id; + } + } +} + +#endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/psa_crypto_slot_management.h b/Android/Level4/app/src/main/c/mbedtls/library/psa_crypto_slot_management.h new file mode 100644 index 0000000..c6fecbb --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/psa_crypto_slot_management.h @@ -0,0 +1,125 @@ +/* + * PSA crypto layer on top of Mbed TLS crypto + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 PSA_CRYPTO_SLOT_MANAGEMENT_H +#define PSA_CRYPTO_SLOT_MANAGEMENT_H + +#include "psa/crypto.h" +#include "psa_crypto_se.h" + +/* Number of key slots (plus one because 0 is not used). + * The value is a compile-time constant for now, for simplicity. */ +#define PSA_KEY_SLOT_COUNT 32 + +/** Access a key slot at the given handle. + * + * \param handle Key handle to query. + * \param[out] p_slot On success, `*p_slot` contains a pointer to the + * key slot in memory designated by \p handle. + * + * \retval PSA_SUCCESS + * Success: \p handle is a handle to `*p_slot`. Note that `*p_slot` + * may be empty or occupied. + * \retval PSA_ERROR_INVALID_HANDLE + * \p handle is out of range or is not in use. + * \retval PSA_ERROR_BAD_STATE + * The library has not been initialized. + */ +psa_status_t psa_get_key_slot( psa_key_handle_t handle, + psa_key_slot_t **p_slot ); + +/** Initialize the key slot structures. + * + * \retval PSA_SUCCESS + * Currently this function always succeeds. + */ +psa_status_t psa_initialize_key_slots( void ); + +/** Delete all data from key slots in memory. + * + * This does not affect persistent storage. */ +void psa_wipe_all_key_slots( void ); + +/** Find a free key slot. + * + * This function returns a key slot that is available for use and is in its + * ground state (all-bits-zero). + * + * \param[out] handle On success, a slot number that can be used as a + * handle to the slot. + * \param[out] p_slot On success, a pointer to the slot. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_BAD_STATE + */ +psa_status_t psa_get_empty_key_slot( psa_key_handle_t *handle, + psa_key_slot_t **p_slot ); + +/** Test whether a lifetime designates a key in an external cryptoprocessor. + * + * \param lifetime The lifetime to test. + * + * \retval 1 + * The lifetime designates an external key. There should be a + * registered driver for this lifetime, otherwise the key cannot + * be created or manipulated. + * \retval 0 + * The lifetime designates a key that is volatile or in internal + * storage. + */ +static inline int psa_key_lifetime_is_external( psa_key_lifetime_t lifetime ) +{ + return( PSA_KEY_LIFETIME_GET_LOCATION( lifetime ) + != PSA_KEY_LOCATION_LOCAL_STORAGE ); +} + +/** Validate a key's location. + * + * This function checks whether the key's attributes point to a location that + * is known to the PSA Core, and returns the driver function table if the key + * is to be found in an external location. + * + * \param[in] lifetime The key lifetime attribute. + * \param[out] p_drv On success, when a key is located in external + * storage, returns a pointer to the driver table + * associated with the key's storage location. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_ARGUMENT + */ +psa_status_t psa_validate_key_location( psa_key_lifetime_t lifetime, + psa_se_drv_table_entry_t **p_drv ); + +/** Validate that a key's persistence attributes are valid. + * + * This function checks whether a key's declared persistence level and key ID + * attributes are valid and known to the PSA Core in its actual configuration. + * + * \param[in] lifetime The key lifetime attribute. + * \param[in] key The key identifier. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_ARGUMENT + */ +psa_status_t psa_validate_key_persistence( psa_key_lifetime_t lifetime, + mbedtls_svc_key_id_t key ); + +#endif /* PSA_CRYPTO_SLOT_MANAGEMENT_H */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/psa_crypto_storage.c b/Android/Level4/app/src/main/c/mbedtls/library/psa_crypto_storage.c new file mode 100644 index 0000000..2ab5903 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/psa_crypto_storage.c @@ -0,0 +1,523 @@ +/* + * PSA persistent key storage + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ + +#if defined(MBEDTLS_CONFIG_FILE) +#include MBEDTLS_CONFIG_FILE +#else +#include "mbedtls/config.h" +#endif + +#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) + +#include +#include + +#include "psa_crypto_service_integration.h" +#include "psa/crypto.h" +#include "psa_crypto_storage.h" +#include "mbedtls/platform_util.h" + +#if defined(MBEDTLS_PSA_ITS_FILE_C) +#include "psa_crypto_its.h" +#else /* Native ITS implementation */ +#include "psa/error.h" +#include "psa/internal_trusted_storage.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + + + +/****************************************************************/ +/* Key storage */ +/****************************************************************/ + +/* Determine a file name (ITS file identifier) for the given key identifier. + * The file name must be distinct from any file that is used for a purpose + * other than storing a key. Currently, the only such file is the random seed + * file whose name is PSA_CRYPTO_ITS_RANDOM_SEED_UID and whose value is + * 0xFFFFFF52. */ +static psa_storage_uid_t psa_its_identifier_of_slot( mbedtls_svc_key_id_t key ) +{ +#if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) + /* Encode the owner in the upper 32 bits. This means that if + * owner values are nonzero (as they are on a PSA platform), + * no key file will ever have a value less than 0x100000000, so + * the whole range 0..0xffffffff is available for non-key files. */ + uint32_t unsigned_owner_id = MBEDTLS_SVC_KEY_ID_GET_OWNER_ID( key ); + return( ( (uint64_t) unsigned_owner_id << 32 ) | + MBEDTLS_SVC_KEY_ID_GET_KEY_ID( key ) ); +#else + /* Use the key id directly as a file name. + * psa_is_key_id_valid() in psa_crypto_slot_management.c + * is responsible for ensuring that key identifiers do not have a + * value that is reserved for non-key files. */ + return( key ); +#endif +} + +/** + * \brief Load persistent data for the given key slot number. + * + * This function reads data from a storage backend and returns the data in a + * buffer. + * + * \param key Persistent identifier of the key to be loaded. This + * should be an occupied storage location. + * \param[out] data Buffer where the data is to be written. + * \param data_size Size of the \c data buffer in bytes. + * + * \retval PSA_SUCCESS + * \retval PSA_ERROR_STORAGE_FAILURE + * \retval PSA_ERROR_DOES_NOT_EXIST + */ +static psa_status_t psa_crypto_storage_load( + const mbedtls_svc_key_id_t key, uint8_t *data, size_t data_size ) +{ + psa_status_t status; + psa_storage_uid_t data_identifier = psa_its_identifier_of_slot( key ); + struct psa_storage_info_t data_identifier_info; + size_t data_length = 0; + + status = psa_its_get_info( data_identifier, &data_identifier_info ); + if( status != PSA_SUCCESS ) + return( status ); + + status = psa_its_get( data_identifier, 0, (uint32_t) data_size, data, &data_length ); + if( data_size != data_length ) + return( PSA_ERROR_STORAGE_FAILURE ); + + return( status ); +} + +int psa_is_key_present_in_storage( const mbedtls_svc_key_id_t key ) +{ + psa_status_t ret; + psa_storage_uid_t data_identifier = psa_its_identifier_of_slot( key ); + struct psa_storage_info_t data_identifier_info; + + ret = psa_its_get_info( data_identifier, &data_identifier_info ); + + if( ret == PSA_ERROR_DOES_NOT_EXIST ) + return( 0 ); + return( 1 ); +} + +/** + * \brief Store persistent data for the given key slot number. + * + * This function stores the given data buffer to a persistent storage. + * + * \param key Persistent identifier of the key to be stored. This + * should be an unoccupied storage location. + * \param[in] data Buffer containing the data to be stored. + * \param data_length The number of bytes + * that make up the data. + * + * \retval PSA_SUCCESS + * \retval PSA_ERROR_INSUFFICIENT_STORAGE + * \retval PSA_ERROR_STORAGE_FAILURE + * \retval PSA_ERROR_ALREADY_EXISTS + */ +static psa_status_t psa_crypto_storage_store( const mbedtls_svc_key_id_t key, + const uint8_t *data, + size_t data_length ) +{ + psa_status_t status; + psa_storage_uid_t data_identifier = psa_its_identifier_of_slot( key ); + struct psa_storage_info_t data_identifier_info; + + if( psa_is_key_present_in_storage( key ) == 1 ) + return( PSA_ERROR_ALREADY_EXISTS ); + + status = psa_its_set( data_identifier, (uint32_t) data_length, data, 0 ); + if( status != PSA_SUCCESS ) + { + return( PSA_ERROR_STORAGE_FAILURE ); + } + + status = psa_its_get_info( data_identifier, &data_identifier_info ); + if( status != PSA_SUCCESS ) + { + goto exit; + } + + if( data_identifier_info.size != data_length ) + { + status = PSA_ERROR_STORAGE_FAILURE; + goto exit; + } + +exit: + if( status != PSA_SUCCESS ) + { + /* Remove the file in case we managed to create it but something + * went wrong. It's ok if the file doesn't exist. If the file exists + * but the removal fails, we're already reporting an error so there's + * nothing else we can do. */ + (void) psa_its_remove( data_identifier ); + } + return( status ); +} + +psa_status_t psa_destroy_persistent_key( const mbedtls_svc_key_id_t key ) +{ + psa_status_t ret; + psa_storage_uid_t data_identifier = psa_its_identifier_of_slot( key ); + struct psa_storage_info_t data_identifier_info; + + ret = psa_its_get_info( data_identifier, &data_identifier_info ); + if( ret == PSA_ERROR_DOES_NOT_EXIST ) + return( PSA_SUCCESS ); + + if( psa_its_remove( data_identifier ) != PSA_SUCCESS ) + return( PSA_ERROR_STORAGE_FAILURE ); + + ret = psa_its_get_info( data_identifier, &data_identifier_info ); + if( ret != PSA_ERROR_DOES_NOT_EXIST ) + return( PSA_ERROR_STORAGE_FAILURE ); + + return( PSA_SUCCESS ); +} + +/** + * \brief Get data length for given key slot number. + * + * \param key Persistent identifier whose stored data length + * is to be obtained. + * \param[out] data_length The number of bytes that make up the data. + * + * \retval PSA_SUCCESS + * \retval PSA_ERROR_STORAGE_FAILURE + */ +static psa_status_t psa_crypto_storage_get_data_length( + const mbedtls_svc_key_id_t key, + size_t *data_length ) +{ + psa_status_t status; + psa_storage_uid_t data_identifier = psa_its_identifier_of_slot( key ); + struct psa_storage_info_t data_identifier_info; + + status = psa_its_get_info( data_identifier, &data_identifier_info ); + if( status != PSA_SUCCESS ) + return( status ); + + *data_length = (size_t) data_identifier_info.size; + + return( PSA_SUCCESS ); +} + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_UINT32_LE +#define GET_UINT32_LE( n, b, i ) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] ) \ + | ( (uint32_t) (b)[(i) + 1] << 8 ) \ + | ( (uint32_t) (b)[(i) + 2] << 16 ) \ + | ( (uint32_t) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef PUT_UINT32_LE +#define PUT_UINT32_LE( n, b, i ) \ +{ \ + (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ + (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ + (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ + (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ +} +#endif + +/* + * 16-bit integer manipulation macros (little endian) + */ +#ifndef GET_UINT16_LE +#define GET_UINT16_LE( n, b, i ) \ +{ \ + (n) = ( (uint16_t) (b)[(i) ] ) \ + | ( (uint16_t) (b)[(i) + 1] << 8 ); \ +} +#endif + +#ifndef PUT_UINT16_LE +#define PUT_UINT16_LE( n, b, i ) \ +{ \ + (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ + (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ +} +#endif + +/** + * Persistent key storage magic header. + */ +#define PSA_KEY_STORAGE_MAGIC_HEADER "PSA\0KEY" +#define PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH ( sizeof( PSA_KEY_STORAGE_MAGIC_HEADER ) ) + +typedef struct { + uint8_t magic[PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH]; + uint8_t version[4]; + uint8_t lifetime[sizeof( psa_key_lifetime_t )]; + uint8_t type[2]; + uint8_t bits[2]; + uint8_t policy[sizeof( psa_key_policy_t )]; + uint8_t data_len[4]; + uint8_t key_data[]; +} psa_persistent_key_storage_format; + +void psa_format_key_data_for_storage( const uint8_t *data, + const size_t data_length, + const psa_core_key_attributes_t *attr, + uint8_t *storage_data ) +{ + psa_persistent_key_storage_format *storage_format = + (psa_persistent_key_storage_format *) storage_data; + + memcpy( storage_format->magic, PSA_KEY_STORAGE_MAGIC_HEADER, PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH ); + PUT_UINT32_LE( 0, storage_format->version, 0 ); + PUT_UINT32_LE( attr->lifetime, storage_format->lifetime, 0 ); + PUT_UINT16_LE( (uint16_t) attr->type, storage_format->type, 0 ); + PUT_UINT16_LE( (uint16_t) attr->bits, storage_format->bits, 0 ); + PUT_UINT32_LE( attr->policy.usage, storage_format->policy, 0 ); + PUT_UINT32_LE( attr->policy.alg, storage_format->policy, sizeof( uint32_t ) ); + PUT_UINT32_LE( attr->policy.alg2, storage_format->policy, 2 * sizeof( uint32_t ) ); + PUT_UINT32_LE( data_length, storage_format->data_len, 0 ); + memcpy( storage_format->key_data, data, data_length ); +} + +static psa_status_t check_magic_header( const uint8_t *data ) +{ + if( memcmp( data, PSA_KEY_STORAGE_MAGIC_HEADER, + PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH ) != 0 ) + return( PSA_ERROR_STORAGE_FAILURE ); + return( PSA_SUCCESS ); +} + +psa_status_t psa_parse_key_data_from_storage( const uint8_t *storage_data, + size_t storage_data_length, + uint8_t **key_data, + size_t *key_data_length, + psa_core_key_attributes_t *attr ) +{ + psa_status_t status; + const psa_persistent_key_storage_format *storage_format = + (const psa_persistent_key_storage_format *)storage_data; + uint32_t version; + + if( storage_data_length < sizeof(*storage_format) ) + return( PSA_ERROR_STORAGE_FAILURE ); + + status = check_magic_header( storage_data ); + if( status != PSA_SUCCESS ) + return( status ); + + GET_UINT32_LE( version, storage_format->version, 0 ); + if( version != 0 ) + return( PSA_ERROR_STORAGE_FAILURE ); + + GET_UINT32_LE( *key_data_length, storage_format->data_len, 0 ); + if( *key_data_length > ( storage_data_length - sizeof(*storage_format) ) || + *key_data_length > PSA_CRYPTO_MAX_STORAGE_SIZE ) + return( PSA_ERROR_STORAGE_FAILURE ); + + if( *key_data_length == 0 ) + { + *key_data = NULL; + } + else + { + *key_data = mbedtls_calloc( 1, *key_data_length ); + if( *key_data == NULL ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + memcpy( *key_data, storage_format->key_data, *key_data_length ); + } + + GET_UINT32_LE( attr->lifetime, storage_format->lifetime, 0 ); + GET_UINT16_LE( attr->type, storage_format->type, 0 ); + GET_UINT16_LE( attr->bits, storage_format->bits, 0 ); + GET_UINT32_LE( attr->policy.usage, storage_format->policy, 0 ); + GET_UINT32_LE( attr->policy.alg, storage_format->policy, sizeof( uint32_t ) ); + GET_UINT32_LE( attr->policy.alg2, storage_format->policy, 2 * sizeof( uint32_t ) ); + + return( PSA_SUCCESS ); +} + +psa_status_t psa_save_persistent_key( const psa_core_key_attributes_t *attr, + const uint8_t *data, + const size_t data_length ) +{ + size_t storage_data_length; + uint8_t *storage_data; + psa_status_t status; + + if( data_length > PSA_CRYPTO_MAX_STORAGE_SIZE ) + return PSA_ERROR_INSUFFICIENT_STORAGE; + storage_data_length = data_length + sizeof( psa_persistent_key_storage_format ); + + storage_data = mbedtls_calloc( 1, storage_data_length ); + if( storage_data == NULL ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + + psa_format_key_data_for_storage( data, data_length, attr, storage_data ); + + status = psa_crypto_storage_store( attr->id, + storage_data, storage_data_length ); + + mbedtls_free( storage_data ); + + return( status ); +} + +void psa_free_persistent_key_data( uint8_t *key_data, size_t key_data_length ) +{ + if( key_data != NULL ) + { + mbedtls_platform_zeroize( key_data, key_data_length ); + } + mbedtls_free( key_data ); +} + +psa_status_t psa_load_persistent_key( psa_core_key_attributes_t *attr, + uint8_t **data, + size_t *data_length ) +{ + psa_status_t status = PSA_SUCCESS; + uint8_t *loaded_data; + size_t storage_data_length = 0; + mbedtls_svc_key_id_t key = attr->id; + + status = psa_crypto_storage_get_data_length( key, &storage_data_length ); + if( status != PSA_SUCCESS ) + return( status ); + + loaded_data = mbedtls_calloc( 1, storage_data_length ); + + if( loaded_data == NULL ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + + status = psa_crypto_storage_load( key, loaded_data, storage_data_length ); + if( status != PSA_SUCCESS ) + goto exit; + + status = psa_parse_key_data_from_storage( loaded_data, storage_data_length, + data, data_length, attr ); + +exit: + mbedtls_free( loaded_data ); + return( status ); +} + + + +/****************************************************************/ +/* Transactions */ +/****************************************************************/ + +#if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) + +psa_crypto_transaction_t psa_crypto_transaction; + +psa_status_t psa_crypto_save_transaction( void ) +{ + struct psa_storage_info_t p_info; + psa_status_t status; + status = psa_its_get_info( PSA_CRYPTO_ITS_TRANSACTION_UID, &p_info ); + if( status == PSA_SUCCESS ) + { + /* This shouldn't happen: we're trying to start a transaction while + * there is still a transaction that hasn't been replayed. */ + return( PSA_ERROR_CORRUPTION_DETECTED ); + } + else if( status != PSA_ERROR_DOES_NOT_EXIST ) + return( status ); + return( psa_its_set( PSA_CRYPTO_ITS_TRANSACTION_UID, + sizeof( psa_crypto_transaction ), + &psa_crypto_transaction, + 0 ) ); +} + +psa_status_t psa_crypto_load_transaction( void ) +{ + psa_status_t status; + size_t length; + status = psa_its_get( PSA_CRYPTO_ITS_TRANSACTION_UID, 0, + sizeof( psa_crypto_transaction ), + &psa_crypto_transaction, &length ); + if( status != PSA_SUCCESS ) + return( status ); + if( length != sizeof( psa_crypto_transaction ) ) + return( PSA_ERROR_STORAGE_FAILURE ); + return( PSA_SUCCESS ); +} + +psa_status_t psa_crypto_stop_transaction( void ) +{ + psa_status_t status = psa_its_remove( PSA_CRYPTO_ITS_TRANSACTION_UID ); + /* Whether or not updating the storage succeeded, the transaction is + * finished now. It's too late to go back, so zero out the in-memory + * data. */ + memset( &psa_crypto_transaction, 0, sizeof( psa_crypto_transaction ) ); + return( status ); +} + +#endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */ + + + +/****************************************************************/ +/* Random generator state */ +/****************************************************************/ + +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) +psa_status_t mbedtls_psa_storage_inject_entropy( const unsigned char *seed, + size_t seed_size ) +{ + psa_status_t status; + struct psa_storage_info_t p_info; + + status = psa_its_get_info( PSA_CRYPTO_ITS_RANDOM_SEED_UID, &p_info ); + + if( PSA_ERROR_DOES_NOT_EXIST == status ) /* No seed exists */ + { + status = psa_its_set( PSA_CRYPTO_ITS_RANDOM_SEED_UID, seed_size, seed, 0 ); + } + else if( PSA_SUCCESS == status ) + { + /* You should not be here. Seed needs to be injected only once */ + status = PSA_ERROR_NOT_PERMITTED; + } + return( status ); +} +#endif /* MBEDTLS_PSA_INJECT_ENTROPY */ + + + +/****************************************************************/ +/* The end */ +/****************************************************************/ + +#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/psa_crypto_storage.h b/Android/Level4/app/src/main/c/mbedtls/library/psa_crypto_storage.h new file mode 100644 index 0000000..3def1b5 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/psa_crypto_storage.h @@ -0,0 +1,389 @@ +/** + * \file psa_crypto_storage.h + * + * \brief PSA cryptography module: Mbed TLS key storage + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 PSA_CRYPTO_STORAGE_H +#define PSA_CRYPTO_STORAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "psa/crypto.h" +#include "psa/crypto_se_driver.h" + +#include +#include + +/* Limit the maximum key size in storage. This should have no effect + * since the key size is limited in memory. */ +#define PSA_CRYPTO_MAX_STORAGE_SIZE ( PSA_BITS_TO_BYTES( PSA_MAX_KEY_BITS ) ) +/* Sanity check: a file size must fit in 32 bits. Allow a generous + * 64kB of metadata. */ +#if PSA_CRYPTO_MAX_STORAGE_SIZE > 0xffff0000 +#error PSA_CRYPTO_MAX_STORAGE_SIZE > 0xffff0000 +#endif + +/** The maximum permitted persistent slot number. + * + * In Mbed Crypto 0.1.0b: + * - Using the file backend, all key ids are ok except 0. + * - Using the ITS backend, all key ids are ok except 0xFFFFFF52 + * (#PSA_CRYPTO_ITS_RANDOM_SEED_UID) for which the file contains the + * device's random seed (if this feature is enabled). + * - Only key ids from 1 to #PSA_KEY_SLOT_COUNT are actually used. + * + * Since we need to preserve the random seed, avoid using that key slot. + * Reserve a whole range of key slots just in case something else comes up. + * + * This limitation will probably become moot when we implement client + * separation for key storage. + */ +#define PSA_MAX_PERSISTENT_KEY_IDENTIFIER PSA_KEY_ID_VENDOR_MAX + +/** + * \brief Checks if persistent data is stored for the given key slot number + * + * This function checks if any key data or metadata exists for the key slot in + * the persistent storage. + * + * \param key Persistent identifier to check. + * + * \retval 0 + * No persistent data present for slot number + * \retval 1 + * Persistent data present for slot number + */ +int psa_is_key_present_in_storage( const mbedtls_svc_key_id_t key ); + +/** + * \brief Format key data and metadata and save to a location for given key + * slot. + * + * This function formats the key data and metadata and saves it to a + * persistent storage backend. The storage location corresponding to the + * key slot must be empty, otherwise this function will fail. This function + * should be called after loading the key into an internal slot to ensure the + * persistent key is not saved into a storage location corresponding to an + * already occupied non-persistent key, as well as ensuring the key data is + * validated. + * + * + * \param[in] attr The attributes of the key to save. + * The key identifier field in the attributes + * determines the key's location. + * \param[in] data Buffer containing the key data. + * \param data_length The number of bytes that make up the key data. + * + * \retval PSA_SUCCESS + * \retval PSA_ERROR_INSUFFICIENT_MEMORY + * \retval PSA_ERROR_INSUFFICIENT_STORAGE + * \retval PSA_ERROR_STORAGE_FAILURE + * \retval PSA_ERROR_ALREADY_EXISTS + */ +psa_status_t psa_save_persistent_key( const psa_core_key_attributes_t *attr, + const uint8_t *data, + const size_t data_length ); + +/** + * \brief Parses key data and metadata and load persistent key for given + * key slot number. + * + * This function reads from a storage backend, parses the key data and + * metadata and writes them to the appropriate output parameters. + * + * Note: This function allocates a buffer and returns a pointer to it through + * the data parameter. psa_free_persistent_key_data() must be called after + * this function to zeroize and free this buffer, regardless of whether this + * function succeeds or fails. + * + * \param[in,out] attr On input, the key identifier field identifies + * the key to load. Other fields are ignored. + * On success, the attribute structure contains + * the key metadata that was loaded from storage. + * \param[out] data Pointer to an allocated key data buffer on return. + * \param[out] data_length The number of bytes that make up the key data. + * + * \retval PSA_SUCCESS + * \retval PSA_ERROR_INSUFFICIENT_MEMORY + * \retval PSA_ERROR_STORAGE_FAILURE + * \retval PSA_ERROR_DOES_NOT_EXIST + */ +psa_status_t psa_load_persistent_key( psa_core_key_attributes_t *attr, + uint8_t **data, + size_t *data_length ); + +/** + * \brief Remove persistent data for the given key slot number. + * + * \param key Persistent identifier of the key to remove + * from persistent storage. + * + * \retval PSA_SUCCESS + * The key was successfully removed, + * or the key did not exist. + * \retval PSA_ERROR_STORAGE_FAILURE + */ +psa_status_t psa_destroy_persistent_key( const mbedtls_svc_key_id_t key ); + +/** + * \brief Free the temporary buffer allocated by psa_load_persistent_key(). + * + * This function must be called at some point after psa_load_persistent_key() + * to zeroize and free the memory allocated to the buffer in that function. + * + * \param key_data Buffer for the key data. + * \param key_data_length Size of the key data buffer. + * + */ +void psa_free_persistent_key_data( uint8_t *key_data, size_t key_data_length ); + +/** + * \brief Formats key data and metadata for persistent storage + * + * \param[in] data Buffer containing the key data. + * \param data_length Length of the key data buffer. + * \param[in] attr The core attributes of the key. + * \param[out] storage_data Output buffer for the formatted data. + * + */ +void psa_format_key_data_for_storage( const uint8_t *data, + const size_t data_length, + const psa_core_key_attributes_t *attr, + uint8_t *storage_data ); + +/** + * \brief Parses persistent storage data into key data and metadata + * + * \param[in] storage_data Buffer for the storage data. + * \param storage_data_length Length of the storage data buffer + * \param[out] key_data On output, pointer to a newly allocated buffer + * containing the key data. This must be freed + * using psa_free_persistent_key_data() + * \param[out] key_data_length Length of the key data buffer + * \param[out] attr On success, the attribute structure is filled + * with the loaded key metadata. + * + * \retval PSA_SUCCESS + * \retval PSA_ERROR_INSUFFICIENT_STORAGE + * \retval PSA_ERROR_INSUFFICIENT_MEMORY + * \retval PSA_ERROR_STORAGE_FAILURE + */ +psa_status_t psa_parse_key_data_from_storage( const uint8_t *storage_data, + size_t storage_data_length, + uint8_t **key_data, + size_t *key_data_length, + psa_core_key_attributes_t *attr ); + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) +/** This symbol is defined if transaction support is required. */ +#define PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS +#endif + +#if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) + +/** The type of transaction that is in progress. + */ +/* This is an integer type rather than an enum for two reasons: to support + * unknown values when loading a transaction file, and to ensure that the + * type has a known size. + */ +typedef uint16_t psa_crypto_transaction_type_t; + +/** No transaction is in progress. + * + * This has the value 0, so zero-initialization sets a transaction's type to + * this value. + */ +#define PSA_CRYPTO_TRANSACTION_NONE ( (psa_crypto_transaction_type_t) 0x0000 ) + +/** A key creation transaction. + * + * This is only used for keys in an external cryptoprocessor (secure element). + * Keys in RAM or in internal storage are created atomically in storage + * (simple file creation), so they do not need a transaction mechanism. + */ +#define PSA_CRYPTO_TRANSACTION_CREATE_KEY ( (psa_crypto_transaction_type_t) 0x0001 ) + +/** A key destruction transaction. + * + * This is only used for keys in an external cryptoprocessor (secure element). + * Keys in RAM or in internal storage are destroyed atomically in storage + * (simple file deletion), so they do not need a transaction mechanism. + */ +#define PSA_CRYPTO_TRANSACTION_DESTROY_KEY ( (psa_crypto_transaction_type_t) 0x0002 ) + +/** Transaction data. + * + * This type is designed to be serialized by writing the memory representation + * and reading it back on the same device. + * + * \note The transaction mechanism is designed for a single active transaction + * at a time. The transaction object is #psa_crypto_transaction. + * + * \note If an API call starts a transaction, it must complete this transaction + * before returning to the application. + * + * The lifetime of a transaction is the following (note that only one + * transaction may be active at a time): + * + * -# Call psa_crypto_prepare_transaction() to initialize the transaction + * object in memory and declare the type of transaction that is starting. + * -# Fill in the type-specific fields of #psa_crypto_transaction. + * -# Call psa_crypto_save_transaction() to start the transaction. This + * saves the transaction data to internal storage. + * -# Perform the work of the transaction by modifying files, contacting + * external entities, or whatever needs doing. Note that the transaction + * may be interrupted by a power failure, so you need to have a way + * recover from interruptions either by undoing what has been done + * so far or by resuming where you left off. + * -# If there are intermediate stages in the transaction, update + * the fields of #psa_crypto_transaction and call + * psa_crypto_save_transaction() again when each stage is reached. + * -# When the transaction is over, call psa_crypto_stop_transaction() to + * remove the transaction data in storage and in memory. + * + * If the system crashes while a transaction is in progress, psa_crypto_init() + * calls psa_crypto_load_transaction() and takes care of completing or + * rewinding the transaction. This is done in psa_crypto_recover_transaction() + * in psa_crypto.c. If you add a new type of transaction, be + * sure to add code for it in psa_crypto_recover_transaction(). + */ +typedef union +{ + /* Each element of this union must have the following properties + * to facilitate serialization and deserialization: + * + * - The element is a struct. + * - The first field of the struct is `psa_crypto_transaction_type_t type`. + * - Elements of the struct are arranged such a way that there is + * no padding. + */ + struct psa_crypto_transaction_unknown_s + { + psa_crypto_transaction_type_t type; + uint16_t unused1; + uint32_t unused2; + uint64_t unused3; + uint64_t unused4; + } unknown; + /* ::type is #PSA_CRYPTO_TRANSACTION_CREATE_KEY or + * #PSA_CRYPTO_TRANSACTION_DESTROY_KEY. */ + struct psa_crypto_transaction_key_s + { + psa_crypto_transaction_type_t type; + uint16_t unused1; + psa_key_lifetime_t lifetime; + psa_key_slot_number_t slot; + mbedtls_svc_key_id_t id; + } key; +} psa_crypto_transaction_t; + +/** The single active transaction. + */ +extern psa_crypto_transaction_t psa_crypto_transaction; + +/** Prepare for a transaction. + * + * There must not be an ongoing transaction. + * + * \param type The type of transaction to start. + */ +static inline void psa_crypto_prepare_transaction( + psa_crypto_transaction_type_t type ) +{ + psa_crypto_transaction.unknown.type = type; +} + +/** Save the transaction data to storage. + * + * You may call this function multiple times during a transaction to + * atomically update the transaction state. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE + * \retval #PSA_ERROR_STORAGE_FAILURE + */ +psa_status_t psa_crypto_save_transaction( void ); + +/** Load the transaction data from storage, if any. + * + * This function is meant to be called from psa_crypto_init() to recover + * in case a transaction was interrupted by a system crash. + * + * \retval #PSA_SUCCESS + * The data about the ongoing transaction has been loaded to + * #psa_crypto_transaction. + * \retval #PSA_ERROR_DOES_NOT_EXIST + * There is no ongoing transaction. + * \retval #PSA_ERROR_STORAGE_FAILURE + */ +psa_status_t psa_crypto_load_transaction( void ); + +/** Indicate that the current transaction is finished. + * + * Call this function at the very end of transaction processing. + * This function does not "commit" or "abort" the transaction: the storage + * subsystem has no concept of "commit" and "abort", just saving and + * removing the transaction information in storage. + * + * This function erases the transaction data in storage (if any) and + * resets the transaction data in memory. + * + * \retval #PSA_SUCCESS + * There was transaction data in storage. + * \retval #PSA_ERROR_DOES_NOT_EXIST + * There was no transaction data in storage. + * \retval #PSA_ERROR_STORAGE_FAILURE + * It was impossible to determine whether there was transaction data + * in storage, or the transaction data could not be erased. + */ +psa_status_t psa_crypto_stop_transaction( void ); + +/** The ITS file identifier for the transaction data. + * + * 0xffffffNN = special file; 0x74 = 't' for transaction. + */ +#define PSA_CRYPTO_ITS_TRANSACTION_UID ( (psa_key_id_t) 0xffffff74 ) + +#endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */ + +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) +/** Backend side of mbedtls_psa_inject_entropy(). + * + * This function stores the supplied data into the entropy seed file. + * + * \retval #PSA_SUCCESS + * Success + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE + * \retval #PSA_ERROR_NOT_PERMITTED + * The entropy seed file already exists. + */ +psa_status_t mbedtls_psa_storage_inject_entropy( const unsigned char *seed, + size_t seed_size ); +#endif /* MBEDTLS_PSA_INJECT_ENTROPY */ + +#ifdef __cplusplus +} +#endif + +#endif /* PSA_CRYPTO_STORAGE_H */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/psa_its_file.c b/Android/Level4/app/src/main/c/mbedtls/library/psa_its_file.c new file mode 100644 index 0000000..2fbff20 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/psa_its_file.c @@ -0,0 +1,259 @@ +/* + * PSA ITS simulator over stdio files. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ + +#if defined(MBEDTLS_CONFIG_FILE) +#include MBEDTLS_CONFIG_FILE +#else +#include "mbedtls/config.h" +#endif + +#if defined(MBEDTLS_PSA_ITS_FILE_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#define mbedtls_snprintf snprintf +#endif + +#if defined(_WIN32) +#include +#endif + +#include "psa_crypto_its.h" + +#include +#include +#include +#include + +#if !defined(PSA_ITS_STORAGE_PREFIX) +#define PSA_ITS_STORAGE_PREFIX "" +#endif + +#define PSA_ITS_STORAGE_FILENAME_PATTERN "%08lx%08lx" +#define PSA_ITS_STORAGE_SUFFIX ".psa_its" +#define PSA_ITS_STORAGE_FILENAME_LENGTH \ + ( sizeof( PSA_ITS_STORAGE_PREFIX ) - 1 + /*prefix without terminating 0*/ \ + 16 + /*UID (64-bit number in hex)*/ \ + sizeof( PSA_ITS_STORAGE_SUFFIX ) - 1 + /*suffix without terminating 0*/ \ + 1 /*terminating null byte*/ ) +#define PSA_ITS_STORAGE_TEMP \ + PSA_ITS_STORAGE_PREFIX "tempfile" PSA_ITS_STORAGE_SUFFIX + +/* The maximum value of psa_storage_info_t.size */ +#define PSA_ITS_MAX_SIZE 0xffffffff + +#define PSA_ITS_MAGIC_STRING "PSA\0ITS\0" +#define PSA_ITS_MAGIC_LENGTH 8 + +/* As rename fails on Windows if the new filepath already exists, + * use MoveFileExA with the MOVEFILE_REPLACE_EXISTING flag instead. + * Returns 0 on success, nonzero on failure. */ +#if defined(_WIN32) +#define rename_replace_existing( oldpath, newpath ) \ + ( ! MoveFileExA( oldpath, newpath, MOVEFILE_REPLACE_EXISTING ) ) +#else +#define rename_replace_existing( oldpath, newpath ) rename( oldpath, newpath ) +#endif + +typedef struct +{ + uint8_t magic[PSA_ITS_MAGIC_LENGTH]; + uint8_t size[sizeof( uint32_t )]; + uint8_t flags[sizeof( psa_storage_create_flags_t )]; +} psa_its_file_header_t; + +static void psa_its_fill_filename( psa_storage_uid_t uid, char *filename ) +{ + /* Break up the UID into two 32-bit pieces so as not to rely on + * long long support in snprintf. */ + mbedtls_snprintf( filename, PSA_ITS_STORAGE_FILENAME_LENGTH, + "%s" PSA_ITS_STORAGE_FILENAME_PATTERN "%s", + PSA_ITS_STORAGE_PREFIX, + (unsigned long) ( uid >> 32 ), + (unsigned long) ( uid & 0xffffffff ), + PSA_ITS_STORAGE_SUFFIX ); +} + +static psa_status_t psa_its_read_file( psa_storage_uid_t uid, + struct psa_storage_info_t *p_info, + FILE **p_stream ) +{ + char filename[PSA_ITS_STORAGE_FILENAME_LENGTH]; + psa_its_file_header_t header; + size_t n; + + *p_stream = NULL; + psa_its_fill_filename( uid, filename ); + *p_stream = fopen( filename, "rb" ); + if( *p_stream == NULL ) + return( PSA_ERROR_DOES_NOT_EXIST ); + + n = fread( &header, 1, sizeof( header ), *p_stream ); + if( n != sizeof( header ) ) + return( PSA_ERROR_DATA_CORRUPT ); + if( memcmp( header.magic, PSA_ITS_MAGIC_STRING, + PSA_ITS_MAGIC_LENGTH ) != 0 ) + return( PSA_ERROR_DATA_CORRUPT ); + + p_info->size = ( header.size[0] | + header.size[1] << 8 | + header.size[2] << 16 | + header.size[3] << 24 ); + p_info->flags = ( header.flags[0] | + header.flags[1] << 8 | + header.flags[2] << 16 | + header.flags[3] << 24 ); + return( PSA_SUCCESS ); +} + +psa_status_t psa_its_get_info( psa_storage_uid_t uid, + struct psa_storage_info_t *p_info ) +{ + psa_status_t status; + FILE *stream = NULL; + status = psa_its_read_file( uid, p_info, &stream ); + if( stream != NULL ) + fclose( stream ); + return( status ); +} + +psa_status_t psa_its_get( psa_storage_uid_t uid, + uint32_t data_offset, + uint32_t data_length, + void *p_data, + size_t *p_data_length ) +{ + psa_status_t status; + FILE *stream = NULL; + size_t n; + struct psa_storage_info_t info; + + status = psa_its_read_file( uid, &info, &stream ); + if( status != PSA_SUCCESS ) + goto exit; + status = PSA_ERROR_INVALID_ARGUMENT; + if( data_offset + data_length < data_offset ) + goto exit; +#if SIZE_MAX < 0xffffffff + if( data_offset + data_length > SIZE_MAX ) + goto exit; +#endif + if( data_offset + data_length > info.size ) + goto exit; + + status = PSA_ERROR_STORAGE_FAILURE; +#if LONG_MAX < 0xffffffff + while( data_offset > LONG_MAX ) + { + if( fseek( stream, LONG_MAX, SEEK_CUR ) != 0 ) + goto exit; + data_offset -= LONG_MAX; + } +#endif + if( fseek( stream, data_offset, SEEK_CUR ) != 0 ) + goto exit; + n = fread( p_data, 1, data_length, stream ); + if( n != data_length ) + goto exit; + status = PSA_SUCCESS; + if( p_data_length != NULL ) + *p_data_length = n; + +exit: + if( stream != NULL ) + fclose( stream ); + return( status ); +} + +psa_status_t psa_its_set( psa_storage_uid_t uid, + uint32_t data_length, + const void *p_data, + psa_storage_create_flags_t create_flags ) +{ + psa_status_t status = PSA_ERROR_STORAGE_FAILURE; + char filename[PSA_ITS_STORAGE_FILENAME_LENGTH]; + FILE *stream = NULL; + psa_its_file_header_t header; + size_t n; + + memcpy( header.magic, PSA_ITS_MAGIC_STRING, PSA_ITS_MAGIC_LENGTH ); + header.size[0] = data_length & 0xff; + header.size[1] = ( data_length >> 8 ) & 0xff; + header.size[2] = ( data_length >> 16 ) & 0xff; + header.size[3] = ( data_length >> 24 ) & 0xff; + header.flags[0] = create_flags & 0xff; + header.flags[1] = ( create_flags >> 8 ) & 0xff; + header.flags[2] = ( create_flags >> 16 ) & 0xff; + header.flags[3] = ( create_flags >> 24 ) & 0xff; + + psa_its_fill_filename( uid, filename ); + stream = fopen( PSA_ITS_STORAGE_TEMP, "wb" ); + if( stream == NULL ) + goto exit; + + status = PSA_ERROR_INSUFFICIENT_STORAGE; + n = fwrite( &header, 1, sizeof( header ), stream ); + if( n != sizeof( header ) ) + goto exit; + if( data_length != 0 ) + { + n = fwrite( p_data, 1, data_length, stream ); + if( n != data_length ) + goto exit; + } + status = PSA_SUCCESS; + +exit: + if( stream != NULL ) + { + int ret = fclose( stream ); + if( status == PSA_SUCCESS && ret != 0 ) + status = PSA_ERROR_INSUFFICIENT_STORAGE; + } + if( status == PSA_SUCCESS ) + { + if( rename_replace_existing( PSA_ITS_STORAGE_TEMP, filename ) != 0 ) + status = PSA_ERROR_STORAGE_FAILURE; + } + /* The temporary file may still exist, but only in failure cases where + * we're already reporting an error. So there's nothing we can do on + * failure. If the function succeeded, and in some error cases, the + * temporary file doesn't exist and so remove() is expected to fail. + * Thus we just ignore the return status of remove(). */ + (void) remove( PSA_ITS_STORAGE_TEMP ); + return( status ); +} + +psa_status_t psa_its_remove( psa_storage_uid_t uid ) +{ + char filename[PSA_ITS_STORAGE_FILENAME_LENGTH]; + FILE *stream; + psa_its_fill_filename( uid, filename ); + stream = fopen( filename, "rb" ); + if( stream == NULL ) + return( PSA_ERROR_DOES_NOT_EXIST ); + fclose( stream ); + if( remove( filename ) != 0 ) + return( PSA_ERROR_STORAGE_FAILURE ); + return( PSA_SUCCESS ); +} + +#endif /* MBEDTLS_PSA_ITS_FILE_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/ripemd160.c b/Android/Level4/app/src/main/c/mbedtls/library/ripemd160.c new file mode 100644 index 0000000..603b6ba --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/ripemd160.c @@ -0,0 +1,553 @@ +/* + * RIPE MD-160 implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ + +/* + * The RIPEMD-160 algorithm was designed by RIPE in 1996 + * http://homes.esat.kuleuven.be/~bosselae/mbedtls_ripemd160.html + * http://ehash.iaik.tugraz.at/wiki/RIPEMD-160 + */ + +#include "common.h" + +#if defined(MBEDTLS_RIPEMD160_C) + +#include "mbedtls/ripemd160.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_RIPEMD160_ALT) + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_UINT32_LE +#define GET_UINT32_LE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] ) \ + | ( (uint32_t) (b)[(i) + 1] << 8 ) \ + | ( (uint32_t) (b)[(i) + 2] << 16 ) \ + | ( (uint32_t) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef PUT_UINT32_LE +#define PUT_UINT32_LE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ + (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ + (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ + (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ +} +#endif + +void mbedtls_ripemd160_init( mbedtls_ripemd160_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_ripemd160_context ) ); +} + +void mbedtls_ripemd160_free( mbedtls_ripemd160_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ripemd160_context ) ); +} + +void mbedtls_ripemd160_clone( mbedtls_ripemd160_context *dst, + const mbedtls_ripemd160_context *src ) +{ + *dst = *src; +} + +/* + * RIPEMD-160 context setup + */ +int mbedtls_ripemd160_starts_ret( mbedtls_ripemd160_context *ctx ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + ctx->state[4] = 0xC3D2E1F0; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_ripemd160_starts( mbedtls_ripemd160_context *ctx ) +{ + mbedtls_ripemd160_starts_ret( ctx ); +} +#endif + +#if !defined(MBEDTLS_RIPEMD160_PROCESS_ALT) +/* + * Process one block + */ +int mbedtls_internal_ripemd160_process( mbedtls_ripemd160_context *ctx, + const unsigned char data[64] ) +{ + uint32_t A, B, C, D, E, Ap, Bp, Cp, Dp, Ep, X[16]; + + GET_UINT32_LE( X[ 0], data, 0 ); + GET_UINT32_LE( X[ 1], data, 4 ); + GET_UINT32_LE( X[ 2], data, 8 ); + GET_UINT32_LE( X[ 3], data, 12 ); + GET_UINT32_LE( X[ 4], data, 16 ); + GET_UINT32_LE( X[ 5], data, 20 ); + GET_UINT32_LE( X[ 6], data, 24 ); + GET_UINT32_LE( X[ 7], data, 28 ); + GET_UINT32_LE( X[ 8], data, 32 ); + GET_UINT32_LE( X[ 9], data, 36 ); + GET_UINT32_LE( X[10], data, 40 ); + GET_UINT32_LE( X[11], data, 44 ); + GET_UINT32_LE( X[12], data, 48 ); + GET_UINT32_LE( X[13], data, 52 ); + GET_UINT32_LE( X[14], data, 56 ); + GET_UINT32_LE( X[15], data, 60 ); + + A = Ap = ctx->state[0]; + B = Bp = ctx->state[1]; + C = Cp = ctx->state[2]; + D = Dp = ctx->state[3]; + E = Ep = ctx->state[4]; + +#define F1( x, y, z ) ( (x) ^ (y) ^ (z) ) +#define F2( x, y, z ) ( ( (x) & (y) ) | ( ~(x) & (z) ) ) +#define F3( x, y, z ) ( ( (x) | ~(y) ) ^ (z) ) +#define F4( x, y, z ) ( ( (x) & (z) ) | ( (y) & ~(z) ) ) +#define F5( x, y, z ) ( (x) ^ ( (y) | ~(z) ) ) + +#define S( x, n ) ( ( (x) << (n) ) | ( (x) >> (32 - (n)) ) ) + +#define P( a, b, c, d, e, r, s, f, k ) \ + do \ + { \ + (a) += f( (b), (c), (d) ) + X[r] + (k); \ + (a) = S( (a), (s) ) + (e); \ + (c) = S( (c), 10 ); \ + } while( 0 ) + +#define P2( a, b, c, d, e, r, s, rp, sp ) \ + do \ + { \ + P( (a), (b), (c), (d), (e), (r), (s), F, K ); \ + P( a ## p, b ## p, c ## p, d ## p, e ## p, \ + (rp), (sp), Fp, Kp ); \ + } while( 0 ) + +#define F F1 +#define K 0x00000000 +#define Fp F5 +#define Kp 0x50A28BE6 + P2( A, B, C, D, E, 0, 11, 5, 8 ); + P2( E, A, B, C, D, 1, 14, 14, 9 ); + P2( D, E, A, B, C, 2, 15, 7, 9 ); + P2( C, D, E, A, B, 3, 12, 0, 11 ); + P2( B, C, D, E, A, 4, 5, 9, 13 ); + P2( A, B, C, D, E, 5, 8, 2, 15 ); + P2( E, A, B, C, D, 6, 7, 11, 15 ); + P2( D, E, A, B, C, 7, 9, 4, 5 ); + P2( C, D, E, A, B, 8, 11, 13, 7 ); + P2( B, C, D, E, A, 9, 13, 6, 7 ); + P2( A, B, C, D, E, 10, 14, 15, 8 ); + P2( E, A, B, C, D, 11, 15, 8, 11 ); + P2( D, E, A, B, C, 12, 6, 1, 14 ); + P2( C, D, E, A, B, 13, 7, 10, 14 ); + P2( B, C, D, E, A, 14, 9, 3, 12 ); + P2( A, B, C, D, E, 15, 8, 12, 6 ); +#undef F +#undef K +#undef Fp +#undef Kp + +#define F F2 +#define K 0x5A827999 +#define Fp F4 +#define Kp 0x5C4DD124 + P2( E, A, B, C, D, 7, 7, 6, 9 ); + P2( D, E, A, B, C, 4, 6, 11, 13 ); + P2( C, D, E, A, B, 13, 8, 3, 15 ); + P2( B, C, D, E, A, 1, 13, 7, 7 ); + P2( A, B, C, D, E, 10, 11, 0, 12 ); + P2( E, A, B, C, D, 6, 9, 13, 8 ); + P2( D, E, A, B, C, 15, 7, 5, 9 ); + P2( C, D, E, A, B, 3, 15, 10, 11 ); + P2( B, C, D, E, A, 12, 7, 14, 7 ); + P2( A, B, C, D, E, 0, 12, 15, 7 ); + P2( E, A, B, C, D, 9, 15, 8, 12 ); + P2( D, E, A, B, C, 5, 9, 12, 7 ); + P2( C, D, E, A, B, 2, 11, 4, 6 ); + P2( B, C, D, E, A, 14, 7, 9, 15 ); + P2( A, B, C, D, E, 11, 13, 1, 13 ); + P2( E, A, B, C, D, 8, 12, 2, 11 ); +#undef F +#undef K +#undef Fp +#undef Kp + +#define F F3 +#define K 0x6ED9EBA1 +#define Fp F3 +#define Kp 0x6D703EF3 + P2( D, E, A, B, C, 3, 11, 15, 9 ); + P2( C, D, E, A, B, 10, 13, 5, 7 ); + P2( B, C, D, E, A, 14, 6, 1, 15 ); + P2( A, B, C, D, E, 4, 7, 3, 11 ); + P2( E, A, B, C, D, 9, 14, 7, 8 ); + P2( D, E, A, B, C, 15, 9, 14, 6 ); + P2( C, D, E, A, B, 8, 13, 6, 6 ); + P2( B, C, D, E, A, 1, 15, 9, 14 ); + P2( A, B, C, D, E, 2, 14, 11, 12 ); + P2( E, A, B, C, D, 7, 8, 8, 13 ); + P2( D, E, A, B, C, 0, 13, 12, 5 ); + P2( C, D, E, A, B, 6, 6, 2, 14 ); + P2( B, C, D, E, A, 13, 5, 10, 13 ); + P2( A, B, C, D, E, 11, 12, 0, 13 ); + P2( E, A, B, C, D, 5, 7, 4, 7 ); + P2( D, E, A, B, C, 12, 5, 13, 5 ); +#undef F +#undef K +#undef Fp +#undef Kp + +#define F F4 +#define K 0x8F1BBCDC +#define Fp F2 +#define Kp 0x7A6D76E9 + P2( C, D, E, A, B, 1, 11, 8, 15 ); + P2( B, C, D, E, A, 9, 12, 6, 5 ); + P2( A, B, C, D, E, 11, 14, 4, 8 ); + P2( E, A, B, C, D, 10, 15, 1, 11 ); + P2( D, E, A, B, C, 0, 14, 3, 14 ); + P2( C, D, E, A, B, 8, 15, 11, 14 ); + P2( B, C, D, E, A, 12, 9, 15, 6 ); + P2( A, B, C, D, E, 4, 8, 0, 14 ); + P2( E, A, B, C, D, 13, 9, 5, 6 ); + P2( D, E, A, B, C, 3, 14, 12, 9 ); + P2( C, D, E, A, B, 7, 5, 2, 12 ); + P2( B, C, D, E, A, 15, 6, 13, 9 ); + P2( A, B, C, D, E, 14, 8, 9, 12 ); + P2( E, A, B, C, D, 5, 6, 7, 5 ); + P2( D, E, A, B, C, 6, 5, 10, 15 ); + P2( C, D, E, A, B, 2, 12, 14, 8 ); +#undef F +#undef K +#undef Fp +#undef Kp + +#define F F5 +#define K 0xA953FD4E +#define Fp F1 +#define Kp 0x00000000 + P2( B, C, D, E, A, 4, 9, 12, 8 ); + P2( A, B, C, D, E, 0, 15, 15, 5 ); + P2( E, A, B, C, D, 5, 5, 10, 12 ); + P2( D, E, A, B, C, 9, 11, 4, 9 ); + P2( C, D, E, A, B, 7, 6, 1, 12 ); + P2( B, C, D, E, A, 12, 8, 5, 5 ); + P2( A, B, C, D, E, 2, 13, 8, 14 ); + P2( E, A, B, C, D, 10, 12, 7, 6 ); + P2( D, E, A, B, C, 14, 5, 6, 8 ); + P2( C, D, E, A, B, 1, 12, 2, 13 ); + P2( B, C, D, E, A, 3, 13, 13, 6 ); + P2( A, B, C, D, E, 8, 14, 14, 5 ); + P2( E, A, B, C, D, 11, 11, 0, 15 ); + P2( D, E, A, B, C, 6, 8, 3, 13 ); + P2( C, D, E, A, B, 15, 5, 9, 11 ); + P2( B, C, D, E, A, 13, 6, 11, 11 ); +#undef F +#undef K +#undef Fp +#undef Kp + + C = ctx->state[1] + C + Dp; + ctx->state[1] = ctx->state[2] + D + Ep; + ctx->state[2] = ctx->state[3] + E + Ap; + ctx->state[3] = ctx->state[4] + A + Bp; + ctx->state[4] = ctx->state[0] + B + Cp; + ctx->state[0] = C; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_ripemd160_process( mbedtls_ripemd160_context *ctx, + const unsigned char data[64] ) +{ + mbedtls_internal_ripemd160_process( ctx, data ); +} +#endif +#endif /* !MBEDTLS_RIPEMD160_PROCESS_ALT */ + +/* + * RIPEMD-160 process buffer + */ +int mbedtls_ripemd160_update_ret( mbedtls_ripemd160_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t fill; + uint32_t left; + + if( ilen == 0 ) + return( 0 ); + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (uint32_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), input, fill ); + + if( ( ret = mbedtls_internal_ripemd160_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + if( ( ret = mbedtls_internal_ripemd160_process( ctx, input ) ) != 0 ) + return( ret ); + + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + { + memcpy( (void *) (ctx->buffer + left), input, ilen ); + } + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_ripemd160_update( mbedtls_ripemd160_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + mbedtls_ripemd160_update_ret( ctx, input, ilen ); +} +#endif + +static const unsigned char ripemd160_padding[64] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * RIPEMD-160 final digest + */ +int mbedtls_ripemd160_finish_ret( mbedtls_ripemd160_context *ctx, + unsigned char output[20] ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + uint32_t last, padn; + uint32_t high, low; + unsigned char msglen[8]; + + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT32_LE( low, msglen, 0 ); + PUT_UINT32_LE( high, msglen, 4 ); + + last = ctx->total[0] & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + ret = mbedtls_ripemd160_update_ret( ctx, ripemd160_padding, padn ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_ripemd160_update_ret( ctx, msglen, 8 ); + if( ret != 0 ) + return( ret ); + + PUT_UINT32_LE( ctx->state[0], output, 0 ); + PUT_UINT32_LE( ctx->state[1], output, 4 ); + PUT_UINT32_LE( ctx->state[2], output, 8 ); + PUT_UINT32_LE( ctx->state[3], output, 12 ); + PUT_UINT32_LE( ctx->state[4], output, 16 ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_ripemd160_finish( mbedtls_ripemd160_context *ctx, + unsigned char output[20] ) +{ + mbedtls_ripemd160_finish_ret( ctx, output ); +} +#endif + +#endif /* ! MBEDTLS_RIPEMD160_ALT */ + +/* + * output = RIPEMD-160( input buffer ) + */ +int mbedtls_ripemd160_ret( const unsigned char *input, + size_t ilen, + unsigned char output[20] ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ripemd160_context ctx; + + mbedtls_ripemd160_init( &ctx ); + + if( ( ret = mbedtls_ripemd160_starts_ret( &ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_ripemd160_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_ripemd160_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_ripemd160_free( &ctx ); + + return( ret ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_ripemd160( const unsigned char *input, + size_t ilen, + unsigned char output[20] ) +{ + mbedtls_ripemd160_ret( input, ilen, output ); +} +#endif + +#if defined(MBEDTLS_SELF_TEST) +/* + * Test vectors from the RIPEMD-160 paper and + * http://homes.esat.kuleuven.be/~bosselae/mbedtls_ripemd160.html#HMAC + */ +#define TESTS 8 +static const unsigned char ripemd160_test_str[TESTS][81] = +{ + { "" }, + { "a" }, + { "abc" }, + { "message digest" }, + { "abcdefghijklmnopqrstuvwxyz" }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, + { "12345678901234567890123456789012345678901234567890123456789012345678901234567890" }, +}; + +static const size_t ripemd160_test_strlen[TESTS] = +{ + 0, 1, 3, 14, 26, 56, 62, 80 +}; + +static const unsigned char ripemd160_test_md[TESTS][20] = +{ + { 0x9c, 0x11, 0x85, 0xa5, 0xc5, 0xe9, 0xfc, 0x54, 0x61, 0x28, + 0x08, 0x97, 0x7e, 0xe8, 0xf5, 0x48, 0xb2, 0x25, 0x8d, 0x31 }, + { 0x0b, 0xdc, 0x9d, 0x2d, 0x25, 0x6b, 0x3e, 0xe9, 0xda, 0xae, + 0x34, 0x7b, 0xe6, 0xf4, 0xdc, 0x83, 0x5a, 0x46, 0x7f, 0xfe }, + { 0x8e, 0xb2, 0x08, 0xf7, 0xe0, 0x5d, 0x98, 0x7a, 0x9b, 0x04, + 0x4a, 0x8e, 0x98, 0xc6, 0xb0, 0x87, 0xf1, 0x5a, 0x0b, 0xfc }, + { 0x5d, 0x06, 0x89, 0xef, 0x49, 0xd2, 0xfa, 0xe5, 0x72, 0xb8, + 0x81, 0xb1, 0x23, 0xa8, 0x5f, 0xfa, 0x21, 0x59, 0x5f, 0x36 }, + { 0xf7, 0x1c, 0x27, 0x10, 0x9c, 0x69, 0x2c, 0x1b, 0x56, 0xbb, + 0xdc, 0xeb, 0x5b, 0x9d, 0x28, 0x65, 0xb3, 0x70, 0x8d, 0xbc }, + { 0x12, 0xa0, 0x53, 0x38, 0x4a, 0x9c, 0x0c, 0x88, 0xe4, 0x05, + 0xa0, 0x6c, 0x27, 0xdc, 0xf4, 0x9a, 0xda, 0x62, 0xeb, 0x2b }, + { 0xb0, 0xe2, 0x0b, 0x6e, 0x31, 0x16, 0x64, 0x02, 0x86, 0xed, + 0x3a, 0x87, 0xa5, 0x71, 0x30, 0x79, 0xb2, 0x1f, 0x51, 0x89 }, + { 0x9b, 0x75, 0x2e, 0x45, 0x57, 0x3d, 0x4b, 0x39, 0xf4, 0xdb, + 0xd3, 0x32, 0x3c, 0xab, 0x82, 0xbf, 0x63, 0x32, 0x6b, 0xfb }, +}; + +/* + * Checkup routine + */ +int mbedtls_ripemd160_self_test( int verbose ) +{ + int i, ret = 0; + unsigned char output[20]; + + memset( output, 0, sizeof output ); + + for( i = 0; i < TESTS; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " RIPEMD-160 test #%d: ", i + 1 ); + + ret = mbedtls_ripemd160_ret( ripemd160_test_str[i], + ripemd160_test_strlen[i], output ); + if( ret != 0 ) + goto fail; + + if( memcmp( output, ripemd160_test_md[i], 20 ) != 0 ) + { + ret = 1; + goto fail; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_RIPEMD160_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/rsa.c b/Android/Level4/app/src/main/c/mbedtls/library/rsa.c new file mode 100644 index 0000000..d6abd65 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/rsa.c @@ -0,0 +1,2758 @@ +/* + * The RSA public-key cryptosystem + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ + +/* + * The following sources were referenced in the design of this implementation + * of the RSA algorithm: + * + * [1] A method for obtaining digital signatures and public-key cryptosystems + * R Rivest, A Shamir, and L Adleman + * http://people.csail.mit.edu/rivest/pubs.html#RSA78 + * + * [2] Handbook of Applied Cryptography - 1997, Chapter 8 + * Menezes, van Oorschot and Vanstone + * + * [3] Malware Guard Extension: Using SGX to Conceal Cache Attacks + * Michael Schwarz, Samuel Weiser, Daniel Gruss, Clémentine Maurice and + * Stefan Mangard + * https://arxiv.org/abs/1702.08719v2 + * + */ + +#include "common.h" + +#if defined(MBEDTLS_RSA_C) + +#include "mbedtls/rsa.h" +#include "mbedtls/rsa_internal.h" +#include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_PKCS1_V21) +#include "mbedtls/md.h" +#endif + +#if defined(MBEDTLS_PKCS1_V15) && !defined(__OpenBSD__) && !defined(__NetBSD__) +#include +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if !defined(MBEDTLS_RSA_ALT) + +/* Parameter validation macros */ +#define RSA_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_RSA_BAD_INPUT_DATA ) +#define RSA_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if defined(MBEDTLS_PKCS1_V15) +/* constant-time buffer comparison */ +static inline int mbedtls_safer_memcmp( const void *a, const void *b, size_t n ) +{ + size_t i; + const unsigned char *A = (const unsigned char *) a; + const unsigned char *B = (const unsigned char *) b; + unsigned char diff = 0; + + for( i = 0; i < n; i++ ) + diff |= A[i] ^ B[i]; + + return( diff ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +int mbedtls_rsa_import( mbedtls_rsa_context *ctx, + const mbedtls_mpi *N, + const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, const mbedtls_mpi *E ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + RSA_VALIDATE_RET( ctx != NULL ); + + if( ( N != NULL && ( ret = mbedtls_mpi_copy( &ctx->N, N ) ) != 0 ) || + ( P != NULL && ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 ) || + ( Q != NULL && ( ret = mbedtls_mpi_copy( &ctx->Q, Q ) ) != 0 ) || + ( D != NULL && ( ret = mbedtls_mpi_copy( &ctx->D, D ) ) != 0 ) || + ( E != NULL && ( ret = mbedtls_mpi_copy( &ctx->E, E ) ) != 0 ) ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + } + + if( N != NULL ) + ctx->len = mbedtls_mpi_size( &ctx->N ); + + return( 0 ); +} + +int mbedtls_rsa_import_raw( mbedtls_rsa_context *ctx, + unsigned char const *N, size_t N_len, + unsigned char const *P, size_t P_len, + unsigned char const *Q, size_t Q_len, + unsigned char const *D, size_t D_len, + unsigned char const *E, size_t E_len ) +{ + int ret = 0; + RSA_VALIDATE_RET( ctx != NULL ); + + if( N != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->N, N, N_len ) ); + ctx->len = mbedtls_mpi_size( &ctx->N ); + } + + if( P != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->P, P, P_len ) ); + + if( Q != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->Q, Q, Q_len ) ); + + if( D != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->D, D, D_len ) ); + + if( E != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->E, E, E_len ) ); + +cleanup: + + if( ret != 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + + return( 0 ); +} + +/* + * Checks whether the context fields are set in such a way + * that the RSA primitives will be able to execute without error. + * It does *not* make guarantees for consistency of the parameters. + */ +static int rsa_check_context( mbedtls_rsa_context const *ctx, int is_priv, + int blinding_needed ) +{ +#if !defined(MBEDTLS_RSA_NO_CRT) + /* blinding_needed is only used for NO_CRT to decide whether + * P,Q need to be present or not. */ + ((void) blinding_needed); +#endif + + if( ctx->len != mbedtls_mpi_size( &ctx->N ) || + ctx->len > MBEDTLS_MPI_MAX_SIZE ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + /* + * 1. Modular exponentiation needs positive, odd moduli. + */ + + /* Modular exponentiation wrt. N is always used for + * RSA public key operations. */ + if( mbedtls_mpi_cmp_int( &ctx->N, 0 ) <= 0 || + mbedtls_mpi_get_bit( &ctx->N, 0 ) == 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + +#if !defined(MBEDTLS_RSA_NO_CRT) + /* Modular exponentiation for P and Q is only + * used for private key operations and if CRT + * is used. */ + if( is_priv && + ( mbedtls_mpi_cmp_int( &ctx->P, 0 ) <= 0 || + mbedtls_mpi_get_bit( &ctx->P, 0 ) == 0 || + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) <= 0 || + mbedtls_mpi_get_bit( &ctx->Q, 0 ) == 0 ) ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } +#endif /* !MBEDTLS_RSA_NO_CRT */ + + /* + * 2. Exponents must be positive + */ + + /* Always need E for public key operations */ + if( mbedtls_mpi_cmp_int( &ctx->E, 0 ) <= 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_RSA_NO_CRT) + /* For private key operations, use D or DP & DQ + * as (unblinded) exponents. */ + if( is_priv && mbedtls_mpi_cmp_int( &ctx->D, 0 ) <= 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); +#else + if( is_priv && + ( mbedtls_mpi_cmp_int( &ctx->DP, 0 ) <= 0 || + mbedtls_mpi_cmp_int( &ctx->DQ, 0 ) <= 0 ) ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } +#endif /* MBEDTLS_RSA_NO_CRT */ + + /* Blinding shouldn't make exponents negative either, + * so check that P, Q >= 1 if that hasn't yet been + * done as part of 1. */ +#if defined(MBEDTLS_RSA_NO_CRT) + if( is_priv && blinding_needed && + ( mbedtls_mpi_cmp_int( &ctx->P, 0 ) <= 0 || + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) <= 0 ) ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } +#endif + + /* It wouldn't lead to an error if it wasn't satisfied, + * but check for QP >= 1 nonetheless. */ +#if !defined(MBEDTLS_RSA_NO_CRT) + if( is_priv && + mbedtls_mpi_cmp_int( &ctx->QP, 0 ) <= 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } +#endif + + return( 0 ); +} + +int mbedtls_rsa_complete( mbedtls_rsa_context *ctx ) +{ + int ret = 0; + int have_N, have_P, have_Q, have_D, have_E; +#if !defined(MBEDTLS_RSA_NO_CRT) + int have_DP, have_DQ, have_QP; +#endif + int n_missing, pq_missing, d_missing, is_pub, is_priv; + + RSA_VALIDATE_RET( ctx != NULL ); + + have_N = ( mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 ); + have_P = ( mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 ); + have_Q = ( mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 ); + have_D = ( mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 ); + have_E = ( mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0 ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + have_DP = ( mbedtls_mpi_cmp_int( &ctx->DP, 0 ) != 0 ); + have_DQ = ( mbedtls_mpi_cmp_int( &ctx->DQ, 0 ) != 0 ); + have_QP = ( mbedtls_mpi_cmp_int( &ctx->QP, 0 ) != 0 ); +#endif + + /* + * Check whether provided parameters are enough + * to deduce all others. The following incomplete + * parameter sets for private keys are supported: + * + * (1) P, Q missing. + * (2) D and potentially N missing. + * + */ + + n_missing = have_P && have_Q && have_D && have_E; + pq_missing = have_N && !have_P && !have_Q && have_D && have_E; + d_missing = have_P && have_Q && !have_D && have_E; + is_pub = have_N && !have_P && !have_Q && !have_D && have_E; + + /* These three alternatives are mutually exclusive */ + is_priv = n_missing || pq_missing || d_missing; + + if( !is_priv && !is_pub ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* + * Step 1: Deduce N if P, Q are provided. + */ + + if( !have_N && have_P && have_Q ) + { + if( ( ret = mbedtls_mpi_mul_mpi( &ctx->N, &ctx->P, + &ctx->Q ) ) != 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + } + + ctx->len = mbedtls_mpi_size( &ctx->N ); + } + + /* + * Step 2: Deduce and verify all remaining core parameters. + */ + + if( pq_missing ) + { + ret = mbedtls_rsa_deduce_primes( &ctx->N, &ctx->E, &ctx->D, + &ctx->P, &ctx->Q ); + if( ret != 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + + } + else if( d_missing ) + { + if( ( ret = mbedtls_rsa_deduce_private_exponent( &ctx->P, + &ctx->Q, + &ctx->E, + &ctx->D ) ) != 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + } + } + + /* + * Step 3: Deduce all additional parameters specific + * to our current RSA implementation. + */ + +#if !defined(MBEDTLS_RSA_NO_CRT) + if( is_priv && ! ( have_DP && have_DQ && have_QP ) ) + { + ret = mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D, + &ctx->DP, &ctx->DQ, &ctx->QP ); + if( ret != 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + } +#endif /* MBEDTLS_RSA_NO_CRT */ + + /* + * Step 3: Basic sanity checks + */ + + return( rsa_check_context( ctx, is_priv, 1 ) ); +} + +int mbedtls_rsa_export_raw( const mbedtls_rsa_context *ctx, + unsigned char *N, size_t N_len, + unsigned char *P, size_t P_len, + unsigned char *Q, size_t Q_len, + unsigned char *D, size_t D_len, + unsigned char *E, size_t E_len ) +{ + int ret = 0; + int is_priv; + RSA_VALIDATE_RET( ctx != NULL ); + + /* Check if key is private or public */ + is_priv = + mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0; + + if( !is_priv ) + { + /* If we're trying to export private parameters for a public key, + * something must be wrong. */ + if( P != NULL || Q != NULL || D != NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + } + + if( N != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->N, N, N_len ) ); + + if( P != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->P, P, P_len ) ); + + if( Q != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->Q, Q, Q_len ) ); + + if( D != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->D, D, D_len ) ); + + if( E != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->E, E, E_len ) ); + +cleanup: + + return( ret ); +} + +int mbedtls_rsa_export( const mbedtls_rsa_context *ctx, + mbedtls_mpi *N, mbedtls_mpi *P, mbedtls_mpi *Q, + mbedtls_mpi *D, mbedtls_mpi *E ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + int is_priv; + RSA_VALIDATE_RET( ctx != NULL ); + + /* Check if key is private or public */ + is_priv = + mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0; + + if( !is_priv ) + { + /* If we're trying to export private parameters for a public key, + * something must be wrong. */ + if( P != NULL || Q != NULL || D != NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + } + + /* Export all requested core parameters. */ + + if( ( N != NULL && ( ret = mbedtls_mpi_copy( N, &ctx->N ) ) != 0 ) || + ( P != NULL && ( ret = mbedtls_mpi_copy( P, &ctx->P ) ) != 0 ) || + ( Q != NULL && ( ret = mbedtls_mpi_copy( Q, &ctx->Q ) ) != 0 ) || + ( D != NULL && ( ret = mbedtls_mpi_copy( D, &ctx->D ) ) != 0 ) || + ( E != NULL && ( ret = mbedtls_mpi_copy( E, &ctx->E ) ) != 0 ) ) + { + return( ret ); + } + + return( 0 ); +} + +/* + * Export CRT parameters + * This must also be implemented if CRT is not used, for being able to + * write DER encoded RSA keys. The helper function mbedtls_rsa_deduce_crt + * can be used in this case. + */ +int mbedtls_rsa_export_crt( const mbedtls_rsa_context *ctx, + mbedtls_mpi *DP, mbedtls_mpi *DQ, mbedtls_mpi *QP ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + int is_priv; + RSA_VALIDATE_RET( ctx != NULL ); + + /* Check if key is private or public */ + is_priv = + mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0; + + if( !is_priv ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + /* Export all requested blinding parameters. */ + if( ( DP != NULL && ( ret = mbedtls_mpi_copy( DP, &ctx->DP ) ) != 0 ) || + ( DQ != NULL && ( ret = mbedtls_mpi_copy( DQ, &ctx->DQ ) ) != 0 ) || + ( QP != NULL && ( ret = mbedtls_mpi_copy( QP, &ctx->QP ) ) != 0 ) ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + } +#else + if( ( ret = mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D, + DP, DQ, QP ) ) != 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + } +#endif + + return( 0 ); +} + +/* + * Initialize an RSA context + */ +void mbedtls_rsa_init( mbedtls_rsa_context *ctx, + int padding, + int hash_id ) +{ + RSA_VALIDATE( ctx != NULL ); + RSA_VALIDATE( padding == MBEDTLS_RSA_PKCS_V15 || + padding == MBEDTLS_RSA_PKCS_V21 ); + + memset( ctx, 0, sizeof( mbedtls_rsa_context ) ); + + mbedtls_rsa_set_padding( ctx, padding, hash_id ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif +} + +/* + * Set padding for an existing RSA context + */ +void mbedtls_rsa_set_padding( mbedtls_rsa_context *ctx, int padding, + int hash_id ) +{ + RSA_VALIDATE( ctx != NULL ); + RSA_VALIDATE( padding == MBEDTLS_RSA_PKCS_V15 || + padding == MBEDTLS_RSA_PKCS_V21 ); + + ctx->padding = padding; + ctx->hash_id = hash_id; +} + +/* + * Get length in bytes of RSA modulus + */ + +size_t mbedtls_rsa_get_len( const mbedtls_rsa_context *ctx ) +{ + return( ctx->len ); +} + + +#if defined(MBEDTLS_GENPRIME) + +/* + * Generate an RSA keypair + * + * This generation method follows the RSA key pair generation procedure of + * FIPS 186-4 if 2^16 < exponent < 2^256 and nbits = 2048 or nbits = 3072. + */ +int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + unsigned int nbits, int exponent ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi H, G, L; + int prime_quality = 0; + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( f_rng != NULL ); + + if( nbits < 128 || exponent < 3 || nbits % 2 != 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* + * If the modulus is 1024 bit long or shorter, then the security strength of + * the RSA algorithm is less than or equal to 80 bits and therefore an error + * rate of 2^-80 is sufficient. + */ + if( nbits > 1024 ) + prime_quality = MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR; + + mbedtls_mpi_init( &H ); + mbedtls_mpi_init( &G ); + mbedtls_mpi_init( &L ); + + /* + * find primes P and Q with Q < P so that: + * 1. |P-Q| > 2^( nbits / 2 - 100 ) + * 2. GCD( E, (P-1)*(Q-1) ) == 1 + * 3. E^-1 mod LCM(P-1, Q-1) > 2^( nbits / 2 ) + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->E, exponent ) ); + + do + { + MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->P, nbits >> 1, + prime_quality, f_rng, p_rng ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->Q, nbits >> 1, + prime_quality, f_rng, p_rng ) ); + + /* make sure the difference between p and q is not too small (FIPS 186-4 §B.3.3 step 5.4) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &H, &ctx->P, &ctx->Q ) ); + if( mbedtls_mpi_bitlen( &H ) <= ( ( nbits >= 200 ) ? ( ( nbits >> 1 ) - 99 ) : 0 ) ) + continue; + + /* not required by any standards, but some users rely on the fact that P > Q */ + if( H.s < 0 ) + mbedtls_mpi_swap( &ctx->P, &ctx->Q ); + + /* Temporarily replace P,Q by P-1, Q-1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &ctx->P, &ctx->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &ctx->Q, &ctx->Q, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &H, &ctx->P, &ctx->Q ) ); + + /* check GCD( E, (P-1)*(Q-1) ) == 1 (FIPS 186-4 §B.3.1 criterion 2(a)) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->E, &H ) ); + if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 ) + continue; + + /* compute smallest possible D = E^-1 mod LCM(P-1, Q-1) (FIPS 186-4 §B.3.1 criterion 3(b)) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->P, &ctx->Q ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &L, NULL, &H, &G ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->D, &ctx->E, &L ) ); + + if( mbedtls_mpi_bitlen( &ctx->D ) <= ( ( nbits + 1 ) / 2 ) ) // (FIPS 186-4 §B.3.1 criterion 3(a)) + continue; + + break; + } + while( 1 ); + + /* Restore P,Q */ + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &ctx->P, &ctx->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &ctx->Q, &ctx->Q, 1 ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) ); + + ctx->len = mbedtls_mpi_size( &ctx->N ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + /* + * DP = D mod (P - 1) + * DQ = D mod (Q - 1) + * QP = Q^-1 mod P + */ + MBEDTLS_MPI_CHK( mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D, + &ctx->DP, &ctx->DQ, &ctx->QP ) ); +#endif /* MBEDTLS_RSA_NO_CRT */ + + /* Double-check */ + MBEDTLS_MPI_CHK( mbedtls_rsa_check_privkey( ctx ) ); + +cleanup: + + mbedtls_mpi_free( &H ); + mbedtls_mpi_free( &G ); + mbedtls_mpi_free( &L ); + + if( ret != 0 ) + { + mbedtls_rsa_free( ctx ); + return( MBEDTLS_ERR_RSA_KEY_GEN_FAILED + ret ); + } + + return( 0 ); +} + +#endif /* MBEDTLS_GENPRIME */ + +/* + * Check a public RSA key + */ +int mbedtls_rsa_check_pubkey( const mbedtls_rsa_context *ctx ) +{ + RSA_VALIDATE_RET( ctx != NULL ); + + if( rsa_check_context( ctx, 0 /* public */, 0 /* no blinding */ ) != 0 ) + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + + if( mbedtls_mpi_bitlen( &ctx->N ) < 128 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + if( mbedtls_mpi_get_bit( &ctx->E, 0 ) == 0 || + mbedtls_mpi_bitlen( &ctx->E ) < 2 || + mbedtls_mpi_cmp_mpi( &ctx->E, &ctx->N ) >= 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + return( 0 ); +} + +/* + * Check for the consistency of all fields in an RSA private key context + */ +int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx ) +{ + RSA_VALIDATE_RET( ctx != NULL ); + + if( mbedtls_rsa_check_pubkey( ctx ) != 0 || + rsa_check_context( ctx, 1 /* private */, 1 /* blinding */ ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + if( mbedtls_rsa_validate_params( &ctx->N, &ctx->P, &ctx->Q, + &ctx->D, &ctx->E, NULL, NULL ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + +#if !defined(MBEDTLS_RSA_NO_CRT) + else if( mbedtls_rsa_validate_crt( &ctx->P, &ctx->Q, &ctx->D, + &ctx->DP, &ctx->DQ, &ctx->QP ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } +#endif + + return( 0 ); +} + +/* + * Check if contexts holding a public and private key match + */ +int mbedtls_rsa_check_pub_priv( const mbedtls_rsa_context *pub, + const mbedtls_rsa_context *prv ) +{ + RSA_VALIDATE_RET( pub != NULL ); + RSA_VALIDATE_RET( prv != NULL ); + + if( mbedtls_rsa_check_pubkey( pub ) != 0 || + mbedtls_rsa_check_privkey( prv ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + if( mbedtls_mpi_cmp_mpi( &pub->N, &prv->N ) != 0 || + mbedtls_mpi_cmp_mpi( &pub->E, &prv->E ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + return( 0 ); +} + +/* + * Do an RSA public key operation + */ +int mbedtls_rsa_public( mbedtls_rsa_context *ctx, + const unsigned char *input, + unsigned char *output ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t olen; + mbedtls_mpi T; + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( input != NULL ); + RSA_VALIDATE_RET( output != NULL ); + + if( rsa_check_context( ctx, 0 /* public */, 0 /* no blinding */ ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &T ); + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &T, input, ctx->len ) ); + + if( mbedtls_mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) + { + ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + goto cleanup; + } + + olen = ctx->len; + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T, &T, &ctx->E, &ctx->N, &ctx->RN ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &T, output, olen ) ); + +cleanup: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + mbedtls_mpi_free( &T ); + + if( ret != 0 ) + return( MBEDTLS_ERR_RSA_PUBLIC_FAILED + ret ); + + return( 0 ); +} + +/* + * Generate or update blinding values, see section 10 of: + * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA, + * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer + * Berlin Heidelberg, 1996. p. 104-113. + */ +static int rsa_prepare_blinding( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret, count = 0; + mbedtls_mpi R; + + mbedtls_mpi_init( &R ); + + if( ctx->Vf.p != NULL ) + { + /* We already have blinding values, just update them by squaring */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->N ) ); + + goto cleanup; + } + + /* Unblinding value: Vf = random number, invertible mod N */ + do { + if( count++ > 10 ) + { + ret = MBEDTLS_ERR_RSA_RNG_FAILED; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->Vf, ctx->len - 1, f_rng, p_rng ) ); + + /* Compute Vf^-1 as R * (R Vf)^-1 to avoid leaks from inv_mod. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, ctx->len - 1, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vf, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->N ) ); + + /* At this point, Vi is invertible mod N if and only if both Vf and R + * are invertible mod N. If one of them isn't, we don't need to know + * which one, we just loop and choose new values for both of them. + * (Each iteration succeeds with overwhelming probability.) */ + ret = mbedtls_mpi_inv_mod( &ctx->Vi, &ctx->Vi, &ctx->N ); + if( ret != 0 && ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) + goto cleanup; + + } while( ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); + + /* Finish the computation of Vf^-1 = R * (R Vf)^-1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->N ) ); + + /* Blinding value: Vi = Vf^(-e) mod N + * (Vi already contains Vf^-1 at this point) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->Vi, &ctx->Vi, &ctx->E, &ctx->N, &ctx->RN ) ); + + +cleanup: + mbedtls_mpi_free( &R ); + + return( ret ); +} + +/* + * Exponent blinding supposed to prevent side-channel attacks using multiple + * traces of measurements to recover the RSA key. The more collisions are there, + * the more bits of the key can be recovered. See [3]. + * + * Collecting n collisions with m bit long blinding value requires 2^(m-m/n) + * observations on avarage. + * + * For example with 28 byte blinding to achieve 2 collisions the adversary has + * to make 2^112 observations on avarage. + * + * (With the currently (as of 2017 April) known best algorithms breaking 2048 + * bit RSA requires approximately as much time as trying out 2^112 random keys. + * Thus in this sense with 28 byte blinding the security is not reduced by + * side-channel attacks like the one in [3]) + * + * This countermeasure does not help if the key recovery is possible with a + * single trace. + */ +#define RSA_EXPONENT_BLINDING 28 + +/* + * Do an RSA private key operation + */ +int mbedtls_rsa_private( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + const unsigned char *input, + unsigned char *output ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t olen; + + /* Temporary holding the result */ + mbedtls_mpi T; + + /* Temporaries holding P-1, Q-1 and the + * exponent blinding factor, respectively. */ + mbedtls_mpi P1, Q1, R; + +#if !defined(MBEDTLS_RSA_NO_CRT) + /* Temporaries holding the results mod p resp. mod q. */ + mbedtls_mpi TP, TQ; + + /* Temporaries holding the blinded exponents for + * the mod p resp. mod q computation (if used). */ + mbedtls_mpi DP_blind, DQ_blind; + + /* Pointers to actual exponents to be used - either the unblinded + * or the blinded ones, depending on the presence of a PRNG. */ + mbedtls_mpi *DP = &ctx->DP; + mbedtls_mpi *DQ = &ctx->DQ; +#else + /* Temporary holding the blinded exponent (if used). */ + mbedtls_mpi D_blind; + + /* Pointer to actual exponent to be used - either the unblinded + * or the blinded one, depending on the presence of a PRNG. */ + mbedtls_mpi *D = &ctx->D; +#endif /* MBEDTLS_RSA_NO_CRT */ + + /* Temporaries holding the initial input and the double + * checked result; should be the same in the end. */ + mbedtls_mpi I, C; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( input != NULL ); + RSA_VALIDATE_RET( output != NULL ); + + if( rsa_check_context( ctx, 1 /* private key checks */, + f_rng != NULL /* blinding y/n */ ) != 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + /* MPI Initialization */ + mbedtls_mpi_init( &T ); + + mbedtls_mpi_init( &P1 ); + mbedtls_mpi_init( &Q1 ); + mbedtls_mpi_init( &R ); + + if( f_rng != NULL ) + { +#if defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_init( &D_blind ); +#else + mbedtls_mpi_init( &DP_blind ); + mbedtls_mpi_init( &DQ_blind ); +#endif + } + +#if !defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_init( &TP ); mbedtls_mpi_init( &TQ ); +#endif + + mbedtls_mpi_init( &I ); + mbedtls_mpi_init( &C ); + + /* End of MPI initialization */ + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &T, input, ctx->len ) ); + if( mbedtls_mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) + { + ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &I, &T ) ); + + if( f_rng != NULL ) + { + /* + * Blinding + * T = T * Vi mod N + */ + MBEDTLS_MPI_CHK( rsa_prepare_blinding( ctx, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &T, &ctx->Vi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T, &ctx->N ) ); + + /* + * Exponent blinding + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &P1, &ctx->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &Q1, &ctx->Q, 1 ) ); + +#if defined(MBEDTLS_RSA_NO_CRT) + /* + * D_blind = ( P - 1 ) * ( Q - 1 ) * R + D + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING, + f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &D_blind, &P1, &Q1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &D_blind, &D_blind, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &D_blind, &D_blind, &ctx->D ) ); + + D = &D_blind; +#else + /* + * DP_blind = ( P - 1 ) * R + DP + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING, + f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DP_blind, &P1, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &DP_blind, &DP_blind, + &ctx->DP ) ); + + DP = &DP_blind; + + /* + * DQ_blind = ( Q - 1 ) * R + DQ + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING, + f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DQ_blind, &Q1, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &DQ_blind, &DQ_blind, + &ctx->DQ ) ); + + DQ = &DQ_blind; +#endif /* MBEDTLS_RSA_NO_CRT */ + } + +#if defined(MBEDTLS_RSA_NO_CRT) + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T, &T, D, &ctx->N, &ctx->RN ) ); +#else + /* + * Faster decryption using the CRT + * + * TP = input ^ dP mod P + * TQ = input ^ dQ mod Q + */ + + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &TP, &T, DP, &ctx->P, &ctx->RP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &TQ, &T, DQ, &ctx->Q, &ctx->RQ ) ); + + /* + * T = (TP - TQ) * (Q^-1 mod P) mod P + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &TP, &TQ ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &TP, &T, &ctx->QP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &TP, &ctx->P ) ); + + /* + * T = TQ + T * Q + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &TP, &T, &ctx->Q ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &TQ, &TP ) ); +#endif /* MBEDTLS_RSA_NO_CRT */ + + if( f_rng != NULL ) + { + /* + * Unblind + * T = T * Vf mod N + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &T, &ctx->Vf ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T, &ctx->N ) ); + } + + /* Verify the result to prevent glitching attacks. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &C, &T, &ctx->E, + &ctx->N, &ctx->RN ) ); + if( mbedtls_mpi_cmp_mpi( &C, &I ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_VERIFY_FAILED; + goto cleanup; + } + + olen = ctx->len; + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &T, output, olen ) ); + +cleanup: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + mbedtls_mpi_free( &P1 ); + mbedtls_mpi_free( &Q1 ); + mbedtls_mpi_free( &R ); + + if( f_rng != NULL ) + { +#if defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_free( &D_blind ); +#else + mbedtls_mpi_free( &DP_blind ); + mbedtls_mpi_free( &DQ_blind ); +#endif + } + + mbedtls_mpi_free( &T ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_free( &TP ); mbedtls_mpi_free( &TQ ); +#endif + + mbedtls_mpi_free( &C ); + mbedtls_mpi_free( &I ); + + if( ret != 0 ) + return( MBEDTLS_ERR_RSA_PRIVATE_FAILED + ret ); + + return( 0 ); +} + +#if defined(MBEDTLS_PKCS1_V21) +/** + * Generate and apply the MGF1 operation (from PKCS#1 v2.1) to a buffer. + * + * \param dst buffer to mask + * \param dlen length of destination buffer + * \param src source of the mask generation + * \param slen length of the source buffer + * \param md_ctx message digest context to use + */ +static int mgf_mask( unsigned char *dst, size_t dlen, unsigned char *src, + size_t slen, mbedtls_md_context_t *md_ctx ) +{ + unsigned char mask[MBEDTLS_MD_MAX_SIZE]; + unsigned char counter[4]; + unsigned char *p; + unsigned int hlen; + size_t i, use_len; + int ret = 0; + + memset( mask, 0, MBEDTLS_MD_MAX_SIZE ); + memset( counter, 0, 4 ); + + hlen = mbedtls_md_get_size( md_ctx->md_info ); + + /* Generate and apply dbMask */ + p = dst; + + while( dlen > 0 ) + { + use_len = hlen; + if( dlen < hlen ) + use_len = dlen; + + if( ( ret = mbedtls_md_starts( md_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( md_ctx, src, slen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( md_ctx, counter, 4 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_finish( md_ctx, mask ) ) != 0 ) + goto exit; + + for( i = 0; i < use_len; ++i ) + *p++ ^= mask[i]; + + counter[3]++; + + dlen -= use_len; + } + +exit: + mbedtls_platform_zeroize( mask, sizeof( mask ) ); + + return( ret ); +} +#endif /* MBEDTLS_PKCS1_V21 */ + +#if defined(MBEDTLS_PKCS1_V21) +/* + * Implementation of the PKCS#1 v2.1 RSAES-OAEP-ENCRYPT function + */ +int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + const unsigned char *label, size_t label_len, + size_t ilen, + const unsigned char *input, + unsigned char *output ) +{ + size_t olen; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = output; + unsigned int hlen; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( output != NULL ); + RSA_VALIDATE_RET( ilen == 0 || input != NULL ); + RSA_VALIDATE_RET( label_len == 0 || label != NULL ); + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( f_rng == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + olen = ctx->len; + hlen = mbedtls_md_get_size( md_info ); + + /* first comparison checks for overflow */ + if( ilen + 2 * hlen + 2 < ilen || olen < ilen + 2 * hlen + 2 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + memset( output, 0, olen ); + + *p++ = 0; + + /* Generate a random octet string seed */ + if( ( ret = f_rng( p_rng, p, hlen ) ) != 0 ) + return( MBEDTLS_ERR_RSA_RNG_FAILED + ret ); + + p += hlen; + + /* Construct DB */ + if( ( ret = mbedtls_md( md_info, label, label_len, p ) ) != 0 ) + return( ret ); + p += hlen; + p += olen - 2 * hlen - 2 - ilen; + *p++ = 1; + if( ilen != 0 ) + memcpy( p, input, ilen ); + + mbedtls_md_init( &md_ctx ); + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) + goto exit; + + /* maskedDB: Apply dbMask to DB */ + if( ( ret = mgf_mask( output + hlen + 1, olen - hlen - 1, output + 1, hlen, + &md_ctx ) ) != 0 ) + goto exit; + + /* maskedSeed: Apply seedMask to seed */ + if( ( ret = mgf_mask( output + 1, hlen, output + hlen + 1, olen - hlen - 1, + &md_ctx ) ) != 0 ) + goto exit; + +exit: + mbedtls_md_free( &md_ctx ); + + if( ret != 0 ) + return( ret ); + + return( ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, output, output ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, output, output ) ); +} +#endif /* MBEDTLS_PKCS1_V21 */ + +#if defined(MBEDTLS_PKCS1_V15) +/* + * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-ENCRYPT function + */ +int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t ilen, + const unsigned char *input, + unsigned char *output ) +{ + size_t nb_pad, olen; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = output; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( output != NULL ); + RSA_VALIDATE_RET( ilen == 0 || input != NULL ); + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + olen = ctx->len; + + /* first comparison checks for overflow */ + if( ilen + 11 < ilen || olen < ilen + 11 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + nb_pad = olen - 3 - ilen; + + *p++ = 0; + if( mode == MBEDTLS_RSA_PUBLIC ) + { + if( f_rng == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + *p++ = MBEDTLS_RSA_CRYPT; + + while( nb_pad-- > 0 ) + { + int rng_dl = 100; + + do { + ret = f_rng( p_rng, p, 1 ); + } while( *p == 0 && --rng_dl && ret == 0 ); + + /* Check if RNG failed to generate data */ + if( rng_dl == 0 || ret != 0 ) + return( MBEDTLS_ERR_RSA_RNG_FAILED + ret ); + + p++; + } + } + else + { + *p++ = MBEDTLS_RSA_SIGN; + + while( nb_pad-- > 0 ) + *p++ = 0xFF; + } + + *p++ = 0; + if( ilen != 0 ) + memcpy( p, input, ilen ); + + return( ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, output, output ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, output, output ) ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +/* + * Add the message padding, then do an RSA operation + */ +int mbedtls_rsa_pkcs1_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t ilen, + const unsigned char *input, + unsigned char *output ) +{ + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( output != NULL ); + RSA_VALIDATE_RET( ilen == 0 || input != NULL ); + + switch( ctx->padding ) + { +#if defined(MBEDTLS_PKCS1_V15) + case MBEDTLS_RSA_PKCS_V15: + return mbedtls_rsa_rsaes_pkcs1_v15_encrypt( ctx, f_rng, p_rng, mode, ilen, + input, output ); +#endif + +#if defined(MBEDTLS_PKCS1_V21) + case MBEDTLS_RSA_PKCS_V21: + return mbedtls_rsa_rsaes_oaep_encrypt( ctx, f_rng, p_rng, mode, NULL, 0, + ilen, input, output ); +#endif + + default: + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + } +} + +#if defined(MBEDTLS_PKCS1_V21) +/* + * Implementation of the PKCS#1 v2.1 RSAES-OAEP-DECRYPT function + */ +int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + const unsigned char *label, size_t label_len, + size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t ilen, i, pad_len; + unsigned char *p, bad, pad_done; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + unsigned char lhash[MBEDTLS_MD_MAX_SIZE]; + unsigned int hlen; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( output_max_len == 0 || output != NULL ); + RSA_VALIDATE_RET( label_len == 0 || label != NULL ); + RSA_VALIDATE_RET( input != NULL ); + RSA_VALIDATE_RET( olen != NULL ); + + /* + * Parameters sanity checks + */ + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + ilen = ctx->len; + + if( ilen < 16 || ilen > sizeof( buf ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hlen = mbedtls_md_get_size( md_info ); + + // checking for integer underflow + if( 2 * hlen + 2 > ilen ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* + * RSA operation + */ + ret = ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, input, buf ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, input, buf ); + + if( ret != 0 ) + goto cleanup; + + /* + * Unmask data and generate lHash + */ + mbedtls_md_init( &md_ctx ); + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) + { + mbedtls_md_free( &md_ctx ); + goto cleanup; + } + + /* seed: Apply seedMask to maskedSeed */ + if( ( ret = mgf_mask( buf + 1, hlen, buf + hlen + 1, ilen - hlen - 1, + &md_ctx ) ) != 0 || + /* DB: Apply dbMask to maskedDB */ + ( ret = mgf_mask( buf + hlen + 1, ilen - hlen - 1, buf + 1, hlen, + &md_ctx ) ) != 0 ) + { + mbedtls_md_free( &md_ctx ); + goto cleanup; + } + + mbedtls_md_free( &md_ctx ); + + /* Generate lHash */ + if( ( ret = mbedtls_md( md_info, label, label_len, lhash ) ) != 0 ) + goto cleanup; + + /* + * Check contents, in "constant-time" + */ + p = buf; + bad = 0; + + bad |= *p++; /* First byte must be 0 */ + + p += hlen; /* Skip seed */ + + /* Check lHash */ + for( i = 0; i < hlen; i++ ) + bad |= lhash[i] ^ *p++; + + /* Get zero-padding len, but always read till end of buffer + * (minus one, for the 01 byte) */ + pad_len = 0; + pad_done = 0; + for( i = 0; i < ilen - 2 * hlen - 2; i++ ) + { + pad_done |= p[i]; + pad_len += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1; + } + + p += pad_len; + bad |= *p++ ^ 0x01; + + /* + * The only information "leaked" is whether the padding was correct or not + * (eg, no data is copied if it was not correct). This meets the + * recommendations in PKCS#1 v2.2: an opponent cannot distinguish between + * the different error conditions. + */ + if( bad != 0 ) + { + ret = MBEDTLS_ERR_RSA_INVALID_PADDING; + goto cleanup; + } + + if( ilen - ( p - buf ) > output_max_len ) + { + ret = MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE; + goto cleanup; + } + + *olen = ilen - (p - buf); + if( *olen != 0 ) + memcpy( output, p, *olen ); + ret = 0; + +cleanup: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + mbedtls_platform_zeroize( lhash, sizeof( lhash ) ); + + return( ret ); +} +#endif /* MBEDTLS_PKCS1_V21 */ + +#if defined(MBEDTLS_PKCS1_V15) +/** Turn zero-or-nonzero into zero-or-all-bits-one, without branches. + * + * \param value The value to analyze. + * \return Zero if \p value is zero, otherwise all-bits-one. + */ +static unsigned all_or_nothing_int( unsigned value ) +{ + /* MSVC has a warning about unary minus on unsigned, but this is + * well-defined and precisely what we want to do here */ +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + return( - ( ( value | - value ) >> ( sizeof( value ) * 8 - 1 ) ) ); +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif +} + +/** Check whether a size is out of bounds, without branches. + * + * This is equivalent to `size > max`, but is likely to be compiled to + * to code using bitwise operation rather than a branch. + * + * \param size Size to check. + * \param max Maximum desired value for \p size. + * \return \c 0 if `size <= max`. + * \return \c 1 if `size > max`. + */ +static unsigned size_greater_than( size_t size, size_t max ) +{ + /* Return the sign bit (1 for negative) of (max - size). */ + return( ( max - size ) >> ( sizeof( size_t ) * 8 - 1 ) ); +} + +/** Choose between two integer values, without branches. + * + * This is equivalent to `cond ? if1 : if0`, but is likely to be compiled + * to code using bitwise operation rather than a branch. + * + * \param cond Condition to test. + * \param if1 Value to use if \p cond is nonzero. + * \param if0 Value to use if \p cond is zero. + * \return \c if1 if \p cond is nonzero, otherwise \c if0. + */ +static unsigned if_int( unsigned cond, unsigned if1, unsigned if0 ) +{ + unsigned mask = all_or_nothing_int( cond ); + return( ( mask & if1 ) | (~mask & if0 ) ); +} + +/** Shift some data towards the left inside a buffer without leaking + * the length of the data through side channels. + * + * `mem_move_to_left(start, total, offset)` is functionally equivalent to + * ``` + * memmove(start, start + offset, total - offset); + * memset(start + offset, 0, total - offset); + * ``` + * but it strives to use a memory access pattern (and thus total timing) + * that does not depend on \p offset. This timing independence comes at + * the expense of performance. + * + * \param start Pointer to the start of the buffer. + * \param total Total size of the buffer. + * \param offset Offset from which to copy \p total - \p offset bytes. + */ +static void mem_move_to_left( void *start, + size_t total, + size_t offset ) +{ + volatile unsigned char *buf = start; + size_t i, n; + if( total == 0 ) + return; + for( i = 0; i < total; i++ ) + { + unsigned no_op = size_greater_than( total - offset, i ); + /* The first `total - offset` passes are a no-op. The last + * `offset` passes shift the data one byte to the left and + * zero out the last byte. */ + for( n = 0; n < total - 1; n++ ) + { + unsigned char current = buf[n]; + unsigned char next = buf[n+1]; + buf[n] = if_int( no_op, current, next ); + } + buf[total-1] = if_int( no_op, buf[total-1], 0 ); + } +} + +/* + * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-DECRYPT function + */ +int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t ilen, i, plaintext_max_size; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + /* The following variables take sensitive values: their value must + * not leak into the observable behavior of the function other than + * the designated outputs (output, olen, return value). Otherwise + * this would open the execution of the function to + * side-channel-based variants of the Bleichenbacher padding oracle + * attack. Potential side channels include overall timing, memory + * access patterns (especially visible to an adversary who has access + * to a shared memory cache), and branches (especially visible to + * an adversary who has access to a shared code cache or to a shared + * branch predictor). */ + size_t pad_count = 0; + unsigned bad = 0; + unsigned char pad_done = 0; + size_t plaintext_size = 0; + unsigned output_too_large; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( output_max_len == 0 || output != NULL ); + RSA_VALIDATE_RET( input != NULL ); + RSA_VALIDATE_RET( olen != NULL ); + + ilen = ctx->len; + plaintext_max_size = ( output_max_len > ilen - 11 ? + ilen - 11 : + output_max_len ); + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( ilen < 16 || ilen > sizeof( buf ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + ret = ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, input, buf ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, input, buf ); + + if( ret != 0 ) + goto cleanup; + + /* Check and get padding length in constant time and constant + * memory trace. The first byte must be 0. */ + bad |= buf[0]; + + if( mode == MBEDTLS_RSA_PRIVATE ) + { + /* Decode EME-PKCS1-v1_5 padding: 0x00 || 0x02 || PS || 0x00 + * where PS must be at least 8 nonzero bytes. */ + bad |= buf[1] ^ MBEDTLS_RSA_CRYPT; + + /* Read the whole buffer. Set pad_done to nonzero if we find + * the 0x00 byte and remember the padding length in pad_count. */ + for( i = 2; i < ilen; i++ ) + { + pad_done |= ((buf[i] | (unsigned char)-buf[i]) >> 7) ^ 1; + pad_count += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1; + } + } + else + { + /* Decode EMSA-PKCS1-v1_5 padding: 0x00 || 0x01 || PS || 0x00 + * where PS must be at least 8 bytes with the value 0xFF. */ + bad |= buf[1] ^ MBEDTLS_RSA_SIGN; + + /* Read the whole buffer. Set pad_done to nonzero if we find + * the 0x00 byte and remember the padding length in pad_count. + * If there's a non-0xff byte in the padding, the padding is bad. */ + for( i = 2; i < ilen; i++ ) + { + pad_done |= if_int( buf[i], 0, 1 ); + pad_count += if_int( pad_done, 0, 1 ); + bad |= if_int( pad_done, 0, buf[i] ^ 0xFF ); + } + } + + /* If pad_done is still zero, there's no data, only unfinished padding. */ + bad |= if_int( pad_done, 0, 1 ); + + /* There must be at least 8 bytes of padding. */ + bad |= size_greater_than( 8, pad_count ); + + /* If the padding is valid, set plaintext_size to the number of + * remaining bytes after stripping the padding. If the padding + * is invalid, avoid leaking this fact through the size of the + * output: use the maximum message size that fits in the output + * buffer. Do it without branches to avoid leaking the padding + * validity through timing. RSA keys are small enough that all the + * size_t values involved fit in unsigned int. */ + plaintext_size = if_int( bad, + (unsigned) plaintext_max_size, + (unsigned) ( ilen - pad_count - 3 ) ); + + /* Set output_too_large to 0 if the plaintext fits in the output + * buffer and to 1 otherwise. */ + output_too_large = size_greater_than( plaintext_size, + plaintext_max_size ); + + /* Set ret without branches to avoid timing attacks. Return: + * - INVALID_PADDING if the padding is bad (bad != 0). + * - OUTPUT_TOO_LARGE if the padding is good but the decrypted + * plaintext does not fit in the output buffer. + * - 0 if the padding is correct. */ + ret = - (int) if_int( bad, - MBEDTLS_ERR_RSA_INVALID_PADDING, + if_int( output_too_large, - MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE, + 0 ) ); + + /* If the padding is bad or the plaintext is too large, zero the + * data that we're about to copy to the output buffer. + * We need to copy the same amount of data + * from the same buffer whether the padding is good or not to + * avoid leaking the padding validity through overall timing or + * through memory or cache access patterns. */ + bad = all_or_nothing_int( bad | output_too_large ); + for( i = 11; i < ilen; i++ ) + buf[i] &= ~bad; + + /* If the plaintext is too large, truncate it to the buffer size. + * Copy anyway to avoid revealing the length through timing, because + * revealing the length is as bad as revealing the padding validity + * for a Bleichenbacher attack. */ + plaintext_size = if_int( output_too_large, + (unsigned) plaintext_max_size, + (unsigned) plaintext_size ); + + /* Move the plaintext to the leftmost position where it can start in + * the working buffer, i.e. make it start plaintext_max_size from + * the end of the buffer. Do this with a memory access trace that + * does not depend on the plaintext size. After this move, the + * starting location of the plaintext is no longer sensitive + * information. */ + mem_move_to_left( buf + ilen - plaintext_max_size, + plaintext_max_size, + plaintext_max_size - plaintext_size ); + + /* Finally copy the decrypted plaintext plus trailing zeros into the output + * buffer. If output_max_len is 0, then output may be an invalid pointer + * and the result of memcpy() would be undefined; prevent undefined + * behavior making sure to depend only on output_max_len (the size of the + * user-provided output buffer), which is independent from plaintext + * length, validity of padding, success of the decryption, and other + * secrets. */ + if( output_max_len != 0 ) + memcpy( output, buf + ilen - plaintext_max_size, plaintext_max_size ); + + /* Report the amount of data we copied to the output buffer. In case + * of errors (bad padding or output too large), the value of *olen + * when this function returns is not specified. Making it equivalent + * to the good case limits the risks of leaking the padding validity. */ + *olen = plaintext_size; + +cleanup: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + + return( ret ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +/* + * Do an RSA operation, then remove the message padding + */ +int mbedtls_rsa_pkcs1_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len) +{ + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( output_max_len == 0 || output != NULL ); + RSA_VALIDATE_RET( input != NULL ); + RSA_VALIDATE_RET( olen != NULL ); + + switch( ctx->padding ) + { +#if defined(MBEDTLS_PKCS1_V15) + case MBEDTLS_RSA_PKCS_V15: + return mbedtls_rsa_rsaes_pkcs1_v15_decrypt( ctx, f_rng, p_rng, mode, olen, + input, output, output_max_len ); +#endif + +#if defined(MBEDTLS_PKCS1_V21) + case MBEDTLS_RSA_PKCS_V21: + return mbedtls_rsa_rsaes_oaep_decrypt( ctx, f_rng, p_rng, mode, NULL, 0, + olen, input, output, + output_max_len ); +#endif + + default: + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + } +} + +#if defined(MBEDTLS_PKCS1_V21) +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PSS-SIGN function + */ +int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ) +{ + size_t olen; + unsigned char *p = sig; + unsigned char salt[MBEDTLS_MD_MAX_SIZE]; + size_t slen, min_slen, hlen, offset = 0; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t msb; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + RSA_VALIDATE_RET( sig != NULL ); + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( f_rng == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + olen = ctx->len; + + if( md_alg != MBEDTLS_MD_NONE ) + { + /* Gather length of hash to sign */ + md_info = mbedtls_md_info_from_type( md_alg ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hashlen = mbedtls_md_get_size( md_info ); + } + + md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hlen = mbedtls_md_get_size( md_info ); + + /* Calculate the largest possible salt length. Normally this is the hash + * length, which is the maximum length the salt can have. If there is not + * enough room, use the maximum salt length that fits. The constraint is + * that the hash length plus the salt length plus 2 bytes must be at most + * the key length. This complies with FIPS 186-4 §5.5 (e) and RFC 8017 + * (PKCS#1 v2.2) §9.1.1 step 3. */ + min_slen = hlen - 2; + if( olen < hlen + min_slen + 2 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + else if( olen >= hlen + hlen + 2 ) + slen = hlen; + else + slen = olen - hlen - 2; + + memset( sig, 0, olen ); + + /* Generate salt of length slen */ + if( ( ret = f_rng( p_rng, salt, slen ) ) != 0 ) + return( MBEDTLS_ERR_RSA_RNG_FAILED + ret ); + + /* Note: EMSA-PSS encoding is over the length of N - 1 bits */ + msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; + p += olen - hlen - slen - 2; + *p++ = 0x01; + memcpy( p, salt, slen ); + p += slen; + + mbedtls_md_init( &md_ctx ); + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) + goto exit; + + /* Generate H = Hash( M' ) */ + if( ( ret = mbedtls_md_starts( &md_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( &md_ctx, p, 8 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( &md_ctx, hash, hashlen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( &md_ctx, salt, slen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_finish( &md_ctx, p ) ) != 0 ) + goto exit; + + /* Compensate for boundary condition when applying mask */ + if( msb % 8 == 0 ) + offset = 1; + + /* maskedDB: Apply dbMask to DB */ + if( ( ret = mgf_mask( sig + offset, olen - hlen - 1 - offset, p, hlen, + &md_ctx ) ) != 0 ) + goto exit; + + msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; + sig[0] &= 0xFF >> ( olen * 8 - msb ); + + p += hlen; + *p++ = 0xBC; + + mbedtls_platform_zeroize( salt, sizeof( salt ) ); + +exit: + mbedtls_md_free( &md_ctx ); + + if( ret != 0 ) + return( ret ); + + return( ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, sig, sig ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, sig ) ); +} +#endif /* MBEDTLS_PKCS1_V21 */ + +#if defined(MBEDTLS_PKCS1_V15) +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-V1_5-SIGN function + */ + +/* Construct a PKCS v1.5 encoding of a hashed message + * + * This is used both for signature generation and verification. + * + * Parameters: + * - md_alg: Identifies the hash algorithm used to generate the given hash; + * MBEDTLS_MD_NONE if raw data is signed. + * - hashlen: Length of hash in case hashlen is MBEDTLS_MD_NONE. + * - hash: Buffer containing the hashed message or the raw data. + * - dst_len: Length of the encoded message. + * - dst: Buffer to hold the encoded message. + * + * Assumptions: + * - hash has size hashlen if md_alg == MBEDTLS_MD_NONE. + * - hash has size corresponding to md_alg if md_alg != MBEDTLS_MD_NONE. + * - dst points to a buffer of size at least dst_len. + * + */ +static int rsa_rsassa_pkcs1_v15_encode( mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + size_t dst_len, + unsigned char *dst ) +{ + size_t oid_size = 0; + size_t nb_pad = dst_len; + unsigned char *p = dst; + const char *oid = NULL; + + /* Are we signing hashed or raw data? */ + if( md_alg != MBEDTLS_MD_NONE ) + { + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( mbedtls_oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hashlen = mbedtls_md_get_size( md_info ); + + /* Double-check that 8 + hashlen + oid_size can be used as a + * 1-byte ASN.1 length encoding and that there's no overflow. */ + if( 8 + hashlen + oid_size >= 0x80 || + 10 + hashlen < hashlen || + 10 + hashlen + oid_size < 10 + hashlen ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* + * Static bounds check: + * - Need 10 bytes for five tag-length pairs. + * (Insist on 1-byte length encodings to protect against variants of + * Bleichenbacher's forgery attack against lax PKCS#1v1.5 verification) + * - Need hashlen bytes for hash + * - Need oid_size bytes for hash alg OID. + */ + if( nb_pad < 10 + hashlen + oid_size ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + nb_pad -= 10 + hashlen + oid_size; + } + else + { + if( nb_pad < hashlen ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + nb_pad -= hashlen; + } + + /* Need space for signature header and padding delimiter (3 bytes), + * and 8 bytes for the minimal padding */ + if( nb_pad < 3 + 8 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + nb_pad -= 3; + + /* Now nb_pad is the amount of memory to be filled + * with padding, and at least 8 bytes long. */ + + /* Write signature header and padding */ + *p++ = 0; + *p++ = MBEDTLS_RSA_SIGN; + memset( p, 0xFF, nb_pad ); + p += nb_pad; + *p++ = 0; + + /* Are we signing raw data? */ + if( md_alg == MBEDTLS_MD_NONE ) + { + memcpy( p, hash, hashlen ); + return( 0 ); + } + + /* Signing hashed data, add corresponding ASN.1 structure + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm DigestAlgorithmIdentifier, + * digest Digest } + * DigestAlgorithmIdentifier ::= AlgorithmIdentifier + * Digest ::= OCTET STRING + * + * Schematic: + * TAG-SEQ + LEN [ TAG-SEQ + LEN [ TAG-OID + LEN [ OID ] + * TAG-NULL + LEN [ NULL ] ] + * TAG-OCTET + LEN [ HASH ] ] + */ + *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; + *p++ = (unsigned char)( 0x08 + oid_size + hashlen ); + *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; + *p++ = (unsigned char)( 0x04 + oid_size ); + *p++ = MBEDTLS_ASN1_OID; + *p++ = (unsigned char) oid_size; + memcpy( p, oid, oid_size ); + p += oid_size; + *p++ = MBEDTLS_ASN1_NULL; + *p++ = 0x00; + *p++ = MBEDTLS_ASN1_OCTET_STRING; + *p++ = (unsigned char) hashlen; + memcpy( p, hash, hashlen ); + p += hashlen; + + /* Just a sanity-check, should be automatic + * after the initial bounds check. */ + if( p != dst + dst_len ) + { + mbedtls_platform_zeroize( dst, dst_len ); + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + return( 0 ); +} + +/* + * Do an RSA operation to sign the message digest + */ +int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *sig_try = NULL, *verif = NULL; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + RSA_VALIDATE_RET( sig != NULL ); + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* + * Prepare PKCS1-v1.5 encoding (padding and hash identifier) + */ + + if( ( ret = rsa_rsassa_pkcs1_v15_encode( md_alg, hashlen, hash, + ctx->len, sig ) ) != 0 ) + return( ret ); + + /* + * Call respective RSA primitive + */ + + if( mode == MBEDTLS_RSA_PUBLIC ) + { + /* Skip verification on a public key operation */ + return( mbedtls_rsa_public( ctx, sig, sig ) ); + } + + /* Private key operation + * + * In order to prevent Lenstra's attack, make the signature in a + * temporary buffer and check it before returning it. + */ + + sig_try = mbedtls_calloc( 1, ctx->len ); + if( sig_try == NULL ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + + verif = mbedtls_calloc( 1, ctx->len ); + if( verif == NULL ) + { + mbedtls_free( sig_try ); + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + } + + MBEDTLS_MPI_CHK( mbedtls_rsa_private( ctx, f_rng, p_rng, sig, sig_try ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_public( ctx, sig_try, verif ) ); + + if( mbedtls_safer_memcmp( verif, sig, ctx->len ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_PRIVATE_FAILED; + goto cleanup; + } + + memcpy( sig, sig_try, ctx->len ); + +cleanup: + mbedtls_free( sig_try ); + mbedtls_free( verif ); + + return( ret ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +/* + * Do an RSA operation to sign the message digest + */ +int mbedtls_rsa_pkcs1_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ) +{ + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + RSA_VALIDATE_RET( sig != NULL ); + + switch( ctx->padding ) + { +#if defined(MBEDTLS_PKCS1_V15) + case MBEDTLS_RSA_PKCS_V15: + return mbedtls_rsa_rsassa_pkcs1_v15_sign( ctx, f_rng, p_rng, mode, md_alg, + hashlen, hash, sig ); +#endif + +#if defined(MBEDTLS_PKCS1_V21) + case MBEDTLS_RSA_PKCS_V21: + return mbedtls_rsa_rsassa_pss_sign( ctx, f_rng, p_rng, mode, md_alg, + hashlen, hash, sig ); +#endif + + default: + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + } +} + +#if defined(MBEDTLS_PKCS1_V21) +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PSS-VERIFY function + */ +int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + mbedtls_md_type_t mgf1_hash_id, + int expected_salt_len, + const unsigned char *sig ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t siglen; + unsigned char *p; + unsigned char *hash_start; + unsigned char result[MBEDTLS_MD_MAX_SIZE]; + unsigned char zeros[8]; + unsigned int hlen; + size_t observed_salt_len, msb; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( sig != NULL ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + siglen = ctx->len; + + if( siglen < 16 || siglen > sizeof( buf ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + ret = ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, sig, buf ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, buf ); + + if( ret != 0 ) + return( ret ); + + p = buf; + + if( buf[siglen - 1] != 0xBC ) + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + + if( md_alg != MBEDTLS_MD_NONE ) + { + /* Gather length of hash to sign */ + md_info = mbedtls_md_info_from_type( md_alg ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hashlen = mbedtls_md_get_size( md_info ); + } + + md_info = mbedtls_md_info_from_type( mgf1_hash_id ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hlen = mbedtls_md_get_size( md_info ); + + memset( zeros, 0, 8 ); + + /* + * Note: EMSA-PSS verification is over the length of N - 1 bits + */ + msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; + + if( buf[0] >> ( 8 - siglen * 8 + msb ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* Compensate for boundary condition when applying mask */ + if( msb % 8 == 0 ) + { + p++; + siglen -= 1; + } + + if( siglen < hlen + 2 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + hash_start = p + siglen - hlen - 1; + + mbedtls_md_init( &md_ctx ); + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) + goto exit; + + ret = mgf_mask( p, siglen - hlen - 1, hash_start, hlen, &md_ctx ); + if( ret != 0 ) + goto exit; + + buf[0] &= 0xFF >> ( siglen * 8 - msb ); + + while( p < hash_start - 1 && *p == 0 ) + p++; + + if( *p++ != 0x01 ) + { + ret = MBEDTLS_ERR_RSA_INVALID_PADDING; + goto exit; + } + + observed_salt_len = hash_start - p; + + if( expected_salt_len != MBEDTLS_RSA_SALT_LEN_ANY && + observed_salt_len != (size_t) expected_salt_len ) + { + ret = MBEDTLS_ERR_RSA_INVALID_PADDING; + goto exit; + } + + /* + * Generate H = Hash( M' ) + */ + ret = mbedtls_md_starts( &md_ctx ); + if ( ret != 0 ) + goto exit; + ret = mbedtls_md_update( &md_ctx, zeros, 8 ); + if ( ret != 0 ) + goto exit; + ret = mbedtls_md_update( &md_ctx, hash, hashlen ); + if ( ret != 0 ) + goto exit; + ret = mbedtls_md_update( &md_ctx, p, observed_salt_len ); + if ( ret != 0 ) + goto exit; + ret = mbedtls_md_finish( &md_ctx, result ); + if ( ret != 0 ) + goto exit; + + if( memcmp( hash_start, result, hlen ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_VERIFY_FAILED; + goto exit; + } + +exit: + mbedtls_md_free( &md_ctx ); + + return( ret ); +} + +/* + * Simplified PKCS#1 v2.1 RSASSA-PSS-VERIFY function + */ +int mbedtls_rsa_rsassa_pss_verify( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ) +{ + mbedtls_md_type_t mgf1_hash_id; + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( sig != NULL ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + + mgf1_hash_id = ( ctx->hash_id != MBEDTLS_MD_NONE ) + ? (mbedtls_md_type_t) ctx->hash_id + : md_alg; + + return( mbedtls_rsa_rsassa_pss_verify_ext( ctx, f_rng, p_rng, mode, + md_alg, hashlen, hash, + mgf1_hash_id, MBEDTLS_RSA_SALT_LEN_ANY, + sig ) ); + +} +#endif /* MBEDTLS_PKCS1_V21 */ + +#if defined(MBEDTLS_PKCS1_V15) +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-v1_5-VERIFY function + */ +int mbedtls_rsa_rsassa_pkcs1_v15_verify( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ) +{ + int ret = 0; + size_t sig_len; + unsigned char *encoded = NULL, *encoded_expected = NULL; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( sig != NULL ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + + sig_len = ctx->len; + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* + * Prepare expected PKCS1 v1.5 encoding of hash. + */ + + if( ( encoded = mbedtls_calloc( 1, sig_len ) ) == NULL || + ( encoded_expected = mbedtls_calloc( 1, sig_len ) ) == NULL ) + { + ret = MBEDTLS_ERR_MPI_ALLOC_FAILED; + goto cleanup; + } + + if( ( ret = rsa_rsassa_pkcs1_v15_encode( md_alg, hashlen, hash, sig_len, + encoded_expected ) ) != 0 ) + goto cleanup; + + /* + * Apply RSA primitive to get what should be PKCS1 encoded hash. + */ + + ret = ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, sig, encoded ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, encoded ); + if( ret != 0 ) + goto cleanup; + + /* + * Compare + */ + + if( ( ret = mbedtls_safer_memcmp( encoded, encoded_expected, + sig_len ) ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_VERIFY_FAILED; + goto cleanup; + } + +cleanup: + + if( encoded != NULL ) + { + mbedtls_platform_zeroize( encoded, sig_len ); + mbedtls_free( encoded ); + } + + if( encoded_expected != NULL ) + { + mbedtls_platform_zeroize( encoded_expected, sig_len ); + mbedtls_free( encoded_expected ); + } + + return( ret ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +/* + * Do an RSA operation and check the message digest + */ +int mbedtls_rsa_pkcs1_verify( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ) +{ + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( sig != NULL ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + + switch( ctx->padding ) + { +#if defined(MBEDTLS_PKCS1_V15) + case MBEDTLS_RSA_PKCS_V15: + return mbedtls_rsa_rsassa_pkcs1_v15_verify( ctx, f_rng, p_rng, mode, md_alg, + hashlen, hash, sig ); +#endif + +#if defined(MBEDTLS_PKCS1_V21) + case MBEDTLS_RSA_PKCS_V21: + return mbedtls_rsa_rsassa_pss_verify( ctx, f_rng, p_rng, mode, md_alg, + hashlen, hash, sig ); +#endif + + default: + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + } +} + +/* + * Copy the components of an RSA key + */ +int mbedtls_rsa_copy( mbedtls_rsa_context *dst, const mbedtls_rsa_context *src ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + RSA_VALIDATE_RET( dst != NULL ); + RSA_VALIDATE_RET( src != NULL ); + + dst->ver = src->ver; + dst->len = src->len; + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->N, &src->N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->E, &src->E ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->D, &src->D ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->P, &src->P ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Q, &src->Q ) ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->DP, &src->DP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->DQ, &src->DQ ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->QP, &src->QP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RP, &src->RP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RQ, &src->RQ ) ); +#endif + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RN, &src->RN ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Vi, &src->Vi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Vf, &src->Vf ) ); + + dst->padding = src->padding; + dst->hash_id = src->hash_id; + +cleanup: + if( ret != 0 ) + mbedtls_rsa_free( dst ); + + return( ret ); +} + +/* + * Free the components of an RSA key + */ +void mbedtls_rsa_free( mbedtls_rsa_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_mpi_free( &ctx->Vi ); + mbedtls_mpi_free( &ctx->Vf ); + mbedtls_mpi_free( &ctx->RN ); + mbedtls_mpi_free( &ctx->D ); + mbedtls_mpi_free( &ctx->Q ); + mbedtls_mpi_free( &ctx->P ); + mbedtls_mpi_free( &ctx->E ); + mbedtls_mpi_free( &ctx->N ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_free( &ctx->RQ ); + mbedtls_mpi_free( &ctx->RP ); + mbedtls_mpi_free( &ctx->QP ); + mbedtls_mpi_free( &ctx->DQ ); + mbedtls_mpi_free( &ctx->DP ); +#endif /* MBEDTLS_RSA_NO_CRT */ + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free( &ctx->mutex ); +#endif +} + +#endif /* !MBEDTLS_RSA_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +#include "mbedtls/sha1.h" + +/* + * Example RSA-1024 keypair, for test purposes + */ +#define KEY_LEN 128 + +#define RSA_N "9292758453063D803DD603D5E777D788" \ + "8ED1D5BF35786190FA2F23EBC0848AEA" \ + "DDA92CA6C3D80B32C4D109BE0F36D6AE" \ + "7130B9CED7ACDF54CFC7555AC14EEBAB" \ + "93A89813FBF3C4F8066D2D800F7C38A8" \ + "1AE31942917403FF4946B0A83D3D3E05" \ + "EE57C6F5F5606FB5D4BC6CD34EE0801A" \ + "5E94BB77B07507233A0BC7BAC8F90F79" + +#define RSA_E "10001" + +#define RSA_D "24BF6185468786FDD303083D25E64EFC" \ + "66CA472BC44D253102F8B4A9D3BFA750" \ + "91386C0077937FE33FA3252D28855837" \ + "AE1B484A8A9A45F7EE8C0C634F99E8CD" \ + "DF79C5CE07EE72C7F123142198164234" \ + "CABB724CF78B8173B9F880FC86322407" \ + "AF1FEDFDDE2BEB674CA15F3E81A1521E" \ + "071513A1E85B5DFA031F21ECAE91A34D" + +#define RSA_P "C36D0EB7FCD285223CFB5AABA5BDA3D8" \ + "2C01CAD19EA484A87EA4377637E75500" \ + "FCB2005C5C7DD6EC4AC023CDA285D796" \ + "C3D9E75E1EFC42488BB4F1D13AC30A57" + +#define RSA_Q "C000DF51A7C77AE8D7C7370C1FF55B69" \ + "E211C2B9E5DB1ED0BF61D0D9899620F4" \ + "910E4168387E3C30AA1E00C339A79508" \ + "8452DD96A9A5EA5D9DCA68DA636032AF" + +#define PT_LEN 24 +#define RSA_PT "\xAA\xBB\xCC\x03\x02\x01\x00\xFF\xFF\xFF\xFF\xFF" \ + "\x11\x22\x33\x0A\x0B\x0C\xCC\xDD\xDD\xDD\xDD\xDD" + +#if defined(MBEDTLS_PKCS1_V15) +static int myrand( void *rng_state, unsigned char *output, size_t len ) +{ +#if !defined(__OpenBSD__) && !defined(__NetBSD__) + size_t i; + + if( rng_state != NULL ) + rng_state = NULL; + + for( i = 0; i < len; ++i ) + output[i] = rand(); +#else + if( rng_state != NULL ) + rng_state = NULL; + + arc4random_buf( output, len ); +#endif /* !OpenBSD && !NetBSD */ + + return( 0 ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +/* + * Checkup routine + */ +int mbedtls_rsa_self_test( int verbose ) +{ + int ret = 0; +#if defined(MBEDTLS_PKCS1_V15) + size_t len; + mbedtls_rsa_context rsa; + unsigned char rsa_plaintext[PT_LEN]; + unsigned char rsa_decrypted[PT_LEN]; + unsigned char rsa_ciphertext[KEY_LEN]; +#if defined(MBEDTLS_SHA1_C) + unsigned char sha1sum[20]; +#endif + + mbedtls_mpi K; + + mbedtls_mpi_init( &K ); + mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, 0 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_N ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, &K, NULL, NULL, NULL, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_P ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, &K, NULL, NULL, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_Q ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, NULL, &K, NULL, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_D ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, NULL, NULL, &K, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_E ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, NULL, NULL, NULL, &K ) ); + + MBEDTLS_MPI_CHK( mbedtls_rsa_complete( &rsa ) ); + + if( verbose != 0 ) + mbedtls_printf( " RSA key validation: " ); + + if( mbedtls_rsa_check_pubkey( &rsa ) != 0 || + mbedtls_rsa_check_privkey( &rsa ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n PKCS#1 encryption : " ); + + memcpy( rsa_plaintext, RSA_PT, PT_LEN ); + + if( mbedtls_rsa_pkcs1_encrypt( &rsa, myrand, NULL, MBEDTLS_RSA_PUBLIC, + PT_LEN, rsa_plaintext, + rsa_ciphertext ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n PKCS#1 decryption : " ); + + if( mbedtls_rsa_pkcs1_decrypt( &rsa, myrand, NULL, MBEDTLS_RSA_PRIVATE, + &len, rsa_ciphertext, rsa_decrypted, + sizeof(rsa_decrypted) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( memcmp( rsa_decrypted, rsa_plaintext, len ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + +#if defined(MBEDTLS_SHA1_C) + if( verbose != 0 ) + mbedtls_printf( " PKCS#1 data sign : " ); + + if( mbedtls_sha1_ret( rsa_plaintext, PT_LEN, sha1sum ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + if( mbedtls_rsa_pkcs1_sign( &rsa, myrand, NULL, + MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA1, 0, + sha1sum, rsa_ciphertext ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n PKCS#1 sig. verify: " ); + + if( mbedtls_rsa_pkcs1_verify( &rsa, NULL, NULL, + MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 0, + sha1sum, rsa_ciphertext ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); +#endif /* MBEDTLS_SHA1_C */ + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +cleanup: + mbedtls_mpi_free( &K ); + mbedtls_rsa_free( &rsa ); +#else /* MBEDTLS_PKCS1_V15 */ + ((void) verbose); +#endif /* MBEDTLS_PKCS1_V15 */ + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_RSA_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/rsa_internal.c b/Android/Level4/app/src/main/c/mbedtls/library/rsa_internal.c new file mode 100644 index 0000000..d6ba97a --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/rsa_internal.c @@ -0,0 +1,486 @@ +/* + * Helper functions for the RSA module + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 "common.h" + +#if defined(MBEDTLS_RSA_C) + +#include "mbedtls/rsa.h" +#include "mbedtls/bignum.h" +#include "mbedtls/rsa_internal.h" + +/* + * Compute RSA prime factors from public and private exponents + * + * Summary of algorithm: + * Setting F := lcm(P-1,Q-1), the idea is as follows: + * + * (a) For any 1 <= X < N with gcd(X,N)=1, we have X^F = 1 modulo N, so X^(F/2) + * is a square root of 1 in Z/NZ. Since Z/NZ ~= Z/PZ x Z/QZ by CRT and the + * square roots of 1 in Z/PZ and Z/QZ are +1 and -1, this leaves the four + * possibilities X^(F/2) = (+-1, +-1). If it happens that X^(F/2) = (-1,+1) + * or (+1,-1), then gcd(X^(F/2) + 1, N) will be equal to one of the prime + * factors of N. + * + * (b) If we don't know F/2 but (F/2) * K for some odd (!) K, then the same + * construction still applies since (-)^K is the identity on the set of + * roots of 1 in Z/NZ. + * + * The public and private key primitives (-)^E and (-)^D are mutually inverse + * bijections on Z/NZ if and only if (-)^(DE) is the identity on Z/NZ, i.e. + * if and only if DE - 1 is a multiple of F, say DE - 1 = F * L. + * Splitting L = 2^t * K with K odd, we have + * + * DE - 1 = FL = (F/2) * (2^(t+1)) * K, + * + * so (F / 2) * K is among the numbers + * + * (DE - 1) >> 1, (DE - 1) >> 2, ..., (DE - 1) >> ord + * + * where ord is the order of 2 in (DE - 1). + * We can therefore iterate through these numbers apply the construction + * of (a) and (b) above to attempt to factor N. + * + */ +int mbedtls_rsa_deduce_primes( mbedtls_mpi const *N, + mbedtls_mpi const *E, mbedtls_mpi const *D, + mbedtls_mpi *P, mbedtls_mpi *Q ) +{ + int ret = 0; + + uint16_t attempt; /* Number of current attempt */ + uint16_t iter; /* Number of squares computed in the current attempt */ + + uint16_t order; /* Order of 2 in DE - 1 */ + + mbedtls_mpi T; /* Holds largest odd divisor of DE - 1 */ + mbedtls_mpi K; /* Temporary holding the current candidate */ + + const unsigned char primes[] = { 2, + 3, 5, 7, 11, 13, 17, 19, 23, + 29, 31, 37, 41, 43, 47, 53, 59, + 61, 67, 71, 73, 79, 83, 89, 97, + 101, 103, 107, 109, 113, 127, 131, 137, + 139, 149, 151, 157, 163, 167, 173, 179, + 181, 191, 193, 197, 199, 211, 223, 227, + 229, 233, 239, 241, 251 + }; + + const size_t num_primes = sizeof( primes ) / sizeof( *primes ); + + if( P == NULL || Q == NULL || P->p != NULL || Q->p != NULL ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || + mbedtls_mpi_cmp_int( D, 1 ) <= 0 || + mbedtls_mpi_cmp_mpi( D, N ) >= 0 || + mbedtls_mpi_cmp_int( E, 1 ) <= 0 || + mbedtls_mpi_cmp_mpi( E, N ) >= 0 ) + { + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + } + + /* + * Initializations and temporary changes + */ + + mbedtls_mpi_init( &K ); + mbedtls_mpi_init( &T ); + + /* T := DE - 1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, D, E ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &T, &T, 1 ) ); + + if( ( order = (uint16_t) mbedtls_mpi_lsb( &T ) ) == 0 ) + { + ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + goto cleanup; + } + + /* After this operation, T holds the largest odd divisor of DE - 1. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &T, order ) ); + + /* + * Actual work + */ + + /* Skip trying 2 if N == 1 mod 8 */ + attempt = 0; + if( N->p[0] % 8 == 1 ) + attempt = 1; + + for( ; attempt < num_primes; ++attempt ) + { + mbedtls_mpi_lset( &K, primes[attempt] ); + + /* Check if gcd(K,N) = 1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( P, &K, N ) ); + if( mbedtls_mpi_cmp_int( P, 1 ) != 0 ) + continue; + + /* Go through K^T + 1, K^(2T) + 1, K^(4T) + 1, ... + * and check whether they have nontrivial GCD with N. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &K, &K, &T, N, + Q /* temporarily use Q for storing Montgomery + * multiplication helper values */ ) ); + + for( iter = 1; iter <= order; ++iter ) + { + /* If we reach 1 prematurely, there's no point + * in continuing to square K */ + if( mbedtls_mpi_cmp_int( &K, 1 ) == 0 ) + break; + + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( P, &K, N ) ); + + if( mbedtls_mpi_cmp_int( P, 1 ) == 1 && + mbedtls_mpi_cmp_mpi( P, N ) == -1 ) + { + /* + * Have found a nontrivial divisor P of N. + * Set Q := N / P. + */ + + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( Q, NULL, N, P ) ); + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, &K, &K ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, N ) ); + } + + /* + * If we get here, then either we prematurely aborted the loop because + * we reached 1, or K holds primes[attempt]^(DE - 1) mod N, which must + * be 1 if D,E,N were consistent. + * Check if that's the case and abort if not, to avoid very long, + * yet eventually failing, computations if N,D,E were not sane. + */ + if( mbedtls_mpi_cmp_int( &K, 1 ) != 0 ) + { + break; + } + } + + ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + +cleanup: + + mbedtls_mpi_free( &K ); + mbedtls_mpi_free( &T ); + return( ret ); +} + +/* + * Given P, Q and the public exponent E, deduce D. + * This is essentially a modular inversion. + */ +int mbedtls_rsa_deduce_private_exponent( mbedtls_mpi const *P, + mbedtls_mpi const *Q, + mbedtls_mpi const *E, + mbedtls_mpi *D ) +{ + int ret = 0; + mbedtls_mpi K, L; + + if( D == NULL || mbedtls_mpi_cmp_int( D, 0 ) != 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + if( mbedtls_mpi_cmp_int( P, 1 ) <= 0 || + mbedtls_mpi_cmp_int( Q, 1 ) <= 0 || + mbedtls_mpi_cmp_int( E, 0 ) == 0 ) + { + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + } + + mbedtls_mpi_init( &K ); + mbedtls_mpi_init( &L ); + + /* Temporarily put K := P-1 and L := Q-1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &L, Q, 1 ) ); + + /* Temporarily put D := gcd(P-1, Q-1) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( D, &K, &L ) ); + + /* K := LCM(P-1, Q-1) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, &K, &L ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &K, NULL, &K, D ) ); + + /* Compute modular inverse of E in LCM(P-1, Q-1) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( D, E, &K ) ); + +cleanup: + + mbedtls_mpi_free( &K ); + mbedtls_mpi_free( &L ); + + return( ret ); +} + +/* + * Check that RSA CRT parameters are in accordance with core parameters. + */ +int mbedtls_rsa_validate_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, const mbedtls_mpi *DP, + const mbedtls_mpi *DQ, const mbedtls_mpi *QP ) +{ + int ret = 0; + + mbedtls_mpi K, L; + mbedtls_mpi_init( &K ); + mbedtls_mpi_init( &L ); + + /* Check that DP - D == 0 mod P - 1 */ + if( DP != NULL ) + { + if( P == NULL ) + { + ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &L, DP, D ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &L, &L, &K ) ); + + if( mbedtls_mpi_cmp_int( &L, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + + /* Check that DQ - D == 0 mod Q - 1 */ + if( DQ != NULL ) + { + if( Q == NULL ) + { + ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, Q, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &L, DQ, D ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &L, &L, &K ) ); + + if( mbedtls_mpi_cmp_int( &L, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + + /* Check that QP * Q - 1 == 0 mod P */ + if( QP != NULL ) + { + if( P == NULL || Q == NULL ) + { + ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, QP, Q ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, P ) ); + if( mbedtls_mpi_cmp_int( &K, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + +cleanup: + + /* Wrap MPI error codes by RSA check failure error code */ + if( ret != 0 && + ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED && + ret != MBEDTLS_ERR_RSA_BAD_INPUT_DATA ) + { + ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + } + + mbedtls_mpi_free( &K ); + mbedtls_mpi_free( &L ); + + return( ret ); +} + +/* + * Check that core RSA parameters are sane. + */ +int mbedtls_rsa_validate_params( const mbedtls_mpi *N, const mbedtls_mpi *P, + const mbedtls_mpi *Q, const mbedtls_mpi *D, + const mbedtls_mpi *E, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = 0; + mbedtls_mpi K, L; + + mbedtls_mpi_init( &K ); + mbedtls_mpi_init( &L ); + + /* + * Step 1: If PRNG provided, check that P and Q are prime + */ + +#if defined(MBEDTLS_GENPRIME) + /* + * When generating keys, the strongest security we support aims for an error + * rate of at most 2^-100 and we are aiming for the same certainty here as + * well. + */ + if( f_rng != NULL && P != NULL && + ( ret = mbedtls_mpi_is_prime_ext( P, 50, f_rng, p_rng ) ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + + if( f_rng != NULL && Q != NULL && + ( ret = mbedtls_mpi_is_prime_ext( Q, 50, f_rng, p_rng ) ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } +#else + ((void) f_rng); + ((void) p_rng); +#endif /* MBEDTLS_GENPRIME */ + + /* + * Step 2: Check that 1 < N = P * Q + */ + + if( P != NULL && Q != NULL && N != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, P, Q ) ); + if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 || + mbedtls_mpi_cmp_mpi( &K, N ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + + /* + * Step 3: Check and 1 < D, E < N if present. + */ + + if( N != NULL && D != NULL && E != NULL ) + { + if ( mbedtls_mpi_cmp_int( D, 1 ) <= 0 || + mbedtls_mpi_cmp_int( E, 1 ) <= 0 || + mbedtls_mpi_cmp_mpi( D, N ) >= 0 || + mbedtls_mpi_cmp_mpi( E, N ) >= 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + + /* + * Step 4: Check that D, E are inverse modulo P-1 and Q-1 + */ + + if( P != NULL && Q != NULL && D != NULL && E != NULL ) + { + if( mbedtls_mpi_cmp_int( P, 1 ) <= 0 || + mbedtls_mpi_cmp_int( Q, 1 ) <= 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + + /* Compute DE-1 mod P-1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, D, E ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &L, P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, &L ) ); + if( mbedtls_mpi_cmp_int( &K, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + + /* Compute DE-1 mod Q-1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, D, E ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &L, Q, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, &L ) ); + if( mbedtls_mpi_cmp_int( &K, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + +cleanup: + + mbedtls_mpi_free( &K ); + mbedtls_mpi_free( &L ); + + /* Wrap MPI error codes by RSA check failure error code */ + if( ret != 0 && ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ) + { + ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + } + + return( ret ); +} + +int mbedtls_rsa_deduce_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, mbedtls_mpi *DP, + mbedtls_mpi *DQ, mbedtls_mpi *QP ) +{ + int ret = 0; + mbedtls_mpi K; + mbedtls_mpi_init( &K ); + + /* DP = D mod P-1 */ + if( DP != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( DP, D, &K ) ); + } + + /* DQ = D mod Q-1 */ + if( DQ != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, Q, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( DQ, D, &K ) ); + } + + /* QP = Q^{-1} mod P */ + if( QP != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( QP, Q, P ) ); + } + +cleanup: + mbedtls_mpi_free( &K ); + + return( ret ); +} + +#endif /* MBEDTLS_RSA_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/sha1.c b/Android/Level4/app/src/main/c/mbedtls/library/sha1.c new file mode 100644 index 0000000..593f795 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/sha1.c @@ -0,0 +1,568 @@ +/* + * FIPS-180-1 compliant SHA-1 implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ +/* + * The SHA-1 standard was published by NIST in 1993. + * + * http://www.itl.nist.gov/fipspubs/fip180-1.htm + */ + +#include "common.h" + +#if defined(MBEDTLS_SHA1_C) + +#include "mbedtls/sha1.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#define SHA1_VALIDATE_RET(cond) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_SHA1_BAD_INPUT_DATA ) + +#define SHA1_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if !defined(MBEDTLS_SHA1_ALT) + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +void mbedtls_sha1_init( mbedtls_sha1_context *ctx ) +{ + SHA1_VALIDATE( ctx != NULL ); + + memset( ctx, 0, sizeof( mbedtls_sha1_context ) ); +} + +void mbedtls_sha1_free( mbedtls_sha1_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_sha1_context ) ); +} + +void mbedtls_sha1_clone( mbedtls_sha1_context *dst, + const mbedtls_sha1_context *src ) +{ + SHA1_VALIDATE( dst != NULL ); + SHA1_VALIDATE( src != NULL ); + + *dst = *src; +} + +/* + * SHA-1 context setup + */ +int mbedtls_sha1_starts_ret( mbedtls_sha1_context *ctx ) +{ + SHA1_VALIDATE_RET( ctx != NULL ); + + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + ctx->state[4] = 0xC3D2E1F0; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha1_starts( mbedtls_sha1_context *ctx ) +{ + mbedtls_sha1_starts_ret( ctx ); +} +#endif + +#if !defined(MBEDTLS_SHA1_PROCESS_ALT) +int mbedtls_internal_sha1_process( mbedtls_sha1_context *ctx, + const unsigned char data[64] ) +{ + uint32_t temp, W[16], A, B, C, D, E; + + SHA1_VALIDATE_RET( ctx != NULL ); + SHA1_VALIDATE_RET( (const unsigned char *)data != NULL ); + + GET_UINT32_BE( W[ 0], data, 0 ); + GET_UINT32_BE( W[ 1], data, 4 ); + GET_UINT32_BE( W[ 2], data, 8 ); + GET_UINT32_BE( W[ 3], data, 12 ); + GET_UINT32_BE( W[ 4], data, 16 ); + GET_UINT32_BE( W[ 5], data, 20 ); + GET_UINT32_BE( W[ 6], data, 24 ); + GET_UINT32_BE( W[ 7], data, 28 ); + GET_UINT32_BE( W[ 8], data, 32 ); + GET_UINT32_BE( W[ 9], data, 36 ); + GET_UINT32_BE( W[10], data, 40 ); + GET_UINT32_BE( W[11], data, 44 ); + GET_UINT32_BE( W[12], data, 48 ); + GET_UINT32_BE( W[13], data, 52 ); + GET_UINT32_BE( W[14], data, 56 ); + GET_UINT32_BE( W[15], data, 60 ); + +#define S(x,n) (((x) << (n)) | (((x) & 0xFFFFFFFF) >> (32 - (n)))) + +#define R(t) \ + ( \ + temp = W[( (t) - 3 ) & 0x0F] ^ W[( (t) - 8 ) & 0x0F] ^ \ + W[( (t) - 14 ) & 0x0F] ^ W[ (t) & 0x0F], \ + ( W[(t) & 0x0F] = S(temp,1) ) \ + ) + +#define P(a,b,c,d,e,x) \ + do \ + { \ + (e) += S((a),5) + F((b),(c),(d)) + K + (x); \ + (b) = S((b),30); \ + } while( 0 ) + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + E = ctx->state[4]; + +#define F(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) +#define K 0x5A827999 + + P( A, B, C, D, E, W[0] ); + P( E, A, B, C, D, W[1] ); + P( D, E, A, B, C, W[2] ); + P( C, D, E, A, B, W[3] ); + P( B, C, D, E, A, W[4] ); + P( A, B, C, D, E, W[5] ); + P( E, A, B, C, D, W[6] ); + P( D, E, A, B, C, W[7] ); + P( C, D, E, A, B, W[8] ); + P( B, C, D, E, A, W[9] ); + P( A, B, C, D, E, W[10] ); + P( E, A, B, C, D, W[11] ); + P( D, E, A, B, C, W[12] ); + P( C, D, E, A, B, W[13] ); + P( B, C, D, E, A, W[14] ); + P( A, B, C, D, E, W[15] ); + P( E, A, B, C, D, R(16) ); + P( D, E, A, B, C, R(17) ); + P( C, D, E, A, B, R(18) ); + P( B, C, D, E, A, R(19) ); + +#undef K +#undef F + +#define F(x,y,z) ((x) ^ (y) ^ (z)) +#define K 0x6ED9EBA1 + + P( A, B, C, D, E, R(20) ); + P( E, A, B, C, D, R(21) ); + P( D, E, A, B, C, R(22) ); + P( C, D, E, A, B, R(23) ); + P( B, C, D, E, A, R(24) ); + P( A, B, C, D, E, R(25) ); + P( E, A, B, C, D, R(26) ); + P( D, E, A, B, C, R(27) ); + P( C, D, E, A, B, R(28) ); + P( B, C, D, E, A, R(29) ); + P( A, B, C, D, E, R(30) ); + P( E, A, B, C, D, R(31) ); + P( D, E, A, B, C, R(32) ); + P( C, D, E, A, B, R(33) ); + P( B, C, D, E, A, R(34) ); + P( A, B, C, D, E, R(35) ); + P( E, A, B, C, D, R(36) ); + P( D, E, A, B, C, R(37) ); + P( C, D, E, A, B, R(38) ); + P( B, C, D, E, A, R(39) ); + +#undef K +#undef F + +#define F(x,y,z) (((x) & (y)) | ((z) & ((x) | (y)))) +#define K 0x8F1BBCDC + + P( A, B, C, D, E, R(40) ); + P( E, A, B, C, D, R(41) ); + P( D, E, A, B, C, R(42) ); + P( C, D, E, A, B, R(43) ); + P( B, C, D, E, A, R(44) ); + P( A, B, C, D, E, R(45) ); + P( E, A, B, C, D, R(46) ); + P( D, E, A, B, C, R(47) ); + P( C, D, E, A, B, R(48) ); + P( B, C, D, E, A, R(49) ); + P( A, B, C, D, E, R(50) ); + P( E, A, B, C, D, R(51) ); + P( D, E, A, B, C, R(52) ); + P( C, D, E, A, B, R(53) ); + P( B, C, D, E, A, R(54) ); + P( A, B, C, D, E, R(55) ); + P( E, A, B, C, D, R(56) ); + P( D, E, A, B, C, R(57) ); + P( C, D, E, A, B, R(58) ); + P( B, C, D, E, A, R(59) ); + +#undef K +#undef F + +#define F(x,y,z) ((x) ^ (y) ^ (z)) +#define K 0xCA62C1D6 + + P( A, B, C, D, E, R(60) ); + P( E, A, B, C, D, R(61) ); + P( D, E, A, B, C, R(62) ); + P( C, D, E, A, B, R(63) ); + P( B, C, D, E, A, R(64) ); + P( A, B, C, D, E, R(65) ); + P( E, A, B, C, D, R(66) ); + P( D, E, A, B, C, R(67) ); + P( C, D, E, A, B, R(68) ); + P( B, C, D, E, A, R(69) ); + P( A, B, C, D, E, R(70) ); + P( E, A, B, C, D, R(71) ); + P( D, E, A, B, C, R(72) ); + P( C, D, E, A, B, R(73) ); + P( B, C, D, E, A, R(74) ); + P( A, B, C, D, E, R(75) ); + P( E, A, B, C, D, R(76) ); + P( D, E, A, B, C, R(77) ); + P( C, D, E, A, B, R(78) ); + P( B, C, D, E, A, R(79) ); + +#undef K +#undef F + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; + ctx->state[4] += E; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha1_process( mbedtls_sha1_context *ctx, + const unsigned char data[64] ) +{ + mbedtls_internal_sha1_process( ctx, data ); +} +#endif +#endif /* !MBEDTLS_SHA1_PROCESS_ALT */ + +/* + * SHA-1 process buffer + */ +int mbedtls_sha1_update_ret( mbedtls_sha1_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t fill; + uint32_t left; + + SHA1_VALIDATE_RET( ctx != NULL ); + SHA1_VALIDATE_RET( ilen == 0 || input != NULL ); + + if( ilen == 0 ) + return( 0 ); + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (uint32_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), input, fill ); + + if( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + if( ( ret = mbedtls_internal_sha1_process( ctx, input ) ) != 0 ) + return( ret ); + + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + memcpy( (void *) (ctx->buffer + left), input, ilen ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha1_update( mbedtls_sha1_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + mbedtls_sha1_update_ret( ctx, input, ilen ); +} +#endif + +/* + * SHA-1 final digest + */ +int mbedtls_sha1_finish_ret( mbedtls_sha1_context *ctx, + unsigned char output[20] ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + uint32_t used; + uint32_t high, low; + + SHA1_VALIDATE_RET( ctx != NULL ); + SHA1_VALIDATE_RET( (unsigned char *)output != NULL ); + + /* + * Add padding: 0x80 then 0x00 until 8 bytes remain for the length + */ + used = ctx->total[0] & 0x3F; + + ctx->buffer[used++] = 0x80; + + if( used <= 56 ) + { + /* Enough room for padding + length in current block */ + memset( ctx->buffer + used, 0, 56 - used ); + } + else + { + /* We'll need an extra block */ + memset( ctx->buffer + used, 0, 64 - used ); + + if( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + memset( ctx->buffer, 0, 56 ); + } + + /* + * Add message length + */ + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT32_BE( high, ctx->buffer, 56 ); + PUT_UINT32_BE( low, ctx->buffer, 60 ); + + if( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + /* + * Output final state + */ + PUT_UINT32_BE( ctx->state[0], output, 0 ); + PUT_UINT32_BE( ctx->state[1], output, 4 ); + PUT_UINT32_BE( ctx->state[2], output, 8 ); + PUT_UINT32_BE( ctx->state[3], output, 12 ); + PUT_UINT32_BE( ctx->state[4], output, 16 ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, + unsigned char output[20] ) +{ + mbedtls_sha1_finish_ret( ctx, output ); +} +#endif + +#endif /* !MBEDTLS_SHA1_ALT */ + +/* + * output = SHA-1( input buffer ) + */ +int mbedtls_sha1_ret( const unsigned char *input, + size_t ilen, + unsigned char output[20] ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_sha1_context ctx; + + SHA1_VALIDATE_RET( ilen == 0 || input != NULL ); + SHA1_VALIDATE_RET( (unsigned char *)output != NULL ); + + mbedtls_sha1_init( &ctx ); + + if( ( ret = mbedtls_sha1_starts_ret( &ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha1_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha1_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_sha1_free( &ctx ); + + return( ret ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha1( const unsigned char *input, + size_t ilen, + unsigned char output[20] ) +{ + mbedtls_sha1_ret( input, ilen, output ); +} +#endif + +#if defined(MBEDTLS_SELF_TEST) +/* + * FIPS-180-1 test vectors + */ +static const unsigned char sha1_test_buf[3][57] = +{ + { "abc" }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, + { "" } +}; + +static const size_t sha1_test_buflen[3] = +{ + 3, 56, 1000 +}; + +static const unsigned char sha1_test_sum[3][20] = +{ + { 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E, + 0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D }, + { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE, + 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1 }, + { 0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E, + 0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F } +}; + +/* + * Checkup routine + */ +int mbedtls_sha1_self_test( int verbose ) +{ + int i, j, buflen, ret = 0; + unsigned char buf[1024]; + unsigned char sha1sum[20]; + mbedtls_sha1_context ctx; + + mbedtls_sha1_init( &ctx ); + + /* + * SHA-1 + */ + for( i = 0; i < 3; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " SHA-1 test #%d: ", i + 1 ); + + if( ( ret = mbedtls_sha1_starts_ret( &ctx ) ) != 0 ) + goto fail; + + if( i == 2 ) + { + memset( buf, 'a', buflen = 1000 ); + + for( j = 0; j < 1000; j++ ) + { + ret = mbedtls_sha1_update_ret( &ctx, buf, buflen ); + if( ret != 0 ) + goto fail; + } + } + else + { + ret = mbedtls_sha1_update_ret( &ctx, sha1_test_buf[i], + sha1_test_buflen[i] ); + if( ret != 0 ) + goto fail; + } + + if( ( ret = mbedtls_sha1_finish_ret( &ctx, sha1sum ) ) != 0 ) + goto fail; + + if( memcmp( sha1sum, sha1_test_sum[i], 20 ) != 0 ) + { + ret = 1; + goto fail; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + goto exit; + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + +exit: + mbedtls_sha1_free( &ctx ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_SHA1_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/sha256.c b/Android/Level4/app/src/main/c/mbedtls/library/sha256.c new file mode 100644 index 0000000..b4c4b36 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/sha256.c @@ -0,0 +1,581 @@ +/* + * FIPS-180-2 compliant SHA-256 implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ +/* + * The SHA-256 Secure Hash Standard was published by NIST in 2002. + * + * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf + */ + +#include "common.h" + +#if defined(MBEDTLS_SHA256_C) + +#include "mbedtls/sha256.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#define SHA256_VALIDATE_RET(cond) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_SHA256_BAD_INPUT_DATA ) +#define SHA256_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if !defined(MBEDTLS_SHA256_ALT) + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +do { \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} while( 0 ) +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +do { \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} while( 0 ) +#endif + +void mbedtls_sha256_init( mbedtls_sha256_context *ctx ) +{ + SHA256_VALIDATE( ctx != NULL ); + + memset( ctx, 0, sizeof( mbedtls_sha256_context ) ); +} + +void mbedtls_sha256_free( mbedtls_sha256_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_sha256_context ) ); +} + +void mbedtls_sha256_clone( mbedtls_sha256_context *dst, + const mbedtls_sha256_context *src ) +{ + SHA256_VALIDATE( dst != NULL ); + SHA256_VALIDATE( src != NULL ); + + *dst = *src; +} + +/* + * SHA-256 context setup + */ +int mbedtls_sha256_starts_ret( mbedtls_sha256_context *ctx, int is224 ) +{ + SHA256_VALIDATE_RET( ctx != NULL ); + SHA256_VALIDATE_RET( is224 == 0 || is224 == 1 ); + + ctx->total[0] = 0; + ctx->total[1] = 0; + + if( is224 == 0 ) + { + /* SHA-256 */ + ctx->state[0] = 0x6A09E667; + ctx->state[1] = 0xBB67AE85; + ctx->state[2] = 0x3C6EF372; + ctx->state[3] = 0xA54FF53A; + ctx->state[4] = 0x510E527F; + ctx->state[5] = 0x9B05688C; + ctx->state[6] = 0x1F83D9AB; + ctx->state[7] = 0x5BE0CD19; + } + else + { + /* SHA-224 */ + ctx->state[0] = 0xC1059ED8; + ctx->state[1] = 0x367CD507; + ctx->state[2] = 0x3070DD17; + ctx->state[3] = 0xF70E5939; + ctx->state[4] = 0xFFC00B31; + ctx->state[5] = 0x68581511; + ctx->state[6] = 0x64F98FA7; + ctx->state[7] = 0xBEFA4FA4; + } + + ctx->is224 = is224; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, + int is224 ) +{ + mbedtls_sha256_starts_ret( ctx, is224 ); +} +#endif + +#if !defined(MBEDTLS_SHA256_PROCESS_ALT) +static const uint32_t K[] = +{ + 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, + 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, + 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, + 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, + 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, + 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, + 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, + 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967, + 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, + 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, + 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, + 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, + 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, + 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, + 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, + 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2, +}; + +#define SHR(x,n) (((x) & 0xFFFFFFFF) >> (n)) +#define ROTR(x,n) (SHR(x,n) | ((x) << (32 - (n)))) + +#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3)) +#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10)) + +#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22)) +#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25)) + +#define F0(x,y,z) (((x) & (y)) | ((z) & ((x) | (y)))) +#define F1(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) + +#define R(t) \ + ( \ + W[t] = S1(W[(t) - 2]) + W[(t) - 7] + \ + S0(W[(t) - 15]) + W[(t) - 16] \ + ) + +#define P(a,b,c,d,e,f,g,h,x,K) \ + do \ + { \ + temp1 = (h) + S3(e) + F1((e),(f),(g)) + (K) + (x); \ + temp2 = S2(a) + F0((a),(b),(c)); \ + (d) += temp1; (h) = temp1 + temp2; \ + } while( 0 ) + +int mbedtls_internal_sha256_process( mbedtls_sha256_context *ctx, + const unsigned char data[64] ) +{ + uint32_t temp1, temp2, W[64]; + uint32_t A[8]; + unsigned int i; + + SHA256_VALIDATE_RET( ctx != NULL ); + SHA256_VALIDATE_RET( (const unsigned char *)data != NULL ); + + for( i = 0; i < 8; i++ ) + A[i] = ctx->state[i]; + +#if defined(MBEDTLS_SHA256_SMALLER) + for( i = 0; i < 64; i++ ) + { + if( i < 16 ) + GET_UINT32_BE( W[i], data, 4 * i ); + else + R( i ); + + P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i], K[i] ); + + temp1 = A[7]; A[7] = A[6]; A[6] = A[5]; A[5] = A[4]; A[4] = A[3]; + A[3] = A[2]; A[2] = A[1]; A[1] = A[0]; A[0] = temp1; + } +#else /* MBEDTLS_SHA256_SMALLER */ + for( i = 0; i < 16; i++ ) + GET_UINT32_BE( W[i], data, 4 * i ); + + for( i = 0; i < 16; i += 8 ) + { + P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i+0], K[i+0] ); + P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], W[i+1], K[i+1] ); + P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], W[i+2], K[i+2] ); + P( A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], W[i+3], K[i+3] ); + P( A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], W[i+4], K[i+4] ); + P( A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], W[i+5], K[i+5] ); + P( A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], W[i+6], K[i+6] ); + P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], W[i+7], K[i+7] ); + } + + for( i = 16; i < 64; i += 8 ) + { + P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], R(i+0), K[i+0] ); + P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], R(i+1), K[i+1] ); + P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], R(i+2), K[i+2] ); + P( A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], R(i+3), K[i+3] ); + P( A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], R(i+4), K[i+4] ); + P( A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], R(i+5), K[i+5] ); + P( A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], R(i+6), K[i+6] ); + P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], R(i+7), K[i+7] ); + } +#endif /* MBEDTLS_SHA256_SMALLER */ + + for( i = 0; i < 8; i++ ) + ctx->state[i] += A[i]; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha256_process( mbedtls_sha256_context *ctx, + const unsigned char data[64] ) +{ + mbedtls_internal_sha256_process( ctx, data ); +} +#endif +#endif /* !MBEDTLS_SHA256_PROCESS_ALT */ + +/* + * SHA-256 process buffer + */ +int mbedtls_sha256_update_ret( mbedtls_sha256_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t fill; + uint32_t left; + + SHA256_VALIDATE_RET( ctx != NULL ); + SHA256_VALIDATE_RET( ilen == 0 || input != NULL ); + + if( ilen == 0 ) + return( 0 ); + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (uint32_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), input, fill ); + + if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + if( ( ret = mbedtls_internal_sha256_process( ctx, input ) ) != 0 ) + return( ret ); + + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + memcpy( (void *) (ctx->buffer + left), input, ilen ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha256_update( mbedtls_sha256_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + mbedtls_sha256_update_ret( ctx, input, ilen ); +} +#endif + +/* + * SHA-256 final digest + */ +int mbedtls_sha256_finish_ret( mbedtls_sha256_context *ctx, + unsigned char output[32] ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + uint32_t used; + uint32_t high, low; + + SHA256_VALIDATE_RET( ctx != NULL ); + SHA256_VALIDATE_RET( (unsigned char *)output != NULL ); + + /* + * Add padding: 0x80 then 0x00 until 8 bytes remain for the length + */ + used = ctx->total[0] & 0x3F; + + ctx->buffer[used++] = 0x80; + + if( used <= 56 ) + { + /* Enough room for padding + length in current block */ + memset( ctx->buffer + used, 0, 56 - used ); + } + else + { + /* We'll need an extra block */ + memset( ctx->buffer + used, 0, 64 - used ); + + if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + memset( ctx->buffer, 0, 56 ); + } + + /* + * Add message length + */ + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT32_BE( high, ctx->buffer, 56 ); + PUT_UINT32_BE( low, ctx->buffer, 60 ); + + if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + /* + * Output final state + */ + PUT_UINT32_BE( ctx->state[0], output, 0 ); + PUT_UINT32_BE( ctx->state[1], output, 4 ); + PUT_UINT32_BE( ctx->state[2], output, 8 ); + PUT_UINT32_BE( ctx->state[3], output, 12 ); + PUT_UINT32_BE( ctx->state[4], output, 16 ); + PUT_UINT32_BE( ctx->state[5], output, 20 ); + PUT_UINT32_BE( ctx->state[6], output, 24 ); + + if( ctx->is224 == 0 ) + PUT_UINT32_BE( ctx->state[7], output, 28 ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, + unsigned char output[32] ) +{ + mbedtls_sha256_finish_ret( ctx, output ); +} +#endif + +#endif /* !MBEDTLS_SHA256_ALT */ + +/* + * output = SHA-256( input buffer ) + */ +int mbedtls_sha256_ret( const unsigned char *input, + size_t ilen, + unsigned char output[32], + int is224 ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_sha256_context ctx; + + SHA256_VALIDATE_RET( is224 == 0 || is224 == 1 ); + SHA256_VALIDATE_RET( ilen == 0 || input != NULL ); + SHA256_VALIDATE_RET( (unsigned char *)output != NULL ); + + mbedtls_sha256_init( &ctx ); + + if( ( ret = mbedtls_sha256_starts_ret( &ctx, is224 ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha256_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha256_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_sha256_free( &ctx ); + + return( ret ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha256( const unsigned char *input, + size_t ilen, + unsigned char output[32], + int is224 ) +{ + mbedtls_sha256_ret( input, ilen, output, is224 ); +} +#endif + +#if defined(MBEDTLS_SELF_TEST) +/* + * FIPS-180-2 test vectors + */ +static const unsigned char sha256_test_buf[3][57] = +{ + { "abc" }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, + { "" } +}; + +static const size_t sha256_test_buflen[3] = +{ + 3, 56, 1000 +}; + +static const unsigned char sha256_test_sum[6][32] = +{ + /* + * SHA-224 test vectors + */ + { 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 }, + { 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 }, + { 0x20, 0x79, 0x46, 0x55, 0x98, 0x0C, 0x91, 0xD8, + 0xBB, 0xB4, 0xC1, 0xEA, 0x97, 0x61, 0x8A, 0x4B, + 0xF0, 0x3F, 0x42, 0x58, 0x19, 0x48, 0xB2, 0xEE, + 0x4E, 0xE7, 0xAD, 0x67 }, + + /* + * SHA-256 test vectors + */ + { 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 }, + { 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 }, + { 0xCD, 0xC7, 0x6E, 0x5C, 0x99, 0x14, 0xFB, 0x92, + 0x81, 0xA1, 0xC7, 0xE2, 0x84, 0xD7, 0x3E, 0x67, + 0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E, + 0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0 } +}; + +/* + * Checkup routine + */ +int mbedtls_sha256_self_test( int verbose ) +{ + int i, j, k, buflen, ret = 0; + unsigned char *buf; + unsigned char sha256sum[32]; + mbedtls_sha256_context ctx; + + buf = mbedtls_calloc( 1024, sizeof(unsigned char) ); + if( NULL == buf ) + { + if( verbose != 0 ) + mbedtls_printf( "Buffer allocation failed\n" ); + + return( 1 ); + } + + mbedtls_sha256_init( &ctx ); + + for( i = 0; i < 6; i++ ) + { + j = i % 3; + k = i < 3; + + if( verbose != 0 ) + mbedtls_printf( " SHA-%d test #%d: ", 256 - k * 32, j + 1 ); + + if( ( ret = mbedtls_sha256_starts_ret( &ctx, k ) ) != 0 ) + goto fail; + + if( j == 2 ) + { + memset( buf, 'a', buflen = 1000 ); + + for( j = 0; j < 1000; j++ ) + { + ret = mbedtls_sha256_update_ret( &ctx, buf, buflen ); + if( ret != 0 ) + goto fail; + } + + } + else + { + ret = mbedtls_sha256_update_ret( &ctx, sha256_test_buf[j], + sha256_test_buflen[j] ); + if( ret != 0 ) + goto fail; + } + + if( ( ret = mbedtls_sha256_finish_ret( &ctx, sha256sum ) ) != 0 ) + goto fail; + + + if( memcmp( sha256sum, sha256_test_sum[i], 32 - k * 4 ) != 0 ) + { + ret = 1; + goto fail; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + goto exit; + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + +exit: + mbedtls_sha256_free( &ctx ); + mbedtls_free( buf ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_SHA256_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/sha512.c b/Android/Level4/app/src/main/c/mbedtls/library/sha512.c new file mode 100644 index 0000000..e881198 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/sha512.c @@ -0,0 +1,673 @@ +/* + * FIPS-180-2 compliant SHA-384/512 implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ +/* + * The SHA-512 Secure Hash Standard was published by NIST in 2002. + * + * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf + */ + +#include "common.h" + +#if defined(MBEDTLS_SHA512_C) + +#include "mbedtls/sha512.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#if defined(_MSC_VER) || defined(__WATCOMC__) + #define UL64(x) x##ui64 +#else + #define UL64(x) x##ULL +#endif + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#define SHA512_VALIDATE_RET(cond) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_SHA512_BAD_INPUT_DATA ) +#define SHA512_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if !defined(MBEDTLS_SHA512_ALT) + +/* + * 64-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT64_BE +#define GET_UINT64_BE(n,b,i) \ +{ \ + (n) = ( (uint64_t) (b)[(i) ] << 56 ) \ + | ( (uint64_t) (b)[(i) + 1] << 48 ) \ + | ( (uint64_t) (b)[(i) + 2] << 40 ) \ + | ( (uint64_t) (b)[(i) + 3] << 32 ) \ + | ( (uint64_t) (b)[(i) + 4] << 24 ) \ + | ( (uint64_t) (b)[(i) + 5] << 16 ) \ + | ( (uint64_t) (b)[(i) + 6] << 8 ) \ + | ( (uint64_t) (b)[(i) + 7] ); \ +} +#endif /* GET_UINT64_BE */ + +#ifndef PUT_UINT64_BE +#define PUT_UINT64_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 56 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 48 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 40 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) >> 32 ); \ + (b)[(i) + 4] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 5] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 6] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 7] = (unsigned char) ( (n) ); \ +} +#endif /* PUT_UINT64_BE */ + +#if defined(MBEDTLS_SHA512_SMALLER) +static void sha512_put_uint64_be( uint64_t n, unsigned char *b, uint8_t i ) +{ + PUT_UINT64_BE(n, b, i); +} +#else +#define sha512_put_uint64_be PUT_UINT64_BE +#endif /* MBEDTLS_SHA512_SMALLER */ + +void mbedtls_sha512_init( mbedtls_sha512_context *ctx ) +{ + SHA512_VALIDATE( ctx != NULL ); + + memset( ctx, 0, sizeof( mbedtls_sha512_context ) ); +} + +void mbedtls_sha512_free( mbedtls_sha512_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_sha512_context ) ); +} + +void mbedtls_sha512_clone( mbedtls_sha512_context *dst, + const mbedtls_sha512_context *src ) +{ + SHA512_VALIDATE( dst != NULL ); + SHA512_VALIDATE( src != NULL ); + + *dst = *src; +} + +/* + * SHA-512 context setup + */ +int mbedtls_sha512_starts_ret( mbedtls_sha512_context *ctx, int is384 ) +{ + SHA512_VALIDATE_RET( ctx != NULL ); +#if !defined(MBEDTLS_SHA512_NO_SHA384) + SHA512_VALIDATE_RET( is384 == 0 || is384 == 1 ); +#else + SHA512_VALIDATE_RET( is384 == 0 ); +#endif + + ctx->total[0] = 0; + ctx->total[1] = 0; + + if( is384 == 0 ) + { + /* SHA-512 */ + ctx->state[0] = UL64(0x6A09E667F3BCC908); + ctx->state[1] = UL64(0xBB67AE8584CAA73B); + ctx->state[2] = UL64(0x3C6EF372FE94F82B); + ctx->state[3] = UL64(0xA54FF53A5F1D36F1); + ctx->state[4] = UL64(0x510E527FADE682D1); + ctx->state[5] = UL64(0x9B05688C2B3E6C1F); + ctx->state[6] = UL64(0x1F83D9ABFB41BD6B); + ctx->state[7] = UL64(0x5BE0CD19137E2179); + } + else + { +#if defined(MBEDTLS_SHA512_NO_SHA384) + return( MBEDTLS_ERR_SHA512_BAD_INPUT_DATA ); +#else + /* SHA-384 */ + ctx->state[0] = UL64(0xCBBB9D5DC1059ED8); + ctx->state[1] = UL64(0x629A292A367CD507); + ctx->state[2] = UL64(0x9159015A3070DD17); + ctx->state[3] = UL64(0x152FECD8F70E5939); + ctx->state[4] = UL64(0x67332667FFC00B31); + ctx->state[5] = UL64(0x8EB44A8768581511); + ctx->state[6] = UL64(0xDB0C2E0D64F98FA7); + ctx->state[7] = UL64(0x47B5481DBEFA4FA4); +#endif /* MBEDTLS_SHA512_NO_SHA384 */ + } + +#if !defined(MBEDTLS_SHA512_NO_SHA384) + ctx->is384 = is384; +#endif + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, + int is384 ) +{ + mbedtls_sha512_starts_ret( ctx, is384 ); +} +#endif + +#if !defined(MBEDTLS_SHA512_PROCESS_ALT) + +/* + * Round constants + */ +static const uint64_t K[80] = +{ + UL64(0x428A2F98D728AE22), UL64(0x7137449123EF65CD), + UL64(0xB5C0FBCFEC4D3B2F), UL64(0xE9B5DBA58189DBBC), + UL64(0x3956C25BF348B538), UL64(0x59F111F1B605D019), + UL64(0x923F82A4AF194F9B), UL64(0xAB1C5ED5DA6D8118), + UL64(0xD807AA98A3030242), UL64(0x12835B0145706FBE), + UL64(0x243185BE4EE4B28C), UL64(0x550C7DC3D5FFB4E2), + UL64(0x72BE5D74F27B896F), UL64(0x80DEB1FE3B1696B1), + UL64(0x9BDC06A725C71235), UL64(0xC19BF174CF692694), + UL64(0xE49B69C19EF14AD2), UL64(0xEFBE4786384F25E3), + UL64(0x0FC19DC68B8CD5B5), UL64(0x240CA1CC77AC9C65), + UL64(0x2DE92C6F592B0275), UL64(0x4A7484AA6EA6E483), + UL64(0x5CB0A9DCBD41FBD4), UL64(0x76F988DA831153B5), + UL64(0x983E5152EE66DFAB), UL64(0xA831C66D2DB43210), + UL64(0xB00327C898FB213F), UL64(0xBF597FC7BEEF0EE4), + UL64(0xC6E00BF33DA88FC2), UL64(0xD5A79147930AA725), + UL64(0x06CA6351E003826F), UL64(0x142929670A0E6E70), + UL64(0x27B70A8546D22FFC), UL64(0x2E1B21385C26C926), + UL64(0x4D2C6DFC5AC42AED), UL64(0x53380D139D95B3DF), + UL64(0x650A73548BAF63DE), UL64(0x766A0ABB3C77B2A8), + UL64(0x81C2C92E47EDAEE6), UL64(0x92722C851482353B), + UL64(0xA2BFE8A14CF10364), UL64(0xA81A664BBC423001), + UL64(0xC24B8B70D0F89791), UL64(0xC76C51A30654BE30), + UL64(0xD192E819D6EF5218), UL64(0xD69906245565A910), + UL64(0xF40E35855771202A), UL64(0x106AA07032BBD1B8), + UL64(0x19A4C116B8D2D0C8), UL64(0x1E376C085141AB53), + UL64(0x2748774CDF8EEB99), UL64(0x34B0BCB5E19B48A8), + UL64(0x391C0CB3C5C95A63), UL64(0x4ED8AA4AE3418ACB), + UL64(0x5B9CCA4F7763E373), UL64(0x682E6FF3D6B2B8A3), + UL64(0x748F82EE5DEFB2FC), UL64(0x78A5636F43172F60), + UL64(0x84C87814A1F0AB72), UL64(0x8CC702081A6439EC), + UL64(0x90BEFFFA23631E28), UL64(0xA4506CEBDE82BDE9), + UL64(0xBEF9A3F7B2C67915), UL64(0xC67178F2E372532B), + UL64(0xCA273ECEEA26619C), UL64(0xD186B8C721C0C207), + UL64(0xEADA7DD6CDE0EB1E), UL64(0xF57D4F7FEE6ED178), + UL64(0x06F067AA72176FBA), UL64(0x0A637DC5A2C898A6), + UL64(0x113F9804BEF90DAE), UL64(0x1B710B35131C471B), + UL64(0x28DB77F523047D84), UL64(0x32CAAB7B40C72493), + UL64(0x3C9EBE0A15C9BEBC), UL64(0x431D67C49C100D4C), + UL64(0x4CC5D4BECB3E42B6), UL64(0x597F299CFC657E2A), + UL64(0x5FCB6FAB3AD6FAEC), UL64(0x6C44198C4A475817) +}; + +int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx, + const unsigned char data[128] ) +{ + int i; + uint64_t temp1, temp2, W[80]; + uint64_t A[8]; + + SHA512_VALIDATE_RET( ctx != NULL ); + SHA512_VALIDATE_RET( (const unsigned char *)data != NULL ); + +#define SHR(x,n) ((x) >> (n)) +#define ROTR(x,n) (SHR((x),(n)) | ((x) << (64 - (n)))) + +#define S0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7)) +#define S1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x, 6)) + +#define S2(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39)) +#define S3(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41)) + +#define F0(x,y,z) (((x) & (y)) | ((z) & ((x) | (y)))) +#define F1(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) + +#define P(a,b,c,d,e,f,g,h,x,K) \ + do \ + { \ + temp1 = (h) + S3(e) + F1((e),(f),(g)) + (K) + (x); \ + temp2 = S2(a) + F0((a),(b),(c)); \ + (d) += temp1; (h) = temp1 + temp2; \ + } while( 0 ) + + for( i = 0; i < 8; i++ ) + A[i] = ctx->state[i]; + +#if defined(MBEDTLS_SHA512_SMALLER) + for( i = 0; i < 80; i++ ) + { + if( i < 16 ) + { + GET_UINT64_BE( W[i], data, i << 3 ); + } + else + { + W[i] = S1(W[i - 2]) + W[i - 7] + + S0(W[i - 15]) + W[i - 16]; + } + + P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i], K[i] ); + + temp1 = A[7]; A[7] = A[6]; A[6] = A[5]; A[5] = A[4]; A[4] = A[3]; + A[3] = A[2]; A[2] = A[1]; A[1] = A[0]; A[0] = temp1; + } +#else /* MBEDTLS_SHA512_SMALLER */ + for( i = 0; i < 16; i++ ) + { + GET_UINT64_BE( W[i], data, i << 3 ); + } + + for( ; i < 80; i++ ) + { + W[i] = S1(W[i - 2]) + W[i - 7] + + S0(W[i - 15]) + W[i - 16]; + } + + i = 0; + do + { + P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i], K[i] ); i++; + P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], W[i], K[i] ); i++; + P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], W[i], K[i] ); i++; + P( A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], W[i], K[i] ); i++; + P( A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], W[i], K[i] ); i++; + P( A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], W[i], K[i] ); i++; + P( A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], W[i], K[i] ); i++; + P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], W[i], K[i] ); i++; + } + while( i < 80 ); +#endif /* MBEDTLS_SHA512_SMALLER */ + + for( i = 0; i < 8; i++ ) + ctx->state[i] += A[i]; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha512_process( mbedtls_sha512_context *ctx, + const unsigned char data[128] ) +{ + mbedtls_internal_sha512_process( ctx, data ); +} +#endif +#endif /* !MBEDTLS_SHA512_PROCESS_ALT */ + +/* + * SHA-512 process buffer + */ +int mbedtls_sha512_update_ret( mbedtls_sha512_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t fill; + unsigned int left; + + SHA512_VALIDATE_RET( ctx != NULL ); + SHA512_VALIDATE_RET( ilen == 0 || input != NULL ); + + if( ilen == 0 ) + return( 0 ); + + left = (unsigned int) (ctx->total[0] & 0x7F); + fill = 128 - left; + + ctx->total[0] += (uint64_t) ilen; + + if( ctx->total[0] < (uint64_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), input, fill ); + + if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 128 ) + { + if( ( ret = mbedtls_internal_sha512_process( ctx, input ) ) != 0 ) + return( ret ); + + input += 128; + ilen -= 128; + } + + if( ilen > 0 ) + memcpy( (void *) (ctx->buffer + left), input, ilen ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha512_update( mbedtls_sha512_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + mbedtls_sha512_update_ret( ctx, input, ilen ); +} +#endif + +/* + * SHA-512 final digest + */ +int mbedtls_sha512_finish_ret( mbedtls_sha512_context *ctx, + unsigned char output[64] ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned used; + uint64_t high, low; + + SHA512_VALIDATE_RET( ctx != NULL ); + SHA512_VALIDATE_RET( (unsigned char *)output != NULL ); + + /* + * Add padding: 0x80 then 0x00 until 16 bytes remain for the length + */ + used = ctx->total[0] & 0x7F; + + ctx->buffer[used++] = 0x80; + + if( used <= 112 ) + { + /* Enough room for padding + length in current block */ + memset( ctx->buffer + used, 0, 112 - used ); + } + else + { + /* We'll need an extra block */ + memset( ctx->buffer + used, 0, 128 - used ); + + if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + memset( ctx->buffer, 0, 112 ); + } + + /* + * Add message length + */ + high = ( ctx->total[0] >> 61 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + sha512_put_uint64_be( high, ctx->buffer, 112 ); + sha512_put_uint64_be( low, ctx->buffer, 120 ); + + if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + /* + * Output final state + */ + sha512_put_uint64_be( ctx->state[0], output, 0 ); + sha512_put_uint64_be( ctx->state[1], output, 8 ); + sha512_put_uint64_be( ctx->state[2], output, 16 ); + sha512_put_uint64_be( ctx->state[3], output, 24 ); + sha512_put_uint64_be( ctx->state[4], output, 32 ); + sha512_put_uint64_be( ctx->state[5], output, 40 ); + +#if !defined(MBEDTLS_SHA512_NO_SHA384) + if( ctx->is384 == 0 ) +#endif + { + sha512_put_uint64_be( ctx->state[6], output, 48 ); + sha512_put_uint64_be( ctx->state[7], output, 56 ); + } + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, + unsigned char output[64] ) +{ + mbedtls_sha512_finish_ret( ctx, output ); +} +#endif + +#endif /* !MBEDTLS_SHA512_ALT */ + +/* + * output = SHA-512( input buffer ) + */ +int mbedtls_sha512_ret( const unsigned char *input, + size_t ilen, + unsigned char output[64], + int is384 ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_sha512_context ctx; + +#if !defined(MBEDTLS_SHA512_NO_SHA384) + SHA512_VALIDATE_RET( is384 == 0 || is384 == 1 ); +#else + SHA512_VALIDATE_RET( is384 == 0 ); +#endif + SHA512_VALIDATE_RET( ilen == 0 || input != NULL ); + SHA512_VALIDATE_RET( (unsigned char *)output != NULL ); + + mbedtls_sha512_init( &ctx ); + + if( ( ret = mbedtls_sha512_starts_ret( &ctx, is384 ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha512_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha512_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_sha512_free( &ctx ); + + return( ret ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha512( const unsigned char *input, + size_t ilen, + unsigned char output[64], + int is384 ) +{ + mbedtls_sha512_ret( input, ilen, output, is384 ); +} +#endif + +#if defined(MBEDTLS_SELF_TEST) + +/* + * FIPS-180-2 test vectors + */ +static const unsigned char sha512_test_buf[3][113] = +{ + { "abc" }, + { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" }, + { "" } +}; + +static const size_t sha512_test_buflen[3] = +{ + 3, 112, 1000 +}; + +static const unsigned char sha512_test_sum[][64] = +{ +#if !defined(MBEDTLS_SHA512_NO_SHA384) + /* + * SHA-384 test vectors + */ + { 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 }, + { 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 }, + { 0x9D, 0x0E, 0x18, 0x09, 0x71, 0x64, 0x74, 0xCB, + 0x08, 0x6E, 0x83, 0x4E, 0x31, 0x0A, 0x4A, 0x1C, + 0xED, 0x14, 0x9E, 0x9C, 0x00, 0xF2, 0x48, 0x52, + 0x79, 0x72, 0xCE, 0xC5, 0x70, 0x4C, 0x2A, 0x5B, + 0x07, 0xB8, 0xB3, 0xDC, 0x38, 0xEC, 0xC4, 0xEB, + 0xAE, 0x97, 0xDD, 0xD8, 0x7F, 0x3D, 0x89, 0x85 }, +#endif /* !MBEDTLS_SHA512_NO_SHA384 */ + + /* + * SHA-512 test vectors + */ + { 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 }, + { 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 }, + { 0xE7, 0x18, 0x48, 0x3D, 0x0C, 0xE7, 0x69, 0x64, + 0x4E, 0x2E, 0x42, 0xC7, 0xBC, 0x15, 0xB4, 0x63, + 0x8E, 0x1F, 0x98, 0xB1, 0x3B, 0x20, 0x44, 0x28, + 0x56, 0x32, 0xA8, 0x03, 0xAF, 0xA9, 0x73, 0xEB, + 0xDE, 0x0F, 0xF2, 0x44, 0x87, 0x7E, 0xA6, 0x0A, + 0x4C, 0xB0, 0x43, 0x2C, 0xE5, 0x77, 0xC3, 0x1B, + 0xEB, 0x00, 0x9C, 0x5C, 0x2C, 0x49, 0xAA, 0x2E, + 0x4E, 0xAD, 0xB2, 0x17, 0xAD, 0x8C, 0xC0, 0x9B } +}; + +#define ARRAY_LENGTH( a ) ( sizeof( a ) / sizeof( ( a )[0] ) ) + +/* + * Checkup routine + */ +int mbedtls_sha512_self_test( int verbose ) +{ + int i, j, k, buflen, ret = 0; + unsigned char *buf; + unsigned char sha512sum[64]; + mbedtls_sha512_context ctx; + + buf = mbedtls_calloc( 1024, sizeof(unsigned char) ); + if( NULL == buf ) + { + if( verbose != 0 ) + mbedtls_printf( "Buffer allocation failed\n" ); + + return( 1 ); + } + + mbedtls_sha512_init( &ctx ); + + for( i = 0; i < (int) ARRAY_LENGTH(sha512_test_sum); i++ ) + { + j = i % 3; +#if !defined(MBEDTLS_SHA512_NO_SHA384) + k = i < 3; +#else + k = 0; +#endif + + if( verbose != 0 ) + mbedtls_printf( " SHA-%d test #%d: ", 512 - k * 128, j + 1 ); + + if( ( ret = mbedtls_sha512_starts_ret( &ctx, k ) ) != 0 ) + goto fail; + + if( j == 2 ) + { + memset( buf, 'a', buflen = 1000 ); + + for( j = 0; j < 1000; j++ ) + { + ret = mbedtls_sha512_update_ret( &ctx, buf, buflen ); + if( ret != 0 ) + goto fail; + } + } + else + { + ret = mbedtls_sha512_update_ret( &ctx, sha512_test_buf[j], + sha512_test_buflen[j] ); + if( ret != 0 ) + goto fail; + } + + if( ( ret = mbedtls_sha512_finish_ret( &ctx, sha512sum ) ) != 0 ) + goto fail; + + if( memcmp( sha512sum, sha512_test_sum[i], 64 - k * 16 ) != 0 ) + { + ret = 1; + goto fail; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + goto exit; + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + +exit: + mbedtls_sha512_free( &ctx ); + mbedtls_free( buf ); + + return( ret ); +} + +#undef ARRAY_LENGTH + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_SHA512_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/ssl_cache.c b/Android/Level4/app/src/main/c/mbedtls/library/ssl_cache.c new file mode 100644 index 0000000..7e9d4da --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/ssl_cache.c @@ -0,0 +1,347 @@ +/* + * SSL session cache implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ +/* + * These session callbacks use a simple chained list + * to store and retrieve the session information. + */ + +#include "common.h" + +#if defined(MBEDTLS_SSL_CACHE_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/ssl_cache.h" +#include "mbedtls/ssl_internal.h" + +#include + +void mbedtls_ssl_cache_init( mbedtls_ssl_cache_context *cache ) +{ + memset( cache, 0, sizeof( mbedtls_ssl_cache_context ) ); + + cache->timeout = MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT; + cache->max_entries = MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES; + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &cache->mutex ); +#endif +} + +int mbedtls_ssl_cache_get( void *data, mbedtls_ssl_session *session ) +{ + int ret = 1; +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t t = mbedtls_time( NULL ); +#endif + mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data; + mbedtls_ssl_cache_entry *cur, *entry; + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_lock( &cache->mutex ) != 0 ) + return( 1 ); +#endif + + cur = cache->chain; + entry = NULL; + + while( cur != NULL ) + { + entry = cur; + cur = cur->next; + +#if defined(MBEDTLS_HAVE_TIME) + if( cache->timeout != 0 && + (int) ( t - entry->timestamp ) > cache->timeout ) + continue; +#endif + + if( session->ciphersuite != entry->session.ciphersuite || + session->compression != entry->session.compression || + session->id_len != entry->session.id_len ) + continue; + + if( memcmp( session->id, entry->session.id, + entry->session.id_len ) != 0 ) + continue; + + ret = mbedtls_ssl_session_copy( session, &entry->session ); + if( ret != 0 ) + { + ret = 1; + goto exit; + } + +#if defined(MBEDTLS_X509_CRT_PARSE_C) && \ + defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + /* + * Restore peer certificate (without rest of the original chain) + */ + if( entry->peer_cert.p != NULL ) + { + /* `session->peer_cert` is NULL after the call to + * mbedtls_ssl_session_copy(), because cache entries + * have the `peer_cert` field set to NULL. */ + + if( ( session->peer_cert = mbedtls_calloc( 1, + sizeof(mbedtls_x509_crt) ) ) == NULL ) + { + ret = 1; + goto exit; + } + + mbedtls_x509_crt_init( session->peer_cert ); + if( mbedtls_x509_crt_parse( session->peer_cert, entry->peer_cert.p, + entry->peer_cert.len ) != 0 ) + { + mbedtls_free( session->peer_cert ); + session->peer_cert = NULL; + ret = 1; + goto exit; + } + } +#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + + ret = 0; + goto exit; + } + +exit: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &cache->mutex ) != 0 ) + ret = 1; +#endif + + return( ret ); +} + +int mbedtls_ssl_cache_set( void *data, const mbedtls_ssl_session *session ) +{ + int ret = 1; +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t t = mbedtls_time( NULL ), oldest = 0; + mbedtls_ssl_cache_entry *old = NULL; +#endif + mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data; + mbedtls_ssl_cache_entry *cur, *prv; + int count = 0; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &cache->mutex ) ) != 0 ) + return( ret ); +#endif + + cur = cache->chain; + prv = NULL; + + while( cur != NULL ) + { + count++; + +#if defined(MBEDTLS_HAVE_TIME) + if( cache->timeout != 0 && + (int) ( t - cur->timestamp ) > cache->timeout ) + { + cur->timestamp = t; + break; /* expired, reuse this slot, update timestamp */ + } +#endif + + if( memcmp( session->id, cur->session.id, cur->session.id_len ) == 0 ) + break; /* client reconnected, keep timestamp for session id */ + +#if defined(MBEDTLS_HAVE_TIME) + if( oldest == 0 || cur->timestamp < oldest ) + { + oldest = cur->timestamp; + old = cur; + } +#endif + + prv = cur; + cur = cur->next; + } + + if( cur == NULL ) + { +#if defined(MBEDTLS_HAVE_TIME) + /* + * Reuse oldest entry if max_entries reached + */ + if( count >= cache->max_entries ) + { + if( old == NULL ) + { + ret = 1; + goto exit; + } + + cur = old; + } +#else /* MBEDTLS_HAVE_TIME */ + /* + * Reuse first entry in chain if max_entries reached, + * but move to last place + */ + if( count >= cache->max_entries ) + { + if( cache->chain == NULL ) + { + ret = 1; + goto exit; + } + + cur = cache->chain; + cache->chain = cur->next; + cur->next = NULL; + prv->next = cur; + } +#endif /* MBEDTLS_HAVE_TIME */ + else + { + /* + * max_entries not reached, create new entry + */ + cur = mbedtls_calloc( 1, sizeof(mbedtls_ssl_cache_entry) ); + if( cur == NULL ) + { + ret = 1; + goto exit; + } + + if( prv == NULL ) + cache->chain = cur; + else + prv->next = cur; + } + +#if defined(MBEDTLS_HAVE_TIME) + cur->timestamp = t; +#endif + } + +#if defined(MBEDTLS_X509_CRT_PARSE_C) && \ + defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + /* + * If we're reusing an entry, free its certificate first + */ + if( cur->peer_cert.p != NULL ) + { + mbedtls_free( cur->peer_cert.p ); + memset( &cur->peer_cert, 0, sizeof(mbedtls_x509_buf) ); + } +#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + + /* Copy the entire session; this temporarily makes a copy of the + * X.509 CRT structure even though we only want to store the raw CRT. + * This inefficiency will go away as soon as we implement on-demand + * parsing of CRTs, in which case there's no need for the `peer_cert` + * field anymore in the first place, and we're done after this call. */ + ret = mbedtls_ssl_session_copy( &cur->session, session ); + if( ret != 0 ) + { + ret = 1; + goto exit; + } + +#if defined(MBEDTLS_X509_CRT_PARSE_C) && \ + defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + /* If present, free the X.509 structure and only store the raw CRT data. */ + if( cur->session.peer_cert != NULL ) + { + cur->peer_cert.p = + mbedtls_calloc( 1, cur->session.peer_cert->raw.len ); + if( cur->peer_cert.p == NULL ) + { + ret = 1; + goto exit; + } + + memcpy( cur->peer_cert.p, + cur->session.peer_cert->raw.p, + cur->session.peer_cert->raw.len ); + cur->peer_cert.len = session->peer_cert->raw.len; + + mbedtls_x509_crt_free( cur->session.peer_cert ); + mbedtls_free( cur->session.peer_cert ); + cur->session.peer_cert = NULL; + } +#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + + ret = 0; + +exit: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &cache->mutex ) != 0 ) + ret = 1; +#endif + + return( ret ); +} + +#if defined(MBEDTLS_HAVE_TIME) +void mbedtls_ssl_cache_set_timeout( mbedtls_ssl_cache_context *cache, int timeout ) +{ + if( timeout < 0 ) timeout = 0; + + cache->timeout = timeout; +} +#endif /* MBEDTLS_HAVE_TIME */ + +void mbedtls_ssl_cache_set_max_entries( mbedtls_ssl_cache_context *cache, int max ) +{ + if( max < 0 ) max = 0; + + cache->max_entries = max; +} + +void mbedtls_ssl_cache_free( mbedtls_ssl_cache_context *cache ) +{ + mbedtls_ssl_cache_entry *cur, *prv; + + cur = cache->chain; + + while( cur != NULL ) + { + prv = cur; + cur = cur->next; + + mbedtls_ssl_session_free( &prv->session ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) && \ + defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + mbedtls_free( prv->peer_cert.p ); +#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + + mbedtls_free( prv ); + } + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free( &cache->mutex ); +#endif + cache->chain = NULL; +} + +#endif /* MBEDTLS_SSL_CACHE_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/ssl_ciphersuites.c b/Android/Level4/app/src/main/c/mbedtls/library/ssl_ciphersuites.c new file mode 100644 index 0000000..6985fe5 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/ssl_ciphersuites.c @@ -0,0 +1,2367 @@ +/** + * \file ssl_ciphersuites.c + * + * \brief SSL ciphersuites for mbed TLS + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 "common.h" + +#if defined(MBEDTLS_SSL_TLS_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#endif + +#include "mbedtls/ssl_ciphersuites.h" +#include "mbedtls/ssl.h" + +#include + +/* + * Ordered from most preferred to least preferred in terms of security. + * + * Current rule (except RC4 and 3DES, weak and null which come last): + * 1. By key exchange: + * Forward-secure non-PSK > forward-secure PSK > ECJPAKE > other non-PSK > other PSK + * 2. By key length and cipher: + * ChaCha > AES-256 > Camellia-256 > ARIA-256 > AES-128 > Camellia-128 > ARIA-128 + * 3. By cipher mode when relevant GCM > CCM > CBC > CCM_8 + * 4. By hash function used when relevant + * 5. By key exchange/auth again: EC > non-EC + */ +static const int ciphersuite_preference[] = +{ +#if defined(MBEDTLS_SSL_CIPHERSUITES) + MBEDTLS_SSL_CIPHERSUITES, +#else + /* Chacha-Poly ephemeral suites */ + MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + + /* All AES-256 ephemeral suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM, + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8, + + /* All CAMELLIA-256 ephemeral suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, + + /* All ARIA-256 ephemeral suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384, + MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384, + MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384, + + /* All AES-128 ephemeral suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM, + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8, + + /* All CAMELLIA-128 ephemeral suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, + + /* All ARIA-128 ephemeral suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256, + MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256, + + /* The PSK ephemeral suites */ + MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM, + MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8, + MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384, + MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384, + + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM, + MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8, + MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256, + + /* The ECJPAKE suite */ + MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8, + + /* All AES-256 suites */ + MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_RSA_WITH_AES_256_CCM, + MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256, + MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8, + + /* All CAMELLIA-256 suites */ + MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256, + MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, + MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, + + /* All ARIA-256 suites */ + MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384, + MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384, + MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384, + + /* All AES-128 suites */ + MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_RSA_WITH_AES_128_CCM, + MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8, + + /* All CAMELLIA-128 suites */ + MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, + MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, + + /* All ARIA-128 suites */ + MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256, + MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256, + MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256, + + /* The RSA PSK suites */ + MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256, + MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384, + + MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256, + + /* The PSK suites */ + MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256, + MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_PSK_WITH_AES_256_CCM, + MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8, + MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384, + + MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_PSK_WITH_AES_128_CCM, + MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8, + MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256, + + /* 3DES suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA, + + /* RC4 suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, + MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA, + MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA, + MBEDTLS_TLS_RSA_WITH_RC4_128_SHA, + MBEDTLS_TLS_RSA_WITH_RC4_128_MD5, + MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA, + MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA, + MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA, + MBEDTLS_TLS_PSK_WITH_RC4_128_SHA, + + /* Weak suites */ + MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA, + MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA, + + /* NULL suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA, + MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA, + MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384, + MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256, + MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384, + MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA, + + MBEDTLS_TLS_RSA_WITH_NULL_SHA256, + MBEDTLS_TLS_RSA_WITH_NULL_SHA, + MBEDTLS_TLS_RSA_WITH_NULL_MD5, + MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA, + MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA, + MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384, + MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256, + MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA, + MBEDTLS_TLS_PSK_WITH_NULL_SHA384, + MBEDTLS_TLS_PSK_WITH_NULL_SHA256, + MBEDTLS_TLS_PSK_WITH_NULL_SHA, + +#endif /* MBEDTLS_SSL_CIPHERSUITES */ + 0 +}; + +static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] = +{ +#if defined(MBEDTLS_CHACHAPOLY_C) && \ + defined(MBEDTLS_SHA256_C) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) + { MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + "TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + "TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) + { MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + "TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + { MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256, + "TLS-PSK-WITH-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + { MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256, + "TLS-ECDHE-PSK-WITH-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + { MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256, + "TLS-DHE-PSK-WITH-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + { MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256, + "TLS-RSA-PSK-WITH-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#endif /* MBEDTLS_CHACHAPOLY_C && + MBEDTLS_SHA256_C && + MBEDTLS_SSL_PROTO_TLS1_2 */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, "TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, "TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA512_C */ +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM, "TLS-ECDHE-ECDSA-WITH-AES-256-CCM", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, "TLS-ECDHE-ECDSA-WITH-AES-256-CCM-8", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM, "TLS-ECDHE-ECDSA-WITH-AES-128-CCM", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, "TLS-ECDHE-ECDSA-WITH-AES-128-CCM-8", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, "TLS-ECDHE-ECDSA-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA, "TLS-ECDHE-ECDSA-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, "TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, "TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-RSA-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-RSA-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDHE-RSA-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDHE-RSA-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA, "TLS-ECDHE-RSA-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA, "TLS-ECDHE-RSA-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_SHA512_C) && defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, "TLS-DHE-RSA-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C && MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, "TLS-DHE-RSA-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, "TLS-DHE-RSA-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, "TLS-DHE-RSA-WITH-AES-256-CBC-SHA256", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA, "TLS-DHE-RSA-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA, "TLS-DHE-RSA-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM, "TLS-DHE-RSA-WITH-AES-256-CCM", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8, "TLS-DHE-RSA-WITH-AES-256-CCM-8", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, + { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM, "TLS-DHE-RSA-WITH-AES-128-CCM", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8, "TLS-DHE-RSA-WITH-AES-128-CCM-8", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-DHE-RSA-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_SHA512_C) && defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384, "TLS-RSA-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C && MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256, "TLS-RSA-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256, "TLS-RSA-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256, "TLS-RSA-WITH-AES-256-CBC-SHA256", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA, "TLS-RSA-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA, "TLS-RSA-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_TLS_RSA_WITH_AES_256_CCM, "TLS-RSA-WITH-AES-256-CCM", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8, "TLS-RSA-WITH-AES-256-CCM-8", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, + { MBEDTLS_TLS_RSA_WITH_AES_128_CCM, "TLS-RSA-WITH-AES-128-CCM", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8, "TLS-RSA-WITH-AES-128-CCM-8", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256, "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-RSA-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-RSA-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-RSA-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_MD5_C) + { MBEDTLS_TLS_RSA_WITH_RC4_128_MD5, "TLS-RSA-WITH-RC4-128-MD5", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_MD5, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_WITH_RC4_128_SHA, "TLS-RSA-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif +#endif /* MBEDTLS_ARC4_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, "TLS-ECDH-RSA-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, "TLS-ECDH-RSA-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDH-RSA-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDH-RSA-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDH-RSA-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDH-RSA-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDH-RSA-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA, "TLS-ECDH-RSA-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA, "TLS-ECDH-RSA-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, "TLS-ECDH-ECDSA-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, "TLS-ECDH-ECDSA-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDH-ECDSA-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA, "TLS-ECDH-ECDSA-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA, "TLS-ECDH-ECDSA-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256, "TLS-PSK-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384, "TLS-PSK-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256, "TLS-PSK-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384, "TLS-PSK-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA, "TLS-PSK-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA, "TLS-PSK-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_TLS_PSK_WITH_AES_256_CCM, "TLS-PSK-WITH-AES-256-CCM", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8, "TLS-PSK-WITH-AES-256-CCM-8", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, + { MBEDTLS_TLS_PSK_WITH_AES_128_CCM, "TLS-PSK-WITH-AES-128-CCM", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8, "TLS-PSK-WITH-AES-128-CCM-8", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-PSK-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-PSK-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-PSK-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-PSK-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-PSK-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_PSK_WITH_RC4_128_SHA, "TLS-PSK-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, "TLS-DHE-PSK-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, "TLS-DHE-PSK-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, "TLS-DHE-PSK-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, "TLS-DHE-PSK-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA, "TLS-DHE-PSK-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA, "TLS-DHE-PSK-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM, "TLS-DHE-PSK-WITH-AES-256-CCM", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8, "TLS-DHE-PSK-WITH-AES-256-CCM-8", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, + { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM, "TLS-DHE-PSK-WITH-AES-128-CCM", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8, "TLS-DHE-PSK-WITH-AES-128-CCM-8", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-DHE-PSK-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-DHE-PSK-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-DHE-PSK-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-DHE-PSK-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-DHE-PSK-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA, "TLS-DHE-PSK-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +#if defined(MBEDTLS_AES_C) + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, "TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, "TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-PSK-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-PSK-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-ECDHE-PSK-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA, "TLS-ECDHE-PSK-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, "TLS-RSA-PSK-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384, "TLS-RSA-PSK-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, "TLS-RSA-PSK-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, "TLS-RSA-PSK-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA, "TLS-RSA-PSK-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA, "TLS-RSA-PSK-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-RSA-PSK-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-RSA-PSK-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-RSA-PSK-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-RSA-PSK-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-RSA-PSK-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA, "TLS-RSA-PSK-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8, "TLS-ECJPAKE-WITH-AES-128-CCM-8", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECJPAKE, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_ENABLE_WEAK_CIPHERSUITES) +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) +#if defined(MBEDTLS_MD5_C) + { MBEDTLS_TLS_RSA_WITH_NULL_MD5, "TLS-RSA-WITH-NULL-MD5", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_MD5, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_WITH_NULL_SHA, "TLS-RSA-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif + +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_WITH_NULL_SHA256, "TLS-RSA-WITH-NULL-SHA256", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_PSK_WITH_NULL_SHA, "TLS-PSK-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ + +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_PSK_WITH_NULL_SHA256, "TLS-PSK-WITH-NULL-SHA256", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_PSK_WITH_NULL_SHA384, "TLS-PSK-WITH-NULL-SHA384", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA, "TLS-DHE-PSK-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ + +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256, "TLS-DHE-PSK-WITH-NULL-SHA256", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384, "TLS-DHE-PSK-WITH-NULL-SHA384", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA, "TLS-ECDHE-PSK-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ + +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256, "TLS-ECDHE-PSK-WITH-NULL-SHA256", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384, "TLS-ECDHE-PSK-WITH-NULL-SHA384", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA, "TLS-RSA-PSK-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ + +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256, "TLS-RSA-PSK-WITH-NULL-SHA256", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif + +#if defined(MBEDTLS_SHA512_C) + { MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384, "TLS-RSA-PSK-WITH-NULL-SHA384", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA, "TLS-DHE-RSA-WITH-DES-CBC-SHA", + MBEDTLS_CIPHER_DES_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA, "TLS-RSA-WITH-DES-CBC-SHA", + MBEDTLS_CIPHER_DES_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ +#endif /* MBEDTLS_ENABLE_WEAK_CIPHERSUITES */ + +#if defined(MBEDTLS_ARIA_C) + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384, + "TLS-RSA-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384, + "TLS-RSA-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256, + "TLS-RSA-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256, + "TLS-RSA-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384, + "TLS-RSA-PSK-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384, + "TLS-RSA-PSK-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256, + "TLS-RSA-PSK-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256, + "TLS-RSA-PSK-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384, + "TLS-PSK-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384,MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384, + "TLS-PSK-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256, + "TLS-PSK-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256, + "TLS-PSK-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384, + "TLS-ECDH-RSA-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384, + "TLS-ECDH-RSA-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256, + "TLS-ECDH-RSA-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256, + "TLS-ECDH-RSA-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384, + "TLS-ECDHE-RSA-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384, + "TLS-ECDHE-RSA-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256, + "TLS-ECDHE-RSA-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256, + "TLS-ECDHE-RSA-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384, + "TLS-ECDHE-PSK-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256, + "TLS-ECDHE-PSK-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384, + "TLS-ECDHE-ECDSA-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384, + "TLS-ECDHE-ECDSA-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256, + "TLS-ECDHE-ECDSA-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256, + "TLS-ECDHE-ECDSA-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384, + "TLS-ECDH-ECDSA-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384, + "TLS-ECDH-ECDSA-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256, + "TLS-ECDH-ECDSA-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256, + "TLS-ECDH-ECDSA-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384, + "TLS-DHE-RSA-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384, + "TLS-DHE-RSA-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256, + "TLS-DHE-RSA-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256, + "TLS-DHE-RSA-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384, + "TLS-DHE-PSK-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384, + "TLS-DHE-PSK-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256, + "TLS-DHE-PSK-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256, + "TLS-DHE-PSK-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ + +#endif /* MBEDTLS_ARIA_C */ + + + { 0, "", + MBEDTLS_CIPHER_NONE, MBEDTLS_MD_NONE, MBEDTLS_KEY_EXCHANGE_NONE, + 0, 0, 0, 0, 0 } +}; + +#if defined(MBEDTLS_SSL_CIPHERSUITES) +const int *mbedtls_ssl_list_ciphersuites( void ) +{ + return( ciphersuite_preference ); +} +#else +#define MAX_CIPHERSUITES sizeof( ciphersuite_definitions ) / \ + sizeof( ciphersuite_definitions[0] ) +static int supported_ciphersuites[MAX_CIPHERSUITES]; +static int supported_init = 0; + +static int ciphersuite_is_removed( const mbedtls_ssl_ciphersuite_t *cs_info ) +{ + (void)cs_info; + +#if defined(MBEDTLS_REMOVE_ARC4_CIPHERSUITES) + if( cs_info->cipher == MBEDTLS_CIPHER_ARC4_128 ) + return( 1 ); +#endif /* MBEDTLS_REMOVE_ARC4_CIPHERSUITES */ + +#if defined(MBEDTLS_REMOVE_3DES_CIPHERSUITES) + if( cs_info->cipher == MBEDTLS_CIPHER_DES_EDE3_ECB || + cs_info->cipher == MBEDTLS_CIPHER_DES_EDE3_CBC ) + { + return( 1 ); + } +#endif /* MBEDTLS_REMOVE_3DES_CIPHERSUITES */ + + return( 0 ); +} + +const int *mbedtls_ssl_list_ciphersuites( void ) +{ + /* + * On initial call filter out all ciphersuites not supported by current + * build based on presence in the ciphersuite_definitions. + */ + if( supported_init == 0 ) + { + const int *p; + int *q; + + for( p = ciphersuite_preference, q = supported_ciphersuites; + *p != 0 && q < supported_ciphersuites + MAX_CIPHERSUITES - 1; + p++ ) + { + const mbedtls_ssl_ciphersuite_t *cs_info; + if( ( cs_info = mbedtls_ssl_ciphersuite_from_id( *p ) ) != NULL && + !ciphersuite_is_removed( cs_info ) ) + { + *(q++) = *p; + } + } + *q = 0; + + supported_init = 1; + } + + return( supported_ciphersuites ); +} +#endif /* MBEDTLS_SSL_CIPHERSUITES */ + +const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_string( + const char *ciphersuite_name ) +{ + const mbedtls_ssl_ciphersuite_t *cur = ciphersuite_definitions; + + if( NULL == ciphersuite_name ) + return( NULL ); + + while( cur->id != 0 ) + { + if( 0 == strcmp( cur->name, ciphersuite_name ) ) + return( cur ); + + cur++; + } + + return( NULL ); +} + +const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_id( int ciphersuite ) +{ + const mbedtls_ssl_ciphersuite_t *cur = ciphersuite_definitions; + + while( cur->id != 0 ) + { + if( cur->id == ciphersuite ) + return( cur ); + + cur++; + } + + return( NULL ); +} + +const char *mbedtls_ssl_get_ciphersuite_name( const int ciphersuite_id ) +{ + const mbedtls_ssl_ciphersuite_t *cur; + + cur = mbedtls_ssl_ciphersuite_from_id( ciphersuite_id ); + + if( cur == NULL ) + return( "unknown" ); + + return( cur->name ); +} + +int mbedtls_ssl_get_ciphersuite_id( const char *ciphersuite_name ) +{ + const mbedtls_ssl_ciphersuite_t *cur; + + cur = mbedtls_ssl_ciphersuite_from_string( ciphersuite_name ); + + if( cur == NULL ) + return( 0 ); + + return( cur->id ); +} + +#if defined(MBEDTLS_PK_C) +mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_pk_alg( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_RSA: + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_RSA_PSK: + return( MBEDTLS_PK_RSA ); + + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + return( MBEDTLS_PK_ECDSA ); + + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + return( MBEDTLS_PK_ECKEY ); + + default: + return( MBEDTLS_PK_NONE ); + } +} + +mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_alg( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_RSA: + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + return( MBEDTLS_PK_RSA ); + + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + return( MBEDTLS_PK_ECDSA ); + + default: + return( MBEDTLS_PK_NONE ); + } +} + +#endif /* MBEDTLS_PK_C */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +int mbedtls_ssl_ciphersuite_uses_ec( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + case MBEDTLS_KEY_EXCHANGE_ECJPAKE: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED*/ + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) +int mbedtls_ssl_ciphersuite_uses_psk( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_PSK: + case MBEDTLS_KEY_EXCHANGE_RSA_PSK: + case MBEDTLS_KEY_EXCHANGE_DHE_PSK: + case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ + +#endif /* MBEDTLS_SSL_TLS_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/ssl_cli.c b/Android/Level4/app/src/main/c/mbedtls/library/ssl_cli.c new file mode 100644 index 0000000..76be8ab --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/ssl_cli.c @@ -0,0 +1,4542 @@ +/* + * SSLv3/TLSv1 client-side functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 "common.h" + +#if defined(MBEDTLS_SSL_CLI_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/ssl.h" +#include "mbedtls/ssl_internal.h" +#include "mbedtls/debug.h" +#include "mbedtls/error.h" + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "mbedtls/psa_util.h" +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#include + +#include + +#if defined(MBEDTLS_HAVE_TIME) +#include "mbedtls/platform_time.h" +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +#include "mbedtls/platform_util.h" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) +static int ssl_conf_has_static_psk( mbedtls_ssl_config const *conf ) +{ + if( conf->psk_identity == NULL || + conf->psk_identity_len == 0 ) + { + return( 0 ); + } + + if( conf->psk != NULL && conf->psk_len != 0 ) + return( 1 ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( conf->psk_opaque != 0 ) + return( 1 ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + return( 0 ); +} + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +static int ssl_conf_has_static_raw_psk( mbedtls_ssl_config const *conf ) +{ + if( conf->psk_identity == NULL || + conf->psk_identity_len == 0 ) + { + return( 0 ); + } + + if( conf->psk != NULL && conf->psk_len != 0 ) + return( 1 ); + + return( 0 ); +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +static int ssl_write_hostname_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + size_t hostname_len; + + *olen = 0; + + if( ssl->hostname == NULL ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding server name extension: %s", + ssl->hostname ) ); + + hostname_len = strlen( ssl->hostname ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, hostname_len + 9 ); + + /* + * Sect. 3, RFC 6066 (TLS Extensions Definitions) + * + * In order to provide any of the server names, clients MAY include an + * extension of type "server_name" in the (extended) client hello. The + * "extension_data" field of this extension SHALL contain + * "ServerNameList" where: + * + * struct { + * NameType name_type; + * select (name_type) { + * case host_name: HostName; + * } name; + * } ServerName; + * + * enum { + * host_name(0), (255) + * } NameType; + * + * opaque HostName<1..2^16-1>; + * + * struct { + * ServerName server_name_list<1..2^16-1> + * } ServerNameList; + * + */ + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SERVERNAME >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SERVERNAME ) & 0xFF ); + + *p++ = (unsigned char)( ( (hostname_len + 5) >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( (hostname_len + 5) ) & 0xFF ); + + *p++ = (unsigned char)( ( (hostname_len + 3) >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( (hostname_len + 3) ) & 0xFF ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME ) & 0xFF ); + *p++ = (unsigned char)( ( hostname_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( hostname_len ) & 0xFF ); + + memcpy( p, ssl->hostname, hostname_len ); + + *olen = hostname_len + 9; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +static int ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + + *olen = 0; + + /* We're always including an TLS_EMPTY_RENEGOTIATION_INFO_SCSV in the + * initial ClientHello, in which case also adding the renegotiation + * info extension is NOT RECOMMENDED as per RFC 5746 Section 3.4. */ + if( ssl->renego_status != MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding renegotiation extension" ) ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 5 + ssl->verify_data_len ); + + /* + * Secure renegotiation + */ + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO >> 8 ) + & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO ) + & 0xFF ); + + *p++ = 0x00; + *p++ = ( ssl->verify_data_len + 1 ) & 0xFF; + *p++ = ssl->verify_data_len & 0xFF; + + memcpy( p, ssl->own_verify_data, ssl->verify_data_len ); + + *olen = 5 + ssl->verify_data_len; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +/* + * Only if we handle at least one key exchange that needs signatures. + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) +static int ssl_write_signature_algorithms_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + size_t sig_alg_len = 0; + const int *md; + +#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_C) + unsigned char *sig_alg_list = buf + 6; +#endif + + *olen = 0; + + if( ssl->conf->max_minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding signature_algorithms extension" ) ); + + if( ssl->conf->sig_hashes == NULL ) + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); + + for( md = ssl->conf->sig_hashes; *md != MBEDTLS_MD_NONE; md++ ) + { +#if defined(MBEDTLS_ECDSA_C) + sig_alg_len += 2; +#endif +#if defined(MBEDTLS_RSA_C) + sig_alg_len += 2; +#endif + if( sig_alg_len > MBEDTLS_SSL_MAX_SIG_HASH_ALG_LIST_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "length in bytes of sig-hash-alg extension too big" ) ); + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); + } + } + + /* Empty signature algorithms list, this is a configuration error. */ + if( sig_alg_len == 0 ) + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, sig_alg_len + 6 ); + + /* + * Prepare signature_algorithms extension (TLS 1.2) + */ + sig_alg_len = 0; + + for( md = ssl->conf->sig_hashes; *md != MBEDTLS_MD_NONE; md++ ) + { +#if defined(MBEDTLS_ECDSA_C) + sig_alg_list[sig_alg_len++] = mbedtls_ssl_hash_from_md_alg( *md ); + sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_ECDSA; +#endif +#if defined(MBEDTLS_RSA_C) + sig_alg_list[sig_alg_len++] = mbedtls_ssl_hash_from_md_alg( *md ); + sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_RSA; +#endif + } + + /* + * enum { + * none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5), + * sha512(6), (255) + * } HashAlgorithm; + * + * enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) } + * SignatureAlgorithm; + * + * struct { + * HashAlgorithm hash; + * SignatureAlgorithm signature; + * } SignatureAndHashAlgorithm; + * + * SignatureAndHashAlgorithm + * supported_signature_algorithms<2..2^16-2>; + */ + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SIG_ALG >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SIG_ALG ) & 0xFF ); + + *p++ = (unsigned char)( ( ( sig_alg_len + 2 ) >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( ( sig_alg_len + 2 ) ) & 0xFF ); + + *p++ = (unsigned char)( ( sig_alg_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( sig_alg_len ) & 0xFF ); + + *olen = 6 + sig_alg_len; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static int ssl_write_supported_elliptic_curves_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + unsigned char *elliptic_curve_list = p + 6; + size_t elliptic_curve_len = 0; + const mbedtls_ecp_curve_info *info; + const mbedtls_ecp_group_id *grp_id; + + *olen = 0; + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding supported_elliptic_curves extension" ) ); + + if( ssl->conf->curve_list == NULL ) + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); + + for( grp_id = ssl->conf->curve_list; + *grp_id != MBEDTLS_ECP_DP_NONE; + grp_id++ ) + { + info = mbedtls_ecp_curve_info_from_grp_id( *grp_id ); + if( info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "invalid curve in ssl configuration" ) ); + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); + } + elliptic_curve_len += 2; + + if( elliptic_curve_len > MBEDTLS_SSL_MAX_CURVE_LIST_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "malformed supported_elliptic_curves extension in config" ) ); + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); + } + } + + /* Empty elliptic curve list, this is a configuration error. */ + if( elliptic_curve_len == 0 ) + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 6 + elliptic_curve_len ); + + elliptic_curve_len = 0; + + for( grp_id = ssl->conf->curve_list; + *grp_id != MBEDTLS_ECP_DP_NONE; + grp_id++ ) + { + info = mbedtls_ecp_curve_info_from_grp_id( *grp_id ); + elliptic_curve_list[elliptic_curve_len++] = info->tls_id >> 8; + elliptic_curve_list[elliptic_curve_len++] = info->tls_id & 0xFF; + } + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES >> 8 ) + & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES ) + & 0xFF ); + + *p++ = (unsigned char)( ( ( elliptic_curve_len + 2 ) >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( ( elliptic_curve_len + 2 ) ) & 0xFF ); + + *p++ = (unsigned char)( ( ( elliptic_curve_len ) >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( ( elliptic_curve_len ) ) & 0xFF ); + + *olen = 6 + elliptic_curve_len; + + return( 0 ); +} + +static int ssl_write_supported_point_formats_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + (void) ssl; /* ssl used for debugging only */ + + *olen = 0; + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding supported_point_formats extension" ) ); + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 6 ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS >> 8 ) + & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS ) + & 0xFF ); + + *p++ = 0x00; + *p++ = 2; + + *p++ = 1; + *p++ = MBEDTLS_ECP_PF_UNCOMPRESSED; + + *olen = 6; + + return( 0 ); +} +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || + MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static int ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = buf; + size_t kkpp_len; + + *olen = 0; + + /* Skip costly extension if we can't use EC J-PAKE anyway */ + if( mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding ecjpake_kkpp extension" ) ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 4 ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ECJPAKE_KKPP >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ECJPAKE_KKPP ) & 0xFF ); + + /* + * We may need to send ClientHello multiple times for Hello verification. + * We don't want to compute fresh values every time (both for performance + * and consistency reasons), so cache the extension content. + */ + if( ssl->handshake->ecjpake_cache == NULL || + ssl->handshake->ecjpake_cache_len == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "generating new ecjpake parameters" ) ); + + ret = mbedtls_ecjpake_write_round_one( &ssl->handshake->ecjpake_ctx, + p + 2, end - p - 2, &kkpp_len, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1 , + "mbedtls_ecjpake_write_round_one", ret ); + return( ret ); + } + + ssl->handshake->ecjpake_cache = mbedtls_calloc( 1, kkpp_len ); + if( ssl->handshake->ecjpake_cache == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "allocation failed" ) ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + memcpy( ssl->handshake->ecjpake_cache, p + 2, kkpp_len ); + ssl->handshake->ecjpake_cache_len = kkpp_len; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "re-using cached ecjpake parameters" ) ); + + kkpp_len = ssl->handshake->ecjpake_cache_len; + MBEDTLS_SSL_CHK_BUF_PTR( p + 2, end, kkpp_len ); + + memcpy( p + 2, ssl->handshake->ecjpake_cache, kkpp_len ); + } + + *p++ = (unsigned char)( ( kkpp_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( kkpp_len ) & 0xFF ); + + *olen = kkpp_len + 4; + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) +static int ssl_write_cid_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + size_t ext_len; + + /* + * Quoting draft-ietf-tls-dtls-connection-id-05 + * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05 + * + * struct { + * opaque cid<0..2^8-1>; + * } ConnectionId; + */ + + *olen = 0; + if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM || + ssl->negotiate_cid == MBEDTLS_SSL_CID_DISABLED ) + { + return( 0 ); + } + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding CID extension" ) ); + + /* ssl->own_cid_len is at most MBEDTLS_SSL_CID_IN_LEN_MAX + * which is at most 255, so the increment cannot overflow. */ + MBEDTLS_SSL_CHK_BUF_PTR( p, end, (unsigned)( ssl->own_cid_len + 5 ) ); + + /* Add extension ID + size */ + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_CID >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_CID ) & 0xFF ); + ext_len = (size_t) ssl->own_cid_len + 1; + *p++ = (unsigned char)( ( ext_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( ext_len ) & 0xFF ); + + *p++ = (uint8_t) ssl->own_cid_len; + memcpy( p, ssl->own_cid, ssl->own_cid_len ); + + *olen = ssl->own_cid_len + 5; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +static int ssl_write_max_fragment_length_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + + *olen = 0; + + if( ssl->conf->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding max_fragment_length extension" ) ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 5 ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH >> 8 ) + & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH ) + & 0xFF ); + + *p++ = 0x00; + *p++ = 1; + + *p++ = ssl->conf->mfl_code; + + *olen = 5; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) +static int ssl_write_truncated_hmac_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + + *olen = 0; + + if( ssl->conf->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_DISABLED ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding truncated_hmac extension" ) ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 4 ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_TRUNCATED_HMAC >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_TRUNCATED_HMAC ) & 0xFF ); + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +static int ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + + *olen = 0; + + if( ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED || + ssl->conf->max_minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding encrypt_then_mac extension" ) ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 4 ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC ) & 0xFF ); + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +static int ssl_write_extended_ms_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + + *olen = 0; + + if( ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED || + ssl->conf->max_minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding extended_master_secret extension" ) ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 4 ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET >> 8 ) + & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET ) + & 0xFF ); + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +static int ssl_write_session_ticket_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + size_t tlen = ssl->session_negotiate->ticket_len; + + *olen = 0; + + if( ssl->conf->session_tickets == MBEDTLS_SSL_SESSION_TICKETS_DISABLED ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding session ticket extension" ) ); + + /* The addition is safe here since the ticket length is 16 bit. */ + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 4 + tlen ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SESSION_TICKET >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SESSION_TICKET ) & 0xFF ); + + *p++ = (unsigned char)( ( tlen >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( tlen ) & 0xFF ); + + *olen = 4; + + if( ssl->session_negotiate->ticket == NULL || tlen == 0 ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "sending session ticket of length %d", tlen ) ); + + memcpy( p, ssl->session_negotiate->ticket, tlen ); + + *olen += tlen; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_SSL_ALPN) +static int ssl_write_alpn_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + size_t alpnlen = 0; + const char **cur; + + *olen = 0; + + if( ssl->conf->alpn_list == NULL ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding alpn extension" ) ); + + for( cur = ssl->conf->alpn_list; *cur != NULL; cur++ ) + alpnlen += strlen( *cur ) + 1; + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 6 + alpnlen ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ALPN >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ALPN ) & 0xFF ); + + /* + * opaque ProtocolName<1..2^8-1>; + * + * struct { + * ProtocolName protocol_name_list<2..2^16-1> + * } ProtocolNameList; + */ + + /* Skip writing extension and list length for now */ + p += 4; + + for( cur = ssl->conf->alpn_list; *cur != NULL; cur++ ) + { + /* + * mbedtls_ssl_conf_set_alpn_protocols() checked that the length of + * protocol names is less than 255. + */ + *p = (unsigned char)strlen( *cur ); + memcpy( p + 1, *cur, *p ); + p += 1 + *p; + } + + *olen = p - buf; + + /* List length = olen - 2 (ext_type) - 2 (ext_len) - 2 (list_len) */ + buf[4] = (unsigned char)( ( ( *olen - 6 ) >> 8 ) & 0xFF ); + buf[5] = (unsigned char)( ( ( *olen - 6 ) ) & 0xFF ); + + /* Extension length = olen - 2 (ext_type) - 2 (ext_len) */ + buf[2] = (unsigned char)( ( ( *olen - 4 ) >> 8 ) & 0xFF ); + buf[3] = (unsigned char)( ( ( *olen - 4 ) ) & 0xFF ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_ALPN */ + +#if defined(MBEDTLS_SSL_DTLS_SRTP) +static int ssl_write_use_srtp_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + size_t protection_profiles_index = 0, ext_len = 0; + uint16_t mki_len = 0, profile_value = 0; + + *olen = 0; + + if( ( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ) || + ( ssl->conf->dtls_srtp_profile_list == NULL ) || + ( ssl->conf->dtls_srtp_profile_list_len == 0 ) ) + { + return( 0 ); + } + + /* RFC 5764 section 4.1.1 + * uint8 SRTPProtectionProfile[2]; + * + * struct { + * SRTPProtectionProfiles SRTPProtectionProfiles; + * opaque srtp_mki<0..255>; + * } UseSRTPData; + * SRTPProtectionProfile SRTPProtectionProfiles<2..2^16-1>; + */ + if( ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED ) + { + mki_len = ssl->dtls_srtp_info.mki_len; + } + /* Extension length = 2 bytes for profiles length, + * ssl->conf->dtls_srtp_profile_list_len * 2 (each profile is 2 bytes length ), + * 1 byte for srtp_mki vector length and the mki_len value + */ + ext_len = 2 + 2 * ( ssl->conf->dtls_srtp_profile_list_len ) + 1 + mki_len; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding use_srtp extension" ) ); + + /* Check there is room in the buffer for the extension + 4 bytes + * - the extension tag (2 bytes) + * - the extension length (2 bytes) + */ + MBEDTLS_SSL_CHK_BUF_PTR( p, end, ext_len + 4 ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_USE_SRTP >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_USE_SRTP ) & 0xFF ); + + + *p++ = (unsigned char)( ( ( ext_len & 0xFF00 ) >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ext_len & 0xFF ); + + /* protection profile length: 2*(ssl->conf->dtls_srtp_profile_list_len) */ + /* micro-optimization: + * the list size is limited to MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH + * which is lower than 127, so the upper byte of the length is always 0 + * For the documentation, the more generic code is left in comments + * *p++ = (unsigned char)( ( ( 2 * ssl->conf->dtls_srtp_profile_list_len ) + * >> 8 ) & 0xFF ); + */ + *p++ = 0; + *p++ = (unsigned char)( ( 2 * ssl->conf->dtls_srtp_profile_list_len ) + & 0xFF ); + + for( protection_profiles_index=0; + protection_profiles_index < ssl->conf->dtls_srtp_profile_list_len; + protection_profiles_index++ ) + { + profile_value = mbedtls_ssl_check_srtp_profile_value + ( ssl->conf->dtls_srtp_profile_list[protection_profiles_index] ); + if( profile_value != MBEDTLS_TLS_SRTP_UNSET ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_write_use_srtp_ext, add profile: %04x", + profile_value ) ); + *p++ = ( ( profile_value >> 8 ) & 0xFF ); + *p++ = ( profile_value & 0xFF ); + } + else + { + /* + * Note: we shall never arrive here as protection profiles + * is checked by mbedtls_ssl_conf_dtls_srtp_protection_profiles function + */ + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, " + "illegal DTLS-SRTP protection profile %d", + ssl->conf->dtls_srtp_profile_list[protection_profiles_index] + ) ); + return( MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED ); + } + } + + *p++ = mki_len & 0xFF; + + if( mki_len != 0 ) + { + memcpy( p, ssl->dtls_srtp_info.mki_value, mki_len ); + /* + * Increment p to point to the current position. + */ + p += mki_len; + MBEDTLS_SSL_DEBUG_BUF( 3, "sending mki", ssl->dtls_srtp_info.mki_value, + ssl->dtls_srtp_info.mki_len ); + } + + /* + * total extension length: extension type (2 bytes) + * + extension length (2 bytes) + * + protection profile length (2 bytes) + * + 2 * number of protection profiles + * + srtp_mki vector length(1 byte) + * + mki value + */ + *olen = p - buf; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_DTLS_SRTP */ + +/* + * Generate random bytes for ClientHello + */ +static int ssl_generate_random( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = ssl->handshake->randbytes; +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t t; +#endif + + /* + * When responding to a verify request, MUST reuse random (RFC 6347 4.2.1) + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake->verify_cookie != NULL ) + { + return( 0 ); + } +#endif + +#if defined(MBEDTLS_HAVE_TIME) + t = mbedtls_time( NULL ); + *p++ = (unsigned char)( t >> 24 ); + *p++ = (unsigned char)( t >> 16 ); + *p++ = (unsigned char)( t >> 8 ); + *p++ = (unsigned char)( t ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, current time: %lu", t ) ); +#else + if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 4 ) ) != 0 ) + return( ret ); + + p += 4; +#endif /* MBEDTLS_HAVE_TIME */ + + if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 28 ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +/** + * \brief Validate cipher suite against config in SSL context. + * + * \param suite_info cipher suite to validate + * \param ssl SSL context + * \param min_minor_ver Minimal minor version to accept a cipher suite + * \param max_minor_ver Maximal minor version to accept a cipher suite + * + * \return 0 if valid, else 1 + */ +static int ssl_validate_ciphersuite( + const mbedtls_ssl_ciphersuite_t * suite_info, + const mbedtls_ssl_context * ssl, + int min_minor_ver, int max_minor_ver ) +{ + (void) ssl; + if( suite_info == NULL ) + return( 1 ); + + if( suite_info->min_minor_ver > max_minor_ver || + suite_info->max_minor_ver < min_minor_ver ) + return( 1 ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ( suite_info->flags & MBEDTLS_CIPHERSUITE_NODTLS ) ) + return( 1 ); +#endif + +#if defined(MBEDTLS_ARC4_C) + if( ssl->conf->arc4_disabled == MBEDTLS_SSL_ARC4_DISABLED && + suite_info->cipher == MBEDTLS_CIPHER_ARC4_128 ) + return( 1 ); +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE && + mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 ) + return( 1 ); +#endif + + /* Don't suggest PSK-based ciphersuite if no PSK is available. */ +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) + if( mbedtls_ssl_ciphersuite_uses_psk( suite_info ) && + ssl_conf_has_static_psk( ssl->conf ) == 0 ) + { + return( 1 ); + } +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ + + return( 0 ); +} + +static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i, n, olen, ext_len = 0; + + unsigned char *buf; + unsigned char *p, *q; + const unsigned char *end; + + unsigned char offer_compress; + const int *ciphersuites; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + int uses_ec = 0; +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write client hello" ) ); + + if( ssl->conf->f_rng == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "no RNG provided") ); + return( MBEDTLS_ERR_SSL_NO_RNG ); + } + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE ) +#endif + { + ssl->major_ver = ssl->conf->min_major_ver; + ssl->minor_ver = ssl->conf->min_minor_ver; + } + + if( ssl->conf->max_major_ver == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "configured max major version is invalid, consider using mbedtls_ssl_config_defaults()" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + buf = ssl->out_msg; + end = buf + MBEDTLS_SSL_OUT_CONTENT_LEN; + + /* + * Check if there's enough space for the first part of the ClientHello + * consisting of the 38 bytes described below, the session identifier (at + * most 32 bytes) and its length (1 byte). + * + * Use static upper bounds instead of the actual values + * to allow the compiler to optimize this away. + */ + MBEDTLS_SSL_CHK_BUF_PTR( buf, end, 38 + 1 + 32 ); + + /* + * The 38 first bytes of the ClientHello: + * 0 . 0 handshake type (written later) + * 1 . 3 handshake length (written later) + * 4 . 5 highest version supported + * 6 . 9 current UNIX time + * 10 . 37 random bytes + * + * The current UNIX time (4 bytes) and following 28 random bytes are written + * by ssl_generate_random() into ssl->handshake->randbytes buffer and then + * copied from there into the output buffer. + */ + + p = buf + 4; + mbedtls_ssl_write_version( ssl->conf->max_major_ver, + ssl->conf->max_minor_ver, + ssl->conf->transport, p ); + p += 2; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, max version: [%d:%d]", + buf[4], buf[5] ) ); + + if( ( ret = ssl_generate_random( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_generate_random", ret ); + return( ret ); + } + + memcpy( p, ssl->handshake->randbytes, 32 ); + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, random bytes", p, 32 ); + p += 32; + + /* + * 38 . 38 session id length + * 39 . 39+n session id + * 39+n . 39+n DTLS only: cookie length (1 byte) + * 40+n . .. DTLS only: cookie + * .. . .. ciphersuitelist length (2 bytes) + * .. . .. ciphersuitelist + * .. . .. compression methods length (1 byte) + * .. . .. compression methods + * .. . .. extensions length (2 bytes) + * .. . .. extensions + */ + n = ssl->session_negotiate->id_len; + + if( n < 16 || n > 32 || +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE || +#endif + ssl->handshake->resume == 0 ) + { + n = 0; + } + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + /* + * RFC 5077 section 3.4: "When presenting a ticket, the client MAY + * generate and include a Session ID in the TLS ClientHello." + */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE ) +#endif + { + if( ssl->session_negotiate->ticket != NULL && + ssl->session_negotiate->ticket_len != 0 ) + { + ret = ssl->conf->f_rng( ssl->conf->p_rng, + ssl->session_negotiate->id, 32 ); + + if( ret != 0 ) + return( ret ); + + ssl->session_negotiate->id_len = n = 32; + } + } +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + + /* + * The first check of the output buffer size above ( + * MBEDTLS_SSL_CHK_BUF_PTR( buf, end, 38 + 1 + 32 );) + * has checked that there is enough space in the output buffer for the + * session identifier length byte and the session identifier (n <= 32). + */ + *p++ = (unsigned char) n; + + for( i = 0; i < n; i++ ) + *p++ = ssl->session_negotiate->id[i]; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, session id len.: %d", n ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, session id", buf + 39, n ); + + /* + * With 'n' being the length of the session identifier + * + * 39+n . 39+n DTLS only: cookie length (1 byte) + * 40+n . .. DTLS only: cookie + * .. . .. ciphersuitelist length (2 bytes) + * .. . .. ciphersuitelist + * .. . .. compression methods length (1 byte) + * .. . .. compression methods + * .. . .. extensions length (2 bytes) + * .. . .. extensions + */ + + /* + * DTLS cookie + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 1 ); + + if( ssl->handshake->verify_cookie == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "no verify cookie to send" ) ); + *p++ = 0; + } + else + { + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, cookie", + ssl->handshake->verify_cookie, + ssl->handshake->verify_cookie_len ); + + *p++ = ssl->handshake->verify_cookie_len; + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, + ssl->handshake->verify_cookie_len ); + memcpy( p, ssl->handshake->verify_cookie, + ssl->handshake->verify_cookie_len ); + p += ssl->handshake->verify_cookie_len; + } + } +#endif + + /* + * Ciphersuite list + */ + ciphersuites = ssl->conf->ciphersuite_list[ssl->minor_ver]; + + /* Skip writing ciphersuite length for now */ + n = 0; + q = p; + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); + p += 2; + + for( i = 0; ciphersuites[i] != 0; i++ ) + { + ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( ciphersuites[i] ); + + if( ssl_validate_ciphersuite( ciphersuite_info, ssl, + ssl->conf->min_minor_ver, + ssl->conf->max_minor_ver ) != 0 ) + continue; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, add ciphersuite: %#04x (%s)", + ciphersuites[i], ciphersuite_info->name ) ); + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + uses_ec |= mbedtls_ssl_ciphersuite_uses_ec( ciphersuite_info ); +#endif + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); + + n++; + *p++ = (unsigned char)( ciphersuites[i] >> 8 ); + *p++ = (unsigned char)( ciphersuites[i] ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, got %d ciphersuites (excluding SCSVs)", n ) ); + + /* + * Add TLS_EMPTY_RENEGOTIATION_INFO_SCSV + */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE ) +#endif + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "adding EMPTY_RENEGOTIATION_INFO_SCSV" ) ); + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); + *p++ = (unsigned char)( MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO >> 8 ); + *p++ = (unsigned char)( MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO ); + n++; + } + + /* Some versions of OpenSSL don't handle it correctly if not at end */ +#if defined(MBEDTLS_SSL_FALLBACK_SCSV) + if( ssl->conf->fallback == MBEDTLS_SSL_IS_FALLBACK ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "adding FALLBACK_SCSV" ) ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); + *p++ = (unsigned char)( MBEDTLS_SSL_FALLBACK_SCSV_VALUE >> 8 ); + *p++ = (unsigned char)( MBEDTLS_SSL_FALLBACK_SCSV_VALUE ); + n++; + } +#endif + + *q++ = (unsigned char)( n >> 7 ); + *q++ = (unsigned char)( n << 1 ); + +#if defined(MBEDTLS_ZLIB_SUPPORT) + offer_compress = 1; +#else + offer_compress = 0; +#endif + + /* + * We don't support compression with DTLS right now: if many records come + * in the same datagram, uncompressing one could overwrite the next one. + * We don't want to add complexity for handling that case unless there is + * an actual need for it. + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + offer_compress = 0; +#endif + + if( offer_compress ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress len.: %d", 2 ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress alg.: %d %d", + MBEDTLS_SSL_COMPRESS_DEFLATE, + MBEDTLS_SSL_COMPRESS_NULL ) ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 3 ); + *p++ = 2; + *p++ = MBEDTLS_SSL_COMPRESS_DEFLATE; + *p++ = MBEDTLS_SSL_COMPRESS_NULL; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress len.: %d", 1 ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress alg.: %d", + MBEDTLS_SSL_COMPRESS_NULL ) ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); + *p++ = 1; + *p++ = MBEDTLS_SSL_COMPRESS_NULL; + } + + /* First write extensions, then the total length */ + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if( ( ret = ssl_write_hostname_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_hostname_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + + /* Note that TLS_EMPTY_RENEGOTIATION_INFO_SCSV is always added + * even if MBEDTLS_SSL_RENEGOTIATION is not defined. */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ( ret = ssl_write_renegotiation_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_renegotiation_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + if( ( ret = ssl_write_signature_algorithms_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_signature_algorithms_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( uses_ec ) + { + if( ( ret = ssl_write_supported_elliptic_curves_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_supported_elliptic_curves_ext", ret ); + return( ret ); + } + ext_len += olen; + + if( ( ret = ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_supported_point_formats_ext", ret ); + return( ret ); + } + ext_len += olen; + } +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( ( ret = ssl_write_ecjpake_kkpp_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_ecjpake_kkpp_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + if( ( ret = ssl_write_cid_ext( ssl, p + 2 + ext_len, end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_cid_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + if( ( ret = ssl_write_max_fragment_length_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_max_fragment_length_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + if( ( ret = ssl_write_truncated_hmac_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_truncated_hmac_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + if( ( ret = ssl_write_encrypt_then_mac_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_encrypt_then_mac_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + if( ( ret = ssl_write_extended_ms_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_extended_ms_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_ALPN) + if( ( ret = ssl_write_alpn_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_alpn_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_DTLS_SRTP) + if( ( ret = ssl_write_use_srtp_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_use_srtp_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + if( ( ret = ssl_write_session_ticket_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_session_ticket_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + + /* olen unused if all extensions are disabled */ + ((void) olen); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, total extension length: %d", + ext_len ) ); + + if( ext_len > 0 ) + { + /* No need to check for space here, because the extension + * writing functions already took care of that. */ + *p++ = (unsigned char)( ( ext_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( ext_len ) & 0xFF ); + p += ext_len; + } + + ssl->out_msglen = p - buf; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_CLIENT_HELLO; + + ssl->state++; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + mbedtls_ssl_send_flight_completed( ssl ); +#endif + + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret ); + return( ret ); + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write client hello" ) ); + + return( 0 ); +} + +static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) + { + /* Check verify-data in constant-time. The length OTOH is no secret */ + if( len != 1 + ssl->verify_data_len * 2 || + buf[0] != ssl->verify_data_len * 2 || + mbedtls_ssl_safer_memcmp( buf + 1, + ssl->own_verify_data, ssl->verify_data_len ) != 0 || + mbedtls_ssl_safer_memcmp( buf + 1 + ssl->verify_data_len, + ssl->peer_verify_data, ssl->verify_data_len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching renegotiation info" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + } + else +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + { + if( len != 1 || buf[0] != 0x00 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "non-zero length renegotiation info" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; + } + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +static int ssl_parse_max_fragment_length_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + /* + * server should use the extension only if we did, + * and if so the server's value should match ours (and len is always 1) + */ + if( ssl->conf->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE || + len != 1 || + buf[0] != ssl->conf->mfl_code ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "non-matching max fragment length extension" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + return( 0 ); +} +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) +static int ssl_parse_truncated_hmac_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( ssl->conf->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_DISABLED || + len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "non-matching truncated HMAC extension" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + ((void) buf); + + ssl->session_negotiate->trunc_hmac = MBEDTLS_SSL_TRUNC_HMAC_ENABLED; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) +static int ssl_parse_cid_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + size_t peer_cid_len; + + if( /* CID extension only makes sense in DTLS */ + ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM || + /* The server must only send the CID extension if we have offered it. */ + ssl->negotiate_cid == MBEDTLS_SSL_CID_DISABLED ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "CID extension unexpected" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + if( len == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "CID extension invalid" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + peer_cid_len = *buf++; + len--; + + if( peer_cid_len > MBEDTLS_SSL_CID_OUT_LEN_MAX ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "CID extension invalid" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + if( len != peer_cid_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "CID extension invalid" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + ssl->handshake->cid_in_use = MBEDTLS_SSL_CID_ENABLED; + ssl->handshake->peer_cid_len = (uint8_t) peer_cid_len; + memcpy( ssl->handshake->peer_cid, buf, peer_cid_len ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Use of CID extension negotiated" ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "Server CID", buf, peer_cid_len ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +static int ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED || + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 || + len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "non-matching encrypt-then-MAC extension" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + ((void) buf); + + ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +static int ssl_parse_extended_ms_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED || + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 || + len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "non-matching extended master secret extension" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + ((void) buf); + + ssl->handshake->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +static int ssl_parse_session_ticket_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( ssl->conf->session_tickets == MBEDTLS_SSL_SESSION_TICKETS_DISABLED || + len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "non-matching session ticket extension" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + ((void) buf); + + ssl->handshake->new_session_ticket = 1; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static int ssl_parse_supported_point_formats_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + size_t list_size; + const unsigned char *p; + + if( len == 0 || (size_t)( buf[0] + 1 ) != len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + list_size = buf[0]; + + p = buf + 1; + while( list_size > 0 ) + { + if( p[0] == MBEDTLS_ECP_PF_UNCOMPRESSED || + p[0] == MBEDTLS_ECP_PF_COMPRESSED ) + { +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) + ssl->handshake->ecdh_ctx.point_format = p[0]; +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + ssl->handshake->ecjpake_ctx.point_format = p[0]; +#endif + MBEDTLS_SSL_DEBUG_MSG( 4, ( "point format selected: %d", p[0] ) ); + return( 0 ); + } + + list_size--; + p++; + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "no point format in common" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); +} +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || + MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ssl->handshake->ciphersuite_info->key_exchange != + MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip ecjpake kkpp extension" ) ); + return( 0 ); + } + + /* If we got here, we no longer need our cached extension */ + mbedtls_free( ssl->handshake->ecjpake_cache ); + ssl->handshake->ecjpake_cache = NULL; + ssl->handshake->ecjpake_cache_len = 0; + + if( ( ret = mbedtls_ecjpake_read_round_one( &ssl->handshake->ecjpake_ctx, + buf, len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_one", ret ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_ALPN) +static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + size_t list_len, name_len; + const char **p; + + /* If we didn't send it, the server shouldn't send it */ + if( ssl->conf->alpn_list == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching ALPN extension" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + /* + * opaque ProtocolName<1..2^8-1>; + * + * struct { + * ProtocolName protocol_name_list<2..2^16-1> + * } ProtocolNameList; + * + * the "ProtocolNameList" MUST contain exactly one "ProtocolName" + */ + + /* Min length is 2 (list_len) + 1 (name_len) + 1 (name) */ + if( len < 4 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + list_len = ( buf[0] << 8 ) | buf[1]; + if( list_len != len - 2 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + name_len = buf[2]; + if( name_len != list_len - 1 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + /* Check that the server chosen protocol was in our list and save it */ + for( p = ssl->conf->alpn_list; *p != NULL; p++ ) + { + if( name_len == strlen( *p ) && + memcmp( buf + 3, *p, name_len ) == 0 ) + { + ssl->alpn_chosen = *p; + return( 0 ); + } + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "ALPN extension: no matching protocol" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); +} +#endif /* MBEDTLS_SSL_ALPN */ + +#if defined(MBEDTLS_SSL_DTLS_SRTP) +static int ssl_parse_use_srtp_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + mbedtls_ssl_srtp_profile server_protection = MBEDTLS_TLS_SRTP_UNSET; + size_t i, mki_len = 0; + uint16_t server_protection_profile_value = 0; + + /* If use_srtp is not configured, just ignore the extension */ + if( ( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ) || + ( ssl->conf->dtls_srtp_profile_list == NULL ) || + ( ssl->conf->dtls_srtp_profile_list_len == 0 ) ) + return( 0 ); + + /* RFC 5764 section 4.1.1 + * uint8 SRTPProtectionProfile[2]; + * + * struct { + * SRTPProtectionProfiles SRTPProtectionProfiles; + * opaque srtp_mki<0..255>; + * } UseSRTPData; + + * SRTPProtectionProfile SRTPProtectionProfiles<2..2^16-1>; + * + */ + if( ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED ) + { + mki_len = ssl->dtls_srtp_info.mki_len; + } + + /* + * Length is 5 + optional mki_value : one protection profile length (2 bytes) + * + protection profile (2 bytes) + * + mki_len(1 byte) + * and optional srtp_mki + */ + if( ( len < 5 ) || ( len != ( buf[4] + 5u ) ) ) + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + + /* + * get the server protection profile + */ + + /* + * protection profile length must be 0x0002 as we must have only + * one protection profile in server Hello + */ + if( ( buf[0] != 0 ) || ( buf[1] != 2 ) ) + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + + server_protection_profile_value = ( buf[2] << 8 ) | buf[3]; + server_protection = mbedtls_ssl_check_srtp_profile_value( + server_protection_profile_value ); + if( server_protection != MBEDTLS_TLS_SRTP_UNSET ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found srtp profile: %s", + mbedtls_ssl_get_srtp_profile_as_string( + server_protection ) ) ); + } + + ssl->dtls_srtp_info.chosen_dtls_srtp_profile = MBEDTLS_TLS_SRTP_UNSET; + + /* + * Check we have the server profile in our list + */ + for( i=0; i < ssl->conf->dtls_srtp_profile_list_len; i++) + { + if( server_protection == ssl->conf->dtls_srtp_profile_list[i] ) + { + ssl->dtls_srtp_info.chosen_dtls_srtp_profile = ssl->conf->dtls_srtp_profile_list[i]; + MBEDTLS_SSL_DEBUG_MSG( 3, ( "selected srtp profile: %s", + mbedtls_ssl_get_srtp_profile_as_string( + server_protection ) ) ); + break; + } + } + + /* If no match was found : server problem, it shall never answer with incompatible profile */ + if( ssl->dtls_srtp_info.chosen_dtls_srtp_profile == MBEDTLS_TLS_SRTP_UNSET ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + /* If server does not use mki in its reply, make sure the client won't keep + * one as negotiated */ + if( len == 5 ) + { + ssl->dtls_srtp_info.mki_len = 0; + } + + /* + * RFC5764: + * If the client detects a nonzero-length MKI in the server's response + * that is different than the one the client offered, then the client + * MUST abort the handshake and SHOULD send an invalid_parameter alert. + */ + if( len > 5 && ( buf[4] != mki_len || + ( memcmp( ssl->dtls_srtp_info.mki_value, &buf[5], mki_len ) ) ) ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } +#if defined (MBEDTLS_DEBUG_C) + if( len > 5 ) + { + MBEDTLS_SSL_DEBUG_BUF( 3, "received mki", ssl->dtls_srtp_info.mki_value, + ssl->dtls_srtp_info.mki_len ); + } +#endif + return( 0 ); +} +#endif /* MBEDTLS_SSL_DTLS_SRTP */ + +/* + * Parse HelloVerifyRequest. Only called after verifying the HS type. + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) +static int ssl_parse_hello_verify_request( mbedtls_ssl_context *ssl ) +{ + const unsigned char *p = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); + int major_ver, minor_ver; + unsigned char cookie_len; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse hello verify request" ) ); + + /* Check that there is enough room for: + * - 2 bytes of version + * - 1 byte of cookie_len + */ + if( mbedtls_ssl_hs_hdr_len( ssl ) + 3 > ssl->in_msglen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "incoming HelloVerifyRequest message is too short" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + /* + * struct { + * ProtocolVersion server_version; + * opaque cookie<0..2^8-1>; + * } HelloVerifyRequest; + */ + MBEDTLS_SSL_DEBUG_BUF( 3, "server version", p, 2 ); + mbedtls_ssl_read_version( &major_ver, &minor_ver, ssl->conf->transport, p ); + p += 2; + + /* + * Since the RFC is not clear on this point, accept DTLS 1.0 (TLS 1.1) + * even is lower than our min version. + */ + if( major_ver < MBEDTLS_SSL_MAJOR_VERSION_3 || + minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 || + major_ver > ssl->conf->max_major_ver || + minor_ver > ssl->conf->max_minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server version" ) ); + + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); + + return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION ); + } + + cookie_len = *p++; + if( ( ssl->in_msg + ssl->in_msglen ) - p < cookie_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "cookie length does not match incoming message size" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + MBEDTLS_SSL_DEBUG_BUF( 3, "cookie", p, cookie_len ); + + mbedtls_free( ssl->handshake->verify_cookie ); + + ssl->handshake->verify_cookie = mbedtls_calloc( 1, cookie_len ); + if( ssl->handshake->verify_cookie == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc failed (%d bytes)", cookie_len ) ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + memcpy( ssl->handshake->verify_cookie, p, cookie_len ); + ssl->handshake->verify_cookie_len = cookie_len; + + /* Start over at ClientHello */ + ssl->state = MBEDTLS_SSL_CLIENT_HELLO; + mbedtls_ssl_reset_checksum( ssl ); + + mbedtls_ssl_recv_flight_completed( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse hello verify request" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) +{ + int ret, i; + size_t n; + size_t ext_len; + unsigned char *buf, *ext; + unsigned char comp; +#if defined(MBEDTLS_ZLIB_SUPPORT) + int accept_comp; +#endif +#if defined(MBEDTLS_SSL_RENEGOTIATION) + int renegotiation_info_seen = 0; +#endif + int handshake_failure = 0; + const mbedtls_ssl_ciphersuite_t *suite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server hello" ) ); + + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) + { + /* No alert on a read error. */ + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + buf = ssl->in_msg; + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + { + ssl->renego_records_seen++; + + if( ssl->conf->renego_max_records >= 0 && + ssl->renego_records_seen > ssl->conf->renego_max_records ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "renegotiation requested, but not honored by server" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "non-handshake message during renegotiation" ) ); + + ssl->keep_current_message = 1; + return( MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO ); + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + if( buf[0] == MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "received hello verify request" ) ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server hello" ) ); + return( ssl_parse_hello_verify_request( ssl ) ); + } + else + { + /* We made it through the verification process */ + mbedtls_free( ssl->handshake->verify_cookie ); + ssl->handshake->verify_cookie = NULL; + ssl->handshake->verify_cookie_len = 0; + } + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + if( ssl->in_hslen < 38 + mbedtls_ssl_hs_hdr_len( ssl ) || + buf[0] != MBEDTLS_SSL_HS_SERVER_HELLO ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + /* + * 0 . 1 server_version + * 2 . 33 random (maybe including 4 bytes of Unix time) + * 34 . 34 session_id length = n + * 35 . 34+n session_id + * 35+n . 36+n cipher_suite + * 37+n . 37+n compression_method + * + * 38+n . 39+n extensions length (optional) + * 40+n . .. extensions + */ + buf += mbedtls_ssl_hs_hdr_len( ssl ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, version", buf + 0, 2 ); + mbedtls_ssl_read_version( &ssl->major_ver, &ssl->minor_ver, + ssl->conf->transport, buf + 0 ); + + if( ssl->major_ver < ssl->conf->min_major_ver || + ssl->minor_ver < ssl->conf->min_minor_ver || + ssl->major_ver > ssl->conf->max_major_ver || + ssl->minor_ver > ssl->conf->max_minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "server version out of bounds - min: [%d:%d], server: [%d:%d], max: [%d:%d]", + ssl->conf->min_major_ver, + ssl->conf->min_minor_ver, + ssl->major_ver, ssl->minor_ver, + ssl->conf->max_major_ver, + ssl->conf->max_minor_ver ) ); + + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); + + return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu", + ( (uint32_t) buf[2] << 24 ) | + ( (uint32_t) buf[3] << 16 ) | + ( (uint32_t) buf[4] << 8 ) | + ( (uint32_t) buf[5] ) ) ); + + memcpy( ssl->handshake->randbytes + 32, buf + 2, 32 ); + + n = buf[34]; + + MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, random bytes", buf + 2, 32 ); + + if( n > 32 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + if( ssl->in_hslen > mbedtls_ssl_hs_hdr_len( ssl ) + 39 + n ) + { + ext_len = ( ( buf[38 + n] << 8 ) + | ( buf[39 + n] ) ); + + if( ( ext_len > 0 && ext_len < 4 ) || + ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + 40 + n + ext_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + } + else if( ssl->in_hslen == mbedtls_ssl_hs_hdr_len( ssl ) + 38 + n ) + { + ext_len = 0; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + /* ciphersuite (used later) */ + i = ( buf[35 + n] << 8 ) | buf[36 + n]; + + /* + * Read and check compression + */ + comp = buf[37 + n]; + +#if defined(MBEDTLS_ZLIB_SUPPORT) + /* See comments in ssl_write_client_hello() */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + accept_comp = 0; + else +#endif + accept_comp = 1; + + if( comp != MBEDTLS_SSL_COMPRESS_NULL && + ( comp != MBEDTLS_SSL_COMPRESS_DEFLATE || accept_comp == 0 ) ) +#else /* MBEDTLS_ZLIB_SUPPORT */ + if( comp != MBEDTLS_SSL_COMPRESS_NULL ) +#endif/* MBEDTLS_ZLIB_SUPPORT */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "server hello, bad compression: %d", comp ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + + /* + * Initialize update checksum functions + */ + ssl->handshake->ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( i ); + if( ssl->handshake->ciphersuite_info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "ciphersuite info for %04x not found", i ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + mbedtls_ssl_optimize_checksum( ssl, ssl->handshake->ciphersuite_info ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %d", n ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, session id", buf + 35, n ); + + /* + * Check if the session can be resumed + */ + if( ssl->handshake->resume == 0 || n == 0 || +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE || +#endif + ssl->session_negotiate->ciphersuite != i || + ssl->session_negotiate->compression != comp || + ssl->session_negotiate->id_len != n || + memcmp( ssl->session_negotiate->id, buf + 35, n ) != 0 ) + { + ssl->state++; + ssl->handshake->resume = 0; +#if defined(MBEDTLS_HAVE_TIME) + ssl->session_negotiate->start = mbedtls_time( NULL ); +#endif + ssl->session_negotiate->ciphersuite = i; + ssl->session_negotiate->compression = comp; + ssl->session_negotiate->id_len = n; + memcpy( ssl->session_negotiate->id, buf + 35, n ); + } + else + { + ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC; + + if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + return( ret ); + } + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "%s session has been resumed", + ssl->handshake->resume ? "a" : "no" ) ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %04x", i ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: %d", + buf[37 + n] ) ); + + /* + * Perform cipher suite validation in same way as in ssl_write_client_hello. + */ + i = 0; + while( 1 ) + { + if( ssl->conf->ciphersuite_list[ssl->minor_ver][i] == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + if( ssl->conf->ciphersuite_list[ssl->minor_ver][i++] == + ssl->session_negotiate->ciphersuite ) + { + break; + } + } + + suite_info = mbedtls_ssl_ciphersuite_from_id( + ssl->session_negotiate->ciphersuite ); + if( ssl_validate_ciphersuite( suite_info, ssl, ssl->minor_ver, + ssl->minor_ver ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "server hello, chosen ciphersuite: %s", suite_info->name ) ); + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA && + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + ssl->handshake->ecrs_enabled = 1; + } +#endif + + if( comp != MBEDTLS_SSL_COMPRESS_NULL +#if defined(MBEDTLS_ZLIB_SUPPORT) + && comp != MBEDTLS_SSL_COMPRESS_DEFLATE +#endif + ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + ssl->session_negotiate->compression = comp; + + ext = buf + 40 + n; + + MBEDTLS_SSL_DEBUG_MSG( 2, + ( "server hello, total extension length: %d", ext_len ) ); + + while( ext_len ) + { + unsigned int ext_id = ( ( ext[0] << 8 ) + | ( ext[1] ) ); + unsigned int ext_size = ( ( ext[2] << 8 ) + | ( ext[3] ) ); + + if( ext_size + 4 > ext_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( + ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + switch( ext_id ) + { + case MBEDTLS_TLS_EXT_RENEGOTIATION_INFO: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found renegotiation extension" ) ); +#if defined(MBEDTLS_SSL_RENEGOTIATION) + renegotiation_info_seen = 1; +#endif + + if( ( ret = ssl_parse_renegotiation_info( ssl, ext + 4, + ext_size ) ) != 0 ) + return( ret ); + + break; + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + case MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH: + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "found max_fragment_length extension" ) ); + + if( ( ret = ssl_parse_max_fragment_length_ext( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + case MBEDTLS_TLS_EXT_TRUNCATED_HMAC: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found truncated_hmac extension" ) ); + + if( ( ret = ssl_parse_truncated_hmac_ext( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + case MBEDTLS_TLS_EXT_CID: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found CID extension" ) ); + + if( ( ret = ssl_parse_cid_ext( ssl, + ext + 4, + ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + case MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found encrypt_then_mac extension" ) ); + + if( ( ret = ssl_parse_encrypt_then_mac_ext( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + case MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET: + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "found extended_master_secret extension" ) ); + + if( ( ret = ssl_parse_extended_ms_ext( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + case MBEDTLS_TLS_EXT_SESSION_TICKET: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found session_ticket extension" ) ); + + if( ( ret = ssl_parse_session_ticket_ext( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + case MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS: + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "found supported_point_formats extension" ) ); + + if( ( ret = ssl_parse_supported_point_formats_ext( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || + MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + case MBEDTLS_TLS_EXT_ECJPAKE_KKPP: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found ecjpake_kkpp extension" ) ); + + if( ( ret = ssl_parse_ecjpake_kkpp( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_ALPN) + case MBEDTLS_TLS_EXT_ALPN: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found alpn extension" ) ); + + if( ( ret = ssl_parse_alpn_ext( ssl, ext + 4, ext_size ) ) != 0 ) + return( ret ); + + break; +#endif /* MBEDTLS_SSL_ALPN */ + +#if defined(MBEDTLS_SSL_DTLS_SRTP) + case MBEDTLS_TLS_EXT_USE_SRTP: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found use_srtp extension" ) ); + + if( ( ret = ssl_parse_use_srtp_ext( ssl, ext + 4, ext_size ) ) != 0 ) + return( ret ); + + break; +#endif /* MBEDTLS_SSL_DTLS_SRTP */ + + default: + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "unknown extension found: %d (ignoring)", ext_id ) ); + } + + ext_len -= 4 + ext_size; + ext += 4 + ext_size; + + if( ext_len > 0 && ext_len < 4 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + } + + /* + * Renegotiation security checks + */ + if( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + ssl->conf->allow_legacy_renegotiation == + MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "legacy renegotiation, breaking off handshake" ) ); + handshake_failure = 1; + } +#if defined(MBEDTLS_SSL_RENEGOTIATION) + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->secure_renegotiation == MBEDTLS_SSL_SECURE_RENEGOTIATION && + renegotiation_info_seen == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "renegotiation_info extension missing (secure)" ) ); + handshake_failure = 1; + } + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + ssl->conf->allow_legacy_renegotiation == + MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation not allowed" ) ); + handshake_failure = 1; + } + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + renegotiation_info_seen == 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "renegotiation_info extension present (legacy)" ) ); + handshake_failure = 1; + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + if( handshake_failure == 1 ) + { + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server hello" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) +static int ssl_parse_server_dh_params( mbedtls_ssl_context *ssl, + unsigned char **p, + unsigned char *end ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + + /* + * Ephemeral DH parameters: + * + * struct { + * opaque dh_p<1..2^16-1>; + * opaque dh_g<1..2^16-1>; + * opaque dh_Ys<1..2^16-1>; + * } ServerDHParams; + */ + if( ( ret = mbedtls_dhm_read_params( &ssl->handshake->dhm_ctx, + p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 2, ( "mbedtls_dhm_read_params" ), ret ); + return( ret ); + } + + if( ssl->handshake->dhm_ctx.len * 8 < ssl->conf->dhm_min_bitlen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "DHM prime too short: %d < %d", + ssl->handshake->dhm_ctx.len * 8, + ssl->conf->dhm_min_bitlen ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->handshake->dhm_ctx.P ); + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->handshake->dhm_ctx.G ); + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GY", &ssl->handshake->dhm_ctx.GY ); + + return( ret ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +static int ssl_check_server_ecdh_params( const mbedtls_ssl_context *ssl ) +{ + const mbedtls_ecp_curve_info *curve_info; + mbedtls_ecp_group_id grp_id; +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + grp_id = ssl->handshake->ecdh_ctx.grp.id; +#else + grp_id = ssl->handshake->ecdh_ctx.grp_id; +#endif + + curve_info = mbedtls_ecp_curve_info_from_grp_id( grp_id ); + if( curve_info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "ECDH curve: %s", curve_info->name ) ); + +#if defined(MBEDTLS_ECP_C) + if( mbedtls_ssl_check_curve( ssl, grp_id ) != 0 ) +#else + if( ssl->handshake->ecdh_ctx.grp.nbits < 163 || + ssl->handshake->ecdh_ctx.grp.nbits > 521 ) +#endif + return( -1 ); + + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_QP ); + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) && \ + ( defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) ) +static int ssl_parse_server_ecdh_params_psa( mbedtls_ssl_context *ssl, + unsigned char **p, + unsigned char *end ) +{ + uint16_t tls_id; + size_t ecdh_bits = 0; + uint8_t ecpoint_len; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + + /* + * Parse ECC group + */ + + if( end - *p < 4 ) + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + + /* First byte is curve_type; only named_curve is handled */ + if( *(*p)++ != MBEDTLS_ECP_TLS_NAMED_CURVE ) + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + + /* Next two bytes are the namedcurve value */ + tls_id = *(*p)++; + tls_id <<= 8; + tls_id |= *(*p)++; + + /* Convert EC group to PSA key type. */ + if( ( handshake->ecdh_psa_type = + mbedtls_psa_parse_tls_ecc_group( tls_id, &ecdh_bits ) ) == 0 ) + { + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + if( ecdh_bits > 0xffff ) + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + handshake->ecdh_bits = (uint16_t) ecdh_bits; + + /* + * Put peer's ECDH public key in the format understood by PSA. + */ + + ecpoint_len = *(*p)++; + if( (size_t)( end - *p ) < ecpoint_len ) + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + + if( mbedtls_psa_tls_ecpoint_to_psa_ec( + *p, ecpoint_len, + handshake->ecdh_psa_peerkey, + sizeof( handshake->ecdh_psa_peerkey ), + &handshake->ecdh_psa_peerkey_len ) != 0 ) + { + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + *p += ecpoint_len; + return( 0 ); +} +#endif /* MBEDTLS_USE_PSA_CRYPTO && + ( MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED ) */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +static int ssl_parse_server_ecdh_params( mbedtls_ssl_context *ssl, + unsigned char **p, + unsigned char *end ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + + /* + * Ephemeral ECDH parameters: + * + * struct { + * ECParameters curve_params; + * ECPoint public; + * } ServerECDHParams; + */ + if( ( ret = mbedtls_ecdh_read_params( &ssl->handshake->ecdh_ctx, + (const unsigned char **) p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_read_params" ), ret ); +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; +#endif + return( ret ); + } + + if( ssl_check_server_ecdh_params( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "bad server key exchange message (ECDHE curve)" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + return( ret ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) +static int ssl_parse_server_psk_hint( mbedtls_ssl_context *ssl, + unsigned char **p, + unsigned char *end ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + uint16_t len; + ((void) ssl); + + /* + * PSK parameters: + * + * opaque psk_identity_hint<0..2^16-1>; + */ + if( end - (*p) < 2 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "bad server key exchange message (psk_identity_hint length)" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + len = (*p)[0] << 8 | (*p)[1]; + *p += 2; + + if( end - (*p) < len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "bad server key exchange message (psk_identity_hint length)" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + /* + * Note: we currently ignore the PKS identity hint, as we only allow one + * PSK to be provisionned on the client. This could be changed later if + * someone needs that feature. + */ + *p += len; + ret = 0; + + return( ret ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) +/* + * Generate a pre-master secret and encrypt it with the server's RSA key + */ +static int ssl_write_encrypted_pms( mbedtls_ssl_context *ssl, + size_t offset, size_t *olen, + size_t pms_offset ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len_bytes = ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ? 0 : 2; + unsigned char *p = ssl->handshake->premaster + pms_offset; + mbedtls_pk_context * peer_pk; + + if( offset + len_bytes > MBEDTLS_SSL_OUT_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small for encrypted pms" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + /* + * Generate (part of) the pre-master as + * struct { + * ProtocolVersion client_version; + * opaque random[46]; + * } PreMasterSecret; + */ + mbedtls_ssl_write_version( ssl->conf->max_major_ver, + ssl->conf->max_minor_ver, + ssl->conf->transport, p ); + + if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p + 2, 46 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "f_rng", ret ); + return( ret ); + } + + ssl->handshake->pmslen = 48; + +#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + peer_pk = &ssl->handshake->peer_pubkey; +#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + if( ssl->session_negotiate->peer_cert == NULL ) + { + /* Should never happen */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + peer_pk = &ssl->session_negotiate->peer_cert->pk; +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + + /* + * Now write it out, encrypted + */ + if( ! mbedtls_pk_can_do( peer_pk, MBEDTLS_PK_RSA ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "certificate key type mismatch" ) ); + return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); + } + + if( ( ret = mbedtls_pk_encrypt( peer_pk, + p, ssl->handshake->pmslen, + ssl->out_msg + offset + len_bytes, olen, + MBEDTLS_SSL_OUT_CONTENT_LEN - offset - len_bytes, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_rsa_pkcs1_encrypt", ret ); + return( ret ); + } + +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( len_bytes == 2 ) + { + ssl->out_msg[offset+0] = (unsigned char)( *olen >> 8 ); + ssl->out_msg[offset+1] = (unsigned char)( *olen ); + *olen += 2; + } +#endif + +#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + /* We don't need the peer's public key anymore. Free it. */ + mbedtls_pk_free( peer_pk ); +#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +static int ssl_parse_signature_algorithm( mbedtls_ssl_context *ssl, + unsigned char **p, + unsigned char *end, + mbedtls_md_type_t *md_alg, + mbedtls_pk_type_t *pk_alg ) +{ + ((void) ssl); + *md_alg = MBEDTLS_MD_NONE; + *pk_alg = MBEDTLS_PK_NONE; + + /* Only in TLS 1.2 */ + if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) + { + return( 0 ); + } + + if( (*p) + 2 > end ) + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + + /* + * Get hash algorithm + */ + if( ( *md_alg = mbedtls_ssl_md_alg_from_hash( (*p)[0] ) ) + == MBEDTLS_MD_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "Server used unsupported HashAlgorithm %d", *(p)[0] ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + /* + * Get signature algorithm + */ + if( ( *pk_alg = mbedtls_ssl_pk_alg_from_sig( (*p)[1] ) ) + == MBEDTLS_PK_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "server used unsupported SignatureAlgorithm %d", (*p)[1] ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + /* + * Check if the hash is acceptable + */ + if( mbedtls_ssl_check_sig_hash( ssl, *md_alg ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "server used HashAlgorithm %d that was not offered", *(p)[0] ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Server used SignatureAlgorithm %d", + (*p)[1] ) ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Server used HashAlgorithm %d", + (*p)[0] ) ); + *p += 2; + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const mbedtls_ecp_keypair *peer_key; + mbedtls_pk_context * peer_pk; + +#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + peer_pk = &ssl->handshake->peer_pubkey; +#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + if( ssl->session_negotiate->peer_cert == NULL ) + { + /* Should never happen */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + peer_pk = &ssl->session_negotiate->peer_cert->pk; +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + + if( ! mbedtls_pk_can_do( peer_pk, MBEDTLS_PK_ECKEY ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "server key not ECDH capable" ) ); + return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); + } + + peer_key = mbedtls_pk_ec( *peer_pk ); + + if( ( ret = mbedtls_ecdh_get_params( &ssl->handshake->ecdh_ctx, peer_key, + MBEDTLS_ECDH_THEIRS ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_get_params" ), ret ); + return( ret ); + } + + if( ssl_check_server_ecdh_params( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server certificate (ECDH curve)" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } + +#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + /* We don't need the peer's public key anymore. Free it, + * so that more RAM is available for upcoming expensive + * operations like ECDHE. */ + mbedtls_pk_free( peer_pk ); +#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + + return( ret ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + unsigned char *p = NULL, *end = NULL; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server key exchange" ) ); + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse server key exchange" ) ); + ssl->state++; + return( 0 ); + } + ((void) p); + ((void) end); +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA ) + { + if( ( ret = ssl_get_ecdh_params_from_cert( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_get_ecdh_params_from_cert", ret ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse server key exchange" ) ); + ssl->state++; + return( 0 ); + } + ((void) p); + ((void) end); +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ssl->handshake->ecrs_enabled && + ssl->handshake->ecrs_state == ssl_ecrs_ske_start_processing ) + { + goto start_processing; + } +#endif + + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + /* + * ServerKeyExchange may be skipped with PSK and RSA-PSK when the server + * doesn't use a psk_identity_hint + */ + if( ssl->in_msg[0] != MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE ) + { + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) + { + /* Current message is probably either + * CertificateRequest or ServerHelloDone */ + ssl->keep_current_message = 1; + goto exit; + } + + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "server key exchange message must not be skipped" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ssl->handshake->ecrs_enabled ) + ssl->handshake->ecrs_state = ssl_ecrs_ske_start_processing; + +start_processing: +#endif + p = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); + end = ssl->in_msg + ssl->in_hslen; + MBEDTLS_SSL_DEBUG_BUF( 3, "server key exchange", p, end - p ); + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) + { + if( ssl_parse_server_psk_hint( ssl, &p, end ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + } /* FALLTROUGH */ +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) + ; /* nothing more to do */ + else +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED || + MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ) + { + if( ssl_parse_server_dh_params( ssl, &p, end ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) && \ + ( defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) ) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ) + { + if( ssl_parse_server_ecdh_params_psa( ssl, &p, end ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + } + else +#endif /* MBEDTLS_USE_PSA_CRYPTO && + ( MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED ) */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ) + { + if( ssl_parse_server_ecdh_params( ssl, &p, end ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + ret = mbedtls_ecjpake_read_round_two( &ssl->handshake->ecjpake_ctx, + p, end - p ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_two", ret ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) + if( mbedtls_ssl_ciphersuite_uses_server_signature( ciphersuite_info ) ) + { + size_t sig_len, hashlen; + unsigned char hash[64]; + mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE; + mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; + unsigned char *params = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); + size_t params_len = p - params; + void *rs_ctx = NULL; + + mbedtls_pk_context * peer_pk; + + /* + * Handle the digitally-signed structure + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + if( ssl_parse_signature_algorithm( ssl, &p, end, + &md_alg, &pk_alg ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + if( pk_alg != + mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 ) + { + pk_alg = mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ); + + /* Default hash for ECDSA is SHA-1 */ + if( pk_alg == MBEDTLS_PK_ECDSA && md_alg == MBEDTLS_MD_NONE ) + md_alg = MBEDTLS_MD_SHA1; + } + else +#endif + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* + * Read signature + */ + + if( p > end - 2 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + sig_len = ( p[0] << 8 ) | p[1]; + p += 2; + + if( p != end - sig_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "signature", p, sig_len ); + + /* + * Compute the hash that has been signed + */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( md_alg == MBEDTLS_MD_NONE ) + { + hashlen = 36; + ret = mbedtls_ssl_get_key_exchange_md_ssl_tls( ssl, hash, params, + params_len ); + if( ret != 0 ) + return( ret ); + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ + MBEDTLS_SSL_PROTO_TLS1_1 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( md_alg != MBEDTLS_MD_NONE ) + { + ret = mbedtls_ssl_get_key_exchange_md_tls1_2( ssl, hash, &hashlen, + params, params_len, + md_alg ); + if( ret != 0 ) + return( ret ); + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ + MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen ); + +#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + peer_pk = &ssl->handshake->peer_pubkey; +#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + if( ssl->session_negotiate->peer_cert == NULL ) + { + /* Should never happen */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + peer_pk = &ssl->session_negotiate->peer_cert->pk; +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + + /* + * Verify signature + */ + if( !mbedtls_pk_can_do( peer_pk, pk_alg ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); + } + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ssl->handshake->ecrs_enabled ) + rs_ctx = &ssl->handshake->ecrs_ctx.pk; +#endif + + if( ( ret = mbedtls_pk_verify_restartable( peer_pk, + md_alg, hash, hashlen, p, sig_len, rs_ctx ) ) != 0 ) + { +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) +#endif + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR ); + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_verify", ret ); +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; +#endif + return( ret ); + } + +#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + /* We don't need the peer's public key anymore. Free it, + * so that more RAM is available for upcoming expensive + * operations like ECDHE. */ + mbedtls_pk_free( peer_pk ); +#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + } +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */ + +exit: + ssl->state++; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server key exchange" ) ); + + return( 0 ); +} + +#if ! defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) +static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) ); + + if( ! mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate request" ) ); + ssl->state++; + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); +} +#else /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ +static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *buf; + size_t n = 0; + size_t cert_type_len = 0, dn_len = 0; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) ); + + if( ! mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate request" ) ); + ssl->state++; + return( 0 ); + } + + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + ssl->state++; + ssl->client_auth = ( ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE_REQUEST ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "got %s certificate request", + ssl->client_auth ? "a" : "no" ) ); + + if( ssl->client_auth == 0 ) + { + /* Current message is probably the ServerHelloDone */ + ssl->keep_current_message = 1; + goto exit; + } + + /* + * struct { + * ClientCertificateType certificate_types<1..2^8-1>; + * SignatureAndHashAlgorithm + * supported_signature_algorithms<2^16-1>; -- TLS 1.2 only + * DistinguishedName certificate_authorities<0..2^16-1>; + * } CertificateRequest; + * + * Since we only support a single certificate on clients, let's just + * ignore all the information that's supposed to help us pick a + * certificate. + * + * We could check that our certificate matches the request, and bail out + * if it doesn't, but it's simpler to just send the certificate anyway, + * and give the server the opportunity to decide if it should terminate + * the connection when it doesn't like our certificate. + * + * Same goes for the hash in TLS 1.2's signature_algorithms: at this + * point we only have one hash available (see comments in + * write_certificate_verify), so let's just use what we have. + * + * However, we still minimally parse the message to check it is at least + * superficially sane. + */ + buf = ssl->in_msg; + + /* certificate_types */ + if( ssl->in_hslen <= mbedtls_ssl_hs_hdr_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); + } + cert_type_len = buf[mbedtls_ssl_hs_hdr_len( ssl )]; + n = cert_type_len; + + /* + * In the subsequent code there are two paths that read from buf: + * * the length of the signature algorithms field (if minor version of + * SSL is 3), + * * distinguished name length otherwise. + * Both reach at most the index: + * ...hdr_len + 2 + n, + * therefore the buffer length at this point must be greater than that + * regardless of the actual code path. + */ + if( ssl->in_hslen <= mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); + } + + /* supported_signature_algorithms */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + size_t sig_alg_len = + ( ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 1 + n] << 8 ) + | ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n] ) ); +#if defined(MBEDTLS_DEBUG_C) + unsigned char* sig_alg; + size_t i; +#endif + + /* + * The furthest access in buf is in the loop few lines below: + * sig_alg[i + 1], + * where: + * sig_alg = buf + ...hdr_len + 3 + n, + * max(i) = sig_alg_len - 1. + * Therefore the furthest access is: + * buf[...hdr_len + 3 + n + sig_alg_len - 1 + 1], + * which reduces to: + * buf[...hdr_len + 3 + n + sig_alg_len], + * which is one less than we need the buf to be. + */ + if( ssl->in_hslen <= mbedtls_ssl_hs_hdr_len( ssl ) + + 3 + n + sig_alg_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); + } + +#if defined(MBEDTLS_DEBUG_C) + sig_alg = buf + mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n; + for( i = 0; i < sig_alg_len; i += 2 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "Supported Signature Algorithm found: %d,%d", + sig_alg[i], sig_alg[i + 1] ) ); + } +#endif + + n += 2 + sig_alg_len; + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + /* certificate_authorities */ + dn_len = ( ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 1 + n] << 8 ) + | ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n] ) ); + + n += dn_len; + if( ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); + } + +exit: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate request" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ + +static int ssl_parse_server_hello_done( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server hello done" ) ); + + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + if( ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) || + ssl->in_msg[0] != MBEDTLS_SSL_HS_SERVER_HELLO_DONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE ); + } + + ssl->state++; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + mbedtls_ssl_recv_flight_completed( ssl ); +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server hello done" ) ); + + return( 0 ); +} + +static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + size_t header_len; + size_t content_len; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write client key exchange" ) ); + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA ) + { + /* + * DHM key exchange -- send G^X mod P + */ + content_len = ssl->handshake->dhm_ctx.len; + + ssl->out_msg[4] = (unsigned char)( content_len >> 8 ); + ssl->out_msg[5] = (unsigned char)( content_len ); + header_len = 6; + + ret = mbedtls_dhm_make_public( &ssl->handshake->dhm_ctx, + (int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ), + &ssl->out_msg[header_len], content_len, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_make_public", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->handshake->dhm_ctx.X ); + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->handshake->dhm_ctx.GX ); + + if( ( ret = mbedtls_dhm_calc_secret( &ssl->handshake->dhm_ctx, + ssl->handshake->premaster, + MBEDTLS_PREMASTER_SIZE, + &ssl->handshake->pmslen, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_calc_secret", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) && \ + ( defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) ) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ) + { + psa_status_t status; + psa_key_attributes_t key_attributes; + + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + + unsigned char own_pubkey[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH]; + size_t own_pubkey_len; + unsigned char *own_pubkey_ecpoint; + size_t own_pubkey_ecpoint_len; + + header_len = 4; + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Perform PSA-based ECDH computation." ) ); + + /* + * Generate EC private key for ECDHE exchange. + */ + + /* The master secret is obtained from the shared ECDH secret by + * applying the TLS 1.2 PRF with a specific salt and label. While + * the PSA Crypto API encourages combining key agreement schemes + * such as ECDH with fixed KDFs such as TLS 1.2 PRF, it does not + * yet support the provisioning of salt + label to the KDF. + * For the time being, we therefore need to split the computation + * of the ECDH secret and the application of the TLS 1.2 PRF. */ + key_attributes = psa_key_attributes_init(); + psa_set_key_usage_flags( &key_attributes, PSA_KEY_USAGE_DERIVE ); + psa_set_key_algorithm( &key_attributes, PSA_ALG_ECDH ); + psa_set_key_type( &key_attributes, handshake->ecdh_psa_type ); + psa_set_key_bits( &key_attributes, handshake->ecdh_bits ); + + /* Generate ECDH private key. */ + status = psa_generate_key( &key_attributes, + &handshake->ecdh_psa_privkey ); + if( status != PSA_SUCCESS ) + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + + /* Export the public part of the ECDH private key from PSA + * and convert it to ECPoint format used in ClientKeyExchange. */ + status = psa_export_public_key( handshake->ecdh_psa_privkey, + own_pubkey, sizeof( own_pubkey ), + &own_pubkey_len ); + if( status != PSA_SUCCESS ) + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + + if( mbedtls_psa_tls_psa_ec_to_ecpoint( own_pubkey, + own_pubkey_len, + &own_pubkey_ecpoint, + &own_pubkey_ecpoint_len ) != 0 ) + { + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + /* Copy ECPoint structure to outgoing message buffer. */ + ssl->out_msg[header_len] = (unsigned char) own_pubkey_ecpoint_len; + memcpy( ssl->out_msg + header_len + 1, + own_pubkey_ecpoint, own_pubkey_ecpoint_len ); + content_len = own_pubkey_ecpoint_len + 1; + + /* The ECDH secret is the premaster secret used for key derivation. */ + + /* Compute ECDH shared secret. */ + status = psa_raw_key_agreement( PSA_ALG_ECDH, + handshake->ecdh_psa_privkey, + handshake->ecdh_psa_peerkey, + handshake->ecdh_psa_peerkey_len, + ssl->handshake->premaster, + sizeof( ssl->handshake->premaster ), + &ssl->handshake->pmslen ); + if( status != PSA_SUCCESS ) + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + + status = psa_destroy_key( handshake->ecdh_psa_privkey ); + if( status != PSA_SUCCESS ) + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + handshake->ecdh_psa_privkey = 0; + } + else +#endif /* MBEDTLS_USE_PSA_CRYPTO && + ( MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED ) */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA ) + { + /* + * ECDH key exchange -- send client public value + */ + header_len = 4; + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ssl->handshake->ecrs_enabled ) + { + if( ssl->handshake->ecrs_state == ssl_ecrs_cke_ecdh_calc_secret ) + goto ecdh_calc_secret; + + mbedtls_ecdh_enable_restart( &ssl->handshake->ecdh_ctx ); + } +#endif + + ret = mbedtls_ecdh_make_public( &ssl->handshake->ecdh_ctx, + &content_len, + &ssl->out_msg[header_len], 1000, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_public", ret ); +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; +#endif + return( ret ); + } + + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_Q ); + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ssl->handshake->ecrs_enabled ) + { + ssl->handshake->ecrs_n = content_len; + ssl->handshake->ecrs_state = ssl_ecrs_cke_ecdh_calc_secret; + } + +ecdh_calc_secret: + if( ssl->handshake->ecrs_enabled ) + content_len = ssl->handshake->ecrs_n; +#endif + if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx, + &ssl->handshake->pmslen, + ssl->handshake->premaster, + MBEDTLS_MPI_MAX_SIZE, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret ); +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; +#endif + return( ret ); + } + + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_Z ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) + if( mbedtls_ssl_ciphersuite_uses_psk( ciphersuite_info ) ) + { + /* + * opaque psk_identity<0..2^16-1>; + */ + if( ssl_conf_has_static_psk( ssl->conf ) == 0 ) + { + /* We don't offer PSK suites if we don't have a PSK, + * and we check that the server's choice is among the + * ciphersuites we offered, so this should never happen. */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + header_len = 4; + content_len = ssl->conf->psk_identity_len; + + if( header_len + 2 + content_len > MBEDTLS_SSL_OUT_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "psk identity too long or SSL buffer too short" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + ssl->out_msg[header_len++] = (unsigned char)( content_len >> 8 ); + ssl->out_msg[header_len++] = (unsigned char)( content_len ); + + memcpy( ssl->out_msg + header_len, + ssl->conf->psk_identity, + ssl->conf->psk_identity_len ); + header_len += ssl->conf->psk_identity_len; + +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ) + { + content_len = 0; + } + else +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) + { +#if defined(MBEDTLS_USE_PSA_CRYPTO) + /* Opaque PSKs are currently only supported for PSK-only suites. */ + if( ssl_conf_has_static_raw_psk( ssl->conf ) == 0 ) + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + if( ( ret = ssl_write_encrypted_pms( ssl, header_len, + &content_len, 2 ) ) != 0 ) + return( ret ); + } + else +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ) + { +#if defined(MBEDTLS_USE_PSA_CRYPTO) + /* Opaque PSKs are currently only supported for PSK-only suites. */ + if( ssl_conf_has_static_raw_psk( ssl->conf ) == 0 ) + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + /* + * ClientDiffieHellmanPublic public (DHM send G^X mod P) + */ + content_len = ssl->handshake->dhm_ctx.len; + + if( header_len + 2 + content_len > + MBEDTLS_SSL_OUT_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "psk identity or DHM size too long or SSL buffer too short" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + ssl->out_msg[header_len++] = (unsigned char)( content_len >> 8 ); + ssl->out_msg[header_len++] = (unsigned char)( content_len ); + + ret = mbedtls_dhm_make_public( &ssl->handshake->dhm_ctx, + (int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ), + &ssl->out_msg[header_len], content_len, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_make_public", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) + { +#if defined(MBEDTLS_USE_PSA_CRYPTO) + /* Opaque PSKs are currently only supported for PSK-only suites. */ + if( ssl_conf_has_static_raw_psk( ssl->conf ) == 0 ) + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + /* + * ClientECDiffieHellmanPublic public; + */ + ret = mbedtls_ecdh_make_public( &ssl->handshake->ecdh_ctx, + &content_len, + &ssl->out_msg[header_len], + MBEDTLS_SSL_OUT_CONTENT_LEN - header_len, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_public", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_Q ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_USE_PSA_CRYPTO) && \ + defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK && + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 && + ssl_conf_has_static_raw_psk( ssl->conf ) == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "skip PMS generation for opaque PSK" ) ); + } + else +#endif /* MBEDTLS_USE_PSA_CRYPTO && + MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ + if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, + ciphersuite_info->key_exchange ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, + "mbedtls_ssl_psk_derive_premaster", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA ) + { + header_len = 4; + if( ( ret = ssl_write_encrypted_pms( ssl, header_len, + &content_len, 0 ) ) != 0 ) + return( ret ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + header_len = 4; + + ret = mbedtls_ecjpake_write_round_two( &ssl->handshake->ecjpake_ctx, + ssl->out_msg + header_len, + MBEDTLS_SSL_OUT_CONTENT_LEN - header_len, + &content_len, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_write_round_two", ret ); + return( ret ); + } + + ret = mbedtls_ecjpake_derive_secret( &ssl->handshake->ecjpake_ctx, + ssl->handshake->premaster, 32, &ssl->handshake->pmslen, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_derive_secret", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ + { + ((void) ciphersuite_info); + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + ssl->out_msglen = header_len + content_len; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE; + + ssl->state++; + + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write client key exchange" ) ); + + return( 0 ); +} + +#if !defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) +static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) ); + + if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); + return( ret ); + } + + if( !mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) ); + ssl->state++; + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); +} +#else /* !MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ +static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + size_t n = 0, offset = 0; + unsigned char hash[48]; + unsigned char *hash_start = hash; + mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE; + size_t hashlen; + void *rs_ctx = NULL; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) ); + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ssl->handshake->ecrs_enabled && + ssl->handshake->ecrs_state == ssl_ecrs_crt_vrfy_sign ) + { + goto sign; + } +#endif + + if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); + return( ret ); + } + + if( !mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) ); + ssl->state++; + return( 0 ); + } + + if( ssl->client_auth == 0 || mbedtls_ssl_own_cert( ssl ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) ); + ssl->state++; + return( 0 ); + } + + if( mbedtls_ssl_own_key( ssl ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no private key for certificate" ) ); + return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); + } + + /* + * Make a signature of the handshake digests + */ +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ssl->handshake->ecrs_enabled ) + ssl->handshake->ecrs_state = ssl_ecrs_crt_vrfy_sign; + +sign: +#endif + + ssl->handshake->calc_verify( ssl, hash, &hashlen ); + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) + { + /* + * digitally-signed struct { + * opaque md5_hash[16]; + * opaque sha_hash[20]; + * }; + * + * md5_hash + * MD5(handshake_messages); + * + * sha_hash + * SHA(handshake_messages); + */ + md_alg = MBEDTLS_MD_NONE; + + /* + * For ECDSA, default hash is SHA-1 only + */ + if( mbedtls_pk_can_do( mbedtls_ssl_own_key( ssl ), MBEDTLS_PK_ECDSA ) ) + { + hash_start += 16; + hashlen -= 16; + md_alg = MBEDTLS_MD_SHA1; + } + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ + MBEDTLS_SSL_PROTO_TLS1_1 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + /* + * digitally-signed struct { + * opaque handshake_messages[handshake_messages_length]; + * }; + * + * Taking shortcut here. We assume that the server always allows the + * PRF Hash function and has sent it in the allowed signature + * algorithms list received in the Certificate Request message. + * + * Until we encounter a server that does not, we will take this + * shortcut. + * + * Reason: Otherwise we should have running hashes for SHA512 and + * SHA224 in order to satisfy 'weird' needs from the server + * side. + */ + if( ssl->handshake->ciphersuite_info->mac == MBEDTLS_MD_SHA384 ) + { + md_alg = MBEDTLS_MD_SHA384; + ssl->out_msg[4] = MBEDTLS_SSL_HASH_SHA384; + } + else + { + md_alg = MBEDTLS_MD_SHA256; + ssl->out_msg[4] = MBEDTLS_SSL_HASH_SHA256; + } + ssl->out_msg[5] = mbedtls_ssl_sig_from_pk( mbedtls_ssl_own_key( ssl ) ); + + /* Info from md_alg will be used instead */ + hashlen = 0; + offset = 2; + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ssl->handshake->ecrs_enabled ) + rs_ctx = &ssl->handshake->ecrs_ctx.pk; +#endif + + if( ( ret = mbedtls_pk_sign_restartable( mbedtls_ssl_own_key( ssl ), + md_alg, hash_start, hashlen, + ssl->out_msg + 6 + offset, &n, + ssl->conf->f_rng, ssl->conf->p_rng, rs_ctx ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_sign", ret ); +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; +#endif + return( ret ); + } + + ssl->out_msg[4 + offset] = (unsigned char)( n >> 8 ); + ssl->out_msg[5 + offset] = (unsigned char)( n ); + + ssl->out_msglen = 6 + n + offset; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE_VERIFY; + + ssl->state++; + + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write certificate verify" ) ); + + return( ret ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + uint32_t lifetime; + size_t ticket_len; + unsigned char *ticket; + const unsigned char *msg; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse new session ticket" ) ); + + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + /* + * struct { + * uint32 ticket_lifetime_hint; + * opaque ticket<0..2^16-1>; + * } NewSessionTicket; + * + * 0 . 3 ticket_lifetime_hint + * 4 . 5 ticket_len (n) + * 6 . 5+n ticket content + */ + if( ssl->in_msg[0] != MBEDTLS_SSL_HS_NEW_SESSION_TICKET || + ssl->in_hslen < 6 + mbedtls_ssl_hs_hdr_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET ); + } + + msg = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); + + lifetime = ( ((uint32_t) msg[0]) << 24 ) | ( msg[1] << 16 ) | + ( msg[2] << 8 ) | ( msg[3] ); + + ticket_len = ( msg[4] << 8 ) | ( msg[5] ); + + if( ticket_len + 6 + mbedtls_ssl_hs_hdr_len( ssl ) != ssl->in_hslen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket length: %d", ticket_len ) ); + + /* We're not waiting for a NewSessionTicket message any more */ + ssl->handshake->new_session_ticket = 0; + ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC; + + /* + * Zero-length ticket means the server changed his mind and doesn't want + * to send a ticket after all, so just forget it + */ + if( ticket_len == 0 ) + return( 0 ); + + if( ssl->session != NULL && ssl->session->ticket != NULL ) + { + mbedtls_platform_zeroize( ssl->session->ticket, + ssl->session->ticket_len ); + mbedtls_free( ssl->session->ticket ); + ssl->session->ticket = NULL; + ssl->session->ticket_len = 0; + } + + mbedtls_platform_zeroize( ssl->session_negotiate->ticket, + ssl->session_negotiate->ticket_len ); + mbedtls_free( ssl->session_negotiate->ticket ); + ssl->session_negotiate->ticket = NULL; + ssl->session_negotiate->ticket_len = 0; + + if( ( ticket = mbedtls_calloc( 1, ticket_len ) ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "ticket alloc failed" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + memcpy( ticket, msg + 6, ticket_len ); + + ssl->session_negotiate->ticket = ticket; + ssl->session_negotiate->ticket_len = ticket_len; + ssl->session_negotiate->ticket_lifetime = lifetime; + + /* + * RFC 5077 section 3.4: + * "If the client receives a session ticket from the server, then it + * discards any Session ID that was sent in the ServerHello." + */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket in use, discarding session id" ) ); + ssl->session_negotiate->id_len = 0; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse new session ticket" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +/* + * SSL handshake -- client side -- single step + */ +int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl ) +{ + int ret = 0; + + if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER || ssl->handshake == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "client state: %d", ssl->state ) ); + + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + return( ret ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) + { + if( ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) + return( ret ); + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + /* Change state now, so that it is right in mbedtls_ssl_read_record(), used + * by DTLS for dropping out-of-sequence ChangeCipherSpec records */ +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + if( ssl->state == MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC && + ssl->handshake->new_session_ticket != 0 ) + { + ssl->state = MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET; + } +#endif + + switch( ssl->state ) + { + case MBEDTLS_SSL_HELLO_REQUEST: + ssl->state = MBEDTLS_SSL_CLIENT_HELLO; + break; + + /* + * ==> ClientHello + */ + case MBEDTLS_SSL_CLIENT_HELLO: + ret = ssl_write_client_hello( ssl ); + break; + + /* + * <== ServerHello + * Certificate + * ( ServerKeyExchange ) + * ( CertificateRequest ) + * ServerHelloDone + */ + case MBEDTLS_SSL_SERVER_HELLO: + ret = ssl_parse_server_hello( ssl ); + break; + + case MBEDTLS_SSL_SERVER_CERTIFICATE: + ret = mbedtls_ssl_parse_certificate( ssl ); + break; + + case MBEDTLS_SSL_SERVER_KEY_EXCHANGE: + ret = ssl_parse_server_key_exchange( ssl ); + break; + + case MBEDTLS_SSL_CERTIFICATE_REQUEST: + ret = ssl_parse_certificate_request( ssl ); + break; + + case MBEDTLS_SSL_SERVER_HELLO_DONE: + ret = ssl_parse_server_hello_done( ssl ); + break; + + /* + * ==> ( Certificate/Alert ) + * ClientKeyExchange + * ( CertificateVerify ) + * ChangeCipherSpec + * Finished + */ + case MBEDTLS_SSL_CLIENT_CERTIFICATE: + ret = mbedtls_ssl_write_certificate( ssl ); + break; + + case MBEDTLS_SSL_CLIENT_KEY_EXCHANGE: + ret = ssl_write_client_key_exchange( ssl ); + break; + + case MBEDTLS_SSL_CERTIFICATE_VERIFY: + ret = ssl_write_certificate_verify( ssl ); + break; + + case MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC: + ret = mbedtls_ssl_write_change_cipher_spec( ssl ); + break; + + case MBEDTLS_SSL_CLIENT_FINISHED: + ret = mbedtls_ssl_write_finished( ssl ); + break; + + /* + * <== ( NewSessionTicket ) + * ChangeCipherSpec + * Finished + */ +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + case MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET: + ret = ssl_parse_new_session_ticket( ssl ); + break; +#endif + + case MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC: + ret = mbedtls_ssl_parse_change_cipher_spec( ssl ); + break; + + case MBEDTLS_SSL_SERVER_FINISHED: + ret = mbedtls_ssl_parse_finished( ssl ); + break; + + case MBEDTLS_SSL_FLUSH_BUFFERS: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "handshake: done" ) ); + ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; + break; + + case MBEDTLS_SSL_HANDSHAKE_WRAPUP: + mbedtls_ssl_handshake_wrapup( ssl ); + break; + + default: + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + return( ret ); +} +#endif /* MBEDTLS_SSL_CLI_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/ssl_cookie.c b/Android/Level4/app/src/main/c/mbedtls/library/ssl_cookie.c new file mode 100644 index 0000000..c8bd1bd --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/ssl_cookie.c @@ -0,0 +1,249 @@ +/* + * DTLS cookie callbacks implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ +/* + * These session callbacks use a simple chained list + * to store and retrieve the session information. + */ + +#include "common.h" + +#if defined(MBEDTLS_SSL_COOKIE_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/ssl_cookie.h" +#include "mbedtls/ssl_internal.h" +#include "mbedtls/error.h" +#include "mbedtls/platform_util.h" + +#include + +/* + * If DTLS is in use, then at least one of SHA-1, SHA-256, SHA-512 is + * available. Try SHA-256 first, 512 wastes resources since we need to stay + * with max 32 bytes of cookie for DTLS 1.0 + */ +#if defined(MBEDTLS_SHA256_C) +#define COOKIE_MD MBEDTLS_MD_SHA224 +#define COOKIE_MD_OUTLEN 32 +#define COOKIE_HMAC_LEN 28 +#elif defined(MBEDTLS_SHA512_C) +#define COOKIE_MD MBEDTLS_MD_SHA384 +#define COOKIE_MD_OUTLEN 48 +#define COOKIE_HMAC_LEN 28 +#elif defined(MBEDTLS_SHA1_C) +#define COOKIE_MD MBEDTLS_MD_SHA1 +#define COOKIE_MD_OUTLEN 20 +#define COOKIE_HMAC_LEN 20 +#else +#error "DTLS hello verify needs SHA-1 or SHA-2" +#endif + +/* + * Cookies are formed of a 4-bytes timestamp (or serial number) and + * an HMAC of timestemp and client ID. + */ +#define COOKIE_LEN ( 4 + COOKIE_HMAC_LEN ) + +void mbedtls_ssl_cookie_init( mbedtls_ssl_cookie_ctx *ctx ) +{ + mbedtls_md_init( &ctx->hmac_ctx ); +#if !defined(MBEDTLS_HAVE_TIME) + ctx->serial = 0; +#endif + ctx->timeout = MBEDTLS_SSL_COOKIE_TIMEOUT; + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif +} + +void mbedtls_ssl_cookie_set_timeout( mbedtls_ssl_cookie_ctx *ctx, unsigned long delay ) +{ + ctx->timeout = delay; +} + +void mbedtls_ssl_cookie_free( mbedtls_ssl_cookie_ctx *ctx ) +{ + mbedtls_md_free( &ctx->hmac_ctx ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free( &ctx->mutex ); +#endif + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ssl_cookie_ctx ) ); +} + +int mbedtls_ssl_cookie_setup( mbedtls_ssl_cookie_ctx *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char key[COOKIE_MD_OUTLEN]; + + if( ( ret = f_rng( p_rng, key, sizeof( key ) ) ) != 0 ) + return( ret ); + + ret = mbedtls_md_setup( &ctx->hmac_ctx, mbedtls_md_info_from_type( COOKIE_MD ), 1 ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_md_hmac_starts( &ctx->hmac_ctx, key, sizeof( key ) ); + if( ret != 0 ) + return( ret ); + + mbedtls_platform_zeroize( key, sizeof( key ) ); + + return( 0 ); +} + +/* + * Generate the HMAC part of a cookie + */ +static int ssl_cookie_hmac( mbedtls_md_context_t *hmac_ctx, + const unsigned char time[4], + unsigned char **p, unsigned char *end, + const unsigned char *cli_id, size_t cli_id_len ) +{ + unsigned char hmac_out[COOKIE_MD_OUTLEN]; + + MBEDTLS_SSL_CHK_BUF_PTR( *p, end, COOKIE_HMAC_LEN ); + + if( mbedtls_md_hmac_reset( hmac_ctx ) != 0 || + mbedtls_md_hmac_update( hmac_ctx, time, 4 ) != 0 || + mbedtls_md_hmac_update( hmac_ctx, cli_id, cli_id_len ) != 0 || + mbedtls_md_hmac_finish( hmac_ctx, hmac_out ) != 0 ) + { + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + memcpy( *p, hmac_out, COOKIE_HMAC_LEN ); + *p += COOKIE_HMAC_LEN; + + return( 0 ); +} + +/* + * Generate cookie for DTLS ClientHello verification + */ +int mbedtls_ssl_cookie_write( void *p_ctx, + unsigned char **p, unsigned char *end, + const unsigned char *cli_id, size_t cli_id_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ssl_cookie_ctx *ctx = (mbedtls_ssl_cookie_ctx *) p_ctx; + unsigned long t; + + if( ctx == NULL || cli_id == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + MBEDTLS_SSL_CHK_BUF_PTR( *p, end, COOKIE_LEN ); + +#if defined(MBEDTLS_HAVE_TIME) + t = (unsigned long) mbedtls_time( NULL ); +#else + t = ctx->serial++; +#endif + + (*p)[0] = (unsigned char)( t >> 24 ); + (*p)[1] = (unsigned char)( t >> 16 ); + (*p)[2] = (unsigned char)( t >> 8 ); + (*p)[3] = (unsigned char)( t ); + *p += 4; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR + ret ); +#endif + + ret = ssl_cookie_hmac( &ctx->hmac_ctx, *p - 4, + p, end, cli_id, cli_id_len ); + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR + + MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +/* + * Check a cookie + */ +int mbedtls_ssl_cookie_check( void *p_ctx, + const unsigned char *cookie, size_t cookie_len, + const unsigned char *cli_id, size_t cli_id_len ) +{ + unsigned char ref_hmac[COOKIE_HMAC_LEN]; + int ret = 0; + unsigned char *p = ref_hmac; + mbedtls_ssl_cookie_ctx *ctx = (mbedtls_ssl_cookie_ctx *) p_ctx; + unsigned long cur_time, cookie_time; + + if( ctx == NULL || cli_id == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( cookie_len != COOKIE_LEN ) + return( -1 ); + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR + ret ); +#endif + + if( ssl_cookie_hmac( &ctx->hmac_ctx, cookie, + &p, p + sizeof( ref_hmac ), + cli_id, cli_id_len ) != 0 ) + ret = -1; + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR + + MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + if( ret != 0 ) + return( ret ); + + if( mbedtls_ssl_safer_memcmp( cookie + 4, ref_hmac, sizeof( ref_hmac ) ) != 0 ) + return( -1 ); + +#if defined(MBEDTLS_HAVE_TIME) + cur_time = (unsigned long) mbedtls_time( NULL ); +#else + cur_time = ctx->serial; +#endif + + cookie_time = ( (unsigned long) cookie[0] << 24 ) | + ( (unsigned long) cookie[1] << 16 ) | + ( (unsigned long) cookie[2] << 8 ) | + ( (unsigned long) cookie[3] ); + + if( ctx->timeout != 0 && cur_time - cookie_time > ctx->timeout ) + return( -1 ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_COOKIE_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/ssl_invasive.h b/Android/Level4/app/src/main/c/mbedtls/library/ssl_invasive.h new file mode 100644 index 0000000..babbc27 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/ssl_invasive.h @@ -0,0 +1,100 @@ +/** + * \file ssl_invasive.h + * + * \brief SSL module: interfaces for invasive testing only. + * + * The interfaces in this file are intended for testing purposes only. + * They SHOULD NOT be made available in library integrations except when + * building the library for testing. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 MBEDTLS_SSL_INVASIVE_H +#define MBEDTLS_SSL_INVASIVE_H + +#include "common.h" +#include "mbedtls/md.h" + +#if defined(MBEDTLS_TEST_HOOKS) && \ + defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) +/** \brief Compute the HMAC of variable-length data with constant flow. + * + * This function computes the HMAC of the concatenation of \p add_data and \p + * data, and does with a code flow and memory access pattern that does not + * depend on \p data_len_secret, but only on \p min_data_len and \p + * max_data_len. In particular, this function always reads exactly \p + * max_data_len bytes from \p data. + * + * \param ctx The HMAC context. It must have keys configured + * with mbedtls_md_hmac_starts() and use one of the + * following hashes: SHA-384, SHA-256, SHA-1 or MD-5. + * It is reset using mbedtls_md_hmac_reset() after + * the computation is complete to prepare for the + * next computation. + * \param add_data The additional data prepended to \p data. This + * must point to a readable buffer of \p add_data_len + * bytes. + * \param add_data_len The length of \p add_data in bytes. + * \param data The data appended to \p add_data. This must point + * to a readable buffer of \p max_data_len bytes. + * \param data_len_secret The length of the data to process in \p data. + * This must be no less than \p min_data_len and no + * greater than \p max_data_len. + * \param min_data_len The minimal length of \p data in bytes. + * \param max_data_len The maximal length of \p data in bytes. + * \param output The HMAC will be written here. This must point to + * a writable buffer of sufficient size to hold the + * HMAC value. + * + * \retval 0 + * Success. + * \retval MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED + * The hardware accelerator failed. + */ +int mbedtls_ssl_cf_hmac( + mbedtls_md_context_t *ctx, + const unsigned char *add_data, size_t add_data_len, + const unsigned char *data, size_t data_len_secret, + size_t min_data_len, size_t max_data_len, + unsigned char *output ); + +/** \brief Copy data from a secret position with constant flow. + * + * This function copies \p len bytes from \p src_base + \p offset_secret to \p + * dst, with a code flow and memory access pattern that does not depend on \p + * offset_secret, but only on \p offset_min, \p offset_max and \p len. + * + * \param dst The destination buffer. This must point to a writable + * buffer of at least \p len bytes. + * \param src_base The base of the source buffer. This must point to a + * readable buffer of at least \p offset_max + \p len + * bytes. + * \param offset_secret The offset in the source buffer from which to copy. + * This must be no less than \p offset_min and no greater + * than \p offset_max. + * \param offset_min The minimal value of \p offset_secret. + * \param offset_max The maximal value of \p offset_secret. + * \param len The number of bytes to copy. + */ +void mbedtls_ssl_cf_memcpy_offset( unsigned char *dst, + const unsigned char *src_base, + size_t offset_secret, + size_t offset_min, size_t offset_max, + size_t len ); +#endif /* MBEDTLS_TEST_HOOKS && MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */ + +#endif /* MBEDTLS_SSL_INVASIVE_H */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/ssl_msg.c b/Android/Level4/app/src/main/c/mbedtls/library/ssl_msg.c new file mode 100644 index 0000000..bdf882d --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/ssl_msg.c @@ -0,0 +1,6035 @@ +/* + * Generic SSL/TLS messaging layer functions + * (record layer + retransmission state machine) + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ +/* + * The SSL 3.0 specification was drafted by Netscape in 1996, + * and became an IETF standard in 1999. + * + * http://wp.netscape.com/eng/ssl3/ + * http://www.ietf.org/rfc/rfc2246.txt + * http://www.ietf.org/rfc/rfc4346.txt + */ + +#include "common.h" + +#if defined(MBEDTLS_SSL_TLS_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/ssl.h" +#include "mbedtls/ssl_internal.h" +#include "mbedtls/debug.h" +#include "mbedtls/error.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/version.h" + +#include "ssl_invasive.h" + +#include + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "mbedtls/psa_util.h" +#include "psa/crypto.h" +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#include "mbedtls/oid.h" +#endif + +static uint32_t ssl_get_hs_total_len( mbedtls_ssl_context const *ssl ); + +/* + * Start a timer. + * Passing millisecs = 0 cancels a running timer. + */ +void mbedtls_ssl_set_timer( mbedtls_ssl_context *ssl, uint32_t millisecs ) +{ + if( ssl->f_set_timer == NULL ) + return; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "set_timer to %d ms", (int) millisecs ) ); + ssl->f_set_timer( ssl->p_timer, millisecs / 4, millisecs ); +} + +/* + * Return -1 is timer is expired, 0 if it isn't. + */ +int mbedtls_ssl_check_timer( mbedtls_ssl_context *ssl ) +{ + if( ssl->f_get_timer == NULL ) + return( 0 ); + + if( ssl->f_get_timer( ssl->p_timer ) == 2 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "timer expired" ) ); + return( -1 ); + } + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_RECORD_CHECKING) +static int ssl_parse_record_header( mbedtls_ssl_context const *ssl, + unsigned char *buf, + size_t len, + mbedtls_record *rec ); + +int mbedtls_ssl_check_record( mbedtls_ssl_context const *ssl, + unsigned char *buf, + size_t buflen ) +{ + int ret = 0; + MBEDTLS_SSL_DEBUG_MSG( 1, ( "=> mbedtls_ssl_check_record" ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "record buffer", buf, buflen ); + + /* We don't support record checking in TLS because + * (a) there doesn't seem to be a usecase for it, and + * (b) In SSLv3 and TLS 1.0, CBC record decryption has state + * and we'd need to backup the transform here. + */ + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_STREAM ) + { + ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + goto exit; + } +#if defined(MBEDTLS_SSL_PROTO_DTLS) + else + { + mbedtls_record rec; + + ret = ssl_parse_record_header( ssl, buf, buflen, &rec ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 3, "ssl_parse_record_header", ret ); + goto exit; + } + + if( ssl->transform_in != NULL ) + { + ret = mbedtls_ssl_decrypt_buf( ssl, ssl->transform_in, &rec ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 3, "mbedtls_ssl_decrypt_buf", ret ); + goto exit; + } + } + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +exit: + /* On success, we have decrypted the buffer in-place, so make + * sure we don't leak any plaintext data. */ + mbedtls_platform_zeroize( buf, buflen ); + + /* For the purpose of this API, treat messages with unexpected CID + * as well as such from future epochs as unexpected. */ + if( ret == MBEDTLS_ERR_SSL_UNEXPECTED_CID || + ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE ) + { + ret = MBEDTLS_ERR_SSL_UNEXPECTED_RECORD; + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "<= mbedtls_ssl_check_record" ) ); + return( ret ); +} +#endif /* MBEDTLS_SSL_RECORD_CHECKING */ + +#define SSL_DONT_FORCE_FLUSH 0 +#define SSL_FORCE_FLUSH 1 + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + +/* Forward declarations for functions related to message buffering. */ +static void ssl_buffering_free_slot( mbedtls_ssl_context *ssl, + uint8_t slot ); +static void ssl_free_buffered_record( mbedtls_ssl_context *ssl ); +static int ssl_load_buffered_message( mbedtls_ssl_context *ssl ); +static int ssl_load_buffered_record( mbedtls_ssl_context *ssl ); +static int ssl_buffer_message( mbedtls_ssl_context *ssl ); +static int ssl_buffer_future_record( mbedtls_ssl_context *ssl, + mbedtls_record const *rec ); +static int ssl_next_record_is_in_datagram( mbedtls_ssl_context *ssl ); + +static size_t ssl_get_maximum_datagram_size( mbedtls_ssl_context const *ssl ) +{ + size_t mtu = mbedtls_ssl_get_current_mtu( ssl ); +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t out_buf_len = ssl->out_buf_len; +#else + size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN; +#endif + + if( mtu != 0 && mtu < out_buf_len ) + return( mtu ); + + return( out_buf_len ); +} + +static int ssl_get_remaining_space_in_datagram( mbedtls_ssl_context const *ssl ) +{ + size_t const bytes_written = ssl->out_left; + size_t const mtu = ssl_get_maximum_datagram_size( ssl ); + + /* Double-check that the write-index hasn't gone + * past what we can transmit in a single datagram. */ + if( bytes_written > mtu ) + { + /* Should never happen... */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + return( (int) ( mtu - bytes_written ) ); +} + +static int ssl_get_remaining_payload_in_datagram( mbedtls_ssl_context const *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t remaining, expansion; + size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN; + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + const size_t mfl = mbedtls_ssl_get_output_max_frag_len( ssl ); + + if( max_len > mfl ) + max_len = mfl; + + /* By the standard (RFC 6066 Sect. 4), the MFL extension + * only limits the maximum record payload size, so in theory + * we would be allowed to pack multiple records of payload size + * MFL into a single datagram. However, this would mean that there's + * no way to explicitly communicate MTU restrictions to the peer. + * + * The following reduction of max_len makes sure that we never + * write datagrams larger than MFL + Record Expansion Overhead. + */ + if( max_len <= ssl->out_left ) + return( 0 ); + + max_len -= ssl->out_left; +#endif + + ret = ssl_get_remaining_space_in_datagram( ssl ); + if( ret < 0 ) + return( ret ); + remaining = (size_t) ret; + + ret = mbedtls_ssl_get_record_expansion( ssl ); + if( ret < 0 ) + return( ret ); + expansion = (size_t) ret; + + if( remaining <= expansion ) + return( 0 ); + + remaining -= expansion; + if( remaining >= max_len ) + remaining = max_len; + + return( (int) remaining ); +} + +/* + * Double the retransmit timeout value, within the allowed range, + * returning -1 if the maximum value has already been reached. + */ +static int ssl_double_retransmit_timeout( mbedtls_ssl_context *ssl ) +{ + uint32_t new_timeout; + + if( ssl->handshake->retransmit_timeout >= ssl->conf->hs_timeout_max ) + return( -1 ); + + /* Implement the final paragraph of RFC 6347 section 4.1.1.1 + * in the following way: after the initial transmission and a first + * retransmission, back off to a temporary estimated MTU of 508 bytes. + * This value is guaranteed to be deliverable (if not guaranteed to be + * delivered) of any compliant IPv4 (and IPv6) network, and should work + * on most non-IP stacks too. */ + if( ssl->handshake->retransmit_timeout != ssl->conf->hs_timeout_min ) + { + ssl->handshake->mtu = 508; + MBEDTLS_SSL_DEBUG_MSG( 2, ( "mtu autoreduction to %d bytes", ssl->handshake->mtu ) ); + } + + new_timeout = 2 * ssl->handshake->retransmit_timeout; + + /* Avoid arithmetic overflow and range overflow */ + if( new_timeout < ssl->handshake->retransmit_timeout || + new_timeout > ssl->conf->hs_timeout_max ) + { + new_timeout = ssl->conf->hs_timeout_max; + } + + ssl->handshake->retransmit_timeout = new_timeout; + MBEDTLS_SSL_DEBUG_MSG( 3, ( "update timeout value to %d millisecs", + ssl->handshake->retransmit_timeout ) ); + + return( 0 ); +} + +static void ssl_reset_retransmit_timeout( mbedtls_ssl_context *ssl ) +{ + ssl->handshake->retransmit_timeout = ssl->conf->hs_timeout_min; + MBEDTLS_SSL_DEBUG_MSG( 3, ( "update timeout value to %d millisecs", + ssl->handshake->retransmit_timeout ) ); +} +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) +int (*mbedtls_ssl_hw_record_init)( mbedtls_ssl_context *ssl, + const unsigned char *key_enc, const unsigned char *key_dec, + size_t keylen, + const unsigned char *iv_enc, const unsigned char *iv_dec, + size_t ivlen, + const unsigned char *mac_enc, const unsigned char *mac_dec, + size_t maclen ) = NULL; +int (*mbedtls_ssl_hw_record_activate)( mbedtls_ssl_context *ssl, int direction) = NULL; +int (*mbedtls_ssl_hw_record_reset)( mbedtls_ssl_context *ssl ) = NULL; +int (*mbedtls_ssl_hw_record_write)( mbedtls_ssl_context *ssl ) = NULL; +int (*mbedtls_ssl_hw_record_read)( mbedtls_ssl_context *ssl ) = NULL; +int (*mbedtls_ssl_hw_record_finish)( mbedtls_ssl_context *ssl ) = NULL; +#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ + +/* + * Encryption/decryption functions + */ + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL) + +static size_t ssl_compute_padding_length( size_t len, + size_t granularity ) +{ + return( ( granularity - ( len + 1 ) % granularity ) % granularity ); +} + +/* This functions transforms a (D)TLS plaintext fragment and a record content + * type into an instance of the (D)TLSInnerPlaintext structure. This is used + * in DTLS 1.2 + CID and within TLS 1.3 to allow flexible padding and to protect + * a record's content type. + * + * struct { + * opaque content[DTLSPlaintext.length]; + * ContentType real_type; + * uint8 zeros[length_of_padding]; + * } (D)TLSInnerPlaintext; + * + * Input: + * - `content`: The beginning of the buffer holding the + * plaintext to be wrapped. + * - `*content_size`: The length of the plaintext in Bytes. + * - `max_len`: The number of Bytes available starting from + * `content`. This must be `>= *content_size`. + * - `rec_type`: The desired record content type. + * + * Output: + * - `content`: The beginning of the resulting (D)TLSInnerPlaintext structure. + * - `*content_size`: The length of the resulting (D)TLSInnerPlaintext structure. + * + * Returns: + * - `0` on success. + * - A negative error code if `max_len` didn't offer enough space + * for the expansion. + */ +static int ssl_build_inner_plaintext( unsigned char *content, + size_t *content_size, + size_t remaining, + uint8_t rec_type, + size_t pad ) +{ + size_t len = *content_size; + + /* Write real content type */ + if( remaining == 0 ) + return( -1 ); + content[ len ] = rec_type; + len++; + remaining--; + + if( remaining < pad ) + return( -1 ); + memset( content + len, 0, pad ); + len += pad; + remaining -= pad; + + *content_size = len; + return( 0 ); +} + +/* This function parses a (D)TLSInnerPlaintext structure. + * See ssl_build_inner_plaintext() for details. */ +static int ssl_parse_inner_plaintext( unsigned char const *content, + size_t *content_size, + uint8_t *rec_type ) +{ + size_t remaining = *content_size; + + /* Determine length of padding by skipping zeroes from the back. */ + do + { + if( remaining == 0 ) + return( -1 ); + remaining--; + } while( content[ remaining ] == 0 ); + + *content_size = remaining; + *rec_type = content[ remaining ]; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID || + MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */ + +/* `add_data` must have size 13 Bytes if the CID extension is disabled, + * and 13 + 1 + CID-length Bytes if the CID extension is enabled. */ +static void ssl_extract_add_data_from_record( unsigned char* add_data, + size_t *add_data_len, + mbedtls_record *rec, + unsigned minor_ver ) +{ + /* Quoting RFC 5246 (TLS 1.2): + * + * additional_data = seq_num + TLSCompressed.type + + * TLSCompressed.version + TLSCompressed.length; + * + * For the CID extension, this is extended as follows + * (quoting draft-ietf-tls-dtls-connection-id-05, + * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05): + * + * additional_data = seq_num + DTLSPlaintext.type + + * DTLSPlaintext.version + + * cid + + * cid_length + + * length_of_DTLSInnerPlaintext; + * + * For TLS 1.3, the record sequence number is dropped from the AAD + * and encoded within the nonce of the AEAD operation instead. + */ + + unsigned char *cur = add_data; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL) + if( minor_ver != MBEDTLS_SSL_MINOR_VERSION_4 ) +#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */ + { + ((void) minor_ver); + memcpy( cur, rec->ctr, sizeof( rec->ctr ) ); + cur += sizeof( rec->ctr ); + } + + *cur = rec->type; + cur++; + + memcpy( cur, rec->ver, sizeof( rec->ver ) ); + cur += sizeof( rec->ver ); + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + if( rec->cid_len != 0 ) + { + memcpy( cur, rec->cid, rec->cid_len ); + cur += rec->cid_len; + + *cur = rec->cid_len; + cur++; + + cur[0] = ( rec->data_len >> 8 ) & 0xFF; + cur[1] = ( rec->data_len >> 0 ) & 0xFF; + cur += 2; + } + else +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + { + cur[0] = ( rec->data_len >> 8 ) & 0xFF; + cur[1] = ( rec->data_len >> 0 ) & 0xFF; + cur += 2; + } + + *add_data_len = cur - add_data; +} + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + +#define SSL3_MAC_MAX_BYTES 20 /* MD-5 or SHA-1 */ + +/* + * SSLv3.0 MAC functions + */ +static void ssl_mac( mbedtls_md_context_t *md_ctx, + const unsigned char *secret, + const unsigned char *buf, size_t len, + const unsigned char *ctr, int type, + unsigned char out[SSL3_MAC_MAX_BYTES] ) +{ + unsigned char header[11]; + unsigned char padding[48]; + int padlen; + int md_size = mbedtls_md_get_size( md_ctx->md_info ); + int md_type = mbedtls_md_get_type( md_ctx->md_info ); + + /* Only MD5 and SHA-1 supported */ + if( md_type == MBEDTLS_MD_MD5 ) + padlen = 48; + else + padlen = 40; + + memcpy( header, ctr, 8 ); + header[ 8] = (unsigned char) type; + header[ 9] = (unsigned char)( len >> 8 ); + header[10] = (unsigned char)( len ); + + memset( padding, 0x36, padlen ); + mbedtls_md_starts( md_ctx ); + mbedtls_md_update( md_ctx, secret, md_size ); + mbedtls_md_update( md_ctx, padding, padlen ); + mbedtls_md_update( md_ctx, header, 11 ); + mbedtls_md_update( md_ctx, buf, len ); + mbedtls_md_finish( md_ctx, out ); + + memset( padding, 0x5C, padlen ); + mbedtls_md_starts( md_ctx ); + mbedtls_md_update( md_ctx, secret, md_size ); + mbedtls_md_update( md_ctx, padding, padlen ); + mbedtls_md_update( md_ctx, out, md_size ); + mbedtls_md_finish( md_ctx, out ); +} +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + +#if defined(MBEDTLS_GCM_C) || \ + defined(MBEDTLS_CCM_C) || \ + defined(MBEDTLS_CHACHAPOLY_C) +static int ssl_transform_aead_dynamic_iv_is_explicit( + mbedtls_ssl_transform const *transform ) +{ + return( transform->ivlen != transform->fixed_ivlen ); +} + +/* Compute IV := ( fixed_iv || 0 ) XOR ( 0 || dynamic_IV ) + * + * Concretely, this occurs in two variants: + * + * a) Fixed and dynamic IV lengths add up to total IV length, giving + * IV = fixed_iv || dynamic_iv + * + * This variant is used in TLS 1.2 when used with GCM or CCM. + * + * b) Fixed IV lengths matches total IV length, giving + * IV = fixed_iv XOR ( 0 || dynamic_iv ) + * + * This variant occurs in TLS 1.3 and for TLS 1.2 when using ChaChaPoly. + * + * See also the documentation of mbedtls_ssl_transform. + * + * This function has the precondition that + * + * dst_iv_len >= max( fixed_iv_len, dynamic_iv_len ) + * + * which has to be ensured by the caller. If this precondition + * violated, the behavior of this function is undefined. + */ +static void ssl_build_record_nonce( unsigned char *dst_iv, + size_t dst_iv_len, + unsigned char const *fixed_iv, + size_t fixed_iv_len, + unsigned char const *dynamic_iv, + size_t dynamic_iv_len ) +{ + size_t i; + + /* Start with Fixed IV || 0 */ + memset( dst_iv, 0, dst_iv_len ); + memcpy( dst_iv, fixed_iv, fixed_iv_len ); + + dst_iv += dst_iv_len - dynamic_iv_len; + for( i = 0; i < dynamic_iv_len; i++ ) + dst_iv[i] ^= dynamic_iv[i]; +} +#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C || MBEDTLS_CHACHAPOLY_C */ + +int mbedtls_ssl_encrypt_buf( mbedtls_ssl_context *ssl, + mbedtls_ssl_transform *transform, + mbedtls_record *rec, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + mbedtls_cipher_mode_t mode; + int auth_done = 0; + unsigned char * data; + unsigned char add_data[13 + 1 + MBEDTLS_SSL_CID_OUT_LEN_MAX ]; + size_t add_data_len; + size_t post_avail; + + /* The SSL context is only used for debugging purposes! */ +#if !defined(MBEDTLS_DEBUG_C) + ssl = NULL; /* make sure we don't use it except for debug */ + ((void) ssl); +#endif + + /* The PRNG is used for dynamic IV generation that's used + * for CBC transformations in TLS 1.1 and TLS 1.2. */ +#if !( defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) && \ + ( defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) ) ) + ((void) f_rng); + ((void) p_rng); +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> encrypt buf" ) ); + + if( transform == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "no transform provided to encrypt_buf" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + if( rec == NULL + || rec->buf == NULL + || rec->buf_len < rec->data_offset + || rec->buf_len - rec->data_offset < rec->data_len +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + || rec->cid_len != 0 +#endif + ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad record structure provided to encrypt_buf" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + data = rec->buf + rec->data_offset; + post_avail = rec->buf_len - ( rec->data_len + rec->data_offset ); + MBEDTLS_SSL_DEBUG_BUF( 4, "before encrypt: output payload", + data, rec->data_len ); + + mode = mbedtls_cipher_get_cipher_mode( &transform->cipher_ctx_enc ); + + if( rec->data_len > MBEDTLS_SSL_OUT_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Record content %u too large, maximum %d", + (unsigned) rec->data_len, + MBEDTLS_SSL_OUT_CONTENT_LEN ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + /* The following two code paths implement the (D)TLSInnerPlaintext + * structure present in TLS 1.3 and DTLS 1.2 + CID. + * + * See ssl_build_inner_plaintext() for more information. + * + * Note that this changes `rec->data_len`, and hence + * `post_avail` needs to be recalculated afterwards. + * + * Note also that the two code paths cannot occur simultaneously + * since they apply to different versions of the protocol. There + * is hence no risk of double-addition of the inner plaintext. + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL) + if( transform->minor_ver == MBEDTLS_SSL_MINOR_VERSION_4 ) + { + size_t padding = + ssl_compute_padding_length( rec->data_len, + MBEDTLS_SSL_TLS1_3_PADDING_GRANULARITY ); + if( ssl_build_inner_plaintext( data, + &rec->data_len, + post_avail, + rec->type, + padding ) != 0 ) + { + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + rec->type = MBEDTLS_SSL_MSG_APPLICATION_DATA; + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */ + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + /* + * Add CID information + */ + rec->cid_len = transform->out_cid_len; + memcpy( rec->cid, transform->out_cid, transform->out_cid_len ); + MBEDTLS_SSL_DEBUG_BUF( 3, "CID", rec->cid, rec->cid_len ); + + if( rec->cid_len != 0 ) + { + size_t padding = + ssl_compute_padding_length( rec->data_len, + MBEDTLS_SSL_CID_PADDING_GRANULARITY ); + /* + * Wrap plaintext into DTLSInnerPlaintext structure. + * See ssl_build_inner_plaintext() for more information. + * + * Note that this changes `rec->data_len`, and hence + * `post_avail` needs to be recalculated afterwards. + */ + if( ssl_build_inner_plaintext( data, + &rec->data_len, + post_avail, + rec->type, + padding ) != 0 ) + { + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + rec->type = MBEDTLS_SSL_MSG_CID; + } +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + + post_avail = rec->buf_len - ( rec->data_len + rec->data_offset ); + + /* + * Add MAC before if needed + */ +#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) + if( mode == MBEDTLS_MODE_STREAM || + ( mode == MBEDTLS_MODE_CBC +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + && transform->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED +#endif + ) ) + { + if( post_avail < transform->maclen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( transform->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + unsigned char mac[SSL3_MAC_MAX_BYTES]; + ssl_mac( &transform->md_ctx_enc, transform->mac_enc, + data, rec->data_len, rec->ctr, rec->type, mac ); + memcpy( data + rec->data_len, mac, transform->maclen ); + } + else +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( transform->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 ) + { + unsigned char mac[MBEDTLS_SSL_MAC_ADD]; + + ssl_extract_add_data_from_record( add_data, &add_data_len, rec, + transform->minor_ver ); + + mbedtls_md_hmac_update( &transform->md_ctx_enc, add_data, + add_data_len ); + mbedtls_md_hmac_update( &transform->md_ctx_enc, + data, rec->data_len ); + mbedtls_md_hmac_finish( &transform->md_ctx_enc, mac ); + mbedtls_md_hmac_reset( &transform->md_ctx_enc ); + + memcpy( data + rec->data_len, mac, transform->maclen ); + } + else +#endif + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_BUF( 4, "computed mac", data + rec->data_len, + transform->maclen ); + + rec->data_len += transform->maclen; + post_avail -= transform->maclen; + auth_done++; + } +#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */ + + /* + * Encrypt + */ +#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) + if( mode == MBEDTLS_MODE_STREAM ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t olen; + MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, " + "including %d bytes of padding", + rec->data_len, 0 ) ); + + if( ( ret = mbedtls_cipher_crypt( &transform->cipher_ctx_enc, + transform->iv_enc, transform->ivlen, + data, rec->data_len, + data, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret ); + return( ret ); + } + + if( rec->data_len != olen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } + else +#endif /* MBEDTLS_ARC4_C || MBEDTLS_CIPHER_NULL_CIPHER */ + +#if defined(MBEDTLS_GCM_C) || \ + defined(MBEDTLS_CCM_C) || \ + defined(MBEDTLS_CHACHAPOLY_C) + if( mode == MBEDTLS_MODE_GCM || + mode == MBEDTLS_MODE_CCM || + mode == MBEDTLS_MODE_CHACHAPOLY ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char iv[12]; + unsigned char *dynamic_iv; + size_t dynamic_iv_len; + int dynamic_iv_is_explicit = + ssl_transform_aead_dynamic_iv_is_explicit( transform ); + + /* Check that there's space for the authentication tag. */ + if( post_avail < transform->taglen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + /* + * Build nonce for AEAD encryption. + * + * Note: In the case of CCM and GCM in TLS 1.2, the dynamic + * part of the IV is prepended to the ciphertext and + * can be chosen freely - in particular, it need not + * agree with the record sequence number. + * However, since ChaChaPoly as well as all AEAD modes + * in TLS 1.3 use the record sequence number as the + * dynamic part of the nonce, we uniformly use the + * record sequence number here in all cases. + */ + dynamic_iv = rec->ctr; + dynamic_iv_len = sizeof( rec->ctr ); + + ssl_build_record_nonce( iv, sizeof( iv ), + transform->iv_enc, + transform->fixed_ivlen, + dynamic_iv, + dynamic_iv_len ); + + /* + * Build additional data for AEAD encryption. + * This depends on the TLS version. + */ + ssl_extract_add_data_from_record( add_data, &add_data_len, rec, + transform->minor_ver ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "IV used (internal)", + iv, transform->ivlen ); + MBEDTLS_SSL_DEBUG_BUF( 4, "IV used (transmitted)", + dynamic_iv, + dynamic_iv_is_explicit ? dynamic_iv_len : 0 ); + MBEDTLS_SSL_DEBUG_BUF( 4, "additional data used for AEAD", + add_data, add_data_len ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, " + "including 0 bytes of padding", + rec->data_len ) ); + + /* + * Encrypt and authenticate + */ + + if( ( ret = mbedtls_cipher_auth_encrypt( &transform->cipher_ctx_enc, + iv, transform->ivlen, + add_data, add_data_len, /* add data */ + data, rec->data_len, /* source */ + data, &rec->data_len, /* destination */ + data + rec->data_len, transform->taglen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_auth_encrypt", ret ); + return( ret ); + } + MBEDTLS_SSL_DEBUG_BUF( 4, "after encrypt: tag", + data + rec->data_len, transform->taglen ); + /* Account for authentication tag. */ + rec->data_len += transform->taglen; + post_avail -= transform->taglen; + + /* + * Prefix record content with dynamic IV in case it is explicit. + */ + if( dynamic_iv_is_explicit != 0 ) + { + if( rec->data_offset < dynamic_iv_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + memcpy( data - dynamic_iv_len, dynamic_iv, dynamic_iv_len ); + rec->data_offset -= dynamic_iv_len; + rec->data_len += dynamic_iv_len; + } + + auth_done++; + } + else +#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C || MBEDTLS_CHACHAPOLY_C */ +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) + if( mode == MBEDTLS_MODE_CBC ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t padlen, i; + size_t olen; + + /* Currently we're always using minimal padding + * (up to 255 bytes would be allowed). */ + padlen = transform->ivlen - ( rec->data_len + 1 ) % transform->ivlen; + if( padlen == transform->ivlen ) + padlen = 0; + + /* Check there's enough space in the buffer for the padding. */ + if( post_avail < padlen + 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + for( i = 0; i <= padlen; i++ ) + data[rec->data_len + i] = (unsigned char) padlen; + + rec->data_len += padlen + 1; + post_avail -= padlen + 1; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) + /* + * Prepend per-record IV for block cipher in TLS v1.1 and up as per + * Method 1 (6.2.3.2. in RFC4346 and RFC5246) + */ + if( transform->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) + { + if( f_rng == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "No PRNG provided to encrypt_record routine" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + if( rec->data_offset < transform->ivlen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + /* + * Generate IV + */ + ret = f_rng( p_rng, transform->iv_enc, transform->ivlen ); + if( ret != 0 ) + return( ret ); + + memcpy( data - transform->ivlen, transform->iv_enc, + transform->ivlen ); + + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */ + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, " + "including %d bytes of IV and %d bytes of padding", + rec->data_len, transform->ivlen, + padlen + 1 ) ); + + if( ( ret = mbedtls_cipher_crypt( &transform->cipher_ctx_enc, + transform->iv_enc, + transform->ivlen, + data, rec->data_len, + data, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret ); + return( ret ); + } + + if( rec->data_len != olen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) + if( transform->minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 ) + { + /* + * Save IV in SSL3 and TLS1 + */ + memcpy( transform->iv_enc, transform->cipher_ctx_enc.iv, + transform->ivlen ); + } + else +#endif + { + data -= transform->ivlen; + rec->data_offset -= transform->ivlen; + rec->data_len += transform->ivlen; + } + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + if( auth_done == 0 ) + { + unsigned char mac[MBEDTLS_SSL_MAC_ADD]; + + /* + * MAC(MAC_write_key, seq_num + + * TLSCipherText.type + + * TLSCipherText.version + + * length_of( (IV +) ENC(...) ) + + * IV + // except for TLS 1.0 + * ENC(content + padding + padding_length)); + */ + + if( post_avail < transform->maclen) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + ssl_extract_add_data_from_record( add_data, &add_data_len, + rec, transform->minor_ver ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "using encrypt then mac" ) ); + MBEDTLS_SSL_DEBUG_BUF( 4, "MAC'd meta-data", add_data, + add_data_len ); + + mbedtls_md_hmac_update( &transform->md_ctx_enc, add_data, + add_data_len ); + mbedtls_md_hmac_update( &transform->md_ctx_enc, + data, rec->data_len ); + mbedtls_md_hmac_finish( &transform->md_ctx_enc, mac ); + mbedtls_md_hmac_reset( &transform->md_ctx_enc ); + + memcpy( data + rec->data_len, mac, transform->maclen ); + + rec->data_len += transform->maclen; + post_avail -= transform->maclen; + auth_done++; + } +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + } + else +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC) */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* Make extra sure authentication was performed, exactly once */ + if( auth_done != 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= encrypt buf" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) +/* + * Turn a bit into a mask: + * - if bit == 1, return the all-bits 1 mask, aka (size_t) -1 + * - if bit == 0, return the all-bits 0 mask, aka 0 + * + * This function can be used to write constant-time code by replacing branches + * with bit operations using masks. + * + * This function is implemented without using comparison operators, as those + * might be translated to branches by some compilers on some platforms. + */ +static size_t mbedtls_ssl_cf_mask_from_bit( size_t bit ) +{ + /* MSVC has a warning about unary minus on unsigned integer types, + * but this is well-defined and precisely what we want to do here. */ +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + return -bit; +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif +} + +/* + * Constant-flow mask generation for "less than" comparison: + * - if x < y, return all bits 1, that is (size_t) -1 + * - otherwise, return all bits 0, that is 0 + * + * This function can be used to write constant-time code by replacing branches + * with bit operations using masks. + * + * This function is implemented without using comparison operators, as those + * might be translated to branches by some compilers on some platforms. + */ +static size_t mbedtls_ssl_cf_mask_lt( size_t x, size_t y ) +{ + /* This has the most significant bit set if and only if x < y */ + const size_t sub = x - y; + + /* sub1 = (x < y) ? 1 : 0 */ + const size_t sub1 = sub >> ( sizeof( sub ) * 8 - 1 ); + + /* mask = (x < y) ? 0xff... : 0x00... */ + const size_t mask = mbedtls_ssl_cf_mask_from_bit( sub1 ); + + return( mask ); +} + +/* + * Constant-flow mask generation for "greater or equal" comparison: + * - if x >= y, return all bits 1, that is (size_t) -1 + * - otherwise, return all bits 0, that is 0 + * + * This function can be used to write constant-time code by replacing branches + * with bit operations using masks. + * + * This function is implemented without using comparison operators, as those + * might be translated to branches by some compilers on some platforms. + */ +static size_t mbedtls_ssl_cf_mask_ge( size_t x, size_t y ) +{ + return( ~mbedtls_ssl_cf_mask_lt( x, y ) ); +} + +/* + * Constant-flow boolean "equal" comparison: + * return x == y + * + * This function can be used to write constant-time code by replacing branches + * with bit operations - it can be used in conjunction with + * mbedtls_ssl_cf_mask_from_bit(). + * + * This function is implemented without using comparison operators, as those + * might be translated to branches by some compilers on some platforms. + */ +static size_t mbedtls_ssl_cf_bool_eq( size_t x, size_t y ) +{ + /* diff = 0 if x == y, non-zero otherwise */ + const size_t diff = x ^ y; + + /* MSVC has a warning about unary minus on unsigned integer types, + * but this is well-defined and precisely what we want to do here. */ +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + + /* diff_msb's most significant bit is equal to x != y */ + const size_t diff_msb = ( diff | -diff ); + +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif + + /* diff1 = (x != y) ? 1 : 0 */ + const size_t diff1 = diff_msb >> ( sizeof( diff_msb ) * 8 - 1 ); + + return( 1 ^ diff1 ); +} + +/* + * Constant-flow conditional memcpy: + * - if c1 == c2, equivalent to memcpy(dst, src, len), + * - otherwise, a no-op, + * but with execution flow independent of the values of c1 and c2. + * + * This function is implemented without using comparison operators, as those + * might be translated to branches by some compilers on some platforms. + */ +static void mbedtls_ssl_cf_memcpy_if_eq( unsigned char *dst, + const unsigned char *src, + size_t len, + size_t c1, size_t c2 ) +{ + /* mask = c1 == c2 ? 0xff : 0x00 */ + const size_t equal = mbedtls_ssl_cf_bool_eq( c1, c2 ); + const unsigned char mask = (unsigned char) mbedtls_ssl_cf_mask_from_bit( equal ); + + /* dst[i] = c1 == c2 ? src[i] : dst[i] */ + for( size_t i = 0; i < len; i++ ) + dst[i] = ( src[i] & mask ) | ( dst[i] & ~mask ); +} + +/* + * Compute HMAC of variable-length data with constant flow. + * + * Only works with MD-5, SHA-1, SHA-256 and SHA-384. + * (Otherwise, computation of block_size needs to be adapted.) + */ +MBEDTLS_STATIC_TESTABLE int mbedtls_ssl_cf_hmac( + mbedtls_md_context_t *ctx, + const unsigned char *add_data, size_t add_data_len, + const unsigned char *data, size_t data_len_secret, + size_t min_data_len, size_t max_data_len, + unsigned char *output ) +{ + /* + * This function breaks the HMAC abstraction and uses the md_clone() + * extension to the MD API in order to get constant-flow behaviour. + * + * HMAC(msg) is defined as HASH(okey + HASH(ikey + msg)) where + means + * concatenation, and okey/ikey are the XOR of the key with some fixed bit + * patterns (see RFC 2104, sec. 2), which are stored in ctx->hmac_ctx. + * + * We'll first compute inner_hash = HASH(ikey + msg) by hashing up to + * minlen, then cloning the context, and for each byte up to maxlen + * finishing up the hash computation, keeping only the correct result. + * + * Then we only need to compute HASH(okey + inner_hash) and we're done. + */ + const mbedtls_md_type_t md_alg = mbedtls_md_get_type( ctx->md_info ); + /* TLS 1.0-1.2 only support SHA-384, SHA-256, SHA-1, MD-5, + * all of which have the same block size except SHA-384. */ + const size_t block_size = md_alg == MBEDTLS_MD_SHA384 ? 128 : 64; + const unsigned char * const ikey = ctx->hmac_ctx; + const unsigned char * const okey = ikey + block_size; + const size_t hash_size = mbedtls_md_get_size( ctx->md_info ); + + unsigned char aux_out[MBEDTLS_MD_MAX_SIZE]; + mbedtls_md_context_t aux; + size_t offset; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + mbedtls_md_init( &aux ); + +#define MD_CHK( func_call ) \ + do { \ + ret = (func_call); \ + if( ret != 0 ) \ + goto cleanup; \ + } while( 0 ) + + MD_CHK( mbedtls_md_setup( &aux, ctx->md_info, 0 ) ); + + /* After hmac_start() of hmac_reset(), ikey has already been hashed, + * so we can start directly with the message */ + MD_CHK( mbedtls_md_update( ctx, add_data, add_data_len ) ); + MD_CHK( mbedtls_md_update( ctx, data, min_data_len ) ); + + /* For each possible length, compute the hash up to that point */ + for( offset = min_data_len; offset <= max_data_len; offset++ ) + { + MD_CHK( mbedtls_md_clone( &aux, ctx ) ); + MD_CHK( mbedtls_md_finish( &aux, aux_out ) ); + /* Keep only the correct inner_hash in the output buffer */ + mbedtls_ssl_cf_memcpy_if_eq( output, aux_out, hash_size, + offset, data_len_secret ); + + if( offset < max_data_len ) + MD_CHK( mbedtls_md_update( ctx, data + offset, 1 ) ); + } + + /* Now compute HASH(okey + inner_hash) */ + MD_CHK( mbedtls_md_starts( ctx ) ); + MD_CHK( mbedtls_md_update( ctx, okey, block_size ) ); + MD_CHK( mbedtls_md_update( ctx, output, hash_size ) ); + MD_CHK( mbedtls_md_finish( ctx, output ) ); + + /* Done, get ready for next time */ + MD_CHK( mbedtls_md_hmac_reset( ctx ) ); + +#undef MD_CHK + +cleanup: + mbedtls_md_free( &aux ); + return( ret ); +} + +/* + * Constant-flow memcpy from variable position in buffer. + * - functionally equivalent to memcpy(dst, src + offset_secret, len) + * - but with execution flow independent from the value of offset_secret. + */ +MBEDTLS_STATIC_TESTABLE void mbedtls_ssl_cf_memcpy_offset( + unsigned char *dst, + const unsigned char *src_base, + size_t offset_secret, + size_t offset_min, size_t offset_max, + size_t len ) +{ + size_t offset; + + for( offset = offset_min; offset <= offset_max; offset++ ) + { + mbedtls_ssl_cf_memcpy_if_eq( dst, src_base + offset, len, + offset, offset_secret ); + } +} +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */ + +int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context const *ssl, + mbedtls_ssl_transform *transform, + mbedtls_record *rec ) +{ + size_t olen; + mbedtls_cipher_mode_t mode; + int ret, auth_done = 0; +#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) + size_t padlen = 0, correct = 1; +#endif + unsigned char* data; + unsigned char add_data[13 + 1 + MBEDTLS_SSL_CID_IN_LEN_MAX ]; + size_t add_data_len; + +#if !defined(MBEDTLS_DEBUG_C) + ssl = NULL; /* make sure we don't use it except for debug */ + ((void) ssl); +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> decrypt buf" ) ); + if( rec == NULL || + rec->buf == NULL || + rec->buf_len < rec->data_offset || + rec->buf_len - rec->data_offset < rec->data_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad record structure provided to decrypt_buf" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + data = rec->buf + rec->data_offset; + mode = mbedtls_cipher_get_cipher_mode( &transform->cipher_ctx_dec ); + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + /* + * Match record's CID with incoming CID. + */ + if( rec->cid_len != transform->in_cid_len || + memcmp( rec->cid, transform->in_cid, rec->cid_len ) != 0 ) + { + return( MBEDTLS_ERR_SSL_UNEXPECTED_CID ); + } +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + +#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) + if( mode == MBEDTLS_MODE_STREAM ) + { + padlen = 0; + if( ( ret = mbedtls_cipher_crypt( &transform->cipher_ctx_dec, + transform->iv_dec, + transform->ivlen, + data, rec->data_len, + data, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret ); + return( ret ); + } + + if( rec->data_len != olen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } + else +#endif /* MBEDTLS_ARC4_C || MBEDTLS_CIPHER_NULL_CIPHER */ +#if defined(MBEDTLS_GCM_C) || \ + defined(MBEDTLS_CCM_C) || \ + defined(MBEDTLS_CHACHAPOLY_C) + if( mode == MBEDTLS_MODE_GCM || + mode == MBEDTLS_MODE_CCM || + mode == MBEDTLS_MODE_CHACHAPOLY ) + { + unsigned char iv[12]; + unsigned char *dynamic_iv; + size_t dynamic_iv_len; + + /* + * Extract dynamic part of nonce for AEAD decryption. + * + * Note: In the case of CCM and GCM in TLS 1.2, the dynamic + * part of the IV is prepended to the ciphertext and + * can be chosen freely - in particular, it need not + * agree with the record sequence number. + */ + dynamic_iv_len = sizeof( rec->ctr ); + if( ssl_transform_aead_dynamic_iv_is_explicit( transform ) == 1 ) + { + if( rec->data_len < dynamic_iv_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < explicit_iv_len (%d) ", + rec->data_len, + dynamic_iv_len ) ); + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } + dynamic_iv = data; + + data += dynamic_iv_len; + rec->data_offset += dynamic_iv_len; + rec->data_len -= dynamic_iv_len; + } + else + { + dynamic_iv = rec->ctr; + } + + /* Check that there's space for the authentication tag. */ + if( rec->data_len < transform->taglen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < taglen (%d) " ) ); + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } + rec->data_len -= transform->taglen; + + /* + * Prepare nonce from dynamic and static parts. + */ + ssl_build_record_nonce( iv, sizeof( iv ), + transform->iv_dec, + transform->fixed_ivlen, + dynamic_iv, + dynamic_iv_len ); + + /* + * Build additional data for AEAD encryption. + * This depends on the TLS version. + */ + ssl_extract_add_data_from_record( add_data, &add_data_len, rec, + transform->minor_ver ); + MBEDTLS_SSL_DEBUG_BUF( 4, "additional data used for AEAD", + add_data, add_data_len ); + + /* Because of the check above, we know that there are + * explicit_iv_len Bytes preceeding data, and taglen + * bytes following data + data_len. This justifies + * the debug message and the invocation of + * mbedtls_cipher_auth_decrypt() below. */ + + MBEDTLS_SSL_DEBUG_BUF( 4, "IV used", iv, transform->ivlen ); + MBEDTLS_SSL_DEBUG_BUF( 4, "TAG used", data + rec->data_len, + transform->taglen ); + + /* + * Decrypt and authenticate + */ + if( ( ret = mbedtls_cipher_auth_decrypt( &transform->cipher_ctx_dec, + iv, transform->ivlen, + add_data, add_data_len, + data, rec->data_len, + data, &olen, + data + rec->data_len, + transform->taglen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_auth_decrypt", ret ); + + if( ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED ) + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + + return( ret ); + } + auth_done++; + + /* Double-check that AEAD decryption doesn't change content length. */ + if( olen != rec->data_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } + else +#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C */ +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) + if( mode == MBEDTLS_MODE_CBC ) + { + size_t minlen = 0; + + /* + * Check immediate ciphertext sanity + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( transform->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) + { + /* The ciphertext is prefixed with the CBC IV. */ + minlen += transform->ivlen; + } +#endif + + /* Size considerations: + * + * - The CBC cipher text must not be empty and hence + * at least of size transform->ivlen. + * + * Together with the potential IV-prefix, this explains + * the first of the two checks below. + * + * - The record must contain a MAC, either in plain or + * encrypted, depending on whether Encrypt-then-MAC + * is used or not. + * - If it is, the message contains the IV-prefix, + * the CBC ciphertext, and the MAC. + * - If it is not, the padded plaintext, and hence + * the CBC ciphertext, has at least length maclen + 1 + * because there is at least the padding length byte. + * + * As the CBC ciphertext is not empty, both cases give the + * lower bound minlen + maclen + 1 on the record size, which + * we test for in the second check below. + */ + if( rec->data_len < minlen + transform->ivlen || + rec->data_len < minlen + transform->maclen + 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < max( ivlen(%d), maclen (%d) " + "+ 1 ) ( + expl IV )", rec->data_len, + transform->ivlen, + transform->maclen ) ); + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } + + /* + * Authenticate before decrypt if enabled + */ +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + if( transform->encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED ) + { + unsigned char mac_expect[MBEDTLS_SSL_MAC_ADD]; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "using encrypt then mac" ) ); + + /* Update data_len in tandem with add_data. + * + * The subtraction is safe because of the previous check + * data_len >= minlen + maclen + 1. + * + * Afterwards, we know that data + data_len is followed by at + * least maclen Bytes, which justifies the call to + * mbedtls_ssl_safer_memcmp() below. + * + * Further, we still know that data_len > minlen */ + rec->data_len -= transform->maclen; + ssl_extract_add_data_from_record( add_data, &add_data_len, rec, + transform->minor_ver ); + + /* Calculate expected MAC. */ + MBEDTLS_SSL_DEBUG_BUF( 4, "MAC'd meta-data", add_data, + add_data_len ); + mbedtls_md_hmac_update( &transform->md_ctx_dec, add_data, + add_data_len ); + mbedtls_md_hmac_update( &transform->md_ctx_dec, + data, rec->data_len ); + mbedtls_md_hmac_finish( &transform->md_ctx_dec, mac_expect ); + mbedtls_md_hmac_reset( &transform->md_ctx_dec ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "message mac", data + rec->data_len, + transform->maclen ); + MBEDTLS_SSL_DEBUG_BUF( 4, "expected mac", mac_expect, + transform->maclen ); + + /* Compare expected MAC with MAC at the end of the record. */ + if( mbedtls_ssl_safer_memcmp( data + rec->data_len, mac_expect, + transform->maclen ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "message mac does not match" ) ); + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } + auth_done++; + } +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + + /* + * Check length sanity + */ + + /* We know from above that data_len > minlen >= 0, + * so the following check in particular implies that + * data_len >= minlen + ivlen ( = minlen or 2 * minlen ). */ + if( rec->data_len % transform->ivlen != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) %% ivlen (%d) != 0", + rec->data_len, transform->ivlen ) ); + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } + +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) + /* + * Initialize for prepended IV for block cipher in TLS v1.1 and up + */ + if( transform->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) + { + /* Safe because data_len >= minlen + ivlen = 2 * ivlen. */ + memcpy( transform->iv_dec, data, transform->ivlen ); + + data += transform->ivlen; + rec->data_offset += transform->ivlen; + rec->data_len -= transform->ivlen; + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */ + + /* We still have data_len % ivlen == 0 and data_len >= ivlen here. */ + + if( ( ret = mbedtls_cipher_crypt( &transform->cipher_ctx_dec, + transform->iv_dec, transform->ivlen, + data, rec->data_len, data, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret ); + return( ret ); + } + + /* Double-check that length hasn't changed during decryption. */ + if( rec->data_len != olen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) + if( transform->minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 ) + { + /* + * Save IV in SSL3 and TLS1, where CBC decryption of consecutive + * records is equivalent to CBC decryption of the concatenation + * of the records; in other words, IVs are maintained across + * record decryptions. + */ + memcpy( transform->iv_dec, transform->cipher_ctx_dec.iv, + transform->ivlen ); + } +#endif + + /* Safe since data_len >= minlen + maclen + 1, so after having + * subtracted at most minlen and maclen up to this point, + * data_len > 0 (because of data_len % ivlen == 0, it's actually + * >= ivlen ). */ + padlen = data[rec->data_len - 1]; + + if( auth_done == 1 ) + { + const size_t mask = mbedtls_ssl_cf_mask_ge( + rec->data_len, + padlen + 1 ); + correct &= mask; + padlen &= mask; + } + else + { +#if defined(MBEDTLS_SSL_DEBUG_ALL) + if( rec->data_len < transform->maclen + padlen + 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < maclen (%d) + padlen (%d)", + rec->data_len, + transform->maclen, + padlen + 1 ) ); + } +#endif + + const size_t mask = mbedtls_ssl_cf_mask_ge( + rec->data_len, + transform->maclen + padlen + 1 ); + correct &= mask; + padlen &= mask; + } + + padlen++; + + /* Regardless of the validity of the padding, + * we have data_len >= padlen here. */ + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( transform->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + /* This is the SSL 3.0 path, we don't have to worry about Lucky + * 13, because there's a strictly worse padding attack built in + * the protocol (known as part of POODLE), so we don't care if the + * code is not constant-time, in particular branches are OK. */ + if( padlen > transform->ivlen ) + { +#if defined(MBEDTLS_SSL_DEBUG_ALL) + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad padding length: is %d, " + "should be no more than %d", + padlen, transform->ivlen ) ); +#endif + correct = 0; + } + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( transform->minor_ver > MBEDTLS_SSL_MINOR_VERSION_0 ) + { + /* The padding check involves a series of up to 256 + * consecutive memory reads at the end of the record + * plaintext buffer. In order to hide the length and + * validity of the padding, always perform exactly + * `min(256,plaintext_len)` reads (but take into account + * only the last `padlen` bytes for the padding check). */ + size_t pad_count = 0; + volatile unsigned char* const check = data; + + /* Index of first padding byte; it has been ensured above + * that the subtraction is safe. */ + size_t const padding_idx = rec->data_len - padlen; + size_t const num_checks = rec->data_len <= 256 ? rec->data_len : 256; + size_t const start_idx = rec->data_len - num_checks; + size_t idx; + + for( idx = start_idx; idx < rec->data_len; idx++ ) + { + /* pad_count += (idx >= padding_idx) && + * (check[idx] == padlen - 1); + */ + const size_t mask = mbedtls_ssl_cf_mask_ge( idx, padding_idx ); + const size_t equal = mbedtls_ssl_cf_bool_eq( check[idx], + padlen - 1 ); + pad_count += mask & equal; + } + correct &= mbedtls_ssl_cf_bool_eq( pad_count, padlen ); + +#if defined(MBEDTLS_SSL_DEBUG_ALL) + if( padlen > 0 && correct == 0 ) + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad padding byte detected" ) ); +#endif + padlen &= mbedtls_ssl_cf_mask_from_bit( correct ); + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ + MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* If the padding was found to be invalid, padlen == 0 + * and the subtraction is safe. If the padding was found valid, + * padlen hasn't been changed and the previous assertion + * data_len >= padlen still holds. */ + rec->data_len -= padlen; + } + else +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_SSL_DEBUG_ALL) + MBEDTLS_SSL_DEBUG_BUF( 4, "raw buffer after decryption", + data, rec->data_len ); +#endif + + /* + * Authenticate if not done yet. + * Compute the MAC regardless of the padding result (RFC4346, CBCTIME). + */ +#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) + if( auth_done == 0 ) + { + unsigned char mac_expect[MBEDTLS_SSL_MAC_ADD]; + unsigned char mac_peer[MBEDTLS_SSL_MAC_ADD]; + + /* If the initial value of padlen was such that + * data_len < maclen + padlen + 1, then padlen + * got reset to 1, and the initial check + * data_len >= minlen + maclen + 1 + * guarantees that at this point we still + * have at least data_len >= maclen. + * + * If the initial value of padlen was such that + * data_len >= maclen + padlen + 1, then we have + * subtracted either padlen + 1 (if the padding was correct) + * or 0 (if the padding was incorrect) since then, + * hence data_len >= maclen in any case. + */ + rec->data_len -= transform->maclen; + ssl_extract_add_data_from_record( add_data, &add_data_len, rec, + transform->minor_ver ); + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( transform->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + ssl_mac( &transform->md_ctx_dec, + transform->mac_dec, + data, rec->data_len, + rec->ctr, rec->type, + mac_expect ); + memcpy( mac_peer, data + rec->data_len, transform->maclen ); + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( transform->minor_ver > MBEDTLS_SSL_MINOR_VERSION_0 ) + { + /* + * The next two sizes are the minimum and maximum values of + * data_len over all padlen values. + * + * They're independent of padlen, since we previously did + * data_len -= padlen. + * + * Note that max_len + maclen is never more than the buffer + * length, as we previously did in_msglen -= maclen too. + */ + const size_t max_len = rec->data_len + padlen; + const size_t min_len = ( max_len > 256 ) ? max_len - 256 : 0; + + ret = mbedtls_ssl_cf_hmac( &transform->md_ctx_dec, + add_data, add_data_len, + data, rec->data_len, min_len, max_len, + mac_expect ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_cf_hmac", ret ); + return( ret ); + } + + mbedtls_ssl_cf_memcpy_offset( mac_peer, data, + rec->data_len, + min_len, max_len, + transform->maclen ); + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ + MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_SSL_DEBUG_ALL) + MBEDTLS_SSL_DEBUG_BUF( 4, "expected mac", mac_expect, transform->maclen ); + MBEDTLS_SSL_DEBUG_BUF( 4, "message mac", mac_peer, transform->maclen ); +#endif + + if( mbedtls_ssl_safer_memcmp( mac_peer, mac_expect, + transform->maclen ) != 0 ) + { +#if defined(MBEDTLS_SSL_DEBUG_ALL) + MBEDTLS_SSL_DEBUG_MSG( 1, ( "message mac does not match" ) ); +#endif + correct = 0; + } + auth_done++; + } + + /* + * Finally check the correct flag + */ + if( correct == 0 ) + return( MBEDTLS_ERR_SSL_INVALID_MAC ); +#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */ + + /* Make extra sure authentication was performed, exactly once */ + if( auth_done != 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL) + if( transform->minor_ver == MBEDTLS_SSL_MINOR_VERSION_4 ) + { + /* Remove inner padding and infer true content type. */ + ret = ssl_parse_inner_plaintext( data, &rec->data_len, + &rec->type ); + + if( ret != 0 ) + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */ + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + if( rec->cid_len != 0 ) + { + ret = ssl_parse_inner_plaintext( data, &rec->data_len, + &rec->type ); + if( ret != 0 ) + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= decrypt buf" ) ); + + return( 0 ); +} + +#undef MAC_NONE +#undef MAC_PLAINTEXT +#undef MAC_CIPHERTEXT + +#if defined(MBEDTLS_ZLIB_SUPPORT) +/* + * Compression/decompression functions + */ +static int ssl_compress_buf( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *msg_post = ssl->out_msg; + ptrdiff_t bytes_written = ssl->out_msg - ssl->out_buf; + size_t len_pre = ssl->out_msglen; + unsigned char *msg_pre = ssl->compress_buf; +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t out_buf_len = ssl->out_buf_len; +#else + size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN; +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> compress buf" ) ); + + if( len_pre == 0 ) + return( 0 ); + + memcpy( msg_pre, ssl->out_msg, len_pre ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "before compression: msglen = %d, ", + ssl->out_msglen ) ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "before compression: output payload", + ssl->out_msg, ssl->out_msglen ); + + ssl->transform_out->ctx_deflate.next_in = msg_pre; + ssl->transform_out->ctx_deflate.avail_in = len_pre; + ssl->transform_out->ctx_deflate.next_out = msg_post; + ssl->transform_out->ctx_deflate.avail_out = out_buf_len - bytes_written; + + ret = deflate( &ssl->transform_out->ctx_deflate, Z_SYNC_FLUSH ); + if( ret != Z_OK ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "failed to perform compression (%d)", ret ) ); + return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED ); + } + + ssl->out_msglen = out_buf_len - + ssl->transform_out->ctx_deflate.avail_out - bytes_written; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "after compression: msglen = %d, ", + ssl->out_msglen ) ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "after compression: output payload", + ssl->out_msg, ssl->out_msglen ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= compress buf" ) ); + + return( 0 ); +} + +static int ssl_decompress_buf( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *msg_post = ssl->in_msg; + ptrdiff_t header_bytes = ssl->in_msg - ssl->in_buf; + size_t len_pre = ssl->in_msglen; + unsigned char *msg_pre = ssl->compress_buf; +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t in_buf_len = ssl->in_buf_len; +#else + size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN; +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> decompress buf" ) ); + + if( len_pre == 0 ) + return( 0 ); + + memcpy( msg_pre, ssl->in_msg, len_pre ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "before decompression: msglen = %d, ", + ssl->in_msglen ) ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "before decompression: input payload", + ssl->in_msg, ssl->in_msglen ); + + ssl->transform_in->ctx_inflate.next_in = msg_pre; + ssl->transform_in->ctx_inflate.avail_in = len_pre; + ssl->transform_in->ctx_inflate.next_out = msg_post; + ssl->transform_in->ctx_inflate.avail_out = in_buf_len - header_bytes; + + ret = inflate( &ssl->transform_in->ctx_inflate, Z_SYNC_FLUSH ); + if( ret != Z_OK ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "failed to perform decompression (%d)", ret ) ); + return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED ); + } + + ssl->in_msglen = in_buf_len - + ssl->transform_in->ctx_inflate.avail_out - header_bytes; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "after decompression: msglen = %d, ", + ssl->in_msglen ) ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "after decompression: input payload", + ssl->in_msg, ssl->in_msglen ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= decompress buf" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_ZLIB_SUPPORT */ + +/* + * Fill the input message buffer by appending data to it. + * The amount of data already fetched is in ssl->in_left. + * + * If we return 0, is it guaranteed that (at least) nb_want bytes are + * available (from this read and/or a previous one). Otherwise, an error code + * is returned (possibly EOF or WANT_READ). + * + * With stream transport (TLS) on success ssl->in_left == nb_want, but + * with datagram transport (DTLS) on success ssl->in_left >= nb_want, + * since we always read a whole datagram at once. + * + * For DTLS, it is up to the caller to set ssl->next_record_offset when + * they're done reading a record. + */ +int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t in_buf_len = ssl->in_buf_len; +#else + size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN; +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> fetch input" ) ); + + if( ssl->f_recv == NULL && ssl->f_recv_timeout == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Bad usage of mbedtls_ssl_set_bio() " + "or mbedtls_ssl_set_bio()" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + if( nb_want > in_buf_len - (size_t)( ssl->in_hdr - ssl->in_buf ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "requesting more data than fits" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + uint32_t timeout; + + /* + * The point is, we need to always read a full datagram at once, so we + * sometimes read more then requested, and handle the additional data. + * It could be the rest of the current record (while fetching the + * header) and/or some other records in the same datagram. + */ + + /* + * Move to the next record in the already read datagram if applicable + */ + if( ssl->next_record_offset != 0 ) + { + if( ssl->in_left < ssl->next_record_offset ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + ssl->in_left -= ssl->next_record_offset; + + if( ssl->in_left != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "next record in same datagram, offset: %d", + ssl->next_record_offset ) ); + memmove( ssl->in_hdr, + ssl->in_hdr + ssl->next_record_offset, + ssl->in_left ); + } + + ssl->next_record_offset = 0; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d", + ssl->in_left, nb_want ) ); + + /* + * Done if we already have enough data. + */ + if( nb_want <= ssl->in_left) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= fetch input" ) ); + return( 0 ); + } + + /* + * A record can't be split across datagrams. If we need to read but + * are not at the beginning of a new record, the caller did something + * wrong. + */ + if( ssl->in_left != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* + * Don't even try to read if time's out already. + * This avoids by-passing the timer when repeatedly receiving messages + * that will end up being dropped. + */ + if( mbedtls_ssl_check_timer( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "timer has expired" ) ); + ret = MBEDTLS_ERR_SSL_TIMEOUT; + } + else + { + len = in_buf_len - ( ssl->in_hdr - ssl->in_buf ); + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + timeout = ssl->handshake->retransmit_timeout; + else + timeout = ssl->conf->read_timeout; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "f_recv_timeout: %u ms", timeout ) ); + + if( ssl->f_recv_timeout != NULL ) + ret = ssl->f_recv_timeout( ssl->p_bio, ssl->in_hdr, len, + timeout ); + else + ret = ssl->f_recv( ssl->p_bio, ssl->in_hdr, len ); + + MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_recv(_timeout)", ret ); + + if( ret == 0 ) + return( MBEDTLS_ERR_SSL_CONN_EOF ); + } + + if( ret == MBEDTLS_ERR_SSL_TIMEOUT ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "timeout" ) ); + mbedtls_ssl_set_timer( ssl, 0 ); + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + { + if( ssl_double_retransmit_timeout( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake timeout" ) ); + return( MBEDTLS_ERR_SSL_TIMEOUT ); + } + + if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend", ret ); + return( ret ); + } + + return( MBEDTLS_ERR_SSL_WANT_READ ); + } +#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION) + else if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) + { + if( ( ret = mbedtls_ssl_resend_hello_request( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend_hello_request", + ret ); + return( ret ); + } + + return( MBEDTLS_ERR_SSL_WANT_READ ); + } +#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */ + } + + if( ret < 0 ) + return( ret ); + + ssl->in_left = ret; + } + else +#endif + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d", + ssl->in_left, nb_want ) ); + + while( ssl->in_left < nb_want ) + { + len = nb_want - ssl->in_left; + + if( mbedtls_ssl_check_timer( ssl ) != 0 ) + ret = MBEDTLS_ERR_SSL_TIMEOUT; + else + { + if( ssl->f_recv_timeout != NULL ) + { + ret = ssl->f_recv_timeout( ssl->p_bio, + ssl->in_hdr + ssl->in_left, len, + ssl->conf->read_timeout ); + } + else + { + ret = ssl->f_recv( ssl->p_bio, + ssl->in_hdr + ssl->in_left, len ); + } + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d", + ssl->in_left, nb_want ) ); + MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_recv(_timeout)", ret ); + + if( ret == 0 ) + return( MBEDTLS_ERR_SSL_CONN_EOF ); + + if( ret < 0 ) + return( ret ); + + if ( (size_t)ret > len || ( INT_MAX > SIZE_MAX && ret > (int)SIZE_MAX ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "f_recv returned %d bytes but only %lu were requested", + ret, (unsigned long)len ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + ssl->in_left += ret; + } + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= fetch input" ) ); + + return( 0 ); +} + +/* + * Flush any data not yet written + */ +int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *buf; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> flush output" ) ); + + if( ssl->f_send == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Bad usage of mbedtls_ssl_set_bio() " + "or mbedtls_ssl_set_bio()" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + /* Avoid incrementing counter if data is flushed */ + if( ssl->out_left == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= flush output" ) ); + return( 0 ); + } + + while( ssl->out_left > 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "message length: %d, out_left: %d", + mbedtls_ssl_out_hdr_len( ssl ) + ssl->out_msglen, ssl->out_left ) ); + + buf = ssl->out_hdr - ssl->out_left; + ret = ssl->f_send( ssl->p_bio, buf, ssl->out_left ); + + MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_send", ret ); + + if( ret <= 0 ) + return( ret ); + + if( (size_t)ret > ssl->out_left || ( INT_MAX > SIZE_MAX && ret > (int)SIZE_MAX ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "f_send returned %d bytes but only %lu bytes were sent", + ret, (unsigned long)ssl->out_left ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + ssl->out_left -= ret; + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ssl->out_hdr = ssl->out_buf; + } + else +#endif + { + ssl->out_hdr = ssl->out_buf + 8; + } + mbedtls_ssl_update_out_pointers( ssl, ssl->transform_out ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= flush output" ) ); + + return( 0 ); +} + +/* + * Functions to handle the DTLS retransmission state machine + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) +/* + * Append current handshake message to current outgoing flight + */ +static int ssl_flight_append( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_flight_item *msg; + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_flight_append" ) ); + MBEDTLS_SSL_DEBUG_BUF( 4, "message appended to flight", + ssl->out_msg, ssl->out_msglen ); + + /* Allocate space for current message */ + if( ( msg = mbedtls_calloc( 1, sizeof( mbedtls_ssl_flight_item ) ) ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc %d bytes failed", + sizeof( mbedtls_ssl_flight_item ) ) ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + if( ( msg->p = mbedtls_calloc( 1, ssl->out_msglen ) ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc %d bytes failed", ssl->out_msglen ) ); + mbedtls_free( msg ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + /* Copy current handshake message with headers */ + memcpy( msg->p, ssl->out_msg, ssl->out_msglen ); + msg->len = ssl->out_msglen; + msg->type = ssl->out_msgtype; + msg->next = NULL; + + /* Append to the current flight */ + if( ssl->handshake->flight == NULL ) + ssl->handshake->flight = msg; + else + { + mbedtls_ssl_flight_item *cur = ssl->handshake->flight; + while( cur->next != NULL ) + cur = cur->next; + cur->next = msg; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_flight_append" ) ); + return( 0 ); +} + +/* + * Free the current flight of handshake messages + */ +void mbedtls_ssl_flight_free( mbedtls_ssl_flight_item *flight ) +{ + mbedtls_ssl_flight_item *cur = flight; + mbedtls_ssl_flight_item *next; + + while( cur != NULL ) + { + next = cur->next; + + mbedtls_free( cur->p ); + mbedtls_free( cur ); + + cur = next; + } +} + +/* + * Swap transform_out and out_ctr with the alternative ones + */ +static int ssl_swap_epochs( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_transform *tmp_transform; + unsigned char tmp_out_ctr[8]; + + if( ssl->transform_out == ssl->handshake->alt_transform_out ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip swap epochs" ) ); + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "swap epochs" ) ); + + /* Swap transforms */ + tmp_transform = ssl->transform_out; + ssl->transform_out = ssl->handshake->alt_transform_out; + ssl->handshake->alt_transform_out = tmp_transform; + + /* Swap epoch + sequence_number */ + memcpy( tmp_out_ctr, ssl->cur_out_ctr, 8 ); + memcpy( ssl->cur_out_ctr, ssl->handshake->alt_out_ctr, 8 ); + memcpy( ssl->handshake->alt_out_ctr, tmp_out_ctr, 8 ); + + /* Adjust to the newly activated transform */ + mbedtls_ssl_update_out_pointers( ssl, ssl->transform_out ); + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_activate != NULL ) + { + int ret = mbedtls_ssl_hw_record_activate( ssl, MBEDTLS_SSL_CHANNEL_OUTBOUND ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_activate", ret ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + } +#endif + + return( 0 ); +} + +/* + * Retransmit the current flight of messages. + */ +int mbedtls_ssl_resend( mbedtls_ssl_context *ssl ) +{ + int ret = 0; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_resend" ) ); + + ret = mbedtls_ssl_flight_transmit( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= mbedtls_ssl_resend" ) ); + + return( ret ); +} + +/* + * Transmit or retransmit the current flight of messages. + * + * Need to remember the current message in case flush_output returns + * WANT_WRITE, causing us to exit this function and come back later. + * This function must be called until state is no longer SENDING. + */ +int mbedtls_ssl_flight_transmit( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_flight_transmit" ) ); + + if( ssl->handshake->retransmit_state != MBEDTLS_SSL_RETRANS_SENDING ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialise flight transmission" ) ); + + ssl->handshake->cur_msg = ssl->handshake->flight; + ssl->handshake->cur_msg_p = ssl->handshake->flight->p + 12; + ret = ssl_swap_epochs( ssl ); + if( ret != 0 ) + return( ret ); + + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_SENDING; + } + + while( ssl->handshake->cur_msg != NULL ) + { + size_t max_frag_len; + const mbedtls_ssl_flight_item * const cur = ssl->handshake->cur_msg; + + int const is_finished = + ( cur->type == MBEDTLS_SSL_MSG_HANDSHAKE && + cur->p[0] == MBEDTLS_SSL_HS_FINISHED ); + + uint8_t const force_flush = ssl->disable_datagram_packing == 1 ? + SSL_FORCE_FLUSH : SSL_DONT_FORCE_FLUSH; + + /* Swap epochs before sending Finished: we can't do it after + * sending ChangeCipherSpec, in case write returns WANT_READ. + * Must be done before copying, may change out_msg pointer */ + if( is_finished && ssl->handshake->cur_msg_p == ( cur->p + 12 ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "swap epochs to send finished message" ) ); + ret = ssl_swap_epochs( ssl ); + if( ret != 0 ) + return( ret ); + } + + ret = ssl_get_remaining_payload_in_datagram( ssl ); + if( ret < 0 ) + return( ret ); + max_frag_len = (size_t) ret; + + /* CCS is copied as is, while HS messages may need fragmentation */ + if( cur->type == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC ) + { + if( max_frag_len == 0 ) + { + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + return( ret ); + + continue; + } + + memcpy( ssl->out_msg, cur->p, cur->len ); + ssl->out_msglen = cur->len; + ssl->out_msgtype = cur->type; + + /* Update position inside current message */ + ssl->handshake->cur_msg_p += cur->len; + } + else + { + const unsigned char * const p = ssl->handshake->cur_msg_p; + const size_t hs_len = cur->len - 12; + const size_t frag_off = p - ( cur->p + 12 ); + const size_t rem_len = hs_len - frag_off; + size_t cur_hs_frag_len, max_hs_frag_len; + + if( ( max_frag_len < 12 ) || ( max_frag_len == 12 && hs_len != 0 ) ) + { + if( is_finished ) + { + ret = ssl_swap_epochs( ssl ); + if( ret != 0 ) + return( ret ); + } + + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + return( ret ); + + continue; + } + max_hs_frag_len = max_frag_len - 12; + + cur_hs_frag_len = rem_len > max_hs_frag_len ? + max_hs_frag_len : rem_len; + + if( frag_off == 0 && cur_hs_frag_len != hs_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "fragmenting handshake message (%u > %u)", + (unsigned) cur_hs_frag_len, + (unsigned) max_hs_frag_len ) ); + } + + /* Messages are stored with handshake headers as if not fragmented, + * copy beginning of headers then fill fragmentation fields. + * Handshake headers: type(1) len(3) seq(2) f_off(3) f_len(3) */ + memcpy( ssl->out_msg, cur->p, 6 ); + + ssl->out_msg[6] = ( ( frag_off >> 16 ) & 0xff ); + ssl->out_msg[7] = ( ( frag_off >> 8 ) & 0xff ); + ssl->out_msg[8] = ( ( frag_off ) & 0xff ); + + ssl->out_msg[ 9] = ( ( cur_hs_frag_len >> 16 ) & 0xff ); + ssl->out_msg[10] = ( ( cur_hs_frag_len >> 8 ) & 0xff ); + ssl->out_msg[11] = ( ( cur_hs_frag_len ) & 0xff ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "handshake header", ssl->out_msg, 12 ); + + /* Copy the handshake message content and set records fields */ + memcpy( ssl->out_msg + 12, p, cur_hs_frag_len ); + ssl->out_msglen = cur_hs_frag_len + 12; + ssl->out_msgtype = cur->type; + + /* Update position inside current message */ + ssl->handshake->cur_msg_p += cur_hs_frag_len; + } + + /* If done with the current message move to the next one if any */ + if( ssl->handshake->cur_msg_p >= cur->p + cur->len ) + { + if( cur->next != NULL ) + { + ssl->handshake->cur_msg = cur->next; + ssl->handshake->cur_msg_p = cur->next->p + 12; + } + else + { + ssl->handshake->cur_msg = NULL; + ssl->handshake->cur_msg_p = NULL; + } + } + + /* Actually send the message out */ + if( ( ret = mbedtls_ssl_write_record( ssl, force_flush ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + } + + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + return( ret ); + + /* Update state and set timer */ + if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED; + else + { + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING; + mbedtls_ssl_set_timer( ssl, ssl->handshake->retransmit_timeout ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= mbedtls_ssl_flight_transmit" ) ); + + return( 0 ); +} + +/* + * To be called when the last message of an incoming flight is received. + */ +void mbedtls_ssl_recv_flight_completed( mbedtls_ssl_context *ssl ) +{ + /* We won't need to resend that one any more */ + mbedtls_ssl_flight_free( ssl->handshake->flight ); + ssl->handshake->flight = NULL; + ssl->handshake->cur_msg = NULL; + + /* The next incoming flight will start with this msg_seq */ + ssl->handshake->in_flight_start_seq = ssl->handshake->in_msg_seq; + + /* We don't want to remember CCS's across flight boundaries. */ + ssl->handshake->buffering.seen_ccs = 0; + + /* Clear future message buffering structure. */ + mbedtls_ssl_buffering_free( ssl ); + + /* Cancel timer */ + mbedtls_ssl_set_timer( ssl, 0 ); + + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED ) + { + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED; + } + else + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_PREPARING; +} + +/* + * To be called when the last message of an outgoing flight is send. + */ +void mbedtls_ssl_send_flight_completed( mbedtls_ssl_context *ssl ) +{ + ssl_reset_retransmit_timeout( ssl ); + mbedtls_ssl_set_timer( ssl, ssl->handshake->retransmit_timeout ); + + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED ) + { + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED; + } + else + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING; +} +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +/* + * Handshake layer functions + */ + +/* + * Write (DTLS: or queue) current handshake (including CCS) message. + * + * - fill in handshake headers + * - update handshake checksum + * - DTLS: save message for resending + * - then pass to the record layer + * + * DTLS: except for HelloRequest, messages are only queued, and will only be + * actually sent when calling flight_transmit() or resend(). + * + * Inputs: + * - ssl->out_msglen: 4 + actual handshake message len + * (4 is the size of handshake headers for TLS) + * - ssl->out_msg[0]: the handshake type (ClientHello, ServerHello, etc) + * - ssl->out_msg + 4: the handshake message body + * + * Outputs, ie state before passing to flight_append() or write_record(): + * - ssl->out_msglen: the length of the record contents + * (including handshake headers but excluding record headers) + * - ssl->out_msg: the record contents (handshake headers + content) + */ +int mbedtls_ssl_write_handshake_msg( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const size_t hs_len = ssl->out_msglen - 4; + const unsigned char hs_type = ssl->out_msg[0]; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write handshake message" ) ); + + /* + * Sanity checks + */ + if( ssl->out_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE && + ssl->out_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC ) + { + /* In SSLv3, the client might send a NoCertificate alert. */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_CLI_C) + if( ! ( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 && + ssl->out_msgtype == MBEDTLS_SSL_MSG_ALERT && + ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) ) +#endif /* MBEDTLS_SSL_PROTO_SSL3 && MBEDTLS_SSL_SRV_C */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } + + /* Whenever we send anything different from a + * HelloRequest we should be in a handshake - double check. */ + if( ! ( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + hs_type == MBEDTLS_SSL_HS_HELLO_REQUEST ) && + ssl->handshake == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake != NULL && + ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } +#endif + + /* Double-check that we did not exceed the bounds + * of the outgoing record buffer. + * This should never fail as the various message + * writing functions must obey the bounds of the + * outgoing record buffer, but better be safe. + * + * Note: We deliberately do not check for the MTU or MFL here. + */ + if( ssl->out_msglen > MBEDTLS_SSL_OUT_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Record too large: " + "size %u, maximum %u", + (unsigned) ssl->out_msglen, + (unsigned) MBEDTLS_SSL_OUT_CONTENT_LEN ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* + * Fill handshake headers + */ + if( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) + { + ssl->out_msg[1] = (unsigned char)( hs_len >> 16 ); + ssl->out_msg[2] = (unsigned char)( hs_len >> 8 ); + ssl->out_msg[3] = (unsigned char)( hs_len ); + + /* + * DTLS has additional fields in the Handshake layer, + * between the length field and the actual payload: + * uint16 message_seq; + * uint24 fragment_offset; + * uint24 fragment_length; + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + /* Make room for the additional DTLS fields */ + if( MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen < 8 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS handshake message too large: " + "size %u, maximum %u", + (unsigned) ( hs_len ), + (unsigned) ( MBEDTLS_SSL_OUT_CONTENT_LEN - 12 ) ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + memmove( ssl->out_msg + 12, ssl->out_msg + 4, hs_len ); + ssl->out_msglen += 8; + + /* Write message_seq and update it, except for HelloRequest */ + if( hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST ) + { + ssl->out_msg[4] = ( ssl->handshake->out_msg_seq >> 8 ) & 0xFF; + ssl->out_msg[5] = ( ssl->handshake->out_msg_seq ) & 0xFF; + ++( ssl->handshake->out_msg_seq ); + } + else + { + ssl->out_msg[4] = 0; + ssl->out_msg[5] = 0; + } + + /* Handshake hashes are computed without fragmentation, + * so set frag_offset = 0 and frag_len = hs_len for now */ + memset( ssl->out_msg + 6, 0x00, 3 ); + memcpy( ssl->out_msg + 9, ssl->out_msg + 1, 3 ); + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + /* Update running hashes of handshake messages seen */ + if( hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST ) + ssl->handshake->update_checksum( ssl, ssl->out_msg, ssl->out_msglen ); + } + + /* Either send now, or just save to be sent (and resent) later */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ! ( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + hs_type == MBEDTLS_SSL_HS_HELLO_REQUEST ) ) + { + if( ( ret = ssl_flight_append( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_flight_append", ret ); + return( ret ); + } + } + else +#endif + { + if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_record", ret ); + return( ret ); + } + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write handshake message" ) ); + + return( 0 ); +} + +/* + * Record layer functions + */ + +/* + * Write current record. + * + * Uses: + * - ssl->out_msgtype: type of the message (AppData, Handshake, Alert, CCS) + * - ssl->out_msglen: length of the record content (excl headers) + * - ssl->out_msg: record content + */ +int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl, uint8_t force_flush ) +{ + int ret, done = 0; + size_t len = ssl->out_msglen; + uint8_t flush = force_flush; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write record" ) ); + +#if defined(MBEDTLS_ZLIB_SUPPORT) + if( ssl->transform_out != NULL && + ssl->session_out->compression == MBEDTLS_SSL_COMPRESS_DEFLATE ) + { + if( ( ret = ssl_compress_buf( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_compress_buf", ret ); + return( ret ); + } + + len = ssl->out_msglen; + } +#endif /*MBEDTLS_ZLIB_SUPPORT */ + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_write != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_write()" ) ); + + ret = mbedtls_ssl_hw_record_write( ssl ); + if( ret != 0 && ret != MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_write", ret ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + if( ret == 0 ) + done = 1; + } +#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ + if( !done ) + { + unsigned i; + size_t protected_record_size; +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t out_buf_len = ssl->out_buf_len; +#else + size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN; +#endif + /* Skip writing the record content type to after the encryption, + * as it may change when using the CID extension. */ + + mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, + ssl->conf->transport, ssl->out_hdr + 1 ); + + memcpy( ssl->out_ctr, ssl->cur_out_ctr, 8 ); + ssl->out_len[0] = (unsigned char)( len >> 8 ); + ssl->out_len[1] = (unsigned char)( len ); + + if( ssl->transform_out != NULL ) + { + mbedtls_record rec; + + rec.buf = ssl->out_iv; + rec.buf_len = out_buf_len - ( ssl->out_iv - ssl->out_buf ); + rec.data_len = ssl->out_msglen; + rec.data_offset = ssl->out_msg - rec.buf; + + memcpy( &rec.ctr[0], ssl->out_ctr, 8 ); + mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, + ssl->conf->transport, rec.ver ); + rec.type = ssl->out_msgtype; + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + /* The CID is set by mbedtls_ssl_encrypt_buf(). */ + rec.cid_len = 0; +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + + if( ( ret = mbedtls_ssl_encrypt_buf( ssl, ssl->transform_out, &rec, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_encrypt_buf", ret ); + return( ret ); + } + + if( rec.data_offset != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* Update the record content type and CID. */ + ssl->out_msgtype = rec.type; +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID ) + memcpy( ssl->out_cid, rec.cid, rec.cid_len ); +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + ssl->out_msglen = len = rec.data_len; + ssl->out_len[0] = (unsigned char)( rec.data_len >> 8 ); + ssl->out_len[1] = (unsigned char)( rec.data_len ); + } + + protected_record_size = len + mbedtls_ssl_out_hdr_len( ssl ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + /* In case of DTLS, double-check that we don't exceed + * the remaining space in the datagram. */ + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ret = ssl_get_remaining_space_in_datagram( ssl ); + if( ret < 0 ) + return( ret ); + + if( protected_record_size > (size_t) ret ) + { + /* Should never happen */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + /* Now write the potentially updated record content type. */ + ssl->out_hdr[0] = (unsigned char) ssl->out_msgtype; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "output record: msgtype = %d, " + "version = [%d:%d], msglen = %d", + ssl->out_hdr[0], ssl->out_hdr[1], + ssl->out_hdr[2], len ) ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "output record sent to network", + ssl->out_hdr, protected_record_size ); + + ssl->out_left += protected_record_size; + ssl->out_hdr += protected_record_size; + mbedtls_ssl_update_out_pointers( ssl, ssl->transform_out ); + + for( i = 8; i > mbedtls_ssl_ep_len( ssl ); i-- ) + if( ++ssl->cur_out_ctr[i - 1] != 0 ) + break; + + /* The loop goes to its end iff the counter is wrapping */ + if( i == mbedtls_ssl_ep_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "outgoing message counter would wrap" ) ); + return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); + } + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + flush == SSL_DONT_FORCE_FLUSH ) + { + size_t remaining; + ret = ssl_get_remaining_payload_in_datagram( ssl ); + if( ret < 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_get_remaining_payload_in_datagram", + ret ); + return( ret ); + } + + remaining = (size_t) ret; + if( remaining == 0 ) + { + flush = SSL_FORCE_FLUSH; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Still %u bytes available in current datagram", (unsigned) remaining ) ); + } + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + if( ( flush == SSL_FORCE_FLUSH ) && + ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flush_output", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write record" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + +static int ssl_hs_is_proper_fragment( mbedtls_ssl_context *ssl ) +{ + if( ssl->in_msglen < ssl->in_hslen || + memcmp( ssl->in_msg + 6, "\0\0\0", 3 ) != 0 || + memcmp( ssl->in_msg + 9, ssl->in_msg + 1, 3 ) != 0 ) + { + return( 1 ); + } + return( 0 ); +} + +static uint32_t ssl_get_hs_frag_len( mbedtls_ssl_context const *ssl ) +{ + return( ( ssl->in_msg[9] << 16 ) | + ( ssl->in_msg[10] << 8 ) | + ssl->in_msg[11] ); +} + +static uint32_t ssl_get_hs_frag_off( mbedtls_ssl_context const *ssl ) +{ + return( ( ssl->in_msg[6] << 16 ) | + ( ssl->in_msg[7] << 8 ) | + ssl->in_msg[8] ); +} + +static int ssl_check_hs_header( mbedtls_ssl_context const *ssl ) +{ + uint32_t msg_len, frag_off, frag_len; + + msg_len = ssl_get_hs_total_len( ssl ); + frag_off = ssl_get_hs_frag_off( ssl ); + frag_len = ssl_get_hs_frag_len( ssl ); + + if( frag_off > msg_len ) + return( -1 ); + + if( frag_len > msg_len - frag_off ) + return( -1 ); + + if( frag_len + 12 > ssl->in_msglen ) + return( -1 ); + + return( 0 ); +} + +/* + * Mark bits in bitmask (used for DTLS HS reassembly) + */ +static void ssl_bitmask_set( unsigned char *mask, size_t offset, size_t len ) +{ + unsigned int start_bits, end_bits; + + start_bits = 8 - ( offset % 8 ); + if( start_bits != 8 ) + { + size_t first_byte_idx = offset / 8; + + /* Special case */ + if( len <= start_bits ) + { + for( ; len != 0; len-- ) + mask[first_byte_idx] |= 1 << ( start_bits - len ); + + /* Avoid potential issues with offset or len becoming invalid */ + return; + } + + offset += start_bits; /* Now offset % 8 == 0 */ + len -= start_bits; + + for( ; start_bits != 0; start_bits-- ) + mask[first_byte_idx] |= 1 << ( start_bits - 1 ); + } + + end_bits = len % 8; + if( end_bits != 0 ) + { + size_t last_byte_idx = ( offset + len ) / 8; + + len -= end_bits; /* Now len % 8 == 0 */ + + for( ; end_bits != 0; end_bits-- ) + mask[last_byte_idx] |= 1 << ( 8 - end_bits ); + } + + memset( mask + offset / 8, 0xFF, len / 8 ); +} + +/* + * Check that bitmask is full + */ +static int ssl_bitmask_check( unsigned char *mask, size_t len ) +{ + size_t i; + + for( i = 0; i < len / 8; i++ ) + if( mask[i] != 0xFF ) + return( -1 ); + + for( i = 0; i < len % 8; i++ ) + if( ( mask[len / 8] & ( 1 << ( 7 - i ) ) ) == 0 ) + return( -1 ); + + return( 0 ); +} + +/* msg_len does not include the handshake header */ +static size_t ssl_get_reassembly_buffer_size( size_t msg_len, + unsigned add_bitmap ) +{ + size_t alloc_len; + + alloc_len = 12; /* Handshake header */ + alloc_len += msg_len; /* Content buffer */ + + if( add_bitmap ) + alloc_len += msg_len / 8 + ( msg_len % 8 != 0 ); /* Bitmap */ + + return( alloc_len ); +} + +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +static uint32_t ssl_get_hs_total_len( mbedtls_ssl_context const *ssl ) +{ + return( ( ssl->in_msg[1] << 16 ) | + ( ssl->in_msg[2] << 8 ) | + ssl->in_msg[3] ); +} + +int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl ) +{ + if( ssl->in_msglen < mbedtls_ssl_hs_hdr_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake message too short: %d", + ssl->in_msglen ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + ssl->in_hslen = mbedtls_ssl_hs_hdr_len( ssl ) + ssl_get_hs_total_len( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "handshake message: msglen =" + " %d, type = %d, hslen = %d", + ssl->in_msglen, ssl->in_msg[0], ssl->in_hslen ) ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned int recv_msg_seq = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5]; + + if( ssl_check_hs_header( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid handshake header" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + if( ssl->handshake != NULL && + ( ( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER && + recv_msg_seq != ssl->handshake->in_msg_seq ) || + ( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER && + ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO ) ) ) + { + if( recv_msg_seq > ssl->handshake->in_msg_seq ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "received future handshake message of sequence number %u (next %u)", + recv_msg_seq, + ssl->handshake->in_msg_seq ) ); + return( MBEDTLS_ERR_SSL_EARLY_MESSAGE ); + } + + /* Retransmit only on last message from previous flight, to avoid + * too many retransmissions. + * Besides, No sane server ever retransmits HelloVerifyRequest */ + if( recv_msg_seq == ssl->handshake->in_flight_start_seq - 1 && + ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "received message from last flight, " + "message_seq = %d, start_of_flight = %d", + recv_msg_seq, + ssl->handshake->in_flight_start_seq ) ); + + if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend", ret ); + return( ret ); + } + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "dropping out-of-sequence message: " + "message_seq = %d, expected = %d", + recv_msg_seq, + ssl->handshake->in_msg_seq ) ); + } + + return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ); + } + /* Wait until message completion to increment in_msg_seq */ + + /* Message reassembly is handled alongside buffering of future + * messages; the commonality is that both handshake fragments and + * future messages cannot be forwarded immediately to the + * handshake logic layer. */ + if( ssl_hs_is_proper_fragment( ssl ) == 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "found fragmented DTLS handshake message" ) ); + return( MBEDTLS_ERR_SSL_EARLY_MESSAGE ); + } + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + /* With TLS we don't handle fragmentation (for now) */ + if( ssl->in_msglen < ssl->in_hslen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "TLS handshake fragmentation not supported" ) ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + + return( 0 ); +} + +void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER && hs != NULL ) + { + ssl->handshake->update_checksum( ssl, ssl->in_msg, ssl->in_hslen ); + } + + /* Handshake message is complete, increment counter */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake != NULL ) + { + unsigned offset; + mbedtls_ssl_hs_buffer *hs_buf; + + /* Increment handshake sequence number */ + hs->in_msg_seq++; + + /* + * Clear up handshake buffering and reassembly structure. + */ + + /* Free first entry */ + ssl_buffering_free_slot( ssl, 0 ); + + /* Shift all other entries */ + for( offset = 0, hs_buf = &hs->buffering.hs[0]; + offset + 1 < MBEDTLS_SSL_MAX_BUFFERED_HS; + offset++, hs_buf++ ) + { + *hs_buf = *(hs_buf + 1); + } + + /* Create a fresh last entry */ + memset( hs_buf, 0, sizeof( mbedtls_ssl_hs_buffer ) ); + } +#endif +} + +/* + * DTLS anti-replay: RFC 6347 4.1.2.6 + * + * in_window is a field of bits numbered from 0 (lsb) to 63 (msb). + * Bit n is set iff record number in_window_top - n has been seen. + * + * Usually, in_window_top is the last record number seen and the lsb of + * in_window is set. The only exception is the initial state (record number 0 + * not seen yet). + */ +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +void mbedtls_ssl_dtls_replay_reset( mbedtls_ssl_context *ssl ) +{ + ssl->in_window_top = 0; + ssl->in_window = 0; +} + +static inline uint64_t ssl_load_six_bytes( unsigned char *buf ) +{ + return( ( (uint64_t) buf[0] << 40 ) | + ( (uint64_t) buf[1] << 32 ) | + ( (uint64_t) buf[2] << 24 ) | + ( (uint64_t) buf[3] << 16 ) | + ( (uint64_t) buf[4] << 8 ) | + ( (uint64_t) buf[5] ) ); +} + +static int mbedtls_ssl_dtls_record_replay_check( mbedtls_ssl_context *ssl, uint8_t *record_in_ctr ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *original_in_ctr; + + // save original in_ctr + original_in_ctr = ssl->in_ctr; + + // use counter from record + ssl->in_ctr = record_in_ctr; + + ret = mbedtls_ssl_dtls_replay_check( (mbedtls_ssl_context const *) ssl ); + + // restore the counter + ssl->in_ctr = original_in_ctr; + + return ret; +} + +/* + * Return 0 if sequence number is acceptable, -1 otherwise + */ +int mbedtls_ssl_dtls_replay_check( mbedtls_ssl_context const *ssl ) +{ + uint64_t rec_seqnum = ssl_load_six_bytes( ssl->in_ctr + 2 ); + uint64_t bit; + + if( ssl->conf->anti_replay == MBEDTLS_SSL_ANTI_REPLAY_DISABLED ) + return( 0 ); + + if( rec_seqnum > ssl->in_window_top ) + return( 0 ); + + bit = ssl->in_window_top - rec_seqnum; + + if( bit >= 64 ) + return( -1 ); + + if( ( ssl->in_window & ( (uint64_t) 1 << bit ) ) != 0 ) + return( -1 ); + + return( 0 ); +} + +/* + * Update replay window on new validated record + */ +void mbedtls_ssl_dtls_replay_update( mbedtls_ssl_context *ssl ) +{ + uint64_t rec_seqnum = ssl_load_six_bytes( ssl->in_ctr + 2 ); + + if( ssl->conf->anti_replay == MBEDTLS_SSL_ANTI_REPLAY_DISABLED ) + return; + + if( rec_seqnum > ssl->in_window_top ) + { + /* Update window_top and the contents of the window */ + uint64_t shift = rec_seqnum - ssl->in_window_top; + + if( shift >= 64 ) + ssl->in_window = 1; + else + { + ssl->in_window <<= shift; + ssl->in_window |= 1; + } + + ssl->in_window_top = rec_seqnum; + } + else + { + /* Mark that number as seen in the current window */ + uint64_t bit = ssl->in_window_top - rec_seqnum; + + if( bit < 64 ) /* Always true, but be extra sure */ + ssl->in_window |= (uint64_t) 1 << bit; + } +} +#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ + +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) +/* + * Without any SSL context, check if a datagram looks like a ClientHello with + * a valid cookie, and if it doesn't, generate a HelloVerifyRequest message. + * Both input and output include full DTLS headers. + * + * - if cookie is valid, return 0 + * - if ClientHello looks superficially valid but cookie is not, + * fill obuf and set olen, then + * return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED + * - otherwise return a specific error code + */ +static int ssl_check_dtls_clihlo_cookie( + mbedtls_ssl_cookie_write_t *f_cookie_write, + mbedtls_ssl_cookie_check_t *f_cookie_check, + void *p_cookie, + const unsigned char *cli_id, size_t cli_id_len, + const unsigned char *in, size_t in_len, + unsigned char *obuf, size_t buf_len, size_t *olen ) +{ + size_t sid_len, cookie_len; + unsigned char *p; + + /* + * Structure of ClientHello with record and handshake headers, + * and expected values. We don't need to check a lot, more checks will be + * done when actually parsing the ClientHello - skipping those checks + * avoids code duplication and does not make cookie forging any easier. + * + * 0-0 ContentType type; copied, must be handshake + * 1-2 ProtocolVersion version; copied + * 3-4 uint16 epoch; copied, must be 0 + * 5-10 uint48 sequence_number; copied + * 11-12 uint16 length; (ignored) + * + * 13-13 HandshakeType msg_type; (ignored) + * 14-16 uint24 length; (ignored) + * 17-18 uint16 message_seq; copied + * 19-21 uint24 fragment_offset; copied, must be 0 + * 22-24 uint24 fragment_length; (ignored) + * + * 25-26 ProtocolVersion client_version; (ignored) + * 27-58 Random random; (ignored) + * 59-xx SessionID session_id; 1 byte len + sid_len content + * 60+ opaque cookie<0..2^8-1>; 1 byte len + content + * ... + * + * Minimum length is 61 bytes. + */ + if( in_len < 61 || + in[0] != MBEDTLS_SSL_MSG_HANDSHAKE || + in[3] != 0 || in[4] != 0 || + in[19] != 0 || in[20] != 0 || in[21] != 0 ) + { + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + sid_len = in[59]; + if( sid_len > in_len - 61 ) + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + + cookie_len = in[60 + sid_len]; + if( cookie_len > in_len - 60 ) + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + + if( f_cookie_check( p_cookie, in + sid_len + 61, cookie_len, + cli_id, cli_id_len ) == 0 ) + { + /* Valid cookie */ + return( 0 ); + } + + /* + * If we get here, we've got an invalid cookie, let's prepare HVR. + * + * 0-0 ContentType type; copied + * 1-2 ProtocolVersion version; copied + * 3-4 uint16 epoch; copied + * 5-10 uint48 sequence_number; copied + * 11-12 uint16 length; olen - 13 + * + * 13-13 HandshakeType msg_type; hello_verify_request + * 14-16 uint24 length; olen - 25 + * 17-18 uint16 message_seq; copied + * 19-21 uint24 fragment_offset; copied + * 22-24 uint24 fragment_length; olen - 25 + * + * 25-26 ProtocolVersion server_version; 0xfe 0xff + * 27-27 opaque cookie<0..2^8-1>; cookie_len = olen - 27, cookie + * + * Minimum length is 28. + */ + if( buf_len < 28 ) + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + + /* Copy most fields and adapt others */ + memcpy( obuf, in, 25 ); + obuf[13] = MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST; + obuf[25] = 0xfe; + obuf[26] = 0xff; + + /* Generate and write actual cookie */ + p = obuf + 28; + if( f_cookie_write( p_cookie, + &p, obuf + buf_len, cli_id, cli_id_len ) != 0 ) + { + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + *olen = p - obuf; + + /* Go back and fill length fields */ + obuf[27] = (unsigned char)( *olen - 28 ); + + obuf[14] = obuf[22] = (unsigned char)( ( *olen - 25 ) >> 16 ); + obuf[15] = obuf[23] = (unsigned char)( ( *olen - 25 ) >> 8 ); + obuf[16] = obuf[24] = (unsigned char)( ( *olen - 25 ) ); + + obuf[11] = (unsigned char)( ( *olen - 13 ) >> 8 ); + obuf[12] = (unsigned char)( ( *olen - 13 ) ); + + return( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ); +} + +/* + * Handle possible client reconnect with the same UDP quadruplet + * (RFC 6347 Section 4.2.8). + * + * Called by ssl_parse_record_header() in case we receive an epoch 0 record + * that looks like a ClientHello. + * + * - if the input looks like a ClientHello without cookies, + * send back HelloVerifyRequest, then return 0 + * - if the input looks like a ClientHello with a valid cookie, + * reset the session of the current context, and + * return MBEDTLS_ERR_SSL_CLIENT_RECONNECT + * - if anything goes wrong, return a specific error code + * + * This function is called (through ssl_check_client_reconnect()) when an + * unexpected record is found in ssl_get_next_record(), which will discard the + * record if we return 0, and bubble up the return value otherwise (this + * includes the case of MBEDTLS_ERR_SSL_CLIENT_RECONNECT and of unexpected + * errors, and is the right thing to do in both cases). + */ +static int ssl_handle_possible_reconnect( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + if( ssl->conf->f_cookie_write == NULL || + ssl->conf->f_cookie_check == NULL ) + { + /* If we can't use cookies to verify reachability of the peer, + * drop the record. */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "no cookie callbacks, " + "can't check reconnect validity" ) ); + return( 0 ); + } + + ret = ssl_check_dtls_clihlo_cookie( + ssl->conf->f_cookie_write, + ssl->conf->f_cookie_check, + ssl->conf->p_cookie, + ssl->cli_id, ssl->cli_id_len, + ssl->in_buf, ssl->in_left, + ssl->out_buf, MBEDTLS_SSL_OUT_CONTENT_LEN, &len ); + + MBEDTLS_SSL_DEBUG_RET( 2, "ssl_check_dtls_clihlo_cookie", ret ); + + if( ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ) + { + int send_ret; + MBEDTLS_SSL_DEBUG_MSG( 1, ( "sending HelloVerifyRequest" ) ); + MBEDTLS_SSL_DEBUG_BUF( 4, "output record sent to network", + ssl->out_buf, len ); + /* Don't check write errors as we can't do anything here. + * If the error is permanent we'll catch it later, + * if it's not, then hopefully it'll work next time. */ + send_ret = ssl->f_send( ssl->p_bio, ssl->out_buf, len ); + MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_send", send_ret ); + (void) send_ret; + + return( 0 ); + } + + if( ret == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "cookie is valid, resetting context" ) ); + if( ( ret = mbedtls_ssl_session_reset_int( ssl, 1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "reset", ret ); + return( ret ); + } + + return( MBEDTLS_ERR_SSL_CLIENT_RECONNECT ); + } + + return( ret ); +} +#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */ + +static int ssl_check_record_type( uint8_t record_type ) +{ + if( record_type != MBEDTLS_SSL_MSG_HANDSHAKE && + record_type != MBEDTLS_SSL_MSG_ALERT && + record_type != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC && + record_type != MBEDTLS_SSL_MSG_APPLICATION_DATA ) + { + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + return( 0 ); +} + +/* + * ContentType type; + * ProtocolVersion version; + * uint16 epoch; // DTLS only + * uint48 sequence_number; // DTLS only + * uint16 length; + * + * Return 0 if header looks sane (and, for DTLS, the record is expected) + * MBEDTLS_ERR_SSL_INVALID_RECORD if the header looks bad, + * MBEDTLS_ERR_SSL_UNEXPECTED_RECORD (DTLS only) if sane but unexpected. + * + * With DTLS, mbedtls_ssl_read_record() will: + * 1. proceed with the record if this function returns 0 + * 2. drop only the current record if this function returns UNEXPECTED_RECORD + * 3. return CLIENT_RECONNECT if this function return that value + * 4. drop the whole datagram if this function returns anything else. + * Point 2 is needed when the peer is resending, and we have already received + * the first record from a datagram but are still waiting for the others. + */ +static int ssl_parse_record_header( mbedtls_ssl_context const *ssl, + unsigned char *buf, + size_t len, + mbedtls_record *rec ) +{ + int major_ver, minor_ver; + + size_t const rec_hdr_type_offset = 0; + size_t const rec_hdr_type_len = 1; + + size_t const rec_hdr_version_offset = rec_hdr_type_offset + + rec_hdr_type_len; + size_t const rec_hdr_version_len = 2; + + size_t const rec_hdr_ctr_len = 8; +#if defined(MBEDTLS_SSL_PROTO_DTLS) + uint32_t rec_epoch; + size_t const rec_hdr_ctr_offset = rec_hdr_version_offset + + rec_hdr_version_len; + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + size_t const rec_hdr_cid_offset = rec_hdr_ctr_offset + + rec_hdr_ctr_len; + size_t rec_hdr_cid_len = 0; +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + size_t rec_hdr_len_offset; /* To be determined */ + size_t const rec_hdr_len_len = 2; + + /* + * Check minimum lengths for record header. + */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + rec_hdr_len_offset = rec_hdr_ctr_offset + rec_hdr_ctr_len; + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + { + rec_hdr_len_offset = rec_hdr_version_offset + rec_hdr_version_len; + } + + if( len < rec_hdr_len_offset + rec_hdr_len_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "datagram of length %u too small to hold DTLS record header of length %u", + (unsigned) len, + (unsigned)( rec_hdr_len_len + rec_hdr_len_len ) ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + /* + * Parse and validate record content type + */ + + rec->type = buf[ rec_hdr_type_offset ]; + + /* Check record content type */ +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + rec->cid_len = 0; + + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->conf->cid_len != 0 && + rec->type == MBEDTLS_SSL_MSG_CID ) + { + /* Shift pointers to account for record header including CID + * struct { + * ContentType special_type = tls12_cid; + * ProtocolVersion version; + * uint16 epoch; + * uint48 sequence_number; + * opaque cid[cid_length]; // Additional field compared to + * // default DTLS record format + * uint16 length; + * opaque enc_content[DTLSCiphertext.length]; + * } DTLSCiphertext; + */ + + /* So far, we only support static CID lengths + * fixed in the configuration. */ + rec_hdr_cid_len = ssl->conf->cid_len; + rec_hdr_len_offset += rec_hdr_cid_len; + + if( len < rec_hdr_len_offset + rec_hdr_len_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "datagram of length %u too small to hold DTLS record header including CID, length %u", + (unsigned) len, + (unsigned)( rec_hdr_len_offset + rec_hdr_len_len ) ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + /* configured CID len is guaranteed at most 255, see + * MBEDTLS_SSL_CID_OUT_LEN_MAX in check_config.h */ + rec->cid_len = (uint8_t) rec_hdr_cid_len; + memcpy( rec->cid, buf + rec_hdr_cid_offset, rec_hdr_cid_len ); + } + else +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + { + if( ssl_check_record_type( rec->type ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "unknown record type %u", + (unsigned) rec->type ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + } + + /* + * Parse and validate record version + */ + + rec->ver[0] = buf[ rec_hdr_version_offset + 0 ]; + rec->ver[1] = buf[ rec_hdr_version_offset + 1 ]; + mbedtls_ssl_read_version( &major_ver, &minor_ver, + ssl->conf->transport, + &rec->ver[0] ); + + if( major_ver != ssl->major_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "major version mismatch" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + if( minor_ver > ssl->conf->max_minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "minor version mismatch" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + /* + * Parse/Copy record sequence number. + */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + /* Copy explicit record sequence number from input buffer. */ + memcpy( &rec->ctr[0], buf + rec_hdr_ctr_offset, + rec_hdr_ctr_len ); + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + { + /* Copy implicit record sequence number from SSL context structure. */ + memcpy( &rec->ctr[0], ssl->in_ctr, rec_hdr_ctr_len ); + } + + /* + * Parse record length. + */ + + rec->data_offset = rec_hdr_len_offset + rec_hdr_len_len; + rec->data_len = ( (size_t) buf[ rec_hdr_len_offset + 0 ] << 8 ) | + ( (size_t) buf[ rec_hdr_len_offset + 1 ] << 0 ); + MBEDTLS_SSL_DEBUG_BUF( 4, "input record header", buf, rec->data_offset ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "input record: msgtype = %d, " + "version = [%d:%d], msglen = %d", + rec->type, + major_ver, minor_ver, rec->data_len ) ); + + rec->buf = buf; + rec->buf_len = rec->data_offset + rec->data_len; + + if( rec->data_len == 0 ) + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + + /* + * DTLS-related tests. + * Check epoch before checking length constraint because + * the latter varies with the epoch. E.g., if a ChangeCipherSpec + * message gets duplicated before the corresponding Finished message, + * the second ChangeCipherSpec should be discarded because it belongs + * to an old epoch, but not because its length is shorter than + * the minimum record length for packets using the new record transform. + * Note that these two kinds of failures are handled differently, + * as an unexpected record is silently skipped but an invalid + * record leads to the entire datagram being dropped. + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + rec_epoch = ( rec->ctr[0] << 8 ) | rec->ctr[1]; + + /* Check that the datagram is large enough to contain a record + * of the advertised length. */ + if( len < rec->data_offset + rec->data_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Datagram of length %u too small to contain record of advertised length %u.", + (unsigned) len, + (unsigned)( rec->data_offset + rec->data_len ) ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + /* Records from other, non-matching epochs are silently discarded. + * (The case of same-port Client reconnects must be considered in + * the caller). */ + if( rec_epoch != ssl->in_epoch ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "record from another epoch: " + "expected %d, received %d", + ssl->in_epoch, rec_epoch ) ); + + /* Records from the next epoch are considered for buffering + * (concretely: early Finished messages). */ + if( rec_epoch == (unsigned) ssl->in_epoch + 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Consider record for buffering" ) ); + return( MBEDTLS_ERR_SSL_EARLY_MESSAGE ); + } + + return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); + } +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + /* For records from the correct epoch, check whether their + * sequence number has been seen before. */ + else if( mbedtls_ssl_dtls_record_replay_check( (mbedtls_ssl_context *) ssl, + &rec->ctr[0] ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "replayed record" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); + } +#endif + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + return( 0 ); +} + + +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) +static int ssl_check_client_reconnect( mbedtls_ssl_context *ssl ) +{ + unsigned int rec_epoch = ( ssl->in_ctr[0] << 8 ) | ssl->in_ctr[1]; + + /* + * Check for an epoch 0 ClientHello. We can't use in_msg here to + * access the first byte of record content (handshake type), as we + * have an active transform (possibly iv_len != 0), so use the + * fact that the record header len is 13 instead. + */ + if( rec_epoch == 0 && + ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER && + ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + ssl->in_left > 13 && + ssl->in_buf[13] == MBEDTLS_SSL_HS_CLIENT_HELLO ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "possible client reconnect " + "from the same port" ) ); + return( ssl_handle_possible_reconnect( ssl ) ); + } + + return( 0 ); +} +#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */ + +/* + * If applicable, decrypt record content + */ +static int ssl_prepare_record_content( mbedtls_ssl_context *ssl, + mbedtls_record *rec ) +{ + int ret, done = 0; + + MBEDTLS_SSL_DEBUG_BUF( 4, "input record from network", + rec->buf, rec->buf_len ); + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_read != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_read()" ) ); + + ret = mbedtls_ssl_hw_record_read( ssl ); + if( ret != 0 && ret != MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_read", ret ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + if( ret == 0 ) + done = 1; + } +#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ + if( !done && ssl->transform_in != NULL ) + { + unsigned char const old_msg_type = rec->type; + + if( ( ret = mbedtls_ssl_decrypt_buf( ssl, ssl->transform_in, + rec ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_decrypt_buf", ret ); + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + if( ret == MBEDTLS_ERR_SSL_UNEXPECTED_CID && + ssl->conf->ignore_unexpected_cid + == MBEDTLS_SSL_UNEXPECTED_CID_IGNORE ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ignoring unexpected CID" ) ); + ret = MBEDTLS_ERR_SSL_CONTINUE_PROCESSING; + } +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + + return( ret ); + } + + if( old_msg_type != rec->type ) + { + MBEDTLS_SSL_DEBUG_MSG( 4, ( "record type after decrypt (before %d): %d", + old_msg_type, rec->type ) ); + } + + MBEDTLS_SSL_DEBUG_BUF( 4, "input payload after decrypt", + rec->buf + rec->data_offset, rec->data_len ); + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + /* We have already checked the record content type + * in ssl_parse_record_header(), failing or silently + * dropping the record in the case of an unknown type. + * + * Since with the use of CIDs, the record content type + * might change during decryption, re-check the record + * content type, but treat a failure as fatal this time. */ + if( ssl_check_record_type( rec->type ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "unknown record type" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + + if( rec->data_len == 0 ) + { +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 + && rec->type != MBEDTLS_SSL_MSG_APPLICATION_DATA ) + { + /* TLS v1.2 explicitly disallows zero-length messages which are not application data */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid zero-length message type: %d", ssl->in_msgtype ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + ssl->nb_zero++; + + /* + * Three or more empty messages may be a DoS attack + * (excessive CPU consumption). + */ + if( ssl->nb_zero > 3 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "received four consecutive empty " + "messages, possible DoS attack" ) ); + /* Treat the records as if they were not properly authenticated, + * thereby failing the connection if we see more than allowed + * by the configured bad MAC threshold. */ + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } + } + else + ssl->nb_zero = 0; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ; /* in_ctr read from peer, not maintained internally */ + } + else +#endif + { + unsigned i; + for( i = 8; i > mbedtls_ssl_ep_len( ssl ); i-- ) + if( ++ssl->in_ctr[i - 1] != 0 ) + break; + + /* The loop goes to its end iff the counter is wrapping */ + if( i == mbedtls_ssl_ep_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "incoming message counter would wrap" ) ); + return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); + } + } + + } + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + mbedtls_ssl_dtls_replay_update( ssl ); + } +#endif + + /* Check actual (decrypted) record content length against + * configured maximum. */ + if( ssl->in_msglen > MBEDTLS_SSL_IN_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + return( 0 ); +} + +/* + * Read a record. + * + * Silently ignore non-fatal alert (and for DTLS, invalid records as well, + * RFC 6347 4.1.2.7) and continue reading until a valid record is found. + * + */ + +/* Helper functions for mbedtls_ssl_read_record(). */ +static int ssl_consume_current_message( mbedtls_ssl_context *ssl ); +static int ssl_get_next_record( mbedtls_ssl_context *ssl ); +static int ssl_record_is_in_progress( mbedtls_ssl_context *ssl ); + +int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl, + unsigned update_hs_digest ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> read record" ) ); + + if( ssl->keep_current_message == 0 ) + { + do { + + ret = ssl_consume_current_message( ssl ); + if( ret != 0 ) + return( ret ); + + if( ssl_record_is_in_progress( ssl ) == 0 ) + { +#if defined(MBEDTLS_SSL_PROTO_DTLS) + int have_buffered = 0; + + /* We only check for buffered messages if the + * current datagram is fully consumed. */ + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl_next_record_is_in_datagram( ssl ) == 0 ) + { + if( ssl_load_buffered_message( ssl ) == 0 ) + have_buffered = 1; + } + + if( have_buffered == 0 ) +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + { + ret = ssl_get_next_record( ssl ); + if( ret == MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ) + continue; + + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_get_next_record" ), ret ); + return( ret ); + } + } + } + + ret = mbedtls_ssl_handle_message_type( ssl ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE ) + { + /* Buffer future message */ + ret = ssl_buffer_message( ssl ); + if( ret != 0 ) + return( ret ); + + ret = MBEDTLS_ERR_SSL_CONTINUE_PROCESSING; + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + } while( MBEDTLS_ERR_SSL_NON_FATAL == ret || + MBEDTLS_ERR_SSL_CONTINUE_PROCESSING == ret ); + + if( 0 != ret ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_handle_message_type" ), ret ); + return( ret ); + } + + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + update_hs_digest == 1 ) + { + mbedtls_ssl_update_handshake_status( ssl ); + } + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "reuse previously read message" ) ); + ssl->keep_current_message = 0; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= read record" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +static int ssl_next_record_is_in_datagram( mbedtls_ssl_context *ssl ) +{ + if( ssl->in_left > ssl->next_record_offset ) + return( 1 ); + + return( 0 ); +} + +static int ssl_load_buffered_message( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + mbedtls_ssl_hs_buffer * hs_buf; + int ret = 0; + + if( hs == NULL ) + return( -1 ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_load_buffered_messsage" ) ); + + if( ssl->state == MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC || + ssl->state == MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC ) + { + /* Check if we have seen a ChangeCipherSpec before. + * If yes, synthesize a CCS record. */ + if( !hs->buffering.seen_ccs ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "CCS not seen in the current flight" ) ); + ret = -1; + goto exit; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Injecting buffered CCS message" ) ); + ssl->in_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC; + ssl->in_msglen = 1; + ssl->in_msg[0] = 1; + + /* As long as they are equal, the exact value doesn't matter. */ + ssl->in_left = 0; + ssl->next_record_offset = 0; + + hs->buffering.seen_ccs = 0; + goto exit; + } + +#if defined(MBEDTLS_DEBUG_C) + /* Debug only */ + { + unsigned offset; + for( offset = 1; offset < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++ ) + { + hs_buf = &hs->buffering.hs[offset]; + if( hs_buf->is_valid == 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Future message with sequence number %u %s buffered.", + hs->in_msg_seq + offset, + hs_buf->is_complete ? "fully" : "partially" ) ); + } + } + } +#endif /* MBEDTLS_DEBUG_C */ + + /* Check if we have buffered and/or fully reassembled the + * next handshake message. */ + hs_buf = &hs->buffering.hs[0]; + if( ( hs_buf->is_valid == 1 ) && ( hs_buf->is_complete == 1 ) ) + { + /* Synthesize a record containing the buffered HS message. */ + size_t msg_len = ( hs_buf->data[1] << 16 ) | + ( hs_buf->data[2] << 8 ) | + hs_buf->data[3]; + + /* Double-check that we haven't accidentally buffered + * a message that doesn't fit into the input buffer. */ + if( msg_len + 12 > MBEDTLS_SSL_IN_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Next handshake message has been buffered - load" ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "Buffered handshake message (incl. header)", + hs_buf->data, msg_len + 12 ); + + ssl->in_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->in_hslen = msg_len + 12; + ssl->in_msglen = msg_len + 12; + memcpy( ssl->in_msg, hs_buf->data, ssl->in_hslen ); + + ret = 0; + goto exit; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Next handshake message %u not or only partially bufffered", + hs->in_msg_seq ) ); + } + + ret = -1; + +exit: + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_load_buffered_message" ) ); + return( ret ); +} + +static int ssl_buffer_make_space( mbedtls_ssl_context *ssl, + size_t desired ) +{ + int offset; + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Attempt to free buffered messages to have %u bytes available", + (unsigned) desired ) ); + + /* Get rid of future records epoch first, if such exist. */ + ssl_free_buffered_record( ssl ); + + /* Check if we have enough space available now. */ + if( desired <= ( MBEDTLS_SSL_DTLS_MAX_BUFFERING - + hs->buffering.total_bytes_buffered ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Enough space available after freeing future epoch record" ) ); + return( 0 ); + } + + /* We don't have enough space to buffer the next expected handshake + * message. Remove buffers used for future messages to gain space, + * starting with the most distant one. */ + for( offset = MBEDTLS_SSL_MAX_BUFFERED_HS - 1; + offset >= 0; offset-- ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Free buffering slot %d to make space for reassembly of next handshake message", + offset ) ); + + ssl_buffering_free_slot( ssl, (uint8_t) offset ); + + /* Check if we have enough space available now. */ + if( desired <= ( MBEDTLS_SSL_DTLS_MAX_BUFFERING - + hs->buffering.total_bytes_buffered ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Enough space available after freeing buffered HS messages" ) ); + return( 0 ); + } + } + + return( -1 ); +} + +static int ssl_buffer_message( mbedtls_ssl_context *ssl ) +{ + int ret = 0; + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + + if( hs == NULL ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_buffer_message" ) ); + + switch( ssl->in_msgtype ) + { + case MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Remember CCS message" ) ); + + hs->buffering.seen_ccs = 1; + break; + + case MBEDTLS_SSL_MSG_HANDSHAKE: + { + unsigned recv_msg_seq_offset; + unsigned recv_msg_seq = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5]; + mbedtls_ssl_hs_buffer *hs_buf; + size_t msg_len = ssl->in_hslen - 12; + + /* We should never receive an old handshake + * message - double-check nonetheless. */ + if( recv_msg_seq < ssl->handshake->in_msg_seq ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + recv_msg_seq_offset = recv_msg_seq - ssl->handshake->in_msg_seq; + if( recv_msg_seq_offset >= MBEDTLS_SSL_MAX_BUFFERED_HS ) + { + /* Silently ignore -- message too far in the future */ + MBEDTLS_SSL_DEBUG_MSG( 2, + ( "Ignore future HS message with sequence number %u, " + "buffering window %u - %u", + recv_msg_seq, ssl->handshake->in_msg_seq, + ssl->handshake->in_msg_seq + MBEDTLS_SSL_MAX_BUFFERED_HS - 1 ) ); + + goto exit; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering HS message with sequence number %u, offset %u ", + recv_msg_seq, recv_msg_seq_offset ) ); + + hs_buf = &hs->buffering.hs[ recv_msg_seq_offset ]; + + /* Check if the buffering for this seq nr has already commenced. */ + if( !hs_buf->is_valid ) + { + size_t reassembly_buf_sz; + + hs_buf->is_fragmented = + ( ssl_hs_is_proper_fragment( ssl ) == 1 ); + + /* We copy the message back into the input buffer + * after reassembly, so check that it's not too large. + * This is an implementation-specific limitation + * and not one from the standard, hence it is not + * checked in ssl_check_hs_header(). */ + if( msg_len + 12 > MBEDTLS_SSL_IN_CONTENT_LEN ) + { + /* Ignore message */ + goto exit; + } + + /* Check if we have enough space to buffer the message. */ + if( hs->buffering.total_bytes_buffered > + MBEDTLS_SSL_DTLS_MAX_BUFFERING ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + reassembly_buf_sz = ssl_get_reassembly_buffer_size( msg_len, + hs_buf->is_fragmented ); + + if( reassembly_buf_sz > ( MBEDTLS_SSL_DTLS_MAX_BUFFERING - + hs->buffering.total_bytes_buffered ) ) + { + if( recv_msg_seq_offset > 0 ) + { + /* If we can't buffer a future message because + * of space limitations -- ignore. */ + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future message of size %u would exceed the compile-time limit %u (already %u bytes buffered) -- ignore\n", + (unsigned) msg_len, MBEDTLS_SSL_DTLS_MAX_BUFFERING, + (unsigned) hs->buffering.total_bytes_buffered ) ); + goto exit; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future message of size %u would exceed the compile-time limit %u (already %u bytes buffered) -- attempt to make space by freeing buffered future messages\n", + (unsigned) msg_len, MBEDTLS_SSL_DTLS_MAX_BUFFERING, + (unsigned) hs->buffering.total_bytes_buffered ) ); + } + + if( ssl_buffer_make_space( ssl, reassembly_buf_sz ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Reassembly of next message of size %u (%u with bitmap) would exceed the compile-time limit %u (already %u bytes buffered) -- fail\n", + (unsigned) msg_len, + (unsigned) reassembly_buf_sz, + MBEDTLS_SSL_DTLS_MAX_BUFFERING, + (unsigned) hs->buffering.total_bytes_buffered ) ); + ret = MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; + goto exit; + } + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialize reassembly, total length = %d", + msg_len ) ); + + hs_buf->data = mbedtls_calloc( 1, reassembly_buf_sz ); + if( hs_buf->data == NULL ) + { + ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; + goto exit; + } + hs_buf->data_len = reassembly_buf_sz; + + /* Prepare final header: copy msg_type, length and message_seq, + * then add standardised fragment_offset and fragment_length */ + memcpy( hs_buf->data, ssl->in_msg, 6 ); + memset( hs_buf->data + 6, 0, 3 ); + memcpy( hs_buf->data + 9, hs_buf->data + 1, 3 ); + + hs_buf->is_valid = 1; + + hs->buffering.total_bytes_buffered += reassembly_buf_sz; + } + else + { + /* Make sure msg_type and length are consistent */ + if( memcmp( hs_buf->data, ssl->in_msg, 4 ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Fragment header mismatch - ignore" ) ); + /* Ignore */ + goto exit; + } + } + + if( !hs_buf->is_complete ) + { + size_t frag_len, frag_off; + unsigned char * const msg = hs_buf->data + 12; + + /* + * Check and copy current fragment + */ + + /* Validation of header fields already done in + * mbedtls_ssl_prepare_handshake_record(). */ + frag_off = ssl_get_hs_frag_off( ssl ); + frag_len = ssl_get_hs_frag_len( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "adding fragment, offset = %d, length = %d", + frag_off, frag_len ) ); + memcpy( msg + frag_off, ssl->in_msg + 12, frag_len ); + + if( hs_buf->is_fragmented ) + { + unsigned char * const bitmask = msg + msg_len; + ssl_bitmask_set( bitmask, frag_off, frag_len ); + hs_buf->is_complete = ( ssl_bitmask_check( bitmask, + msg_len ) == 0 ); + } + else + { + hs_buf->is_complete = 1; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "message %scomplete", + hs_buf->is_complete ? "" : "not yet " ) ); + } + + break; + } + + default: + /* We don't buffer other types of messages. */ + break; + } + +exit: + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_buffer_message" ) ); + return( ret ); +} +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +static int ssl_consume_current_message( mbedtls_ssl_context *ssl ) +{ + /* + * Consume last content-layer message and potentially + * update in_msglen which keeps track of the contents' + * consumption state. + * + * (1) Handshake messages: + * Remove last handshake message, move content + * and adapt in_msglen. + * + * (2) Alert messages: + * Consume whole record content, in_msglen = 0. + * + * (3) Change cipher spec: + * Consume whole record content, in_msglen = 0. + * + * (4) Application data: + * Don't do anything - the record layer provides + * the application data as a stream transport + * and consumes through mbedtls_ssl_read only. + * + */ + + /* Case (1): Handshake messages */ + if( ssl->in_hslen != 0 ) + { + /* Hard assertion to be sure that no application data + * is in flight, as corrupting ssl->in_msglen during + * ssl->in_offt != NULL is fatal. */ + if( ssl->in_offt != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* + * Get next Handshake message in the current record + */ + + /* Notes: + * (1) in_hslen is not necessarily the size of the + * current handshake content: If DTLS handshake + * fragmentation is used, that's the fragment + * size instead. Using the total handshake message + * size here is faulty and should be changed at + * some point. + * (2) While it doesn't seem to cause problems, one + * has to be very careful not to assume that in_hslen + * is always <= in_msglen in a sensible communication. + * Again, it's wrong for DTLS handshake fragmentation. + * The following check is therefore mandatory, and + * should not be treated as a silently corrected assertion. + * Additionally, ssl->in_hslen might be arbitrarily out of + * bounds after handling a DTLS message with an unexpected + * sequence number, see mbedtls_ssl_prepare_handshake_record. + */ + if( ssl->in_hslen < ssl->in_msglen ) + { + ssl->in_msglen -= ssl->in_hslen; + memmove( ssl->in_msg, ssl->in_msg + ssl->in_hslen, + ssl->in_msglen ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "remaining content in record", + ssl->in_msg, ssl->in_msglen ); + } + else + { + ssl->in_msglen = 0; + } + + ssl->in_hslen = 0; + } + /* Case (4): Application data */ + else if( ssl->in_offt != NULL ) + { + return( 0 ); + } + /* Everything else (CCS & Alerts) */ + else + { + ssl->in_msglen = 0; + } + + return( 0 ); +} + +static int ssl_record_is_in_progress( mbedtls_ssl_context *ssl ) +{ + if( ssl->in_msglen > 0 ) + return( 1 ); + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + +static void ssl_free_buffered_record( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + if( hs == NULL ) + return; + + if( hs->buffering.future_record.data != NULL ) + { + hs->buffering.total_bytes_buffered -= + hs->buffering.future_record.len; + + mbedtls_free( hs->buffering.future_record.data ); + hs->buffering.future_record.data = NULL; + } +} + +static int ssl_load_buffered_record( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + unsigned char * rec; + size_t rec_len; + unsigned rec_epoch; +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t in_buf_len = ssl->in_buf_len; +#else + size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN; +#endif + if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + return( 0 ); + + if( hs == NULL ) + return( 0 ); + + rec = hs->buffering.future_record.data; + rec_len = hs->buffering.future_record.len; + rec_epoch = hs->buffering.future_record.epoch; + + if( rec == NULL ) + return( 0 ); + + /* Only consider loading future records if the + * input buffer is empty. */ + if( ssl_next_record_is_in_datagram( ssl ) == 1 ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_load_buffered_record" ) ); + + if( rec_epoch != ssl->in_epoch ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffered record not from current epoch." ) ); + goto exit; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Found buffered record from current epoch - load" ) ); + + /* Double-check that the record is not too large */ + if( rec_len > in_buf_len - (size_t)( ssl->in_hdr - ssl->in_buf ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + memcpy( ssl->in_hdr, rec, rec_len ); + ssl->in_left = rec_len; + ssl->next_record_offset = 0; + + ssl_free_buffered_record( ssl ); + +exit: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_load_buffered_record" ) ); + return( 0 ); +} + +static int ssl_buffer_future_record( mbedtls_ssl_context *ssl, + mbedtls_record const *rec ) +{ + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + + /* Don't buffer future records outside handshakes. */ + if( hs == NULL ) + return( 0 ); + + /* Only buffer handshake records (we are only interested + * in Finished messages). */ + if( rec->type != MBEDTLS_SSL_MSG_HANDSHAKE ) + return( 0 ); + + /* Don't buffer more than one future epoch record. */ + if( hs->buffering.future_record.data != NULL ) + return( 0 ); + + /* Don't buffer record if there's not enough buffering space remaining. */ + if( rec->buf_len > ( MBEDTLS_SSL_DTLS_MAX_BUFFERING - + hs->buffering.total_bytes_buffered ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future epoch record of size %u would exceed the compile-time limit %u (already %u bytes buffered) -- ignore\n", + (unsigned) rec->buf_len, MBEDTLS_SSL_DTLS_MAX_BUFFERING, + (unsigned) hs->buffering.total_bytes_buffered ) ); + return( 0 ); + } + + /* Buffer record */ + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffer record from epoch %u", + ssl->in_epoch + 1 ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "Buffered record", rec->buf, rec->buf_len ); + + /* ssl_parse_record_header() only considers records + * of the next epoch as candidates for buffering. */ + hs->buffering.future_record.epoch = ssl->in_epoch + 1; + hs->buffering.future_record.len = rec->buf_len; + + hs->buffering.future_record.data = + mbedtls_calloc( 1, hs->buffering.future_record.len ); + if( hs->buffering.future_record.data == NULL ) + { + /* If we run out of RAM trying to buffer a + * record from the next epoch, just ignore. */ + return( 0 ); + } + + memcpy( hs->buffering.future_record.data, rec->buf, rec->buf_len ); + + hs->buffering.total_bytes_buffered += rec->buf_len; + return( 0 ); +} + +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +static int ssl_get_next_record( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_record rec; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + /* We might have buffered a future record; if so, + * and if the epoch matches now, load it. + * On success, this call will set ssl->in_left to + * the length of the buffered record, so that + * the calls to ssl_fetch_input() below will + * essentially be no-ops. */ + ret = ssl_load_buffered_record( ssl ); + if( ret != 0 ) + return( ret ); +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + /* Ensure that we have enough space available for the default form + * of TLS / DTLS record headers (5 Bytes for TLS, 13 Bytes for DTLS, + * with no space for CIDs counted in). */ + ret = mbedtls_ssl_fetch_input( ssl, mbedtls_ssl_in_hdr_len( ssl ) ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); + return( ret ); + } + + ret = ssl_parse_record_header( ssl, ssl->in_hdr, ssl->in_left, &rec ); + if( ret != 0 ) + { +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + if( ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE ) + { + ret = ssl_buffer_future_record( ssl, &rec ); + if( ret != 0 ) + return( ret ); + + /* Fall through to handling of unexpected records */ + ret = MBEDTLS_ERR_SSL_UNEXPECTED_RECORD; + } + + if( ret == MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ) + { +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) + /* Reset in pointers to default state for TLS/DTLS records, + * assuming no CID and no offset between record content and + * record plaintext. */ + mbedtls_ssl_update_in_pointers( ssl ); + + /* Setup internal message pointers from record structure. */ + ssl->in_msgtype = rec.type; +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + ssl->in_len = ssl->in_cid + rec.cid_len; +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + ssl->in_iv = ssl->in_msg = ssl->in_len + 2; + ssl->in_msglen = rec.data_len; + + ret = ssl_check_client_reconnect( ssl ); + MBEDTLS_SSL_DEBUG_RET( 2, "ssl_check_client_reconnect", ret ); + if( ret != 0 ) + return( ret ); +#endif + + /* Skip unexpected record (but not whole datagram) */ + ssl->next_record_offset = rec.buf_len; + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding unexpected record " + "(header)" ) ); + } + else + { + /* Skip invalid record and the rest of the datagram */ + ssl->next_record_offset = 0; + ssl->in_left = 0; + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding invalid record " + "(header)" ) ); + } + + /* Get next record */ + return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ); + } + else +#endif + { + return( ret ); + } + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + /* Remember offset of next record within datagram. */ + ssl->next_record_offset = rec.buf_len; + if( ssl->next_record_offset < ssl->in_left ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "more than one record within datagram" ) ); + } + } + else +#endif + { + /* + * Fetch record contents from underlying transport. + */ + ret = mbedtls_ssl_fetch_input( ssl, rec.buf_len ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); + return( ret ); + } + + ssl->in_left = 0; + } + + /* + * Decrypt record contents. + */ + + if( ( ret = ssl_prepare_record_content( ssl, &rec ) ) != 0 ) + { +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + /* Silently discard invalid records */ + if( ret == MBEDTLS_ERR_SSL_INVALID_MAC ) + { + /* Except when waiting for Finished as a bad mac here + * probably means something went wrong in the handshake + * (eg wrong psk used, mitm downgrade attempt, etc.) */ + if( ssl->state == MBEDTLS_SSL_CLIENT_FINISHED || + ssl->state == MBEDTLS_SSL_SERVER_FINISHED ) + { +#if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES) + if( ret == MBEDTLS_ERR_SSL_INVALID_MAC ) + { + mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC ); + } +#endif + return( ret ); + } + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) + if( ssl->conf->badmac_limit != 0 && + ++ssl->badmac_seen >= ssl->conf->badmac_limit ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "too many records with bad MAC" ) ); + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } +#endif + + /* As above, invalid records cause + * dismissal of the whole datagram. */ + + ssl->next_record_offset = 0; + ssl->in_left = 0; + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding invalid record (mac)" ) ); + return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ); + } + + return( ret ); + } + else +#endif + { + /* Error out (and send alert) on invalid records */ +#if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES) + if( ret == MBEDTLS_ERR_SSL_INVALID_MAC ) + { + mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC ); + } +#endif + return( ret ); + } + } + + + /* Reset in pointers to default state for TLS/DTLS records, + * assuming no CID and no offset between record content and + * record plaintext. */ + mbedtls_ssl_update_in_pointers( ssl ); +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + ssl->in_len = ssl->in_cid + rec.cid_len; +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + ssl->in_iv = ssl->in_len + 2; + + /* The record content type may change during decryption, + * so re-read it. */ + ssl->in_msgtype = rec.type; + /* Also update the input buffer, because unfortunately + * the server-side ssl_parse_client_hello() reparses the + * record header when receiving a ClientHello initiating + * a renegotiation. */ + ssl->in_hdr[0] = rec.type; + ssl->in_msg = rec.buf + rec.data_offset; + ssl->in_msglen = rec.data_len; + ssl->in_len[0] = (unsigned char)( rec.data_len >> 8 ); + ssl->in_len[1] = (unsigned char)( rec.data_len ); + +#if defined(MBEDTLS_ZLIB_SUPPORT) + if( ssl->transform_in != NULL && + ssl->session_in->compression == MBEDTLS_SSL_COMPRESS_DEFLATE ) + { + if( ( ret = ssl_decompress_buf( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_decompress_buf", ret ); + return( ret ); + } + + /* Check actual (decompress) record content length against + * configured maximum. */ + if( ssl->in_msglen > MBEDTLS_SSL_IN_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + } +#endif /* MBEDTLS_ZLIB_SUPPORT */ + + return( 0 ); +} + +int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* + * Handle particular types of records + */ + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) + { + if( ( ret = mbedtls_ssl_prepare_handshake_record( ssl ) ) != 0 ) + { + return( ret ); + } + } + + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC ) + { + if( ssl->in_msglen != 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid CCS message, len: %d", + ssl->in_msglen ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + if( ssl->in_msg[0] != 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid CCS message, content: %02x", + ssl->in_msg[0] ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->state != MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC && + ssl->state != MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC ) + { + if( ssl->handshake == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping ChangeCipherSpec outside handshake" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "received out-of-order ChangeCipherSpec - remember" ) ); + return( MBEDTLS_ERR_SSL_EARLY_MESSAGE ); + } +#endif + } + + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT ) + { + if( ssl->in_msglen != 2 ) + { + /* Note: Standard allows for more than one 2 byte alert + to be packed in a single message, but Mbed TLS doesn't + currently support this. */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid alert message, len: %d", + ssl->in_msglen ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "got an alert message, type: [%d:%d]", + ssl->in_msg[0], ssl->in_msg[1] ) ); + + /* + * Ignore non-fatal alerts, except close_notify and no_renegotiation + */ + if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_FATAL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "is a fatal alert message (msg %d)", + ssl->in_msg[1] ) ); + return( MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE ); + } + + if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && + ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a close notify message" ) ); + return( MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY ); + } + +#if defined(MBEDTLS_SSL_RENEGOTIATION_ENABLED) + if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && + ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a SSLv3 no renegotiation alert" ) ); + /* Will be handled when trying to parse ServerHello */ + return( 0 ); + } +#endif + +#if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_SRV_C) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 && + ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && + ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_CERT ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a SSLv3 no_cert" ) ); + /* Will be handled in mbedtls_ssl_parse_certificate() */ + return( 0 ); + } +#endif /* MBEDTLS_SSL_PROTO_SSL3 && MBEDTLS_SSL_SRV_C */ + + /* Silently ignore: fetch new message */ + return MBEDTLS_ERR_SSL_NON_FATAL; + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + /* Drop unexpected ApplicationData records, + * except at the beginning of renegotiations */ + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA && + ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER +#if defined(MBEDTLS_SSL_RENEGOTIATION) + && ! ( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->state == MBEDTLS_SSL_SERVER_HELLO ) +#endif + ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping unexpected ApplicationData" ) ); + return( MBEDTLS_ERR_SSL_NON_FATAL ); + } + + if( ssl->handshake != NULL && + ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) + { + mbedtls_ssl_handshake_wrapup_free_hs_transform( ssl ); + } + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + return( 0 ); +} + +int mbedtls_ssl_send_fatal_handshake_failure( mbedtls_ssl_context *ssl ) +{ + return( mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ) ); +} + +int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl, + unsigned char level, + unsigned char message ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> send alert message" ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "send alert level=%u message=%u", level, message )); + + ssl->out_msgtype = MBEDTLS_SSL_MSG_ALERT; + ssl->out_msglen = 2; + ssl->out_msg[0] = level; + ssl->out_msg[1] = message; + + if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= send alert message" ) ); + + return( 0 ); +} + +int mbedtls_ssl_write_change_cipher_spec( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write change cipher spec" ) ); + + ssl->out_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC; + ssl->out_msglen = 1; + ssl->out_msg[0] = 1; + + ssl->state++; + + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write change cipher spec" ) ); + + return( 0 ); +} + +int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse change cipher spec" ) ); + + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + /* CCS records are only accepted if they have length 1 and content '1', + * so we don't need to check this here. */ + + /* + * Switch to our negotiated transform and session parameters for inbound + * data. + */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "switching to new transform spec for inbound data" ) ); + ssl->transform_in = ssl->transform_negotiate; + ssl->session_in = ssl->session_negotiate; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + mbedtls_ssl_dtls_replay_reset( ssl ); +#endif + + /* Increment epoch */ + if( ++ssl->in_epoch == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS epoch would wrap" ) ); + /* This is highly unlikely to happen for legitimate reasons, so + treat it as an attack and don't send an alert. */ + return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); + } + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + memset( ssl->in_ctr, 0, 8 ); + + mbedtls_ssl_update_in_pointers( ssl ); + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_activate != NULL ) + { + if( ( ret = mbedtls_ssl_hw_record_activate( ssl, MBEDTLS_SSL_CHANNEL_INBOUND ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_activate", ret ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + } +#endif + + ssl->state++; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse change cipher spec" ) ); + + return( 0 ); +} + +/* Once ssl->out_hdr as the address of the beginning of the + * next outgoing record is set, deduce the other pointers. + * + * Note: For TLS, we save the implicit record sequence number + * (entering MAC computation) in the 8 bytes before ssl->out_hdr, + * and the caller has to make sure there's space for this. + */ + +static size_t ssl_transform_get_explicit_iv_len( + mbedtls_ssl_transform const *transform ) +{ + if( transform->minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 ) + return( 0 ); + + return( transform->ivlen - transform->fixed_ivlen ); +} + +void mbedtls_ssl_update_out_pointers( mbedtls_ssl_context *ssl, + mbedtls_ssl_transform *transform ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ssl->out_ctr = ssl->out_hdr + 3; +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + ssl->out_cid = ssl->out_ctr + 8; + ssl->out_len = ssl->out_cid; + if( transform != NULL ) + ssl->out_len += transform->out_cid_len; +#else /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + ssl->out_len = ssl->out_ctr + 8; +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + ssl->out_iv = ssl->out_len + 2; + } + else +#endif + { + ssl->out_ctr = ssl->out_hdr - 8; + ssl->out_len = ssl->out_hdr + 3; +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + ssl->out_cid = ssl->out_len; +#endif + ssl->out_iv = ssl->out_hdr + 5; + } + + ssl->out_msg = ssl->out_iv; + /* Adjust out_msg to make space for explicit IV, if used. */ + if( transform != NULL ) + ssl->out_msg += ssl_transform_get_explicit_iv_len( transform ); +} + +/* Once ssl->in_hdr as the address of the beginning of the + * next incoming record is set, deduce the other pointers. + * + * Note: For TLS, we save the implicit record sequence number + * (entering MAC computation) in the 8 bytes before ssl->in_hdr, + * and the caller has to make sure there's space for this. + */ + +void mbedtls_ssl_update_in_pointers( mbedtls_ssl_context *ssl ) +{ + /* This function sets the pointers to match the case + * of unprotected TLS/DTLS records, with both ssl->in_iv + * and ssl->in_msg pointing to the beginning of the record + * content. + * + * When decrypting a protected record, ssl->in_msg + * will be shifted to point to the beginning of the + * record plaintext. + */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + /* This sets the header pointers to match records + * without CID. When we receive a record containing + * a CID, the fields are shifted accordingly in + * ssl_parse_record_header(). */ + ssl->in_ctr = ssl->in_hdr + 3; +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + ssl->in_cid = ssl->in_ctr + 8; + ssl->in_len = ssl->in_cid; /* Default: no CID */ +#else /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + ssl->in_len = ssl->in_ctr + 8; +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + ssl->in_iv = ssl->in_len + 2; + } + else +#endif + { + ssl->in_ctr = ssl->in_hdr - 8; + ssl->in_len = ssl->in_hdr + 3; +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + ssl->in_cid = ssl->in_len; +#endif + ssl->in_iv = ssl->in_hdr + 5; + } + + /* This will be adjusted at record decryption time. */ + ssl->in_msg = ssl->in_iv; +} + +/* + * Setup an SSL context + */ + +void mbedtls_ssl_reset_in_out_pointers( mbedtls_ssl_context *ssl ) +{ + /* Set the incoming and outgoing record pointers. */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ssl->out_hdr = ssl->out_buf; + ssl->in_hdr = ssl->in_buf; + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + { + ssl->out_hdr = ssl->out_buf + 8; + ssl->in_hdr = ssl->in_buf + 8; + } + + /* Derive other internal pointers. */ + mbedtls_ssl_update_out_pointers( ssl, NULL /* no transform enabled */ ); + mbedtls_ssl_update_in_pointers ( ssl ); +} + +/* + * SSL get accessors + */ +size_t mbedtls_ssl_get_bytes_avail( const mbedtls_ssl_context *ssl ) +{ + return( ssl->in_offt == NULL ? 0 : ssl->in_msglen ); +} + +int mbedtls_ssl_check_pending( const mbedtls_ssl_context *ssl ) +{ + /* + * Case A: We're currently holding back + * a message for further processing. + */ + + if( ssl->keep_current_message == 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: record held back for processing" ) ); + return( 1 ); + } + + /* + * Case B: Further records are pending in the current datagram. + */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->in_left > ssl->next_record_offset ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: more records within current datagram" ) ); + return( 1 ); + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + /* + * Case C: A handshake message is being processed. + */ + + if( ssl->in_hslen > 0 && ssl->in_hslen < ssl->in_msglen ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: more handshake messages within current record" ) ); + return( 1 ); + } + + /* + * Case D: An application data message is being processed + */ + if( ssl->in_offt != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: application data record is being processed" ) ); + return( 1 ); + } + + /* + * In all other cases, the rest of the message can be dropped. + * As in ssl_get_next_record, this needs to be adapted if + * we implement support for multiple alerts in single records. + */ + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: nothing pending" ) ); + return( 0 ); +} + + +int mbedtls_ssl_get_record_expansion( const mbedtls_ssl_context *ssl ) +{ + size_t transform_expansion = 0; + const mbedtls_ssl_transform *transform = ssl->transform_out; + unsigned block_size; + + size_t out_hdr_len = mbedtls_ssl_out_hdr_len( ssl ); + + if( transform == NULL ) + return( (int) out_hdr_len ); + +#if defined(MBEDTLS_ZLIB_SUPPORT) + if( ssl->session_out->compression != MBEDTLS_SSL_COMPRESS_NULL ) + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); +#endif + + switch( mbedtls_cipher_get_cipher_mode( &transform->cipher_ctx_enc ) ) + { + case MBEDTLS_MODE_GCM: + case MBEDTLS_MODE_CCM: + case MBEDTLS_MODE_CHACHAPOLY: + case MBEDTLS_MODE_STREAM: + transform_expansion = transform->minlen; + break; + + case MBEDTLS_MODE_CBC: + + block_size = mbedtls_cipher_get_block_size( + &transform->cipher_ctx_enc ); + + /* Expansion due to the addition of the MAC. */ + transform_expansion += transform->maclen; + + /* Expansion due to the addition of CBC padding; + * Theoretically up to 256 bytes, but we never use + * more than the block size of the underlying cipher. */ + transform_expansion += block_size; + + /* For TLS 1.1 or higher, an explicit IV is added + * after the record header. */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) + transform_expansion += block_size; +#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */ + + break; + + default: + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + if( transform->out_cid_len != 0 ) + transform_expansion += MBEDTLS_SSL_MAX_CID_EXPANSION; +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + + return( (int)( out_hdr_len + transform_expansion ) ); +} + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +/* + * Check record counters and renegotiate if they're above the limit. + */ +static int ssl_check_ctr_renegotiate( mbedtls_ssl_context *ssl ) +{ + size_t ep_len = mbedtls_ssl_ep_len( ssl ); + int in_ctr_cmp; + int out_ctr_cmp; + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER || + ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING || + ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED ) + { + return( 0 ); + } + + in_ctr_cmp = memcmp( ssl->in_ctr + ep_len, + ssl->conf->renego_period + ep_len, 8 - ep_len ); + out_ctr_cmp = memcmp( ssl->cur_out_ctr + ep_len, + ssl->conf->renego_period + ep_len, 8 - ep_len ); + + if( in_ctr_cmp <= 0 && out_ctr_cmp <= 0 ) + { + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "record counter limit reached: renegotiate" ) ); + return( mbedtls_ssl_renegotiate( ssl ) ); +} +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +/* + * Receive application data decrypted from the SSL layer + */ +int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n; + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> read" ) ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + return( ret ); + + if( ssl->handshake != NULL && + ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) + { + if( ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) + return( ret ); + } + } +#endif + + /* + * Check if renegotiation is necessary and/or handshake is + * in process. If yes, perform/continue, and fall through + * if an unexpected packet is received while the client + * is waiting for the ServerHello. + * + * (There is no equivalent to the last condition on + * the server-side as it is not treated as within + * a handshake while waiting for the ClientHello + * after a renegotiation request.) + */ + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ret = ssl_check_ctr_renegotiate( ssl ); + if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO && + ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_check_ctr_renegotiate", ret ); + return( ret ); + } +#endif + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + { + ret = mbedtls_ssl_handshake( ssl ); + if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO && + ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); + return( ret ); + } + } + + /* Loop as long as no application data record is available */ + while( ssl->in_offt == NULL ) + { + /* Start timer if not already running */ + if( ssl->f_get_timer != NULL && + ssl->f_get_timer( ssl->p_timer ) == -1 ) + { + mbedtls_ssl_set_timer( ssl, ssl->conf->read_timeout ); + } + + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_SSL_CONN_EOF ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msglen == 0 && + ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA ) + { + /* + * OpenSSL sends empty messages to randomize the IV + */ + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_SSL_CONN_EOF ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + } + + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "received handshake message" ) ); + + /* + * - For client-side, expect SERVER_HELLO_REQUEST. + * - For server-side, expect CLIENT_HELLO. + * - Fail (TLS) or silently drop record (DTLS) in other cases. + */ + +#if defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && + ( ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_REQUEST || + ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake received (not HelloRequest)" ) ); + + /* With DTLS, drop the packet (probably from last handshake) */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + continue; + } +#endif + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } +#endif /* MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake received (not ClientHello)" ) ); + + /* With DTLS, drop the packet (probably from last handshake) */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + continue; + } +#endif + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + /* Determine whether renegotiation attempt should be accepted */ + if( ! ( ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED || + ( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + ssl->conf->allow_legacy_renegotiation == + MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) ) ) + { + /* + * Accept renegotiation request + */ + + /* DTLS clients need to know renego is server-initiated */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + { + ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING; + } +#endif + ret = mbedtls_ssl_start_renegotiation( ssl ); + if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO && + ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_start_renegotiation", + ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + { + /* + * Refuse renegotiation + */ + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "refusing renegotiation, sending alert" ) ); + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + /* SSLv3 does not have a "no_renegotiation" warning, so + we send a fatal alert and abort the connection. */ + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 ) + { + if( ( ret = mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_WARNING, + MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION ) ) != 0 ) + { + return( ret ); + } + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || + MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } + + /* At this point, we don't know whether the renegotiation has been + * completed or not. The cases to consider are the following: + * 1) The renegotiation is complete. In this case, no new record + * has been read yet. + * 2) The renegotiation is incomplete because the client received + * an application data record while awaiting the ServerHello. + * 3) The renegotiation is incomplete because the client received + * a non-handshake, non-application data message while awaiting + * the ServerHello. + * In each of these case, looping will be the proper action: + * - For 1), the next iteration will read a new record and check + * if it's application data. + * - For 2), the loop condition isn't satisfied as application data + * is present, hence continue is the same as break + * - For 3), the loop condition is satisfied and read_record + * will re-deliver the message that was held back by the client + * when expecting the ServerHello. + */ + continue; + } +#if defined(MBEDTLS_SSL_RENEGOTIATION) + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) + { + if( ssl->conf->renego_max_records >= 0 ) + { + if( ++ssl->renego_records_seen > ssl->conf->renego_max_records ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation requested, " + "but not honored by client" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + } + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + /* Fatal and closure alerts handled by mbedtls_ssl_read_record() */ + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "ignoring non-fatal non-closure alert" ) ); + return( MBEDTLS_ERR_SSL_WANT_READ ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_APPLICATION_DATA ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad application data message" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + ssl->in_offt = ssl->in_msg; + + /* We're going to return something now, cancel timer, + * except if handshake (renegotiation) is in progress */ + if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) + mbedtls_ssl_set_timer( ssl, 0 ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + /* If we requested renego but received AppData, resend HelloRequest. + * Do it now, after setting in_offt, to avoid taking this branch + * again if ssl_write_hello_request() returns WANT_WRITE */ +#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) + { + if( ( ret = mbedtls_ssl_resend_hello_request( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend_hello_request", + ret ); + return( ret ); + } + } +#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */ +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + } + + n = ( len < ssl->in_msglen ) + ? len : ssl->in_msglen; + + memcpy( buf, ssl->in_offt, n ); + ssl->in_msglen -= n; + + /* Zeroising the plaintext buffer to erase unused application data + from the memory. */ + mbedtls_platform_zeroize( ssl->in_offt, n ); + + if( ssl->in_msglen == 0 ) + { + /* all bytes consumed */ + ssl->in_offt = NULL; + ssl->keep_current_message = 0; + } + else + { + /* more data available */ + ssl->in_offt += n; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= read" ) ); + + return( (int) n ); +} + +/* + * Send application data to be encrypted by the SSL layer, taking care of max + * fragment length and buffer size. + * + * According to RFC 5246 Section 6.2.1: + * + * Zero-length fragments of Application data MAY be sent as they are + * potentially useful as a traffic analysis countermeasure. + * + * Therefore, it is possible that the input message length is 0 and the + * corresponding return code is 0 on success. + */ +static int ssl_write_real( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + int ret = mbedtls_ssl_get_max_out_record_payload( ssl ); + const size_t max_len = (size_t) ret; + + if( ret < 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_get_max_out_record_payload", ret ); + return( ret ); + } + + if( len > max_len ) + { +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "fragment larger than the (negotiated) " + "maximum fragment length: %d > %d", + len, max_len ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + else +#endif + len = max_len; + } + + if( ssl->out_left != 0 ) + { + /* + * The user has previously tried to send the data and + * MBEDTLS_ERR_SSL_WANT_WRITE or the message was only partially + * written. In this case, we expect the high-level write function + * (e.g. mbedtls_ssl_write()) to be called with the same parameters + */ + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flush_output", ret ); + return( ret ); + } + } + else + { + /* + * The user is trying to send a message the first time, so we need to + * copy the data into the internal buffers and setup the data structure + * to keep track of partial writes + */ + ssl->out_msglen = len; + ssl->out_msgtype = MBEDTLS_SSL_MSG_APPLICATION_DATA; + memcpy( ssl->out_msg, buf, len ); + + if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + } + + return( (int) len ); +} + +/* + * Write application data, doing 1/n-1 splitting if necessary. + * + * With non-blocking I/O, ssl_write_real() may return WANT_WRITE, + * then the caller will call us again with the same arguments, so + * remember whether we already did the split or not. + */ +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) +static int ssl_write_split( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ssl->conf->cbc_record_splitting == + MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED || + len <= 1 || + ssl->minor_ver > MBEDTLS_SSL_MINOR_VERSION_1 || + mbedtls_cipher_get_cipher_mode( &ssl->transform_out->cipher_ctx_enc ) + != MBEDTLS_MODE_CBC ) + { + return( ssl_write_real( ssl, buf, len ) ); + } + + if( ssl->split_done == 0 ) + { + if( ( ret = ssl_write_real( ssl, buf, 1 ) ) <= 0 ) + return( ret ); + ssl->split_done = 1; + } + + if( ( ret = ssl_write_real( ssl, buf + 1, len - 1 ) ) <= 0 ) + return( ret ); + ssl->split_done = 0; + + return( ret + 1 ); +} +#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */ + +/* + * Write application data (public-facing wrapper) + */ +int mbedtls_ssl_write( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write" ) ); + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ( ret = ssl_check_ctr_renegotiate( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_check_ctr_renegotiate", ret ); + return( ret ); + } +#endif + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + { + if( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); + return( ret ); + } + } + +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) + ret = ssl_write_split( ssl, buf, len ); +#else + ret = ssl_write_real( ssl, buf, len ); +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write" ) ); + + return( ret ); +} + +/* + * Notify the peer that the connection is being closed + */ +int mbedtls_ssl_close_notify( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write close notify" ) ); + + if( ssl->out_left != 0 ) + return( mbedtls_ssl_flush_output( ssl ) ); + + if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) + { + if( ( ret = mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_WARNING, + MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_send_alert_message", ret ); + return( ret ); + } + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write close notify" ) ); + + return( 0 ); +} + +void mbedtls_ssl_transform_free( mbedtls_ssl_transform *transform ) +{ + if( transform == NULL ) + return; + +#if defined(MBEDTLS_ZLIB_SUPPORT) + deflateEnd( &transform->ctx_deflate ); + inflateEnd( &transform->ctx_inflate ); +#endif + + mbedtls_cipher_free( &transform->cipher_ctx_enc ); + mbedtls_cipher_free( &transform->cipher_ctx_dec ); + +#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) + mbedtls_md_free( &transform->md_ctx_enc ); + mbedtls_md_free( &transform->md_ctx_dec ); +#endif + + mbedtls_platform_zeroize( transform, sizeof( mbedtls_ssl_transform ) ); +} + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + +void mbedtls_ssl_buffering_free( mbedtls_ssl_context *ssl ) +{ + unsigned offset; + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + + if( hs == NULL ) + return; + + ssl_free_buffered_record( ssl ); + + for( offset = 0; offset < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++ ) + ssl_buffering_free_slot( ssl, offset ); +} + +static void ssl_buffering_free_slot( mbedtls_ssl_context *ssl, + uint8_t slot ) +{ + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + mbedtls_ssl_hs_buffer * const hs_buf = &hs->buffering.hs[slot]; + + if( slot >= MBEDTLS_SSL_MAX_BUFFERED_HS ) + return; + + if( hs_buf->is_valid == 1 ) + { + hs->buffering.total_bytes_buffered -= hs_buf->data_len; + mbedtls_platform_zeroize( hs_buf->data, hs_buf->data_len ); + mbedtls_free( hs_buf->data ); + memset( hs_buf, 0, sizeof( mbedtls_ssl_hs_buffer ) ); + } +} + +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +/* + * Convert version numbers to/from wire format + * and, for DTLS, to/from TLS equivalent. + * + * For TLS this is the identity. + * For DTLS, use 1's complement (v -> 255 - v, and then map as follows: + * 1.0 <-> 3.2 (DTLS 1.0 is based on TLS 1.1) + * 1.x <-> 3.x+1 for x != 0 (DTLS 1.2 based on TLS 1.2) + */ +void mbedtls_ssl_write_version( int major, int minor, int transport, + unsigned char ver[2] ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + if( minor == MBEDTLS_SSL_MINOR_VERSION_2 ) + --minor; /* DTLS 1.0 stored as TLS 1.1 internally */ + + ver[0] = (unsigned char)( 255 - ( major - 2 ) ); + ver[1] = (unsigned char)( 255 - ( minor - 1 ) ); + } + else +#else + ((void) transport); +#endif + { + ver[0] = (unsigned char) major; + ver[1] = (unsigned char) minor; + } +} + +void mbedtls_ssl_read_version( int *major, int *minor, int transport, + const unsigned char ver[2] ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + *major = 255 - ver[0] + 2; + *minor = 255 - ver[1] + 1; + + if( *minor == MBEDTLS_SSL_MINOR_VERSION_1 ) + ++*minor; /* DTLS 1.0 stored as TLS 1.1 internally */ + } + else +#else + ((void) transport); +#endif + { + *major = ver[0]; + *minor = ver[1]; + } +} + +#endif /* MBEDTLS_SSL_TLS_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/ssl_srv.c b/Android/Level4/app/src/main/c/mbedtls/library/ssl_srv.c new file mode 100644 index 0000000..070a591 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/ssl_srv.c @@ -0,0 +1,4780 @@ +/* + * SSLv3/TLSv1 server-side functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 "common.h" + +#if defined(MBEDTLS_SSL_SRV_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/ssl.h" +#include "mbedtls/ssl_internal.h" +#include "mbedtls/debug.h" +#include "mbedtls/error.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/ecp.h" +#endif + +#if defined(MBEDTLS_HAVE_TIME) +#include "mbedtls/platform_time.h" +#endif + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) +int mbedtls_ssl_set_client_transport_id( mbedtls_ssl_context *ssl, + const unsigned char *info, + size_t ilen ) +{ + if( ssl->conf->endpoint != MBEDTLS_SSL_IS_SERVER ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + mbedtls_free( ssl->cli_id ); + + if( ( ssl->cli_id = mbedtls_calloc( 1, ilen ) ) == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + memcpy( ssl->cli_id, info, ilen ); + ssl->cli_id_len = ilen; + + return( 0 ); +} + +void mbedtls_ssl_conf_dtls_cookies( mbedtls_ssl_config *conf, + mbedtls_ssl_cookie_write_t *f_cookie_write, + mbedtls_ssl_cookie_check_t *f_cookie_check, + void *p_cookie ) +{ + conf->f_cookie_write = f_cookie_write; + conf->f_cookie_check = f_cookie_check; + conf->p_cookie = p_cookie; +} +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t servername_list_size, hostname_len; + const unsigned char *p; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "parse ServerName extension" ) ); + + if( len < 2 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + servername_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); + if( servername_list_size + 2 != len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + p = buf + 2; + while( servername_list_size > 2 ) + { + hostname_len = ( ( p[1] << 8 ) | p[2] ); + if( hostname_len + 3 > servername_list_size ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + if( p[0] == MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME ) + { + ret = ssl->conf->f_sni( ssl->conf->p_sni, + ssl, p + 3, hostname_len ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_sni_wrapper", ret ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNRECOGNIZED_NAME ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + return( 0 ); + } + + servername_list_size -= hostname_len + 3; + p += hostname_len + 3; + } + + if( servername_list_size != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) +static int ssl_conf_has_psk_or_cb( mbedtls_ssl_config const *conf ) +{ + if( conf->f_psk != NULL ) + return( 1 ); + + if( conf->psk_identity_len == 0 || conf->psk_identity == NULL ) + return( 0 ); + + if( conf->psk != NULL && conf->psk_len != 0 ) + return( 1 ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( conf->psk_opaque != 0 ) + return( 1 ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + return( 0 ); +} + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +static int ssl_use_opaque_psk( mbedtls_ssl_context const *ssl ) +{ + if( ssl->conf->f_psk != NULL ) + { + /* If we've used a callback to select the PSK, + * the static configuration is irrelevant. */ + + if( ssl->handshake->psk_opaque != 0 ) + return( 1 ); + + return( 0 ); + } + + if( ssl->conf->psk_opaque != 0 ) + return( 1 ); + + return( 0 ); +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ + +static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) + { + /* Check verify-data in constant-time. The length OTOH is no secret */ + if( len != 1 + ssl->verify_data_len || + buf[0] != ssl->verify_data_len || + mbedtls_ssl_safer_memcmp( buf + 1, ssl->peer_verify_data, + ssl->verify_data_len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching renegotiation info" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + } + else +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + { + if( len != 1 || buf[0] != 0x0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-zero length renegotiation info" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; + } + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + +/* + * Status of the implementation of signature-algorithms extension: + * + * Currently, we are only considering the signature-algorithm extension + * to pick a ciphersuite which allows us to send the ServerKeyExchange + * message with a signature-hash combination that the user allows. + * + * We do *not* check whether all certificates in our certificate + * chain are signed with an allowed signature-hash pair. + * This needs to be done at a later stage. + * + */ +static int ssl_parse_signature_algorithms_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + size_t sig_alg_list_size; + + const unsigned char *p; + const unsigned char *end = buf + len; + + mbedtls_md_type_t md_cur; + mbedtls_pk_type_t sig_cur; + + if ( len < 2 ) { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + sig_alg_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); + if( sig_alg_list_size + 2 != len || + sig_alg_list_size % 2 != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* Currently we only guarantee signing the ServerKeyExchange message according + * to the constraints specified in this extension (see above), so it suffices + * to remember only one suitable hash for each possible signature algorithm. + * + * This will change when we also consider certificate signatures, + * in which case we will need to remember the whole signature-hash + * pair list from the extension. + */ + + for( p = buf + 2; p < end; p += 2 ) + { + /* Silently ignore unknown signature or hash algorithms. */ + + if( ( sig_cur = mbedtls_ssl_pk_alg_from_sig( p[1] ) ) == MBEDTLS_PK_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext" + " unknown sig alg encoding %d", p[1] ) ); + continue; + } + + /* Check if we support the hash the user proposes */ + md_cur = mbedtls_ssl_md_alg_from_hash( p[0] ); + if( md_cur == MBEDTLS_MD_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext:" + " unknown hash alg encoding %d", p[0] ) ); + continue; + } + + if( mbedtls_ssl_check_sig_hash( ssl, md_cur ) == 0 ) + { + mbedtls_ssl_sig_hash_set_add( &ssl->handshake->hash_algs, sig_cur, md_cur ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext:" + " match sig %d and hash %d", + sig_cur, md_cur ) ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext: " + "hash alg %d not supported", md_cur ) ); + } + } + + return( 0 ); +} +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static int ssl_parse_supported_elliptic_curves( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + size_t list_size, our_size; + const unsigned char *p; + const mbedtls_ecp_curve_info *curve_info, **curves; + + if ( len < 2 ) { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); + if( list_size + 2 != len || + list_size % 2 != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* Should never happen unless client duplicates the extension */ + if( ssl->handshake->curves != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* Don't allow our peer to make us allocate too much memory, + * and leave room for a final 0 */ + our_size = list_size / 2 + 1; + if( our_size > MBEDTLS_ECP_DP_MAX ) + our_size = MBEDTLS_ECP_DP_MAX; + + if( ( curves = mbedtls_calloc( our_size, sizeof( *curves ) ) ) == NULL ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + ssl->handshake->curves = curves; + + p = buf + 2; + while( list_size > 0 && our_size > 1 ) + { + curve_info = mbedtls_ecp_curve_info_from_tls_id( ( p[0] << 8 ) | p[1] ); + + if( curve_info != NULL ) + { + *curves++ = curve_info; + our_size--; + } + + list_size -= 2; + p += 2; + } + + return( 0 ); +} + +static int ssl_parse_supported_point_formats( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + size_t list_size; + const unsigned char *p; + + if( len == 0 || (size_t)( buf[0] + 1 ) != len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + list_size = buf[0]; + + p = buf + 1; + while( list_size > 0 ) + { + if( p[0] == MBEDTLS_ECP_PF_UNCOMPRESSED || + p[0] == MBEDTLS_ECP_PF_COMPRESSED ) + { +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) + ssl->handshake->ecdh_ctx.point_format = p[0]; +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + ssl->handshake->ecjpake_ctx.point_format = p[0]; +#endif + MBEDTLS_SSL_DEBUG_MSG( 4, ( "point format selected: %d", p[0] ) ); + return( 0 ); + } + + list_size--; + p++; + } + + return( 0 ); +} +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || + MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip ecjpake kkpp extension" ) ); + return( 0 ); + } + + if( ( ret = mbedtls_ecjpake_read_round_one( &ssl->handshake->ecjpake_ctx, + buf, len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_one", ret ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( ret ); + } + + /* Only mark the extension as OK when we're sure it is */ + ssl->handshake->cli_exts |= MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK; + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +static int ssl_parse_max_fragment_length_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( len != 1 || buf[0] >= MBEDTLS_SSL_MAX_FRAG_LEN_INVALID ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ssl->session_negotiate->mfl_code = buf[0]; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) +static int ssl_parse_cid_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + size_t peer_cid_len; + + /* CID extension only makes sense in DTLS */ + if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* + * Quoting draft-ietf-tls-dtls-connection-id-05 + * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05 + * + * struct { + * opaque cid<0..2^8-1>; + * } ConnectionId; + */ + + if( len < 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + peer_cid_len = *buf++; + len--; + + if( len != peer_cid_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* Ignore CID if the user has disabled its use. */ + if( ssl->negotiate_cid == MBEDTLS_SSL_CID_DISABLED ) + { + /* Leave ssl->handshake->cid_in_use in its default + * value of MBEDTLS_SSL_CID_DISABLED. */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Client sent CID extension, but CID disabled" ) ); + return( 0 ); + } + + if( peer_cid_len > MBEDTLS_SSL_CID_OUT_LEN_MAX ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ssl->handshake->cid_in_use = MBEDTLS_SSL_CID_ENABLED; + ssl->handshake->peer_cid_len = (uint8_t) peer_cid_len; + memcpy( ssl->handshake->peer_cid, buf, peer_cid_len ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Use of CID extension negotiated" ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "Client CID", buf, peer_cid_len ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) +static int ssl_parse_truncated_hmac_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ((void) buf); + + if( ssl->conf->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_ENABLED ) + ssl->session_negotiate->trunc_hmac = MBEDTLS_SSL_TRUNC_HMAC_ENABLED; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +static int ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ((void) buf); + + if( ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED && + ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 ) + { + ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED; + } + + return( 0 ); +} +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +static int ssl_parse_extended_ms_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ((void) buf); + + if( ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED && + ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 ) + { + ssl->handshake->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED; + } + + return( 0 ); +} +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +static int ssl_parse_session_ticket_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ssl_session session; + + mbedtls_ssl_session_init( &session ); + + if( ssl->conf->f_ticket_parse == NULL || + ssl->conf->f_ticket_write == NULL ) + { + return( 0 ); + } + + /* Remember the client asked us to send a new ticket */ + ssl->handshake->new_session_ticket = 1; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket length: %d", len ) ); + + if( len == 0 ) + return( 0 ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket rejected: renegotiating" ) ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + /* + * Failures are ok: just ignore the ticket and proceed. + */ + if( ( ret = ssl->conf->f_ticket_parse( ssl->conf->p_ticket, &session, + buf, len ) ) != 0 ) + { + mbedtls_ssl_session_free( &session ); + + if( ret == MBEDTLS_ERR_SSL_INVALID_MAC ) + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket is not authentic" ) ); + else if( ret == MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED ) + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket is expired" ) ); + else + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_ticket_parse", ret ); + + return( 0 ); + } + + /* + * Keep the session ID sent by the client, since we MUST send it back to + * inform them we're accepting the ticket (RFC 5077 section 3.4) + */ + session.id_len = ssl->session_negotiate->id_len; + memcpy( &session.id, ssl->session_negotiate->id, session.id_len ); + + mbedtls_ssl_session_free( ssl->session_negotiate ); + memcpy( ssl->session_negotiate, &session, sizeof( mbedtls_ssl_session ) ); + + /* Zeroize instead of free as we copied the content */ + mbedtls_platform_zeroize( &session, sizeof( mbedtls_ssl_session ) ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "session successfully restored from ticket" ) ); + + ssl->handshake->resume = 1; + + /* Don't send a new ticket after all, this one is OK */ + ssl->handshake->new_session_ticket = 0; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_SSL_ALPN) +static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + size_t list_len, cur_len, ours_len; + const unsigned char *theirs, *start, *end; + const char **ours; + + /* If ALPN not configured, just ignore the extension */ + if( ssl->conf->alpn_list == NULL ) + return( 0 ); + + /* + * opaque ProtocolName<1..2^8-1>; + * + * struct { + * ProtocolName protocol_name_list<2..2^16-1> + * } ProtocolNameList; + */ + + /* Min length is 2 (list_len) + 1 (name_len) + 1 (name) */ + if( len < 4 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + list_len = ( buf[0] << 8 ) | buf[1]; + if( list_len != len - 2 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* + * Validate peer's list (lengths) + */ + start = buf + 2; + end = buf + len; + for( theirs = start; theirs != end; theirs += cur_len ) + { + cur_len = *theirs++; + + /* Current identifier must fit in list */ + if( cur_len > (size_t)( end - theirs ) ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* Empty strings MUST NOT be included */ + if( cur_len == 0 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + } + + /* + * Use our order of preference + */ + for( ours = ssl->conf->alpn_list; *ours != NULL; ours++ ) + { + ours_len = strlen( *ours ); + for( theirs = start; theirs != end; theirs += cur_len ) + { + cur_len = *theirs++; + + if( cur_len == ours_len && + memcmp( theirs, *ours, cur_len ) == 0 ) + { + ssl->alpn_chosen = *ours; + return( 0 ); + } + } + } + + /* If we get there, no match was found */ + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); +} +#endif /* MBEDTLS_SSL_ALPN */ + +#if defined(MBEDTLS_SSL_DTLS_SRTP) +static int ssl_parse_use_srtp_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + mbedtls_ssl_srtp_profile client_protection = MBEDTLS_TLS_SRTP_UNSET; + size_t i,j; + size_t profile_length; + uint16_t mki_length; + /*! 2 bytes for profile length and 1 byte for mki len */ + const size_t size_of_lengths = 3; + + /* If use_srtp is not configured, just ignore the extension */ + if( ( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ) || + ( ssl->conf->dtls_srtp_profile_list == NULL ) || + ( ssl->conf->dtls_srtp_profile_list_len == 0 ) ) + { + return( 0 ); + } + + /* RFC5764 section 4.1.1 + * uint8 SRTPProtectionProfile[2]; + * + * struct { + * SRTPProtectionProfiles SRTPProtectionProfiles; + * opaque srtp_mki<0..255>; + * } UseSRTPData; + + * SRTPProtectionProfile SRTPProtectionProfiles<2..2^16-1>; + */ + + /* + * Min length is 5: at least one protection profile(2 bytes) + * and length(2 bytes) + srtp_mki length(1 byte) + * Check here that we have at least 2 bytes of protection profiles length + * and one of srtp_mki length + */ + if( len < size_of_lengths ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ssl->dtls_srtp_info.chosen_dtls_srtp_profile = MBEDTLS_TLS_SRTP_UNSET; + + /* first 2 bytes are protection profile length(in bytes) */ + profile_length = ( buf[0] << 8 ) | buf[1]; + buf += 2; + + /* The profile length cannot be bigger than input buffer size - lengths fields */ + if( profile_length > len - size_of_lengths || + profile_length % 2 != 0 ) /* profiles are 2 bytes long, so the length must be even */ + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + /* + * parse the extension list values are defined in + * http://www.iana.org/assignments/srtp-protection/srtp-protection.xhtml + */ + for( j = 0; j < profile_length; j += 2 ) + { + uint16_t protection_profile_value = buf[j] << 8 | buf[j + 1]; + client_protection = mbedtls_ssl_check_srtp_profile_value( protection_profile_value ); + + if( client_protection != MBEDTLS_TLS_SRTP_UNSET ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found srtp profile: %s", + mbedtls_ssl_get_srtp_profile_as_string( + client_protection ) ) ); + } + else + { + continue; + } + /* check if suggested profile is in our list */ + for( i = 0; i < ssl->conf->dtls_srtp_profile_list_len; i++) + { + if( client_protection == ssl->conf->dtls_srtp_profile_list[i] ) + { + ssl->dtls_srtp_info.chosen_dtls_srtp_profile = ssl->conf->dtls_srtp_profile_list[i]; + MBEDTLS_SSL_DEBUG_MSG( 3, ( "selected srtp profile: %s", + mbedtls_ssl_get_srtp_profile_as_string( + client_protection ) ) ); + break; + } + } + if( ssl->dtls_srtp_info.chosen_dtls_srtp_profile != MBEDTLS_TLS_SRTP_UNSET ) + break; + } + buf += profile_length; /* buf points to the mki length */ + mki_length = *buf; + buf++; + + if( mki_length > MBEDTLS_TLS_SRTP_MAX_MKI_LENGTH || + mki_length + profile_length + size_of_lengths != len ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* Parse the mki only if present and mki is supported locally */ + if( ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED && + mki_length > 0 ) + { + ssl->dtls_srtp_info.mki_len = mki_length; + + memcpy( ssl->dtls_srtp_info.mki_value, buf, mki_length ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "using mki", ssl->dtls_srtp_info.mki_value, + ssl->dtls_srtp_info.mki_len ); + } + + return( 0 ); +} +#endif /* MBEDTLS_SSL_DTLS_SRTP */ + +/* + * Auxiliary functions for ServerHello parsing and related actions + */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/* + * Return 0 if the given key uses one of the acceptable curves, -1 otherwise + */ +#if defined(MBEDTLS_ECDSA_C) +static int ssl_check_key_curve( mbedtls_pk_context *pk, + const mbedtls_ecp_curve_info **curves ) +{ + const mbedtls_ecp_curve_info **crv = curves; + mbedtls_ecp_group_id grp_id = mbedtls_pk_ec( *pk )->grp.id; + + while( *crv != NULL ) + { + if( (*crv)->grp_id == grp_id ) + return( 0 ); + crv++; + } + + return( -1 ); +} +#endif /* MBEDTLS_ECDSA_C */ + +/* + * Try picking a certificate for this ciphersuite, + * return 0 on success and -1 on failure. + */ +static int ssl_pick_cert( mbedtls_ssl_context *ssl, + const mbedtls_ssl_ciphersuite_t * ciphersuite_info ) +{ + mbedtls_ssl_key_cert *cur, *list, *fallback = NULL; + mbedtls_pk_type_t pk_alg = + mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ); + uint32_t flags; + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if( ssl->handshake->sni_key_cert != NULL ) + list = ssl->handshake->sni_key_cert; + else +#endif + list = ssl->conf->key_cert; + + if( pk_alg == MBEDTLS_PK_NONE ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite requires certificate" ) ); + + if( list == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server has no certificate" ) ); + return( -1 ); + } + + for( cur = list; cur != NULL; cur = cur->next ) + { + flags = 0; + MBEDTLS_SSL_DEBUG_CRT( 3, "candidate certificate chain, certificate", + cur->cert ); + + if( ! mbedtls_pk_can_do( &cur->cert->pk, pk_alg ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: key type" ) ); + continue; + } + + /* + * This avoids sending the client a cert it'll reject based on + * keyUsage or other extensions. + * + * It also allows the user to provision different certificates for + * different uses based on keyUsage, eg if they want to avoid signing + * and decrypting with the same RSA key. + */ + if( mbedtls_ssl_check_cert_usage( cur->cert, ciphersuite_info, + MBEDTLS_SSL_IS_SERVER, &flags ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: " + "(extended) key usage extension" ) ); + continue; + } + +#if defined(MBEDTLS_ECDSA_C) + if( pk_alg == MBEDTLS_PK_ECDSA && + ssl_check_key_curve( &cur->cert->pk, ssl->handshake->curves ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: elliptic curve" ) ); + continue; + } +#endif + + /* + * Try to select a SHA-1 certificate for pre-1.2 clients, but still + * present them a SHA-higher cert rather than failing if it's the only + * one we got that satisfies the other conditions. + */ + if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 && + cur->cert->sig_md != MBEDTLS_MD_SHA1 ) + { + if( fallback == NULL ) + fallback = cur; + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate not preferred: " + "sha-2 with pre-TLS 1.2 client" ) ); + continue; + } + } + + /* If we get there, we got a winner */ + break; + } + + if( cur == NULL ) + cur = fallback; + + /* Do not update ssl->handshake->key_cert unless there is a match */ + if( cur != NULL ) + { + ssl->handshake->key_cert = cur; + MBEDTLS_SSL_DEBUG_CRT( 3, "selected certificate chain, certificate", + ssl->handshake->key_cert->cert ); + return( 0 ); + } + + return( -1 ); +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +/* + * Check if a given ciphersuite is suitable for use with our config/keys/etc + * Sets ciphersuite_info only if the suite matches. + */ +static int ssl_ciphersuite_match( mbedtls_ssl_context *ssl, int suite_id, + const mbedtls_ssl_ciphersuite_t **ciphersuite_info ) +{ + const mbedtls_ssl_ciphersuite_t *suite_info; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + mbedtls_pk_type_t sig_type; +#endif + + suite_info = mbedtls_ssl_ciphersuite_from_id( suite_id ); + if( suite_info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "trying ciphersuite: %#04x (%s)", + suite_id, suite_info->name ) ); + + if( suite_info->min_minor_ver > ssl->minor_ver || + suite_info->max_minor_ver < ssl->minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: version" ) ); + return( 0 ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ( suite_info->flags & MBEDTLS_CIPHERSUITE_NODTLS ) ) + return( 0 ); +#endif + +#if defined(MBEDTLS_ARC4_C) + if( ssl->conf->arc4_disabled == MBEDTLS_SSL_ARC4_DISABLED && + suite_info->cipher == MBEDTLS_CIPHER_ARC4_128 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: rc4" ) ); + return( 0 ); + } +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE && + ( ssl->handshake->cli_exts & MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK ) == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: ecjpake " + "not configured or ext missing" ) ); + return( 0 ); + } +#endif + + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) + if( mbedtls_ssl_ciphersuite_uses_ec( suite_info ) && + ( ssl->handshake->curves == NULL || + ssl->handshake->curves[0] == NULL ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: " + "no common elliptic curve" ) ); + return( 0 ); + } +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) + /* If the ciphersuite requires a pre-shared key and we don't + * have one, skip it now rather than failing later */ + if( mbedtls_ssl_ciphersuite_uses_psk( suite_info ) && + ssl_conf_has_psk_or_cb( ssl->conf ) == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: no pre-shared key" ) ); + return( 0 ); + } +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + /* If the ciphersuite requires signing, check whether + * a suitable hash algorithm is present. */ + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + sig_type = mbedtls_ssl_get_ciphersuite_sig_alg( suite_info ); + if( sig_type != MBEDTLS_PK_NONE && + mbedtls_ssl_sig_hash_set_find( &ssl->handshake->hash_algs, sig_type ) == MBEDTLS_MD_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: no suitable hash algorithm " + "for signature algorithm %d", sig_type ) ); + return( 0 ); + } + } + +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + /* + * Final check: if ciphersuite requires us to have a + * certificate/key of a particular type: + * - select the appropriate certificate if we have one, or + * - try the next ciphersuite if we don't + * This must be done last since we modify the key_cert list. + */ + if( ssl_pick_cert( ssl, suite_info ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: " + "no suitable certificate" ) ); + return( 0 ); + } +#endif + + *ciphersuite_info = suite_info; + return( 0 ); +} + +#if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) +static int ssl_parse_client_hello_v2( mbedtls_ssl_context *ssl ) +{ + int ret, got_common_suite; + unsigned int i, j; + size_t n; + unsigned int ciph_len, sess_len, chal_len; + unsigned char *buf, *p; + const int *ciphersuites; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client hello v2" ) ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "client hello v2 illegal for renegotiation" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + buf = ssl->in_hdr; + + MBEDTLS_SSL_DEBUG_BUF( 4, "record header", buf, 5 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v2, message type: %d", + buf[2] ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v2, message len.: %d", + ( ( buf[0] & 0x7F ) << 8 ) | buf[1] ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v2, max. version: [%d:%d]", + buf[3], buf[4] ) ); + + /* + * SSLv2 Client Hello + * + * Record layer: + * 0 . 1 message length + * + * SSL layer: + * 2 . 2 message type + * 3 . 4 protocol version + */ + if( buf[2] != MBEDTLS_SSL_HS_CLIENT_HELLO || + buf[3] != MBEDTLS_SSL_MAJOR_VERSION_3 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + n = ( ( buf[0] << 8 ) | buf[1] ) & 0x7FFF; + + if( n < 17 || n > 512 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ssl->major_ver = MBEDTLS_SSL_MAJOR_VERSION_3; + ssl->minor_ver = ( buf[4] <= ssl->conf->max_minor_ver ) + ? buf[4] : ssl->conf->max_minor_ver; + + if( ssl->minor_ver < ssl->conf->min_minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "client only supports ssl smaller than minimum" + " [%d:%d] < [%d:%d]", + ssl->major_ver, ssl->minor_ver, + ssl->conf->min_major_ver, ssl->conf->min_minor_ver ) ); + + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); + return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION ); + } + + ssl->handshake->max_major_ver = buf[3]; + ssl->handshake->max_minor_ver = buf[4]; + + if( ( ret = mbedtls_ssl_fetch_input( ssl, 2 + n ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); + return( ret ); + } + + ssl->handshake->update_checksum( ssl, buf + 2, n ); + + buf = ssl->in_msg; + n = ssl->in_left - 5; + + /* + * 0 . 1 ciphersuitelist length + * 2 . 3 session id length + * 4 . 5 challenge length + * 6 . .. ciphersuitelist + * .. . .. session id + * .. . .. challenge + */ + MBEDTLS_SSL_DEBUG_BUF( 4, "record contents", buf, n ); + + ciph_len = ( buf[0] << 8 ) | buf[1]; + sess_len = ( buf[2] << 8 ) | buf[3]; + chal_len = ( buf[4] << 8 ) | buf[5]; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciph_len: %d, sess_len: %d, chal_len: %d", + ciph_len, sess_len, chal_len ) ); + + /* + * Make sure each parameter length is valid + */ + if( ciph_len < 3 || ( ciph_len % 3 ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + if( sess_len > 32 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + if( chal_len < 8 || chal_len > 32 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + if( n != 6 + ciph_len + sess_len + chal_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, ciphersuitelist", + buf + 6, ciph_len ); + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, session id", + buf + 6 + ciph_len, sess_len ); + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, challenge", + buf + 6 + ciph_len + sess_len, chal_len ); + + p = buf + 6 + ciph_len; + ssl->session_negotiate->id_len = sess_len; + memset( ssl->session_negotiate->id, 0, + sizeof( ssl->session_negotiate->id ) ); + memcpy( ssl->session_negotiate->id, p, ssl->session_negotiate->id_len ); + + p += sess_len; + memset( ssl->handshake->randbytes, 0, 64 ); + memcpy( ssl->handshake->randbytes + 32 - chal_len, p, chal_len ); + + /* + * Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV + */ + for( i = 0, p = buf + 6; i < ciph_len; i += 3, p += 3 ) + { + if( p[0] == 0 && p[1] == 0 && p[2] == MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "received TLS_EMPTY_RENEGOTIATION_INFO " ) ); +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "received RENEGOTIATION SCSV " + "during renegotiation" ) ); + + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; + break; + } + } + +#if defined(MBEDTLS_SSL_FALLBACK_SCSV) + for( i = 0, p = buf + 6; i < ciph_len; i += 3, p += 3 ) + { + if( p[0] == 0 && + p[1] == (unsigned char)( ( MBEDTLS_SSL_FALLBACK_SCSV_VALUE >> 8 ) & 0xff ) && + p[2] == (unsigned char)( ( MBEDTLS_SSL_FALLBACK_SCSV_VALUE ) & 0xff ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "received FALLBACK_SCSV" ) ); + + if( ssl->minor_ver < ssl->conf->max_minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "inapropriate fallback" ) ); + + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK ); + + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + break; + } + } +#endif /* MBEDTLS_SSL_FALLBACK_SCSV */ + + got_common_suite = 0; + ciphersuites = ssl->conf->ciphersuite_list[ssl->minor_ver]; + ciphersuite_info = NULL; +#if defined(MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE) + for( j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3 ) + for( i = 0; ciphersuites[i] != 0; i++ ) +#else + for( i = 0; ciphersuites[i] != 0; i++ ) + for( j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3 ) +#endif + { + if( p[0] != 0 || + p[1] != ( ( ciphersuites[i] >> 8 ) & 0xFF ) || + p[2] != ( ( ciphersuites[i] ) & 0xFF ) ) + continue; + + got_common_suite = 1; + + if( ( ret = ssl_ciphersuite_match( ssl, ciphersuites[i], + &ciphersuite_info ) ) != 0 ) + return( ret ); + + if( ciphersuite_info != NULL ) + goto have_ciphersuite_v2; + } + + if( got_common_suite ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got ciphersuites in common, " + "but none of them usable" ) ); + return( MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no ciphersuites in common" ) ); + return( MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN ); + } + +have_ciphersuite_v2: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "selected ciphersuite: %s", ciphersuite_info->name ) ); + + ssl->session_negotiate->ciphersuite = ciphersuites[i]; + ssl->handshake->ciphersuite_info = ciphersuite_info; + + /* + * SSLv2 Client Hello relevant renegotiation security checks + */ + if( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ssl->in_left = 0; + ssl->state++; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse client hello v2" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO */ + +/* This function doesn't alert on errors that happen early during + ClientHello parsing because they might indicate that the client is + not talking SSL/TLS at all and would not understand our alert. */ +static int ssl_parse_client_hello( mbedtls_ssl_context *ssl ) +{ + int ret, got_common_suite; + size_t i, j; + size_t ciph_offset, comp_offset, ext_offset; + size_t msg_len, ciph_len, sess_len, comp_len, ext_len; +#if defined(MBEDTLS_SSL_PROTO_DTLS) + size_t cookie_offset, cookie_len; +#endif + unsigned char *buf, *p, *ext; +#if defined(MBEDTLS_SSL_RENEGOTIATION) + int renegotiation_info_seen = 0; +#endif + int handshake_failure = 0; + const int *ciphersuites; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + int major, minor; + + /* If there is no signature-algorithm extension present, + * we need to fall back to the default values for allowed + * signature-hash pairs. */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + int sig_hash_alg_ext_present = 0; +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client hello" ) ); + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +read_record_header: +#endif + /* + * If renegotiating, then the input was read with mbedtls_ssl_read_record(), + * otherwise read it ourselves manually in order to support SSLv2 + * ClientHello, which doesn't use the same record layer format. + */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE ) +#endif + { + if( ( ret = mbedtls_ssl_fetch_input( ssl, 5 ) ) != 0 ) + { + /* No alert on a read error. */ + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); + return( ret ); + } + } + + buf = ssl->in_hdr; + +#if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_STREAM ) +#endif + if( ( buf[0] & 0x80 ) != 0 ) + return( ssl_parse_client_hello_v2( ssl ) ); +#endif + + MBEDTLS_SSL_DEBUG_BUF( 4, "record header", buf, mbedtls_ssl_in_hdr_len( ssl ) ); + + /* + * SSLv3/TLS Client Hello + * + * Record layer: + * 0 . 0 message type + * 1 . 2 protocol version + * 3 . 11 DTLS: epoch + record sequence number + * 3 . 4 message length + */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, message type: %d", + buf[0] ) ); + + if( buf[0] != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, message len.: %d", + ( ssl->in_len[0] << 8 ) | ssl->in_len[1] ) ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, protocol version: [%d:%d]", + buf[1], buf[2] ) ); + + mbedtls_ssl_read_version( &major, &minor, ssl->conf->transport, buf + 1 ); + + /* According to RFC 5246 Appendix E.1, the version here is typically + * "{03,00}, the lowest version number supported by the client, [or] the + * value of ClientHello.client_version", so the only meaningful check here + * is the major version shouldn't be less than 3 */ + if( major < MBEDTLS_SSL_MAJOR_VERSION_3 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* For DTLS if this is the initial handshake, remember the client sequence + * number to use it in our next message (RFC 6347 4.2.1) */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM +#if defined(MBEDTLS_SSL_RENEGOTIATION) + && ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE +#endif + ) + { + /* Epoch should be 0 for initial handshakes */ + if( ssl->in_ctr[0] != 0 || ssl->in_ctr[1] != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + memcpy( ssl->cur_out_ctr + 2, ssl->in_ctr + 2, 6 ); + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + if( mbedtls_ssl_dtls_replay_check( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "replayed record, discarding" ) ); + ssl->next_record_offset = 0; + ssl->in_left = 0; + goto read_record_header; + } + + /* No MAC to check yet, so we can update right now */ + mbedtls_ssl_dtls_replay_update( ssl ); +#endif + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + msg_len = ( ssl->in_len[0] << 8 ) | ssl->in_len[1]; + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) + { + /* Set by mbedtls_ssl_read_record() */ + msg_len = ssl->in_hslen; + } + else +#endif + { + if( msg_len > MBEDTLS_SSL_IN_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + if( ( ret = mbedtls_ssl_fetch_input( ssl, + mbedtls_ssl_in_hdr_len( ssl ) + msg_len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); + return( ret ); + } + + /* Done reading this record, get ready for the next one */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + ssl->next_record_offset = msg_len + mbedtls_ssl_in_hdr_len( ssl ); + else +#endif + ssl->in_left = 0; + } + + buf = ssl->in_msg; + + MBEDTLS_SSL_DEBUG_BUF( 4, "record contents", buf, msg_len ); + + ssl->handshake->update_checksum( ssl, buf, msg_len ); + + /* + * Handshake layer: + * 0 . 0 handshake type + * 1 . 3 handshake length + * 4 . 5 DTLS only: message seqence number + * 6 . 8 DTLS only: fragment offset + * 9 . 11 DTLS only: fragment length + */ + if( msg_len < mbedtls_ssl_hs_hdr_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, handshake type: %d", buf[0] ) ); + + if( buf[0] != MBEDTLS_SSL_HS_CLIENT_HELLO ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, handshake len.: %d", + ( buf[1] << 16 ) | ( buf[2] << 8 ) | buf[3] ) ); + + /* We don't support fragmentation of ClientHello (yet?) */ + if( buf[1] != 0 || + msg_len != mbedtls_ssl_hs_hdr_len( ssl ) + ( ( buf[2] << 8 ) | buf[3] ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + /* + * Copy the client's handshake message_seq on initial handshakes, + * check sequence number on renego. + */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + { + /* This couldn't be done in ssl_prepare_handshake_record() */ + unsigned int cli_msg_seq = ( ssl->in_msg[4] << 8 ) | + ssl->in_msg[5]; + + if( cli_msg_seq != ssl->handshake->in_msg_seq ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message_seq: " + "%d (expected %d)", cli_msg_seq, + ssl->handshake->in_msg_seq ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ssl->handshake->in_msg_seq++; + } + else +#endif + { + unsigned int cli_msg_seq = ( ssl->in_msg[4] << 8 ) | + ssl->in_msg[5]; + ssl->handshake->out_msg_seq = cli_msg_seq; + ssl->handshake->in_msg_seq = cli_msg_seq + 1; + } + + /* + * For now we don't support fragmentation, so make sure + * fragment_offset == 0 and fragment_length == length + */ + if( ssl->in_msg[6] != 0 || ssl->in_msg[7] != 0 || ssl->in_msg[8] != 0 || + memcmp( ssl->in_msg + 1, ssl->in_msg + 9, 3 ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "ClientHello fragmentation not supported" ) ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + buf += mbedtls_ssl_hs_hdr_len( ssl ); + msg_len -= mbedtls_ssl_hs_hdr_len( ssl ); + + /* + * ClientHello layer: + * 0 . 1 protocol version + * 2 . 33 random bytes (starting with 4 bytes of Unix time) + * 34 . 35 session id length (1 byte) + * 35 . 34+x session id + * 35+x . 35+x DTLS only: cookie length (1 byte) + * 36+x . .. DTLS only: cookie + * .. . .. ciphersuite list length (2 bytes) + * .. . .. ciphersuite list + * .. . .. compression alg. list length (1 byte) + * .. . .. compression alg. list + * .. . .. extensions length (2 bytes, optional) + * .. . .. extensions (optional) + */ + + /* + * Minimal length (with everything empty and extensions omitted) is + * 2 + 32 + 1 + 2 + 1 = 38 bytes. Check that first, so that we can + * read at least up to session id length without worrying. + */ + if( msg_len < 38 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* + * Check and save the protocol version + */ + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, version", buf, 2 ); + + mbedtls_ssl_read_version( &ssl->major_ver, &ssl->minor_ver, + ssl->conf->transport, buf ); + + ssl->handshake->max_major_ver = ssl->major_ver; + ssl->handshake->max_minor_ver = ssl->minor_ver; + + if( ssl->major_ver < ssl->conf->min_major_ver || + ssl->minor_ver < ssl->conf->min_minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "client only supports ssl smaller than minimum" + " [%d:%d] < [%d:%d]", + ssl->major_ver, ssl->minor_ver, + ssl->conf->min_major_ver, ssl->conf->min_minor_ver ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); + return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION ); + } + + if( ssl->major_ver > ssl->conf->max_major_ver ) + { + ssl->major_ver = ssl->conf->max_major_ver; + ssl->minor_ver = ssl->conf->max_minor_ver; + } + else if( ssl->minor_ver > ssl->conf->max_minor_ver ) + ssl->minor_ver = ssl->conf->max_minor_ver; + + /* + * Save client random (inc. Unix time) + */ + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, random bytes", buf + 2, 32 ); + + memcpy( ssl->handshake->randbytes, buf + 2, 32 ); + + /* + * Check the session ID length and save session ID + */ + sess_len = buf[34]; + + if( sess_len > sizeof( ssl->session_negotiate->id ) || + sess_len + 34 + 2 > msg_len ) /* 2 for cipherlist length field */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, session id", buf + 35, sess_len ); + + ssl->session_negotiate->id_len = sess_len; + memset( ssl->session_negotiate->id, 0, + sizeof( ssl->session_negotiate->id ) ); + memcpy( ssl->session_negotiate->id, buf + 35, + ssl->session_negotiate->id_len ); + + /* + * Check the cookie length and content + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + cookie_offset = 35 + sess_len; + cookie_len = buf[cookie_offset]; + + if( cookie_offset + 1 + cookie_len + 2 > msg_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, cookie", + buf + cookie_offset + 1, cookie_len ); + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) + if( ssl->conf->f_cookie_check != NULL +#if defined(MBEDTLS_SSL_RENEGOTIATION) + && ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE +#endif + ) + { + if( ssl->conf->f_cookie_check( ssl->conf->p_cookie, + buf + cookie_offset + 1, cookie_len, + ssl->cli_id, ssl->cli_id_len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "cookie verification failed" ) ); + ssl->handshake->verify_cookie_len = 1; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "cookie verification passed" ) ); + ssl->handshake->verify_cookie_len = 0; + } + } + else +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ + { + /* We know we didn't send a cookie, so it should be empty */ + if( cookie_len != 0 ) + { + /* This may be an attacker's probe, so don't send an alert */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "cookie verification skipped" ) ); + } + + /* + * Check the ciphersuitelist length (will be parsed later) + */ + ciph_offset = cookie_offset + 1 + cookie_len; + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + ciph_offset = 35 + sess_len; + + ciph_len = ( buf[ciph_offset + 0] << 8 ) + | ( buf[ciph_offset + 1] ); + + if( ciph_len < 2 || + ciph_len + 2 + ciph_offset + 1 > msg_len || /* 1 for comp. alg. len */ + ( ciph_len % 2 ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, ciphersuitelist", + buf + ciph_offset + 2, ciph_len ); + + /* + * Check the compression algorithms length and pick one + */ + comp_offset = ciph_offset + 2 + ciph_len; + + comp_len = buf[comp_offset]; + + if( comp_len < 1 || + comp_len > 16 || + comp_len + comp_offset + 1 > msg_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, compression", + buf + comp_offset + 1, comp_len ); + + ssl->session_negotiate->compression = MBEDTLS_SSL_COMPRESS_NULL; +#if defined(MBEDTLS_ZLIB_SUPPORT) + for( i = 0; i < comp_len; ++i ) + { + if( buf[comp_offset + 1 + i] == MBEDTLS_SSL_COMPRESS_DEFLATE ) + { + ssl->session_negotiate->compression = MBEDTLS_SSL_COMPRESS_DEFLATE; + break; + } + } +#endif + + /* See comments in ssl_write_client_hello() */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + ssl->session_negotiate->compression = MBEDTLS_SSL_COMPRESS_NULL; +#endif + + /* Do not parse the extensions if the protocol is SSLv3 */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ( ssl->major_ver != 3 ) || ( ssl->minor_ver != 0 ) ) + { +#endif + /* + * Check the extension length + */ + ext_offset = comp_offset + 1 + comp_len; + if( msg_len > ext_offset ) + { + if( msg_len < ext_offset + 2 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ext_len = ( buf[ext_offset + 0] << 8 ) + | ( buf[ext_offset + 1] ); + + if( ( ext_len > 0 && ext_len < 4 ) || + msg_len != ext_offset + 2 + ext_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + } + else + ext_len = 0; + + ext = buf + ext_offset + 2; + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello extensions", ext, ext_len ); + + while( ext_len != 0 ) + { + unsigned int ext_id; + unsigned int ext_size; + if ( ext_len < 4 ) { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + ext_id = ( ( ext[0] << 8 ) | ( ext[1] ) ); + ext_size = ( ( ext[2] << 8 ) | ( ext[3] ) ); + + if( ext_size + 4 > ext_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + switch( ext_id ) + { +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + case MBEDTLS_TLS_EXT_SERVERNAME: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found ServerName extension" ) ); + if( ssl->conf->f_sni == NULL ) + break; + + ret = ssl_parse_servername_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + + case MBEDTLS_TLS_EXT_RENEGOTIATION_INFO: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found renegotiation extension" ) ); +#if defined(MBEDTLS_SSL_RENEGOTIATION) + renegotiation_info_seen = 1; +#endif + + ret = ssl_parse_renegotiation_info( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + case MBEDTLS_TLS_EXT_SIG_ALG: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found signature_algorithms extension" ) ); + + ret = ssl_parse_signature_algorithms_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + + sig_hash_alg_ext_present = 1; + break; +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + case MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found supported elliptic curves extension" ) ); + + ret = ssl_parse_supported_elliptic_curves( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; + + case MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found supported point formats extension" ) ); + ssl->handshake->cli_exts |= MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT; + + ret = ssl_parse_supported_point_formats( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || + MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + case MBEDTLS_TLS_EXT_ECJPAKE_KKPP: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found ecjpake kkpp extension" ) ); + + ret = ssl_parse_ecjpake_kkpp( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + case MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found max fragment length extension" ) ); + + ret = ssl_parse_max_fragment_length_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + case MBEDTLS_TLS_EXT_TRUNCATED_HMAC: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found truncated hmac extension" ) ); + + ret = ssl_parse_truncated_hmac_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + case MBEDTLS_TLS_EXT_CID: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found CID extension" ) ); + + ret = ssl_parse_cid_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + case MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found encrypt then mac extension" ) ); + + ret = ssl_parse_encrypt_then_mac_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + case MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found extended master secret extension" ) ); + + ret = ssl_parse_extended_ms_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + case MBEDTLS_TLS_EXT_SESSION_TICKET: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found session ticket extension" ) ); + + ret = ssl_parse_session_ticket_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_SSL_ALPN) + case MBEDTLS_TLS_EXT_ALPN: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found alpn extension" ) ); + + ret = ssl_parse_alpn_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_SSL_DTLS_SRTP) + case MBEDTLS_TLS_EXT_USE_SRTP: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found use_srtp extension" ) ); + + ret = ssl_parse_use_srtp_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_DTLS_SRTP */ + + default: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "unknown extension found: %d (ignoring)", + ext_id ) ); + } + + ext_len -= 4 + ext_size; + ext += 4 + ext_size; + + if( ext_len > 0 && ext_len < 4 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + } +#if defined(MBEDTLS_SSL_PROTO_SSL3) + } +#endif + +#if defined(MBEDTLS_SSL_FALLBACK_SCSV) + for( i = 0, p = buf + ciph_offset + 2; i < ciph_len; i += 2, p += 2 ) + { + if( p[0] == (unsigned char)( ( MBEDTLS_SSL_FALLBACK_SCSV_VALUE >> 8 ) & 0xff ) && + p[1] == (unsigned char)( ( MBEDTLS_SSL_FALLBACK_SCSV_VALUE ) & 0xff ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "received FALLBACK_SCSV" ) ); + + if( ssl->minor_ver < ssl->conf->max_minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "inapropriate fallback" ) ); + + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK ); + + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + break; + } + } +#endif /* MBEDTLS_SSL_FALLBACK_SCSV */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + + /* + * Try to fall back to default hash SHA1 if the client + * hasn't provided any preferred signature-hash combinations. + */ + if( sig_hash_alg_ext_present == 0 ) + { + mbedtls_md_type_t md_default = MBEDTLS_MD_SHA1; + + if( mbedtls_ssl_check_sig_hash( ssl, md_default ) != 0 ) + md_default = MBEDTLS_MD_NONE; + + mbedtls_ssl_sig_hash_set_const_hash( &ssl->handshake->hash_algs, md_default ); + } + +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + + /* + * Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV + */ + for( i = 0, p = buf + ciph_offset + 2; i < ciph_len; i += 2, p += 2 ) + { + if( p[0] == 0 && p[1] == MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "received TLS_EMPTY_RENEGOTIATION_INFO " ) ); +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "received RENEGOTIATION SCSV " + "during renegotiation" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } +#endif + ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; + break; + } + } + + /* + * Renegotiation security checks + */ + if( ssl->secure_renegotiation != MBEDTLS_SSL_SECURE_RENEGOTIATION && + ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) ); + handshake_failure = 1; + } +#if defined(MBEDTLS_SSL_RENEGOTIATION) + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->secure_renegotiation == MBEDTLS_SSL_SECURE_RENEGOTIATION && + renegotiation_info_seen == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation_info extension missing (secure)" ) ); + handshake_failure = 1; + } + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation not allowed" ) ); + handshake_failure = 1; + } + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + renegotiation_info_seen == 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation_info extension present (legacy)" ) ); + handshake_failure = 1; + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + if( handshake_failure == 1 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* + * Search for a matching ciphersuite + * (At the end because we need information from the EC-based extensions + * and certificate from the SNI callback triggered by the SNI extension.) + */ + got_common_suite = 0; + ciphersuites = ssl->conf->ciphersuite_list[ssl->minor_ver]; + ciphersuite_info = NULL; +#if defined(MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE) + for( j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2 ) + for( i = 0; ciphersuites[i] != 0; i++ ) +#else + for( i = 0; ciphersuites[i] != 0; i++ ) + for( j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2 ) +#endif + { + if( p[0] != ( ( ciphersuites[i] >> 8 ) & 0xFF ) || + p[1] != ( ( ciphersuites[i] ) & 0xFF ) ) + continue; + + got_common_suite = 1; + + if( ( ret = ssl_ciphersuite_match( ssl, ciphersuites[i], + &ciphersuite_info ) ) != 0 ) + return( ret ); + + if( ciphersuite_info != NULL ) + goto have_ciphersuite; + } + + if( got_common_suite ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got ciphersuites in common, " + "but none of them usable" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no ciphersuites in common" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN ); + } + +have_ciphersuite: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "selected ciphersuite: %s", ciphersuite_info->name ) ); + + ssl->session_negotiate->ciphersuite = ciphersuites[i]; + ssl->handshake->ciphersuite_info = ciphersuite_info; + + ssl->state++; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + mbedtls_ssl_recv_flight_completed( ssl ); +#endif + + /* Debugging-only output for testsuite */ +#if defined(MBEDTLS_DEBUG_C) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + mbedtls_pk_type_t sig_alg = mbedtls_ssl_get_ciphersuite_sig_alg( ciphersuite_info ); + if( sig_alg != MBEDTLS_PK_NONE ) + { + mbedtls_md_type_t md_alg = mbedtls_ssl_sig_hash_set_find( &ssl->handshake->hash_algs, + sig_alg ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext: %d", + mbedtls_ssl_hash_from_md_alg( md_alg ) ) ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "no hash algorithm for signature algorithm " + "%d - should not happen", sig_alg ) ); + } + } +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse client hello" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) +static void ssl_write_truncated_hmac_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->session_negotiate->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_DISABLED ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding truncated hmac extension" ) ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_TRUNCATED_HMAC >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_TRUNCATED_HMAC ) & 0xFF ); + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; +} +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) +static void ssl_write_cid_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + size_t ext_len; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; + + *olen = 0; + + /* Skip writing the extension if we don't want to use it or if + * the client hasn't offered it. */ + if( ssl->handshake->cid_in_use == MBEDTLS_SSL_CID_DISABLED ) + return; + + /* ssl->own_cid_len is at most MBEDTLS_SSL_CID_IN_LEN_MAX + * which is at most 255, so the increment cannot overflow. */ + if( end < p || (size_t)( end - p ) < (unsigned)( ssl->own_cid_len + 5 ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding CID extension" ) ); + + /* + * Quoting draft-ietf-tls-dtls-connection-id-05 + * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05 + * + * struct { + * opaque cid<0..2^8-1>; + * } ConnectionId; + */ + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_CID >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_CID ) & 0xFF ); + ext_len = (size_t) ssl->own_cid_len + 1; + *p++ = (unsigned char)( ( ext_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( ext_len ) & 0xFF ); + + *p++ = (uint8_t) ssl->own_cid_len; + memcpy( p, ssl->own_cid, ssl->own_cid_len ); + + *olen = ssl->own_cid_len + 5; +} +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +static void ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + const mbedtls_ssl_ciphersuite_t *suite = NULL; + const mbedtls_cipher_info_t *cipher = NULL; + + if( ssl->session_negotiate->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED || + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + *olen = 0; + return; + } + + /* + * RFC 7366: "If a server receives an encrypt-then-MAC request extension + * from a client and then selects a stream or Authenticated Encryption + * with Associated Data (AEAD) ciphersuite, it MUST NOT send an + * encrypt-then-MAC response extension back to the client." + */ + if( ( suite = mbedtls_ssl_ciphersuite_from_id( + ssl->session_negotiate->ciphersuite ) ) == NULL || + ( cipher = mbedtls_cipher_info_from_type( suite->cipher ) ) == NULL || + cipher->mode != MBEDTLS_MODE_CBC ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding encrypt then mac extension" ) ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC ) & 0xFF ); + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; +} +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +static void ssl_write_extended_ms_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED || + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding extended master secret " + "extension" ) ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET ) & 0xFF ); + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; +} +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +static void ssl_write_session_ticket_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->handshake->new_session_ticket == 0 ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding session ticket extension" ) ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SESSION_TICKET >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SESSION_TICKET ) & 0xFF ); + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +static void ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->secure_renegotiation != MBEDTLS_SSL_SECURE_RENEGOTIATION ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, secure renegotiation extension" ) ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO ) & 0xFF ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) + { + *p++ = 0x00; + *p++ = ( ssl->verify_data_len * 2 + 1 ) & 0xFF; + *p++ = ssl->verify_data_len * 2 & 0xFF; + + memcpy( p, ssl->peer_verify_data, ssl->verify_data_len ); + p += ssl->verify_data_len; + memcpy( p, ssl->own_verify_data, ssl->verify_data_len ); + p += ssl->verify_data_len; + } + else +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + { + *p++ = 0x00; + *p++ = 0x01; + *p++ = 0x00; + } + + *olen = p - buf; +} + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +static void ssl_write_max_fragment_length_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->session_negotiate->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, max_fragment_length extension" ) ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH ) & 0xFF ); + + *p++ = 0x00; + *p++ = 1; + + *p++ = ssl->session_negotiate->mfl_code; + + *olen = 5; +} +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static void ssl_write_supported_point_formats_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + ((void) ssl); + + if( ( ssl->handshake->cli_exts & + MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT ) == 0 ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, supported_point_formats extension" ) ); + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS ) & 0xFF ); + + *p++ = 0x00; + *p++ = 2; + + *p++ = 1; + *p++ = MBEDTLS_ECP_PF_UNCOMPRESSED; + + *olen = 6; +} +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static void ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = buf; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; + size_t kkpp_len; + + *olen = 0; + + /* Skip costly computation if not needed */ + if( ssl->handshake->ciphersuite_info->key_exchange != + MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + return; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, ecjpake kkpp extension" ) ); + + if( end - p < 4 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ECJPAKE_KKPP >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ECJPAKE_KKPP ) & 0xFF ); + + ret = mbedtls_ecjpake_write_round_one( &ssl->handshake->ecjpake_ctx, + p + 2, end - p - 2, &kkpp_len, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1 , "mbedtls_ecjpake_write_round_one", ret ); + return; + } + + *p++ = (unsigned char)( ( kkpp_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( kkpp_len ) & 0xFF ); + + *olen = kkpp_len + 4; +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_ALPN ) +static void ssl_write_alpn_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, size_t *olen ) +{ + if( ssl->alpn_chosen == NULL ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding alpn extension" ) ); + + /* + * 0 . 1 ext identifier + * 2 . 3 ext length + * 4 . 5 protocol list length + * 6 . 6 protocol name length + * 7 . 7+n protocol name + */ + buf[0] = (unsigned char)( ( MBEDTLS_TLS_EXT_ALPN >> 8 ) & 0xFF ); + buf[1] = (unsigned char)( ( MBEDTLS_TLS_EXT_ALPN ) & 0xFF ); + + *olen = 7 + strlen( ssl->alpn_chosen ); + + buf[2] = (unsigned char)( ( ( *olen - 4 ) >> 8 ) & 0xFF ); + buf[3] = (unsigned char)( ( ( *olen - 4 ) ) & 0xFF ); + + buf[4] = (unsigned char)( ( ( *olen - 6 ) >> 8 ) & 0xFF ); + buf[5] = (unsigned char)( ( ( *olen - 6 ) ) & 0xFF ); + + buf[6] = (unsigned char)( ( ( *olen - 7 ) ) & 0xFF ); + + memcpy( buf + 7, ssl->alpn_chosen, *olen - 7 ); +} +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C */ + +#if defined(MBEDTLS_SSL_DTLS_SRTP ) && defined(MBEDTLS_SSL_PROTO_DTLS) +static void ssl_write_use_srtp_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + size_t mki_len = 0, ext_len = 0; + uint16_t profile_value = 0; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; + + *olen = 0; + + if( ( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ) || + ( ssl->dtls_srtp_info.chosen_dtls_srtp_profile == MBEDTLS_TLS_SRTP_UNSET ) ) + { + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding use_srtp extension" ) ); + + if( ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED ) + { + mki_len = ssl->dtls_srtp_info.mki_len; + } + + /* The extension total size is 9 bytes : + * - 2 bytes for the extension tag + * - 2 bytes for the total size + * - 2 bytes for the protection profile length + * - 2 bytes for the protection profile + * - 1 byte for the mki length + * + the actual mki length + * Check we have enough room in the output buffer */ + if( (size_t)( end - buf ) < mki_len + 9 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + + /* extension */ + buf[0] = (unsigned char)( ( MBEDTLS_TLS_EXT_USE_SRTP >> 8 ) & 0xFF ); + buf[1] = (unsigned char)( ( MBEDTLS_TLS_EXT_USE_SRTP ) & 0xFF ); + /* + * total length 5 and mki value: only one profile(2 bytes) + * and length(2 bytes) and srtp_mki ) + */ + ext_len = 5 + mki_len; + buf[2] = (unsigned char)( ( ext_len >> 8 ) & 0xFF ); + buf[3] = (unsigned char)( ext_len & 0xFF ); + + /* protection profile length: 2 */ + buf[4] = 0x00; + buf[5] = 0x02; + profile_value = mbedtls_ssl_check_srtp_profile_value( + ssl->dtls_srtp_info.chosen_dtls_srtp_profile ); + if( profile_value != MBEDTLS_TLS_SRTP_UNSET ) + { + buf[6] = (unsigned char)( ( profile_value >> 8 ) & 0xFF ); + buf[7] = (unsigned char)( profile_value & 0xFF ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "use_srtp extension invalid profile" ) ); + return; + } + + buf[8] = mki_len & 0xFF; + memcpy( &buf[9], ssl->dtls_srtp_info.mki_value, mki_len ); + + *olen = 9 + mki_len; +} +#endif /* MBEDTLS_SSL_DTLS_SRTP */ + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) +static int ssl_write_hello_verify_request( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = ssl->out_msg + 4; + unsigned char *cookie_len_byte; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write hello verify request" ) ); + + /* + * struct { + * ProtocolVersion server_version; + * opaque cookie<0..2^8-1>; + * } HelloVerifyRequest; + */ + + /* The RFC is not clear on this point, but sending the actual negotiated + * version looks like the most interoperable thing to do. */ + mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, + ssl->conf->transport, p ); + MBEDTLS_SSL_DEBUG_BUF( 3, "server version", p, 2 ); + p += 2; + + /* If we get here, f_cookie_check is not null */ + if( ssl->conf->f_cookie_write == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "inconsistent cookie callbacks" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* Skip length byte until we know the length */ + cookie_len_byte = p++; + + if( ( ret = ssl->conf->f_cookie_write( ssl->conf->p_cookie, + &p, ssl->out_buf + MBEDTLS_SSL_OUT_BUFFER_LEN, + ssl->cli_id, ssl->cli_id_len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "f_cookie_write", ret ); + return( ret ); + } + + *cookie_len_byte = (unsigned char)( p - ( cookie_len_byte + 1 ) ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "cookie sent", cookie_len_byte + 1, *cookie_len_byte ); + + ssl->out_msglen = p - ssl->out_msg; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST; + + ssl->state = MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT; + + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret ); + return( ret ); + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write hello verify request" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ + +static int ssl_write_server_hello( mbedtls_ssl_context *ssl ) +{ +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t t; +#endif + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t olen, ext_len = 0, n; + unsigned char *buf, *p; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server hello" ) ); + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake->verify_cookie_len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "client hello was not authenticated" ) ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello" ) ); + + return( ssl_write_hello_verify_request( ssl ) ); + } +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ + + if( ssl->conf->f_rng == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "no RNG provided") ); + return( MBEDTLS_ERR_SSL_NO_RNG ); + } + + /* + * 0 . 0 handshake type + * 1 . 3 handshake length + * 4 . 5 protocol version + * 6 . 9 UNIX time() + * 10 . 37 random bytes + */ + buf = ssl->out_msg; + p = buf + 4; + + mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, + ssl->conf->transport, p ); + p += 2; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen version: [%d:%d]", + buf[4], buf[5] ) ); + +#if defined(MBEDTLS_HAVE_TIME) + t = mbedtls_time( NULL ); + *p++ = (unsigned char)( t >> 24 ); + *p++ = (unsigned char)( t >> 16 ); + *p++ = (unsigned char)( t >> 8 ); + *p++ = (unsigned char)( t ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu", t ) ); +#else + if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 4 ) ) != 0 ) + return( ret ); + + p += 4; +#endif /* MBEDTLS_HAVE_TIME */ + + if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 28 ) ) != 0 ) + return( ret ); + + p += 28; + + memcpy( ssl->handshake->randbytes + 32, buf + 6, 32 ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, random bytes", buf + 6, 32 ); + + /* + * Resume is 0 by default, see ssl_handshake_init(). + * It may be already set to 1 by ssl_parse_session_ticket_ext(). + * If not, try looking up session ID in our cache. + */ + if( ssl->handshake->resume == 0 && +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE && +#endif + ssl->session_negotiate->id_len != 0 && + ssl->conf->f_get_cache != NULL && + ssl->conf->f_get_cache( ssl->conf->p_cache, ssl->session_negotiate ) == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "session successfully restored from cache" ) ); + ssl->handshake->resume = 1; + } + + if( ssl->handshake->resume == 0 ) + { + /* + * New session, create a new session id, + * unless we're about to issue a session ticket + */ + ssl->state++; + +#if defined(MBEDTLS_HAVE_TIME) + ssl->session_negotiate->start = mbedtls_time( NULL ); +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + if( ssl->handshake->new_session_ticket != 0 ) + { + ssl->session_negotiate->id_len = n = 0; + memset( ssl->session_negotiate->id, 0, 32 ); + } + else +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + { + ssl->session_negotiate->id_len = n = 32; + if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, ssl->session_negotiate->id, + n ) ) != 0 ) + return( ret ); + } + } + else + { + /* + * Resuming a session + */ + n = ssl->session_negotiate->id_len; + ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC; + + if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); + return( ret ); + } + } + + /* + * 38 . 38 session id length + * 39 . 38+n session id + * 39+n . 40+n chosen ciphersuite + * 41+n . 41+n chosen compression alg. + * 42+n . 43+n extensions length + * 44+n . 43+n+m extensions + */ + *p++ = (unsigned char) ssl->session_negotiate->id_len; + memcpy( p, ssl->session_negotiate->id, ssl->session_negotiate->id_len ); + p += ssl->session_negotiate->id_len; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %d", n ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, session id", buf + 39, n ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "%s session has been resumed", + ssl->handshake->resume ? "a" : "no" ) ); + + *p++ = (unsigned char)( ssl->session_negotiate->ciphersuite >> 8 ); + *p++ = (unsigned char)( ssl->session_negotiate->ciphersuite ); + *p++ = (unsigned char)( ssl->session_negotiate->compression ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %s", + mbedtls_ssl_get_ciphersuite_name( ssl->session_negotiate->ciphersuite ) ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: 0x%02X", + ssl->session_negotiate->compression ) ); + + /* Do not write the extensions if the protocol is SSLv3 */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ( ssl->major_ver != 3 ) || ( ssl->minor_ver != 0 ) ) + { +#endif + + /* + * First write extensions, then the total length + */ + ssl_write_renegotiation_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + ssl_write_max_fragment_length_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + ssl_write_truncated_hmac_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + ssl_write_cid_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + ssl_write_encrypt_then_mac_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + ssl_write_extended_ms_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + ssl_write_session_ticket_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if ( mbedtls_ssl_ciphersuite_uses_ec( + mbedtls_ssl_ciphersuite_from_id( ssl->session_negotiate->ciphersuite ) ) ) + { + ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; + } +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + ssl_write_ecjpake_kkpp_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_ALPN) + ssl_write_alpn_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_DTLS_SRTP) + ssl_write_use_srtp_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, total extension length: %d", ext_len ) ); + + if( ext_len > 0 ) + { + *p++ = (unsigned char)( ( ext_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( ext_len ) & 0xFF ); + p += ext_len; + } + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + } +#endif + + ssl->out_msglen = p - buf; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_HELLO; + + ret = mbedtls_ssl_write_handshake_msg( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello" ) ); + + return( ret ); +} + +#if !defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) +static int ssl_write_certificate_request( mbedtls_ssl_context *ssl ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate request" ) ); + + if( !mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate request" ) ); + ssl->state++; + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); +} +#else /* !MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ +static int ssl_write_certificate_request( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + uint16_t dn_size, total_dn_size; /* excluding length bytes */ + size_t ct_len, sa_len; /* including length bytes */ + unsigned char *buf, *p; + const unsigned char * const end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; + const mbedtls_x509_crt *crt; + int authmode; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate request" ) ); + + ssl->state++; + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if( ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET ) + authmode = ssl->handshake->sni_authmode; + else +#endif + authmode = ssl->conf->authmode; + + if( !mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) || + authmode == MBEDTLS_SSL_VERIFY_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate request" ) ); + return( 0 ); + } + + /* + * 0 . 0 handshake type + * 1 . 3 handshake length + * 4 . 4 cert type count + * 5 .. m-1 cert types + * m .. m+1 sig alg length (TLS 1.2 only) + * m+1 .. n-1 SignatureAndHashAlgorithms (TLS 1.2 only) + * n .. n+1 length of all DNs + * n+2 .. n+3 length of DN 1 + * n+4 .. ... Distinguished Name #1 + * ... .. ... length of DN 2, etc. + */ + buf = ssl->out_msg; + p = buf + 4; + + /* + * Supported certificate types + * + * ClientCertificateType certificate_types<1..2^8-1>; + * enum { (255) } ClientCertificateType; + */ + ct_len = 0; + +#if defined(MBEDTLS_RSA_C) + p[1 + ct_len++] = MBEDTLS_SSL_CERT_TYPE_RSA_SIGN; +#endif +#if defined(MBEDTLS_ECDSA_C) + p[1 + ct_len++] = MBEDTLS_SSL_CERT_TYPE_ECDSA_SIGN; +#endif + + p[0] = (unsigned char) ct_len++; + p += ct_len; + + sa_len = 0; +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + /* + * Add signature_algorithms for verify (TLS 1.2) + * + * SignatureAndHashAlgorithm supported_signature_algorithms<2..2^16-2>; + * + * struct { + * HashAlgorithm hash; + * SignatureAlgorithm signature; + * } SignatureAndHashAlgorithm; + * + * enum { (255) } HashAlgorithm; + * enum { (255) } SignatureAlgorithm; + */ + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + const int *cur; + + /* + * Supported signature algorithms + */ + for( cur = ssl->conf->sig_hashes; *cur != MBEDTLS_MD_NONE; cur++ ) + { + unsigned char hash = mbedtls_ssl_hash_from_md_alg( *cur ); + + if( MBEDTLS_SSL_HASH_NONE == hash || mbedtls_ssl_set_calc_verify_md( ssl, hash ) ) + continue; + +#if defined(MBEDTLS_RSA_C) + p[2 + sa_len++] = hash; + p[2 + sa_len++] = MBEDTLS_SSL_SIG_RSA; +#endif +#if defined(MBEDTLS_ECDSA_C) + p[2 + sa_len++] = hash; + p[2 + sa_len++] = MBEDTLS_SSL_SIG_ECDSA; +#endif + } + + p[0] = (unsigned char)( sa_len >> 8 ); + p[1] = (unsigned char)( sa_len ); + sa_len += 2; + p += sa_len; + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + /* + * DistinguishedName certificate_authorities<0..2^16-1>; + * opaque DistinguishedName<1..2^16-1>; + */ + p += 2; + + total_dn_size = 0; + + if( ssl->conf->cert_req_ca_list == MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED ) + { + /* NOTE: If trusted certificates are provisioned + * via a CA callback (configured through + * `mbedtls_ssl_conf_ca_cb()`, then the + * CertificateRequest is currently left empty. */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if( ssl->handshake->sni_ca_chain != NULL ) + crt = ssl->handshake->sni_ca_chain; + else +#endif + crt = ssl->conf->ca_chain; + + while( crt != NULL && crt->version != 0 ) + { + /* It follows from RFC 5280 A.1 that this length + * can be represented in at most 11 bits. */ + dn_size = (uint16_t) crt->subject_raw.len; + + if( end < p || (size_t)( end - p ) < 2 + (size_t) dn_size ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "skipping CAs: buffer too short" ) ); + break; + } + + *p++ = (unsigned char)( dn_size >> 8 ); + *p++ = (unsigned char)( dn_size ); + memcpy( p, crt->subject_raw.p, dn_size ); + p += dn_size; + + MBEDTLS_SSL_DEBUG_BUF( 3, "requested DN", p - dn_size, dn_size ); + + total_dn_size += 2 + dn_size; + crt = crt->next; + } + } + + ssl->out_msglen = p - buf; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE_REQUEST; + ssl->out_msg[4 + ct_len + sa_len] = (unsigned char)( total_dn_size >> 8 ); + ssl->out_msg[5 + ct_len + sa_len] = (unsigned char)( total_dn_size ); + + ret = mbedtls_ssl_write_handshake_msg( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write certificate request" ) ); + + return( ret ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ! mbedtls_pk_can_do( mbedtls_ssl_own_key( ssl ), MBEDTLS_PK_ECKEY ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "server key not ECDH capable" ) ); + return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); + } + + if( ( ret = mbedtls_ecdh_get_params( &ssl->handshake->ecdh_ctx, + mbedtls_pk_ec( *mbedtls_ssl_own_key( ssl ) ), + MBEDTLS_ECDH_OURS ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_get_params" ), ret ); + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) && \ + defined(MBEDTLS_SSL_ASYNC_PRIVATE) +static int ssl_resume_server_key_exchange( mbedtls_ssl_context *ssl, + size_t *signature_len ) +{ + /* Append the signature to ssl->out_msg, leaving 2 bytes for the + * signature length which will be added in ssl_write_server_key_exchange + * after the call to ssl_prepare_server_key_exchange. + * ssl_write_server_key_exchange also takes care of incrementing + * ssl->out_msglen. */ + unsigned char *sig_start = ssl->out_msg + ssl->out_msglen + 2; + size_t sig_max_len = ( ssl->out_buf + MBEDTLS_SSL_OUT_CONTENT_LEN + - sig_start ); + int ret = ssl->conf->f_async_resume( ssl, + sig_start, signature_len, sig_max_len ); + if( ret != MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ) + { + ssl->handshake->async_in_progress = 0; + mbedtls_ssl_set_async_operation_data( ssl, NULL ); + } + MBEDTLS_SSL_DEBUG_RET( 2, "ssl_resume_server_key_exchange", ret ); + return( ret ); +} +#endif /* defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) && + defined(MBEDTLS_SSL_ASYNC_PRIVATE) */ + +/* Prepare the ServerKeyExchange message, up to and including + * calculating the signature if any, but excluding formatting the + * signature and sending the message. */ +static int ssl_prepare_server_key_exchange( mbedtls_ssl_context *ssl, + size_t *signature_len ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PFS_ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) + unsigned char *dig_signed = NULL; +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */ +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PFS_ENABLED */ + + (void) ciphersuite_info; /* unused in some configurations */ +#if !defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) + (void) signature_len; +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */ + + ssl->out_msglen = 4; /* header (type:1, length:3) to be written later */ + + /* + * + * Part 1: Provide key exchange parameters for chosen ciphersuite. + * + */ + + /* + * - ECJPAKE key exchanges + */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + ret = mbedtls_ecjpake_write_round_two( + &ssl->handshake->ecjpake_ctx, + ssl->out_msg + ssl->out_msglen, + MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen, &len, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_write_round_two", ret ); + return( ret ); + } + + ssl->out_msglen += len; + } +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + + /* + * For (EC)DHE key exchanges with PSK, parameters are prefixed by support + * identity hint (RFC 4279, Sec. 3). Until someone needs this feature, + * we use empty support identity hints here. + **/ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) + { + ssl->out_msg[ssl->out_msglen++] = 0x00; + ssl->out_msg[ssl->out_msglen++] = 0x00; + } +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + + /* + * - DHE key exchanges + */ +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED) + if( mbedtls_ssl_ciphersuite_uses_dhe( ciphersuite_info ) ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + if( ssl->conf->dhm_P.p == NULL || ssl->conf->dhm_G.p == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "no DH parameters set" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + /* + * Ephemeral DH parameters: + * + * struct { + * opaque dh_p<1..2^16-1>; + * opaque dh_g<1..2^16-1>; + * opaque dh_Ys<1..2^16-1>; + * } ServerDHParams; + */ + if( ( ret = mbedtls_dhm_set_group( &ssl->handshake->dhm_ctx, + &ssl->conf->dhm_P, + &ssl->conf->dhm_G ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_set_group", ret ); + return( ret ); + } + + if( ( ret = mbedtls_dhm_make_params( + &ssl->handshake->dhm_ctx, + (int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ), + ssl->out_msg + ssl->out_msglen, &len, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_make_params", ret ); + return( ret ); + } + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) + dig_signed = ssl->out_msg + ssl->out_msglen; +#endif + + ssl->out_msglen += len; + + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->handshake->dhm_ctx.X ); + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->handshake->dhm_ctx.P ); + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->handshake->dhm_ctx.G ); + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->handshake->dhm_ctx.GX ); + } +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED */ + + /* + * - ECDHE key exchanges + */ +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED) + if( mbedtls_ssl_ciphersuite_uses_ecdhe( ciphersuite_info ) ) + { + /* + * Ephemeral ECDH parameters: + * + * struct { + * ECParameters curve_params; + * ECPoint public; + * } ServerECDHParams; + */ + const mbedtls_ecp_curve_info **curve = NULL; + const mbedtls_ecp_group_id *gid; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + /* Match our preference list against the offered curves */ + for( gid = ssl->conf->curve_list; *gid != MBEDTLS_ECP_DP_NONE; gid++ ) + for( curve = ssl->handshake->curves; *curve != NULL; curve++ ) + if( (*curve)->grp_id == *gid ) + goto curve_matching_done; + +curve_matching_done: + if( curve == NULL || *curve == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "no matching curve for ECDHE" ) ); + return( MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "ECDHE curve: %s", (*curve)->name ) ); + + if( ( ret = mbedtls_ecdh_setup( &ssl->handshake->ecdh_ctx, + (*curve)->grp_id ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecp_group_load", ret ); + return( ret ); + } + + if( ( ret = mbedtls_ecdh_make_params( + &ssl->handshake->ecdh_ctx, &len, + ssl->out_msg + ssl->out_msglen, + MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_params", ret ); + return( ret ); + } + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) + dig_signed = ssl->out_msg + ssl->out_msglen; +#endif + + ssl->out_msglen += len; + + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_Q ); + } +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED */ + + /* + * + * Part 2: For key exchanges involving the server signing the + * exchange parameters, compute and add the signature here. + * + */ +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) + if( mbedtls_ssl_ciphersuite_uses_server_signature( ciphersuite_info ) ) + { + size_t dig_signed_len = ssl->out_msg + ssl->out_msglen - dig_signed; + size_t hashlen = 0; + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* + * 2.1: Choose hash algorithm: + * A: For TLS 1.2, obey signature-hash-algorithm extension + * to choose appropriate hash. + * B: For SSL3, TLS1.0, TLS1.1 and ECDHE_ECDSA, use SHA1 + * (RFC 4492, Sec. 5.4) + * C: Otherwise, use MD5 + SHA1 (RFC 4346, Sec. 7.4.3) + */ + + mbedtls_md_type_t md_alg; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + mbedtls_pk_type_t sig_alg = + mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ); + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + /* A: For TLS 1.2, obey signature-hash-algorithm extension + * (RFC 5246, Sec. 7.4.1.4.1). */ + if( sig_alg == MBEDTLS_PK_NONE || + ( md_alg = mbedtls_ssl_sig_hash_set_find( &ssl->handshake->hash_algs, + sig_alg ) ) == MBEDTLS_MD_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + /* (... because we choose a cipher suite + * only if there is a matching hash.) */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ) + { + /* B: Default hash SHA1 */ + md_alg = MBEDTLS_MD_SHA1; + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ + MBEDTLS_SSL_PROTO_TLS1_1 */ + { + /* C: MD5 + SHA1 */ + md_alg = MBEDTLS_MD_NONE; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "pick hash algorithm %d for signing", md_alg ) ); + + /* + * 2.2: Compute the hash to be signed + */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( md_alg == MBEDTLS_MD_NONE ) + { + hashlen = 36; + ret = mbedtls_ssl_get_key_exchange_md_ssl_tls( ssl, hash, + dig_signed, + dig_signed_len ); + if( ret != 0 ) + return( ret ); + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ + MBEDTLS_SSL_PROTO_TLS1_1 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( md_alg != MBEDTLS_MD_NONE ) + { + ret = mbedtls_ssl_get_key_exchange_md_tls1_2( ssl, hash, &hashlen, + dig_signed, + dig_signed_len, + md_alg ); + if( ret != 0 ) + return( ret ); + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ + MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen ); + + /* + * 2.3: Compute and add the signature + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + /* + * For TLS 1.2, we need to specify signature and hash algorithm + * explicitly through a prefix to the signature. + * + * struct { + * HashAlgorithm hash; + * SignatureAlgorithm signature; + * } SignatureAndHashAlgorithm; + * + * struct { + * SignatureAndHashAlgorithm algorithm; + * opaque signature<0..2^16-1>; + * } DigitallySigned; + * + */ + + ssl->out_msg[ssl->out_msglen++] = + mbedtls_ssl_hash_from_md_alg( md_alg ); + ssl->out_msg[ssl->out_msglen++] = + mbedtls_ssl_sig_from_pk_alg( sig_alg ); + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + if( ssl->conf->f_async_sign_start != NULL ) + { + ret = ssl->conf->f_async_sign_start( ssl, + mbedtls_ssl_own_cert( ssl ), + md_alg, hash, hashlen ); + switch( ret ) + { + case MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH: + /* act as if f_async_sign was null */ + break; + case 0: + ssl->handshake->async_in_progress = 1; + return( ssl_resume_server_key_exchange( ssl, signature_len ) ); + case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS: + ssl->handshake->async_in_progress = 1; + return( MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ); + default: + MBEDTLS_SSL_DEBUG_RET( 1, "f_async_sign_start", ret ); + return( ret ); + } + } +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + + if( mbedtls_ssl_own_key( ssl ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no private key" ) ); + return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); + } + + /* Append the signature to ssl->out_msg, leaving 2 bytes for the + * signature length which will be added in ssl_write_server_key_exchange + * after the call to ssl_prepare_server_key_exchange. + * ssl_write_server_key_exchange also takes care of incrementing + * ssl->out_msglen. */ + if( ( ret = mbedtls_pk_sign( mbedtls_ssl_own_key( ssl ), + md_alg, hash, hashlen, + ssl->out_msg + ssl->out_msglen + 2, + signature_len, + ssl->conf->f_rng, + ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_sign", ret ); + return( ret ); + } + } +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */ + + return( 0 ); +} + +/* Prepare the ServerKeyExchange message and send it. For ciphersuites + * that do not include a ServerKeyExchange message, do nothing. Either + * way, if successful, move on to the next step in the SSL state + * machine. */ +static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t signature_len = 0; +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED) + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED */ + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server key exchange" ) ); + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED) + /* Extract static ECDH parameters and abort if ServerKeyExchange + * is not needed. */ + if( mbedtls_ssl_ciphersuite_no_pfs( ciphersuite_info ) ) + { + /* For suites involving ECDH, extract DH parameters + * from certificate at this point. */ +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED) + if( mbedtls_ssl_ciphersuite_uses_ecdh( ciphersuite_info ) ) + { + ssl_get_ecdh_params_from_cert( ssl ); + } +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED */ + + /* Key exchanges not involving ephemeral keys don't use + * ServerKeyExchange, so end here. */ + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) ); + ssl->state++; + return( 0 ); + } +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) && \ + defined(MBEDTLS_SSL_ASYNC_PRIVATE) + /* If we have already prepared the message and there is an ongoing + * signature operation, resume signing. */ + if( ssl->handshake->async_in_progress != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "resuming signature operation" ) ); + ret = ssl_resume_server_key_exchange( ssl, &signature_len ); + } + else +#endif /* defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) && + defined(MBEDTLS_SSL_ASYNC_PRIVATE) */ + { + /* ServerKeyExchange is needed. Prepare the message. */ + ret = ssl_prepare_server_key_exchange( ssl, &signature_len ); + } + + if( ret != 0 ) + { + /* If we're starting to write a new message, set ssl->out_msglen + * to 0. But if we're resuming after an asynchronous message, + * out_msglen is the amount of data written so far and mst be + * preserved. */ + if( ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ) + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server key exchange (pending)" ) ); + else + ssl->out_msglen = 0; + return( ret ); + } + + /* If there is a signature, write its length. + * ssl_prepare_server_key_exchange already wrote the signature + * itself at its proper place in the output buffer. */ +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) + if( signature_len != 0 ) + { + ssl->out_msg[ssl->out_msglen++] = (unsigned char)( signature_len >> 8 ); + ssl->out_msg[ssl->out_msglen++] = (unsigned char)( signature_len ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "my signature", + ssl->out_msg + ssl->out_msglen, + signature_len ); + + /* Skip over the already-written signature */ + ssl->out_msglen += signature_len; + } +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */ + + /* Add header and send. */ + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE; + + ssl->state++; + + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server key exchange" ) ); + return( 0 ); +} + +static int ssl_write_server_hello_done( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server hello done" ) ); + + ssl->out_msglen = 4; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_HELLO_DONE; + + ssl->state++; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + mbedtls_ssl_send_flight_completed( ssl ); +#endif + + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret ); + return( ret ); + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello done" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) +static int ssl_parse_client_dh_public( mbedtls_ssl_context *ssl, unsigned char **p, + const unsigned char *end ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + size_t n; + + /* + * Receive G^Y mod P, premaster = (G^Y)^X mod P + */ + if( *p + 2 > end ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + n = ( (*p)[0] << 8 ) | (*p)[1]; + *p += 2; + + if( *p + n > end ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + if( ( ret = mbedtls_dhm_read_public( &ssl->handshake->dhm_ctx, *p, n ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_read_public", ret ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP ); + } + + *p += n; + + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GY", &ssl->handshake->dhm_ctx.GY ); + + return( ret ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) +static int ssl_resume_decrypt_pms( mbedtls_ssl_context *ssl, + unsigned char *peer_pms, + size_t *peer_pmslen, + size_t peer_pmssize ) +{ + int ret = ssl->conf->f_async_resume( ssl, + peer_pms, peer_pmslen, peer_pmssize ); + if( ret != MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ) + { + ssl->handshake->async_in_progress = 0; + mbedtls_ssl_set_async_operation_data( ssl, NULL ); + } + MBEDTLS_SSL_DEBUG_RET( 2, "ssl_decrypt_encrypted_pms", ret ); + return( ret ); +} +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + +static int ssl_decrypt_encrypted_pms( mbedtls_ssl_context *ssl, + const unsigned char *p, + const unsigned char *end, + unsigned char *peer_pms, + size_t *peer_pmslen, + size_t peer_pmssize ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_pk_context *private_key = mbedtls_ssl_own_key( ssl ); + mbedtls_pk_context *public_key = &mbedtls_ssl_own_cert( ssl )->pk; + size_t len = mbedtls_pk_get_len( public_key ); + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + /* If we have already started decoding the message and there is an ongoing + * decryption operation, resume signing. */ + if( ssl->handshake->async_in_progress != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "resuming decryption operation" ) ); + return( ssl_resume_decrypt_pms( ssl, + peer_pms, peer_pmslen, peer_pmssize ) ); + } +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + + /* + * Prepare to decrypt the premaster using own private RSA key + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 ) + { + if ( p + 2 > end ) { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + if( *p++ != ( ( len >> 8 ) & 0xFF ) || + *p++ != ( ( len ) & 0xFF ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + } +#endif + + if( p + len != end ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + /* + * Decrypt the premaster secret + */ +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + if( ssl->conf->f_async_decrypt_start != NULL ) + { + ret = ssl->conf->f_async_decrypt_start( ssl, + mbedtls_ssl_own_cert( ssl ), + p, len ); + switch( ret ) + { + case MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH: + /* act as if f_async_decrypt_start was null */ + break; + case 0: + ssl->handshake->async_in_progress = 1; + return( ssl_resume_decrypt_pms( ssl, + peer_pms, + peer_pmslen, + peer_pmssize ) ); + case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS: + ssl->handshake->async_in_progress = 1; + return( MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ); + default: + MBEDTLS_SSL_DEBUG_RET( 1, "f_async_decrypt_start", ret ); + return( ret ); + } + } +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + + if( ! mbedtls_pk_can_do( private_key, MBEDTLS_PK_RSA ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no RSA private key" ) ); + return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); + } + + ret = mbedtls_pk_decrypt( private_key, p, len, + peer_pms, peer_pmslen, peer_pmssize, + ssl->conf->f_rng, ssl->conf->p_rng ); + return( ret ); +} + +static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl, + const unsigned char *p, + const unsigned char *end, + size_t pms_offset ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *pms = ssl->handshake->premaster + pms_offset; + unsigned char ver[2]; + unsigned char fake_pms[48], peer_pms[48]; + unsigned char mask; + size_t i, peer_pmslen; + unsigned int diff; + + /* In case of a failure in decryption, the decryption may write less than + * 2 bytes of output, but we always read the first two bytes. It doesn't + * matter in the end because diff will be nonzero in that case due to + * peer_pmslen being less than 48, and we only care whether diff is 0. + * But do initialize peer_pms for robustness anyway. This also makes + * memory analyzers happy (don't access uninitialized memory, even + * if it's an unsigned char). */ + peer_pms[0] = peer_pms[1] = ~0; + + ret = ssl_decrypt_encrypted_pms( ssl, p, end, + peer_pms, + &peer_pmslen, + sizeof( peer_pms ) ); + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + if ( ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ) + return( ret ); +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + + mbedtls_ssl_write_version( ssl->handshake->max_major_ver, + ssl->handshake->max_minor_ver, + ssl->conf->transport, ver ); + + /* Avoid data-dependent branches while checking for invalid + * padding, to protect against timing-based Bleichenbacher-type + * attacks. */ + diff = (unsigned int) ret; + diff |= peer_pmslen ^ 48; + diff |= peer_pms[0] ^ ver[0]; + diff |= peer_pms[1] ^ ver[1]; + + /* mask = diff ? 0xff : 0x00 using bit operations to avoid branches */ + /* MSVC has a warning about unary minus on unsigned, but this is + * well-defined and precisely what we want to do here */ +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + mask = - ( ( diff | - diff ) >> ( sizeof( unsigned int ) * 8 - 1 ) ); +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif + + /* + * Protection against Bleichenbacher's attack: invalid PKCS#1 v1.5 padding + * must not cause the connection to end immediately; instead, send a + * bad_record_mac later in the handshake. + * To protect against timing-based variants of the attack, we must + * not have any branch that depends on whether the decryption was + * successful. In particular, always generate the fake premaster secret, + * regardless of whether it will ultimately influence the output or not. + */ + ret = ssl->conf->f_rng( ssl->conf->p_rng, fake_pms, sizeof( fake_pms ) ); + if( ret != 0 ) + { + /* It's ok to abort on an RNG failure, since this does not reveal + * anything about the RSA decryption. */ + return( ret ); + } + +#if defined(MBEDTLS_SSL_DEBUG_ALL) + if( diff != 0 ) + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); +#endif + + if( sizeof( ssl->handshake->premaster ) < pms_offset || + sizeof( ssl->handshake->premaster ) - pms_offset < 48 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + ssl->handshake->pmslen = 48; + + /* Set pms to either the true or the fake PMS, without + * data-dependent branches. */ + for( i = 0; i < ssl->handshake->pmslen; i++ ) + pms[i] = ( mask & fake_pms[i] ) | ( (~mask) & peer_pms[i] ); + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) +static int ssl_parse_client_psk_identity( mbedtls_ssl_context *ssl, unsigned char **p, + const unsigned char *end ) +{ + int ret = 0; + uint16_t n; + + if( ssl_conf_has_psk_or_cb( ssl->conf ) == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no pre-shared key" ) ); + return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); + } + + /* + * Receive client pre-shared key identity name + */ + if( end - *p < 2 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + n = ( (*p)[0] << 8 ) | (*p)[1]; + *p += 2; + + if( n == 0 || n > end - *p ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + if( ssl->conf->f_psk != NULL ) + { + if( ssl->conf->f_psk( ssl->conf->p_psk, ssl, *p, n ) != 0 ) + ret = MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY; + } + else + { + /* Identity is not a big secret since clients send it in the clear, + * but treat it carefully anyway, just in case */ + if( n != ssl->conf->psk_identity_len || + mbedtls_ssl_safer_memcmp( ssl->conf->psk_identity, *p, n ) != 0 ) + { + ret = MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY; + } + } + + if( ret == MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY ) + { + MBEDTLS_SSL_DEBUG_BUF( 3, "Unknown PSK identity", *p, n ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY ); + return( MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY ); + } + + *p += n; + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ + +static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + unsigned char *p, *end; + + ciphersuite_info = ssl->handshake->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client key exchange" ) ); + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) && \ + ( defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) ) + if( ( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA ) && + ( ssl->handshake->async_in_progress != 0 ) ) + { + /* We've already read a record and there is an asynchronous + * operation in progress to decrypt it. So skip reading the + * record. */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "will resume decryption of previously-read record" ) ); + } + else +#endif + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + p = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); + end = ssl->in_msg + ssl->in_hslen; + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + if( ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA ) + { + if( ( ret = ssl_parse_client_dh_public( ssl, &p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_dh_public" ), ret ); + return( ret ); + } + + if( p != end ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + if( ( ret = mbedtls_dhm_calc_secret( &ssl->handshake->dhm_ctx, + ssl->handshake->premaster, + MBEDTLS_PREMASTER_SIZE, + &ssl->handshake->pmslen, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_calc_secret", ret ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS ); + } + + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA ) + { + if( ( ret = mbedtls_ecdh_read_public( &ssl->handshake->ecdh_ctx, + p, end - p) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_read_public", ret ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP ); + } + + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_QP ); + + if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx, + &ssl->handshake->pmslen, + ssl->handshake->premaster, + MBEDTLS_MPI_MAX_SIZE, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS ); + } + + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_Z ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ) + { + if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); + return( ret ); + } + + if( p != end ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + /* For opaque PSKs, we perform the PSK-to-MS derivation atomatically + * and skip the intermediate PMS. */ + if( ssl_use_opaque_psk( ssl ) == 1 ) + MBEDTLS_SSL_DEBUG_MSG( 1, ( "skip PMS generation for opaque PSK" ) ); + else +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, + ciphersuite_info->key_exchange ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) + { +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + if ( ssl->handshake->async_in_progress != 0 ) + { + /* There is an asynchronous operation in progress to + * decrypt the encrypted premaster secret, so skip + * directly to resuming this operation. */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "PSK identity already parsed" ) ); + /* Update p to skip the PSK identity. ssl_parse_encrypted_pms + * won't actually use it, but maintain p anyway for robustness. */ + p += ssl->conf->psk_identity_len + 2; + } + else +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); + return( ret ); + } + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + /* Opaque PSKs are currently only supported for PSK-only. */ + if( ssl_use_opaque_psk( ssl ) == 1 ) + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); +#endif + + if( ( ret = ssl_parse_encrypted_pms( ssl, p, end, 2 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_encrypted_pms" ), ret ); + return( ret ); + } + + if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, + ciphersuite_info->key_exchange ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ) + { + if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); + return( ret ); + } + if( ( ret = ssl_parse_client_dh_public( ssl, &p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_dh_public" ), ret ); + return( ret ); + } + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + /* Opaque PSKs are currently only supported for PSK-only. */ + if( ssl_use_opaque_psk( ssl ) == 1 ) + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); +#endif + + if( p != end ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, + ciphersuite_info->key_exchange ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) + { + if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); + return( ret ); + } + + if( ( ret = mbedtls_ecdh_read_public( &ssl->handshake->ecdh_ctx, + p, end - p ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_read_public", ret ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP ); + } + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + /* Opaque PSKs are currently only supported for PSK-only. */ + if( ssl_use_opaque_psk( ssl ) == 1 ) + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); +#endif + + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_QP ); + + if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, + ciphersuite_info->key_exchange ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA ) + { + if( ( ret = ssl_parse_encrypted_pms( ssl, p, end, 0 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_parse_encrypted_pms_secret" ), ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + ret = mbedtls_ecjpake_read_round_two( &ssl->handshake->ecjpake_ctx, + p, end - p ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_two", ret ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + ret = mbedtls_ecjpake_derive_secret( &ssl->handshake->ecjpake_ctx, + ssl->handshake->premaster, 32, &ssl->handshake->pmslen, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_derive_secret", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); + return( ret ); + } + + ssl->state++; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse client key exchange" ) ); + + return( 0 ); +} + +#if !defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) +static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) ); + + if( !mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) ); + ssl->state++; + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); +} +#else /* !MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ +static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + size_t i, sig_len; + unsigned char hash[48]; + unsigned char *hash_start = hash; + size_t hashlen; +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + mbedtls_pk_type_t pk_alg; +#endif + mbedtls_md_type_t md_alg; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + mbedtls_pk_context * peer_pk; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) ); + + if( !mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) ); + ssl->state++; + return( 0 ); + } + +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + if( ssl->session_negotiate->peer_cert == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) ); + ssl->state++; + return( 0 ); + } +#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + if( ssl->session_negotiate->peer_cert_digest == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) ); + ssl->state++; + return( 0 ); + } +#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + + /* Read the message without adding it to the checksum */ + ret = mbedtls_ssl_read_record( ssl, 0 /* no checksum update */ ); + if( 0 != ret ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record" ), ret ); + return( ret ); + } + + ssl->state++; + + /* Process the message contents */ + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE || + ssl->in_msg[0] != MBEDTLS_SSL_HS_CERTIFICATE_VERIFY ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + + i = mbedtls_ssl_hs_hdr_len( ssl ); + +#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + peer_pk = &ssl->handshake->peer_pubkey; +#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + if( ssl->session_negotiate->peer_cert == NULL ) + { + /* Should never happen */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + peer_pk = &ssl->session_negotiate->peer_cert->pk; +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + + /* + * struct { + * SignatureAndHashAlgorithm algorithm; -- TLS 1.2 only + * opaque signature<0..2^16-1>; + * } DigitallySigned; + */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) + { + md_alg = MBEDTLS_MD_NONE; + hashlen = 36; + + /* For ECDSA, use SHA-1, not MD-5 + SHA-1 */ + if( mbedtls_pk_can_do( peer_pk, MBEDTLS_PK_ECDSA ) ) + { + hash_start += 16; + hashlen -= 16; + md_alg = MBEDTLS_MD_SHA1; + } + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || + MBEDTLS_SSL_PROTO_TLS1_1 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + if( i + 2 > ssl->in_hslen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + + /* + * Hash + */ + md_alg = mbedtls_ssl_md_alg_from_hash( ssl->in_msg[i] ); + + if( md_alg == MBEDTLS_MD_NONE || mbedtls_ssl_set_calc_verify_md( ssl, ssl->in_msg[i] ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "peer not adhering to requested sig_alg" + " for verify message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + +#if !defined(MBEDTLS_MD_SHA1) + if( MBEDTLS_MD_SHA1 == md_alg ) + hash_start += 16; +#endif + + /* Info from md_alg will be used instead */ + hashlen = 0; + + i++; + + /* + * Signature + */ + if( ( pk_alg = mbedtls_ssl_pk_alg_from_sig( ssl->in_msg[i] ) ) + == MBEDTLS_PK_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "peer not adhering to requested sig_alg" + " for verify message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + + /* + * Check the certificate's key type matches the signature alg + */ + if( !mbedtls_pk_can_do( peer_pk, pk_alg ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "sig_alg doesn't match cert key" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + + i++; + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + if( i + 2 > ssl->in_hslen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + + sig_len = ( ssl->in_msg[i] << 8 ) | ssl->in_msg[i+1]; + i += 2; + + if( i + sig_len != ssl->in_hslen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + + /* Calculate hash and verify signature */ + { + size_t dummy_hlen; + ssl->handshake->calc_verify( ssl, hash, &dummy_hlen ); + } + + if( ( ret = mbedtls_pk_verify( peer_pk, + md_alg, hash_start, hashlen, + ssl->in_msg + i, sig_len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_verify", ret ); + return( ret ); + } + + mbedtls_ssl_update_handshake_status( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate verify" ) ); + + return( ret ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +static int ssl_write_new_session_ticket( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t tlen; + uint32_t lifetime; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write new session ticket" ) ); + + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_NEW_SESSION_TICKET; + + /* + * struct { + * uint32 ticket_lifetime_hint; + * opaque ticket<0..2^16-1>; + * } NewSessionTicket; + * + * 4 . 7 ticket_lifetime_hint (0 = unspecified) + * 8 . 9 ticket_len (n) + * 10 . 9+n ticket content + */ + + if( ( ret = ssl->conf->f_ticket_write( ssl->conf->p_ticket, + ssl->session_negotiate, + ssl->out_msg + 10, + ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN, + &tlen, &lifetime ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_ticket_write", ret ); + tlen = 0; + } + + ssl->out_msg[4] = ( lifetime >> 24 ) & 0xFF; + ssl->out_msg[5] = ( lifetime >> 16 ) & 0xFF; + ssl->out_msg[6] = ( lifetime >> 8 ) & 0xFF; + ssl->out_msg[7] = ( lifetime ) & 0xFF; + + ssl->out_msg[8] = (unsigned char)( ( tlen >> 8 ) & 0xFF ); + ssl->out_msg[9] = (unsigned char)( ( tlen ) & 0xFF ); + + ssl->out_msglen = 10 + tlen; + + /* + * Morally equivalent to updating ssl->state, but NewSessionTicket and + * ChangeCipherSpec share the same state. + */ + ssl->handshake->new_session_ticket = 0; + + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write new session ticket" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +/* + * SSL handshake -- server side -- single step + */ +int mbedtls_ssl_handshake_server_step( mbedtls_ssl_context *ssl ) +{ + int ret = 0; + + if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER || ssl->handshake == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "server state: %d", ssl->state ) ); + + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + return( ret ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) + { + if( ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) + return( ret ); + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + switch( ssl->state ) + { + case MBEDTLS_SSL_HELLO_REQUEST: + ssl->state = MBEDTLS_SSL_CLIENT_HELLO; + break; + + /* + * <== ClientHello + */ + case MBEDTLS_SSL_CLIENT_HELLO: + ret = ssl_parse_client_hello( ssl ); + break; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + case MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT: + return( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ); +#endif + + /* + * ==> ServerHello + * Certificate + * ( ServerKeyExchange ) + * ( CertificateRequest ) + * ServerHelloDone + */ + case MBEDTLS_SSL_SERVER_HELLO: + ret = ssl_write_server_hello( ssl ); + break; + + case MBEDTLS_SSL_SERVER_CERTIFICATE: + ret = mbedtls_ssl_write_certificate( ssl ); + break; + + case MBEDTLS_SSL_SERVER_KEY_EXCHANGE: + ret = ssl_write_server_key_exchange( ssl ); + break; + + case MBEDTLS_SSL_CERTIFICATE_REQUEST: + ret = ssl_write_certificate_request( ssl ); + break; + + case MBEDTLS_SSL_SERVER_HELLO_DONE: + ret = ssl_write_server_hello_done( ssl ); + break; + + /* + * <== ( Certificate/Alert ) + * ClientKeyExchange + * ( CertificateVerify ) + * ChangeCipherSpec + * Finished + */ + case MBEDTLS_SSL_CLIENT_CERTIFICATE: + ret = mbedtls_ssl_parse_certificate( ssl ); + break; + + case MBEDTLS_SSL_CLIENT_KEY_EXCHANGE: + ret = ssl_parse_client_key_exchange( ssl ); + break; + + case MBEDTLS_SSL_CERTIFICATE_VERIFY: + ret = ssl_parse_certificate_verify( ssl ); + break; + + case MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC: + ret = mbedtls_ssl_parse_change_cipher_spec( ssl ); + break; + + case MBEDTLS_SSL_CLIENT_FINISHED: + ret = mbedtls_ssl_parse_finished( ssl ); + break; + + /* + * ==> ( NewSessionTicket ) + * ChangeCipherSpec + * Finished + */ + case MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC: +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + if( ssl->handshake->new_session_ticket != 0 ) + ret = ssl_write_new_session_ticket( ssl ); + else +#endif + ret = mbedtls_ssl_write_change_cipher_spec( ssl ); + break; + + case MBEDTLS_SSL_SERVER_FINISHED: + ret = mbedtls_ssl_write_finished( ssl ); + break; + + case MBEDTLS_SSL_FLUSH_BUFFERS: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "handshake: done" ) ); + ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; + break; + + case MBEDTLS_SSL_HANDSHAKE_WRAPUP: + mbedtls_ssl_handshake_wrapup( ssl ); + break; + + default: + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + return( ret ); +} +#endif /* MBEDTLS_SSL_SRV_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/ssl_ticket.c b/Android/Level4/app/src/main/c/mbedtls/library/ssl_ticket.c new file mode 100644 index 0000000..e3e8023 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/ssl_ticket.c @@ -0,0 +1,408 @@ +/* + * TLS server tickets callbacks implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 "common.h" + +#if defined(MBEDTLS_SSL_TICKET_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/ssl_internal.h" +#include "mbedtls/ssl_ticket.h" +#include "mbedtls/error.h" +#include "mbedtls/platform_util.h" + +#include + +/* + * Initialze context + */ +void mbedtls_ssl_ticket_init( mbedtls_ssl_ticket_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_ssl_ticket_context ) ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif +} + +#define MAX_KEY_BYTES 32 /* 256 bits */ + +#define TICKET_KEY_NAME_BYTES 4 +#define TICKET_IV_BYTES 12 +#define TICKET_CRYPT_LEN_BYTES 2 +#define TICKET_AUTH_TAG_BYTES 16 + +#define TICKET_MIN_LEN ( TICKET_KEY_NAME_BYTES + \ + TICKET_IV_BYTES + \ + TICKET_CRYPT_LEN_BYTES + \ + TICKET_AUTH_TAG_BYTES ) +#define TICKET_ADD_DATA_LEN ( TICKET_KEY_NAME_BYTES + \ + TICKET_IV_BYTES + \ + TICKET_CRYPT_LEN_BYTES ) + +/* + * Generate/update a key + */ +static int ssl_ticket_gen_key( mbedtls_ssl_ticket_context *ctx, + unsigned char index ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char buf[MAX_KEY_BYTES]; + mbedtls_ssl_ticket_key *key = ctx->keys + index; + +#if defined(MBEDTLS_HAVE_TIME) + key->generation_time = (uint32_t) mbedtls_time( NULL ); +#endif + + if( ( ret = ctx->f_rng( ctx->p_rng, key->name, sizeof( key->name ) ) ) != 0 ) + return( ret ); + + if( ( ret = ctx->f_rng( ctx->p_rng, buf, sizeof( buf ) ) ) != 0 ) + return( ret ); + + /* With GCM and CCM, same context can encrypt & decrypt */ + ret = mbedtls_cipher_setkey( &key->ctx, buf, + mbedtls_cipher_get_key_bitlen( &key->ctx ), + MBEDTLS_ENCRYPT ); + + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + + return( ret ); +} + +/* + * Rotate/generate keys if necessary + */ +static int ssl_ticket_update_keys( mbedtls_ssl_ticket_context *ctx ) +{ +#if !defined(MBEDTLS_HAVE_TIME) + ((void) ctx); +#else + if( ctx->ticket_lifetime != 0 ) + { + uint32_t current_time = (uint32_t) mbedtls_time( NULL ); + uint32_t key_time = ctx->keys[ctx->active].generation_time; + + if( current_time >= key_time && + current_time - key_time < ctx->ticket_lifetime ) + { + return( 0 ); + } + + ctx->active = 1 - ctx->active; + + return( ssl_ticket_gen_key( ctx, ctx->active ) ); + } + else +#endif /* MBEDTLS_HAVE_TIME */ + return( 0 ); +} + +/* + * Setup context for actual use + */ +int mbedtls_ssl_ticket_setup( mbedtls_ssl_ticket_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_cipher_type_t cipher, + uint32_t lifetime ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const mbedtls_cipher_info_t *cipher_info; + + ctx->f_rng = f_rng; + ctx->p_rng = p_rng; + + ctx->ticket_lifetime = lifetime; + + cipher_info = mbedtls_cipher_info_from_type( cipher); + if( cipher_info == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( cipher_info->mode != MBEDTLS_MODE_GCM && + cipher_info->mode != MBEDTLS_MODE_CCM ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + if( cipher_info->key_bitlen > 8 * MAX_KEY_BYTES ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + ret = mbedtls_cipher_setup_psa( &ctx->keys[0].ctx, + cipher_info, TICKET_AUTH_TAG_BYTES ); + if( ret != 0 && ret != MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ) + return( ret ); + /* We don't yet expect to support all ciphers through PSA, + * so allow fallback to ordinary mbedtls_cipher_setup(). */ + if( ret == MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ) +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + if( ( ret = mbedtls_cipher_setup( &ctx->keys[0].ctx, cipher_info ) ) != 0 ) + return( ret ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + ret = mbedtls_cipher_setup_psa( &ctx->keys[1].ctx, + cipher_info, TICKET_AUTH_TAG_BYTES ); + if( ret != 0 && ret != MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ) + return( ret ); + if( ret == MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ) +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + if( ( ret = mbedtls_cipher_setup( &ctx->keys[1].ctx, cipher_info ) ) != 0 ) + return( ret ); + + if( ( ret = ssl_ticket_gen_key( ctx, 0 ) ) != 0 || + ( ret = ssl_ticket_gen_key( ctx, 1 ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} + +/* + * Create session ticket, with the following structure: + * + * struct { + * opaque key_name[4]; + * opaque iv[12]; + * opaque encrypted_state<0..2^16-1>; + * opaque tag[16]; + * } ticket; + * + * The key_name, iv, and length of encrypted_state are the additional + * authenticated data. + */ + +int mbedtls_ssl_ticket_write( void *p_ticket, + const mbedtls_ssl_session *session, + unsigned char *start, + const unsigned char *end, + size_t *tlen, + uint32_t *ticket_lifetime ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ssl_ticket_context *ctx = p_ticket; + mbedtls_ssl_ticket_key *key; + unsigned char *key_name = start; + unsigned char *iv = start + TICKET_KEY_NAME_BYTES; + unsigned char *state_len_bytes = iv + TICKET_IV_BYTES; + unsigned char *state = state_len_bytes + TICKET_CRYPT_LEN_BYTES; + unsigned char *tag; + size_t clear_len, ciph_len; + + *tlen = 0; + + if( ctx == NULL || ctx->f_rng == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + /* We need at least 4 bytes for key_name, 12 for IV, 2 for len 16 for tag, + * in addition to session itself, that will be checked when writing it. */ + MBEDTLS_SSL_CHK_BUF_PTR( start, end, TICKET_MIN_LEN ); + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + if( ( ret = ssl_ticket_update_keys( ctx ) ) != 0 ) + goto cleanup; + + key = &ctx->keys[ctx->active]; + + *ticket_lifetime = ctx->ticket_lifetime; + + memcpy( key_name, key->name, TICKET_KEY_NAME_BYTES ); + + if( ( ret = ctx->f_rng( ctx->p_rng, iv, TICKET_IV_BYTES ) ) != 0 ) + goto cleanup; + + /* Dump session state */ + if( ( ret = mbedtls_ssl_session_save( session, + state, end - state, + &clear_len ) ) != 0 || + (unsigned long) clear_len > 65535 ) + { + goto cleanup; + } + state_len_bytes[0] = ( clear_len >> 8 ) & 0xff; + state_len_bytes[1] = ( clear_len ) & 0xff; + + /* Encrypt and authenticate */ + tag = state + clear_len; + if( ( ret = mbedtls_cipher_auth_encrypt( &key->ctx, + iv, TICKET_IV_BYTES, + /* Additional data: key name, IV and length */ + key_name, TICKET_ADD_DATA_LEN, + state, clear_len, state, &ciph_len, + tag, TICKET_AUTH_TAG_BYTES ) ) != 0 ) + { + goto cleanup; + } + if( ciph_len != clear_len ) + { + ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; + goto cleanup; + } + + *tlen = TICKET_MIN_LEN + ciph_len; + +cleanup: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +/* + * Select key based on name + */ +static mbedtls_ssl_ticket_key *ssl_ticket_select_key( + mbedtls_ssl_ticket_context *ctx, + const unsigned char name[4] ) +{ + unsigned char i; + + for( i = 0; i < sizeof( ctx->keys ) / sizeof( *ctx->keys ); i++ ) + if( memcmp( name, ctx->keys[i].name, 4 ) == 0 ) + return( &ctx->keys[i] ); + + return( NULL ); +} + +/* + * Load session ticket (see mbedtls_ssl_ticket_write for structure) + */ +int mbedtls_ssl_ticket_parse( void *p_ticket, + mbedtls_ssl_session *session, + unsigned char *buf, + size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ssl_ticket_context *ctx = p_ticket; + mbedtls_ssl_ticket_key *key; + unsigned char *key_name = buf; + unsigned char *iv = buf + TICKET_KEY_NAME_BYTES; + unsigned char *enc_len_p = iv + TICKET_IV_BYTES; + unsigned char *ticket = enc_len_p + TICKET_CRYPT_LEN_BYTES; + unsigned char *tag; + size_t enc_len, clear_len; + + if( ctx == NULL || ctx->f_rng == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( len < TICKET_MIN_LEN ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + if( ( ret = ssl_ticket_update_keys( ctx ) ) != 0 ) + goto cleanup; + + enc_len = ( enc_len_p[0] << 8 ) | enc_len_p[1]; + tag = ticket + enc_len; + + if( len != TICKET_MIN_LEN + enc_len ) + { + ret = MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + goto cleanup; + } + + /* Select key */ + if( ( key = ssl_ticket_select_key( ctx, key_name ) ) == NULL ) + { + /* We can't know for sure but this is a likely option unless we're + * under attack - this is only informative anyway */ + ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED; + goto cleanup; + } + + /* Decrypt and authenticate */ + if( ( ret = mbedtls_cipher_auth_decrypt( &key->ctx, + iv, TICKET_IV_BYTES, + /* Additional data: key name, IV and length */ + key_name, TICKET_ADD_DATA_LEN, + ticket, enc_len, + ticket, &clear_len, + tag, TICKET_AUTH_TAG_BYTES ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED ) + ret = MBEDTLS_ERR_SSL_INVALID_MAC; + + goto cleanup; + } + if( clear_len != enc_len ) + { + ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; + goto cleanup; + } + + /* Actually load session */ + if( ( ret = mbedtls_ssl_session_load( session, ticket, clear_len ) ) != 0 ) + goto cleanup; + +#if defined(MBEDTLS_HAVE_TIME) + { + /* Check for expiration */ + mbedtls_time_t current_time = mbedtls_time( NULL ); + + if( current_time < session->start || + (uint32_t)( current_time - session->start ) > ctx->ticket_lifetime ) + { + ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED; + goto cleanup; + } + } +#endif + +cleanup: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +/* + * Free context + */ +void mbedtls_ssl_ticket_free( mbedtls_ssl_ticket_context *ctx ) +{ + mbedtls_cipher_free( &ctx->keys[0].ctx ); + mbedtls_cipher_free( &ctx->keys[1].ctx ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free( &ctx->mutex ); +#endif + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ssl_ticket_context ) ); +} + +#endif /* MBEDTLS_SSL_TICKET_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/ssl_tls.c b/Android/Level4/app/src/main/c/mbedtls/library/ssl_tls.c new file mode 100644 index 0000000..7cb5b8c --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/ssl_tls.c @@ -0,0 +1,7676 @@ +/* + * SSLv3/TLSv1 shared functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ +/* + * The SSL 3.0 specification was drafted by Netscape in 1996, + * and became an IETF standard in 1999. + * + * http://wp.netscape.com/eng/ssl3/ + * http://www.ietf.org/rfc/rfc2246.txt + * http://www.ietf.org/rfc/rfc4346.txt + */ + +#include "common.h" + +#if defined(MBEDTLS_SSL_TLS_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/ssl.h" +#include "mbedtls/ssl_internal.h" +#include "mbedtls/debug.h" +#include "mbedtls/error.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/version.h" + +#include + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "mbedtls/psa_util.h" +#include "psa/crypto.h" +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#include "mbedtls/oid.h" +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) +/* Top-level Connection ID API */ + +int mbedtls_ssl_conf_cid( mbedtls_ssl_config *conf, + size_t len, + int ignore_other_cid ) +{ + if( len > MBEDTLS_SSL_CID_IN_LEN_MAX ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( ignore_other_cid != MBEDTLS_SSL_UNEXPECTED_CID_FAIL && + ignore_other_cid != MBEDTLS_SSL_UNEXPECTED_CID_IGNORE ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + conf->ignore_unexpected_cid = ignore_other_cid; + conf->cid_len = len; + return( 0 ); +} + +int mbedtls_ssl_set_cid( mbedtls_ssl_context *ssl, + int enable, + unsigned char const *own_cid, + size_t own_cid_len ) +{ + if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ssl->negotiate_cid = enable; + if( enable == MBEDTLS_SSL_CID_DISABLED ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Disable use of CID extension." ) ); + return( 0 ); + } + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Enable use of CID extension." ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "Own CID", own_cid, own_cid_len ); + + if( own_cid_len != ssl->conf->cid_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "CID length %u does not match CID length %u in config", + (unsigned) own_cid_len, + (unsigned) ssl->conf->cid_len ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + memcpy( ssl->own_cid, own_cid, own_cid_len ); + /* Truncation is not an issue here because + * MBEDTLS_SSL_CID_IN_LEN_MAX at most 255. */ + ssl->own_cid_len = (uint8_t) own_cid_len; + + return( 0 ); +} + +int mbedtls_ssl_get_peer_cid( mbedtls_ssl_context *ssl, + int *enabled, + unsigned char peer_cid[ MBEDTLS_SSL_CID_OUT_LEN_MAX ], + size_t *peer_cid_len ) +{ + *enabled = MBEDTLS_SSL_CID_DISABLED; + + if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM || + ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + /* We report MBEDTLS_SSL_CID_DISABLED in case the CID extensions + * were used, but client and server requested the empty CID. + * This is indistinguishable from not using the CID extension + * in the first place. */ + if( ssl->transform_in->in_cid_len == 0 && + ssl->transform_in->out_cid_len == 0 ) + { + return( 0 ); + } + + if( peer_cid_len != NULL ) + { + *peer_cid_len = ssl->transform_in->out_cid_len; + if( peer_cid != NULL ) + { + memcpy( peer_cid, ssl->transform_in->out_cid, + ssl->transform_in->out_cid_len ); + } + } + + *enabled = MBEDTLS_SSL_CID_ENABLED; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +/* + * Convert max_fragment_length codes to length. + * RFC 6066 says: + * enum{ + * 2^9(1), 2^10(2), 2^11(3), 2^12(4), (255) + * } MaxFragmentLength; + * and we add 0 -> extension unused + */ +static unsigned int ssl_mfl_code_to_length( int mfl ) +{ + switch( mfl ) + { + case MBEDTLS_SSL_MAX_FRAG_LEN_NONE: + return ( MBEDTLS_TLS_EXT_ADV_CONTENT_LEN ); + case MBEDTLS_SSL_MAX_FRAG_LEN_512: + return 512; + case MBEDTLS_SSL_MAX_FRAG_LEN_1024: + return 1024; + case MBEDTLS_SSL_MAX_FRAG_LEN_2048: + return 2048; + case MBEDTLS_SSL_MAX_FRAG_LEN_4096: + return 4096; + default: + return ( MBEDTLS_TLS_EXT_ADV_CONTENT_LEN ); + } +} +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +int mbedtls_ssl_session_copy( mbedtls_ssl_session *dst, + const mbedtls_ssl_session *src ) +{ + mbedtls_ssl_session_free( dst ); + memcpy( dst, src, sizeof( mbedtls_ssl_session ) ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + if( src->peer_cert != NULL ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + dst->peer_cert = mbedtls_calloc( 1, sizeof(mbedtls_x509_crt) ); + if( dst->peer_cert == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + mbedtls_x509_crt_init( dst->peer_cert ); + + if( ( ret = mbedtls_x509_crt_parse_der( dst->peer_cert, src->peer_cert->raw.p, + src->peer_cert->raw.len ) ) != 0 ) + { + mbedtls_free( dst->peer_cert ); + dst->peer_cert = NULL; + return( ret ); + } + } +#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + if( src->peer_cert_digest != NULL ) + { + dst->peer_cert_digest = + mbedtls_calloc( 1, src->peer_cert_digest_len ); + if( dst->peer_cert_digest == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + memcpy( dst->peer_cert_digest, src->peer_cert_digest, + src->peer_cert_digest_len ); + dst->peer_cert_digest_type = src->peer_cert_digest_type; + dst->peer_cert_digest_len = src->peer_cert_digest_len; + } +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) + if( src->ticket != NULL ) + { + dst->ticket = mbedtls_calloc( 1, src->ticket_len ); + if( dst->ticket == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + memcpy( dst->ticket, src->ticket, src->ticket_len ); + } +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) +static int resize_buffer( unsigned char **buffer, size_t len_new, size_t *len_old ) +{ + unsigned char* resized_buffer = mbedtls_calloc( 1, len_new ); + if( resized_buffer == NULL ) + return -1; + + /* We want to copy len_new bytes when downsizing the buffer, and + * len_old bytes when upsizing, so we choose the smaller of two sizes, + * to fit one buffer into another. Size checks, ensuring that no data is + * lost, are done outside of this function. */ + memcpy( resized_buffer, *buffer, + ( len_new < *len_old ) ? len_new : *len_old ); + mbedtls_platform_zeroize( *buffer, *len_old ); + mbedtls_free( *buffer ); + + *buffer = resized_buffer; + *len_old = len_new; + + return 0; +} +#endif /* MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH */ + +/* + * Key material generation + */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) +static int ssl3_prf( const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ) +{ + int ret = 0; + size_t i; + mbedtls_md5_context md5; + mbedtls_sha1_context sha1; + unsigned char padding[16]; + unsigned char sha1sum[20]; + ((void)label); + + mbedtls_md5_init( &md5 ); + mbedtls_sha1_init( &sha1 ); + + /* + * SSLv3: + * block = + * MD5( secret + SHA1( 'A' + secret + random ) ) + + * MD5( secret + SHA1( 'BB' + secret + random ) ) + + * MD5( secret + SHA1( 'CCC' + secret + random ) ) + + * ... + */ + for( i = 0; i < dlen / 16; i++ ) + { + memset( padding, (unsigned char) ('A' + i), 1 + i ); + + if( ( ret = mbedtls_sha1_starts_ret( &sha1 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_sha1_update_ret( &sha1, padding, 1 + i ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_sha1_update_ret( &sha1, secret, slen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_sha1_update_ret( &sha1, random, rlen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_sha1_finish_ret( &sha1, sha1sum ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md5_starts_ret( &md5 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update_ret( &md5, secret, slen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update_ret( &md5, sha1sum, 20 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_finish_ret( &md5, dstbuf + i * 16 ) ) != 0 ) + goto exit; + } + +exit: + mbedtls_md5_free( &md5 ); + mbedtls_sha1_free( &sha1 ); + + mbedtls_platform_zeroize( padding, sizeof( padding ) ); + mbedtls_platform_zeroize( sha1sum, sizeof( sha1sum ) ); + + return( ret ); +} +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) +static int tls1_prf( const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ) +{ + size_t nb, hs; + size_t i, j, k; + const unsigned char *S1, *S2; + unsigned char *tmp; + size_t tmp_len = 0; + unsigned char h_i[20]; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + mbedtls_md_init( &md_ctx ); + + tmp_len = 20 + strlen( label ) + rlen; + tmp = mbedtls_calloc( 1, tmp_len ); + if( tmp == NULL ) + { + ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; + goto exit; + } + + hs = ( slen + 1 ) / 2; + S1 = secret; + S2 = secret + slen - hs; + + nb = strlen( label ); + memcpy( tmp + 20, label, nb ); + memcpy( tmp + 20 + nb, random, rlen ); + nb += rlen; + + /* + * First compute P_md5(secret,label+random)[0..dlen] + */ + if( ( md_info = mbedtls_md_info_from_type( MBEDTLS_MD_MD5 ) ) == NULL ) + { + ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; + goto exit; + } + + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 ) + { + goto exit; + } + + mbedtls_md_hmac_starts( &md_ctx, S1, hs ); + mbedtls_md_hmac_update( &md_ctx, tmp + 20, nb ); + mbedtls_md_hmac_finish( &md_ctx, 4 + tmp ); + + for( i = 0; i < dlen; i += 16 ) + { + mbedtls_md_hmac_reset ( &md_ctx ); + mbedtls_md_hmac_update( &md_ctx, 4 + tmp, 16 + nb ); + mbedtls_md_hmac_finish( &md_ctx, h_i ); + + mbedtls_md_hmac_reset ( &md_ctx ); + mbedtls_md_hmac_update( &md_ctx, 4 + tmp, 16 ); + mbedtls_md_hmac_finish( &md_ctx, 4 + tmp ); + + k = ( i + 16 > dlen ) ? dlen % 16 : 16; + + for( j = 0; j < k; j++ ) + dstbuf[i + j] = h_i[j]; + } + + mbedtls_md_free( &md_ctx ); + + /* + * XOR out with P_sha1(secret,label+random)[0..dlen] + */ + if( ( md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ) ) == NULL ) + { + ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; + goto exit; + } + + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 ) + { + goto exit; + } + + mbedtls_md_hmac_starts( &md_ctx, S2, hs ); + mbedtls_md_hmac_update( &md_ctx, tmp + 20, nb ); + mbedtls_md_hmac_finish( &md_ctx, tmp ); + + for( i = 0; i < dlen; i += 20 ) + { + mbedtls_md_hmac_reset ( &md_ctx ); + mbedtls_md_hmac_update( &md_ctx, tmp, 20 + nb ); + mbedtls_md_hmac_finish( &md_ctx, h_i ); + + mbedtls_md_hmac_reset ( &md_ctx ); + mbedtls_md_hmac_update( &md_ctx, tmp, 20 ); + mbedtls_md_hmac_finish( &md_ctx, tmp ); + + k = ( i + 20 > dlen ) ? dlen % 20 : 20; + + for( j = 0; j < k; j++ ) + dstbuf[i + j] = (unsigned char)( dstbuf[i + j] ^ h_i[j] ); + } + +exit: + mbedtls_md_free( &md_ctx ); + + mbedtls_platform_zeroize( tmp, tmp_len ); + mbedtls_platform_zeroize( h_i, sizeof( h_i ) ); + + mbedtls_free( tmp ); + return( ret ); +} +#endif /* MBEDTLS_SSL_PROTO_TLS1) || MBEDTLS_SSL_PROTO_TLS1_1 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + +static psa_status_t setup_psa_key_derivation( psa_key_derivation_operation_t* derivation, + psa_key_handle_t slot, + psa_algorithm_t alg, + const unsigned char* seed, size_t seed_length, + const unsigned char* label, size_t label_length, + size_t capacity ) +{ + psa_status_t status; + + status = psa_key_derivation_setup( derivation, alg ); + if( status != PSA_SUCCESS ) + return( status ); + + if( PSA_ALG_IS_TLS12_PRF( alg ) || PSA_ALG_IS_TLS12_PSK_TO_MS( alg ) ) + { + status = psa_key_derivation_input_bytes( derivation, + PSA_KEY_DERIVATION_INPUT_SEED, + seed, seed_length ); + if( status != PSA_SUCCESS ) + return( status ); + + if( slot == 0 ) + { + status = psa_key_derivation_input_bytes( + derivation, PSA_KEY_DERIVATION_INPUT_SECRET, + NULL, 0 ); + } + else + { + status = psa_key_derivation_input_key( + derivation, PSA_KEY_DERIVATION_INPUT_SECRET, + slot ); + } + if( status != PSA_SUCCESS ) + return( status ); + + status = psa_key_derivation_input_bytes( derivation, + PSA_KEY_DERIVATION_INPUT_LABEL, + label, label_length ); + if( status != PSA_SUCCESS ) + return( status ); + } + else + { + return( PSA_ERROR_NOT_SUPPORTED ); + } + + status = psa_key_derivation_set_capacity( derivation, capacity ); + if( status != PSA_SUCCESS ) + return( status ); + + return( PSA_SUCCESS ); +} + +static int tls_prf_generic( mbedtls_md_type_t md_type, + const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ) +{ + psa_status_t status; + psa_algorithm_t alg; + psa_key_handle_t master_slot = 0; + psa_key_derivation_operation_t derivation = + PSA_KEY_DERIVATION_OPERATION_INIT; + + if( md_type == MBEDTLS_MD_SHA384 ) + alg = PSA_ALG_TLS12_PRF(PSA_ALG_SHA_384); + else + alg = PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256); + + /* Normally a "secret" should be long enough to be impossible to + * find by brute force, and in particular should not be empty. But + * this PRF is also used to derive an IV, in particular in EAP-TLS, + * and for this use case it makes sense to have a 0-length "secret". + * Since the key API doesn't allow importing a key of length 0, + * keep master_slot=0, which setup_psa_key_derivation() understands + * to mean a 0-length "secret" input. */ + if( slen != 0 ) + { + psa_key_attributes_t key_attributes = psa_key_attributes_init(); + psa_set_key_usage_flags( &key_attributes, PSA_KEY_USAGE_DERIVE ); + psa_set_key_algorithm( &key_attributes, alg ); + psa_set_key_type( &key_attributes, PSA_KEY_TYPE_DERIVE ); + + status = psa_import_key( &key_attributes, secret, slen, &master_slot ); + if( status != PSA_SUCCESS ) + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + status = setup_psa_key_derivation( &derivation, + master_slot, alg, + random, rlen, + (unsigned char const *) label, + (size_t) strlen( label ), + dlen ); + if( status != PSA_SUCCESS ) + { + psa_key_derivation_abort( &derivation ); + psa_destroy_key( master_slot ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + status = psa_key_derivation_output_bytes( &derivation, dstbuf, dlen ); + if( status != PSA_SUCCESS ) + { + psa_key_derivation_abort( &derivation ); + psa_destroy_key( master_slot ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + status = psa_key_derivation_abort( &derivation ); + if( status != PSA_SUCCESS ) + { + psa_destroy_key( master_slot ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + if( master_slot != 0 ) + status = psa_destroy_key( master_slot ); + if( status != PSA_SUCCESS ) + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + + return( 0 ); +} + +#else /* MBEDTLS_USE_PSA_CRYPTO */ + +static int tls_prf_generic( mbedtls_md_type_t md_type, + const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ) +{ + size_t nb; + size_t i, j, k, md_len; + unsigned char *tmp; + size_t tmp_len = 0; + unsigned char h_i[MBEDTLS_MD_MAX_SIZE]; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + mbedtls_md_init( &md_ctx ); + + if( ( md_info = mbedtls_md_info_from_type( md_type ) ) == NULL ) + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + + md_len = mbedtls_md_get_size( md_info ); + + tmp_len = md_len + strlen( label ) + rlen; + tmp = mbedtls_calloc( 1, tmp_len ); + if( tmp == NULL ) + { + ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; + goto exit; + } + + nb = strlen( label ); + memcpy( tmp + md_len, label, nb ); + memcpy( tmp + md_len + nb, random, rlen ); + nb += rlen; + + /* + * Compute P_(secret, label + random)[0..dlen] + */ + if ( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 ) + goto exit; + + mbedtls_md_hmac_starts( &md_ctx, secret, slen ); + mbedtls_md_hmac_update( &md_ctx, tmp + md_len, nb ); + mbedtls_md_hmac_finish( &md_ctx, tmp ); + + for( i = 0; i < dlen; i += md_len ) + { + mbedtls_md_hmac_reset ( &md_ctx ); + mbedtls_md_hmac_update( &md_ctx, tmp, md_len + nb ); + mbedtls_md_hmac_finish( &md_ctx, h_i ); + + mbedtls_md_hmac_reset ( &md_ctx ); + mbedtls_md_hmac_update( &md_ctx, tmp, md_len ); + mbedtls_md_hmac_finish( &md_ctx, tmp ); + + k = ( i + md_len > dlen ) ? dlen % md_len : md_len; + + for( j = 0; j < k; j++ ) + dstbuf[i + j] = h_i[j]; + } + +exit: + mbedtls_md_free( &md_ctx ); + + mbedtls_platform_zeroize( tmp, tmp_len ); + mbedtls_platform_zeroize( h_i, sizeof( h_i ) ); + + mbedtls_free( tmp ); + + return( ret ); +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#if defined(MBEDTLS_SHA256_C) +static int tls_prf_sha256( const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ) +{ + return( tls_prf_generic( MBEDTLS_MD_SHA256, secret, slen, + label, random, rlen, dstbuf, dlen ) ); +} +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) +static int tls_prf_sha384( const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ) +{ + return( tls_prf_generic( MBEDTLS_MD_SHA384, secret, slen, + label, random, rlen, dstbuf, dlen ) ); +} +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +static void ssl_update_checksum_start( mbedtls_ssl_context *, const unsigned char *, size_t ); + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) +static void ssl_update_checksum_md5sha1( mbedtls_ssl_context *, const unsigned char *, size_t ); +#endif + +#if defined(MBEDTLS_SSL_PROTO_SSL3) +static void ssl_calc_verify_ssl( const mbedtls_ssl_context *, unsigned char *, size_t * ); +static void ssl_calc_finished_ssl( mbedtls_ssl_context *, unsigned char *, int ); +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) +static void ssl_calc_verify_tls( const mbedtls_ssl_context *, unsigned char *, size_t * ); +static void ssl_calc_finished_tls( mbedtls_ssl_context *, unsigned char *, int ); +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) +static void ssl_update_checksum_sha256( mbedtls_ssl_context *, const unsigned char *, size_t ); +static void ssl_calc_verify_tls_sha256( const mbedtls_ssl_context *,unsigned char *, size_t * ); +static void ssl_calc_finished_tls_sha256( mbedtls_ssl_context *,unsigned char *, int ); +#endif + +#if defined(MBEDTLS_SHA512_C) +static void ssl_update_checksum_sha384( mbedtls_ssl_context *, const unsigned char *, size_t ); +static void ssl_calc_verify_tls_sha384( const mbedtls_ssl_context *, unsigned char *, size_t * ); +static void ssl_calc_finished_tls_sha384( mbedtls_ssl_context *, unsigned char *, int ); +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) && \ + defined(MBEDTLS_USE_PSA_CRYPTO) +static int ssl_use_opaque_psk( mbedtls_ssl_context const *ssl ) +{ + if( ssl->conf->f_psk != NULL ) + { + /* If we've used a callback to select the PSK, + * the static configuration is irrelevant. */ + if( ssl->handshake->psk_opaque != 0 ) + return( 1 ); + + return( 0 ); + } + + if( ssl->conf->psk_opaque != 0 ) + return( 1 ); + + return( 0 ); +} +#endif /* MBEDTLS_USE_PSA_CRYPTO && + MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ + +#if defined(MBEDTLS_SSL_EXPORT_KEYS) +static mbedtls_tls_prf_types tls_prf_get_type( mbedtls_ssl_tls_prf_cb *tls_prf ) +{ +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( tls_prf == ssl3_prf ) + { + return( MBEDTLS_SSL_TLS_PRF_SSL3 ); + } + else +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( tls_prf == tls1_prf ) + { + return( MBEDTLS_SSL_TLS_PRF_TLS1 ); + } + else +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA512_C) + if( tls_prf == tls_prf_sha384 ) + { + return( MBEDTLS_SSL_TLS_PRF_SHA384 ); + } + else +#endif +#if defined(MBEDTLS_SHA256_C) + if( tls_prf == tls_prf_sha256 ) + { + return( MBEDTLS_SSL_TLS_PRF_SHA256 ); + } + else +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + return( MBEDTLS_SSL_TLS_PRF_NONE ); +} +#endif /* MBEDTLS_SSL_EXPORT_KEYS */ + +int mbedtls_ssl_tls_prf( const mbedtls_tls_prf_types prf, + const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ) +{ + mbedtls_ssl_tls_prf_cb *tls_prf = NULL; + + switch( prf ) + { +#if defined(MBEDTLS_SSL_PROTO_SSL3) + case MBEDTLS_SSL_TLS_PRF_SSL3: + tls_prf = ssl3_prf; + break; +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) + case MBEDTLS_SSL_TLS_PRF_TLS1: + tls_prf = tls1_prf; + break; +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_SSL_TLS_PRF_SHA384: + tls_prf = tls_prf_sha384; + break; +#endif /* MBEDTLS_SHA512_C */ +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_SSL_TLS_PRF_SHA256: + tls_prf = tls_prf_sha256; + break; +#endif /* MBEDTLS_SHA256_C */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + default: + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + + return( tls_prf( secret, slen, label, random, rlen, dstbuf, dlen ) ); +} + +/* Type for the TLS PRF */ +typedef int ssl_tls_prf_t(const unsigned char *, size_t, const char *, + const unsigned char *, size_t, + unsigned char *, size_t); + +/* + * Populate a transform structure with session keys and all the other + * necessary information. + * + * Parameters: + * - [in/out]: transform: structure to populate + * [in] must be just initialised with mbedtls_ssl_transform_init() + * [out] fully populated, ready for use by mbedtls_ssl_{en,de}crypt_buf() + * - [in] ciphersuite + * - [in] master + * - [in] encrypt_then_mac + * - [in] trunc_hmac + * - [in] compression + * - [in] tls_prf: pointer to PRF to use for key derivation + * - [in] randbytes: buffer holding ServerHello.random + ClientHello.random + * - [in] minor_ver: SSL/TLS minor version + * - [in] endpoint: client or server + * - [in] ssl: optionally used for: + * - MBEDTLS_SSL_HW_RECORD_ACCEL: whole context (non-const) + * - MBEDTLS_SSL_EXPORT_KEYS: ssl->conf->{f,p}_export_keys + * - MBEDTLS_DEBUG_C: ssl->conf->{f,p}_dbg + */ +static int ssl_populate_transform( mbedtls_ssl_transform *transform, + int ciphersuite, + const unsigned char master[48], +#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + int encrypt_then_mac, +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + int trunc_hmac, +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ +#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */ +#if defined(MBEDTLS_ZLIB_SUPPORT) + int compression, +#endif + ssl_tls_prf_t tls_prf, + const unsigned char randbytes[64], + int minor_ver, + unsigned endpoint, +#if !defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + const +#endif + mbedtls_ssl_context *ssl ) +{ + int ret = 0; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + int psa_fallthrough; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + unsigned char keyblk[256]; + unsigned char *key1; + unsigned char *key2; + unsigned char *mac_enc; + unsigned char *mac_dec; + size_t mac_key_len = 0; + size_t iv_copy_len; + unsigned keylen; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + const mbedtls_cipher_info_t *cipher_info; + const mbedtls_md_info_t *md_info; + +#if !defined(MBEDTLS_SSL_HW_RECORD_ACCEL) && \ + !defined(MBEDTLS_SSL_EXPORT_KEYS) && \ + !defined(MBEDTLS_DEBUG_C) + ssl = NULL; /* make sure we don't use it except for those cases */ + (void) ssl; +#endif + + /* + * Some data just needs copying into the structure + */ +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) && \ + defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) + transform->encrypt_then_mac = encrypt_then_mac; +#endif + transform->minor_ver = minor_ver; + +#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) + memcpy( transform->randbytes, randbytes, sizeof( transform->randbytes ) ); +#endif + + /* + * Get various info structures + */ + ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( ciphersuite ); + if( ciphersuite_info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "ciphersuite info for %d not found", + ciphersuite ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + cipher_info = mbedtls_cipher_info_from_type( ciphersuite_info->cipher ); + if( cipher_info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "cipher info for %d not found", + ciphersuite_info->cipher ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + md_info = mbedtls_md_info_from_type( ciphersuite_info->mac ); + if( md_info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "mbedtls_md info for %d not found", + ciphersuite_info->mac ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + /* Copy own and peer's CID if the use of the CID + * extension has been negotiated. */ + if( ssl->handshake->cid_in_use == MBEDTLS_SSL_CID_ENABLED ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Copy CIDs into SSL transform" ) ); + + transform->in_cid_len = ssl->own_cid_len; + memcpy( transform->in_cid, ssl->own_cid, ssl->own_cid_len ); + MBEDTLS_SSL_DEBUG_BUF( 3, "Incoming CID", transform->in_cid, + transform->in_cid_len ); + + transform->out_cid_len = ssl->handshake->peer_cid_len; + memcpy( transform->out_cid, ssl->handshake->peer_cid, + ssl->handshake->peer_cid_len ); + MBEDTLS_SSL_DEBUG_BUF( 3, "Outgoing CID", transform->out_cid, + transform->out_cid_len ); + } +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + + /* + * Compute key block using the PRF + */ + ret = tls_prf( master, 48, "key expansion", randbytes, 64, keyblk, 256 ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "prf", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite = %s", + mbedtls_ssl_get_ciphersuite_name( ciphersuite ) ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "master secret", master, 48 ); + MBEDTLS_SSL_DEBUG_BUF( 4, "random bytes", randbytes, 64 ); + MBEDTLS_SSL_DEBUG_BUF( 4, "key block", keyblk, 256 ); + + /* + * Determine the appropriate key, IV and MAC length. + */ + + keylen = cipher_info->key_bitlen / 8; + +#if defined(MBEDTLS_GCM_C) || \ + defined(MBEDTLS_CCM_C) || \ + defined(MBEDTLS_CHACHAPOLY_C) + if( cipher_info->mode == MBEDTLS_MODE_GCM || + cipher_info->mode == MBEDTLS_MODE_CCM || + cipher_info->mode == MBEDTLS_MODE_CHACHAPOLY ) + { + size_t explicit_ivlen; + + transform->maclen = 0; + mac_key_len = 0; + transform->taglen = + ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16; + + /* All modes haves 96-bit IVs, but the length of the static parts vary + * with mode and version: + * - For GCM and CCM in TLS 1.2, there's a static IV of 4 Bytes + * (to be concatenated with a dynamically chosen IV of 8 Bytes) + * - For ChaChaPoly in TLS 1.2, and all modes in TLS 1.3, there's + * a static IV of 12 Bytes (to be XOR'ed with the 8 Byte record + * sequence number). + */ + transform->ivlen = 12; +#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL) + if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_4 ) + { + transform->fixed_ivlen = 12; + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */ + { + if( cipher_info->mode == MBEDTLS_MODE_CHACHAPOLY ) + transform->fixed_ivlen = 12; + else + transform->fixed_ivlen = 4; + } + + /* Minimum length of encrypted record */ + explicit_ivlen = transform->ivlen - transform->fixed_ivlen; + transform->minlen = explicit_ivlen + transform->taglen; + } + else +#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C || MBEDTLS_CHACHAPOLY_C */ +#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) + if( cipher_info->mode == MBEDTLS_MODE_STREAM || + cipher_info->mode == MBEDTLS_MODE_CBC ) + { + /* Initialize HMAC contexts */ + if( ( ret = mbedtls_md_setup( &transform->md_ctx_enc, md_info, 1 ) ) != 0 || + ( ret = mbedtls_md_setup( &transform->md_ctx_dec, md_info, 1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_setup", ret ); + goto end; + } + + /* Get MAC length */ + mac_key_len = mbedtls_md_get_size( md_info ); + transform->maclen = mac_key_len; + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + /* + * If HMAC is to be truncated, we shall keep the leftmost bytes, + * (rfc 6066 page 13 or rfc 2104 section 4), + * so we only need to adjust the length here. + */ + if( trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_ENABLED ) + { + transform->maclen = MBEDTLS_SSL_TRUNCATED_HMAC_LEN; + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT) + /* Fall back to old, non-compliant version of the truncated + * HMAC implementation which also truncates the key + * (Mbed TLS versions from 1.3 to 2.6.0) */ + mac_key_len = transform->maclen; +#endif + } +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + + /* IV length */ + transform->ivlen = cipher_info->iv_size; + + /* Minimum length */ + if( cipher_info->mode == MBEDTLS_MODE_STREAM ) + transform->minlen = transform->maclen; + else + { + /* + * GenericBlockCipher: + * 1. if EtM is in use: one block plus MAC + * otherwise: * first multiple of blocklen greater than maclen + * 2. IV except for SSL3 and TLS 1.0 + */ +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + if( encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED ) + { + transform->minlen = transform->maclen + + cipher_info->block_size; + } + else +#endif + { + transform->minlen = transform->maclen + + cipher_info->block_size + - transform->maclen % cipher_info->block_size; + } + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) + if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 || + minor_ver == MBEDTLS_SSL_MINOR_VERSION_1 ) + ; /* No need to adjust minlen */ + else +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_2 || + minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + transform->minlen += transform->ivlen; + } + else +#endif + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; + goto end; + } + } + } + else +#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "keylen: %u, minlen: %u, ivlen: %u, maclen: %u", + (unsigned) keylen, + (unsigned) transform->minlen, + (unsigned) transform->ivlen, + (unsigned) transform->maclen ) ); + + /* + * Finally setup the cipher contexts, IVs and MAC secrets. + */ +#if defined(MBEDTLS_SSL_CLI_C) + if( endpoint == MBEDTLS_SSL_IS_CLIENT ) + { + key1 = keyblk + mac_key_len * 2; + key2 = keyblk + mac_key_len * 2 + keylen; + + mac_enc = keyblk; + mac_dec = keyblk + mac_key_len; + + /* + * This is not used in TLS v1.1. + */ + iv_copy_len = ( transform->fixed_ivlen ) ? + transform->fixed_ivlen : transform->ivlen; + memcpy( transform->iv_enc, key2 + keylen, iv_copy_len ); + memcpy( transform->iv_dec, key2 + keylen + iv_copy_len, + iv_copy_len ); + } + else +#endif /* MBEDTLS_SSL_CLI_C */ +#if defined(MBEDTLS_SSL_SRV_C) + if( endpoint == MBEDTLS_SSL_IS_SERVER ) + { + key1 = keyblk + mac_key_len * 2 + keylen; + key2 = keyblk + mac_key_len * 2; + + mac_enc = keyblk + mac_key_len; + mac_dec = keyblk; + + /* + * This is not used in TLS v1.1. + */ + iv_copy_len = ( transform->fixed_ivlen ) ? + transform->fixed_ivlen : transform->ivlen; + memcpy( transform->iv_dec, key1 + keylen, iv_copy_len ); + memcpy( transform->iv_enc, key1 + keylen + iv_copy_len, + iv_copy_len ); + } + else +#endif /* MBEDTLS_SSL_SRV_C */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; + goto end; + } + +#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + if( mac_key_len > sizeof( transform->mac_enc ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; + goto end; + } + + memcpy( transform->mac_enc, mac_enc, mac_key_len ); + memcpy( transform->mac_dec, mac_dec, mac_key_len ); + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 ) + { + /* For HMAC-based ciphersuites, initialize the HMAC transforms. + For AEAD-based ciphersuites, there is nothing to do here. */ + if( mac_key_len != 0 ) + { + mbedtls_md_hmac_starts( &transform->md_ctx_enc, mac_enc, mac_key_len ); + mbedtls_md_hmac_starts( &transform->md_ctx_dec, mac_dec, mac_key_len ); + } + } + else +#endif + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; + goto end; + } +#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */ + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_init != NULL ) + { + ret = 0; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_init()" ) ); + + if( ( ret = mbedtls_ssl_hw_record_init( ssl, key1, key2, keylen, + transform->iv_enc, transform->iv_dec, + iv_copy_len, + mac_enc, mac_dec, + mac_key_len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_init", ret ); + ret = MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; + goto end; + } + } +#else + ((void) mac_dec); + ((void) mac_enc); +#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ + +#if defined(MBEDTLS_SSL_EXPORT_KEYS) + if( ssl->conf->f_export_keys != NULL ) + { + ssl->conf->f_export_keys( ssl->conf->p_export_keys, + master, keyblk, + mac_key_len, keylen, + iv_copy_len ); + } + + if( ssl->conf->f_export_keys_ext != NULL ) + { + ssl->conf->f_export_keys_ext( ssl->conf->p_export_keys, + master, keyblk, + mac_key_len, keylen, + iv_copy_len, + randbytes + 32, + randbytes, + tls_prf_get_type( tls_prf ) ); + } +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + + /* Only use PSA-based ciphers for TLS-1.2. + * That's relevant at least for TLS-1.0, where + * we assume that mbedtls_cipher_crypt() updates + * the structure field for the IV, which the PSA-based + * implementation currently doesn't. */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + ret = mbedtls_cipher_setup_psa( &transform->cipher_ctx_enc, + cipher_info, transform->taglen ); + if( ret != 0 && ret != MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup_psa", ret ); + goto end; + } + + if( ret == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Successfully setup PSA-based encryption cipher context" ) ); + psa_fallthrough = 0; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Failed to setup PSA-based cipher context for record encryption - fall through to default setup." ) ); + psa_fallthrough = 1; + } + } + else + psa_fallthrough = 1; +#else + psa_fallthrough = 1; +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + if( psa_fallthrough == 1 ) +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + if( ( ret = mbedtls_cipher_setup( &transform->cipher_ctx_enc, + cipher_info ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup", ret ); + goto end; + } + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + /* Only use PSA-based ciphers for TLS-1.2. + * That's relevant at least for TLS-1.0, where + * we assume that mbedtls_cipher_crypt() updates + * the structure field for the IV, which the PSA-based + * implementation currently doesn't. */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + ret = mbedtls_cipher_setup_psa( &transform->cipher_ctx_dec, + cipher_info, transform->taglen ); + if( ret != 0 && ret != MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup_psa", ret ); + goto end; + } + + if( ret == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Successfully setup PSA-based decryption cipher context" ) ); + psa_fallthrough = 0; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Failed to setup PSA-based cipher context for record decryption - fall through to default setup." ) ); + psa_fallthrough = 1; + } + } + else + psa_fallthrough = 1; +#else + psa_fallthrough = 1; +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + if( psa_fallthrough == 1 ) +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + if( ( ret = mbedtls_cipher_setup( &transform->cipher_ctx_dec, + cipher_info ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup", ret ); + goto end; + } + + if( ( ret = mbedtls_cipher_setkey( &transform->cipher_ctx_enc, key1, + cipher_info->key_bitlen, + MBEDTLS_ENCRYPT ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setkey", ret ); + goto end; + } + + if( ( ret = mbedtls_cipher_setkey( &transform->cipher_ctx_dec, key2, + cipher_info->key_bitlen, + MBEDTLS_DECRYPT ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setkey", ret ); + goto end; + } + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + if( cipher_info->mode == MBEDTLS_MODE_CBC ) + { + if( ( ret = mbedtls_cipher_set_padding_mode( &transform->cipher_ctx_enc, + MBEDTLS_PADDING_NONE ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_set_padding_mode", ret ); + goto end; + } + + if( ( ret = mbedtls_cipher_set_padding_mode( &transform->cipher_ctx_dec, + MBEDTLS_PADDING_NONE ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_set_padding_mode", ret ); + goto end; + } + } +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + + + /* Initialize Zlib contexts */ +#if defined(MBEDTLS_ZLIB_SUPPORT) + if( compression == MBEDTLS_SSL_COMPRESS_DEFLATE ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Initializing zlib states" ) ); + + memset( &transform->ctx_deflate, 0, sizeof( transform->ctx_deflate ) ); + memset( &transform->ctx_inflate, 0, sizeof( transform->ctx_inflate ) ); + + if( deflateInit( &transform->ctx_deflate, + Z_DEFAULT_COMPRESSION ) != Z_OK || + inflateInit( &transform->ctx_inflate ) != Z_OK ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Failed to initialize compression" ) ); + ret = MBEDTLS_ERR_SSL_COMPRESSION_FAILED; + goto end; + } + } +#endif /* MBEDTLS_ZLIB_SUPPORT */ + +end: + mbedtls_platform_zeroize( keyblk, sizeof( keyblk ) ); + return( ret ); +} + +/* + * Set appropriate PRF function and other SSL / TLS 1.0/1.1 / TLS1.2 functions + * + * Inputs: + * - SSL/TLS minor version + * - hash associated with the ciphersuite (only used by TLS 1.2) + * + * Outputs: + * - the tls_prf, calc_verify and calc_finished members of handshake structure + */ +static int ssl_set_handshake_prfs( mbedtls_ssl_handshake_params *handshake, + int minor_ver, + mbedtls_md_type_t hash ) +{ +#if !defined(MBEDTLS_SSL_PROTO_TLS1_2) || !defined(MBEDTLS_SHA512_C) + (void) hash; +#endif + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + handshake->tls_prf = ssl3_prf; + handshake->calc_verify = ssl_calc_verify_ssl; + handshake->calc_finished = ssl_calc_finished_ssl; + } + else +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 ) + { + handshake->tls_prf = tls1_prf; + handshake->calc_verify = ssl_calc_verify_tls; + handshake->calc_finished = ssl_calc_finished_tls; + } + else +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA512_C) + if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 && + hash == MBEDTLS_MD_SHA384 ) + { + handshake->tls_prf = tls_prf_sha384; + handshake->calc_verify = ssl_calc_verify_tls_sha384; + handshake->calc_finished = ssl_calc_finished_tls_sha384; + } + else +#endif +#if defined(MBEDTLS_SHA256_C) + if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + handshake->tls_prf = tls_prf_sha256; + handshake->calc_verify = ssl_calc_verify_tls_sha256; + handshake->calc_finished = ssl_calc_finished_tls_sha256; + } + else +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + { + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + return( 0 ); +} + +/* + * Compute master secret if needed + * + * Parameters: + * [in/out] handshake + * [in] resume, premaster, extended_ms, calc_verify, tls_prf + * (PSA-PSK) ciphersuite_info, psk_opaque + * [out] premaster (cleared) + * [out] master + * [in] ssl: optionally used for debugging, EMS and PSA-PSK + * debug: conf->f_dbg, conf->p_dbg + * EMS: passed to calc_verify (debug + (SSL3) session_negotiate) + * PSA-PSA: minor_ver, conf + */ +static int ssl_compute_master( mbedtls_ssl_handshake_params *handshake, + unsigned char *master, + const mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* cf. RFC 5246, Section 8.1: + * "The master secret is always exactly 48 bytes in length." */ + size_t const master_secret_len = 48; + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + unsigned char session_hash[48]; +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + + /* The label for the KDF used for key expansion. + * This is either "master secret" or "extended master secret" + * depending on whether the Extended Master Secret extension + * is used. */ + char const *lbl = "master secret"; + + /* The salt for the KDF used for key expansion. + * - If the Extended Master Secret extension is not used, + * this is ClientHello.Random + ServerHello.Random + * (see Sect. 8.1 in RFC 5246). + * - If the Extended Master Secret extension is used, + * this is the transcript of the handshake so far. + * (see Sect. 4 in RFC 7627). */ + unsigned char const *salt = handshake->randbytes; + size_t salt_len = 64; + +#if !defined(MBEDTLS_DEBUG_C) && \ + !defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) && \ + !(defined(MBEDTLS_USE_PSA_CRYPTO) && \ + defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)) + ssl = NULL; /* make sure we don't use it except for those cases */ + (void) ssl; +#endif + + if( handshake->resume != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "no premaster (session resumed)" ) ); + return( 0 ); + } + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + if( handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED ) + { + lbl = "extended master secret"; + salt = session_hash; + handshake->calc_verify( ssl, session_hash, &salt_len ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "session hash for extended master secret", + session_hash, salt_len ); + } +#endif /* MBEDTLS_SSL_EXTENDED_MS_ENABLED */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) && \ + defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + if( handshake->ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK && + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 && + ssl_use_opaque_psk( ssl ) == 1 ) + { + /* Perform PSK-to-MS expansion in a single step. */ + psa_status_t status; + psa_algorithm_t alg; + psa_key_handle_t psk; + psa_key_derivation_operation_t derivation = + PSA_KEY_DERIVATION_OPERATION_INIT; + mbedtls_md_type_t hash_alg = handshake->ciphersuite_info->mac; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "perform PSA-based PSK-to-MS expansion" ) ); + + psk = mbedtls_ssl_get_opaque_psk( ssl ); + + if( hash_alg == MBEDTLS_MD_SHA384 ) + alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_384); + else + alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256); + + status = setup_psa_key_derivation( &derivation, psk, alg, + salt, salt_len, + (unsigned char const *) lbl, + (size_t) strlen( lbl ), + master_secret_len ); + if( status != PSA_SUCCESS ) + { + psa_key_derivation_abort( &derivation ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + status = psa_key_derivation_output_bytes( &derivation, + master, + master_secret_len ); + if( status != PSA_SUCCESS ) + { + psa_key_derivation_abort( &derivation ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + status = psa_key_derivation_abort( &derivation ); + if( status != PSA_SUCCESS ) + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + else +#endif + { + ret = handshake->tls_prf( handshake->premaster, handshake->pmslen, + lbl, salt, salt_len, + master, + master_secret_len ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "prf", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "premaster secret", + handshake->premaster, + handshake->pmslen ); + + mbedtls_platform_zeroize( handshake->premaster, + sizeof(handshake->premaster) ); + } + + return( 0 ); +} + +int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const mbedtls_ssl_ciphersuite_t * const ciphersuite_info = + ssl->handshake->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> derive keys" ) ); + + /* Set PRF, calc_verify and calc_finished function pointers */ + ret = ssl_set_handshake_prfs( ssl->handshake, + ssl->minor_ver, + ciphersuite_info->mac ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_set_handshake_prfs", ret ); + return( ret ); + } + + /* Compute master secret if needed */ + ret = ssl_compute_master( ssl->handshake, + ssl->session_negotiate->master, + ssl ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_compute_master", ret ); + return( ret ); + } + + /* Swap the client and server random values: + * - MS derivation wanted client+server (RFC 5246 8.1) + * - key derivation wants server+client (RFC 5246 6.3) */ + { + unsigned char tmp[64]; + memcpy( tmp, ssl->handshake->randbytes, 64 ); + memcpy( ssl->handshake->randbytes, tmp + 32, 32 ); + memcpy( ssl->handshake->randbytes + 32, tmp, 32 ); + mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); + } + + /* Populate transform structure */ + ret = ssl_populate_transform( ssl->transform_negotiate, + ssl->session_negotiate->ciphersuite, + ssl->session_negotiate->master, +#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + ssl->session_negotiate->encrypt_then_mac, +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + ssl->session_negotiate->trunc_hmac, +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ +#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */ +#if defined(MBEDTLS_ZLIB_SUPPORT) + ssl->session_negotiate->compression, +#endif + ssl->handshake->tls_prf, + ssl->handshake->randbytes, + ssl->minor_ver, + ssl->conf->endpoint, + ssl ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_populate_transform", ret ); + return( ret ); + } + + /* We no longer need Server/ClientHello.random values */ + mbedtls_platform_zeroize( ssl->handshake->randbytes, + sizeof( ssl->handshake->randbytes ) ); + + /* Allocate compression buffer */ +#if defined(MBEDTLS_ZLIB_SUPPORT) + if( ssl->session_negotiate->compression == MBEDTLS_SSL_COMPRESS_DEFLATE && + ssl->compress_buf == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Allocating compression buffer" ) ); + ssl->compress_buf = mbedtls_calloc( 1, MBEDTLS_SSL_COMPRESS_BUFFER_LEN ); + if( ssl->compress_buf == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", + MBEDTLS_SSL_COMPRESS_BUFFER_LEN ) ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + } +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= derive keys" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_PROTO_SSL3) +void ssl_calc_verify_ssl( const mbedtls_ssl_context *ssl, + unsigned char hash[36], + size_t *hlen ) +{ + mbedtls_md5_context md5; + mbedtls_sha1_context sha1; + unsigned char pad_1[48]; + unsigned char pad_2[48]; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc verify ssl" ) ); + + mbedtls_md5_init( &md5 ); + mbedtls_sha1_init( &sha1 ); + + mbedtls_md5_clone( &md5, &ssl->handshake->fin_md5 ); + mbedtls_sha1_clone( &sha1, &ssl->handshake->fin_sha1 ); + + memset( pad_1, 0x36, 48 ); + memset( pad_2, 0x5C, 48 ); + + mbedtls_md5_update_ret( &md5, ssl->session_negotiate->master, 48 ); + mbedtls_md5_update_ret( &md5, pad_1, 48 ); + mbedtls_md5_finish_ret( &md5, hash ); + + mbedtls_md5_starts_ret( &md5 ); + mbedtls_md5_update_ret( &md5, ssl->session_negotiate->master, 48 ); + mbedtls_md5_update_ret( &md5, pad_2, 48 ); + mbedtls_md5_update_ret( &md5, hash, 16 ); + mbedtls_md5_finish_ret( &md5, hash ); + + mbedtls_sha1_update_ret( &sha1, ssl->session_negotiate->master, 48 ); + mbedtls_sha1_update_ret( &sha1, pad_1, 40 ); + mbedtls_sha1_finish_ret( &sha1, hash + 16 ); + + mbedtls_sha1_starts_ret( &sha1 ); + mbedtls_sha1_update_ret( &sha1, ssl->session_negotiate->master, 48 ); + mbedtls_sha1_update_ret( &sha1, pad_2, 40 ); + mbedtls_sha1_update_ret( &sha1, hash + 16, 20 ); + mbedtls_sha1_finish_ret( &sha1, hash + 16 ); + + *hlen = 36; + + MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, *hlen ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); + + mbedtls_md5_free( &md5 ); + mbedtls_sha1_free( &sha1 ); + + return; +} +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) +void ssl_calc_verify_tls( const mbedtls_ssl_context *ssl, + unsigned char hash[36], + size_t *hlen ) +{ + mbedtls_md5_context md5; + mbedtls_sha1_context sha1; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc verify tls" ) ); + + mbedtls_md5_init( &md5 ); + mbedtls_sha1_init( &sha1 ); + + mbedtls_md5_clone( &md5, &ssl->handshake->fin_md5 ); + mbedtls_sha1_clone( &sha1, &ssl->handshake->fin_sha1 ); + + mbedtls_md5_finish_ret( &md5, hash ); + mbedtls_sha1_finish_ret( &sha1, hash + 16 ); + + *hlen = 36; + + MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, *hlen ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); + + mbedtls_md5_free( &md5 ); + mbedtls_sha1_free( &sha1 ); + + return; +} +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) +void ssl_calc_verify_tls_sha256( const mbedtls_ssl_context *ssl, + unsigned char hash[32], + size_t *hlen ) +{ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + size_t hash_size; + psa_status_t status; + psa_hash_operation_t sha256_psa = psa_hash_operation_init(); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> PSA calc verify sha256" ) ); + status = psa_hash_clone( &ssl->handshake->fin_sha256_psa, &sha256_psa ); + if( status != PSA_SUCCESS ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "PSA hash clone failed" ) ); + return; + } + + status = psa_hash_finish( &sha256_psa, hash, 32, &hash_size ); + if( status != PSA_SUCCESS ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "PSA hash finish failed" ) ); + return; + } + + *hlen = 32; + MBEDTLS_SSL_DEBUG_BUF( 3, "PSA calculated verify result", hash, *hlen ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= PSA calc verify" ) ); +#else + mbedtls_sha256_context sha256; + + mbedtls_sha256_init( &sha256 ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc verify sha256" ) ); + + mbedtls_sha256_clone( &sha256, &ssl->handshake->fin_sha256 ); + mbedtls_sha256_finish_ret( &sha256, hash ); + + *hlen = 32; + + MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, *hlen ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); + + mbedtls_sha256_free( &sha256 ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + return; +} +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) +void ssl_calc_verify_tls_sha384( const mbedtls_ssl_context *ssl, + unsigned char hash[48], + size_t *hlen ) +{ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + size_t hash_size; + psa_status_t status; + psa_hash_operation_t sha384_psa = psa_hash_operation_init(); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> PSA calc verify sha384" ) ); + status = psa_hash_clone( &ssl->handshake->fin_sha384_psa, &sha384_psa ); + if( status != PSA_SUCCESS ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "PSA hash clone failed" ) ); + return; + } + + status = psa_hash_finish( &sha384_psa, hash, 48, &hash_size ); + if( status != PSA_SUCCESS ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "PSA hash finish failed" ) ); + return; + } + + *hlen = 48; + MBEDTLS_SSL_DEBUG_BUF( 3, "PSA calculated verify result", hash, *hlen ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= PSA calc verify" ) ); +#else + mbedtls_sha512_context sha512; + + mbedtls_sha512_init( &sha512 ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc verify sha384" ) ); + + mbedtls_sha512_clone( &sha512, &ssl->handshake->fin_sha512 ); + mbedtls_sha512_finish_ret( &sha512, hash ); + + *hlen = 48; + + MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, *hlen ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); + + mbedtls_sha512_free( &sha512 ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + return; +} +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) +int mbedtls_ssl_psk_derive_premaster( mbedtls_ssl_context *ssl, mbedtls_key_exchange_type_t key_ex ) +{ + unsigned char *p = ssl->handshake->premaster; + unsigned char *end = p + sizeof( ssl->handshake->premaster ); + const unsigned char *psk = NULL; + size_t psk_len = 0; + + if( mbedtls_ssl_get_psk( ssl, &psk, &psk_len ) + == MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ) + { + /* + * This should never happen because the existence of a PSK is always + * checked before calling this function + */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* + * PMS = struct { + * opaque other_secret<0..2^16-1>; + * opaque psk<0..2^16-1>; + * }; + * with "other_secret" depending on the particular key exchange + */ +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + if( key_ex == MBEDTLS_KEY_EXCHANGE_PSK ) + { + if( end - p < 2 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + *(p++) = (unsigned char)( psk_len >> 8 ); + *(p++) = (unsigned char)( psk_len ); + + if( end < p || (size_t)( end - p ) < psk_len ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + memset( p, 0, psk_len ); + p += psk_len; + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + if( key_ex == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) + { + /* + * other_secret already set by the ClientKeyExchange message, + * and is 48 bytes long + */ + if( end - p < 2 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + *p++ = 0; + *p++ = 48; + p += 48; + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + if( key_ex == MBEDTLS_KEY_EXCHANGE_DHE_PSK ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + /* Write length only when we know the actual value */ + if( ( ret = mbedtls_dhm_calc_secret( &ssl->handshake->dhm_ctx, + p + 2, end - ( p + 2 ), &len, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_calc_secret", ret ); + return( ret ); + } + *(p++) = (unsigned char)( len >> 8 ); + *(p++) = (unsigned char)( len ); + p += len; + + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + if( key_ex == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t zlen; + + if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx, &zlen, + p + 2, end - ( p + 2 ), + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret ); + return( ret ); + } + + *(p++) = (unsigned char)( zlen >> 8 ); + *(p++) = (unsigned char)( zlen ); + p += zlen; + + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_Z ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* opaque psk<0..2^16-1>; */ + if( end - p < 2 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + *(p++) = (unsigned char)( psk_len >> 8 ); + *(p++) = (unsigned char)( psk_len ); + + if( end < p || (size_t)( end - p ) < psk_len ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + memcpy( p, psk, psk_len ); + p += psk_len; + + ssl->handshake->pmslen = p - ssl->handshake->premaster; + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ + +#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION) +static int ssl_write_hello_request( mbedtls_ssl_context *ssl ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +int mbedtls_ssl_resend_hello_request( mbedtls_ssl_context *ssl ) +{ + /* If renegotiation is not enforced, retransmit until we would reach max + * timeout if we were using the usual handshake doubling scheme */ + if( ssl->conf->renego_max_records < 0 ) + { + uint32_t ratio = ssl->conf->hs_timeout_max / ssl->conf->hs_timeout_min + 1; + unsigned char doublings = 1; + + while( ratio != 0 ) + { + ++doublings; + ratio >>= 1; + } + + if( ++ssl->renego_records_seen > doublings ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "no longer retransmitting hello request" ) ); + return( 0 ); + } + } + + return( ssl_write_hello_request( ssl ) ); +} +#endif +#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +static void ssl_clear_peer_cert( mbedtls_ssl_session *session ) +{ +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + if( session->peer_cert != NULL ) + { + mbedtls_x509_crt_free( session->peer_cert ); + mbedtls_free( session->peer_cert ); + session->peer_cert = NULL; + } +#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + if( session->peer_cert_digest != NULL ) + { + /* Zeroization is not necessary. */ + mbedtls_free( session->peer_cert_digest ); + session->peer_cert_digest = NULL; + session->peer_cert_digest_type = MBEDTLS_MD_NONE; + session->peer_cert_digest_len = 0; + } +#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +/* + * Handshake functions + */ +#if !defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) +/* No certificate support -> dummy functions */ +int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate" ) ); + + if( !mbedtls_ssl_ciphersuite_uses_srv_cert( ciphersuite_info ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) ); + ssl->state++; + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); +} + +int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) ); + + if( !mbedtls_ssl_ciphersuite_uses_srv_cert( ciphersuite_info ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); + ssl->state++; + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); +} + +#else /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ +/* Some certificate support -> implement write and parse */ + +int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + size_t i, n; + const mbedtls_x509_crt *crt; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate" ) ); + + if( !mbedtls_ssl_ciphersuite_uses_srv_cert( ciphersuite_info ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) ); + ssl->state++; + return( 0 ); + } + +#if defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + { + if( ssl->client_auth == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) ); + ssl->state++; + return( 0 ); + } + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + /* + * If using SSLv3 and got no cert, send an Alert message + * (otherwise an empty Certificate message will be sent). + */ + if( mbedtls_ssl_own_cert( ssl ) == NULL && + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + ssl->out_msglen = 2; + ssl->out_msgtype = MBEDTLS_SSL_MSG_ALERT; + ssl->out_msg[0] = MBEDTLS_SSL_ALERT_LEVEL_WARNING; + ssl->out_msg[1] = MBEDTLS_SSL_ALERT_MSG_NO_CERT; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "got no certificate to send" ) ); + goto write_msg; + } +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + } +#endif /* MBEDTLS_SSL_CLI_C */ +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + { + if( mbedtls_ssl_own_cert( ssl ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no certificate to send" ) ); + return( MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED ); + } + } +#endif + + MBEDTLS_SSL_DEBUG_CRT( 3, "own certificate", mbedtls_ssl_own_cert( ssl ) ); + + /* + * 0 . 0 handshake type + * 1 . 3 handshake length + * 4 . 6 length of all certs + * 7 . 9 length of cert. 1 + * 10 . n-1 peer certificate + * n . n+2 length of cert. 2 + * n+3 . ... upper level cert, etc. + */ + i = 7; + crt = mbedtls_ssl_own_cert( ssl ); + + while( crt != NULL ) + { + n = crt->raw.len; + if( n > MBEDTLS_SSL_OUT_CONTENT_LEN - 3 - i ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "certificate too large, %d > %d", + i + 3 + n, MBEDTLS_SSL_OUT_CONTENT_LEN ) ); + return( MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE ); + } + + ssl->out_msg[i ] = (unsigned char)( n >> 16 ); + ssl->out_msg[i + 1] = (unsigned char)( n >> 8 ); + ssl->out_msg[i + 2] = (unsigned char)( n ); + + i += 3; memcpy( ssl->out_msg + i, crt->raw.p, n ); + i += n; crt = crt->next; + } + + ssl->out_msg[4] = (unsigned char)( ( i - 7 ) >> 16 ); + ssl->out_msg[5] = (unsigned char)( ( i - 7 ) >> 8 ); + ssl->out_msg[6] = (unsigned char)( ( i - 7 ) ); + + ssl->out_msglen = i; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE; + +#if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_CLI_C) +write_msg: +#endif + + ssl->state++; + + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write certificate" ) ); + + return( ret ); +} + +#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C) + +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) +static int ssl_check_peer_crt_unchanged( mbedtls_ssl_context *ssl, + unsigned char *crt_buf, + size_t crt_buf_len ) +{ + mbedtls_x509_crt const * const peer_crt = ssl->session->peer_cert; + + if( peer_crt == NULL ) + return( -1 ); + + if( peer_crt->raw.len != crt_buf_len ) + return( -1 ); + + return( memcmp( peer_crt->raw.p, crt_buf, peer_crt->raw.len ) ); +} +#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +static int ssl_check_peer_crt_unchanged( mbedtls_ssl_context *ssl, + unsigned char *crt_buf, + size_t crt_buf_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char const * const peer_cert_digest = + ssl->session->peer_cert_digest; + mbedtls_md_type_t const peer_cert_digest_type = + ssl->session->peer_cert_digest_type; + mbedtls_md_info_t const * const digest_info = + mbedtls_md_info_from_type( peer_cert_digest_type ); + unsigned char tmp_digest[MBEDTLS_SSL_PEER_CERT_DIGEST_MAX_LEN]; + size_t digest_len; + + if( peer_cert_digest == NULL || digest_info == NULL ) + return( -1 ); + + digest_len = mbedtls_md_get_size( digest_info ); + if( digest_len > MBEDTLS_SSL_PEER_CERT_DIGEST_MAX_LEN ) + return( -1 ); + + ret = mbedtls_md( digest_info, crt_buf, crt_buf_len, tmp_digest ); + if( ret != 0 ) + return( -1 ); + + return( memcmp( tmp_digest, peer_cert_digest, digest_len ) ); +} +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#endif /* MBEDTLS_SSL_RENEGOTIATION && MBEDTLS_SSL_CLI_C */ + +/* + * Once the certificate message is read, parse it into a cert chain and + * perform basic checks, but leave actual verification to the caller + */ +static int ssl_parse_certificate_chain( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *chain ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; +#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C) + int crt_cnt=0; +#endif + size_t i, n; + uint8_t alert; + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + if( ssl->in_msg[0] != MBEDTLS_SSL_HS_CERTIFICATE || + ssl->in_hslen < mbedtls_ssl_hs_hdr_len( ssl ) + 3 + 3 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } + + i = mbedtls_ssl_hs_hdr_len( ssl ); + + /* + * Same message structure as in mbedtls_ssl_write_certificate() + */ + n = ( ssl->in_msg[i+1] << 8 ) | ssl->in_msg[i+2]; + + if( ssl->in_msg[i] != 0 || + ssl->in_hslen != n + 3 + mbedtls_ssl_hs_hdr_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } + + /* Make &ssl->in_msg[i] point to the beginning of the CRT chain. */ + i += 3; + + /* Iterate through and parse the CRTs in the provided chain. */ + while( i < ssl->in_hslen ) + { + /* Check that there's room for the next CRT's length fields. */ + if ( i + 3 > ssl->in_hslen ) { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } + /* In theory, the CRT can be up to 2**24 Bytes, but we don't support + * anything beyond 2**16 ~ 64K. */ + if( ssl->in_msg[i] != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } + + /* Read length of the next CRT in the chain. */ + n = ( (unsigned int) ssl->in_msg[i + 1] << 8 ) + | (unsigned int) ssl->in_msg[i + 2]; + i += 3; + + if( n < 128 || i + n > ssl->in_hslen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } + + /* Check if we're handling the first CRT in the chain. */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C) + if( crt_cnt++ == 0 && + ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && + ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + { + /* During client-side renegotiation, check that the server's + * end-CRTs hasn't changed compared to the initial handshake, + * mitigating the triple handshake attack. On success, reuse + * the original end-CRT instead of parsing it again. */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Check that peer CRT hasn't changed during renegotiation" ) ); + if( ssl_check_peer_crt_unchanged( ssl, + &ssl->in_msg[i], + n ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "new server cert during renegotiation" ) ); + mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } + + /* Now we can safely free the original chain. */ + ssl_clear_peer_cert( ssl->session ); + } +#endif /* MBEDTLS_SSL_RENEGOTIATION && MBEDTLS_SSL_CLI_C */ + + /* Parse the next certificate in the chain. */ +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + ret = mbedtls_x509_crt_parse_der( chain, ssl->in_msg + i, n ); +#else + /* If we don't need to store the CRT chain permanently, parse + * it in-place from the input buffer instead of making a copy. */ + ret = mbedtls_x509_crt_parse_der_nocopy( chain, ssl->in_msg + i, n ); +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + switch( ret ) + { + case 0: /*ok*/ + case MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + MBEDTLS_ERR_OID_NOT_FOUND: + /* Ignore certificate with an unknown algorithm: maybe a + prior certificate was already trusted. */ + break; + + case MBEDTLS_ERR_X509_ALLOC_FAILED: + alert = MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR; + goto crt_parse_der_failed; + + case MBEDTLS_ERR_X509_UNKNOWN_VERSION: + alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; + goto crt_parse_der_failed; + + default: + alert = MBEDTLS_SSL_ALERT_MSG_BAD_CERT; + crt_parse_der_failed: + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, alert ); + MBEDTLS_SSL_DEBUG_RET( 1, " mbedtls_x509_crt_parse_der", ret ); + return( ret ); + } + + i += n; + } + + MBEDTLS_SSL_DEBUG_CRT( 3, "peer certificate", chain ); + return( 0 ); +} + +#if defined(MBEDTLS_SSL_SRV_C) +static int ssl_srv_check_client_no_crt_notification( mbedtls_ssl_context *ssl ) +{ + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + return( -1 ); + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + /* + * Check if the client sent an empty certificate + */ + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + if( ssl->in_msglen == 2 && + ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT && + ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && + ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_CERT ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "SSLv3 client has no certificate" ) ); + return( 0 ); + } + + return( -1 ); + } +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->in_hslen == 3 + mbedtls_ssl_hs_hdr_len( ssl ) && + ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE && + memcmp( ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ), "\0\0\0", 3 ) == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "TLSv1 client has no certificate" ) ); + return( 0 ); + } + + return( -1 ); +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ + MBEDTLS_SSL_PROTO_TLS1_2 */ +} +#endif /* MBEDTLS_SSL_SRV_C */ + +/* Check if a certificate message is expected. + * Return either + * - SSL_CERTIFICATE_EXPECTED, or + * - SSL_CERTIFICATE_SKIP + * indicating whether a Certificate message is expected or not. + */ +#define SSL_CERTIFICATE_EXPECTED 0 +#define SSL_CERTIFICATE_SKIP 1 +static int ssl_parse_certificate_coordinate( mbedtls_ssl_context *ssl, + int authmode ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + + if( !mbedtls_ssl_ciphersuite_uses_srv_cert( ciphersuite_info ) ) + return( SSL_CERTIFICATE_SKIP ); + +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + { + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) + return( SSL_CERTIFICATE_SKIP ); + + if( authmode == MBEDTLS_SSL_VERIFY_NONE ) + { + ssl->session_negotiate->verify_result = + MBEDTLS_X509_BADCERT_SKIP_VERIFY; + return( SSL_CERTIFICATE_SKIP ); + } + } +#else + ((void) authmode); +#endif /* MBEDTLS_SSL_SRV_C */ + + return( SSL_CERTIFICATE_EXPECTED ); +} + +static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl, + int authmode, + mbedtls_x509_crt *chain, + void *rs_ctx ) +{ + int ret = 0; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + int have_ca_chain = 0; + + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *); + void *p_vrfy; + + if( authmode == MBEDTLS_SSL_VERIFY_NONE ) + return( 0 ); + + if( ssl->f_vrfy != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Use context-specific verification callback" ) ); + f_vrfy = ssl->f_vrfy; + p_vrfy = ssl->p_vrfy; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Use configuration-specific verification callback" ) ); + f_vrfy = ssl->conf->f_vrfy; + p_vrfy = ssl->conf->p_vrfy; + } + + /* + * Main check: verify certificate + */ +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + if( ssl->conf->f_ca_cb != NULL ) + { + ((void) rs_ctx); + have_ca_chain = 1; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "use CA callback for X.509 CRT verification" ) ); + ret = mbedtls_x509_crt_verify_with_ca_cb( + chain, + ssl->conf->f_ca_cb, + ssl->conf->p_ca_cb, + ssl->conf->cert_profile, + ssl->hostname, + &ssl->session_negotiate->verify_result, + f_vrfy, p_vrfy ); + } + else +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ + { + mbedtls_x509_crt *ca_chain; + mbedtls_x509_crl *ca_crl; + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if( ssl->handshake->sni_ca_chain != NULL ) + { + ca_chain = ssl->handshake->sni_ca_chain; + ca_crl = ssl->handshake->sni_ca_crl; + } + else +#endif + { + ca_chain = ssl->conf->ca_chain; + ca_crl = ssl->conf->ca_crl; + } + + if( ca_chain != NULL ) + have_ca_chain = 1; + + ret = mbedtls_x509_crt_verify_restartable( + chain, + ca_chain, ca_crl, + ssl->conf->cert_profile, + ssl->hostname, + &ssl->session_negotiate->verify_result, + f_vrfy, p_vrfy, rs_ctx ); + } + + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "x509_verify_cert", ret ); + } + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + return( MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS ); +#endif + + /* + * Secondary checks: always done, but change 'ret' only if it was 0 + */ + +#if defined(MBEDTLS_ECP_C) + { + const mbedtls_pk_context *pk = &chain->pk; + + /* If certificate uses an EC key, make sure the curve is OK */ + if( mbedtls_pk_can_do( pk, MBEDTLS_PK_ECKEY ) && + mbedtls_ssl_check_curve( ssl, mbedtls_pk_ec( *pk )->grp.id ) != 0 ) + { + ssl->session_negotiate->verify_result |= MBEDTLS_X509_BADCERT_BAD_KEY; + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate (EC key curve)" ) ); + if( ret == 0 ) + ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE; + } + } +#endif /* MBEDTLS_ECP_C */ + + if( mbedtls_ssl_check_cert_usage( chain, + ciphersuite_info, + ! ssl->conf->endpoint, + &ssl->session_negotiate->verify_result ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate (usage extensions)" ) ); + if( ret == 0 ) + ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE; + } + + /* mbedtls_x509_crt_verify_with_profile is supposed to report a + * verification failure through MBEDTLS_ERR_X509_CERT_VERIFY_FAILED, + * with details encoded in the verification flags. All other kinds + * of error codes, including those from the user provided f_vrfy + * functions, are treated as fatal and lead to a failure of + * ssl_parse_certificate even if verification was optional. */ + if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL && + ( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED || + ret == MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ) ) + { + ret = 0; + } + + if( have_ca_chain == 0 && authmode == MBEDTLS_SSL_VERIFY_REQUIRED ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no CA chain" ) ); + ret = MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED; + } + + if( ret != 0 ) + { + uint8_t alert; + + /* The certificate may have been rejected for several reasons. + Pick one and send the corresponding alert. Which alert to send + may be a subject of debate in some cases. */ + if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_OTHER ) + alert = MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_CN_MISMATCH ) + alert = MBEDTLS_SSL_ALERT_MSG_BAD_CERT; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_KEY_USAGE ) + alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXT_KEY_USAGE ) + alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_NS_CERT_TYPE ) + alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_PK ) + alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_KEY ) + alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXPIRED ) + alert = MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_REVOKED ) + alert = MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_NOT_TRUSTED ) + alert = MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA; + else + alert = MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN; + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + alert ); + } + +#if defined(MBEDTLS_DEBUG_C) + if( ssl->session_negotiate->verify_result != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "! Certificate verification flags %x", + ssl->session_negotiate->verify_result ) ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Certificate verification flags clear" ) ); + } +#endif /* MBEDTLS_DEBUG_C */ + + return( ret ); +} + +#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) +static int ssl_remember_peer_crt_digest( mbedtls_ssl_context *ssl, + unsigned char *start, size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + /* Remember digest of the peer's end-CRT. */ + ssl->session_negotiate->peer_cert_digest = + mbedtls_calloc( 1, MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN ); + if( ssl->session_negotiate->peer_cert_digest == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", + MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN ) ); + mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + ret = mbedtls_md( mbedtls_md_info_from_type( + MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE ), + start, len, + ssl->session_negotiate->peer_cert_digest ); + + ssl->session_negotiate->peer_cert_digest_type = + MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE; + ssl->session_negotiate->peer_cert_digest_len = + MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN; + + return( ret ); +} + +static int ssl_remember_peer_pubkey( mbedtls_ssl_context *ssl, + unsigned char *start, size_t len ) +{ + unsigned char *end = start + len; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* Make a copy of the peer's raw public key. */ + mbedtls_pk_init( &ssl->handshake->peer_pubkey ); + ret = mbedtls_pk_parse_subpubkey( &start, end, + &ssl->handshake->peer_pubkey ); + if( ret != 0 ) + { + /* We should have parsed the public key before. */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + return( 0 ); +} +#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + +int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) +{ + int ret = 0; + int crt_expected; +#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + const int authmode = ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET + ? ssl->handshake->sni_authmode + : ssl->conf->authmode; +#else + const int authmode = ssl->conf->authmode; +#endif + void *rs_ctx = NULL; + mbedtls_x509_crt *chain = NULL; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) ); + + crt_expected = ssl_parse_certificate_coordinate( ssl, authmode ); + if( crt_expected == SSL_CERTIFICATE_SKIP ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); + goto exit; + } + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ssl->handshake->ecrs_enabled && + ssl->handshake->ecrs_state == ssl_ecrs_crt_verify ) + { + chain = ssl->handshake->ecrs_peer_cert; + ssl->handshake->ecrs_peer_cert = NULL; + goto crt_verify; + } +#endif + + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) + { + /* mbedtls_ssl_read_record may have sent an alert already. We + let it decide whether to alert. */ + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + goto exit; + } + +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl_srv_check_client_no_crt_notification( ssl ) == 0 ) + { + ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING; + + if( authmode != MBEDTLS_SSL_VERIFY_OPTIONAL ) + ret = MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE; + + goto exit; + } +#endif /* MBEDTLS_SSL_SRV_C */ + + /* Clear existing peer CRT structure in case we tried to + * reuse a session but it failed, and allocate a new one. */ + ssl_clear_peer_cert( ssl->session_negotiate ); + + chain = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) ); + if( chain == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", + sizeof( mbedtls_x509_crt ) ) ); + mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + + ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; + goto exit; + } + mbedtls_x509_crt_init( chain ); + + ret = ssl_parse_certificate_chain( ssl, chain ); + if( ret != 0 ) + goto exit; + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ssl->handshake->ecrs_enabled) + ssl->handshake->ecrs_state = ssl_ecrs_crt_verify; + +crt_verify: + if( ssl->handshake->ecrs_enabled) + rs_ctx = &ssl->handshake->ecrs_ctx; +#endif + + ret = ssl_parse_certificate_verify( ssl, authmode, + chain, rs_ctx ); + if( ret != 0 ) + goto exit; + +#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + { + unsigned char *crt_start, *pk_start; + size_t crt_len, pk_len; + + /* We parse the CRT chain without copying, so + * these pointers point into the input buffer, + * and are hence still valid after freeing the + * CRT chain. */ + + crt_start = chain->raw.p; + crt_len = chain->raw.len; + + pk_start = chain->pk_raw.p; + pk_len = chain->pk_raw.len; + + /* Free the CRT structures before computing + * digest and copying the peer's public key. */ + mbedtls_x509_crt_free( chain ); + mbedtls_free( chain ); + chain = NULL; + + ret = ssl_remember_peer_crt_digest( ssl, crt_start, crt_len ); + if( ret != 0 ) + goto exit; + + ret = ssl_remember_peer_pubkey( ssl, pk_start, pk_len ); + if( ret != 0 ) + goto exit; + } +#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + /* Pass ownership to session structure. */ + ssl->session_negotiate->peer_cert = chain; + chain = NULL; +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate" ) ); + +exit: + + if( ret == 0 ) + ssl->state++; + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS ) + { + ssl->handshake->ecrs_peer_cert = chain; + chain = NULL; + } +#endif + + if( chain != NULL ) + { + mbedtls_x509_crt_free( chain ); + mbedtls_free( chain ); + } + + return( ret ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + +void mbedtls_ssl_optimize_checksum( mbedtls_ssl_context *ssl, + const mbedtls_ssl_ciphersuite_t *ciphersuite_info ) +{ + ((void) ciphersuite_info); + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 ) + ssl->handshake->update_checksum = ssl_update_checksum_md5sha1; + else +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA512_C) + if( ciphersuite_info->mac == MBEDTLS_MD_SHA384 ) + ssl->handshake->update_checksum = ssl_update_checksum_sha384; + else +#endif +#if defined(MBEDTLS_SHA256_C) + if( ciphersuite_info->mac != MBEDTLS_MD_SHA384 ) + ssl->handshake->update_checksum = ssl_update_checksum_sha256; + else +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return; + } +} + +void mbedtls_ssl_reset_checksum( mbedtls_ssl_context *ssl ) +{ +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + mbedtls_md5_starts_ret( &ssl->handshake->fin_md5 ); + mbedtls_sha1_starts_ret( &ssl->handshake->fin_sha1 ); +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_hash_abort( &ssl->handshake->fin_sha256_psa ); + psa_hash_setup( &ssl->handshake->fin_sha256_psa, PSA_ALG_SHA_256 ); +#else + mbedtls_sha256_starts_ret( &ssl->handshake->fin_sha256, 0 ); +#endif +#endif +#if defined(MBEDTLS_SHA512_C) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_hash_abort( &ssl->handshake->fin_sha384_psa ); + psa_hash_setup( &ssl->handshake->fin_sha384_psa, PSA_ALG_SHA_384 ); +#else + mbedtls_sha512_starts_ret( &ssl->handshake->fin_sha512, 1 ); +#endif +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +} + +static void ssl_update_checksum_start( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + mbedtls_md5_update_ret( &ssl->handshake->fin_md5 , buf, len ); + mbedtls_sha1_update_ret( &ssl->handshake->fin_sha1, buf, len ); +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_hash_update( &ssl->handshake->fin_sha256_psa, buf, len ); +#else + mbedtls_sha256_update_ret( &ssl->handshake->fin_sha256, buf, len ); +#endif +#endif +#if defined(MBEDTLS_SHA512_C) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_hash_update( &ssl->handshake->fin_sha384_psa, buf, len ); +#else + mbedtls_sha512_update_ret( &ssl->handshake->fin_sha512, buf, len ); +#endif +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +} + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) +static void ssl_update_checksum_md5sha1( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + mbedtls_md5_update_ret( &ssl->handshake->fin_md5 , buf, len ); + mbedtls_sha1_update_ret( &ssl->handshake->fin_sha1, buf, len ); +} +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) +static void ssl_update_checksum_sha256( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_hash_update( &ssl->handshake->fin_sha256_psa, buf, len ); +#else + mbedtls_sha256_update_ret( &ssl->handshake->fin_sha256, buf, len ); +#endif +} +#endif + +#if defined(MBEDTLS_SHA512_C) +static void ssl_update_checksum_sha384( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_hash_update( &ssl->handshake->fin_sha384_psa, buf, len ); +#else + mbedtls_sha512_update_ret( &ssl->handshake->fin_sha512, buf, len ); +#endif +} +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_SSL_PROTO_SSL3) +static void ssl_calc_finished_ssl( + mbedtls_ssl_context *ssl, unsigned char *buf, int from ) +{ + const char *sender; + mbedtls_md5_context md5; + mbedtls_sha1_context sha1; + + unsigned char padbuf[48]; + unsigned char md5sum[16]; + unsigned char sha1sum[20]; + + mbedtls_ssl_session *session = ssl->session_negotiate; + if( !session ) + session = ssl->session; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc finished ssl" ) ); + + mbedtls_md5_init( &md5 ); + mbedtls_sha1_init( &sha1 ); + + mbedtls_md5_clone( &md5, &ssl->handshake->fin_md5 ); + mbedtls_sha1_clone( &sha1, &ssl->handshake->fin_sha1 ); + + /* + * SSLv3: + * hash = + * MD5( master + pad2 + + * MD5( handshake + sender + master + pad1 ) ) + * + SHA1( master + pad2 + + * SHA1( handshake + sender + master + pad1 ) ) + */ + +#if !defined(MBEDTLS_MD5_ALT) + MBEDTLS_SSL_DEBUG_BUF( 4, "finished md5 state", (unsigned char *) + md5.state, sizeof( md5.state ) ); +#endif + +#if !defined(MBEDTLS_SHA1_ALT) + MBEDTLS_SSL_DEBUG_BUF( 4, "finished sha1 state", (unsigned char *) + sha1.state, sizeof( sha1.state ) ); +#endif + + sender = ( from == MBEDTLS_SSL_IS_CLIENT ) ? "CLNT" + : "SRVR"; + + memset( padbuf, 0x36, 48 ); + + mbedtls_md5_update_ret( &md5, (const unsigned char *) sender, 4 ); + mbedtls_md5_update_ret( &md5, session->master, 48 ); + mbedtls_md5_update_ret( &md5, padbuf, 48 ); + mbedtls_md5_finish_ret( &md5, md5sum ); + + mbedtls_sha1_update_ret( &sha1, (const unsigned char *) sender, 4 ); + mbedtls_sha1_update_ret( &sha1, session->master, 48 ); + mbedtls_sha1_update_ret( &sha1, padbuf, 40 ); + mbedtls_sha1_finish_ret( &sha1, sha1sum ); + + memset( padbuf, 0x5C, 48 ); + + mbedtls_md5_starts_ret( &md5 ); + mbedtls_md5_update_ret( &md5, session->master, 48 ); + mbedtls_md5_update_ret( &md5, padbuf, 48 ); + mbedtls_md5_update_ret( &md5, md5sum, 16 ); + mbedtls_md5_finish_ret( &md5, buf ); + + mbedtls_sha1_starts_ret( &sha1 ); + mbedtls_sha1_update_ret( &sha1, session->master, 48 ); + mbedtls_sha1_update_ret( &sha1, padbuf , 40 ); + mbedtls_sha1_update_ret( &sha1, sha1sum, 20 ); + mbedtls_sha1_finish_ret( &sha1, buf + 16 ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "calc finished result", buf, 36 ); + + mbedtls_md5_free( &md5 ); + mbedtls_sha1_free( &sha1 ); + + mbedtls_platform_zeroize( padbuf, sizeof( padbuf ) ); + mbedtls_platform_zeroize( md5sum, sizeof( md5sum ) ); + mbedtls_platform_zeroize( sha1sum, sizeof( sha1sum ) ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); +} +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) +static void ssl_calc_finished_tls( + mbedtls_ssl_context *ssl, unsigned char *buf, int from ) +{ + int len = 12; + const char *sender; + mbedtls_md5_context md5; + mbedtls_sha1_context sha1; + unsigned char padbuf[36]; + + mbedtls_ssl_session *session = ssl->session_negotiate; + if( !session ) + session = ssl->session; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc finished tls" ) ); + + mbedtls_md5_init( &md5 ); + mbedtls_sha1_init( &sha1 ); + + mbedtls_md5_clone( &md5, &ssl->handshake->fin_md5 ); + mbedtls_sha1_clone( &sha1, &ssl->handshake->fin_sha1 ); + + /* + * TLSv1: + * hash = PRF( master, finished_label, + * MD5( handshake ) + SHA1( handshake ) )[0..11] + */ + +#if !defined(MBEDTLS_MD5_ALT) + MBEDTLS_SSL_DEBUG_BUF( 4, "finished md5 state", (unsigned char *) + md5.state, sizeof( md5.state ) ); +#endif + +#if !defined(MBEDTLS_SHA1_ALT) + MBEDTLS_SSL_DEBUG_BUF( 4, "finished sha1 state", (unsigned char *) + sha1.state, sizeof( sha1.state ) ); +#endif + + sender = ( from == MBEDTLS_SSL_IS_CLIENT ) + ? "client finished" + : "server finished"; + + mbedtls_md5_finish_ret( &md5, padbuf ); + mbedtls_sha1_finish_ret( &sha1, padbuf + 16 ); + + ssl->handshake->tls_prf( session->master, 48, sender, + padbuf, 36, buf, len ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "calc finished result", buf, len ); + + mbedtls_md5_free( &md5 ); + mbedtls_sha1_free( &sha1 ); + + mbedtls_platform_zeroize( padbuf, sizeof( padbuf ) ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); +} +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) +static void ssl_calc_finished_tls_sha256( + mbedtls_ssl_context *ssl, unsigned char *buf, int from ) +{ + int len = 12; + const char *sender; + unsigned char padbuf[32]; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + size_t hash_size; + psa_hash_operation_t sha256_psa = PSA_HASH_OPERATION_INIT; + psa_status_t status; +#else + mbedtls_sha256_context sha256; +#endif + + mbedtls_ssl_session *session = ssl->session_negotiate; + if( !session ) + session = ssl->session; + + sender = ( from == MBEDTLS_SSL_IS_CLIENT ) + ? "client finished" + : "server finished"; + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + sha256_psa = psa_hash_operation_init(); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc PSA finished tls sha256" ) ); + + status = psa_hash_clone( &ssl->handshake->fin_sha256_psa, &sha256_psa ); + if( status != PSA_SUCCESS ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "PSA hash clone failed" ) ); + return; + } + + status = psa_hash_finish( &sha256_psa, padbuf, sizeof( padbuf ), &hash_size ); + if( status != PSA_SUCCESS ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "PSA hash finish failed" ) ); + return; + } + MBEDTLS_SSL_DEBUG_BUF( 3, "PSA calculated padbuf", padbuf, 32 ); +#else + + mbedtls_sha256_init( &sha256 ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc finished tls sha256" ) ); + + mbedtls_sha256_clone( &sha256, &ssl->handshake->fin_sha256 ); + + /* + * TLSv1.2: + * hash = PRF( master, finished_label, + * Hash( handshake ) )[0.11] + */ + +#if !defined(MBEDTLS_SHA256_ALT) + MBEDTLS_SSL_DEBUG_BUF( 4, "finished sha2 state", (unsigned char *) + sha256.state, sizeof( sha256.state ) ); +#endif + + mbedtls_sha256_finish_ret( &sha256, padbuf ); + mbedtls_sha256_free( &sha256 ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + ssl->handshake->tls_prf( session->master, 48, sender, + padbuf, 32, buf, len ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "calc finished result", buf, len ); + + mbedtls_platform_zeroize( padbuf, sizeof( padbuf ) ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); +} +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) +static void ssl_calc_finished_tls_sha384( + mbedtls_ssl_context *ssl, unsigned char *buf, int from ) +{ + int len = 12; + const char *sender; + unsigned char padbuf[48]; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + size_t hash_size; + psa_hash_operation_t sha384_psa = PSA_HASH_OPERATION_INIT; + psa_status_t status; +#else + mbedtls_sha512_context sha512; +#endif + + mbedtls_ssl_session *session = ssl->session_negotiate; + if( !session ) + session = ssl->session; + + sender = ( from == MBEDTLS_SSL_IS_CLIENT ) + ? "client finished" + : "server finished"; + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + sha384_psa = psa_hash_operation_init(); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc PSA finished tls sha384" ) ); + + status = psa_hash_clone( &ssl->handshake->fin_sha384_psa, &sha384_psa ); + if( status != PSA_SUCCESS ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "PSA hash clone failed" ) ); + return; + } + + status = psa_hash_finish( &sha384_psa, padbuf, sizeof( padbuf ), &hash_size ); + if( status != PSA_SUCCESS ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "PSA hash finish failed" ) ); + return; + } + MBEDTLS_SSL_DEBUG_BUF( 3, "PSA calculated padbuf", padbuf, 48 ); +#else + mbedtls_sha512_init( &sha512 ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc finished tls sha384" ) ); + + mbedtls_sha512_clone( &sha512, &ssl->handshake->fin_sha512 ); + + /* + * TLSv1.2: + * hash = PRF( master, finished_label, + * Hash( handshake ) )[0.11] + */ + +#if !defined(MBEDTLS_SHA512_ALT) + MBEDTLS_SSL_DEBUG_BUF( 4, "finished sha512 state", (unsigned char *) + sha512.state, sizeof( sha512.state ) ); +#endif + + mbedtls_sha512_finish_ret( &sha512, padbuf ); + mbedtls_sha512_free( &sha512 ); +#endif + + ssl->handshake->tls_prf( session->master, 48, sender, + padbuf, 48, buf, len ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "calc finished result", buf, len ); + + mbedtls_platform_zeroize( padbuf, sizeof( padbuf ) ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); +} +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +void mbedtls_ssl_handshake_wrapup_free_hs_transform( mbedtls_ssl_context *ssl ) +{ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "=> handshake wrapup: final free" ) ); + + /* + * Free our handshake params + */ + mbedtls_ssl_handshake_free( ssl ); + mbedtls_free( ssl->handshake ); + ssl->handshake = NULL; + + /* + * Free the previous transform and swith in the current one + */ + if( ssl->transform ) + { + mbedtls_ssl_transform_free( ssl->transform ); + mbedtls_free( ssl->transform ); + } + ssl->transform = ssl->transform_negotiate; + ssl->transform_negotiate = NULL; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "<= handshake wrapup: final free" ) ); +} + +void mbedtls_ssl_handshake_wrapup( mbedtls_ssl_context *ssl ) +{ + int resume = ssl->handshake->resume; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "=> handshake wrapup" ) ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + { + ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_DONE; + ssl->renego_records_seen = 0; + } +#endif + + /* + * Free the previous session and switch in the current one + */ + if( ssl->session ) + { +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + /* RFC 7366 3.1: keep the EtM state */ + ssl->session_negotiate->encrypt_then_mac = + ssl->session->encrypt_then_mac; +#endif + + mbedtls_ssl_session_free( ssl->session ); + mbedtls_free( ssl->session ); + } + ssl->session = ssl->session_negotiate; + ssl->session_negotiate = NULL; + + /* + * Add cache entry + */ + if( ssl->conf->f_set_cache != NULL && + ssl->session->id_len != 0 && + resume == 0 ) + { + if( ssl->conf->f_set_cache( ssl->conf->p_cache, ssl->session ) != 0 ) + MBEDTLS_SSL_DEBUG_MSG( 1, ( "cache did not store session" ) ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake->flight != NULL ) + { + /* Cancel handshake timer */ + mbedtls_ssl_set_timer( ssl, 0 ); + + /* Keep last flight around in case we need to resend it: + * we need the handshake and transform structures for that */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip freeing handshake and transform" ) ); + } + else +#endif + mbedtls_ssl_handshake_wrapup_free_hs_transform( ssl ); + + ssl->state++; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "<= handshake wrapup" ) ); +} + +int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl ) +{ + int ret, hash_len; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write finished" ) ); + + mbedtls_ssl_update_out_pointers( ssl, ssl->transform_negotiate ); + + ssl->handshake->calc_finished( ssl, ssl->out_msg + 4, ssl->conf->endpoint ); + + /* + * RFC 5246 7.4.9 (Page 63) says 12 is the default length and ciphersuites + * may define some other value. Currently (early 2016), no defined + * ciphersuite does this (and this is unlikely to change as activity has + * moved to TLS 1.3 now) so we can keep the hardcoded 12 here. + */ + hash_len = ( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) ? 36 : 12; + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->verify_data_len = hash_len; + memcpy( ssl->own_verify_data, ssl->out_msg + 4, hash_len ); +#endif + + ssl->out_msglen = 4 + hash_len; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_FINISHED; + + /* + * In case of session resuming, invert the client and server + * ChangeCipherSpec messages order. + */ + if( ssl->handshake->resume != 0 ) + { +#if defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; +#endif +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + ssl->state = MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC; +#endif + } + else + ssl->state++; + + /* + * Switch to our negotiated transform and session parameters for outbound + * data. + */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "switching to new transform spec for outbound data" ) ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + unsigned char i; + + /* Remember current epoch settings for resending */ + ssl->handshake->alt_transform_out = ssl->transform_out; + memcpy( ssl->handshake->alt_out_ctr, ssl->cur_out_ctr, 8 ); + + /* Set sequence_number to zero */ + memset( ssl->cur_out_ctr + 2, 0, 6 ); + + /* Increment epoch */ + for( i = 2; i > 0; i-- ) + if( ++ssl->cur_out_ctr[i - 1] != 0 ) + break; + + /* The loop goes to its end iff the counter is wrapping */ + if( i == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS epoch would wrap" ) ); + return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); + } + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + memset( ssl->cur_out_ctr, 0, 8 ); + + ssl->transform_out = ssl->transform_negotiate; + ssl->session_out = ssl->session_negotiate; + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_activate != NULL ) + { + if( ( ret = mbedtls_ssl_hw_record_activate( ssl, MBEDTLS_SSL_CHANNEL_OUTBOUND ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_activate", ret ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + } +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + mbedtls_ssl_send_flight_completed( ssl ); +#endif + + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret ); + return( ret ); + } +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write finished" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_PROTO_SSL3) +#define SSL_MAX_HASH_LEN 36 +#else +#define SSL_MAX_HASH_LEN 12 +#endif + +int mbedtls_ssl_parse_finished( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned int hash_len; + unsigned char buf[SSL_MAX_HASH_LEN]; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse finished" ) ); + + ssl->handshake->calc_finished( ssl, buf, ssl->conf->endpoint ^ 1 ); + + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + /* There is currently no ciphersuite using another length with TLS 1.2 */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + hash_len = 36; + else +#endif + hash_len = 12; + + if( ssl->in_msg[0] != MBEDTLS_SSL_HS_FINISHED || + ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + hash_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_FINISHED ); + } + + if( mbedtls_ssl_safer_memcmp( ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ), + buf, hash_len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_FINISHED ); + } + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->verify_data_len = hash_len; + memcpy( ssl->peer_verify_data, buf, hash_len ); +#endif + + if( ssl->handshake->resume != 0 ) + { +#if defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + ssl->state = MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC; +#endif +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; +#endif + } + else + ssl->state++; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + mbedtls_ssl_recv_flight_completed( ssl ); +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse finished" ) ); + + return( 0 ); +} + +static void ssl_handshake_params_init( mbedtls_ssl_handshake_params *handshake ) +{ + memset( handshake, 0, sizeof( mbedtls_ssl_handshake_params ) ); + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + mbedtls_md5_init( &handshake->fin_md5 ); + mbedtls_sha1_init( &handshake->fin_sha1 ); + mbedtls_md5_starts_ret( &handshake->fin_md5 ); + mbedtls_sha1_starts_ret( &handshake->fin_sha1 ); +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + handshake->fin_sha256_psa = psa_hash_operation_init(); + psa_hash_setup( &handshake->fin_sha256_psa, PSA_ALG_SHA_256 ); +#else + mbedtls_sha256_init( &handshake->fin_sha256 ); + mbedtls_sha256_starts_ret( &handshake->fin_sha256, 0 ); +#endif +#endif +#if defined(MBEDTLS_SHA512_C) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + handshake->fin_sha384_psa = psa_hash_operation_init(); + psa_hash_setup( &handshake->fin_sha384_psa, PSA_ALG_SHA_384 ); +#else + mbedtls_sha512_init( &handshake->fin_sha512 ); + mbedtls_sha512_starts_ret( &handshake->fin_sha512, 1 ); +#endif +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + handshake->update_checksum = ssl_update_checksum_start; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + mbedtls_ssl_sig_hash_set_init( &handshake->hash_algs ); +#endif + +#if defined(MBEDTLS_DHM_C) + mbedtls_dhm_init( &handshake->dhm_ctx ); +#endif +#if defined(MBEDTLS_ECDH_C) + mbedtls_ecdh_init( &handshake->ecdh_ctx ); +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + mbedtls_ecjpake_init( &handshake->ecjpake_ctx ); +#if defined(MBEDTLS_SSL_CLI_C) + handshake->ecjpake_cache = NULL; + handshake->ecjpake_cache_len = 0; +#endif +#endif + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + mbedtls_x509_crt_restart_init( &handshake->ecrs_ctx ); +#endif + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + handshake->sni_authmode = MBEDTLS_SSL_VERIFY_UNSET; +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) && \ + !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + mbedtls_pk_init( &handshake->peer_pubkey ); +#endif +} + +void mbedtls_ssl_transform_init( mbedtls_ssl_transform *transform ) +{ + memset( transform, 0, sizeof(mbedtls_ssl_transform) ); + + mbedtls_cipher_init( &transform->cipher_ctx_enc ); + mbedtls_cipher_init( &transform->cipher_ctx_dec ); + +#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) + mbedtls_md_init( &transform->md_ctx_enc ); + mbedtls_md_init( &transform->md_ctx_dec ); +#endif +} + +void mbedtls_ssl_session_init( mbedtls_ssl_session *session ) +{ + memset( session, 0, sizeof(mbedtls_ssl_session) ); +} + +static int ssl_handshake_init( mbedtls_ssl_context *ssl ) +{ + /* Clear old handshake information if present */ + if( ssl->transform_negotiate ) + mbedtls_ssl_transform_free( ssl->transform_negotiate ); + if( ssl->session_negotiate ) + mbedtls_ssl_session_free( ssl->session_negotiate ); + if( ssl->handshake ) + mbedtls_ssl_handshake_free( ssl ); + + /* + * Either the pointers are now NULL or cleared properly and can be freed. + * Now allocate missing structures. + */ + if( ssl->transform_negotiate == NULL ) + { + ssl->transform_negotiate = mbedtls_calloc( 1, sizeof(mbedtls_ssl_transform) ); + } + + if( ssl->session_negotiate == NULL ) + { + ssl->session_negotiate = mbedtls_calloc( 1, sizeof(mbedtls_ssl_session) ); + } + + if( ssl->handshake == NULL ) + { + ssl->handshake = mbedtls_calloc( 1, sizeof(mbedtls_ssl_handshake_params) ); + } +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + /* If the buffers are too small - reallocate */ + { + int modified = 0; + size_t written_in = 0, iv_offset_in = 0, len_offset_in = 0; + size_t written_out = 0, iv_offset_out = 0, len_offset_out = 0; + if( ssl->in_buf != NULL ) + { + written_in = ssl->in_msg - ssl->in_buf; + iv_offset_in = ssl->in_iv - ssl->in_buf; + len_offset_in = ssl->in_len - ssl->in_buf; + if( ssl->in_buf_len < MBEDTLS_SSL_IN_BUFFER_LEN ) + { + if( resize_buffer( &ssl->in_buf, MBEDTLS_SSL_IN_BUFFER_LEN, + &ssl->in_buf_len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "input buffer resizing failed - out of memory" ) ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Reallocating in_buf to %d", MBEDTLS_SSL_IN_BUFFER_LEN ) ); + modified = 1; + } + } + } + + if( ssl->out_buf != NULL ) + { + written_out = ssl->out_msg - ssl->out_buf; + iv_offset_out = ssl->out_iv - ssl->out_buf; + len_offset_out = ssl->out_len - ssl->out_buf; + if( ssl->out_buf_len < MBEDTLS_SSL_OUT_BUFFER_LEN ) + { + if( resize_buffer( &ssl->out_buf, MBEDTLS_SSL_OUT_BUFFER_LEN, + &ssl->out_buf_len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "output buffer resizing failed - out of memory" ) ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Reallocating out_buf to %d", MBEDTLS_SSL_OUT_BUFFER_LEN ) ); + modified = 1; + } + } + } + if( modified ) + { + /* Update pointers here to avoid doing it twice. */ + mbedtls_ssl_reset_in_out_pointers( ssl ); + /* Fields below might not be properly updated with record + * splitting or with CID, so they are manually updated here. */ + ssl->out_msg = ssl->out_buf + written_out; + ssl->out_len = ssl->out_buf + len_offset_out; + ssl->out_iv = ssl->out_buf + iv_offset_out; + + ssl->in_msg = ssl->in_buf + written_in; + ssl->in_len = ssl->in_buf + len_offset_in; + ssl->in_iv = ssl->in_buf + iv_offset_in; + } + } +#endif + + /* All pointers should exist and can be directly freed without issue */ + if( ssl->handshake == NULL || + ssl->transform_negotiate == NULL || + ssl->session_negotiate == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc() of ssl sub-contexts failed" ) ); + + mbedtls_free( ssl->handshake ); + mbedtls_free( ssl->transform_negotiate ); + mbedtls_free( ssl->session_negotiate ); + + ssl->handshake = NULL; + ssl->transform_negotiate = NULL; + ssl->session_negotiate = NULL; + + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + /* Initialize structures */ + mbedtls_ssl_session_init( ssl->session_negotiate ); + mbedtls_ssl_transform_init( ssl->transform_negotiate ); + ssl_handshake_params_init( ssl->handshake ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ssl->handshake->alt_transform_out = ssl->transform_out; + + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_PREPARING; + else + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING; + + mbedtls_ssl_set_timer( ssl, 0 ); + } +#endif + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) +/* Dummy cookie callbacks for defaults */ +static int ssl_cookie_write_dummy( void *ctx, + unsigned char **p, unsigned char *end, + const unsigned char *cli_id, size_t cli_id_len ) +{ + ((void) ctx); + ((void) p); + ((void) end); + ((void) cli_id); + ((void) cli_id_len); + + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); +} + +static int ssl_cookie_check_dummy( void *ctx, + const unsigned char *cookie, size_t cookie_len, + const unsigned char *cli_id, size_t cli_id_len ) +{ + ((void) ctx); + ((void) cookie); + ((void) cookie_len); + ((void) cli_id); + ((void) cli_id_len); + + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); +} +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */ + +/* + * Initialize an SSL context + */ +void mbedtls_ssl_init( mbedtls_ssl_context *ssl ) +{ + memset( ssl, 0, sizeof( mbedtls_ssl_context ) ); +} + +/* + * Setup an SSL context + */ + +int mbedtls_ssl_setup( mbedtls_ssl_context *ssl, + const mbedtls_ssl_config *conf ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN; + size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN; + + ssl->conf = conf; + + /* + * Prepare base structures + */ + + /* Set to NULL in case of an error condition */ + ssl->out_buf = NULL; + +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + ssl->in_buf_len = in_buf_len; +#endif + ssl->in_buf = mbedtls_calloc( 1, in_buf_len ); + if( ssl->in_buf == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", in_buf_len ) ); + ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; + goto error; + } + +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + ssl->out_buf_len = out_buf_len; +#endif + ssl->out_buf = mbedtls_calloc( 1, out_buf_len ); + if( ssl->out_buf == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", out_buf_len ) ); + ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; + goto error; + } + + mbedtls_ssl_reset_in_out_pointers( ssl ); + +#if defined(MBEDTLS_SSL_DTLS_SRTP) + memset( &ssl->dtls_srtp_info, 0, sizeof(ssl->dtls_srtp_info) ); +#endif + + if( ( ret = ssl_handshake_init( ssl ) ) != 0 ) + goto error; + + return( 0 ); + +error: + mbedtls_free( ssl->in_buf ); + mbedtls_free( ssl->out_buf ); + + ssl->conf = NULL; + +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + ssl->in_buf_len = 0; + ssl->out_buf_len = 0; +#endif + ssl->in_buf = NULL; + ssl->out_buf = NULL; + + ssl->in_hdr = NULL; + ssl->in_ctr = NULL; + ssl->in_len = NULL; + ssl->in_iv = NULL; + ssl->in_msg = NULL; + + ssl->out_hdr = NULL; + ssl->out_ctr = NULL; + ssl->out_len = NULL; + ssl->out_iv = NULL; + ssl->out_msg = NULL; + + return( ret ); +} + +/* + * Reset an initialized and used SSL context for re-use while retaining + * all application-set variables, function pointers and data. + * + * If partial is non-zero, keep data in the input buffer and client ID. + * (Use when a DTLS client reconnects from the same port.) + */ +int mbedtls_ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t in_buf_len = ssl->in_buf_len; + size_t out_buf_len = ssl->out_buf_len; +#else + size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN; + size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN; +#endif + +#if !defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) || \ + !defined(MBEDTLS_SSL_SRV_C) + ((void) partial); +#endif + + ssl->state = MBEDTLS_SSL_HELLO_REQUEST; + + /* Cancel any possibly running timer */ + mbedtls_ssl_set_timer( ssl, 0 ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->renego_status = MBEDTLS_SSL_INITIAL_HANDSHAKE; + ssl->renego_records_seen = 0; + + ssl->verify_data_len = 0; + memset( ssl->own_verify_data, 0, MBEDTLS_SSL_VERIFY_DATA_MAX_LEN ); + memset( ssl->peer_verify_data, 0, MBEDTLS_SSL_VERIFY_DATA_MAX_LEN ); +#endif + ssl->secure_renegotiation = MBEDTLS_SSL_LEGACY_RENEGOTIATION; + + ssl->in_offt = NULL; + mbedtls_ssl_reset_in_out_pointers( ssl ); + + ssl->in_msgtype = 0; + ssl->in_msglen = 0; +#if defined(MBEDTLS_SSL_PROTO_DTLS) + ssl->next_record_offset = 0; + ssl->in_epoch = 0; +#endif +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + mbedtls_ssl_dtls_replay_reset( ssl ); +#endif + + ssl->in_hslen = 0; + ssl->nb_zero = 0; + + ssl->keep_current_message = 0; + + ssl->out_msgtype = 0; + ssl->out_msglen = 0; + ssl->out_left = 0; +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) + if( ssl->split_done != MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED ) + ssl->split_done = 0; +#endif + + memset( ssl->cur_out_ctr, 0, sizeof( ssl->cur_out_ctr ) ); + + ssl->transform_in = NULL; + ssl->transform_out = NULL; + + ssl->session_in = NULL; + ssl->session_out = NULL; + + memset( ssl->out_buf, 0, out_buf_len ); + +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) + if( partial == 0 ) +#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */ + { + ssl->in_left = 0; + memset( ssl->in_buf, 0, in_buf_len ); + } + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_reset != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_reset()" ) ); + if( ( ret = mbedtls_ssl_hw_record_reset( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_reset", ret ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + } +#endif + + if( ssl->transform ) + { + mbedtls_ssl_transform_free( ssl->transform ); + mbedtls_free( ssl->transform ); + ssl->transform = NULL; + } + + if( ssl->session ) + { + mbedtls_ssl_session_free( ssl->session ); + mbedtls_free( ssl->session ); + ssl->session = NULL; + } + +#if defined(MBEDTLS_SSL_ALPN) + ssl->alpn_chosen = NULL; +#endif + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) + if( partial == 0 ) +#endif + { + mbedtls_free( ssl->cli_id ); + ssl->cli_id = NULL; + ssl->cli_id_len = 0; + } +#endif + + if( ( ret = ssl_handshake_init( ssl ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +/* + * Reset an initialized and used SSL context for re-use while retaining + * all application-set variables, function pointers and data. + */ +int mbedtls_ssl_session_reset( mbedtls_ssl_context *ssl ) +{ + return( mbedtls_ssl_session_reset_int( ssl, 0 ) ); +} + +/* + * SSL set accessors + */ +void mbedtls_ssl_conf_endpoint( mbedtls_ssl_config *conf, int endpoint ) +{ + conf->endpoint = endpoint; +} + +void mbedtls_ssl_conf_transport( mbedtls_ssl_config *conf, int transport ) +{ + conf->transport = transport; +} + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +void mbedtls_ssl_conf_dtls_anti_replay( mbedtls_ssl_config *conf, char mode ) +{ + conf->anti_replay = mode; +} +#endif + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) +void mbedtls_ssl_conf_dtls_badmac_limit( mbedtls_ssl_config *conf, unsigned limit ) +{ + conf->badmac_limit = limit; +} +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + +void mbedtls_ssl_set_datagram_packing( mbedtls_ssl_context *ssl, + unsigned allow_packing ) +{ + ssl->disable_datagram_packing = !allow_packing; +} + +void mbedtls_ssl_conf_handshake_timeout( mbedtls_ssl_config *conf, + uint32_t min, uint32_t max ) +{ + conf->hs_timeout_min = min; + conf->hs_timeout_max = max; +} +#endif + +void mbedtls_ssl_conf_authmode( mbedtls_ssl_config *conf, int authmode ) +{ + conf->authmode = authmode; +} + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +void mbedtls_ssl_conf_verify( mbedtls_ssl_config *conf, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ) +{ + conf->f_vrfy = f_vrfy; + conf->p_vrfy = p_vrfy; +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +void mbedtls_ssl_conf_rng( mbedtls_ssl_config *conf, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + conf->f_rng = f_rng; + conf->p_rng = p_rng; +} + +void mbedtls_ssl_conf_dbg( mbedtls_ssl_config *conf, + void (*f_dbg)(void *, int, const char *, int, const char *), + void *p_dbg ) +{ + conf->f_dbg = f_dbg; + conf->p_dbg = p_dbg; +} + +void mbedtls_ssl_set_bio( mbedtls_ssl_context *ssl, + void *p_bio, + mbedtls_ssl_send_t *f_send, + mbedtls_ssl_recv_t *f_recv, + mbedtls_ssl_recv_timeout_t *f_recv_timeout ) +{ + ssl->p_bio = p_bio; + ssl->f_send = f_send; + ssl->f_recv = f_recv; + ssl->f_recv_timeout = f_recv_timeout; +} + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +void mbedtls_ssl_set_mtu( mbedtls_ssl_context *ssl, uint16_t mtu ) +{ + ssl->mtu = mtu; +} +#endif + +void mbedtls_ssl_conf_read_timeout( mbedtls_ssl_config *conf, uint32_t timeout ) +{ + conf->read_timeout = timeout; +} + +void mbedtls_ssl_set_timer_cb( mbedtls_ssl_context *ssl, + void *p_timer, + mbedtls_ssl_set_timer_t *f_set_timer, + mbedtls_ssl_get_timer_t *f_get_timer ) +{ + ssl->p_timer = p_timer; + ssl->f_set_timer = f_set_timer; + ssl->f_get_timer = f_get_timer; + + /* Make sure we start with no timer running */ + mbedtls_ssl_set_timer( ssl, 0 ); +} + +#if defined(MBEDTLS_SSL_SRV_C) +void mbedtls_ssl_conf_session_cache( mbedtls_ssl_config *conf, + void *p_cache, + int (*f_get_cache)(void *, mbedtls_ssl_session *), + int (*f_set_cache)(void *, const mbedtls_ssl_session *) ) +{ + conf->p_cache = p_cache; + conf->f_get_cache = f_get_cache; + conf->f_set_cache = f_set_cache; +} +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_CLI_C) +int mbedtls_ssl_set_session( mbedtls_ssl_context *ssl, const mbedtls_ssl_session *session ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ssl == NULL || + session == NULL || + ssl->session_negotiate == NULL || + ssl->conf->endpoint != MBEDTLS_SSL_IS_CLIENT ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + if( ( ret = mbedtls_ssl_session_copy( ssl->session_negotiate, + session ) ) != 0 ) + return( ret ); + + ssl->handshake->resume = 1; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_CLI_C */ + +void mbedtls_ssl_conf_ciphersuites( mbedtls_ssl_config *conf, + const int *ciphersuites ) +{ + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_0] = ciphersuites; + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_1] = ciphersuites; + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_2] = ciphersuites; + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_3] = ciphersuites; +} + +void mbedtls_ssl_conf_ciphersuites_for_version( mbedtls_ssl_config *conf, + const int *ciphersuites, + int major, int minor ) +{ + if( major != MBEDTLS_SSL_MAJOR_VERSION_3 ) + return; + + if( minor < MBEDTLS_SSL_MINOR_VERSION_0 || minor > MBEDTLS_SSL_MINOR_VERSION_3 ) + return; + + conf->ciphersuite_list[minor] = ciphersuites; +} + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +void mbedtls_ssl_conf_cert_profile( mbedtls_ssl_config *conf, + const mbedtls_x509_crt_profile *profile ) +{ + conf->cert_profile = profile; +} + +/* Append a new keycert entry to a (possibly empty) list */ +static int ssl_append_key_cert( mbedtls_ssl_key_cert **head, + mbedtls_x509_crt *cert, + mbedtls_pk_context *key ) +{ + mbedtls_ssl_key_cert *new_cert; + + new_cert = mbedtls_calloc( 1, sizeof( mbedtls_ssl_key_cert ) ); + if( new_cert == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + new_cert->cert = cert; + new_cert->key = key; + new_cert->next = NULL; + + /* Update head is the list was null, else add to the end */ + if( *head == NULL ) + { + *head = new_cert; + } + else + { + mbedtls_ssl_key_cert *cur = *head; + while( cur->next != NULL ) + cur = cur->next; + cur->next = new_cert; + } + + return( 0 ); +} + +int mbedtls_ssl_conf_own_cert( mbedtls_ssl_config *conf, + mbedtls_x509_crt *own_cert, + mbedtls_pk_context *pk_key ) +{ + return( ssl_append_key_cert( &conf->key_cert, own_cert, pk_key ) ); +} + +void mbedtls_ssl_conf_ca_chain( mbedtls_ssl_config *conf, + mbedtls_x509_crt *ca_chain, + mbedtls_x509_crl *ca_crl ) +{ + conf->ca_chain = ca_chain; + conf->ca_crl = ca_crl; + +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + /* mbedtls_ssl_conf_ca_chain() and mbedtls_ssl_conf_ca_cb() + * cannot be used together. */ + conf->f_ca_cb = NULL; + conf->p_ca_cb = NULL; +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ +} + +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) +void mbedtls_ssl_conf_ca_cb( mbedtls_ssl_config *conf, + mbedtls_x509_crt_ca_cb_t f_ca_cb, + void *p_ca_cb ) +{ + conf->f_ca_cb = f_ca_cb; + conf->p_ca_cb = p_ca_cb; + + /* mbedtls_ssl_conf_ca_chain() and mbedtls_ssl_conf_ca_cb() + * cannot be used together. */ + conf->ca_chain = NULL; + conf->ca_crl = NULL; +} +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +int mbedtls_ssl_set_hs_own_cert( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *own_cert, + mbedtls_pk_context *pk_key ) +{ + return( ssl_append_key_cert( &ssl->handshake->sni_key_cert, + own_cert, pk_key ) ); +} + +void mbedtls_ssl_set_hs_ca_chain( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *ca_chain, + mbedtls_x509_crl *ca_crl ) +{ + ssl->handshake->sni_ca_chain = ca_chain; + ssl->handshake->sni_ca_crl = ca_crl; +} + +void mbedtls_ssl_set_hs_authmode( mbedtls_ssl_context *ssl, + int authmode ) +{ + ssl->handshake->sni_authmode = authmode; +} +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +void mbedtls_ssl_set_verify( mbedtls_ssl_context *ssl, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ) +{ + ssl->f_vrfy = f_vrfy; + ssl->p_vrfy = p_vrfy; +} +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +/* + * Set EC J-PAKE password for current handshake + */ +int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl, + const unsigned char *pw, + size_t pw_len ) +{ + mbedtls_ecjpake_role role; + + if( ssl->handshake == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + role = MBEDTLS_ECJPAKE_SERVER; + else + role = MBEDTLS_ECJPAKE_CLIENT; + + return( mbedtls_ecjpake_setup( &ssl->handshake->ecjpake_ctx, + role, + MBEDTLS_MD_SHA256, + MBEDTLS_ECP_DP_SECP256R1, + pw, pw_len ) ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) + +static void ssl_conf_remove_psk( mbedtls_ssl_config *conf ) +{ + /* Remove reference to existing PSK, if any. */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( conf->psk_opaque != 0 ) + { + /* The maintenance of the PSK key slot is the + * user's responsibility. */ + conf->psk_opaque = 0; + } + /* This and the following branch should never + * be taken simultaenously as we maintain the + * invariant that raw and opaque PSKs are never + * configured simultaneously. As a safeguard, + * though, `else` is omitted here. */ +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + if( conf->psk != NULL ) + { + mbedtls_platform_zeroize( conf->psk, conf->psk_len ); + + mbedtls_free( conf->psk ); + conf->psk = NULL; + conf->psk_len = 0; + } + + /* Remove reference to PSK identity, if any. */ + if( conf->psk_identity != NULL ) + { + mbedtls_free( conf->psk_identity ); + conf->psk_identity = NULL; + conf->psk_identity_len = 0; + } +} + +/* This function assumes that PSK identity in the SSL config is unset. + * It checks that the provided identity is well-formed and attempts + * to make a copy of it in the SSL config. + * On failure, the PSK identity in the config remains unset. */ +static int ssl_conf_set_psk_identity( mbedtls_ssl_config *conf, + unsigned char const *psk_identity, + size_t psk_identity_len ) +{ + /* Identity len will be encoded on two bytes */ + if( psk_identity == NULL || + ( psk_identity_len >> 16 ) != 0 || + psk_identity_len > MBEDTLS_SSL_OUT_CONTENT_LEN ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + conf->psk_identity = mbedtls_calloc( 1, psk_identity_len ); + if( conf->psk_identity == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + conf->psk_identity_len = psk_identity_len; + memcpy( conf->psk_identity, psk_identity, conf->psk_identity_len ); + + return( 0 ); +} + +int mbedtls_ssl_conf_psk( mbedtls_ssl_config *conf, + const unsigned char *psk, size_t psk_len, + const unsigned char *psk_identity, size_t psk_identity_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + /* Remove opaque/raw PSK + PSK Identity */ + ssl_conf_remove_psk( conf ); + + /* Check and set raw PSK */ + if( psk == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + if( psk_len == 0 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + if( psk_len > MBEDTLS_PSK_MAX_LEN ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( ( conf->psk = mbedtls_calloc( 1, psk_len ) ) == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + conf->psk_len = psk_len; + memcpy( conf->psk, psk, conf->psk_len ); + + /* Check and set PSK Identity */ + ret = ssl_conf_set_psk_identity( conf, psk_identity, psk_identity_len ); + if( ret != 0 ) + ssl_conf_remove_psk( conf ); + + return( ret ); +} + +static void ssl_remove_psk( mbedtls_ssl_context *ssl ) +{ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ssl->handshake->psk_opaque != 0 ) + { + ssl->handshake->psk_opaque = 0; + } + else +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + if( ssl->handshake->psk != NULL ) + { + mbedtls_platform_zeroize( ssl->handshake->psk, + ssl->handshake->psk_len ); + mbedtls_free( ssl->handshake->psk ); + ssl->handshake->psk_len = 0; + } +} + +int mbedtls_ssl_set_hs_psk( mbedtls_ssl_context *ssl, + const unsigned char *psk, size_t psk_len ) +{ + if( psk == NULL || ssl->handshake == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( psk_len > MBEDTLS_PSK_MAX_LEN ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ssl_remove_psk( ssl ); + + if( ( ssl->handshake->psk = mbedtls_calloc( 1, psk_len ) ) == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + ssl->handshake->psk_len = psk_len; + memcpy( ssl->handshake->psk, psk, ssl->handshake->psk_len ); + + return( 0 ); +} + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +int mbedtls_ssl_conf_psk_opaque( mbedtls_ssl_config *conf, + psa_key_handle_t psk_slot, + const unsigned char *psk_identity, + size_t psk_identity_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + /* Clear opaque/raw PSK + PSK Identity, if present. */ + ssl_conf_remove_psk( conf ); + + /* Check and set opaque PSK */ + if( psk_slot == 0 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + conf->psk_opaque = psk_slot; + + /* Check and set PSK Identity */ + ret = ssl_conf_set_psk_identity( conf, psk_identity, + psk_identity_len ); + if( ret != 0 ) + ssl_conf_remove_psk( conf ); + + return( ret ); +} + +int mbedtls_ssl_set_hs_psk_opaque( mbedtls_ssl_context *ssl, + psa_key_handle_t psk_slot ) +{ + if( psk_slot == 0 || ssl->handshake == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ssl_remove_psk( ssl ); + ssl->handshake->psk_opaque = psk_slot; + return( 0 ); +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +void mbedtls_ssl_conf_psk_cb( mbedtls_ssl_config *conf, + int (*f_psk)(void *, mbedtls_ssl_context *, const unsigned char *, + size_t), + void *p_psk ) +{ + conf->f_psk = f_psk; + conf->p_psk = p_psk; +} +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +int mbedtls_ssl_conf_dh_param( mbedtls_ssl_config *conf, const char *dhm_P, const char *dhm_G ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ( ret = mbedtls_mpi_read_string( &conf->dhm_P, 16, dhm_P ) ) != 0 || + ( ret = mbedtls_mpi_read_string( &conf->dhm_G, 16, dhm_G ) ) != 0 ) + { + mbedtls_mpi_free( &conf->dhm_P ); + mbedtls_mpi_free( &conf->dhm_G ); + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +int mbedtls_ssl_conf_dh_param_bin( mbedtls_ssl_config *conf, + const unsigned char *dhm_P, size_t P_len, + const unsigned char *dhm_G, size_t G_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ( ret = mbedtls_mpi_read_binary( &conf->dhm_P, dhm_P, P_len ) ) != 0 || + ( ret = mbedtls_mpi_read_binary( &conf->dhm_G, dhm_G, G_len ) ) != 0 ) + { + mbedtls_mpi_free( &conf->dhm_P ); + mbedtls_mpi_free( &conf->dhm_G ); + return( ret ); + } + + return( 0 ); +} + +int mbedtls_ssl_conf_dh_param_ctx( mbedtls_ssl_config *conf, mbedtls_dhm_context *dhm_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ( ret = mbedtls_mpi_copy( &conf->dhm_P, &dhm_ctx->P ) ) != 0 || + ( ret = mbedtls_mpi_copy( &conf->dhm_G, &dhm_ctx->G ) ) != 0 ) + { + mbedtls_mpi_free( &conf->dhm_P ); + mbedtls_mpi_free( &conf->dhm_G ); + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) +/* + * Set the minimum length for Diffie-Hellman parameters + */ +void mbedtls_ssl_conf_dhm_min_bitlen( mbedtls_ssl_config *conf, + unsigned int bitlen ) +{ + conf->dhm_min_bitlen = bitlen; +} +#endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) +/* + * Set allowed/preferred hashes for handshake signatures + */ +void mbedtls_ssl_conf_sig_hashes( mbedtls_ssl_config *conf, + const int *hashes ) +{ + conf->sig_hashes = hashes; +} +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + +#if defined(MBEDTLS_ECP_C) +/* + * Set the allowed elliptic curves + */ +void mbedtls_ssl_conf_curves( mbedtls_ssl_config *conf, + const mbedtls_ecp_group_id *curve_list ) +{ + conf->curve_list = curve_list; +} +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +int mbedtls_ssl_set_hostname( mbedtls_ssl_context *ssl, const char *hostname ) +{ + /* Initialize to suppress unnecessary compiler warning */ + size_t hostname_len = 0; + + /* Check if new hostname is valid before + * making any change to current one */ + if( hostname != NULL ) + { + hostname_len = strlen( hostname ); + + if( hostname_len > MBEDTLS_SSL_MAX_HOST_NAME_LEN ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + /* Now it's clear that we will overwrite the old hostname, + * so we can free it safely */ + + if( ssl->hostname != NULL ) + { + mbedtls_platform_zeroize( ssl->hostname, strlen( ssl->hostname ) ); + mbedtls_free( ssl->hostname ); + } + + /* Passing NULL as hostname shall clear the old one */ + + if( hostname == NULL ) + { + ssl->hostname = NULL; + } + else + { + ssl->hostname = mbedtls_calloc( 1, hostname_len + 1 ); + if( ssl->hostname == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + memcpy( ssl->hostname, hostname, hostname_len ); + + ssl->hostname[hostname_len] = '\0'; + } + + return( 0 ); +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +void mbedtls_ssl_conf_sni( mbedtls_ssl_config *conf, + int (*f_sni)(void *, mbedtls_ssl_context *, + const unsigned char *, size_t), + void *p_sni ) +{ + conf->f_sni = f_sni; + conf->p_sni = p_sni; +} +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_SSL_ALPN) +int mbedtls_ssl_conf_alpn_protocols( mbedtls_ssl_config *conf, const char **protos ) +{ + size_t cur_len, tot_len; + const char **p; + + /* + * RFC 7301 3.1: "Empty strings MUST NOT be included and byte strings + * MUST NOT be truncated." + * We check lengths now rather than later. + */ + tot_len = 0; + for( p = protos; *p != NULL; p++ ) + { + cur_len = strlen( *p ); + tot_len += cur_len; + + if( ( cur_len == 0 ) || + ( cur_len > MBEDTLS_SSL_MAX_ALPN_NAME_LEN ) || + ( tot_len > MBEDTLS_SSL_MAX_ALPN_LIST_LEN ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + conf->alpn_list = protos; + + return( 0 ); +} + +const char *mbedtls_ssl_get_alpn_protocol( const mbedtls_ssl_context *ssl ) +{ + return( ssl->alpn_chosen ); +} +#endif /* MBEDTLS_SSL_ALPN */ + +#if defined(MBEDTLS_SSL_DTLS_SRTP) +void mbedtls_ssl_conf_srtp_mki_value_supported( mbedtls_ssl_config *conf, + int support_mki_value ) +{ + conf->dtls_srtp_mki_support = support_mki_value; +} + +int mbedtls_ssl_dtls_srtp_set_mki_value( mbedtls_ssl_context *ssl, + unsigned char *mki_value, + uint16_t mki_len ) +{ + if( mki_len > MBEDTLS_TLS_SRTP_MAX_MKI_LENGTH ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + if( ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_UNSUPPORTED ) + { + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + + memcpy( ssl->dtls_srtp_info.mki_value, mki_value, mki_len ); + ssl->dtls_srtp_info.mki_len = mki_len; + return( 0 ); +} + +int mbedtls_ssl_conf_dtls_srtp_protection_profiles( mbedtls_ssl_config *conf, + const mbedtls_ssl_srtp_profile *profiles ) +{ + const mbedtls_ssl_srtp_profile *p; + size_t list_size = 0; + + /* check the profiles list: all entry must be valid, + * its size cannot be more than the total number of supported profiles, currently 4 */ + for( p = profiles; *p != MBEDTLS_TLS_SRTP_UNSET && + list_size <= MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH; + p++ ) + { + if( mbedtls_ssl_check_srtp_profile_value( *p ) != MBEDTLS_TLS_SRTP_UNSET ) + { + list_size++; + } + else + { + /* unsupported value, stop parsing and set the size to an error value */ + list_size = MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH + 1; + } + } + + if( list_size > MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH ) + { + conf->dtls_srtp_profile_list = NULL; + conf->dtls_srtp_profile_list_len = 0; + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + conf->dtls_srtp_profile_list = profiles; + conf->dtls_srtp_profile_list_len = list_size; + + return( 0 ); +} + +void mbedtls_ssl_get_dtls_srtp_negotiation_result( const mbedtls_ssl_context *ssl, + mbedtls_dtls_srtp_info *dtls_srtp_info ) +{ + dtls_srtp_info->chosen_dtls_srtp_profile = ssl->dtls_srtp_info.chosen_dtls_srtp_profile; + /* do not copy the mki value if there is no chosen profile */ + if( dtls_srtp_info->chosen_dtls_srtp_profile == MBEDTLS_TLS_SRTP_UNSET ) + { + dtls_srtp_info->mki_len = 0; + } + else + { + dtls_srtp_info->mki_len = ssl->dtls_srtp_info.mki_len; + memcpy( dtls_srtp_info->mki_value, ssl->dtls_srtp_info.mki_value, + ssl->dtls_srtp_info.mki_len ); + } +} +#endif /* MBEDTLS_SSL_DTLS_SRTP */ + +void mbedtls_ssl_conf_max_version( mbedtls_ssl_config *conf, int major, int minor ) +{ + conf->max_major_ver = major; + conf->max_minor_ver = minor; +} + +void mbedtls_ssl_conf_min_version( mbedtls_ssl_config *conf, int major, int minor ) +{ + conf->min_major_ver = major; + conf->min_minor_ver = minor; +} + +#if defined(MBEDTLS_SSL_FALLBACK_SCSV) && defined(MBEDTLS_SSL_CLI_C) +void mbedtls_ssl_conf_fallback( mbedtls_ssl_config *conf, char fallback ) +{ + conf->fallback = fallback; +} +#endif + +#if defined(MBEDTLS_SSL_SRV_C) +void mbedtls_ssl_conf_cert_req_ca_list( mbedtls_ssl_config *conf, + char cert_req_ca_list ) +{ + conf->cert_req_ca_list = cert_req_ca_list; +} +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +void mbedtls_ssl_conf_encrypt_then_mac( mbedtls_ssl_config *conf, char etm ) +{ + conf->encrypt_then_mac = etm; +} +#endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +void mbedtls_ssl_conf_extended_master_secret( mbedtls_ssl_config *conf, char ems ) +{ + conf->extended_ms = ems; +} +#endif + +#if defined(MBEDTLS_ARC4_C) +void mbedtls_ssl_conf_arc4_support( mbedtls_ssl_config *conf, char arc4 ) +{ + conf->arc4_disabled = arc4; +} +#endif + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +int mbedtls_ssl_conf_max_frag_len( mbedtls_ssl_config *conf, unsigned char mfl_code ) +{ + if( mfl_code >= MBEDTLS_SSL_MAX_FRAG_LEN_INVALID || + ssl_mfl_code_to_length( mfl_code ) > MBEDTLS_TLS_EXT_ADV_CONTENT_LEN ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + conf->mfl_code = mfl_code; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) +void mbedtls_ssl_conf_truncated_hmac( mbedtls_ssl_config *conf, int truncate ) +{ + conf->trunc_hmac = truncate; +} +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) +void mbedtls_ssl_conf_cbc_record_splitting( mbedtls_ssl_config *conf, char split ) +{ + conf->cbc_record_splitting = split; +} +#endif + +void mbedtls_ssl_conf_legacy_renegotiation( mbedtls_ssl_config *conf, int allow_legacy ) +{ + conf->allow_legacy_renegotiation = allow_legacy; +} + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +void mbedtls_ssl_conf_renegotiation( mbedtls_ssl_config *conf, int renegotiation ) +{ + conf->disable_renegotiation = renegotiation; +} + +void mbedtls_ssl_conf_renegotiation_enforced( mbedtls_ssl_config *conf, int max_records ) +{ + conf->renego_max_records = max_records; +} + +void mbedtls_ssl_conf_renegotiation_period( mbedtls_ssl_config *conf, + const unsigned char period[8] ) +{ + memcpy( conf->renego_period, period, 8 ); +} +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +#if defined(MBEDTLS_SSL_CLI_C) +void mbedtls_ssl_conf_session_tickets( mbedtls_ssl_config *conf, int use_tickets ) +{ + conf->session_tickets = use_tickets; +} +#endif + +#if defined(MBEDTLS_SSL_SRV_C) +void mbedtls_ssl_conf_session_tickets_cb( mbedtls_ssl_config *conf, + mbedtls_ssl_ticket_write_t *f_ticket_write, + mbedtls_ssl_ticket_parse_t *f_ticket_parse, + void *p_ticket ) +{ + conf->f_ticket_write = f_ticket_write; + conf->f_ticket_parse = f_ticket_parse; + conf->p_ticket = p_ticket; +} +#endif +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_SSL_EXPORT_KEYS) +void mbedtls_ssl_conf_export_keys_cb( mbedtls_ssl_config *conf, + mbedtls_ssl_export_keys_t *f_export_keys, + void *p_export_keys ) +{ + conf->f_export_keys = f_export_keys; + conf->p_export_keys = p_export_keys; +} + +void mbedtls_ssl_conf_export_keys_ext_cb( mbedtls_ssl_config *conf, + mbedtls_ssl_export_keys_ext_t *f_export_keys_ext, + void *p_export_keys ) +{ + conf->f_export_keys_ext = f_export_keys_ext; + conf->p_export_keys = p_export_keys; +} +#endif + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) +void mbedtls_ssl_conf_async_private_cb( + mbedtls_ssl_config *conf, + mbedtls_ssl_async_sign_t *f_async_sign, + mbedtls_ssl_async_decrypt_t *f_async_decrypt, + mbedtls_ssl_async_resume_t *f_async_resume, + mbedtls_ssl_async_cancel_t *f_async_cancel, + void *async_config_data ) +{ + conf->f_async_sign_start = f_async_sign; + conf->f_async_decrypt_start = f_async_decrypt; + conf->f_async_resume = f_async_resume; + conf->f_async_cancel = f_async_cancel; + conf->p_async_config_data = async_config_data; +} + +void *mbedtls_ssl_conf_get_async_config_data( const mbedtls_ssl_config *conf ) +{ + return( conf->p_async_config_data ); +} + +void *mbedtls_ssl_get_async_operation_data( const mbedtls_ssl_context *ssl ) +{ + if( ssl->handshake == NULL ) + return( NULL ); + else + return( ssl->handshake->user_async_ctx ); +} + +void mbedtls_ssl_set_async_operation_data( mbedtls_ssl_context *ssl, + void *ctx ) +{ + if( ssl->handshake != NULL ) + ssl->handshake->user_async_ctx = ctx; +} +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + +/* + * SSL get accessors + */ +uint32_t mbedtls_ssl_get_verify_result( const mbedtls_ssl_context *ssl ) +{ + if( ssl->session != NULL ) + return( ssl->session->verify_result ); + + if( ssl->session_negotiate != NULL ) + return( ssl->session_negotiate->verify_result ); + + return( 0xFFFFFFFF ); +} + +const char *mbedtls_ssl_get_ciphersuite( const mbedtls_ssl_context *ssl ) +{ + if( ssl == NULL || ssl->session == NULL ) + return( NULL ); + + return mbedtls_ssl_get_ciphersuite_name( ssl->session->ciphersuite ); +} + +const char *mbedtls_ssl_get_version( const mbedtls_ssl_context *ssl ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + switch( ssl->minor_ver ) + { + case MBEDTLS_SSL_MINOR_VERSION_2: + return( "DTLSv1.0" ); + + case MBEDTLS_SSL_MINOR_VERSION_3: + return( "DTLSv1.2" ); + + default: + return( "unknown (DTLS)" ); + } + } +#endif + + switch( ssl->minor_ver ) + { + case MBEDTLS_SSL_MINOR_VERSION_0: + return( "SSLv3.0" ); + + case MBEDTLS_SSL_MINOR_VERSION_1: + return( "TLSv1.0" ); + + case MBEDTLS_SSL_MINOR_VERSION_2: + return( "TLSv1.1" ); + + case MBEDTLS_SSL_MINOR_VERSION_3: + return( "TLSv1.2" ); + + default: + return( "unknown" ); + } +} + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +size_t mbedtls_ssl_get_input_max_frag_len( const mbedtls_ssl_context *ssl ) +{ + size_t max_len = MBEDTLS_SSL_MAX_CONTENT_LEN; + size_t read_mfl; + + /* Use the configured MFL for the client if we're past SERVER_HELLO_DONE */ + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && + ssl->state >= MBEDTLS_SSL_SERVER_HELLO_DONE ) + { + return ssl_mfl_code_to_length( ssl->conf->mfl_code ); + } + + /* Check if a smaller max length was negotiated */ + if( ssl->session_out != NULL ) + { + read_mfl = ssl_mfl_code_to_length( ssl->session_out->mfl_code ); + if( read_mfl < max_len ) + { + max_len = read_mfl; + } + } + + // During a handshake, use the value being negotiated + if( ssl->session_negotiate != NULL ) + { + read_mfl = ssl_mfl_code_to_length( ssl->session_negotiate->mfl_code ); + if( read_mfl < max_len ) + { + max_len = read_mfl; + } + } + + return( max_len ); +} + +size_t mbedtls_ssl_get_output_max_frag_len( const mbedtls_ssl_context *ssl ) +{ + size_t max_len; + + /* + * Assume mfl_code is correct since it was checked when set + */ + max_len = ssl_mfl_code_to_length( ssl->conf->mfl_code ); + + /* Check if a smaller max length was negotiated */ + if( ssl->session_out != NULL && + ssl_mfl_code_to_length( ssl->session_out->mfl_code ) < max_len ) + { + max_len = ssl_mfl_code_to_length( ssl->session_out->mfl_code ); + } + + /* During a handshake, use the value being negotiated */ + if( ssl->session_negotiate != NULL && + ssl_mfl_code_to_length( ssl->session_negotiate->mfl_code ) < max_len ) + { + max_len = ssl_mfl_code_to_length( ssl->session_negotiate->mfl_code ); + } + + return( max_len ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +size_t mbedtls_ssl_get_max_frag_len( const mbedtls_ssl_context *ssl ) +{ + return mbedtls_ssl_get_output_max_frag_len( ssl ); +} +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +size_t mbedtls_ssl_get_current_mtu( const mbedtls_ssl_context *ssl ) +{ + /* Return unlimited mtu for client hello messages to avoid fragmentation. */ + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && + ( ssl->state == MBEDTLS_SSL_CLIENT_HELLO || + ssl->state == MBEDTLS_SSL_SERVER_HELLO ) ) + return ( 0 ); + + if( ssl->handshake == NULL || ssl->handshake->mtu == 0 ) + return( ssl->mtu ); + + if( ssl->mtu == 0 ) + return( ssl->handshake->mtu ); + + return( ssl->mtu < ssl->handshake->mtu ? + ssl->mtu : ssl->handshake->mtu ); +} +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +int mbedtls_ssl_get_max_out_record_payload( const mbedtls_ssl_context *ssl ) +{ + size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN; + +#if !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) && \ + !defined(MBEDTLS_SSL_PROTO_DTLS) + (void) ssl; +#endif + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + const size_t mfl = mbedtls_ssl_get_output_max_frag_len( ssl ); + + if( max_len > mfl ) + max_len = mfl; +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( mbedtls_ssl_get_current_mtu( ssl ) != 0 ) + { + const size_t mtu = mbedtls_ssl_get_current_mtu( ssl ); + const int ret = mbedtls_ssl_get_record_expansion( ssl ); + const size_t overhead = (size_t) ret; + + if( ret < 0 ) + return( ret ); + + if( mtu <= overhead ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "MTU too low for record expansion" ) ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + + if( max_len > mtu - overhead ) + max_len = mtu - overhead; + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) && \ + !defined(MBEDTLS_SSL_PROTO_DTLS) + ((void) ssl); +#endif + + return( (int) max_len ); +} + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert( const mbedtls_ssl_context *ssl ) +{ + if( ssl == NULL || ssl->session == NULL ) + return( NULL ); + +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + return( ssl->session->peer_cert ); +#else + return( NULL ); +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_CLI_C) +int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl, + mbedtls_ssl_session *dst ) +{ + if( ssl == NULL || + dst == NULL || + ssl->session == NULL || + ssl->conf->endpoint != MBEDTLS_SSL_IS_CLIENT ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + return( mbedtls_ssl_session_copy( dst, ssl->session ) ); +} +#endif /* MBEDTLS_SSL_CLI_C */ + +const mbedtls_ssl_session *mbedtls_ssl_get_session_pointer( const mbedtls_ssl_context *ssl ) +{ + if( ssl == NULL ) + return( NULL ); + + return( ssl->session ); +} + +/* + * Define ticket header determining Mbed TLS version + * and structure of the ticket. + */ + +/* + * Define bitflag determining compile-time settings influencing + * structure of serialized SSL sessions. + */ + +#if defined(MBEDTLS_HAVE_TIME) +#define SSL_SERIALIZED_SESSION_CONFIG_TIME 1 +#else +#define SSL_SERIALIZED_SESSION_CONFIG_TIME 0 +#endif /* MBEDTLS_HAVE_TIME */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#define SSL_SERIALIZED_SESSION_CONFIG_CRT 1 +#else +#define SSL_SERIALIZED_SESSION_CONFIG_CRT 0 +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_CLI_C) && defined(MBEDTLS_SSL_SESSION_TICKETS) +#define SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET 1 +#else +#define SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET 0 +#endif /* MBEDTLS_SSL_CLI_C && MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +#define SSL_SERIALIZED_SESSION_CONFIG_MFL 1 +#else +#define SSL_SERIALIZED_SESSION_CONFIG_MFL 0 +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) +#define SSL_SERIALIZED_SESSION_CONFIG_TRUNC_HMAC 1 +#else +#define SSL_SERIALIZED_SESSION_CONFIG_TRUNC_HMAC 0 +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +#define SSL_SERIALIZED_SESSION_CONFIG_ETM 1 +#else +#define SSL_SERIALIZED_SESSION_CONFIG_ETM 0 +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +#define SSL_SERIALIZED_SESSION_CONFIG_TICKET 1 +#else +#define SSL_SERIALIZED_SESSION_CONFIG_TICKET 0 +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#define SSL_SERIALIZED_SESSION_CONFIG_TIME_BIT 0 +#define SSL_SERIALIZED_SESSION_CONFIG_CRT_BIT 1 +#define SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET_BIT 2 +#define SSL_SERIALIZED_SESSION_CONFIG_MFL_BIT 3 +#define SSL_SERIALIZED_SESSION_CONFIG_TRUNC_HMAC_BIT 4 +#define SSL_SERIALIZED_SESSION_CONFIG_ETM_BIT 5 +#define SSL_SERIALIZED_SESSION_CONFIG_TICKET_BIT 6 + +#define SSL_SERIALIZED_SESSION_CONFIG_BITFLAG \ + ( (uint16_t) ( \ + ( SSL_SERIALIZED_SESSION_CONFIG_TIME << SSL_SERIALIZED_SESSION_CONFIG_TIME_BIT ) | \ + ( SSL_SERIALIZED_SESSION_CONFIG_CRT << SSL_SERIALIZED_SESSION_CONFIG_CRT_BIT ) | \ + ( SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET << SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET_BIT ) | \ + ( SSL_SERIALIZED_SESSION_CONFIG_MFL << SSL_SERIALIZED_SESSION_CONFIG_MFL_BIT ) | \ + ( SSL_SERIALIZED_SESSION_CONFIG_TRUNC_HMAC << SSL_SERIALIZED_SESSION_CONFIG_TRUNC_HMAC_BIT ) | \ + ( SSL_SERIALIZED_SESSION_CONFIG_ETM << SSL_SERIALIZED_SESSION_CONFIG_ETM_BIT ) | \ + ( SSL_SERIALIZED_SESSION_CONFIG_TICKET << SSL_SERIALIZED_SESSION_CONFIG_TICKET_BIT ) ) ) + +static unsigned char ssl_serialized_session_header[] = { + MBEDTLS_VERSION_MAJOR, + MBEDTLS_VERSION_MINOR, + MBEDTLS_VERSION_PATCH, + ( SSL_SERIALIZED_SESSION_CONFIG_BITFLAG >> 8 ) & 0xFF, + ( SSL_SERIALIZED_SESSION_CONFIG_BITFLAG >> 0 ) & 0xFF, +}; + +/* + * Serialize a session in the following format: + * (in the presentation language of TLS, RFC 8446 section 3) + * + * opaque mbedtls_version[3]; // major, minor, patch + * opaque session_format[2]; // version-specific 16-bit field determining + * // the format of the remaining + * // serialized data. + * + * Note: When updating the format, remember to keep + * these version+format bytes. + * + * // In this version, `session_format` determines + * // the setting of those compile-time + * // configuration options which influence + * // the structure of mbedtls_ssl_session. + * uint64 start_time; + * uint8 ciphersuite[2]; // defined by the standard + * uint8 compression; // 0 or 1 + * uint8 session_id_len; // at most 32 + * opaque session_id[32]; + * opaque master[48]; // fixed length in the standard + * uint32 verify_result; + * opaque peer_cert<0..2^24-1>; // length 0 means no peer cert + * opaque ticket<0..2^24-1>; // length 0 means no ticket + * uint32 ticket_lifetime; + * uint8 mfl_code; // up to 255 according to standard + * uint8 trunc_hmac; // 0 or 1 + * uint8 encrypt_then_mac; // 0 or 1 + * + * The order is the same as in the definition of the structure, except + * verify_result is put before peer_cert so that all mandatory fields come + * together in one block. + */ +static int ssl_session_save( const mbedtls_ssl_session *session, + unsigned char omit_header, + unsigned char *buf, + size_t buf_len, + size_t *olen ) +{ + unsigned char *p = buf; + size_t used = 0; +#if defined(MBEDTLS_HAVE_TIME) + uint64_t start; +#endif +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + size_t cert_len; +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + + if( !omit_header ) + { + /* + * Add version identifier + */ + + used += sizeof( ssl_serialized_session_header ); + + if( used <= buf_len ) + { + memcpy( p, ssl_serialized_session_header, + sizeof( ssl_serialized_session_header ) ); + p += sizeof( ssl_serialized_session_header ); + } + } + + /* + * Time + */ +#if defined(MBEDTLS_HAVE_TIME) + used += 8; + + if( used <= buf_len ) + { + start = (uint64_t) session->start; + + *p++ = (unsigned char)( ( start >> 56 ) & 0xFF ); + *p++ = (unsigned char)( ( start >> 48 ) & 0xFF ); + *p++ = (unsigned char)( ( start >> 40 ) & 0xFF ); + *p++ = (unsigned char)( ( start >> 32 ) & 0xFF ); + *p++ = (unsigned char)( ( start >> 24 ) & 0xFF ); + *p++ = (unsigned char)( ( start >> 16 ) & 0xFF ); + *p++ = (unsigned char)( ( start >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( start ) & 0xFF ); + } +#endif /* MBEDTLS_HAVE_TIME */ + + /* + * Basic mandatory fields + */ + used += 2 /* ciphersuite */ + + 1 /* compression */ + + 1 /* id_len */ + + sizeof( session->id ) + + sizeof( session->master ) + + 4; /* verify_result */ + + if( used <= buf_len ) + { + *p++ = (unsigned char)( ( session->ciphersuite >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( session->ciphersuite ) & 0xFF ); + + *p++ = (unsigned char)( session->compression & 0xFF ); + + *p++ = (unsigned char)( session->id_len & 0xFF ); + memcpy( p, session->id, 32 ); + p += 32; + + memcpy( p, session->master, 48 ); + p += 48; + + *p++ = (unsigned char)( ( session->verify_result >> 24 ) & 0xFF ); + *p++ = (unsigned char)( ( session->verify_result >> 16 ) & 0xFF ); + *p++ = (unsigned char)( ( session->verify_result >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( session->verify_result ) & 0xFF ); + } + + /* + * Peer's end-entity certificate + */ +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + if( session->peer_cert == NULL ) + cert_len = 0; + else + cert_len = session->peer_cert->raw.len; + + used += 3 + cert_len; + + if( used <= buf_len ) + { + *p++ = (unsigned char)( ( cert_len >> 16 ) & 0xFF ); + *p++ = (unsigned char)( ( cert_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( cert_len ) & 0xFF ); + + if( session->peer_cert != NULL ) + { + memcpy( p, session->peer_cert->raw.p, cert_len ); + p += cert_len; + } + } +#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + if( session->peer_cert_digest != NULL ) + { + used += 1 /* type */ + 1 /* length */ + session->peer_cert_digest_len; + if( used <= buf_len ) + { + *p++ = (unsigned char) session->peer_cert_digest_type; + *p++ = (unsigned char) session->peer_cert_digest_len; + memcpy( p, session->peer_cert_digest, + session->peer_cert_digest_len ); + p += session->peer_cert_digest_len; + } + } + else + { + used += 2; + if( used <= buf_len ) + { + *p++ = (unsigned char) MBEDTLS_MD_NONE; + *p++ = 0; + } + } +#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + /* + * Session ticket if any, plus associated data + */ +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) + used += 3 + session->ticket_len + 4; /* len + ticket + lifetime */ + + if( used <= buf_len ) + { + *p++ = (unsigned char)( ( session->ticket_len >> 16 ) & 0xFF ); + *p++ = (unsigned char)( ( session->ticket_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( session->ticket_len ) & 0xFF ); + + if( session->ticket != NULL ) + { + memcpy( p, session->ticket, session->ticket_len ); + p += session->ticket_len; + } + + *p++ = (unsigned char)( ( session->ticket_lifetime >> 24 ) & 0xFF ); + *p++ = (unsigned char)( ( session->ticket_lifetime >> 16 ) & 0xFF ); + *p++ = (unsigned char)( ( session->ticket_lifetime >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( session->ticket_lifetime ) & 0xFF ); + } +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ + + /* + * Misc extension-related info + */ +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + used += 1; + + if( used <= buf_len ) + *p++ = session->mfl_code; +#endif + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + used += 1; + + if( used <= buf_len ) + *p++ = (unsigned char)( ( session->trunc_hmac ) & 0xFF ); +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + used += 1; + + if( used <= buf_len ) + *p++ = (unsigned char)( ( session->encrypt_then_mac ) & 0xFF ); +#endif + + /* Done */ + *olen = used; + + if( used > buf_len ) + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + + return( 0 ); +} + +/* + * Public wrapper for ssl_session_save() + */ +int mbedtls_ssl_session_save( const mbedtls_ssl_session *session, + unsigned char *buf, + size_t buf_len, + size_t *olen ) +{ + return( ssl_session_save( session, 0, buf, buf_len, olen ) ); +} + +/* + * Deserialize session, see mbedtls_ssl_session_save() for format. + * + * This internal version is wrapped by a public function that cleans up in + * case of error, and has an extra option omit_header. + */ +static int ssl_session_load( mbedtls_ssl_session *session, + unsigned char omit_header, + const unsigned char *buf, + size_t len ) +{ + const unsigned char *p = buf; + const unsigned char * const end = buf + len; +#if defined(MBEDTLS_HAVE_TIME) + uint64_t start; +#endif +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + size_t cert_len; +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + if( !omit_header ) + { + /* + * Check version identifier + */ + + if( (size_t)( end - p ) < sizeof( ssl_serialized_session_header ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( memcmp( p, ssl_serialized_session_header, + sizeof( ssl_serialized_session_header ) ) != 0 ) + { + return( MBEDTLS_ERR_SSL_VERSION_MISMATCH ); + } + p += sizeof( ssl_serialized_session_header ); + } + + /* + * Time + */ +#if defined(MBEDTLS_HAVE_TIME) + if( 8 > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + start = ( (uint64_t) p[0] << 56 ) | + ( (uint64_t) p[1] << 48 ) | + ( (uint64_t) p[2] << 40 ) | + ( (uint64_t) p[3] << 32 ) | + ( (uint64_t) p[4] << 24 ) | + ( (uint64_t) p[5] << 16 ) | + ( (uint64_t) p[6] << 8 ) | + ( (uint64_t) p[7] ); + p += 8; + + session->start = (time_t) start; +#endif /* MBEDTLS_HAVE_TIME */ + + /* + * Basic mandatory fields + */ + if( 2 + 1 + 1 + 32 + 48 + 4 > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + session->ciphersuite = ( p[0] << 8 ) | p[1]; + p += 2; + + session->compression = *p++; + + session->id_len = *p++; + memcpy( session->id, p, 32 ); + p += 32; + + memcpy( session->master, p, 48 ); + p += 48; + + session->verify_result = ( (uint32_t) p[0] << 24 ) | + ( (uint32_t) p[1] << 16 ) | + ( (uint32_t) p[2] << 8 ) | + ( (uint32_t) p[3] ); + p += 4; + + /* Immediately clear invalid pointer values that have been read, in case + * we exit early before we replaced them with valid ones. */ +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + session->peer_cert = NULL; +#else + session->peer_cert_digest = NULL; +#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) + session->ticket = NULL; +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ + + /* + * Peer certificate + */ +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + /* Deserialize CRT from the end of the ticket. */ + if( 3 > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + cert_len = ( p[0] << 16 ) | ( p[1] << 8 ) | p[2]; + p += 3; + + if( cert_len != 0 ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( cert_len > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + session->peer_cert = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) ); + + if( session->peer_cert == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + mbedtls_x509_crt_init( session->peer_cert ); + + if( ( ret = mbedtls_x509_crt_parse_der( session->peer_cert, + p, cert_len ) ) != 0 ) + { + mbedtls_x509_crt_free( session->peer_cert ); + mbedtls_free( session->peer_cert ); + session->peer_cert = NULL; + return( ret ); + } + + p += cert_len; + } +#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + /* Deserialize CRT digest from the end of the ticket. */ + if( 2 > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + session->peer_cert_digest_type = (mbedtls_md_type_t) *p++; + session->peer_cert_digest_len = (size_t) *p++; + + if( session->peer_cert_digest_len != 0 ) + { + const mbedtls_md_info_t *md_info = + mbedtls_md_info_from_type( session->peer_cert_digest_type ); + if( md_info == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + if( session->peer_cert_digest_len != mbedtls_md_get_size( md_info ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( session->peer_cert_digest_len > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + session->peer_cert_digest = + mbedtls_calloc( 1, session->peer_cert_digest_len ); + if( session->peer_cert_digest == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + memcpy( session->peer_cert_digest, p, + session->peer_cert_digest_len ); + p += session->peer_cert_digest_len; + } +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + /* + * Session ticket and associated data + */ +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) + if( 3 > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + session->ticket_len = ( p[0] << 16 ) | ( p[1] << 8 ) | p[2]; + p += 3; + + if( session->ticket_len != 0 ) + { + if( session->ticket_len > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + session->ticket = mbedtls_calloc( 1, session->ticket_len ); + if( session->ticket == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + memcpy( session->ticket, p, session->ticket_len ); + p += session->ticket_len; + } + + if( 4 > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + session->ticket_lifetime = ( (uint32_t) p[0] << 24 ) | + ( (uint32_t) p[1] << 16 ) | + ( (uint32_t) p[2] << 8 ) | + ( (uint32_t) p[3] ); + p += 4; +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ + + /* + * Misc extension-related info + */ +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + if( 1 > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + session->mfl_code = *p++; +#endif + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + if( 1 > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + session->trunc_hmac = *p++; +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + if( 1 > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + session->encrypt_then_mac = *p++; +#endif + + /* Done, should have consumed entire buffer */ + if( p != end ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + return( 0 ); +} + +/* + * Deserialize session: public wrapper for error cleaning + */ +int mbedtls_ssl_session_load( mbedtls_ssl_session *session, + const unsigned char *buf, + size_t len ) +{ + int ret = ssl_session_load( session, 0, buf, len ); + + if( ret != 0 ) + mbedtls_ssl_session_free( session ); + + return( ret ); +} + +/* + * Perform a single step of the SSL handshake + */ +int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + ret = mbedtls_ssl_handshake_client_step( ssl ); +#endif +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + ret = mbedtls_ssl_handshake_server_step( ssl ); +#endif + + return( ret ); +} + +/* + * Perform the SSL handshake + */ +int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl ) +{ + int ret = 0; + + /* Sanity checks */ + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ( ssl->f_set_timer == NULL || ssl->f_get_timer == NULL ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "You must use " + "mbedtls_ssl_set_timer_cb() for DTLS" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> handshake" ) ); + + /* Main handshake loop */ + while( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + { + ret = mbedtls_ssl_handshake_step( ssl ); + + if( ret != 0 ) + break; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= handshake" ) ); + + return( ret ); +} + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +#if defined(MBEDTLS_SSL_SRV_C) +/* + * Write HelloRequest to request renegotiation on server + */ +static int ssl_write_hello_request( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write hello request" ) ); + + ssl->out_msglen = 4; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_HELLO_REQUEST; + + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write hello request" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SRV_C */ + +/* + * Actually renegotiate current connection, triggered by either: + * - any side: calling mbedtls_ssl_renegotiate(), + * - client: receiving a HelloRequest during mbedtls_ssl_read(), + * - server: receiving any handshake message on server during mbedtls_ssl_read() after + * the initial handshake is completed. + * If the handshake doesn't complete due to waiting for I/O, it will continue + * during the next calls to mbedtls_ssl_renegotiate() or mbedtls_ssl_read() respectively. + */ +int mbedtls_ssl_start_renegotiation( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> renegotiate" ) ); + + if( ( ret = ssl_handshake_init( ssl ) ) != 0 ) + return( ret ); + + /* RFC 6347 4.2.2: "[...] the HelloRequest will have message_seq = 0 and + * the ServerHello will have message_seq = 1" */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) + { + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + ssl->handshake->out_msg_seq = 1; + else + ssl->handshake->in_msg_seq = 1; + } +#endif + + ssl->state = MBEDTLS_SSL_HELLO_REQUEST; + ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS; + + if( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= renegotiate" ) ); + + return( 0 ); +} + +/* + * Renegotiate current connection on client, + * or request renegotiation on server + */ +int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_SSL_SRV_C) + /* On server, just send the request */ + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + { + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING; + + /* Did we already try/start sending HelloRequest? */ + if( ssl->out_left != 0 ) + return( mbedtls_ssl_flush_output( ssl ) ); + + return( ssl_write_hello_request( ssl ) ); + } +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_CLI_C) + /* + * On client, either start the renegotiation process or, + * if already in progress, continue the handshake + */ + if( ssl->renego_status != MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + { + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_ssl_start_renegotiation( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_start_renegotiation", ret ); + return( ret ); + } + } + else + { + if( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); + return( ret ); + } + } +#endif /* MBEDTLS_SSL_CLI_C */ + + return( ret ); +} +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +static void ssl_key_cert_free( mbedtls_ssl_key_cert *key_cert ) +{ + mbedtls_ssl_key_cert *cur = key_cert, *next; + + while( cur != NULL ) + { + next = cur->next; + mbedtls_free( cur ); + cur = next; + } +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +void mbedtls_ssl_handshake_free( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + + if( handshake == NULL ) + return; + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + if( ssl->conf->f_async_cancel != NULL && handshake->async_in_progress != 0 ) + { + ssl->conf->f_async_cancel( ssl ); + handshake->async_in_progress = 0; + } +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + mbedtls_md5_free( &handshake->fin_md5 ); + mbedtls_sha1_free( &handshake->fin_sha1 ); +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_hash_abort( &handshake->fin_sha256_psa ); +#else + mbedtls_sha256_free( &handshake->fin_sha256 ); +#endif +#endif +#if defined(MBEDTLS_SHA512_C) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_hash_abort( &handshake->fin_sha384_psa ); +#else + mbedtls_sha512_free( &handshake->fin_sha512 ); +#endif +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_DHM_C) + mbedtls_dhm_free( &handshake->dhm_ctx ); +#endif +#if defined(MBEDTLS_ECDH_C) + mbedtls_ecdh_free( &handshake->ecdh_ctx ); +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + mbedtls_ecjpake_free( &handshake->ecjpake_ctx ); +#if defined(MBEDTLS_SSL_CLI_C) + mbedtls_free( handshake->ecjpake_cache ); + handshake->ecjpake_cache = NULL; + handshake->ecjpake_cache_len = 0; +#endif +#endif + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + /* explicit void pointer cast for buggy MS compiler */ + mbedtls_free( (void *) handshake->curves ); +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) + if( handshake->psk != NULL ) + { + mbedtls_platform_zeroize( handshake->psk, handshake->psk_len ); + mbedtls_free( handshake->psk ); + } +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) && \ + defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + /* + * Free only the linked list wrapper, not the keys themselves + * since the belong to the SNI callback + */ + if( handshake->sni_key_cert != NULL ) + { + mbedtls_ssl_key_cert *cur = handshake->sni_key_cert, *next; + + while( cur != NULL ) + { + next = cur->next; + mbedtls_free( cur ); + cur = next; + } + } +#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + mbedtls_x509_crt_restart_free( &handshake->ecrs_ctx ); + if( handshake->ecrs_peer_cert != NULL ) + { + mbedtls_x509_crt_free( handshake->ecrs_peer_cert ); + mbedtls_free( handshake->ecrs_peer_cert ); + } +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) && \ + !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + mbedtls_pk_free( &handshake->peer_pubkey ); +#endif /* MBEDTLS_X509_CRT_PARSE_C && !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + mbedtls_free( handshake->verify_cookie ); + mbedtls_ssl_flight_free( handshake->flight ); + mbedtls_ssl_buffering_free( ssl ); +#endif + +#if defined(MBEDTLS_ECDH_C) && \ + defined(MBEDTLS_USE_PSA_CRYPTO) + psa_destroy_key( handshake->ecdh_psa_privkey ); +#endif /* MBEDTLS_ECDH_C && MBEDTLS_USE_PSA_CRYPTO */ + + mbedtls_platform_zeroize( handshake, + sizeof( mbedtls_ssl_handshake_params ) ); + +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + /* If the buffers are too big - reallocate. Because of the way Mbed TLS + * processes datagrams and the fact that a datagram is allowed to have + * several records in it, it is possible that the I/O buffers are not + * empty at this stage */ + { + int modified = 0; + uint32_t buf_len = mbedtls_ssl_get_input_buflen( ssl ); + size_t written_in = 0, iv_offset_in = 0, len_offset_in = 0; + size_t written_out = 0, iv_offset_out = 0, len_offset_out = 0; + if( ssl->in_buf != NULL ) + { + written_in = ssl->in_msg - ssl->in_buf; + iv_offset_in = ssl->in_iv - ssl->in_buf; + len_offset_in = ssl->in_len - ssl->in_buf; + if( ssl->in_buf_len > buf_len && ssl->in_left < buf_len ) + { + if( resize_buffer( &ssl->in_buf, buf_len, &ssl->in_buf_len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "input buffer resizing failed - out of memory" ) ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Reallocating in_buf to %d", buf_len ) ); + modified = 1; + } + } + } + + + buf_len = mbedtls_ssl_get_output_buflen( ssl ); + if(ssl->out_buf != NULL ) + { + written_out = ssl->out_msg - ssl->out_buf; + iv_offset_out = ssl->out_iv - ssl->out_buf; + len_offset_out = ssl->out_len - ssl->out_buf; + if( ssl->out_buf_len > mbedtls_ssl_get_output_buflen( ssl ) && + ssl->out_left < buf_len ) + { + if( resize_buffer( &ssl->out_buf, buf_len, &ssl->out_buf_len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "output buffer resizing failed - out of memory" ) ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Reallocating out_buf to %d", buf_len ) ); + modified = 1; + } + } + } + if( modified ) + { + /* Update pointers here to avoid doing it twice. */ + mbedtls_ssl_reset_in_out_pointers( ssl ); + /* Fields below might not be properly updated with record + * splitting or with CID, so they are manually updated here. */ + ssl->out_msg = ssl->out_buf + written_out; + ssl->out_len = ssl->out_buf + len_offset_out; + ssl->out_iv = ssl->out_buf + iv_offset_out; + + ssl->in_msg = ssl->in_buf + written_in; + ssl->in_len = ssl->in_buf + len_offset_in; + ssl->in_iv = ssl->in_buf + iv_offset_in; + } + } +#endif +} + +void mbedtls_ssl_session_free( mbedtls_ssl_session *session ) +{ + if( session == NULL ) + return; + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + ssl_clear_peer_cert( session ); +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) + mbedtls_free( session->ticket ); +#endif + + mbedtls_platform_zeroize( session, sizeof( mbedtls_ssl_session ) ); +} + +#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) +#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID 1u +#else +#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID 0u +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) +#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT 1u +#else +#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT 0u +#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */ + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY 1u +#else +#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY 0u +#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ + +#if defined(MBEDTLS_SSL_ALPN) +#define SSL_SERIALIZED_CONTEXT_CONFIG_ALPN 1u +#else +#define SSL_SERIALIZED_CONTEXT_CONFIG_ALPN 0u +#endif /* MBEDTLS_SSL_ALPN */ + +#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT 0 +#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT 1 +#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT 2 +#define SSL_SERIALIZED_CONTEXT_CONFIG_ALPN_BIT 3 + +#define SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG \ + ( (uint32_t) ( \ + ( SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID << SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT ) | \ + ( SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT << SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT ) | \ + ( SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY << SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT ) | \ + ( SSL_SERIALIZED_CONTEXT_CONFIG_ALPN << SSL_SERIALIZED_CONTEXT_CONFIG_ALPN_BIT ) | \ + 0u ) ) + +static unsigned char ssl_serialized_context_header[] = { + MBEDTLS_VERSION_MAJOR, + MBEDTLS_VERSION_MINOR, + MBEDTLS_VERSION_PATCH, + ( SSL_SERIALIZED_SESSION_CONFIG_BITFLAG >> 8 ) & 0xFF, + ( SSL_SERIALIZED_SESSION_CONFIG_BITFLAG >> 0 ) & 0xFF, + ( SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG >> 16 ) & 0xFF, + ( SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG >> 8 ) & 0xFF, + ( SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG >> 0 ) & 0xFF, +}; + +/* + * Serialize a full SSL context + * + * The format of the serialized data is: + * (in the presentation language of TLS, RFC 8446 section 3) + * + * // header + * opaque mbedtls_version[3]; // major, minor, patch + * opaque context_format[5]; // version-specific field determining + * // the format of the remaining + * // serialized data. + * Note: When updating the format, remember to keep these + * version+format bytes. (We may make their size part of the API.) + * + * // session sub-structure + * opaque session<1..2^32-1>; // see mbedtls_ssl_session_save() + * // transform sub-structure + * uint8 random[64]; // ServerHello.random+ClientHello.random + * uint8 in_cid<0..2^8-1> // Connection ID: expected incoming value + * uint8 out_cid<0..2^8-1> // Connection ID: outgoing value to use + * // fields from ssl_context + * uint32 badmac_seen; // DTLS: number of records with failing MAC + * uint64 in_window_top; // DTLS: last validated record seq_num + * uint64 in_window; // DTLS: bitmask for replay protection + * uint8 disable_datagram_packing; // DTLS: only one record per datagram + * uint64 cur_out_ctr; // Record layer: outgoing sequence number + * uint16 mtu; // DTLS: path mtu (max outgoing fragment size) + * uint8 alpn_chosen<0..2^8-1> // ALPN: negotiated application protocol + * + * Note that many fields of the ssl_context or sub-structures are not + * serialized, as they fall in one of the following categories: + * + * 1. forced value (eg in_left must be 0) + * 2. pointer to dynamically-allocated memory (eg session, transform) + * 3. value can be re-derived from other data (eg session keys from MS) + * 4. value was temporary (eg content of input buffer) + * 5. value will be provided by the user again (eg I/O callbacks and context) + */ +int mbedtls_ssl_context_save( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t buf_len, + size_t *olen ) +{ + unsigned char *p = buf; + size_t used = 0; + size_t session_len; + int ret = 0; + + /* + * Enforce usage restrictions, see "return BAD_INPUT_DATA" in + * this function's documentation. + * + * These are due to assumptions/limitations in the implementation. Some of + * them are likely to stay (no handshake in progress) some might go away + * (only DTLS) but are currently used to simplify the implementation. + */ + /* The initial handshake must be over */ + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Initial handshake isn't over" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + if( ssl->handshake != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Handshake isn't completed" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + /* Double-check that sub-structures are indeed ready */ + if( ssl->transform == NULL || ssl->session == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Serialised structures aren't ready" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + /* There must be no pending incoming or outgoing data */ + if( mbedtls_ssl_check_pending( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "There is pending incoming data" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + if( ssl->out_left != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "There is pending outgoing data" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + /* Protocol must be DLTS, not TLS */ + if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Only DTLS is supported" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + /* Version must be 1.2 */ + if( ssl->major_ver != MBEDTLS_SSL_MAJOR_VERSION_3 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Only version 1.2 supported" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Only version 1.2 supported" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + /* We must be using an AEAD ciphersuite */ + if( mbedtls_ssl_transform_uses_aead( ssl->transform ) != 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Only AEAD ciphersuites supported" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + /* Renegotiation must not be enabled */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->conf->disable_renegotiation != MBEDTLS_SSL_RENEGOTIATION_DISABLED ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Renegotiation must not be enabled" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } +#endif + + /* + * Version and format identifier + */ + used += sizeof( ssl_serialized_context_header ); + + if( used <= buf_len ) + { + memcpy( p, ssl_serialized_context_header, + sizeof( ssl_serialized_context_header ) ); + p += sizeof( ssl_serialized_context_header ); + } + + /* + * Session (length + data) + */ + ret = ssl_session_save( ssl->session, 1, NULL, 0, &session_len ); + if( ret != MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ) + return( ret ); + + used += 4 + session_len; + if( used <= buf_len ) + { + *p++ = (unsigned char)( ( session_len >> 24 ) & 0xFF ); + *p++ = (unsigned char)( ( session_len >> 16 ) & 0xFF ); + *p++ = (unsigned char)( ( session_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( session_len ) & 0xFF ); + + ret = ssl_session_save( ssl->session, 1, + p, session_len, &session_len ); + if( ret != 0 ) + return( ret ); + + p += session_len; + } + + /* + * Transform + */ + used += sizeof( ssl->transform->randbytes ); + if( used <= buf_len ) + { + memcpy( p, ssl->transform->randbytes, + sizeof( ssl->transform->randbytes ) ); + p += sizeof( ssl->transform->randbytes ); + } + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + used += 2 + ssl->transform->in_cid_len + ssl->transform->out_cid_len; + if( used <= buf_len ) + { + *p++ = ssl->transform->in_cid_len; + memcpy( p, ssl->transform->in_cid, ssl->transform->in_cid_len ); + p += ssl->transform->in_cid_len; + + *p++ = ssl->transform->out_cid_len; + memcpy( p, ssl->transform->out_cid, ssl->transform->out_cid_len ); + p += ssl->transform->out_cid_len; + } +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + + /* + * Saved fields from top-level ssl_context structure + */ +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) + used += 4; + if( used <= buf_len ) + { + *p++ = (unsigned char)( ( ssl->badmac_seen >> 24 ) & 0xFF ); + *p++ = (unsigned char)( ( ssl->badmac_seen >> 16 ) & 0xFF ); + *p++ = (unsigned char)( ( ssl->badmac_seen >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( ssl->badmac_seen ) & 0xFF ); + } +#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */ + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + used += 16; + if( used <= buf_len ) + { + *p++ = (unsigned char)( ( ssl->in_window_top >> 56 ) & 0xFF ); + *p++ = (unsigned char)( ( ssl->in_window_top >> 48 ) & 0xFF ); + *p++ = (unsigned char)( ( ssl->in_window_top >> 40 ) & 0xFF ); + *p++ = (unsigned char)( ( ssl->in_window_top >> 32 ) & 0xFF ); + *p++ = (unsigned char)( ( ssl->in_window_top >> 24 ) & 0xFF ); + *p++ = (unsigned char)( ( ssl->in_window_top >> 16 ) & 0xFF ); + *p++ = (unsigned char)( ( ssl->in_window_top >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( ssl->in_window_top ) & 0xFF ); + + *p++ = (unsigned char)( ( ssl->in_window >> 56 ) & 0xFF ); + *p++ = (unsigned char)( ( ssl->in_window >> 48 ) & 0xFF ); + *p++ = (unsigned char)( ( ssl->in_window >> 40 ) & 0xFF ); + *p++ = (unsigned char)( ( ssl->in_window >> 32 ) & 0xFF ); + *p++ = (unsigned char)( ( ssl->in_window >> 24 ) & 0xFF ); + *p++ = (unsigned char)( ( ssl->in_window >> 16 ) & 0xFF ); + *p++ = (unsigned char)( ( ssl->in_window >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( ssl->in_window ) & 0xFF ); + } +#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + used += 1; + if( used <= buf_len ) + { + *p++ = ssl->disable_datagram_packing; + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + used += 8; + if( used <= buf_len ) + { + memcpy( p, ssl->cur_out_ctr, 8 ); + p += 8; + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + used += 2; + if( used <= buf_len ) + { + *p++ = (unsigned char)( ( ssl->mtu >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( ssl->mtu ) & 0xFF ); + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_SSL_ALPN) + { + const uint8_t alpn_len = ssl->alpn_chosen + ? (uint8_t) strlen( ssl->alpn_chosen ) + : 0; + + used += 1 + alpn_len; + if( used <= buf_len ) + { + *p++ = alpn_len; + + if( ssl->alpn_chosen != NULL ) + { + memcpy( p, ssl->alpn_chosen, alpn_len ); + p += alpn_len; + } + } + } +#endif /* MBEDTLS_SSL_ALPN */ + + /* + * Done + */ + *olen = used; + + if( used > buf_len ) + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "saved context", buf, used ); + + return( mbedtls_ssl_session_reset_int( ssl, 0 ) ); +} + +/* + * Helper to get TLS 1.2 PRF from ciphersuite + * (Duplicates bits of logic from ssl_set_handshake_prfs().) + */ +typedef int (*tls_prf_fn)( const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ); +static tls_prf_fn ssl_tls12prf_from_cs( int ciphersuite_id ) +{ +#if defined(MBEDTLS_SHA512_C) + const mbedtls_ssl_ciphersuite_t * const ciphersuite_info = + mbedtls_ssl_ciphersuite_from_id( ciphersuite_id ); + + if( ciphersuite_info->mac == MBEDTLS_MD_SHA384 ) + return( tls_prf_sha384 ); +#else + (void) ciphersuite_id; +#endif + return( tls_prf_sha256 ); +} + +/* + * Deserialize context, see mbedtls_ssl_context_save() for format. + * + * This internal version is wrapped by a public function that cleans up in + * case of error. + */ +static int ssl_context_load( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + const unsigned char *p = buf; + const unsigned char * const end = buf + len; + size_t session_len; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* + * The context should have been freshly setup or reset. + * Give the user an error in case of obvious misuse. + * (Checking session is useful because it won't be NULL if we're + * renegotiating, or if the user mistakenly loaded a session first.) + */ + if( ssl->state != MBEDTLS_SSL_HELLO_REQUEST || + ssl->session != NULL ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + /* + * We can't check that the config matches the initial one, but we can at + * least check it matches the requirements for serializing. + */ + if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM || + ssl->conf->max_major_ver < MBEDTLS_SSL_MAJOR_VERSION_3 || + ssl->conf->min_major_ver > MBEDTLS_SSL_MAJOR_VERSION_3 || + ssl->conf->max_minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 || + ssl->conf->min_minor_ver > MBEDTLS_SSL_MINOR_VERSION_3 || +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->conf->disable_renegotiation != MBEDTLS_SSL_RENEGOTIATION_DISABLED || +#endif + 0 ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + MBEDTLS_SSL_DEBUG_BUF( 4, "context to load", buf, len ); + + /* + * Check version identifier + */ + if( (size_t)( end - p ) < sizeof( ssl_serialized_context_header ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( memcmp( p, ssl_serialized_context_header, + sizeof( ssl_serialized_context_header ) ) != 0 ) + { + return( MBEDTLS_ERR_SSL_VERSION_MISMATCH ); + } + p += sizeof( ssl_serialized_context_header ); + + /* + * Session + */ + if( (size_t)( end - p ) < 4 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + session_len = ( (size_t) p[0] << 24 ) | + ( (size_t) p[1] << 16 ) | + ( (size_t) p[2] << 8 ) | + ( (size_t) p[3] ); + p += 4; + + /* This has been allocated by ssl_handshake_init(), called by + * by either mbedtls_ssl_session_reset_int() or mbedtls_ssl_setup(). */ + ssl->session = ssl->session_negotiate; + ssl->session_in = ssl->session; + ssl->session_out = ssl->session; + ssl->session_negotiate = NULL; + + if( (size_t)( end - p ) < session_len ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ret = ssl_session_load( ssl->session, 1, p, session_len ); + if( ret != 0 ) + { + mbedtls_ssl_session_free( ssl->session ); + return( ret ); + } + + p += session_len; + + /* + * Transform + */ + + /* This has been allocated by ssl_handshake_init(), called by + * by either mbedtls_ssl_session_reset_int() or mbedtls_ssl_setup(). */ + ssl->transform = ssl->transform_negotiate; + ssl->transform_in = ssl->transform; + ssl->transform_out = ssl->transform; + ssl->transform_negotiate = NULL; + + /* Read random bytes and populate structure */ + if( (size_t)( end - p ) < sizeof( ssl->transform->randbytes ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ret = ssl_populate_transform( ssl->transform, + ssl->session->ciphersuite, + ssl->session->master, +#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + ssl->session->encrypt_then_mac, +#endif +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + ssl->session->trunc_hmac, +#endif +#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */ +#if defined(MBEDTLS_ZLIB_SUPPORT) + ssl->session->compression, +#endif + ssl_tls12prf_from_cs( ssl->session->ciphersuite ), + p, /* currently pointing to randbytes */ + MBEDTLS_SSL_MINOR_VERSION_3, /* (D)TLS 1.2 is forced */ + ssl->conf->endpoint, + ssl ); + if( ret != 0 ) + return( ret ); + + p += sizeof( ssl->transform->randbytes ); + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + /* Read connection IDs and store them */ + if( (size_t)( end - p ) < 1 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ssl->transform->in_cid_len = *p++; + + if( (size_t)( end - p ) < ssl->transform->in_cid_len + 1u ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + memcpy( ssl->transform->in_cid, p, ssl->transform->in_cid_len ); + p += ssl->transform->in_cid_len; + + ssl->transform->out_cid_len = *p++; + + if( (size_t)( end - p ) < ssl->transform->out_cid_len ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + memcpy( ssl->transform->out_cid, p, ssl->transform->out_cid_len ); + p += ssl->transform->out_cid_len; +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + + /* + * Saved fields from top-level ssl_context structure + */ +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) + if( (size_t)( end - p ) < 4 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ssl->badmac_seen = ( (uint32_t) p[0] << 24 ) | + ( (uint32_t) p[1] << 16 ) | + ( (uint32_t) p[2] << 8 ) | + ( (uint32_t) p[3] ); + p += 4; +#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */ + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + if( (size_t)( end - p ) < 16 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ssl->in_window_top = ( (uint64_t) p[0] << 56 ) | + ( (uint64_t) p[1] << 48 ) | + ( (uint64_t) p[2] << 40 ) | + ( (uint64_t) p[3] << 32 ) | + ( (uint64_t) p[4] << 24 ) | + ( (uint64_t) p[5] << 16 ) | + ( (uint64_t) p[6] << 8 ) | + ( (uint64_t) p[7] ); + p += 8; + + ssl->in_window = ( (uint64_t) p[0] << 56 ) | + ( (uint64_t) p[1] << 48 ) | + ( (uint64_t) p[2] << 40 ) | + ( (uint64_t) p[3] << 32 ) | + ( (uint64_t) p[4] << 24 ) | + ( (uint64_t) p[5] << 16 ) | + ( (uint64_t) p[6] << 8 ) | + ( (uint64_t) p[7] ); + p += 8; +#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( (size_t)( end - p ) < 1 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ssl->disable_datagram_packing = *p++; +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + if( (size_t)( end - p ) < 8 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + memcpy( ssl->cur_out_ctr, p, 8 ); + p += 8; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( (size_t)( end - p ) < 2 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ssl->mtu = ( p[0] << 8 ) | p[1]; + p += 2; +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_SSL_ALPN) + { + uint8_t alpn_len; + const char **cur; + + if( (size_t)( end - p ) < 1 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + alpn_len = *p++; + + if( alpn_len != 0 && ssl->conf->alpn_list != NULL ) + { + /* alpn_chosen should point to an item in the configured list */ + for( cur = ssl->conf->alpn_list; *cur != NULL; cur++ ) + { + if( strlen( *cur ) == alpn_len && + memcmp( p, cur, alpn_len ) == 0 ) + { + ssl->alpn_chosen = *cur; + break; + } + } + } + + /* can only happen on conf mismatch */ + if( alpn_len != 0 && ssl->alpn_chosen == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + p += alpn_len; + } +#endif /* MBEDTLS_SSL_ALPN */ + + /* + * Forced fields from top-level ssl_context structure + * + * Most of them already set to the correct value by mbedtls_ssl_init() and + * mbedtls_ssl_reset(), so we only need to set the remaining ones. + */ + ssl->state = MBEDTLS_SSL_HANDSHAKE_OVER; + + ssl->major_ver = MBEDTLS_SSL_MAJOR_VERSION_3; + ssl->minor_ver = MBEDTLS_SSL_MINOR_VERSION_3; + + /* Adjust pointers for header fields of outgoing records to + * the given transform, accounting for explicit IV and CID. */ + mbedtls_ssl_update_out_pointers( ssl, ssl->transform ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + ssl->in_epoch = 1; +#endif + + /* mbedtls_ssl_reset() leaves the handshake sub-structure allocated, + * which we don't want - otherwise we'd end up freeing the wrong transform + * by calling mbedtls_ssl_handshake_wrapup_free_hs_transform() + * inappropriately. */ + if( ssl->handshake != NULL ) + { + mbedtls_ssl_handshake_free( ssl ); + mbedtls_free( ssl->handshake ); + ssl->handshake = NULL; + } + + /* + * Done - should have consumed entire buffer + */ + if( p != end ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + return( 0 ); +} + +/* + * Deserialize context: public wrapper for error cleaning + */ +int mbedtls_ssl_context_load( mbedtls_ssl_context *context, + const unsigned char *buf, + size_t len ) +{ + int ret = ssl_context_load( context, buf, len ); + + if( ret != 0 ) + mbedtls_ssl_free( context ); + + return( ret ); +} +#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */ + +/* + * Free an SSL context + */ +void mbedtls_ssl_free( mbedtls_ssl_context *ssl ) +{ + if( ssl == NULL ) + return; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> free" ) ); + + if( ssl->out_buf != NULL ) + { +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t out_buf_len = ssl->out_buf_len; +#else + size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN; +#endif + + mbedtls_platform_zeroize( ssl->out_buf, out_buf_len ); + mbedtls_free( ssl->out_buf ); + ssl->out_buf = NULL; + } + + if( ssl->in_buf != NULL ) + { +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t in_buf_len = ssl->in_buf_len; +#else + size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN; +#endif + + mbedtls_platform_zeroize( ssl->in_buf, in_buf_len ); + mbedtls_free( ssl->in_buf ); + ssl->in_buf = NULL; + } + +#if defined(MBEDTLS_ZLIB_SUPPORT) + if( ssl->compress_buf != NULL ) + { + mbedtls_platform_zeroize( ssl->compress_buf, MBEDTLS_SSL_COMPRESS_BUFFER_LEN ); + mbedtls_free( ssl->compress_buf ); + } +#endif + + if( ssl->transform ) + { + mbedtls_ssl_transform_free( ssl->transform ); + mbedtls_free( ssl->transform ); + } + + if( ssl->handshake ) + { + mbedtls_ssl_handshake_free( ssl ); + mbedtls_ssl_transform_free( ssl->transform_negotiate ); + mbedtls_ssl_session_free( ssl->session_negotiate ); + + mbedtls_free( ssl->handshake ); + mbedtls_free( ssl->transform_negotiate ); + mbedtls_free( ssl->session_negotiate ); + } + + if( ssl->session ) + { + mbedtls_ssl_session_free( ssl->session ); + mbedtls_free( ssl->session ); + } + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + if( ssl->hostname != NULL ) + { + mbedtls_platform_zeroize( ssl->hostname, strlen( ssl->hostname ) ); + mbedtls_free( ssl->hostname ); + } +#endif + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_finish != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_finish()" ) ); + mbedtls_ssl_hw_record_finish( ssl ); + } +#endif + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) + mbedtls_free( ssl->cli_id ); +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= free" ) ); + + /* Actually clear after last debug message */ + mbedtls_platform_zeroize( ssl, sizeof( mbedtls_ssl_context ) ); +} + +/* + * Initialze mbedtls_ssl_config + */ +void mbedtls_ssl_config_init( mbedtls_ssl_config *conf ) +{ + memset( conf, 0, sizeof( mbedtls_ssl_config ) ); +} + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) +static int ssl_preset_default_hashes[] = { +#if defined(MBEDTLS_SHA512_C) + MBEDTLS_MD_SHA512, + MBEDTLS_MD_SHA384, +#endif +#if defined(MBEDTLS_SHA256_C) + MBEDTLS_MD_SHA256, + MBEDTLS_MD_SHA224, +#endif +#if defined(MBEDTLS_SHA1_C) && defined(MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE) + MBEDTLS_MD_SHA1, +#endif + MBEDTLS_MD_NONE +}; +#endif + +static int ssl_preset_suiteb_ciphersuites[] = { + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + 0 +}; + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) +static int ssl_preset_suiteb_hashes[] = { + MBEDTLS_MD_SHA256, + MBEDTLS_MD_SHA384, + MBEDTLS_MD_NONE +}; +#endif + +#if defined(MBEDTLS_ECP_C) +static mbedtls_ecp_group_id ssl_preset_suiteb_curves[] = { +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + MBEDTLS_ECP_DP_SECP256R1, +#endif +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + MBEDTLS_ECP_DP_SECP384R1, +#endif + MBEDTLS_ECP_DP_NONE +}; +#endif + +/* + * Load default in mbedtls_ssl_config + */ +int mbedtls_ssl_config_defaults( mbedtls_ssl_config *conf, + int endpoint, int transport, int preset ) +{ +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; +#endif + + /* Use the functions here so that they are covered in tests, + * but otherwise access member directly for efficiency */ + mbedtls_ssl_conf_endpoint( conf, endpoint ); + mbedtls_ssl_conf_transport( conf, transport ); + + /* + * Things that are common to all presets + */ +#if defined(MBEDTLS_SSL_CLI_C) + if( endpoint == MBEDTLS_SSL_IS_CLIENT ) + { + conf->authmode = MBEDTLS_SSL_VERIFY_REQUIRED; +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + conf->session_tickets = MBEDTLS_SSL_SESSION_TICKETS_ENABLED; +#endif + } +#endif + +#if defined(MBEDTLS_ARC4_C) + conf->arc4_disabled = MBEDTLS_SSL_ARC4_DISABLED; +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + conf->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED; +#endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + conf->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED; +#endif + +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) + conf->cbc_record_splitting = MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED; +#endif + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) + conf->f_cookie_write = ssl_cookie_write_dummy; + conf->f_cookie_check = ssl_cookie_check_dummy; +#endif + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + conf->anti_replay = MBEDTLS_SSL_ANTI_REPLAY_ENABLED; +#endif + +#if defined(MBEDTLS_SSL_SRV_C) + conf->cert_req_ca_list = MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED; +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + conf->hs_timeout_min = MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN; + conf->hs_timeout_max = MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX; +#endif + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + conf->renego_max_records = MBEDTLS_SSL_RENEGO_MAX_RECORDS_DEFAULT; + memset( conf->renego_period, 0x00, 2 ); + memset( conf->renego_period + 2, 0xFF, 6 ); +#endif + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) + if( endpoint == MBEDTLS_SSL_IS_SERVER ) + { + const unsigned char dhm_p[] = + MBEDTLS_DHM_RFC3526_MODP_2048_P_BIN; + const unsigned char dhm_g[] = + MBEDTLS_DHM_RFC3526_MODP_2048_G_BIN; + + if ( ( ret = mbedtls_ssl_conf_dh_param_bin( conf, + dhm_p, sizeof( dhm_p ), + dhm_g, sizeof( dhm_g ) ) ) != 0 ) + { + return( ret ); + } + } +#endif + + /* + * Preset-specific defaults + */ + switch( preset ) + { + /* + * NSA Suite B + */ + case MBEDTLS_SSL_PRESET_SUITEB: + conf->min_major_ver = MBEDTLS_SSL_MAJOR_VERSION_3; + conf->min_minor_ver = MBEDTLS_SSL_MINOR_VERSION_3; /* TLS 1.2 */ + conf->max_major_ver = MBEDTLS_SSL_MAX_MAJOR_VERSION; + conf->max_minor_ver = MBEDTLS_SSL_MAX_MINOR_VERSION; + + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_0] = + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_1] = + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_2] = + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_3] = + ssl_preset_suiteb_ciphersuites; + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + conf->cert_profile = &mbedtls_x509_crt_profile_suiteb; +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + conf->sig_hashes = ssl_preset_suiteb_hashes; +#endif + +#if defined(MBEDTLS_ECP_C) + conf->curve_list = ssl_preset_suiteb_curves; +#endif + break; + + /* + * Default + */ + default: + conf->min_major_ver = ( MBEDTLS_SSL_MIN_MAJOR_VERSION > + MBEDTLS_SSL_MIN_VALID_MAJOR_VERSION ) ? + MBEDTLS_SSL_MIN_MAJOR_VERSION : + MBEDTLS_SSL_MIN_VALID_MAJOR_VERSION; + conf->min_minor_ver = ( MBEDTLS_SSL_MIN_MINOR_VERSION > + MBEDTLS_SSL_MIN_VALID_MINOR_VERSION ) ? + MBEDTLS_SSL_MIN_MINOR_VERSION : + MBEDTLS_SSL_MIN_VALID_MINOR_VERSION; + conf->max_major_ver = MBEDTLS_SSL_MAX_MAJOR_VERSION; + conf->max_minor_ver = MBEDTLS_SSL_MAX_MINOR_VERSION; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + conf->min_minor_ver = MBEDTLS_SSL_MINOR_VERSION_2; +#endif + + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_0] = + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_1] = + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_2] = + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_3] = + mbedtls_ssl_list_ciphersuites(); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + conf->cert_profile = &mbedtls_x509_crt_profile_default; +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + conf->sig_hashes = ssl_preset_default_hashes; +#endif + +#if defined(MBEDTLS_ECP_C) + conf->curve_list = mbedtls_ecp_grp_id_list(); +#endif + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) + conf->dhm_min_bitlen = 1024; +#endif + } + + return( 0 ); +} + +/* + * Free mbedtls_ssl_config + */ +void mbedtls_ssl_config_free( mbedtls_ssl_config *conf ) +{ +#if defined(MBEDTLS_DHM_C) + mbedtls_mpi_free( &conf->dhm_P ); + mbedtls_mpi_free( &conf->dhm_G ); +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) + if( conf->psk != NULL ) + { + mbedtls_platform_zeroize( conf->psk, conf->psk_len ); + mbedtls_free( conf->psk ); + conf->psk = NULL; + conf->psk_len = 0; + } + + if( conf->psk_identity != NULL ) + { + mbedtls_platform_zeroize( conf->psk_identity, conf->psk_identity_len ); + mbedtls_free( conf->psk_identity ); + conf->psk_identity = NULL; + conf->psk_identity_len = 0; + } +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + ssl_key_cert_free( conf->key_cert ); +#endif + + mbedtls_platform_zeroize( conf, sizeof( mbedtls_ssl_config ) ); +} + +#if defined(MBEDTLS_PK_C) && \ + ( defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_C) ) +/* + * Convert between MBEDTLS_PK_XXX and SSL_SIG_XXX + */ +unsigned char mbedtls_ssl_sig_from_pk( mbedtls_pk_context *pk ) +{ +#if defined(MBEDTLS_RSA_C) + if( mbedtls_pk_can_do( pk, MBEDTLS_PK_RSA ) ) + return( MBEDTLS_SSL_SIG_RSA ); +#endif +#if defined(MBEDTLS_ECDSA_C) + if( mbedtls_pk_can_do( pk, MBEDTLS_PK_ECDSA ) ) + return( MBEDTLS_SSL_SIG_ECDSA ); +#endif + return( MBEDTLS_SSL_SIG_ANON ); +} + +unsigned char mbedtls_ssl_sig_from_pk_alg( mbedtls_pk_type_t type ) +{ + switch( type ) { + case MBEDTLS_PK_RSA: + return( MBEDTLS_SSL_SIG_RSA ); + case MBEDTLS_PK_ECDSA: + case MBEDTLS_PK_ECKEY: + return( MBEDTLS_SSL_SIG_ECDSA ); + default: + return( MBEDTLS_SSL_SIG_ANON ); + } +} + +mbedtls_pk_type_t mbedtls_ssl_pk_alg_from_sig( unsigned char sig ) +{ + switch( sig ) + { +#if defined(MBEDTLS_RSA_C) + case MBEDTLS_SSL_SIG_RSA: + return( MBEDTLS_PK_RSA ); +#endif +#if defined(MBEDTLS_ECDSA_C) + case MBEDTLS_SSL_SIG_ECDSA: + return( MBEDTLS_PK_ECDSA ); +#endif + default: + return( MBEDTLS_PK_NONE ); + } +} +#endif /* MBEDTLS_PK_C && ( MBEDTLS_RSA_C || MBEDTLS_ECDSA_C ) */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + +/* Find an entry in a signature-hash set matching a given hash algorithm. */ +mbedtls_md_type_t mbedtls_ssl_sig_hash_set_find( mbedtls_ssl_sig_hash_set_t *set, + mbedtls_pk_type_t sig_alg ) +{ + switch( sig_alg ) + { + case MBEDTLS_PK_RSA: + return( set->rsa ); + case MBEDTLS_PK_ECDSA: + return( set->ecdsa ); + default: + return( MBEDTLS_MD_NONE ); + } +} + +/* Add a signature-hash-pair to a signature-hash set */ +void mbedtls_ssl_sig_hash_set_add( mbedtls_ssl_sig_hash_set_t *set, + mbedtls_pk_type_t sig_alg, + mbedtls_md_type_t md_alg ) +{ + switch( sig_alg ) + { + case MBEDTLS_PK_RSA: + if( set->rsa == MBEDTLS_MD_NONE ) + set->rsa = md_alg; + break; + + case MBEDTLS_PK_ECDSA: + if( set->ecdsa == MBEDTLS_MD_NONE ) + set->ecdsa = md_alg; + break; + + default: + break; + } +} + +/* Allow exactly one hash algorithm for each signature. */ +void mbedtls_ssl_sig_hash_set_const_hash( mbedtls_ssl_sig_hash_set_t *set, + mbedtls_md_type_t md_alg ) +{ + set->rsa = md_alg; + set->ecdsa = md_alg; +} + +#endif /* MBEDTLS_SSL_PROTO_TLS1_2) && + MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + +/* + * Convert from MBEDTLS_SSL_HASH_XXX to MBEDTLS_MD_XXX + */ +mbedtls_md_type_t mbedtls_ssl_md_alg_from_hash( unsigned char hash ) +{ + switch( hash ) + { +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_SSL_HASH_MD5: + return( MBEDTLS_MD_MD5 ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_SSL_HASH_SHA1: + return( MBEDTLS_MD_SHA1 ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_SSL_HASH_SHA224: + return( MBEDTLS_MD_SHA224 ); + case MBEDTLS_SSL_HASH_SHA256: + return( MBEDTLS_MD_SHA256 ); +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_SSL_HASH_SHA384: + return( MBEDTLS_MD_SHA384 ); + case MBEDTLS_SSL_HASH_SHA512: + return( MBEDTLS_MD_SHA512 ); +#endif + default: + return( MBEDTLS_MD_NONE ); + } +} + +/* + * Convert from MBEDTLS_MD_XXX to MBEDTLS_SSL_HASH_XXX + */ +unsigned char mbedtls_ssl_hash_from_md_alg( int md ) +{ + switch( md ) + { +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return( MBEDTLS_SSL_HASH_MD5 ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return( MBEDTLS_SSL_HASH_SHA1 ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA224: + return( MBEDTLS_SSL_HASH_SHA224 ); + case MBEDTLS_MD_SHA256: + return( MBEDTLS_SSL_HASH_SHA256 ); +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_MD_SHA384: + return( MBEDTLS_SSL_HASH_SHA384 ); + case MBEDTLS_MD_SHA512: + return( MBEDTLS_SSL_HASH_SHA512 ); +#endif + default: + return( MBEDTLS_SSL_HASH_NONE ); + } +} + +#if defined(MBEDTLS_ECP_C) +/* + * Check if a curve proposed by the peer is in our list. + * Return 0 if we're willing to use it, -1 otherwise. + */ +int mbedtls_ssl_check_curve( const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id ) +{ + const mbedtls_ecp_group_id *gid; + + if( ssl->conf->curve_list == NULL ) + return( -1 ); + + for( gid = ssl->conf->curve_list; *gid != MBEDTLS_ECP_DP_NONE; gid++ ) + if( *gid == grp_id ) + return( 0 ); + + return( -1 ); +} +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) +/* + * Check if a hash proposed by the peer is in our list. + * Return 0 if we're willing to use it, -1 otherwise. + */ +int mbedtls_ssl_check_sig_hash( const mbedtls_ssl_context *ssl, + mbedtls_md_type_t md ) +{ + const int *cur; + + if( ssl->conf->sig_hashes == NULL ) + return( -1 ); + + for( cur = ssl->conf->sig_hashes; *cur != MBEDTLS_MD_NONE; cur++ ) + if( *cur == (int) md ) + return( 0 ); + + return( -1 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +int mbedtls_ssl_check_cert_usage( const mbedtls_x509_crt *cert, + const mbedtls_ssl_ciphersuite_t *ciphersuite, + int cert_endpoint, + uint32_t *flags ) +{ + int ret = 0; +#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) + int usage = 0; +#endif +#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) + const char *ext_oid; + size_t ext_len; +#endif + +#if !defined(MBEDTLS_X509_CHECK_KEY_USAGE) && \ + !defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) + ((void) cert); + ((void) cert_endpoint); + ((void) flags); +#endif + +#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) + if( cert_endpoint == MBEDTLS_SSL_IS_SERVER ) + { + /* Server part of the key exchange */ + switch( ciphersuite->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_RSA: + case MBEDTLS_KEY_EXCHANGE_RSA_PSK: + usage = MBEDTLS_X509_KU_KEY_ENCIPHERMENT; + break; + + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE; + break; + + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + usage = MBEDTLS_X509_KU_KEY_AGREEMENT; + break; + + /* Don't use default: we want warnings when adding new values */ + case MBEDTLS_KEY_EXCHANGE_NONE: + case MBEDTLS_KEY_EXCHANGE_PSK: + case MBEDTLS_KEY_EXCHANGE_DHE_PSK: + case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: + case MBEDTLS_KEY_EXCHANGE_ECJPAKE: + usage = 0; + } + } + else + { + /* Client auth: we only implement rsa_sign and mbedtls_ecdsa_sign for now */ + usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE; + } + + if( mbedtls_x509_crt_check_key_usage( cert, usage ) != 0 ) + { + *flags |= MBEDTLS_X509_BADCERT_KEY_USAGE; + ret = -1; + } +#else + ((void) ciphersuite); +#endif /* MBEDTLS_X509_CHECK_KEY_USAGE */ + +#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) + if( cert_endpoint == MBEDTLS_SSL_IS_SERVER ) + { + ext_oid = MBEDTLS_OID_SERVER_AUTH; + ext_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_SERVER_AUTH ); + } + else + { + ext_oid = MBEDTLS_OID_CLIENT_AUTH; + ext_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_CLIENT_AUTH ); + } + + if( mbedtls_x509_crt_check_extended_key_usage( cert, ext_oid, ext_len ) != 0 ) + { + *flags |= MBEDTLS_X509_BADCERT_EXT_KEY_USAGE; + ret = -1; + } +#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */ + + return( ret ); +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +int mbedtls_ssl_set_calc_verify_md( mbedtls_ssl_context *ssl, int md ) +{ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) + return MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH; + + switch( md ) + { +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_SSL_HASH_MD5: + return MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH; +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_SSL_HASH_SHA1: + ssl->handshake->calc_verify = ssl_calc_verify_tls; + break; +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 */ +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_SSL_HASH_SHA384: + ssl->handshake->calc_verify = ssl_calc_verify_tls_sha384; + break; +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_SSL_HASH_SHA256: + ssl->handshake->calc_verify = ssl_calc_verify_tls_sha256; + break; +#endif + default: + return MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH; + } + + return 0; +#else /* !MBEDTLS_SSL_PROTO_TLS1_2 */ + (void) ssl; + (void) md; + + return MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH; +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +} + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) +int mbedtls_ssl_get_key_exchange_md_ssl_tls( mbedtls_ssl_context *ssl, + unsigned char *output, + unsigned char *data, size_t data_len ) +{ + int ret = 0; + mbedtls_md5_context mbedtls_md5; + mbedtls_sha1_context mbedtls_sha1; + + mbedtls_md5_init( &mbedtls_md5 ); + mbedtls_sha1_init( &mbedtls_sha1 ); + + /* + * digitally-signed struct { + * opaque md5_hash[16]; + * opaque sha_hash[20]; + * }; + * + * md5_hash + * MD5(ClientHello.random + ServerHello.random + * + ServerParams); + * sha_hash + * SHA(ClientHello.random + ServerHello.random + * + ServerParams); + */ + if( ( ret = mbedtls_md5_starts_ret( &mbedtls_md5 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md5_starts_ret", ret ); + goto exit; + } + if( ( ret = mbedtls_md5_update_ret( &mbedtls_md5, + ssl->handshake->randbytes, 64 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md5_update_ret", ret ); + goto exit; + } + if( ( ret = mbedtls_md5_update_ret( &mbedtls_md5, data, data_len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md5_update_ret", ret ); + goto exit; + } + if( ( ret = mbedtls_md5_finish_ret( &mbedtls_md5, output ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md5_finish_ret", ret ); + goto exit; + } + + if( ( ret = mbedtls_sha1_starts_ret( &mbedtls_sha1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_sha1_starts_ret", ret ); + goto exit; + } + if( ( ret = mbedtls_sha1_update_ret( &mbedtls_sha1, + ssl->handshake->randbytes, 64 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_sha1_update_ret", ret ); + goto exit; + } + if( ( ret = mbedtls_sha1_update_ret( &mbedtls_sha1, data, + data_len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_sha1_update_ret", ret ); + goto exit; + } + if( ( ret = mbedtls_sha1_finish_ret( &mbedtls_sha1, + output + 16 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_sha1_finish_ret", ret ); + goto exit; + } + +exit: + mbedtls_md5_free( &mbedtls_md5 ); + mbedtls_sha1_free( &mbedtls_sha1 ); + + if( ret != 0 ) + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + + return( ret ); + +} +#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ + MBEDTLS_SSL_PROTO_TLS1_1 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl, + unsigned char *hash, size_t *hashlen, + unsigned char *data, size_t data_len, + mbedtls_md_type_t md_alg ) +{ + psa_status_t status; + psa_hash_operation_t hash_operation = PSA_HASH_OPERATION_INIT; + psa_algorithm_t hash_alg = mbedtls_psa_translate_md( md_alg ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Perform PSA-based computation of digest of ServerKeyExchange" ) ); + + if( ( status = psa_hash_setup( &hash_operation, + hash_alg ) ) != PSA_SUCCESS ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "psa_hash_setup", status ); + goto exit; + } + + if( ( status = psa_hash_update( &hash_operation, ssl->handshake->randbytes, + 64 ) ) != PSA_SUCCESS ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "psa_hash_update", status ); + goto exit; + } + + if( ( status = psa_hash_update( &hash_operation, + data, data_len ) ) != PSA_SUCCESS ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "psa_hash_update", status ); + goto exit; + } + + if( ( status = psa_hash_finish( &hash_operation, hash, MBEDTLS_MD_MAX_SIZE, + hashlen ) ) != PSA_SUCCESS ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "psa_hash_finish", status ); + goto exit; + } + +exit: + if( status != PSA_SUCCESS ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + switch( status ) + { + case PSA_ERROR_NOT_SUPPORTED: + return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE ); + case PSA_ERROR_BAD_STATE: /* Intentional fallthrough */ + case PSA_ERROR_BUFFER_TOO_SMALL: + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + case PSA_ERROR_INSUFFICIENT_MEMORY: + return( MBEDTLS_ERR_MD_ALLOC_FAILED ); + default: + return( MBEDTLS_ERR_MD_HW_ACCEL_FAILED ); + } + } + return( 0 ); +} + +#else + +int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl, + unsigned char *hash, size_t *hashlen, + unsigned char *data, size_t data_len, + mbedtls_md_type_t md_alg ) +{ + int ret = 0; + mbedtls_md_context_t ctx; + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg ); + *hashlen = mbedtls_md_get_size( md_info ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Perform mbedtls-based computation of digest of ServerKeyExchange" ) ); + + mbedtls_md_init( &ctx ); + + /* + * digitally-signed struct { + * opaque client_random[32]; + * opaque server_random[32]; + * ServerDHParams params; + * }; + */ + if( ( ret = mbedtls_md_setup( &ctx, md_info, 0 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_setup", ret ); + goto exit; + } + if( ( ret = mbedtls_md_starts( &ctx ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_starts", ret ); + goto exit; + } + if( ( ret = mbedtls_md_update( &ctx, ssl->handshake->randbytes, 64 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_update", ret ); + goto exit; + } + if( ( ret = mbedtls_md_update( &ctx, data, data_len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_update", ret ); + goto exit; + } + if( ( ret = mbedtls_md_finish( &ctx, hash ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_finish", ret ); + goto exit; + } + +exit: + mbedtls_md_free( &ctx ); + + if( ret != 0 ) + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + + return( ret ); +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ + MBEDTLS_SSL_PROTO_TLS1_2 */ + +#endif /* MBEDTLS_SSL_TLS_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/ssl_tls13_keys.c b/Android/Level4/app/src/main/c/mbedtls/library/ssl_tls13_keys.c new file mode 100644 index 0000000..c39e032 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/ssl_tls13_keys.c @@ -0,0 +1,349 @@ +/* + * TLS 1.3 key schedule + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 ( the "License" ); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 "common.h" + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL) + +#include "mbedtls/hkdf.h" +#include "mbedtls/ssl_internal.h" +#include "ssl_tls13_keys.h" + +#include +#include + +#define MBEDTLS_SSL_TLS1_3_LABEL( name, string ) \ + .name = string, + +struct mbedtls_ssl_tls1_3_labels_struct const mbedtls_ssl_tls1_3_labels = +{ + /* This seems to work in C, despite the string literal being one + * character too long due to the 0-termination. */ + MBEDTLS_SSL_TLS1_3_LABEL_LIST +}; + +#undef MBEDTLS_SSL_TLS1_3_LABEL + +/* + * This function creates a HkdfLabel structure used in the TLS 1.3 key schedule. + * + * The HkdfLabel is specified in RFC 8446 as follows: + * + * struct HkdfLabel { + * uint16 length; // Length of expanded key material + * opaque label<7..255>; // Always prefixed by "tls13 " + * opaque context<0..255>; // Usually a communication transcript hash + * }; + * + * Parameters: + * - desired_length: Length of expanded key material + * Even though the standard allows expansion to up to + * 2**16 Bytes, TLS 1.3 never uses expansion to more than + * 255 Bytes, so we require `desired_length` to be at most + * 255. This allows us to save a few Bytes of code by + * hardcoding the writing of the high bytes. + * - (label, llen): label + label length, without "tls13 " prefix + * The label length MUST be less than or equal to + * MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN + * It is the caller's responsibility to ensure this. + * All (label, label length) pairs used in TLS 1.3 + * can be obtained via MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(). + * - (ctx, clen): context + context length + * The context length MUST be less than or equal to + * MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN + * It is the caller's responsibility to ensure this. + * - dst: Target buffer for HkdfLabel structure, + * This MUST be a writable buffer of size + * at least SSL_TLS1_3_KEY_SCHEDULE_MAX_HKDF_LABEL_LEN Bytes. + * - dlen: Pointer at which to store the actual length of + * the HkdfLabel structure on success. + */ + +static const char tls1_3_label_prefix[6] = "tls13 "; + +#define SSL_TLS1_3_KEY_SCHEDULE_HKDF_LABEL_LEN( label_len, context_len ) \ + ( 2 /* expansion length */ \ + + 1 /* label length */ \ + + label_len \ + + 1 /* context length */ \ + + context_len ) + +#define SSL_TLS1_3_KEY_SCHEDULE_MAX_HKDF_LABEL_LEN \ + SSL_TLS1_3_KEY_SCHEDULE_HKDF_LABEL_LEN( \ + sizeof(tls1_3_label_prefix) + \ + MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN, \ + MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN ) + +static void ssl_tls1_3_hkdf_encode_label( + size_t desired_length, + const unsigned char *label, size_t llen, + const unsigned char *ctx, size_t clen, + unsigned char *dst, size_t *dlen ) +{ + size_t total_label_len = + sizeof(tls1_3_label_prefix) + llen; + size_t total_hkdf_lbl_len = + SSL_TLS1_3_KEY_SCHEDULE_HKDF_LABEL_LEN( total_label_len, clen ); + + unsigned char *p = dst; + + /* Add the size of the expanded key material. + * We're hardcoding the high byte to 0 here assuming that we never use + * TLS 1.3 HKDF key expansion to more than 255 Bytes. */ +#if MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_EXPANSION_LEN > 255 +#error "The implementation of ssl_tls1_3_hkdf_encode_label() is not fit for the \ + value of MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_EXPANSION_LEN" +#endif + + *p++ = 0; + *p++ = (unsigned char)( ( desired_length >> 0 ) & 0xFF ); + + /* Add label incl. prefix */ + *p++ = (unsigned char)( total_label_len & 0xFF ); + memcpy( p, tls1_3_label_prefix, sizeof(tls1_3_label_prefix) ); + p += sizeof(tls1_3_label_prefix); + memcpy( p, label, llen ); + p += llen; + + /* Add context value */ + *p++ = (unsigned char)( clen & 0xFF ); + if( clen != 0 ) + memcpy( p, ctx, clen ); + + /* Return total length to the caller. */ + *dlen = total_hkdf_lbl_len; +} + +int mbedtls_ssl_tls1_3_hkdf_expand_label( + mbedtls_md_type_t hash_alg, + const unsigned char *secret, size_t slen, + const unsigned char *label, size_t llen, + const unsigned char *ctx, size_t clen, + unsigned char *buf, size_t blen ) +{ + const mbedtls_md_info_t *md; + unsigned char hkdf_label[ SSL_TLS1_3_KEY_SCHEDULE_MAX_HKDF_LABEL_LEN ]; + size_t hkdf_label_len; + + if( llen > MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN ) + { + /* Should never happen since this is an internal + * function, and we know statically which labels + * are allowed. */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + if( clen > MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN ) + { + /* Should not happen, as above. */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + if( blen > MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_EXPANSION_LEN ) + { + /* Should not happen, as above. */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + md = mbedtls_md_info_from_type( hash_alg ); + if( md == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ssl_tls1_3_hkdf_encode_label( blen, + label, llen, + ctx, clen, + hkdf_label, + &hkdf_label_len ); + + return( mbedtls_hkdf_expand( md, + secret, slen, + hkdf_label, hkdf_label_len, + buf, blen ) ); +} + +/* + * The traffic keying material is generated from the following inputs: + * + * - One secret value per sender. + * - A purpose value indicating the specific value being generated + * - The desired lengths of key and IV. + * + * The expansion itself is based on HKDF: + * + * [sender]_write_key = HKDF-Expand-Label( Secret, "key", "", key_length ) + * [sender]_write_iv = HKDF-Expand-Label( Secret, "iv" , "", iv_length ) + * + * [sender] denotes the sending side and the Secret value is provided + * by the function caller. Note that we generate server and client side + * keys in a single function call. + */ +int mbedtls_ssl_tls1_3_make_traffic_keys( + mbedtls_md_type_t hash_alg, + const unsigned char *client_secret, + const unsigned char *server_secret, + size_t slen, size_t key_len, size_t iv_len, + mbedtls_ssl_key_set *keys ) +{ + int ret = 0; + + ret = mbedtls_ssl_tls1_3_hkdf_expand_label( hash_alg, + client_secret, slen, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( key ), + NULL, 0, + keys->client_write_key, key_len ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_ssl_tls1_3_hkdf_expand_label( hash_alg, + server_secret, slen, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( key ), + NULL, 0, + keys->server_write_key, key_len ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_ssl_tls1_3_hkdf_expand_label( hash_alg, + client_secret, slen, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( iv ), + NULL, 0, + keys->client_write_iv, iv_len ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_ssl_tls1_3_hkdf_expand_label( hash_alg, + server_secret, slen, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( iv ), + NULL, 0, + keys->server_write_iv, iv_len ); + if( ret != 0 ) + return( ret ); + + keys->key_len = key_len; + keys->iv_len = iv_len; + + return( 0 ); +} + +int mbedtls_ssl_tls1_3_derive_secret( + mbedtls_md_type_t hash_alg, + const unsigned char *secret, size_t slen, + const unsigned char *label, size_t llen, + const unsigned char *ctx, size_t clen, + int ctx_hashed, + unsigned char *dstbuf, size_t buflen ) +{ + int ret; + unsigned char hashed_context[ MBEDTLS_MD_MAX_SIZE ]; + + const mbedtls_md_info_t *md; + md = mbedtls_md_info_from_type( hash_alg ); + if( md == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( ctx_hashed == MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED ) + { + ret = mbedtls_md( md, ctx, clen, hashed_context ); + if( ret != 0 ) + return( ret ); + clen = mbedtls_md_get_size( md ); + } + else + { + if( clen > sizeof(hashed_context) ) + { + /* This should never happen since this function is internal + * and the code sets `ctx_hashed` correctly. + * Let's double-check nonetheless to not run at the risk + * of getting a stack overflow. */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + memcpy( hashed_context, ctx, clen ); + } + + return( mbedtls_ssl_tls1_3_hkdf_expand_label( hash_alg, + secret, slen, + label, llen, + hashed_context, clen, + dstbuf, buflen ) ); +} + +int mbedtls_ssl_tls1_3_evolve_secret( + mbedtls_md_type_t hash_alg, + const unsigned char *secret_old, + const unsigned char *input, size_t input_len, + unsigned char *secret_new ) +{ + int ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; + size_t hlen, ilen; + unsigned char tmp_secret[ MBEDTLS_MD_MAX_SIZE ] = { 0 }; + unsigned char tmp_input [ MBEDTLS_MD_MAX_SIZE ] = { 0 }; + + const mbedtls_md_info_t *md; + md = mbedtls_md_info_from_type( hash_alg ); + if( md == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + hlen = mbedtls_md_get_size( md ); + + /* For non-initial runs, call Derive-Secret( ., "derived", "") + * on the old secret. */ + if( secret_old != NULL ) + { + ret = mbedtls_ssl_tls1_3_derive_secret( + hash_alg, + secret_old, hlen, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( derived ), + NULL, 0, /* context */ + MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED, + tmp_secret, hlen ); + if( ret != 0 ) + goto cleanup; + } + + if( input != NULL ) + { + memcpy( tmp_input, input, input_len ); + ilen = input_len; + } + else + { + ilen = hlen; + } + + /* HKDF-Extract takes a salt and input key material. + * The salt is the old secret, and the input key material + * is the input secret (PSK / ECDHE). */ + ret = mbedtls_hkdf_extract( md, + tmp_secret, hlen, + tmp_input, ilen, + secret_new ); + if( ret != 0 ) + goto cleanup; + + ret = 0; + + cleanup: + + mbedtls_platform_zeroize( tmp_secret, sizeof(tmp_secret) ); + mbedtls_platform_zeroize( tmp_input, sizeof(tmp_input) ); + return( ret ); +} + +#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/ssl_tls13_keys.h b/Android/Level4/app/src/main/c/mbedtls/library/ssl_tls13_keys.h new file mode 100644 index 0000000..7089049 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/ssl_tls13_keys.h @@ -0,0 +1,274 @@ +/* + * TLS 1.3 key schedule + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 ( the "License" ); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ +#if !defined(MBEDTLS_SSL_TLS1_3_KEYS_H) +#define MBEDTLS_SSL_TLS1_3_KEYS_H + +/* This requires MBEDTLS_SSL_TLS1_3_LABEL( idx, name, string ) to be defined at + * the point of use. See e.g. the definition of mbedtls_ssl_tls1_3_labels_union + * below. */ +#define MBEDTLS_SSL_TLS1_3_LABEL_LIST \ + MBEDTLS_SSL_TLS1_3_LABEL( finished , "finished" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( resumption , "resumption" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( traffic_upd , "traffic upd" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( exporter , "exporter" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( key , "key" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( iv , "iv" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( c_hs_traffic, "c hs traffic" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( c_ap_traffic, "c ap traffic" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( c_e_traffic , "c e traffic" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( s_hs_traffic, "s hs traffic" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( s_ap_traffic, "s ap traffic" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( s_e_traffic , "s e traffic" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( e_exp_master, "e exp master" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( res_master , "res master" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( exp_master , "exp master" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( ext_binder , "ext binder" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( res_binder , "res binder" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( derived , "derived" ) + +#define MBEDTLS_SSL_TLS1_3_LABEL( name, string ) \ + const unsigned char name [ sizeof(string) - 1 ]; + +union mbedtls_ssl_tls1_3_labels_union +{ + MBEDTLS_SSL_TLS1_3_LABEL_LIST +}; +struct mbedtls_ssl_tls1_3_labels_struct +{ + MBEDTLS_SSL_TLS1_3_LABEL_LIST +}; +#undef MBEDTLS_SSL_TLS1_3_LABEL + +extern const struct mbedtls_ssl_tls1_3_labels_struct mbedtls_ssl_tls1_3_labels; + +#define MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( LABEL ) \ + mbedtls_ssl_tls1_3_labels.LABEL, \ + sizeof(mbedtls_ssl_tls1_3_labels.LABEL) + +#define MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN \ + sizeof( union mbedtls_ssl_tls1_3_labels_union ) + +/* The maximum length of HKDF contexts used in the TLS 1.3 standard. + * Since contexts are always hashes of message transcripts, this can + * be approximated from above by the maximum hash size. */ +#define MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN \ + MBEDTLS_MD_MAX_SIZE + +/* Maximum desired length for expanded key material generated + * by HKDF-Expand-Label. + * + * Warning: If this ever needs to be increased, the implementation + * ssl_tls1_3_hkdf_encode_label() in ssl_tls13_keys.c needs to be + * adjusted since it currently assumes that HKDF key expansion + * is never used with more than 255 Bytes of output. */ +#define MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_EXPANSION_LEN 255 + +/** + * \brief The \c HKDF-Expand-Label function from + * the TLS 1.3 standard RFC 8446. + * + * + * HKDF-Expand-Label( Secret, Label, Context, Length ) = + * HKDF-Expand( Secret, HkdfLabel, Length ) + * + * + * \param hash_alg The identifier for the hash algorithm to use. + * \param secret The \c Secret argument to \c HKDF-Expand-Label. + * This must be a readable buffer of length \p slen Bytes. + * \param slen The length of \p secret in Bytes. + * \param label The \c Label argument to \c HKDF-Expand-Label. + * This must be a readable buffer of length \p llen Bytes. + * \param llen The length of \p label in Bytes. + * \param ctx The \c Context argument to \c HKDF-Expand-Label. + * This must be a readable buffer of length \p clen Bytes. + * \param clen The length of \p context in Bytes. + * \param buf The destination buffer to hold the expanded secret. + * This must be a writable buffer of length \p blen Bytes. + * \param blen The desired size of the expanded secret in Bytes. + * + * \returns \c 0 on success. + * \return A negative error code on failure. + */ + +int mbedtls_ssl_tls1_3_hkdf_expand_label( + mbedtls_md_type_t hash_alg, + const unsigned char *secret, size_t slen, + const unsigned char *label, size_t llen, + const unsigned char *ctx, size_t clen, + unsigned char *buf, size_t blen ); + +/** + * \brief This function is part of the TLS 1.3 key schedule. + * It extracts key and IV for the actual client/server traffic + * from the client/server traffic secrets. + * + * From RFC 8446: + * + * + * [sender]_write_key = HKDF-Expand-Label(Secret, "key", "", key_length) + * [sender]_write_iv = HKDF-Expand-Label(Secret, "iv", "", iv_length)* + * + * + * \param hash_alg The identifier for the hash algorithm to be used + * for the HKDF-based expansion of the secret. + * \param client_secret The client traffic secret. + * This must be a readable buffer of size \p slen Bytes + * \param server_secret The server traffic secret. + * This must be a readable buffer of size \p slen Bytes + * \param slen Length of the secrets \p client_secret and + * \p server_secret in Bytes. + * \param key_len The desired length of the key to be extracted in Bytes. + * \param iv_len The desired length of the IV to be extracted in Bytes. + * \param keys The address of the structure holding the generated + * keys and IVs. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ + +int mbedtls_ssl_tls1_3_make_traffic_keys( + mbedtls_md_type_t hash_alg, + const unsigned char *client_secret, + const unsigned char *server_secret, + size_t slen, size_t key_len, size_t iv_len, + mbedtls_ssl_key_set *keys ); + + +#define MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED 0 +#define MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED 1 + +/** + * \brief The \c Derive-Secret function from the TLS 1.3 standard RFC 8446. + * + * + * Derive-Secret( Secret, Label, Messages ) = + * HKDF-Expand-Label( Secret, Label, + * Hash( Messages ), + * Hash.Length ) ) + * + * + * \param hash_alg The identifier for the hash function used for the + * applications of HKDF. + * \param secret The \c Secret argument to the \c Derive-Secret function. + * This must be a readable buffer of length \p slen Bytes. + * \param slen The length of \p secret in Bytes. + * \param label The \c Label argument to the \c Derive-Secret function. + * This must be a readable buffer of length \p llen Bytes. + * \param llen The length of \p label in Bytes. + * \param ctx The hash of the \c Messages argument to the + * \c Derive-Secret function, or the \c Messages argument + * itself, depending on \p context_already_hashed. + * \param clen The length of \p hash. + * \param ctx_hashed This indicates whether the \p ctx contains the hash of + * the \c Messages argument in the application of the + * \c Derive-Secret function + * (value MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED), or whether + * it is the content of \c Messages itself, in which case + * the function takes care of the hashing + * (value MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED). + * \param dstbuf The target buffer to write the output of + * \c Derive-Secret to. This must be a writable buffer of + * size \p buflen Bytes. + * \param buflen The length of \p dstbuf in Bytes. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ +int mbedtls_ssl_tls1_3_derive_secret( + mbedtls_md_type_t hash_alg, + const unsigned char *secret, size_t slen, + const unsigned char *label, size_t llen, + const unsigned char *ctx, size_t clen, + int ctx_hashed, + unsigned char *dstbuf, size_t buflen ); + +/** + * \brief Compute the next secret in the TLS 1.3 key schedule + * + * The TLS 1.3 key schedule proceeds as follows to compute + * the three main secrets during the handshake: The early + * secret for early data, the handshake secret for all + * other encrypted handshake messages, and the master + * secret for all application traffic. + * + * + * 0 + * | + * v + * PSK -> HKDF-Extract = Early Secret + * | + * v + * Derive-Secret( ., "derived", "" ) + * | + * v + * (EC)DHE -> HKDF-Extract = Handshake Secret + * | + * v + * Derive-Secret( ., "derived", "" ) + * | + * v + * 0 -> HKDF-Extract = Master Secret + * + * + * Each of the three secrets in turn is the basis for further + * key derivations, such as the derivation of traffic keys and IVs; + * see e.g. mbedtls_ssl_tls1_3_make_traffic_keys(). + * + * This function implements one step in this evolution of secrets: + * + * + * old_secret + * | + * v + * Derive-Secret( ., "derived", "" ) + * | + * v + * input -> HKDF-Extract = new_secret + * + * + * \param hash_alg The identifier for the hash function used for the + * applications of HKDF. + * \param secret_old The address of the buffer holding the old secret + * on function entry. If not \c NULL, this must be a + * readable buffer whose size matches the output size + * of the hash function represented by \p hash_alg. + * If \c NULL, an all \c 0 array will be used instead. + * \param input The address of the buffer holding the additional + * input for the key derivation (e.g., the PSK or the + * ephemeral (EC)DH secret). If not \c NULL, this must be + * a readable buffer whose size \p input_len Bytes. + * If \c NULL, an all \c 0 array will be used instead. + * \param input_len The length of \p input in Bytes. + * \param secret_new The address of the buffer holding the new secret + * on function exit. This must be a writable buffer + * whose size matches the output size of the hash + * function represented by \p hash_alg. + * This may be the same as \p secret_old. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ + +int mbedtls_ssl_tls1_3_evolve_secret( + mbedtls_md_type_t hash_alg, + const unsigned char *secret_old, + const unsigned char *input, size_t input_len, + unsigned char *secret_new ); + +#endif /* MBEDTLS_SSL_TLS1_3_KEYS_H */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/threading.c b/Android/Level4/app/src/main/c/mbedtls/library/threading.c new file mode 100644 index 0000000..9268da1 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/threading.c @@ -0,0 +1,181 @@ +/* + * Threading abstraction layer + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ + +/* + * Ensure gmtime_r is available even with -std=c99; must be defined before + * config.h, which pulls in glibc's features.h. Harmless on other platforms. + */ +#if !defined(_POSIX_C_SOURCE) +#define _POSIX_C_SOURCE 200112L +#endif + +#include "common.h" + +#if defined(MBEDTLS_THREADING_C) + +#include "mbedtls/threading.h" + +#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT) + +#if !defined(_WIN32) && (defined(unix) || \ + defined(__unix) || defined(__unix__) || (defined(__APPLE__) && \ + defined(__MACH__))) +#include +#endif /* !_WIN32 && (unix || __unix || __unix__ || + * (__APPLE__ && __MACH__)) */ + +#if !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \ + ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \ + _POSIX_THREAD_SAFE_FUNCTIONS >= 20112L ) ) +/* + * This is a convenience shorthand macro to avoid checking the long + * preprocessor conditions above. Ideally, we could expose this macro in + * platform_util.h and simply use it in platform_util.c, threading.c and + * threading.h. However, this macro is not part of the Mbed TLS public API, so + * we keep it private by only defining it in this file + */ + +#if ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) +#define THREADING_USE_GMTIME +#endif /* ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) */ + +#endif /* !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \ + ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \ + _POSIX_THREAD_SAFE_FUNCTIONS >= 20112L ) ) */ + +#endif /* MBEDTLS_HAVE_TIME_DATE && !MBEDTLS_PLATFORM_GMTIME_R_ALT */ + +#if defined(MBEDTLS_THREADING_PTHREAD) +static void threading_mutex_init_pthread( mbedtls_threading_mutex_t *mutex ) +{ + if( mutex == NULL ) + return; + + mutex->is_valid = pthread_mutex_init( &mutex->mutex, NULL ) == 0; +} + +static void threading_mutex_free_pthread( mbedtls_threading_mutex_t *mutex ) +{ + if( mutex == NULL || !mutex->is_valid ) + return; + + (void) pthread_mutex_destroy( &mutex->mutex ); + mutex->is_valid = 0; +} + +static int threading_mutex_lock_pthread( mbedtls_threading_mutex_t *mutex ) +{ + if( mutex == NULL || ! mutex->is_valid ) + return( MBEDTLS_ERR_THREADING_BAD_INPUT_DATA ); + + if( pthread_mutex_lock( &mutex->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); + + return( 0 ); +} + +static int threading_mutex_unlock_pthread( mbedtls_threading_mutex_t *mutex ) +{ + if( mutex == NULL || ! mutex->is_valid ) + return( MBEDTLS_ERR_THREADING_BAD_INPUT_DATA ); + + if( pthread_mutex_unlock( &mutex->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); + + return( 0 ); +} + +void (*mbedtls_mutex_init)( mbedtls_threading_mutex_t * ) = threading_mutex_init_pthread; +void (*mbedtls_mutex_free)( mbedtls_threading_mutex_t * ) = threading_mutex_free_pthread; +int (*mbedtls_mutex_lock)( mbedtls_threading_mutex_t * ) = threading_mutex_lock_pthread; +int (*mbedtls_mutex_unlock)( mbedtls_threading_mutex_t * ) = threading_mutex_unlock_pthread; + +/* + * With phtreads we can statically initialize mutexes + */ +#define MUTEX_INIT = { PTHREAD_MUTEX_INITIALIZER, 1 } + +#endif /* MBEDTLS_THREADING_PTHREAD */ + +#if defined(MBEDTLS_THREADING_ALT) +static int threading_mutex_fail( mbedtls_threading_mutex_t *mutex ) +{ + ((void) mutex ); + return( MBEDTLS_ERR_THREADING_BAD_INPUT_DATA ); +} +static void threading_mutex_dummy( mbedtls_threading_mutex_t *mutex ) +{ + ((void) mutex ); + return; +} + +void (*mbedtls_mutex_init)( mbedtls_threading_mutex_t * ) = threading_mutex_dummy; +void (*mbedtls_mutex_free)( mbedtls_threading_mutex_t * ) = threading_mutex_dummy; +int (*mbedtls_mutex_lock)( mbedtls_threading_mutex_t * ) = threading_mutex_fail; +int (*mbedtls_mutex_unlock)( mbedtls_threading_mutex_t * ) = threading_mutex_fail; + +/* + * Set functions pointers and initialize global mutexes + */ +void mbedtls_threading_set_alt( void (*mutex_init)( mbedtls_threading_mutex_t * ), + void (*mutex_free)( mbedtls_threading_mutex_t * ), + int (*mutex_lock)( mbedtls_threading_mutex_t * ), + int (*mutex_unlock)( mbedtls_threading_mutex_t * ) ) +{ + mbedtls_mutex_init = mutex_init; + mbedtls_mutex_free = mutex_free; + mbedtls_mutex_lock = mutex_lock; + mbedtls_mutex_unlock = mutex_unlock; + +#if defined(MBEDTLS_FS_IO) + mbedtls_mutex_init( &mbedtls_threading_readdir_mutex ); +#endif +#if defined(THREADING_USE_GMTIME) + mbedtls_mutex_init( &mbedtls_threading_gmtime_mutex ); +#endif +} + +/* + * Free global mutexes + */ +void mbedtls_threading_free_alt( void ) +{ +#if defined(MBEDTLS_FS_IO) + mbedtls_mutex_free( &mbedtls_threading_readdir_mutex ); +#endif +#if defined(THREADING_USE_GMTIME) + mbedtls_mutex_free( &mbedtls_threading_gmtime_mutex ); +#endif +} +#endif /* MBEDTLS_THREADING_ALT */ + +/* + * Define global mutexes + */ +#ifndef MUTEX_INIT +#define MUTEX_INIT +#endif +#if defined(MBEDTLS_FS_IO) +mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex MUTEX_INIT; +#endif +#if defined(THREADING_USE_GMTIME) +mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex MUTEX_INIT; +#endif + +#endif /* MBEDTLS_THREADING_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/timing.c b/Android/Level4/app/src/main/c/mbedtls/library/timing.c new file mode 100644 index 0000000..eb41461 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/timing.c @@ -0,0 +1,530 @@ +/* + * Portable interface to the CPU cycle counter + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 "common.h" + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif + +#if defined(MBEDTLS_TIMING_C) + +#include "mbedtls/timing.h" + +#if !defined(MBEDTLS_TIMING_ALT) + +#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ + !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \ + !defined(__HAIKU__) && !defined(__midipix__) +#error "This module only works on Unix and Windows, see MBEDTLS_TIMING_C in config.h" +#endif + +#ifndef asm +#define asm __asm +#endif + +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + +#include +#include + +struct _hr_time +{ + LARGE_INTEGER start; +}; + +#else + +#include +#include +#include +#include +#include + +struct _hr_time +{ + struct timeval start; +}; + +#endif /* _WIN32 && !EFIX64 && !EFI32 */ + +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + ( defined(_MSC_VER) && defined(_M_IX86) ) || defined(__WATCOMC__) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long tsc; + __asm rdtsc + __asm mov [tsc], eax + return( tsc ); +} +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + ( _MSC_VER && _M_IX86 ) || __WATCOMC__ */ + +/* some versions of mingw-64 have 32-bit longs even on x84_64 */ +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + defined(__GNUC__) && ( defined(__i386__) || ( \ + ( defined(__amd64__) || defined( __x86_64__) ) && __SIZEOF_LONG__ == 4 ) ) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long lo, hi; + asm volatile( "rdtsc" : "=a" (lo), "=d" (hi) ); + return( lo ); +} +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + __GNUC__ && __i386__ */ + +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + defined(__GNUC__) && ( defined(__amd64__) || defined(__x86_64__) ) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long lo, hi; + asm volatile( "rdtsc" : "=a" (lo), "=d" (hi) ); + return( lo | ( hi << 32 ) ); +} +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + __GNUC__ && ( __amd64__ || __x86_64__ ) */ + +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + defined(__GNUC__) && ( defined(__powerpc__) || defined(__ppc__) ) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long tbl, tbu0, tbu1; + + do + { + asm volatile( "mftbu %0" : "=r" (tbu0) ); + asm volatile( "mftb %0" : "=r" (tbl ) ); + asm volatile( "mftbu %0" : "=r" (tbu1) ); + } + while( tbu0 != tbu1 ); + + return( tbl ); +} +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + __GNUC__ && ( __powerpc__ || __ppc__ ) */ + +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + defined(__GNUC__) && defined(__sparc64__) + +#if defined(__OpenBSD__) +#warning OpenBSD does not allow access to tick register using software version instead +#else +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long tick; + asm volatile( "rdpr %%tick, %0;" : "=&r" (tick) ); + return( tick ); +} +#endif /* __OpenBSD__ */ +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + __GNUC__ && __sparc64__ */ + +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + defined(__GNUC__) && defined(__sparc__) && !defined(__sparc64__) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long tick; + asm volatile( ".byte 0x83, 0x41, 0x00, 0x00" ); + asm volatile( "mov %%g1, %0" : "=r" (tick) ); + return( tick ); +} +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + __GNUC__ && __sparc__ && !__sparc64__ */ + +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + defined(__GNUC__) && defined(__alpha__) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long cc; + asm volatile( "rpcc %0" : "=r" (cc) ); + return( cc & 0xFFFFFFFF ); +} +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + __GNUC__ && __alpha__ */ + +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + defined(__GNUC__) && defined(__ia64__) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long itc; + asm volatile( "mov %0 = ar.itc" : "=r" (itc) ); + return( itc ); +} +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + __GNUC__ && __ia64__ */ + +#if !defined(HAVE_HARDCLOCK) && defined(_MSC_VER) && \ + !defined(EFIX64) && !defined(EFI32) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + LARGE_INTEGER offset; + + QueryPerformanceCounter( &offset ); + + return( (unsigned long)( offset.QuadPart ) ); +} +#endif /* !HAVE_HARDCLOCK && _MSC_VER && !EFIX64 && !EFI32 */ + +#if !defined(HAVE_HARDCLOCK) + +#define HAVE_HARDCLOCK + +static int hardclock_init = 0; +static struct timeval tv_init; + +unsigned long mbedtls_timing_hardclock( void ) +{ + struct timeval tv_cur; + + if( hardclock_init == 0 ) + { + gettimeofday( &tv_init, NULL ); + hardclock_init = 1; + } + + gettimeofday( &tv_cur, NULL ); + return( ( tv_cur.tv_sec - tv_init.tv_sec ) * 1000000 + + ( tv_cur.tv_usec - tv_init.tv_usec ) ); +} +#endif /* !HAVE_HARDCLOCK */ + +volatile int mbedtls_timing_alarmed = 0; + +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + +unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset ) +{ + struct _hr_time *t = (struct _hr_time *) val; + + if( reset ) + { + QueryPerformanceCounter( &t->start ); + return( 0 ); + } + else + { + unsigned long delta; + LARGE_INTEGER now, hfreq; + QueryPerformanceCounter( &now ); + QueryPerformanceFrequency( &hfreq ); + delta = (unsigned long)( ( now.QuadPart - t->start.QuadPart ) * 1000ul + / hfreq.QuadPart ); + return( delta ); + } +} + +/* It's OK to use a global because alarm() is supposed to be global anyway */ +static DWORD alarmMs; + +static void TimerProc( void *TimerContext ) +{ + (void) TimerContext; + Sleep( alarmMs ); + mbedtls_timing_alarmed = 1; + /* _endthread will be called implicitly on return + * That ensures execution of thread funcition's epilogue */ +} + +void mbedtls_set_alarm( int seconds ) +{ + if( seconds == 0 ) + { + /* No need to create a thread for this simple case. + * Also, this shorcut is more reliable at least on MinGW32 */ + mbedtls_timing_alarmed = 1; + return; + } + + mbedtls_timing_alarmed = 0; + alarmMs = seconds * 1000; + (void) _beginthread( TimerProc, 0, NULL ); +} + +#else /* _WIN32 && !EFIX64 && !EFI32 */ + +unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset ) +{ + struct _hr_time *t = (struct _hr_time *) val; + + if( reset ) + { + gettimeofday( &t->start, NULL ); + return( 0 ); + } + else + { + unsigned long delta; + struct timeval now; + gettimeofday( &now, NULL ); + delta = ( now.tv_sec - t->start.tv_sec ) * 1000ul + + ( now.tv_usec - t->start.tv_usec ) / 1000; + return( delta ); + } +} + +static void sighandler( int signum ) +{ + mbedtls_timing_alarmed = 1; + signal( signum, sighandler ); +} + +void mbedtls_set_alarm( int seconds ) +{ + mbedtls_timing_alarmed = 0; + signal( SIGALRM, sighandler ); + alarm( seconds ); + if( seconds == 0 ) + { + /* alarm(0) cancelled any previous pending alarm, but the + handler won't fire, so raise the flag straight away. */ + mbedtls_timing_alarmed = 1; + } +} + +#endif /* _WIN32 && !EFIX64 && !EFI32 */ + +/* + * Set delays to watch + */ +void mbedtls_timing_set_delay( void *data, uint32_t int_ms, uint32_t fin_ms ) +{ + mbedtls_timing_delay_context *ctx = (mbedtls_timing_delay_context *) data; + + ctx->int_ms = int_ms; + ctx->fin_ms = fin_ms; + + if( fin_ms != 0 ) + (void) mbedtls_timing_get_timer( &ctx->timer, 1 ); +} + +/* + * Get number of delays expired + */ +int mbedtls_timing_get_delay( void *data ) +{ + mbedtls_timing_delay_context *ctx = (mbedtls_timing_delay_context *) data; + unsigned long elapsed_ms; + + if( ctx->fin_ms == 0 ) + return( -1 ); + + elapsed_ms = mbedtls_timing_get_timer( &ctx->timer, 0 ); + + if( elapsed_ms >= ctx->fin_ms ) + return( 2 ); + + if( elapsed_ms >= ctx->int_ms ) + return( 1 ); + + return( 0 ); +} + +#endif /* !MBEDTLS_TIMING_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +/* + * Busy-waits for the given number of milliseconds. + * Used for testing mbedtls_timing_hardclock. + */ +static void busy_msleep( unsigned long msec ) +{ + struct mbedtls_timing_hr_time hires; + unsigned long i = 0; /* for busy-waiting */ + volatile unsigned long j; /* to prevent optimisation */ + + (void) mbedtls_timing_get_timer( &hires, 1 ); + + while( mbedtls_timing_get_timer( &hires, 0 ) < msec ) + i++; + + j = i; + (void) j; +} + +#define FAIL do \ + { \ + if( verbose != 0 ) \ + { \ + mbedtls_printf( "failed at line %d\n", __LINE__ ); \ + mbedtls_printf( " cycles=%lu ratio=%lu millisecs=%lu secs=%lu hardfail=%d a=%lu b=%lu\n", \ + cycles, ratio, millisecs, secs, hardfail, \ + (unsigned long) a, (unsigned long) b ); \ + mbedtls_printf( " elapsed(hires)=%lu elapsed(ctx)=%lu status(ctx)=%d\n", \ + mbedtls_timing_get_timer( &hires, 0 ), \ + mbedtls_timing_get_timer( &ctx.timer, 0 ), \ + mbedtls_timing_get_delay( &ctx ) ); \ + } \ + return( 1 ); \ + } while( 0 ) + +/* + * Checkup routine + * + * Warning: this is work in progress, some tests may not be reliable enough + * yet! False positives may happen. + */ +int mbedtls_timing_self_test( int verbose ) +{ + unsigned long cycles = 0, ratio = 0; + unsigned long millisecs = 0, secs = 0; + int hardfail = 0; + struct mbedtls_timing_hr_time hires; + uint32_t a = 0, b = 0; + mbedtls_timing_delay_context ctx; + + if( verbose != 0 ) + mbedtls_printf( " TIMING tests note: will take some time!\n" ); + + if( verbose != 0 ) + mbedtls_printf( " TIMING test #1 (set_alarm / get_timer): " ); + + { + secs = 1; + + (void) mbedtls_timing_get_timer( &hires, 1 ); + + mbedtls_set_alarm( (int) secs ); + while( !mbedtls_timing_alarmed ) + ; + + millisecs = mbedtls_timing_get_timer( &hires, 0 ); + + /* For some reason on Windows it looks like alarm has an extra delay + * (maybe related to creating a new thread). Allow some room here. */ + if( millisecs < 800 * secs || millisecs > 1200 * secs + 300 ) + FAIL; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " TIMING test #2 (set/get_delay ): " ); + + { + a = 800; + b = 400; + mbedtls_timing_set_delay( &ctx, a, a + b ); /* T = 0 */ + + busy_msleep( a - a / 4 ); /* T = a - a/4 */ + if( mbedtls_timing_get_delay( &ctx ) != 0 ) + FAIL; + + busy_msleep( a / 4 + b / 4 ); /* T = a + b/4 */ + if( mbedtls_timing_get_delay( &ctx ) != 1 ) + FAIL; + + busy_msleep( b ); /* T = a + b + b/4 */ + if( mbedtls_timing_get_delay( &ctx ) != 2 ) + FAIL; + } + + mbedtls_timing_set_delay( &ctx, 0, 0 ); + busy_msleep( 200 ); + if( mbedtls_timing_get_delay( &ctx ) != -1 ) + FAIL; + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " TIMING test #3 (hardclock / get_timer): " ); + + /* + * Allow one failure for possible counter wrapping. + * On a 4Ghz 32-bit machine the cycle counter wraps about once per second; + * since the whole test is about 10ms, it shouldn't happen twice in a row. + */ + +hard_test: + if( hardfail > 1 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed (ignored)\n" ); + + goto hard_test_done; + } + + /* Get a reference ratio cycles/ms */ + millisecs = 1; + cycles = mbedtls_timing_hardclock(); + busy_msleep( millisecs ); + cycles = mbedtls_timing_hardclock() - cycles; + ratio = cycles / millisecs; + + /* Check that the ratio is mostly constant */ + for( millisecs = 2; millisecs <= 4; millisecs++ ) + { + cycles = mbedtls_timing_hardclock(); + busy_msleep( millisecs ); + cycles = mbedtls_timing_hardclock() - cycles; + + /* Allow variation up to 20% */ + if( cycles / millisecs < ratio - ratio / 5 || + cycles / millisecs > ratio + ratio / 5 ) + { + hardfail++; + goto hard_test; + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + +hard_test_done: + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_TIMING_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/version.c b/Android/Level4/app/src/main/c/mbedtls/library/version.c new file mode 100644 index 0000000..32a0d7d --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/version.c @@ -0,0 +1,44 @@ +/* + * Version information + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 "common.h" + +#if defined(MBEDTLS_VERSION_C) + +#include "mbedtls/version.h" +#include + +unsigned int mbedtls_version_get_number( void ) +{ + return( MBEDTLS_VERSION_NUMBER ); +} + +void mbedtls_version_get_string( char *string ) +{ + memcpy( string, MBEDTLS_VERSION_STRING, + sizeof( MBEDTLS_VERSION_STRING ) ); +} + +void mbedtls_version_get_string_full( char *string ) +{ + memcpy( string, MBEDTLS_VERSION_STRING_FULL, + sizeof( MBEDTLS_VERSION_STRING_FULL ) ); +} + +#endif /* MBEDTLS_VERSION_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/version_features.c b/Android/Level4/app/src/main/c/mbedtls/library/version_features.c new file mode 100644 index 0000000..42ccaf9 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/version_features.c @@ -0,0 +1,857 @@ +/* + * Version feature information + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 "common.h" + +#if defined(MBEDTLS_VERSION_C) + +#include "mbedtls/version.h" + +#include + +static const char * const features[] = { +#if defined(MBEDTLS_VERSION_FEATURES) +#if defined(MBEDTLS_HAVE_ASM) + "MBEDTLS_HAVE_ASM", +#endif /* MBEDTLS_HAVE_ASM */ +#if defined(MBEDTLS_NO_UDBL_DIVISION) + "MBEDTLS_NO_UDBL_DIVISION", +#endif /* MBEDTLS_NO_UDBL_DIVISION */ +#if defined(MBEDTLS_NO_64BIT_MULTIPLICATION) + "MBEDTLS_NO_64BIT_MULTIPLICATION", +#endif /* MBEDTLS_NO_64BIT_MULTIPLICATION */ +#if defined(MBEDTLS_HAVE_SSE2) + "MBEDTLS_HAVE_SSE2", +#endif /* MBEDTLS_HAVE_SSE2 */ +#if defined(MBEDTLS_HAVE_TIME) + "MBEDTLS_HAVE_TIME", +#endif /* MBEDTLS_HAVE_TIME */ +#if defined(MBEDTLS_HAVE_TIME_DATE) + "MBEDTLS_HAVE_TIME_DATE", +#endif /* MBEDTLS_HAVE_TIME_DATE */ +#if defined(MBEDTLS_PLATFORM_MEMORY) + "MBEDTLS_PLATFORM_MEMORY", +#endif /* MBEDTLS_PLATFORM_MEMORY */ +#if defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) + "MBEDTLS_PLATFORM_NO_STD_FUNCTIONS", +#endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ +#if defined(MBEDTLS_PLATFORM_EXIT_ALT) + "MBEDTLS_PLATFORM_EXIT_ALT", +#endif /* MBEDTLS_PLATFORM_EXIT_ALT */ +#if defined(MBEDTLS_PLATFORM_TIME_ALT) + "MBEDTLS_PLATFORM_TIME_ALT", +#endif /* MBEDTLS_PLATFORM_TIME_ALT */ +#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) + "MBEDTLS_PLATFORM_FPRINTF_ALT", +#endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */ +#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) + "MBEDTLS_PLATFORM_PRINTF_ALT", +#endif /* MBEDTLS_PLATFORM_PRINTF_ALT */ +#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) + "MBEDTLS_PLATFORM_SNPRINTF_ALT", +#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ +#if defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT) + "MBEDTLS_PLATFORM_VSNPRINTF_ALT", +#endif /* MBEDTLS_PLATFORM_VSNPRINTF_ALT */ +#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) + "MBEDTLS_PLATFORM_NV_SEED_ALT", +#endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */ +#if defined(MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT) + "MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT", +#endif /* MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT */ +#if defined(MBEDTLS_DEPRECATED_WARNING) + "MBEDTLS_DEPRECATED_WARNING", +#endif /* MBEDTLS_DEPRECATED_WARNING */ +#if defined(MBEDTLS_DEPRECATED_REMOVED) + "MBEDTLS_DEPRECATED_REMOVED", +#endif /* MBEDTLS_DEPRECATED_REMOVED */ +#if defined(MBEDTLS_CHECK_PARAMS) + "MBEDTLS_CHECK_PARAMS", +#endif /* MBEDTLS_CHECK_PARAMS */ +#if defined(MBEDTLS_CHECK_PARAMS_ASSERT) + "MBEDTLS_CHECK_PARAMS_ASSERT", +#endif /* MBEDTLS_CHECK_PARAMS_ASSERT */ +#if defined(MBEDTLS_TIMING_ALT) + "MBEDTLS_TIMING_ALT", +#endif /* MBEDTLS_TIMING_ALT */ +#if defined(MBEDTLS_AES_ALT) + "MBEDTLS_AES_ALT", +#endif /* MBEDTLS_AES_ALT */ +#if defined(MBEDTLS_ARC4_ALT) + "MBEDTLS_ARC4_ALT", +#endif /* MBEDTLS_ARC4_ALT */ +#if defined(MBEDTLS_ARIA_ALT) + "MBEDTLS_ARIA_ALT", +#endif /* MBEDTLS_ARIA_ALT */ +#if defined(MBEDTLS_BLOWFISH_ALT) + "MBEDTLS_BLOWFISH_ALT", +#endif /* MBEDTLS_BLOWFISH_ALT */ +#if defined(MBEDTLS_CAMELLIA_ALT) + "MBEDTLS_CAMELLIA_ALT", +#endif /* MBEDTLS_CAMELLIA_ALT */ +#if defined(MBEDTLS_CCM_ALT) + "MBEDTLS_CCM_ALT", +#endif /* MBEDTLS_CCM_ALT */ +#if defined(MBEDTLS_CHACHA20_ALT) + "MBEDTLS_CHACHA20_ALT", +#endif /* MBEDTLS_CHACHA20_ALT */ +#if defined(MBEDTLS_CHACHAPOLY_ALT) + "MBEDTLS_CHACHAPOLY_ALT", +#endif /* MBEDTLS_CHACHAPOLY_ALT */ +#if defined(MBEDTLS_CMAC_ALT) + "MBEDTLS_CMAC_ALT", +#endif /* MBEDTLS_CMAC_ALT */ +#if defined(MBEDTLS_DES_ALT) + "MBEDTLS_DES_ALT", +#endif /* MBEDTLS_DES_ALT */ +#if defined(MBEDTLS_DHM_ALT) + "MBEDTLS_DHM_ALT", +#endif /* MBEDTLS_DHM_ALT */ +#if defined(MBEDTLS_ECJPAKE_ALT) + "MBEDTLS_ECJPAKE_ALT", +#endif /* MBEDTLS_ECJPAKE_ALT */ +#if defined(MBEDTLS_GCM_ALT) + "MBEDTLS_GCM_ALT", +#endif /* MBEDTLS_GCM_ALT */ +#if defined(MBEDTLS_NIST_KW_ALT) + "MBEDTLS_NIST_KW_ALT", +#endif /* MBEDTLS_NIST_KW_ALT */ +#if defined(MBEDTLS_MD2_ALT) + "MBEDTLS_MD2_ALT", +#endif /* MBEDTLS_MD2_ALT */ +#if defined(MBEDTLS_MD4_ALT) + "MBEDTLS_MD4_ALT", +#endif /* MBEDTLS_MD4_ALT */ +#if defined(MBEDTLS_MD5_ALT) + "MBEDTLS_MD5_ALT", +#endif /* MBEDTLS_MD5_ALT */ +#if defined(MBEDTLS_POLY1305_ALT) + "MBEDTLS_POLY1305_ALT", +#endif /* MBEDTLS_POLY1305_ALT */ +#if defined(MBEDTLS_RIPEMD160_ALT) + "MBEDTLS_RIPEMD160_ALT", +#endif /* MBEDTLS_RIPEMD160_ALT */ +#if defined(MBEDTLS_RSA_ALT) + "MBEDTLS_RSA_ALT", +#endif /* MBEDTLS_RSA_ALT */ +#if defined(MBEDTLS_SHA1_ALT) + "MBEDTLS_SHA1_ALT", +#endif /* MBEDTLS_SHA1_ALT */ +#if defined(MBEDTLS_SHA256_ALT) + "MBEDTLS_SHA256_ALT", +#endif /* MBEDTLS_SHA256_ALT */ +#if defined(MBEDTLS_SHA512_ALT) + "MBEDTLS_SHA512_ALT", +#endif /* MBEDTLS_SHA512_ALT */ +#if defined(MBEDTLS_XTEA_ALT) + "MBEDTLS_XTEA_ALT", +#endif /* MBEDTLS_XTEA_ALT */ +#if defined(MBEDTLS_ECP_ALT) + "MBEDTLS_ECP_ALT", +#endif /* MBEDTLS_ECP_ALT */ +#if defined(MBEDTLS_MD2_PROCESS_ALT) + "MBEDTLS_MD2_PROCESS_ALT", +#endif /* MBEDTLS_MD2_PROCESS_ALT */ +#if defined(MBEDTLS_MD4_PROCESS_ALT) + "MBEDTLS_MD4_PROCESS_ALT", +#endif /* MBEDTLS_MD4_PROCESS_ALT */ +#if defined(MBEDTLS_MD5_PROCESS_ALT) + "MBEDTLS_MD5_PROCESS_ALT", +#endif /* MBEDTLS_MD5_PROCESS_ALT */ +#if defined(MBEDTLS_RIPEMD160_PROCESS_ALT) + "MBEDTLS_RIPEMD160_PROCESS_ALT", +#endif /* MBEDTLS_RIPEMD160_PROCESS_ALT */ +#if defined(MBEDTLS_SHA1_PROCESS_ALT) + "MBEDTLS_SHA1_PROCESS_ALT", +#endif /* MBEDTLS_SHA1_PROCESS_ALT */ +#if defined(MBEDTLS_SHA256_PROCESS_ALT) + "MBEDTLS_SHA256_PROCESS_ALT", +#endif /* MBEDTLS_SHA256_PROCESS_ALT */ +#if defined(MBEDTLS_SHA512_PROCESS_ALT) + "MBEDTLS_SHA512_PROCESS_ALT", +#endif /* MBEDTLS_SHA512_PROCESS_ALT */ +#if defined(MBEDTLS_DES_SETKEY_ALT) + "MBEDTLS_DES_SETKEY_ALT", +#endif /* MBEDTLS_DES_SETKEY_ALT */ +#if defined(MBEDTLS_DES_CRYPT_ECB_ALT) + "MBEDTLS_DES_CRYPT_ECB_ALT", +#endif /* MBEDTLS_DES_CRYPT_ECB_ALT */ +#if defined(MBEDTLS_DES3_CRYPT_ECB_ALT) + "MBEDTLS_DES3_CRYPT_ECB_ALT", +#endif /* MBEDTLS_DES3_CRYPT_ECB_ALT */ +#if defined(MBEDTLS_AES_SETKEY_ENC_ALT) + "MBEDTLS_AES_SETKEY_ENC_ALT", +#endif /* MBEDTLS_AES_SETKEY_ENC_ALT */ +#if defined(MBEDTLS_AES_SETKEY_DEC_ALT) + "MBEDTLS_AES_SETKEY_DEC_ALT", +#endif /* MBEDTLS_AES_SETKEY_DEC_ALT */ +#if defined(MBEDTLS_AES_ENCRYPT_ALT) + "MBEDTLS_AES_ENCRYPT_ALT", +#endif /* MBEDTLS_AES_ENCRYPT_ALT */ +#if defined(MBEDTLS_AES_DECRYPT_ALT) + "MBEDTLS_AES_DECRYPT_ALT", +#endif /* MBEDTLS_AES_DECRYPT_ALT */ +#if defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT) + "MBEDTLS_ECDH_GEN_PUBLIC_ALT", +#endif /* MBEDTLS_ECDH_GEN_PUBLIC_ALT */ +#if defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT) + "MBEDTLS_ECDH_COMPUTE_SHARED_ALT", +#endif /* MBEDTLS_ECDH_COMPUTE_SHARED_ALT */ +#if defined(MBEDTLS_ECDSA_VERIFY_ALT) + "MBEDTLS_ECDSA_VERIFY_ALT", +#endif /* MBEDTLS_ECDSA_VERIFY_ALT */ +#if defined(MBEDTLS_ECDSA_SIGN_ALT) + "MBEDTLS_ECDSA_SIGN_ALT", +#endif /* MBEDTLS_ECDSA_SIGN_ALT */ +#if defined(MBEDTLS_ECDSA_GENKEY_ALT) + "MBEDTLS_ECDSA_GENKEY_ALT", +#endif /* MBEDTLS_ECDSA_GENKEY_ALT */ +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + "MBEDTLS_ECP_INTERNAL_ALT", +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ +#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) + "MBEDTLS_ECP_RANDOMIZE_JAC_ALT", +#endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */ +#if defined(MBEDTLS_ECP_ADD_MIXED_ALT) + "MBEDTLS_ECP_ADD_MIXED_ALT", +#endif /* MBEDTLS_ECP_ADD_MIXED_ALT */ +#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) + "MBEDTLS_ECP_DOUBLE_JAC_ALT", +#endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */ +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) + "MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT", +#endif /* MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT */ +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) + "MBEDTLS_ECP_NORMALIZE_JAC_ALT", +#endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */ +#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) + "MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT", +#endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */ +#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) + "MBEDTLS_ECP_RANDOMIZE_MXZ_ALT", +#endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */ +#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) + "MBEDTLS_ECP_NORMALIZE_MXZ_ALT", +#endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */ +#if defined(MBEDTLS_TEST_NULL_ENTROPY) + "MBEDTLS_TEST_NULL_ENTROPY", +#endif /* MBEDTLS_TEST_NULL_ENTROPY */ +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) + "MBEDTLS_ENTROPY_HARDWARE_ALT", +#endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ +#if defined(MBEDTLS_AES_ROM_TABLES) + "MBEDTLS_AES_ROM_TABLES", +#endif /* MBEDTLS_AES_ROM_TABLES */ +#if defined(MBEDTLS_AES_FEWER_TABLES) + "MBEDTLS_AES_FEWER_TABLES", +#endif /* MBEDTLS_AES_FEWER_TABLES */ +#if defined(MBEDTLS_CAMELLIA_SMALL_MEMORY) + "MBEDTLS_CAMELLIA_SMALL_MEMORY", +#endif /* MBEDTLS_CAMELLIA_SMALL_MEMORY */ +#if defined(MBEDTLS_CIPHER_MODE_CBC) + "MBEDTLS_CIPHER_MODE_CBC", +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_CIPHER_MODE_CFB) + "MBEDTLS_CIPHER_MODE_CFB", +#endif /* MBEDTLS_CIPHER_MODE_CFB */ +#if defined(MBEDTLS_CIPHER_MODE_CTR) + "MBEDTLS_CIPHER_MODE_CTR", +#endif /* MBEDTLS_CIPHER_MODE_CTR */ +#if defined(MBEDTLS_CIPHER_MODE_OFB) + "MBEDTLS_CIPHER_MODE_OFB", +#endif /* MBEDTLS_CIPHER_MODE_OFB */ +#if defined(MBEDTLS_CIPHER_MODE_XTS) + "MBEDTLS_CIPHER_MODE_XTS", +#endif /* MBEDTLS_CIPHER_MODE_XTS */ +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) + "MBEDTLS_CIPHER_NULL_CIPHER", +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ +#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) + "MBEDTLS_CIPHER_PADDING_PKCS7", +#endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */ +#if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) + "MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS", +#endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */ +#if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) + "MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN", +#endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */ +#if defined(MBEDTLS_CIPHER_PADDING_ZEROS) + "MBEDTLS_CIPHER_PADDING_ZEROS", +#endif /* MBEDTLS_CIPHER_PADDING_ZEROS */ +#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) + "MBEDTLS_CTR_DRBG_USE_128_BIT_KEY", +#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */ +#if defined(MBEDTLS_ENABLE_WEAK_CIPHERSUITES) + "MBEDTLS_ENABLE_WEAK_CIPHERSUITES", +#endif /* MBEDTLS_ENABLE_WEAK_CIPHERSUITES */ +#if defined(MBEDTLS_REMOVE_ARC4_CIPHERSUITES) + "MBEDTLS_REMOVE_ARC4_CIPHERSUITES", +#endif /* MBEDTLS_REMOVE_ARC4_CIPHERSUITES */ +#if defined(MBEDTLS_REMOVE_3DES_CIPHERSUITES) + "MBEDTLS_REMOVE_3DES_CIPHERSUITES", +#endif /* MBEDTLS_REMOVE_3DES_CIPHERSUITES */ +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + "MBEDTLS_ECP_DP_SECP192R1_ENABLED", +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) + "MBEDTLS_ECP_DP_SECP224R1_ENABLED", +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + "MBEDTLS_ECP_DP_SECP256R1_ENABLED", +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + "MBEDTLS_ECP_DP_SECP384R1_ENABLED", +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) + "MBEDTLS_ECP_DP_SECP521R1_ENABLED", +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) + "MBEDTLS_ECP_DP_SECP192K1_ENABLED", +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) + "MBEDTLS_ECP_DP_SECP224K1_ENABLED", +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) + "MBEDTLS_ECP_DP_SECP256K1_ENABLED", +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) + "MBEDTLS_ECP_DP_BP256R1_ENABLED", +#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) + "MBEDTLS_ECP_DP_BP384R1_ENABLED", +#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) + "MBEDTLS_ECP_DP_BP512R1_ENABLED", +#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) + "MBEDTLS_ECP_DP_CURVE25519_ENABLED", +#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) + "MBEDTLS_ECP_DP_CURVE448_ENABLED", +#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ +#if defined(MBEDTLS_ECP_NIST_OPTIM) + "MBEDTLS_ECP_NIST_OPTIM", +#endif /* MBEDTLS_ECP_NIST_OPTIM */ +#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + "MBEDTLS_ECP_NO_INTERNAL_RNG", +#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + "MBEDTLS_ECP_RESTARTABLE", +#endif /* MBEDTLS_ECP_RESTARTABLE */ +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + "MBEDTLS_ECDH_LEGACY_CONTEXT", +#endif /* MBEDTLS_ECDH_LEGACY_CONTEXT */ +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) + "MBEDTLS_ECDSA_DETERMINISTIC", +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + "MBEDTLS_KEY_EXCHANGE_PSK_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + "MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + "MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + "MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) + "MBEDTLS_KEY_EXCHANGE_RSA_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) + "MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) + "MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) + "MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + "MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) + "MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + "MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ +#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) + "MBEDTLS_PK_PARSE_EC_EXTENDED", +#endif /* MBEDTLS_PK_PARSE_EC_EXTENDED */ +#if defined(MBEDTLS_ERROR_STRERROR_DUMMY) + "MBEDTLS_ERROR_STRERROR_DUMMY", +#endif /* MBEDTLS_ERROR_STRERROR_DUMMY */ +#if defined(MBEDTLS_GENPRIME) + "MBEDTLS_GENPRIME", +#endif /* MBEDTLS_GENPRIME */ +#if defined(MBEDTLS_FS_IO) + "MBEDTLS_FS_IO", +#endif /* MBEDTLS_FS_IO */ +#if defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) + "MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES", +#endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */ +#if defined(MBEDTLS_NO_PLATFORM_ENTROPY) + "MBEDTLS_NO_PLATFORM_ENTROPY", +#endif /* MBEDTLS_NO_PLATFORM_ENTROPY */ +#if defined(MBEDTLS_ENTROPY_FORCE_SHA256) + "MBEDTLS_ENTROPY_FORCE_SHA256", +#endif /* MBEDTLS_ENTROPY_FORCE_SHA256 */ +#if defined(MBEDTLS_ENTROPY_NV_SEED) + "MBEDTLS_ENTROPY_NV_SEED", +#endif /* MBEDTLS_ENTROPY_NV_SEED */ +#if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) + "MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER", +#endif /* MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */ +#if defined(MBEDTLS_MEMORY_DEBUG) + "MBEDTLS_MEMORY_DEBUG", +#endif /* MBEDTLS_MEMORY_DEBUG */ +#if defined(MBEDTLS_MEMORY_BACKTRACE) + "MBEDTLS_MEMORY_BACKTRACE", +#endif /* MBEDTLS_MEMORY_BACKTRACE */ +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) + "MBEDTLS_PK_RSA_ALT_SUPPORT", +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ +#if defined(MBEDTLS_PKCS1_V15) + "MBEDTLS_PKCS1_V15", +#endif /* MBEDTLS_PKCS1_V15 */ +#if defined(MBEDTLS_PKCS1_V21) + "MBEDTLS_PKCS1_V21", +#endif /* MBEDTLS_PKCS1_V21 */ +#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS) + "MBEDTLS_PSA_CRYPTO_DRIVERS", +#endif /* MBEDTLS_PSA_CRYPTO_DRIVERS */ +#if defined(MBEDTLS_PSA_CRYPTO_SPM) + "MBEDTLS_PSA_CRYPTO_SPM", +#endif /* MBEDTLS_PSA_CRYPTO_SPM */ +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) + "MBEDTLS_PSA_INJECT_ENTROPY", +#endif /* MBEDTLS_PSA_INJECT_ENTROPY */ +#if defined(MBEDTLS_RSA_NO_CRT) + "MBEDTLS_RSA_NO_CRT", +#endif /* MBEDTLS_RSA_NO_CRT */ +#if defined(MBEDTLS_SELF_TEST) + "MBEDTLS_SELF_TEST", +#endif /* MBEDTLS_SELF_TEST */ +#if defined(MBEDTLS_SHA256_SMALLER) + "MBEDTLS_SHA256_SMALLER", +#endif /* MBEDTLS_SHA256_SMALLER */ +#if defined(MBEDTLS_SHA512_SMALLER) + "MBEDTLS_SHA512_SMALLER", +#endif /* MBEDTLS_SHA512_SMALLER */ +#if defined(MBEDTLS_SHA512_NO_SHA384) + "MBEDTLS_SHA512_NO_SHA384", +#endif /* MBEDTLS_SHA512_NO_SHA384 */ +#if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES) + "MBEDTLS_SSL_ALL_ALERT_MESSAGES", +#endif /* MBEDTLS_SSL_ALL_ALERT_MESSAGES */ +#if defined(MBEDTLS_SSL_RECORD_CHECKING) + "MBEDTLS_SSL_RECORD_CHECKING", +#endif /* MBEDTLS_SSL_RECORD_CHECKING */ +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + "MBEDTLS_SSL_DTLS_CONNECTION_ID", +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + "MBEDTLS_SSL_ASYNC_PRIVATE", +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ +#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) + "MBEDTLS_SSL_CONTEXT_SERIALIZATION", +#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */ +#if defined(MBEDTLS_SSL_DEBUG_ALL) + "MBEDTLS_SSL_DEBUG_ALL", +#endif /* MBEDTLS_SSL_DEBUG_ALL */ +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + "MBEDTLS_SSL_ENCRYPT_THEN_MAC", +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + "MBEDTLS_SSL_EXTENDED_MASTER_SECRET", +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ +#if defined(MBEDTLS_SSL_FALLBACK_SCSV) + "MBEDTLS_SSL_FALLBACK_SCSV", +#endif /* MBEDTLS_SSL_FALLBACK_SCSV */ +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + "MBEDTLS_SSL_KEEP_PEER_CERTIFICATE", +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + "MBEDTLS_SSL_HW_RECORD_ACCEL", +#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) + "MBEDTLS_SSL_CBC_RECORD_SPLITTING", +#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + "MBEDTLS_SSL_RENEGOTIATION", +#endif /* MBEDTLS_SSL_RENEGOTIATION */ +#if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) + "MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO", +#endif /* MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO */ +#if defined(MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE) + "MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE", +#endif /* MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE */ +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + "MBEDTLS_SSL_MAX_FRAGMENT_LENGTH", +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) + "MBEDTLS_SSL_PROTO_SSL3", +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) + "MBEDTLS_SSL_PROTO_TLS1", +#endif /* MBEDTLS_SSL_PROTO_TLS1 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) + "MBEDTLS_SSL_PROTO_TLS1_1", +#endif /* MBEDTLS_SSL_PROTO_TLS1_1 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + "MBEDTLS_SSL_PROTO_TLS1_2", +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL) + "MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL", +#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + "MBEDTLS_SSL_PROTO_DTLS", +#endif /* MBEDTLS_SSL_PROTO_DTLS */ +#if defined(MBEDTLS_SSL_ALPN) + "MBEDTLS_SSL_ALPN", +#endif /* MBEDTLS_SSL_ALPN */ +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + "MBEDTLS_SSL_DTLS_ANTI_REPLAY", +#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) + "MBEDTLS_SSL_DTLS_HELLO_VERIFY", +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ +#if defined(MBEDTLS_SSL_DTLS_SRTP) + "MBEDTLS_SSL_DTLS_SRTP", +#endif /* MBEDTLS_SSL_DTLS_SRTP */ +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) + "MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE", +#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE */ +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) + "MBEDTLS_SSL_DTLS_BADMAC_LIMIT", +#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */ +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + "MBEDTLS_SSL_SESSION_TICKETS", +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ +#if defined(MBEDTLS_SSL_EXPORT_KEYS) + "MBEDTLS_SSL_EXPORT_KEYS", +#endif /* MBEDTLS_SSL_EXPORT_KEYS */ +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + "MBEDTLS_SSL_SERVER_NAME_INDICATION", +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + "MBEDTLS_SSL_TRUNCATED_HMAC", +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT) + "MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT", +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT */ +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + "MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH", +#endif /* MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH */ +#if defined(MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN) + "MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN", +#endif /* MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN */ +#if defined(MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND) + "MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND", +#endif /* MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND */ +#if defined(MBEDTLS_TEST_HOOKS) + "MBEDTLS_TEST_HOOKS", +#endif /* MBEDTLS_TEST_HOOKS */ +#if defined(MBEDTLS_THREADING_ALT) + "MBEDTLS_THREADING_ALT", +#endif /* MBEDTLS_THREADING_ALT */ +#if defined(MBEDTLS_THREADING_PTHREAD) + "MBEDTLS_THREADING_PTHREAD", +#endif /* MBEDTLS_THREADING_PTHREAD */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + "MBEDTLS_USE_PSA_CRYPTO", +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#if defined(MBEDTLS_PSA_CRYPTO_CONFIG) + "MBEDTLS_PSA_CRYPTO_CONFIG", +#endif /* MBEDTLS_PSA_CRYPTO_CONFIG */ +#if defined(MBEDTLS_VERSION_FEATURES) + "MBEDTLS_VERSION_FEATURES", +#endif /* MBEDTLS_VERSION_FEATURES */ +#if defined(MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3) + "MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3", +#endif /* MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 */ +#if defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION) + "MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION", +#endif /* MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION */ +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + "MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK", +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ +#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) + "MBEDTLS_X509_CHECK_KEY_USAGE", +#endif /* MBEDTLS_X509_CHECK_KEY_USAGE */ +#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) + "MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE", +#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */ +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + "MBEDTLS_X509_RSASSA_PSS_SUPPORT", +#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ +#if defined(MBEDTLS_ZLIB_SUPPORT) + "MBEDTLS_ZLIB_SUPPORT", +#endif /* MBEDTLS_ZLIB_SUPPORT */ +#if defined(MBEDTLS_AESNI_C) + "MBEDTLS_AESNI_C", +#endif /* MBEDTLS_AESNI_C */ +#if defined(MBEDTLS_AES_C) + "MBEDTLS_AES_C", +#endif /* MBEDTLS_AES_C */ +#if defined(MBEDTLS_ARC4_C) + "MBEDTLS_ARC4_C", +#endif /* MBEDTLS_ARC4_C */ +#if defined(MBEDTLS_ASN1_PARSE_C) + "MBEDTLS_ASN1_PARSE_C", +#endif /* MBEDTLS_ASN1_PARSE_C */ +#if defined(MBEDTLS_ASN1_WRITE_C) + "MBEDTLS_ASN1_WRITE_C", +#endif /* MBEDTLS_ASN1_WRITE_C */ +#if defined(MBEDTLS_BASE64_C) + "MBEDTLS_BASE64_C", +#endif /* MBEDTLS_BASE64_C */ +#if defined(MBEDTLS_BIGNUM_C) + "MBEDTLS_BIGNUM_C", +#endif /* MBEDTLS_BIGNUM_C */ +#if defined(MBEDTLS_BLOWFISH_C) + "MBEDTLS_BLOWFISH_C", +#endif /* MBEDTLS_BLOWFISH_C */ +#if defined(MBEDTLS_CAMELLIA_C) + "MBEDTLS_CAMELLIA_C", +#endif /* MBEDTLS_CAMELLIA_C */ +#if defined(MBEDTLS_ARIA_C) + "MBEDTLS_ARIA_C", +#endif /* MBEDTLS_ARIA_C */ +#if defined(MBEDTLS_CCM_C) + "MBEDTLS_CCM_C", +#endif /* MBEDTLS_CCM_C */ +#if defined(MBEDTLS_CERTS_C) + "MBEDTLS_CERTS_C", +#endif /* MBEDTLS_CERTS_C */ +#if defined(MBEDTLS_CHACHA20_C) + "MBEDTLS_CHACHA20_C", +#endif /* MBEDTLS_CHACHA20_C */ +#if defined(MBEDTLS_CHACHAPOLY_C) + "MBEDTLS_CHACHAPOLY_C", +#endif /* MBEDTLS_CHACHAPOLY_C */ +#if defined(MBEDTLS_CIPHER_C) + "MBEDTLS_CIPHER_C", +#endif /* MBEDTLS_CIPHER_C */ +#if defined(MBEDTLS_CMAC_C) + "MBEDTLS_CMAC_C", +#endif /* MBEDTLS_CMAC_C */ +#if defined(MBEDTLS_CTR_DRBG_C) + "MBEDTLS_CTR_DRBG_C", +#endif /* MBEDTLS_CTR_DRBG_C */ +#if defined(MBEDTLS_DEBUG_C) + "MBEDTLS_DEBUG_C", +#endif /* MBEDTLS_DEBUG_C */ +#if defined(MBEDTLS_DES_C) + "MBEDTLS_DES_C", +#endif /* MBEDTLS_DES_C */ +#if defined(MBEDTLS_DHM_C) + "MBEDTLS_DHM_C", +#endif /* MBEDTLS_DHM_C */ +#if defined(MBEDTLS_ECDH_C) + "MBEDTLS_ECDH_C", +#endif /* MBEDTLS_ECDH_C */ +#if defined(MBEDTLS_ECDSA_C) + "MBEDTLS_ECDSA_C", +#endif /* MBEDTLS_ECDSA_C */ +#if defined(MBEDTLS_ECJPAKE_C) + "MBEDTLS_ECJPAKE_C", +#endif /* MBEDTLS_ECJPAKE_C */ +#if defined(MBEDTLS_ECP_C) + "MBEDTLS_ECP_C", +#endif /* MBEDTLS_ECP_C */ +#if defined(MBEDTLS_ENTROPY_C) + "MBEDTLS_ENTROPY_C", +#endif /* MBEDTLS_ENTROPY_C */ +#if defined(MBEDTLS_ERROR_C) + "MBEDTLS_ERROR_C", +#endif /* MBEDTLS_ERROR_C */ +#if defined(MBEDTLS_GCM_C) + "MBEDTLS_GCM_C", +#endif /* MBEDTLS_GCM_C */ +#if defined(MBEDTLS_HAVEGE_C) + "MBEDTLS_HAVEGE_C", +#endif /* MBEDTLS_HAVEGE_C */ +#if defined(MBEDTLS_HKDF_C) + "MBEDTLS_HKDF_C", +#endif /* MBEDTLS_HKDF_C */ +#if defined(MBEDTLS_HMAC_DRBG_C) + "MBEDTLS_HMAC_DRBG_C", +#endif /* MBEDTLS_HMAC_DRBG_C */ +#if defined(MBEDTLS_NIST_KW_C) + "MBEDTLS_NIST_KW_C", +#endif /* MBEDTLS_NIST_KW_C */ +#if defined(MBEDTLS_MD_C) + "MBEDTLS_MD_C", +#endif /* MBEDTLS_MD_C */ +#if defined(MBEDTLS_MD2_C) + "MBEDTLS_MD2_C", +#endif /* MBEDTLS_MD2_C */ +#if defined(MBEDTLS_MD4_C) + "MBEDTLS_MD4_C", +#endif /* MBEDTLS_MD4_C */ +#if defined(MBEDTLS_MD5_C) + "MBEDTLS_MD5_C", +#endif /* MBEDTLS_MD5_C */ +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) + "MBEDTLS_MEMORY_BUFFER_ALLOC_C", +#endif /* MBEDTLS_MEMORY_BUFFER_ALLOC_C */ +#if defined(MBEDTLS_NET_C) + "MBEDTLS_NET_C", +#endif /* MBEDTLS_NET_C */ +#if defined(MBEDTLS_OID_C) + "MBEDTLS_OID_C", +#endif /* MBEDTLS_OID_C */ +#if defined(MBEDTLS_PADLOCK_C) + "MBEDTLS_PADLOCK_C", +#endif /* MBEDTLS_PADLOCK_C */ +#if defined(MBEDTLS_PEM_PARSE_C) + "MBEDTLS_PEM_PARSE_C", +#endif /* MBEDTLS_PEM_PARSE_C */ +#if defined(MBEDTLS_PEM_WRITE_C) + "MBEDTLS_PEM_WRITE_C", +#endif /* MBEDTLS_PEM_WRITE_C */ +#if defined(MBEDTLS_PK_C) + "MBEDTLS_PK_C", +#endif /* MBEDTLS_PK_C */ +#if defined(MBEDTLS_PK_PARSE_C) + "MBEDTLS_PK_PARSE_C", +#endif /* MBEDTLS_PK_PARSE_C */ +#if defined(MBEDTLS_PK_WRITE_C) + "MBEDTLS_PK_WRITE_C", +#endif /* MBEDTLS_PK_WRITE_C */ +#if defined(MBEDTLS_PKCS5_C) + "MBEDTLS_PKCS5_C", +#endif /* MBEDTLS_PKCS5_C */ +#if defined(MBEDTLS_PKCS11_C) + "MBEDTLS_PKCS11_C", +#endif /* MBEDTLS_PKCS11_C */ +#if defined(MBEDTLS_PKCS12_C) + "MBEDTLS_PKCS12_C", +#endif /* MBEDTLS_PKCS12_C */ +#if defined(MBEDTLS_PLATFORM_C) + "MBEDTLS_PLATFORM_C", +#endif /* MBEDTLS_PLATFORM_C */ +#if defined(MBEDTLS_POLY1305_C) + "MBEDTLS_POLY1305_C", +#endif /* MBEDTLS_POLY1305_C */ +#if defined(MBEDTLS_PSA_CRYPTO_C) + "MBEDTLS_PSA_CRYPTO_C", +#endif /* MBEDTLS_PSA_CRYPTO_C */ +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + "MBEDTLS_PSA_CRYPTO_SE_C", +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ +#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) + "MBEDTLS_PSA_CRYPTO_STORAGE_C", +#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */ +#if defined(MBEDTLS_PSA_ITS_FILE_C) + "MBEDTLS_PSA_ITS_FILE_C", +#endif /* MBEDTLS_PSA_ITS_FILE_C */ +#if defined(MBEDTLS_RIPEMD160_C) + "MBEDTLS_RIPEMD160_C", +#endif /* MBEDTLS_RIPEMD160_C */ +#if defined(MBEDTLS_RSA_C) + "MBEDTLS_RSA_C", +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_SHA1_C) + "MBEDTLS_SHA1_C", +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) + "MBEDTLS_SHA256_C", +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + "MBEDTLS_SHA512_C", +#endif /* MBEDTLS_SHA512_C */ +#if defined(MBEDTLS_SSL_CACHE_C) + "MBEDTLS_SSL_CACHE_C", +#endif /* MBEDTLS_SSL_CACHE_C */ +#if defined(MBEDTLS_SSL_COOKIE_C) + "MBEDTLS_SSL_COOKIE_C", +#endif /* MBEDTLS_SSL_COOKIE_C */ +#if defined(MBEDTLS_SSL_TICKET_C) + "MBEDTLS_SSL_TICKET_C", +#endif /* MBEDTLS_SSL_TICKET_C */ +#if defined(MBEDTLS_SSL_CLI_C) + "MBEDTLS_SSL_CLI_C", +#endif /* MBEDTLS_SSL_CLI_C */ +#if defined(MBEDTLS_SSL_SRV_C) + "MBEDTLS_SSL_SRV_C", +#endif /* MBEDTLS_SSL_SRV_C */ +#if defined(MBEDTLS_SSL_TLS_C) + "MBEDTLS_SSL_TLS_C", +#endif /* MBEDTLS_SSL_TLS_C */ +#if defined(MBEDTLS_THREADING_C) + "MBEDTLS_THREADING_C", +#endif /* MBEDTLS_THREADING_C */ +#if defined(MBEDTLS_TIMING_C) + "MBEDTLS_TIMING_C", +#endif /* MBEDTLS_TIMING_C */ +#if defined(MBEDTLS_VERSION_C) + "MBEDTLS_VERSION_C", +#endif /* MBEDTLS_VERSION_C */ +#if defined(MBEDTLS_X509_USE_C) + "MBEDTLS_X509_USE_C", +#endif /* MBEDTLS_X509_USE_C */ +#if defined(MBEDTLS_X509_CRT_PARSE_C) + "MBEDTLS_X509_CRT_PARSE_C", +#endif /* MBEDTLS_X509_CRT_PARSE_C */ +#if defined(MBEDTLS_X509_CRL_PARSE_C) + "MBEDTLS_X509_CRL_PARSE_C", +#endif /* MBEDTLS_X509_CRL_PARSE_C */ +#if defined(MBEDTLS_X509_CSR_PARSE_C) + "MBEDTLS_X509_CSR_PARSE_C", +#endif /* MBEDTLS_X509_CSR_PARSE_C */ +#if defined(MBEDTLS_X509_CREATE_C) + "MBEDTLS_X509_CREATE_C", +#endif /* MBEDTLS_X509_CREATE_C */ +#if defined(MBEDTLS_X509_CRT_WRITE_C) + "MBEDTLS_X509_CRT_WRITE_C", +#endif /* MBEDTLS_X509_CRT_WRITE_C */ +#if defined(MBEDTLS_X509_CSR_WRITE_C) + "MBEDTLS_X509_CSR_WRITE_C", +#endif /* MBEDTLS_X509_CSR_WRITE_C */ +#if defined(MBEDTLS_XTEA_C) + "MBEDTLS_XTEA_C", +#endif /* MBEDTLS_XTEA_C */ +#endif /* MBEDTLS_VERSION_FEATURES */ + NULL +}; + +int mbedtls_version_check_feature( const char *feature ) +{ + const char * const *idx = features; + + if( *idx == NULL ) + return( -2 ); + + if( feature == NULL ) + return( -1 ); + + while( *idx != NULL ) + { + if( !strcmp( *idx, feature ) ) + return( 0 ); + idx++; + } + return( -1 ); +} + +#endif /* MBEDTLS_VERSION_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/x509.c b/Android/Level4/app/src/main/c/mbedtls/library/x509.c new file mode 100644 index 0000000..2a7be32 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/x509.c @@ -0,0 +1,1067 @@ +/* + * X.509 common functions for parsing and verification + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ +/* + * The ITU-T X.509 standard defines a certificate format for PKI. + * + * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) + * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) + * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) + * + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf + */ + +#include "common.h" + +#if defined(MBEDTLS_X509_USE_C) + +#include "mbedtls/x509.h" +#include "mbedtls/asn1.h" +#include "mbedtls/error.h" +#include "mbedtls/oid.h" + +#include +#include + +#if defined(MBEDTLS_PEM_PARSE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_free free +#define mbedtls_calloc calloc +#define mbedtls_printf printf +#define mbedtls_snprintf snprintf +#endif + +#if defined(MBEDTLS_HAVE_TIME) +#include "mbedtls/platform_time.h" +#endif +#if defined(MBEDTLS_HAVE_TIME_DATE) +#include "mbedtls/platform_util.h" +#include +#endif + +#define CHECK(code) if( ( ret = ( code ) ) != 0 ){ return( ret ); } +#define CHECK_RANGE(min, max, val) \ + do \ + { \ + if( ( val ) < ( min ) || ( val ) > ( max ) ) \ + { \ + return( ret ); \ + } \ + } while( 0 ) + +/* + * CertificateSerialNumber ::= INTEGER + */ +int mbedtls_x509_get_serial( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *serial ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_X509_INVALID_SERIAL + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + if( **p != ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_PRIMITIVE | 2 ) && + **p != MBEDTLS_ASN1_INTEGER ) + return( MBEDTLS_ERR_X509_INVALID_SERIAL + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + serial->tag = *(*p)++; + + if( ( ret = mbedtls_asn1_get_len( p, end, &serial->len ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_SERIAL + ret ); + + serial->p = *p; + *p += serial->len; + + return( 0 ); +} + +/* Get an algorithm identifier without parameters (eg for signatures) + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL } + */ +int mbedtls_x509_get_alg_null( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *alg ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ( ret = mbedtls_asn1_get_alg_null( p, end, alg ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + return( 0 ); +} + +/* + * Parse an algorithm identifier with (optional) parameters + */ +int mbedtls_x509_get_alg( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *alg, mbedtls_x509_buf *params ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ( ret = mbedtls_asn1_get_alg( p, end, alg, params ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + return( 0 ); +} + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) +/* + * HashAlgorithm ::= AlgorithmIdentifier + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL } + * + * For HashAlgorithm, parameters MUST be NULL or absent. + */ +static int x509_get_hash_alg( const mbedtls_x509_buf *alg, mbedtls_md_type_t *md_alg ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p; + const unsigned char *end; + mbedtls_x509_buf md_oid; + size_t len; + + /* Make sure we got a SEQUENCE and setup bounds */ + if( alg->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + p = alg->p; + end = p + alg->len; + + if( p >= end ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + /* Parse md_oid */ + md_oid.tag = *p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &md_oid.len, MBEDTLS_ASN1_OID ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + md_oid.p = p; + p += md_oid.len; + + /* Get md_alg from md_oid */ + if( ( ret = mbedtls_oid_get_md_alg( &md_oid, md_alg ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + /* Make sure params is absent of NULL */ + if( p == end ) + return( 0 ); + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_NULL ) ) != 0 || len != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p != end ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * RSASSA-PSS-params ::= SEQUENCE { + * hashAlgorithm [0] HashAlgorithm DEFAULT sha1Identifier, + * maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1Identifier, + * saltLength [2] INTEGER DEFAULT 20, + * trailerField [3] INTEGER DEFAULT 1 } + * -- Note that the tags in this Sequence are explicit. + * + * RFC 4055 (which defines use of RSASSA-PSS in PKIX) states that the value + * of trailerField MUST be 1, and PKCS#1 v2.2 doesn't even define any other + * option. Enfore this at parsing time. + */ +int mbedtls_x509_get_rsassa_pss_params( const mbedtls_x509_buf *params, + mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md, + int *salt_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p; + const unsigned char *end, *end2; + size_t len; + mbedtls_x509_buf alg_id, alg_params; + + /* First set everything to defaults */ + *md_alg = MBEDTLS_MD_SHA1; + *mgf_md = MBEDTLS_MD_SHA1; + *salt_len = 20; + + /* Make sure params is a SEQUENCE and setup bounds */ + if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + p = (unsigned char *) params->p; + end = p + params->len; + + if( p == end ) + return( 0 ); + + /* + * HashAlgorithm + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) == 0 ) + { + end2 = p + len; + + /* HashAlgorithm ::= AlgorithmIdentifier (without parameters) */ + if( ( ret = mbedtls_x509_get_alg_null( &p, end2, &alg_id ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_oid_get_md_alg( &alg_id, md_alg ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p != end2 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p == end ) + return( 0 ); + + /* + * MaskGenAlgorithm + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) ) == 0 ) + { + end2 = p + len; + + /* MaskGenAlgorithm ::= AlgorithmIdentifier (params = HashAlgorithm) */ + if( ( ret = mbedtls_x509_get_alg( &p, end2, &alg_id, &alg_params ) ) != 0 ) + return( ret ); + + /* Only MFG1 is recognised for now */ + if( MBEDTLS_OID_CMP( MBEDTLS_OID_MGF1, &alg_id ) != 0 ) + return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE + + MBEDTLS_ERR_OID_NOT_FOUND ); + + /* Parse HashAlgorithm */ + if( ( ret = x509_get_hash_alg( &alg_params, mgf_md ) ) != 0 ) + return( ret ); + + if( p != end2 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p == end ) + return( 0 ); + + /* + * salt_len + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 2 ) ) == 0 ) + { + end2 = p + len; + + if( ( ret = mbedtls_asn1_get_int( &p, end2, salt_len ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p != end2 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p == end ) + return( 0 ); + + /* + * trailer_field (if present, must be 1) + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 3 ) ) == 0 ) + { + int trailer_field; + + end2 = p + len; + + if( ( ret = mbedtls_asn1_get_int( &p, end2, &trailer_field ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p != end2 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + if( trailer_field != 1 ) + return( MBEDTLS_ERR_X509_INVALID_ALG ); + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p != end ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} +#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ + +/* + * AttributeTypeAndValue ::= SEQUENCE { + * type AttributeType, + * value AttributeValue } + * + * AttributeType ::= OBJECT IDENTIFIER + * + * AttributeValue ::= ANY DEFINED BY AttributeType + */ +static int x509_get_attr_type_value( unsigned char **p, + const unsigned char *end, + mbedtls_x509_name *cur ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + mbedtls_x509_buf *oid; + mbedtls_x509_buf *val; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_NAME + ret ); + + end = *p + len; + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_X509_INVALID_NAME + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + oid = &cur->oid; + oid->tag = **p; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &oid->len, MBEDTLS_ASN1_OID ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_NAME + ret ); + + oid->p = *p; + *p += oid->len; + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_X509_INVALID_NAME + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + if( **p != MBEDTLS_ASN1_BMP_STRING && **p != MBEDTLS_ASN1_UTF8_STRING && + **p != MBEDTLS_ASN1_T61_STRING && **p != MBEDTLS_ASN1_PRINTABLE_STRING && + **p != MBEDTLS_ASN1_IA5_STRING && **p != MBEDTLS_ASN1_UNIVERSAL_STRING && + **p != MBEDTLS_ASN1_BIT_STRING ) + return( MBEDTLS_ERR_X509_INVALID_NAME + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + val = &cur->val; + val->tag = *(*p)++; + + if( ( ret = mbedtls_asn1_get_len( p, end, &val->len ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_NAME + ret ); + + val->p = *p; + *p += val->len; + + if( *p != end ) + { + return( MBEDTLS_ERR_X509_INVALID_NAME + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + + cur->next = NULL; + + return( 0 ); +} + +/* + * Name ::= CHOICE { -- only one possibility for now -- + * rdnSequence RDNSequence } + * + * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName + * + * RelativeDistinguishedName ::= + * SET OF AttributeTypeAndValue + * + * AttributeTypeAndValue ::= SEQUENCE { + * type AttributeType, + * value AttributeValue } + * + * AttributeType ::= OBJECT IDENTIFIER + * + * AttributeValue ::= ANY DEFINED BY AttributeType + * + * The data structure is optimized for the common case where each RDN has only + * one element, which is represented as a list of AttributeTypeAndValue. + * For the general case we still use a flat list, but we mark elements of the + * same set so that they are "merged" together in the functions that consume + * this list, eg mbedtls_x509_dn_gets(). + */ +int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end, + mbedtls_x509_name *cur ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t set_len; + const unsigned char *end_set; + + /* don't use recursion, we'd risk stack overflow if not optimized */ + while( 1 ) + { + /* + * parse SET + */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &set_len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_NAME + ret ); + + end_set = *p + set_len; + + while( 1 ) + { + if( ( ret = x509_get_attr_type_value( p, end_set, cur ) ) != 0 ) + return( ret ); + + if( *p == end_set ) + break; + + /* Mark this item as being no the only one in a set */ + cur->next_merged = 1; + + cur->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) ); + + if( cur->next == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + cur = cur->next; + } + + /* + * continue until end of SEQUENCE is reached + */ + if( *p == end ) + return( 0 ); + + cur->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) ); + + if( cur->next == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + cur = cur->next; + } +} + +static int x509_parse_int( unsigned char **p, size_t n, int *res ) +{ + *res = 0; + + for( ; n > 0; --n ) + { + if( ( **p < '0') || ( **p > '9' ) ) + return ( MBEDTLS_ERR_X509_INVALID_DATE ); + + *res *= 10; + *res += ( *(*p)++ - '0' ); + } + + return( 0 ); +} + +static int x509_date_is_valid(const mbedtls_x509_time *t ) +{ + int ret = MBEDTLS_ERR_X509_INVALID_DATE; + int month_len; + + CHECK_RANGE( 0, 9999, t->year ); + CHECK_RANGE( 0, 23, t->hour ); + CHECK_RANGE( 0, 59, t->min ); + CHECK_RANGE( 0, 59, t->sec ); + + switch( t->mon ) + { + case 1: case 3: case 5: case 7: case 8: case 10: case 12: + month_len = 31; + break; + case 4: case 6: case 9: case 11: + month_len = 30; + break; + case 2: + if( ( !( t->year % 4 ) && t->year % 100 ) || + !( t->year % 400 ) ) + month_len = 29; + else + month_len = 28; + break; + default: + return( ret ); + } + CHECK_RANGE( 1, month_len, t->day ); + + return( 0 ); +} + +/* + * Parse an ASN1_UTC_TIME (yearlen=2) or ASN1_GENERALIZED_TIME (yearlen=4) + * field. + */ +static int x509_parse_time( unsigned char **p, size_t len, size_t yearlen, + mbedtls_x509_time *tm ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* + * Minimum length is 10 or 12 depending on yearlen + */ + if ( len < yearlen + 8 ) + return ( MBEDTLS_ERR_X509_INVALID_DATE ); + len -= yearlen + 8; + + /* + * Parse year, month, day, hour, minute + */ + CHECK( x509_parse_int( p, yearlen, &tm->year ) ); + if ( 2 == yearlen ) + { + if ( tm->year < 50 ) + tm->year += 100; + + tm->year += 1900; + } + + CHECK( x509_parse_int( p, 2, &tm->mon ) ); + CHECK( x509_parse_int( p, 2, &tm->day ) ); + CHECK( x509_parse_int( p, 2, &tm->hour ) ); + CHECK( x509_parse_int( p, 2, &tm->min ) ); + + /* + * Parse seconds if present + */ + if ( len >= 2 ) + { + CHECK( x509_parse_int( p, 2, &tm->sec ) ); + len -= 2; + } + else + return ( MBEDTLS_ERR_X509_INVALID_DATE ); + + /* + * Parse trailing 'Z' if present + */ + if ( 1 == len && 'Z' == **p ) + { + (*p)++; + len--; + } + + /* + * We should have parsed all characters at this point + */ + if ( 0 != len ) + return ( MBEDTLS_ERR_X509_INVALID_DATE ); + + CHECK( x509_date_is_valid( tm ) ); + + return ( 0 ); +} + +/* + * Time ::= CHOICE { + * utcTime UTCTime, + * generalTime GeneralizedTime } + */ +int mbedtls_x509_get_time( unsigned char **p, const unsigned char *end, + mbedtls_x509_time *tm ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len, year_len; + unsigned char tag; + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_X509_INVALID_DATE + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + tag = **p; + + if( tag == MBEDTLS_ASN1_UTC_TIME ) + year_len = 2; + else if( tag == MBEDTLS_ASN1_GENERALIZED_TIME ) + year_len = 4; + else + return( MBEDTLS_ERR_X509_INVALID_DATE + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + (*p)++; + ret = mbedtls_asn1_get_len( p, end, &len ); + + if( ret != 0 ) + return( MBEDTLS_ERR_X509_INVALID_DATE + ret ); + + return x509_parse_time( p, len, year_len, tm ); +} + +int mbedtls_x509_get_sig( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + int tag_type; + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_X509_INVALID_SIGNATURE + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + tag_type = **p; + + if( ( ret = mbedtls_asn1_get_bitstring_null( p, end, &len ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_SIGNATURE + ret ); + + sig->tag = tag_type; + sig->len = len; + sig->p = *p; + + *p += len; + + return( 0 ); +} + +/* + * Get signature algorithm from alg OID and optional parameters + */ +int mbedtls_x509_get_sig_alg( const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params, + mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg, + void **sig_opts ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( *sig_opts != NULL ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_oid_get_sig_alg( sig_oid, md_alg, pk_alg ) ) != 0 ) + return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + ret ); + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + if( *pk_alg == MBEDTLS_PK_RSASSA_PSS ) + { + mbedtls_pk_rsassa_pss_options *pss_opts; + + pss_opts = mbedtls_calloc( 1, sizeof( mbedtls_pk_rsassa_pss_options ) ); + if( pss_opts == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + ret = mbedtls_x509_get_rsassa_pss_params( sig_params, + md_alg, + &pss_opts->mgf1_hash_id, + &pss_opts->expected_salt_len ); + if( ret != 0 ) + { + mbedtls_free( pss_opts ); + return( ret ); + } + + *sig_opts = (void *) pss_opts; + } + else +#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ + { + /* Make sure parameters are absent or NULL */ + if( ( sig_params->tag != MBEDTLS_ASN1_NULL && sig_params->tag != 0 ) || + sig_params->len != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG ); + } + + return( 0 ); +} + +/* + * X.509 Extensions (No parsing of extensions, pointer should + * be either manually updated or extensions should be parsed!) + */ +int mbedtls_x509_get_ext( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *ext, int tag ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + /* Extension structure use EXPLICIT tagging. That is, the actual + * `Extensions` structure is wrapped by a tag-length pair using + * the respective context-specific tag. */ + ret = mbedtls_asn1_get_tag( p, end, &ext->len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag ); + if( ret != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + ext->tag = MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag; + ext->p = *p; + end = *p + ext->len; + + /* + * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension + */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( end != *p + len ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * Store the name in printable form into buf; no more + * than size characters will be written + */ +int mbedtls_x509_dn_gets( char *buf, size_t size, const mbedtls_x509_name *dn ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i, n; + unsigned char c, merge = 0; + const mbedtls_x509_name *name; + const char *short_name = NULL; + char s[MBEDTLS_X509_MAX_DN_NAME_SIZE], *p; + + memset( s, 0, sizeof( s ) ); + + name = dn; + p = buf; + n = size; + + while( name != NULL ) + { + if( !name->oid.p ) + { + name = name->next; + continue; + } + + if( name != dn ) + { + ret = mbedtls_snprintf( p, n, merge ? " + " : ", " ); + MBEDTLS_X509_SAFE_SNPRINTF; + } + + ret = mbedtls_oid_get_attr_short_name( &name->oid, &short_name ); + + if( ret == 0 ) + ret = mbedtls_snprintf( p, n, "%s=", short_name ); + else + ret = mbedtls_snprintf( p, n, "\?\?=" ); + MBEDTLS_X509_SAFE_SNPRINTF; + + for( i = 0; i < name->val.len; i++ ) + { + if( i >= sizeof( s ) - 1 ) + break; + + c = name->val.p[i]; + if( c < 32 || c >= 127 ) + s[i] = '?'; + else s[i] = c; + } + s[i] = '\0'; + ret = mbedtls_snprintf( p, n, "%s", s ); + MBEDTLS_X509_SAFE_SNPRINTF; + + merge = name->next_merged; + name = name->next; + } + + return( (int) ( size - n ) ); +} + +/* + * Store the serial in printable form into buf; no more + * than size characters will be written + */ +int mbedtls_x509_serial_gets( char *buf, size_t size, const mbedtls_x509_buf *serial ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i, n, nr; + char *p; + + p = buf; + n = size; + + nr = ( serial->len <= 32 ) + ? serial->len : 28; + + for( i = 0; i < nr; i++ ) + { + if( i == 0 && nr > 1 && serial->p[i] == 0x0 ) + continue; + + ret = mbedtls_snprintf( p, n, "%02X%s", + serial->p[i], ( i < nr - 1 ) ? ":" : "" ); + MBEDTLS_X509_SAFE_SNPRINTF; + } + + if( nr != serial->len ) + { + ret = mbedtls_snprintf( p, n, "...." ); + MBEDTLS_X509_SAFE_SNPRINTF; + } + + return( (int) ( size - n ) ); +} + +/* + * Helper for writing signature algorithms + */ +int mbedtls_x509_sig_alg_gets( char *buf, size_t size, const mbedtls_x509_buf *sig_oid, + mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, + const void *sig_opts ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + char *p = buf; + size_t n = size; + const char *desc = NULL; + + ret = mbedtls_oid_get_sig_alg_desc( sig_oid, &desc ); + if( ret != 0 ) + ret = mbedtls_snprintf( p, n, "???" ); + else + ret = mbedtls_snprintf( p, n, "%s", desc ); + MBEDTLS_X509_SAFE_SNPRINTF; + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + if( pk_alg == MBEDTLS_PK_RSASSA_PSS ) + { + const mbedtls_pk_rsassa_pss_options *pss_opts; + const mbedtls_md_info_t *md_info, *mgf_md_info; + + pss_opts = (const mbedtls_pk_rsassa_pss_options *) sig_opts; + + md_info = mbedtls_md_info_from_type( md_alg ); + mgf_md_info = mbedtls_md_info_from_type( pss_opts->mgf1_hash_id ); + + ret = mbedtls_snprintf( p, n, " (%s, MGF1-%s, 0x%02X)", + md_info ? mbedtls_md_get_name( md_info ) : "???", + mgf_md_info ? mbedtls_md_get_name( mgf_md_info ) : "???", + (unsigned int) pss_opts->expected_salt_len ); + MBEDTLS_X509_SAFE_SNPRINTF; + } +#else + ((void) pk_alg); + ((void) md_alg); + ((void) sig_opts); +#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ + + return( (int)( size - n ) ); +} + +/* + * Helper for writing "RSA key size", "EC key size", etc + */ +int mbedtls_x509_key_size_helper( char *buf, size_t buf_size, const char *name ) +{ + char *p = buf; + size_t n = buf_size; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + ret = mbedtls_snprintf( p, n, "%s key size", name ); + MBEDTLS_X509_SAFE_SNPRINTF; + + return( 0 ); +} + +#if defined(MBEDTLS_HAVE_TIME_DATE) +/* + * Set the time structure to the current time. + * Return 0 on success, non-zero on failure. + */ +static int x509_get_current_time( mbedtls_x509_time *now ) +{ + struct tm *lt, tm_buf; + mbedtls_time_t tt; + int ret = 0; + + tt = mbedtls_time( NULL ); + lt = mbedtls_platform_gmtime_r( &tt, &tm_buf ); + + if( lt == NULL ) + ret = -1; + else + { + now->year = lt->tm_year + 1900; + now->mon = lt->tm_mon + 1; + now->day = lt->tm_mday; + now->hour = lt->tm_hour; + now->min = lt->tm_min; + now->sec = lt->tm_sec; + } + + return( ret ); +} + +/* + * Return 0 if before <= after, 1 otherwise + */ +static int x509_check_time( const mbedtls_x509_time *before, const mbedtls_x509_time *after ) +{ + if( before->year > after->year ) + return( 1 ); + + if( before->year == after->year && + before->mon > after->mon ) + return( 1 ); + + if( before->year == after->year && + before->mon == after->mon && + before->day > after->day ) + return( 1 ); + + if( before->year == after->year && + before->mon == after->mon && + before->day == after->day && + before->hour > after->hour ) + return( 1 ); + + if( before->year == after->year && + before->mon == after->mon && + before->day == after->day && + before->hour == after->hour && + before->min > after->min ) + return( 1 ); + + if( before->year == after->year && + before->mon == after->mon && + before->day == after->day && + before->hour == after->hour && + before->min == after->min && + before->sec > after->sec ) + return( 1 ); + + return( 0 ); +} + +int mbedtls_x509_time_is_past( const mbedtls_x509_time *to ) +{ + mbedtls_x509_time now; + + if( x509_get_current_time( &now ) != 0 ) + return( 1 ); + + return( x509_check_time( &now, to ) ); +} + +int mbedtls_x509_time_is_future( const mbedtls_x509_time *from ) +{ + mbedtls_x509_time now; + + if( x509_get_current_time( &now ) != 0 ) + return( 1 ); + + return( x509_check_time( from, &now ) ); +} + +#else /* MBEDTLS_HAVE_TIME_DATE */ + +int mbedtls_x509_time_is_past( const mbedtls_x509_time *to ) +{ + ((void) to); + return( 0 ); +} + +int mbedtls_x509_time_is_future( const mbedtls_x509_time *from ) +{ + ((void) from); + return( 0 ); +} +#endif /* MBEDTLS_HAVE_TIME_DATE */ + +#if defined(MBEDTLS_SELF_TEST) + +#include "mbedtls/x509_crt.h" +#include "mbedtls/certs.h" + +/* + * Checkup routine + */ +int mbedtls_x509_self_test( int verbose ) +{ + int ret = 0; +#if defined(MBEDTLS_CERTS_C) && defined(MBEDTLS_SHA256_C) + uint32_t flags; + mbedtls_x509_crt cacert; + mbedtls_x509_crt clicert; + + if( verbose != 0 ) + mbedtls_printf( " X.509 certificate load: " ); + + mbedtls_x509_crt_init( &cacert ); + mbedtls_x509_crt_init( &clicert ); + + ret = mbedtls_x509_crt_parse( &clicert, (const unsigned char *) mbedtls_test_cli_crt, + mbedtls_test_cli_crt_len ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + goto cleanup; + } + + ret = mbedtls_x509_crt_parse( &cacert, (const unsigned char *) mbedtls_test_ca_crt, + mbedtls_test_ca_crt_len ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n X.509 signature verify: "); + + ret = mbedtls_x509_crt_verify( &clicert, &cacert, NULL, NULL, &flags, NULL, NULL ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n\n"); + +cleanup: + mbedtls_x509_crt_free( &cacert ); + mbedtls_x509_crt_free( &clicert ); +#else + ((void) verbose); +#endif /* MBEDTLS_CERTS_C && MBEDTLS_SHA256_C */ + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_X509_USE_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/x509_create.c b/Android/Level4/app/src/main/c/mbedtls/library/x509_create.c new file mode 100644 index 0000000..056bbaa --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/x509_create.c @@ -0,0 +1,374 @@ +/* + * X.509 base functions for creating certificates / CSRs + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 "common.h" + +#if defined(MBEDTLS_X509_CREATE_C) + +#include "mbedtls/x509.h" +#include "mbedtls/asn1write.h" +#include "mbedtls/error.h" +#include "mbedtls/oid.h" + +#include + +/* Structure linking OIDs for X.509 DN AttributeTypes to their + * string representations and default string encodings used by Mbed TLS. */ +typedef struct { + const char *name; /* String representation of AttributeType, e.g. + * "CN" or "emailAddress". */ + size_t name_len; /* Length of 'name', without trailing 0 byte. */ + const char *oid; /* String representation of OID of AttributeType, + * as per RFC 5280, Appendix A.1. */ + int default_tag; /* The default character encoding used for the + * given attribute type, e.g. + * MBEDTLS_ASN1_UTF8_STRING for UTF-8. */ +} x509_attr_descriptor_t; + +#define ADD_STRLEN( s ) s, sizeof( s ) - 1 + +/* X.509 DN attributes from RFC 5280, Appendix A.1. */ +static const x509_attr_descriptor_t x509_attrs[] = +{ + { ADD_STRLEN( "CN" ), + MBEDTLS_OID_AT_CN, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "commonName" ), + MBEDTLS_OID_AT_CN, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "C" ), + MBEDTLS_OID_AT_COUNTRY, MBEDTLS_ASN1_PRINTABLE_STRING }, + { ADD_STRLEN( "countryName" ), + MBEDTLS_OID_AT_COUNTRY, MBEDTLS_ASN1_PRINTABLE_STRING }, + { ADD_STRLEN( "O" ), + MBEDTLS_OID_AT_ORGANIZATION, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "organizationName" ), + MBEDTLS_OID_AT_ORGANIZATION, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "L" ), + MBEDTLS_OID_AT_LOCALITY, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "locality" ), + MBEDTLS_OID_AT_LOCALITY, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "R" ), + MBEDTLS_OID_PKCS9_EMAIL, MBEDTLS_ASN1_IA5_STRING }, + { ADD_STRLEN( "OU" ), + MBEDTLS_OID_AT_ORG_UNIT, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "organizationalUnitName" ), + MBEDTLS_OID_AT_ORG_UNIT, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "ST" ), + MBEDTLS_OID_AT_STATE, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "stateOrProvinceName" ), + MBEDTLS_OID_AT_STATE, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "emailAddress" ), + MBEDTLS_OID_PKCS9_EMAIL, MBEDTLS_ASN1_IA5_STRING }, + { ADD_STRLEN( "serialNumber" ), + MBEDTLS_OID_AT_SERIAL_NUMBER, MBEDTLS_ASN1_PRINTABLE_STRING }, + { ADD_STRLEN( "postalAddress" ), + MBEDTLS_OID_AT_POSTAL_ADDRESS, MBEDTLS_ASN1_PRINTABLE_STRING }, + { ADD_STRLEN( "postalCode" ), + MBEDTLS_OID_AT_POSTAL_CODE, MBEDTLS_ASN1_PRINTABLE_STRING }, + { ADD_STRLEN( "dnQualifier" ), + MBEDTLS_OID_AT_DN_QUALIFIER, MBEDTLS_ASN1_PRINTABLE_STRING }, + { ADD_STRLEN( "title" ), + MBEDTLS_OID_AT_TITLE, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "surName" ), + MBEDTLS_OID_AT_SUR_NAME, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "SN" ), + MBEDTLS_OID_AT_SUR_NAME, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "givenName" ), + MBEDTLS_OID_AT_GIVEN_NAME, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "GN" ), + MBEDTLS_OID_AT_GIVEN_NAME, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "initials" ), + MBEDTLS_OID_AT_INITIALS, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "pseudonym" ), + MBEDTLS_OID_AT_PSEUDONYM, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "generationQualifier" ), + MBEDTLS_OID_AT_GENERATION_QUALIFIER, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "domainComponent" ), + MBEDTLS_OID_DOMAIN_COMPONENT, MBEDTLS_ASN1_IA5_STRING }, + { ADD_STRLEN( "DC" ), + MBEDTLS_OID_DOMAIN_COMPONENT, MBEDTLS_ASN1_IA5_STRING }, + { NULL, 0, NULL, MBEDTLS_ASN1_NULL } +}; + +static const x509_attr_descriptor_t *x509_attr_descr_from_name( const char *name, size_t name_len ) +{ + const x509_attr_descriptor_t *cur; + + for( cur = x509_attrs; cur->name != NULL; cur++ ) + if( cur->name_len == name_len && + strncmp( cur->name, name, name_len ) == 0 ) + break; + + if ( cur->name == NULL ) + return( NULL ); + + return( cur ); +} + +int mbedtls_x509_string_to_names( mbedtls_asn1_named_data **head, const char *name ) +{ + int ret = 0; + const char *s = name, *c = s; + const char *end = s + strlen( s ); + const char *oid = NULL; + const x509_attr_descriptor_t* attr_descr = NULL; + int in_tag = 1; + char data[MBEDTLS_X509_MAX_DN_NAME_SIZE]; + char *d = data; + + /* Clear existing chain if present */ + mbedtls_asn1_free_named_data_list( head ); + + while( c <= end ) + { + if( in_tag && *c == '=' ) + { + if( ( attr_descr = x509_attr_descr_from_name( s, c - s ) ) == NULL ) + { + ret = MBEDTLS_ERR_X509_UNKNOWN_OID; + goto exit; + } + + oid = attr_descr->oid; + s = c + 1; + in_tag = 0; + d = data; + } + + if( !in_tag && *c == '\\' && c != end ) + { + c++; + + /* Check for valid escaped characters */ + if( c == end || *c != ',' ) + { + ret = MBEDTLS_ERR_X509_INVALID_NAME; + goto exit; + } + } + else if( !in_tag && ( *c == ',' || c == end ) ) + { + mbedtls_asn1_named_data* cur = + mbedtls_asn1_store_named_data( head, oid, strlen( oid ), + (unsigned char *) data, + d - data ); + + if(cur == NULL ) + { + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + } + + // set tagType + cur->val.tag = attr_descr->default_tag; + + while( c < end && *(c + 1) == ' ' ) + c++; + + s = c + 1; + in_tag = 1; + } + + if( !in_tag && s != c + 1 ) + { + *(d++) = *c; + + if( d - data == MBEDTLS_X509_MAX_DN_NAME_SIZE ) + { + ret = MBEDTLS_ERR_X509_INVALID_NAME; + goto exit; + } + } + + c++; + } + +exit: + + return( ret ); +} + +/* The first byte of the value in the mbedtls_asn1_named_data structure is reserved + * to store the critical boolean for us + */ +int mbedtls_x509_set_extension( mbedtls_asn1_named_data **head, const char *oid, size_t oid_len, + int critical, const unsigned char *val, size_t val_len ) +{ + mbedtls_asn1_named_data *cur; + + if( ( cur = mbedtls_asn1_store_named_data( head, oid, oid_len, + NULL, val_len + 1 ) ) == NULL ) + { + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + } + + cur->val.p[0] = critical; + memcpy( cur->val.p + 1, val, val_len ); + + return( 0 ); +} + +/* + * RelativeDistinguishedName ::= + * SET OF AttributeTypeAndValue + * + * AttributeTypeAndValue ::= SEQUENCE { + * type AttributeType, + * value AttributeValue } + * + * AttributeType ::= OBJECT IDENTIFIER + * + * AttributeValue ::= ANY DEFINED BY AttributeType + */ +static int x509_write_name( unsigned char **p, unsigned char *start, mbedtls_asn1_named_data* cur_name) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + const char *oid = (const char*)cur_name->oid.p; + size_t oid_len = cur_name->oid.len; + const unsigned char *name = cur_name->val.p; + size_t name_len = cur_name->val.len; + + // Write correct string tag and value + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tagged_string( p, start, + cur_name->val.tag, + (const char *) name, + name_len ) ); + // Write OID + // + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, + oid_len ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SET ) ); + + return( (int) len ); +} + +int mbedtls_x509_write_names( unsigned char **p, unsigned char *start, + mbedtls_asn1_named_data *first ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + mbedtls_asn1_named_data *cur = first; + + while( cur != NULL ) + { + MBEDTLS_ASN1_CHK_ADD( len, x509_write_name( p, start, cur ) ); + cur = cur->next; + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + return( (int) len ); +} + +int mbedtls_x509_write_sig( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len, + unsigned char *sig, size_t size ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + if( *p < start || (size_t)( *p - start ) < size ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + len = size; + (*p) -= len; + memcpy( *p, sig, len ); + + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = 0; + len += 1; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BIT_STRING ) ); + + // Write OID + // + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( p, start, oid, + oid_len, 0 ) ); + + return( (int) len ); +} + +static int x509_write_extension( unsigned char **p, unsigned char *start, + mbedtls_asn1_named_data *ext ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, ext->val.p + 1, + ext->val.len - 1 ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, ext->val.len - 1 ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OCTET_STRING ) ); + + if( ext->val.p[0] != 0 ) + { + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_bool( p, start, 1 ) ); + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, ext->oid.p, + ext->oid.len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, ext->oid.len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OID ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + return( (int) len ); +} + +/* + * Extension ::= SEQUENCE { + * extnID OBJECT IDENTIFIER, + * critical BOOLEAN DEFAULT FALSE, + * extnValue OCTET STRING + * -- contains the DER encoding of an ASN.1 value + * -- corresponding to the extension type identified + * -- by extnID + * } + */ +int mbedtls_x509_write_extensions( unsigned char **p, unsigned char *start, + mbedtls_asn1_named_data *first ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + mbedtls_asn1_named_data *cur_ext = first; + + while( cur_ext != NULL ) + { + MBEDTLS_ASN1_CHK_ADD( len, x509_write_extension( p, start, cur_ext ) ); + cur_ext = cur_ext->next; + } + + return( (int) len ); +} + +#endif /* MBEDTLS_X509_CREATE_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/x509_crl.c b/Android/Level4/app/src/main/c/mbedtls/library/x509_crl.c new file mode 100644 index 0000000..edeb39b --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/x509_crl.c @@ -0,0 +1,768 @@ +/* + * X.509 Certidicate Revocation List (CRL) parsing + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ +/* + * The ITU-T X.509 standard defines a certificate format for PKI. + * + * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) + * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) + * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) + * + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf + */ + +#include "common.h" + +#if defined(MBEDTLS_X509_CRL_PARSE_C) + +#include "mbedtls/x509_crl.h" +#include "mbedtls/error.h" +#include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_PEM_PARSE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_free free +#define mbedtls_calloc calloc +#define mbedtls_snprintf snprintf +#endif + +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) +#include +#else +#include +#endif + +#if defined(MBEDTLS_FS_IO) || defined(EFIX64) || defined(EFI32) +#include +#endif + +/* + * Version ::= INTEGER { v1(0), v2(1) } + */ +static int x509_crl_get_version( unsigned char **p, + const unsigned char *end, + int *ver ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + { + *ver = 0; + return( 0 ); + } + + return( MBEDTLS_ERR_X509_INVALID_VERSION + ret ); + } + + return( 0 ); +} + +/* + * X.509 CRL v2 extensions + * + * We currently don't parse any extension's content, but we do check that the + * list of extensions is well-formed and abort on critical extensions (that + * are unsupported as we don't support any extension so far) + */ +static int x509_get_crl_ext( unsigned char **p, + const unsigned char *end, + mbedtls_x509_buf *ext ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( *p == end ) + return( 0 ); + + /* + * crlExtensions [0] EXPLICIT Extensions OPTIONAL + * -- if present, version MUST be v2 + */ + if( ( ret = mbedtls_x509_get_ext( p, end, ext, 0 ) ) != 0 ) + return( ret ); + + end = ext->p + ext->len; + + while( *p < end ) + { + /* + * Extension ::= SEQUENCE { + * extnID OBJECT IDENTIFIER, + * critical BOOLEAN DEFAULT FALSE, + * extnValue OCTET STRING } + */ + int is_critical = 0; + const unsigned char *end_ext_data; + size_t len; + + /* Get enclosing sequence tag */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + end_ext_data = *p + len; + + /* Get OID (currently ignored) */ + if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &len, + MBEDTLS_ASN1_OID ) ) != 0 ) + { + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + } + *p += len; + + /* Get optional critical */ + if( ( ret = mbedtls_asn1_get_bool( p, end_ext_data, + &is_critical ) ) != 0 && + ( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ) + { + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + } + + /* Data should be octet string type */ + if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &len, + MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + /* Ignore data so far and just check its length */ + *p += len; + if( *p != end_ext_data ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + /* Abort on (unsupported) critical extensions */ + if( is_critical ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + } + + if( *p != end ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * X.509 CRL v2 entry extensions (no extensions parsed yet.) + */ +static int x509_get_crl_entry_ext( unsigned char **p, + const unsigned char *end, + mbedtls_x509_buf *ext ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + /* OPTIONAL */ + if( end <= *p ) + return( 0 ); + + ext->tag = **p; + ext->p = *p; + + /* + * Get CRL-entry extension sequence header + * crlEntryExtensions Extensions OPTIONAL -- if present, MUST be v2 + */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &ext->len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + { + ext->p = NULL; + return( 0 ); + } + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + } + + end = *p + ext->len; + + if( end != *p + ext->len ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + while( *p < end ) + { + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + *p += len; + } + + if( *p != end ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * X.509 CRL Entries + */ +static int x509_get_entries( unsigned char **p, + const unsigned char *end, + mbedtls_x509_crl_entry *entry ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t entry_len; + mbedtls_x509_crl_entry *cur_entry = entry; + + if( *p == end ) + return( 0 ); + + if( ( ret = mbedtls_asn1_get_tag( p, end, &entry_len, + MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( 0 ); + + return( ret ); + } + + end = *p + entry_len; + + while( *p < end ) + { + size_t len2; + const unsigned char *end2; + + cur_entry->raw.tag = **p; + if( ( ret = mbedtls_asn1_get_tag( p, end, &len2, + MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED ) ) != 0 ) + { + return( ret ); + } + + cur_entry->raw.p = *p; + cur_entry->raw.len = len2; + end2 = *p + len2; + + if( ( ret = mbedtls_x509_get_serial( p, end2, &cur_entry->serial ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_x509_get_time( p, end2, + &cur_entry->revocation_date ) ) != 0 ) + return( ret ); + + if( ( ret = x509_get_crl_entry_ext( p, end2, + &cur_entry->entry_ext ) ) != 0 ) + return( ret ); + + if( *p < end ) + { + cur_entry->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_crl_entry ) ); + + if( cur_entry->next == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + cur_entry = cur_entry->next; + } + } + + return( 0 ); +} + +/* + * Parse one CRLs in DER format and append it to the chained list + */ +int mbedtls_x509_crl_parse_der( mbedtls_x509_crl *chain, + const unsigned char *buf, size_t buflen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + unsigned char *p = NULL, *end = NULL; + mbedtls_x509_buf sig_params1, sig_params2, sig_oid2; + mbedtls_x509_crl *crl = chain; + + /* + * Check for valid input + */ + if( crl == NULL || buf == NULL ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + memset( &sig_params1, 0, sizeof( mbedtls_x509_buf ) ); + memset( &sig_params2, 0, sizeof( mbedtls_x509_buf ) ); + memset( &sig_oid2, 0, sizeof( mbedtls_x509_buf ) ); + + /* + * Add new CRL on the end of the chain if needed. + */ + while( crl->version != 0 && crl->next != NULL ) + crl = crl->next; + + if( crl->version != 0 && crl->next == NULL ) + { + crl->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_crl ) ); + + if( crl->next == NULL ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + } + + mbedtls_x509_crl_init( crl->next ); + crl = crl->next; + } + + /* + * Copy raw DER-encoded CRL + */ + if( buflen == 0 ) + return( MBEDTLS_ERR_X509_INVALID_FORMAT ); + + p = mbedtls_calloc( 1, buflen ); + if( p == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + memcpy( p, buf, buflen ); + + crl->raw.p = p; + crl->raw.len = buflen; + + end = p + buflen; + + /* + * CertificateList ::= SEQUENCE { + * tbsCertList TBSCertList, + * signatureAlgorithm AlgorithmIdentifier, + * signatureValue BIT STRING } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT ); + } + + if( len != (size_t) ( end - p ) ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + + /* + * TBSCertList ::= SEQUENCE { + */ + crl->tbs.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + end = p + len; + crl->tbs.len = end - crl->tbs.p; + + /* + * Version ::= INTEGER OPTIONAL { v1(0), v2(1) } + * -- if present, MUST be v2 + * + * signature AlgorithmIdentifier + */ + if( ( ret = x509_crl_get_version( &p, end, &crl->version ) ) != 0 || + ( ret = mbedtls_x509_get_alg( &p, end, &crl->sig_oid, &sig_params1 ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + + if( crl->version < 0 || crl->version > 1 ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_UNKNOWN_VERSION ); + } + + crl->version++; + + if( ( ret = mbedtls_x509_get_sig_alg( &crl->sig_oid, &sig_params1, + &crl->sig_md, &crl->sig_pk, + &crl->sig_opts ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG ); + } + + /* + * issuer Name + */ + crl->issuer_raw.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + if( ( ret = mbedtls_x509_get_name( &p, p + len, &crl->issuer ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + + crl->issuer_raw.len = p - crl->issuer_raw.p; + + /* + * thisUpdate Time + * nextUpdate Time OPTIONAL + */ + if( ( ret = mbedtls_x509_get_time( &p, end, &crl->this_update ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + + if( ( ret = mbedtls_x509_get_time( &p, end, &crl->next_update ) ) != 0 ) + { + if( ret != ( MBEDTLS_ERR_X509_INVALID_DATE + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) && + ret != ( MBEDTLS_ERR_X509_INVALID_DATE + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ) ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + } + + /* + * revokedCertificates SEQUENCE OF SEQUENCE { + * userCertificate CertificateSerialNumber, + * revocationDate Time, + * crlEntryExtensions Extensions OPTIONAL + * -- if present, MUST be v2 + * } OPTIONAL + */ + if( ( ret = x509_get_entries( &p, end, &crl->entry ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + + /* + * crlExtensions EXPLICIT Extensions OPTIONAL + * -- if present, MUST be v2 + */ + if( crl->version == 2 ) + { + ret = x509_get_crl_ext( &p, end, &crl->crl_ext ); + + if( ret != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + } + + if( p != end ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + + end = crl->raw.p + crl->raw.len; + + /* + * signatureAlgorithm AlgorithmIdentifier, + * signatureValue BIT STRING + */ + if( ( ret = mbedtls_x509_get_alg( &p, end, &sig_oid2, &sig_params2 ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + + if( crl->sig_oid.len != sig_oid2.len || + memcmp( crl->sig_oid.p, sig_oid2.p, crl->sig_oid.len ) != 0 || + sig_params1.len != sig_params2.len || + ( sig_params1.len != 0 && + memcmp( sig_params1.p, sig_params2.p, sig_params1.len ) != 0 ) ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_SIG_MISMATCH ); + } + + if( ( ret = mbedtls_x509_get_sig( &p, end, &crl->sig ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + + if( p != end ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + + return( 0 ); +} + +/* + * Parse one or more CRLs and add them to the chained list + */ +int mbedtls_x509_crl_parse( mbedtls_x509_crl *chain, const unsigned char *buf, size_t buflen ) +{ +#if defined(MBEDTLS_PEM_PARSE_C) + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t use_len = 0; + mbedtls_pem_context pem; + int is_pem = 0; + + if( chain == NULL || buf == NULL ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + do + { + mbedtls_pem_init( &pem ); + + // Avoid calling mbedtls_pem_read_buffer() on non-null-terminated + // string + if( buflen == 0 || buf[buflen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN X509 CRL-----", + "-----END X509 CRL-----", + buf, NULL, 0, &use_len ); + + if( ret == 0 ) + { + /* + * Was PEM encoded + */ + is_pem = 1; + + buflen -= use_len; + buf += use_len; + + if( ( ret = mbedtls_x509_crl_parse_der( chain, + pem.buf, pem.buflen ) ) != 0 ) + { + mbedtls_pem_free( &pem ); + return( ret ); + } + } + else if( is_pem ) + { + mbedtls_pem_free( &pem ); + return( ret ); + } + + mbedtls_pem_free( &pem ); + } + /* In the PEM case, buflen is 1 at the end, for the terminated NULL byte. + * And a valid CRL cannot be less than 1 byte anyway. */ + while( is_pem && buflen > 1 ); + + if( is_pem ) + return( 0 ); + else +#endif /* MBEDTLS_PEM_PARSE_C */ + return( mbedtls_x509_crl_parse_der( chain, buf, buflen ) ); +} + +#if defined(MBEDTLS_FS_IO) +/* + * Load one or more CRLs and add them to the chained list + */ +int mbedtls_x509_crl_parse_file( mbedtls_x509_crl *chain, const char *path ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n; + unsigned char *buf; + + if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = mbedtls_x509_crl_parse( chain, buf, n ); + + mbedtls_platform_zeroize( buf, n ); + mbedtls_free( buf ); + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + +/* + * Return an informational string about the certificate. + */ +#define BEFORE_COLON 14 +#define BC "14" +/* + * Return an informational string about the CRL. + */ +int mbedtls_x509_crl_info( char *buf, size_t size, const char *prefix, + const mbedtls_x509_crl *crl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n; + char *p; + const mbedtls_x509_crl_entry *entry; + + p = buf; + n = size; + + ret = mbedtls_snprintf( p, n, "%sCRL version : %d", + prefix, crl->version ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%sissuer name : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + ret = mbedtls_x509_dn_gets( p, n, &crl->issuer ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%sthis update : " \ + "%04d-%02d-%02d %02d:%02d:%02d", prefix, + crl->this_update.year, crl->this_update.mon, + crl->this_update.day, crl->this_update.hour, + crl->this_update.min, crl->this_update.sec ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%snext update : " \ + "%04d-%02d-%02d %02d:%02d:%02d", prefix, + crl->next_update.year, crl->next_update.mon, + crl->next_update.day, crl->next_update.hour, + crl->next_update.min, crl->next_update.sec ); + MBEDTLS_X509_SAFE_SNPRINTF; + + entry = &crl->entry; + + ret = mbedtls_snprintf( p, n, "\n%sRevoked certificates:", + prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + while( entry != NULL && entry->raw.len != 0 ) + { + ret = mbedtls_snprintf( p, n, "\n%sserial number: ", + prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_x509_serial_gets( p, n, &entry->serial ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, " revocation date: " \ + "%04d-%02d-%02d %02d:%02d:%02d", + entry->revocation_date.year, entry->revocation_date.mon, + entry->revocation_date.day, entry->revocation_date.hour, + entry->revocation_date.min, entry->revocation_date.sec ); + MBEDTLS_X509_SAFE_SNPRINTF; + + entry = entry->next; + } + + ret = mbedtls_snprintf( p, n, "\n%ssigned using : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_x509_sig_alg_gets( p, n, &crl->sig_oid, crl->sig_pk, crl->sig_md, + crl->sig_opts ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n" ); + MBEDTLS_X509_SAFE_SNPRINTF; + + return( (int) ( size - n ) ); +} + +/* + * Initialize a CRL chain + */ +void mbedtls_x509_crl_init( mbedtls_x509_crl *crl ) +{ + memset( crl, 0, sizeof(mbedtls_x509_crl) ); +} + +/* + * Unallocate all CRL data + */ +void mbedtls_x509_crl_free( mbedtls_x509_crl *crl ) +{ + mbedtls_x509_crl *crl_cur = crl; + mbedtls_x509_crl *crl_prv; + mbedtls_x509_name *name_cur; + mbedtls_x509_name *name_prv; + mbedtls_x509_crl_entry *entry_cur; + mbedtls_x509_crl_entry *entry_prv; + + if( crl == NULL ) + return; + + do + { +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + mbedtls_free( crl_cur->sig_opts ); +#endif + + name_cur = crl_cur->issuer.next; + while( name_cur != NULL ) + { + name_prv = name_cur; + name_cur = name_cur->next; + mbedtls_platform_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); + mbedtls_free( name_prv ); + } + + entry_cur = crl_cur->entry.next; + while( entry_cur != NULL ) + { + entry_prv = entry_cur; + entry_cur = entry_cur->next; + mbedtls_platform_zeroize( entry_prv, + sizeof( mbedtls_x509_crl_entry ) ); + mbedtls_free( entry_prv ); + } + + if( crl_cur->raw.p != NULL ) + { + mbedtls_platform_zeroize( crl_cur->raw.p, crl_cur->raw.len ); + mbedtls_free( crl_cur->raw.p ); + } + + crl_cur = crl_cur->next; + } + while( crl_cur != NULL ); + + crl_cur = crl; + do + { + crl_prv = crl_cur; + crl_cur = crl_cur->next; + + mbedtls_platform_zeroize( crl_prv, sizeof( mbedtls_x509_crl ) ); + if( crl_prv != crl ) + mbedtls_free( crl_prv ); + } + while( crl_cur != NULL ); +} + +#endif /* MBEDTLS_X509_CRL_PARSE_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/x509_crt.c b/Android/Level4/app/src/main/c/mbedtls/library/x509_crt.c new file mode 100644 index 0000000..71e9cec --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/x509_crt.c @@ -0,0 +1,3399 @@ +/* + * X.509 certificate parsing and verification + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ +/* + * The ITU-T X.509 standard defines a certificate format for PKI. + * + * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) + * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) + * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) + * + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf + * + * [SIRO] https://cabforum.org/wp-content/uploads/Chunghwatelecom201503cabforumV4.pdf + */ + +#include "common.h" + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + +#include "mbedtls/x509_crt.h" +#include "mbedtls/error.h" +#include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_PEM_PARSE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#include "mbedtls/psa_util.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_free free +#define mbedtls_calloc calloc +#define mbedtls_snprintf snprintf +#endif + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) +#include +#else +#include +#endif + +#if defined(MBEDTLS_FS_IO) +#include +#if !defined(_WIN32) || defined(EFIX64) || defined(EFI32) +#include +#include +#include +#endif /* !_WIN32 || EFIX64 || EFI32 */ +#endif + +/* + * Item in a verification chain: cert and flags for it + */ +typedef struct { + mbedtls_x509_crt *crt; + uint32_t flags; +} x509_crt_verify_chain_item; + +/* + * Max size of verification chain: end-entity + intermediates + trusted root + */ +#define X509_MAX_VERIFY_CHAIN_SIZE ( MBEDTLS_X509_MAX_INTERMEDIATE_CA + 2 ) + +/* + * Default profile + */ +const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default = +{ +#if defined(MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES) + /* Allow SHA-1 (weak, but still safe in controlled environments) */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 ) | +#endif + /* Only SHA-2 hashes */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA224 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ), + 0xFFFFFFF, /* Any PK alg */ + 0xFFFFFFF, /* Any curve */ + 2048, +}; + +/* + * Next-default profile + */ +const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next = +{ + /* Hashes from SHA-256 and above */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ), + 0xFFFFFFF, /* Any PK alg */ +#if defined(MBEDTLS_ECP_C) + /* Curves at or above 128-bit security level */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP521R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP256R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP384R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP512R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256K1 ), +#else + 0, +#endif + 2048, +}; + +/* + * NSA Suite B Profile + */ +const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb = +{ + /* Only SHA-256 and 384 */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ), + /* Only ECDSA */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECDSA ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECKEY ), +#if defined(MBEDTLS_ECP_C) + /* Only NIST P-256 and P-384 */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ), +#else + 0, +#endif + 0, +}; + +/* + * Check md_alg against profile + * Return 0 if md_alg is acceptable for this profile, -1 otherwise + */ +static int x509_profile_check_md_alg( const mbedtls_x509_crt_profile *profile, + mbedtls_md_type_t md_alg ) +{ + if( md_alg == MBEDTLS_MD_NONE ) + return( -1 ); + + if( ( profile->allowed_mds & MBEDTLS_X509_ID_FLAG( md_alg ) ) != 0 ) + return( 0 ); + + return( -1 ); +} + +/* + * Check pk_alg against profile + * Return 0 if pk_alg is acceptable for this profile, -1 otherwise + */ +static int x509_profile_check_pk_alg( const mbedtls_x509_crt_profile *profile, + mbedtls_pk_type_t pk_alg ) +{ + if( pk_alg == MBEDTLS_PK_NONE ) + return( -1 ); + + if( ( profile->allowed_pks & MBEDTLS_X509_ID_FLAG( pk_alg ) ) != 0 ) + return( 0 ); + + return( -1 ); +} + +/* + * Check key against profile + * Return 0 if pk is acceptable for this profile, -1 otherwise + */ +static int x509_profile_check_key( const mbedtls_x509_crt_profile *profile, + const mbedtls_pk_context *pk ) +{ + const mbedtls_pk_type_t pk_alg = mbedtls_pk_get_type( pk ); + +#if defined(MBEDTLS_RSA_C) + if( pk_alg == MBEDTLS_PK_RSA || pk_alg == MBEDTLS_PK_RSASSA_PSS ) + { + if( mbedtls_pk_get_bitlen( pk ) >= profile->rsa_min_bitlen ) + return( 0 ); + + return( -1 ); + } +#endif + +#if defined(MBEDTLS_ECP_C) + if( pk_alg == MBEDTLS_PK_ECDSA || + pk_alg == MBEDTLS_PK_ECKEY || + pk_alg == MBEDTLS_PK_ECKEY_DH ) + { + const mbedtls_ecp_group_id gid = mbedtls_pk_ec( *pk )->grp.id; + + if( gid == MBEDTLS_ECP_DP_NONE ) + return( -1 ); + + if( ( profile->allowed_curves & MBEDTLS_X509_ID_FLAG( gid ) ) != 0 ) + return( 0 ); + + return( -1 ); + } +#endif + + return( -1 ); +} + +/* + * Like memcmp, but case-insensitive and always returns -1 if different + */ +static int x509_memcasecmp( const void *s1, const void *s2, size_t len ) +{ + size_t i; + unsigned char diff; + const unsigned char *n1 = s1, *n2 = s2; + + for( i = 0; i < len; i++ ) + { + diff = n1[i] ^ n2[i]; + + if( diff == 0 ) + continue; + + if( diff == 32 && + ( ( n1[i] >= 'a' && n1[i] <= 'z' ) || + ( n1[i] >= 'A' && n1[i] <= 'Z' ) ) ) + { + continue; + } + + return( -1 ); + } + + return( 0 ); +} + +/* + * Return 0 if name matches wildcard, -1 otherwise + */ +static int x509_check_wildcard( const char *cn, const mbedtls_x509_buf *name ) +{ + size_t i; + size_t cn_idx = 0, cn_len = strlen( cn ); + + /* We can't have a match if there is no wildcard to match */ + if( name->len < 3 || name->p[0] != '*' || name->p[1] != '.' ) + return( -1 ); + + for( i = 0; i < cn_len; ++i ) + { + if( cn[i] == '.' ) + { + cn_idx = i; + break; + } + } + + if( cn_idx == 0 ) + return( -1 ); + + if( cn_len - cn_idx == name->len - 1 && + x509_memcasecmp( name->p + 1, cn + cn_idx, name->len - 1 ) == 0 ) + { + return( 0 ); + } + + return( -1 ); +} + +/* + * Compare two X.509 strings, case-insensitive, and allowing for some encoding + * variations (but not all). + * + * Return 0 if equal, -1 otherwise. + */ +static int x509_string_cmp( const mbedtls_x509_buf *a, const mbedtls_x509_buf *b ) +{ + if( a->tag == b->tag && + a->len == b->len && + memcmp( a->p, b->p, b->len ) == 0 ) + { + return( 0 ); + } + + if( ( a->tag == MBEDTLS_ASN1_UTF8_STRING || a->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) && + ( b->tag == MBEDTLS_ASN1_UTF8_STRING || b->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) && + a->len == b->len && + x509_memcasecmp( a->p, b->p, b->len ) == 0 ) + { + return( 0 ); + } + + return( -1 ); +} + +/* + * Compare two X.509 Names (aka rdnSequence). + * + * See RFC 5280 section 7.1, though we don't implement the whole algorithm: + * we sometimes return unequal when the full algorithm would return equal, + * but never the other way. (In particular, we don't do Unicode normalisation + * or space folding.) + * + * Return 0 if equal, -1 otherwise. + */ +static int x509_name_cmp( const mbedtls_x509_name *a, const mbedtls_x509_name *b ) +{ + /* Avoid recursion, it might not be optimised by the compiler */ + while( a != NULL || b != NULL ) + { + if( a == NULL || b == NULL ) + return( -1 ); + + /* type */ + if( a->oid.tag != b->oid.tag || + a->oid.len != b->oid.len || + memcmp( a->oid.p, b->oid.p, b->oid.len ) != 0 ) + { + return( -1 ); + } + + /* value */ + if( x509_string_cmp( &a->val, &b->val ) != 0 ) + return( -1 ); + + /* structure of the list of sets */ + if( a->next_merged != b->next_merged ) + return( -1 ); + + a = a->next; + b = b->next; + } + + /* a == NULL == b */ + return( 0 ); +} + +/* + * Reset (init or clear) a verify_chain + */ +static void x509_crt_verify_chain_reset( + mbedtls_x509_crt_verify_chain *ver_chain ) +{ + size_t i; + + for( i = 0; i < MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE; i++ ) + { + ver_chain->items[i].crt = NULL; + ver_chain->items[i].flags = (uint32_t) -1; + } + + ver_chain->len = 0; + +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + ver_chain->trust_ca_cb_result = NULL; +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ +} + +/* + * Version ::= INTEGER { v1(0), v2(1), v3(2) } + */ +static int x509_get_version( unsigned char **p, + const unsigned char *end, + int *ver ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + { + *ver = 0; + return( 0 ); + } + + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + end = *p + len; + + if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_VERSION + ret ); + + if( *p != end ) + return( MBEDTLS_ERR_X509_INVALID_VERSION + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * Validity ::= SEQUENCE { + * notBefore Time, + * notAfter Time } + */ +static int x509_get_dates( unsigned char **p, + const unsigned char *end, + mbedtls_x509_time *from, + mbedtls_x509_time *to ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_DATE + ret ); + + end = *p + len; + + if( ( ret = mbedtls_x509_get_time( p, end, from ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_x509_get_time( p, end, to ) ) != 0 ) + return( ret ); + + if( *p != end ) + return( MBEDTLS_ERR_X509_INVALID_DATE + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * X.509 v2/v3 unique identifier (not parsed) + */ +static int x509_get_uid( unsigned char **p, + const unsigned char *end, + mbedtls_x509_buf *uid, int n ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( *p == end ) + return( 0 ); + + uid->tag = **p; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &uid->len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | n ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( 0 ); + + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + uid->p = *p; + *p += uid->len; + + return( 0 ); +} + +static int x509_get_basic_constraints( unsigned char **p, + const unsigned char *end, + int *ca_istrue, + int *max_pathlen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + /* + * BasicConstraints ::= SEQUENCE { + * cA BOOLEAN DEFAULT FALSE, + * pathLenConstraint INTEGER (0..MAX) OPTIONAL } + */ + *ca_istrue = 0; /* DEFAULT FALSE */ + *max_pathlen = 0; /* endless */ + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( *p == end ) + return( 0 ); + + if( ( ret = mbedtls_asn1_get_bool( p, end, ca_istrue ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + ret = mbedtls_asn1_get_int( p, end, ca_istrue ); + + if( ret != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( *ca_istrue != 0 ) + *ca_istrue = 1; + } + + if( *p == end ) + return( 0 ); + + if( ( ret = mbedtls_asn1_get_int( p, end, max_pathlen ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( *p != end ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + /* Do not accept max_pathlen equal to INT_MAX to avoid a signed integer + * overflow, which is an undefined behavior. */ + if( *max_pathlen == INT_MAX ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + + (*max_pathlen)++; + + return( 0 ); +} + +static int x509_get_ns_cert_type( unsigned char **p, + const unsigned char *end, + unsigned char *ns_cert_type) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_x509_bitstring bs = { 0, 0, NULL }; + + if( ( ret = mbedtls_asn1_get_bitstring( p, end, &bs ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( bs.len != 1 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + + /* Get actual bitstring */ + *ns_cert_type = *bs.p; + return( 0 ); +} + +static int x509_get_key_usage( unsigned char **p, + const unsigned char *end, + unsigned int *key_usage) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i; + mbedtls_x509_bitstring bs = { 0, 0, NULL }; + + if( ( ret = mbedtls_asn1_get_bitstring( p, end, &bs ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( bs.len < 1 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + + /* Get actual bitstring */ + *key_usage = 0; + for( i = 0; i < bs.len && i < sizeof( unsigned int ); i++ ) + { + *key_usage |= (unsigned int) bs.p[i] << (8*i); + } + + return( 0 ); +} + +/* + * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId + * + * KeyPurposeId ::= OBJECT IDENTIFIER + */ +static int x509_get_ext_key_usage( unsigned char **p, + const unsigned char *end, + mbedtls_x509_sequence *ext_key_usage) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ( ret = mbedtls_asn1_get_sequence_of( p, end, ext_key_usage, MBEDTLS_ASN1_OID ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + /* Sequence length must be >= 1 */ + if( ext_key_usage->buf.p == NULL ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + + return( 0 ); +} + +/* + * SubjectAltName ::= GeneralNames + * + * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName + * + * GeneralName ::= CHOICE { + * otherName [0] OtherName, + * rfc822Name [1] IA5String, + * dNSName [2] IA5String, + * x400Address [3] ORAddress, + * directoryName [4] Name, + * ediPartyName [5] EDIPartyName, + * uniformResourceIdentifier [6] IA5String, + * iPAddress [7] OCTET STRING, + * registeredID [8] OBJECT IDENTIFIER } + * + * OtherName ::= SEQUENCE { + * type-id OBJECT IDENTIFIER, + * value [0] EXPLICIT ANY DEFINED BY type-id } + * + * EDIPartyName ::= SEQUENCE { + * nameAssigner [0] DirectoryString OPTIONAL, + * partyName [1] DirectoryString } + * + * NOTE: we list all types, but only use dNSName and otherName + * of type HwModuleName, as defined in RFC 4108, at this point. + */ +static int x509_get_subject_alt_name( unsigned char **p, + const unsigned char *end, + mbedtls_x509_sequence *subject_alt_name ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len, tag_len; + mbedtls_asn1_buf *buf; + unsigned char tag; + mbedtls_asn1_sequence *cur = subject_alt_name; + + /* Get main sequence tag */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( *p + len != end ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + while( *p < end ) + { + mbedtls_x509_subject_alternative_name dummy_san_buf; + memset( &dummy_san_buf, 0, sizeof( dummy_san_buf ) ); + + tag = **p; + (*p)++; + if( ( ret = mbedtls_asn1_get_len( p, end, &tag_len ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( ( tag & MBEDTLS_ASN1_TAG_CLASS_MASK ) != + MBEDTLS_ASN1_CONTEXT_SPECIFIC ) + { + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + } + + /* + * Check that the SAN is structured correctly. + */ + ret = mbedtls_x509_parse_subject_alt_name( &(cur->buf), &dummy_san_buf ); + /* + * In case the extension is malformed, return an error, + * and clear the allocated sequences. + */ + if( ret != 0 && ret != MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE ) + { + mbedtls_x509_sequence *seq_cur = subject_alt_name->next; + mbedtls_x509_sequence *seq_prv; + while( seq_cur != NULL ) + { + seq_prv = seq_cur; + seq_cur = seq_cur->next; + mbedtls_platform_zeroize( seq_prv, + sizeof( mbedtls_x509_sequence ) ); + mbedtls_free( seq_prv ); + } + subject_alt_name->next = NULL; + return( ret ); + } + + /* Allocate and assign next pointer */ + if( cur->buf.p != NULL ) + { + if( cur->next != NULL ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS ); + + cur->next = mbedtls_calloc( 1, sizeof( mbedtls_asn1_sequence ) ); + + if( cur->next == NULL ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_ALLOC_FAILED ); + + cur = cur->next; + } + + buf = &(cur->buf); + buf->tag = tag; + buf->p = *p; + buf->len = tag_len; + *p += buf->len; + } + + /* Set final sequence entry's next pointer to NULL */ + cur->next = NULL; + + if( *p != end ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 } + * + * anyPolicy OBJECT IDENTIFIER ::= { id-ce-certificatePolicies 0 } + * + * certificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation + * + * PolicyInformation ::= SEQUENCE { + * policyIdentifier CertPolicyId, + * policyQualifiers SEQUENCE SIZE (1..MAX) OF + * PolicyQualifierInfo OPTIONAL } + * + * CertPolicyId ::= OBJECT IDENTIFIER + * + * PolicyQualifierInfo ::= SEQUENCE { + * policyQualifierId PolicyQualifierId, + * qualifier ANY DEFINED BY policyQualifierId } + * + * -- policyQualifierIds for Internet policy qualifiers + * + * id-qt OBJECT IDENTIFIER ::= { id-pkix 2 } + * id-qt-cps OBJECT IDENTIFIER ::= { id-qt 1 } + * id-qt-unotice OBJECT IDENTIFIER ::= { id-qt 2 } + * + * PolicyQualifierId ::= OBJECT IDENTIFIER ( id-qt-cps | id-qt-unotice ) + * + * Qualifier ::= CHOICE { + * cPSuri CPSuri, + * userNotice UserNotice } + * + * CPSuri ::= IA5String + * + * UserNotice ::= SEQUENCE { + * noticeRef NoticeReference OPTIONAL, + * explicitText DisplayText OPTIONAL } + * + * NoticeReference ::= SEQUENCE { + * organization DisplayText, + * noticeNumbers SEQUENCE OF INTEGER } + * + * DisplayText ::= CHOICE { + * ia5String IA5String (SIZE (1..200)), + * visibleString VisibleString (SIZE (1..200)), + * bmpString BMPString (SIZE (1..200)), + * utf8String UTF8String (SIZE (1..200)) } + * + * NOTE: we only parse and use anyPolicy without qualifiers at this point + * as defined in RFC 5280. + */ +static int x509_get_certificate_policies( unsigned char **p, + const unsigned char *end, + mbedtls_x509_sequence *certificate_policies ) +{ + int ret, parse_ret = 0; + size_t len; + mbedtls_asn1_buf *buf; + mbedtls_asn1_sequence *cur = certificate_policies; + + /* Get main sequence tag */ + ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ); + if( ret != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( *p + len != end ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + /* + * Cannot be an empty sequence. + */ + if( len == 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + while( *p < end ) + { + mbedtls_x509_buf policy_oid; + const unsigned char *policy_end; + + /* + * Get the policy sequence + */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + policy_end = *p + len; + + if( ( ret = mbedtls_asn1_get_tag( p, policy_end, &len, + MBEDTLS_ASN1_OID ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + policy_oid.tag = MBEDTLS_ASN1_OID; + policy_oid.len = len; + policy_oid.p = *p; + + /* + * Only AnyPolicy is currently supported when enforcing policy. + */ + if( MBEDTLS_OID_CMP( MBEDTLS_OID_ANY_POLICY, &policy_oid ) != 0 ) + { + /* + * Set the parsing return code but continue parsing, in case this + * extension is critical and MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION + * is configured. + */ + parse_ret = MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE; + } + + /* Allocate and assign next pointer */ + if( cur->buf.p != NULL ) + { + if( cur->next != NULL ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS ); + + cur->next = mbedtls_calloc( 1, sizeof( mbedtls_asn1_sequence ) ); + + if( cur->next == NULL ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_ALLOC_FAILED ); + + cur = cur->next; + } + + buf = &( cur->buf ); + buf->tag = policy_oid.tag; + buf->p = policy_oid.p; + buf->len = policy_oid.len; + + *p += len; + + /* + * If there is an optional qualifier, then *p < policy_end + * Check the Qualifier len to verify it doesn't exceed policy_end. + */ + if( *p < policy_end ) + { + if( ( ret = mbedtls_asn1_get_tag( p, policy_end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + /* + * Skip the optional policy qualifiers. + */ + *p += len; + } + + if( *p != policy_end ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + + /* Set final sequence entry's next pointer to NULL */ + cur->next = NULL; + + if( *p != end ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( parse_ret ); +} + +/* + * X.509 v3 extensions + * + */ +static int x509_get_crt_ext( unsigned char **p, + const unsigned char *end, + mbedtls_x509_crt *crt, + mbedtls_x509_crt_ext_cb_t cb, + void *p_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + unsigned char *end_ext_data, *start_ext_octet, *end_ext_octet; + + if( *p == end ) + return( 0 ); + + if( ( ret = mbedtls_x509_get_ext( p, end, &crt->v3_ext, 3 ) ) != 0 ) + return( ret ); + + end = crt->v3_ext.p + crt->v3_ext.len; + while( *p < end ) + { + /* + * Extension ::= SEQUENCE { + * extnID OBJECT IDENTIFIER, + * critical BOOLEAN DEFAULT FALSE, + * extnValue OCTET STRING } + */ + mbedtls_x509_buf extn_oid = {0, 0, NULL}; + int is_critical = 0; /* DEFAULT FALSE */ + int ext_type = 0; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + end_ext_data = *p + len; + + /* Get extension ID */ + if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &extn_oid.len, + MBEDTLS_ASN1_OID ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + extn_oid.tag = MBEDTLS_ASN1_OID; + extn_oid.p = *p; + *p += extn_oid.len; + + /* Get optional critical */ + if( ( ret = mbedtls_asn1_get_bool( p, end_ext_data, &is_critical ) ) != 0 && + ( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + /* Data should be octet string type */ + if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &len, + MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + start_ext_octet = *p; + end_ext_octet = *p + len; + + if( end_ext_octet != end_ext_data ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + /* + * Detect supported extensions + */ + ret = mbedtls_oid_get_x509_ext_type( &extn_oid, &ext_type ); + + if( ret != 0 ) + { + /* Give the callback (if any) a chance to handle the extension */ + if( cb != NULL ) + { + ret = cb( p_ctx, crt, &extn_oid, is_critical, *p, end_ext_octet ); + if( ret != 0 && is_critical ) + return( ret ); + *p = end_ext_octet; + continue; + } + + /* No parser found, skip extension */ + *p = end_ext_octet; + +#if !defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION) + if( is_critical ) + { + /* Data is marked as critical: fail */ + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + } +#endif + continue; + } + + /* Forbid repeated extensions */ + if( ( crt->ext_types & ext_type ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS ); + + crt->ext_types |= ext_type; + + switch( ext_type ) + { + case MBEDTLS_X509_EXT_BASIC_CONSTRAINTS: + /* Parse basic constraints */ + if( ( ret = x509_get_basic_constraints( p, end_ext_octet, + &crt->ca_istrue, &crt->max_pathlen ) ) != 0 ) + return( ret ); + break; + + case MBEDTLS_X509_EXT_KEY_USAGE: + /* Parse key usage */ + if( ( ret = x509_get_key_usage( p, end_ext_octet, + &crt->key_usage ) ) != 0 ) + return( ret ); + break; + + case MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE: + /* Parse extended key usage */ + if( ( ret = x509_get_ext_key_usage( p, end_ext_octet, + &crt->ext_key_usage ) ) != 0 ) + return( ret ); + break; + + case MBEDTLS_X509_EXT_SUBJECT_ALT_NAME: + /* Parse subject alt name */ + if( ( ret = x509_get_subject_alt_name( p, end_ext_octet, + &crt->subject_alt_names ) ) != 0 ) + return( ret ); + break; + + case MBEDTLS_X509_EXT_NS_CERT_TYPE: + /* Parse netscape certificate type */ + if( ( ret = x509_get_ns_cert_type( p, end_ext_octet, + &crt->ns_cert_type ) ) != 0 ) + return( ret ); + break; + + case MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES: + /* Parse certificate policies type */ + if( ( ret = x509_get_certificate_policies( p, end_ext_octet, + &crt->certificate_policies ) ) != 0 ) + { + /* Give the callback (if any) a chance to handle the extension + * if it contains unsupported policies */ + if( ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE && cb != NULL && + cb( p_ctx, crt, &extn_oid, is_critical, + start_ext_octet, end_ext_octet ) == 0 ) + break; + +#if !defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION) + if( is_critical ) + return( ret ); + else +#endif + /* + * If MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE is returned, then we + * cannot interpret or enforce the policy. However, it is up to + * the user to choose how to enforce the policies, + * unless the extension is critical. + */ + if( ret != MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE ) + return( ret ); + } + break; + + default: + /* + * If this is a non-critical extension, which the oid layer + * supports, but there isn't an x509 parser for it, + * skip the extension. + */ +#if !defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION) + if( is_critical ) + return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE ); + else +#endif + *p = end_ext_octet; + } + } + + if( *p != end ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * Parse and fill a single X.509 certificate in DER format + */ +static int x509_crt_parse_der_core( mbedtls_x509_crt *crt, + const unsigned char *buf, + size_t buflen, + int make_copy, + mbedtls_x509_crt_ext_cb_t cb, + void *p_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + unsigned char *p, *end, *crt_end; + mbedtls_x509_buf sig_params1, sig_params2, sig_oid2; + + memset( &sig_params1, 0, sizeof( mbedtls_x509_buf ) ); + memset( &sig_params2, 0, sizeof( mbedtls_x509_buf ) ); + memset( &sig_oid2, 0, sizeof( mbedtls_x509_buf ) ); + + /* + * Check for valid input + */ + if( crt == NULL || buf == NULL ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + /* Use the original buffer until we figure out actual length. */ + p = (unsigned char*) buf; + len = buflen; + end = p + len; + + /* + * Certificate ::= SEQUENCE { + * tbsCertificate TBSCertificate, + * signatureAlgorithm AlgorithmIdentifier, + * signatureValue BIT STRING } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT ); + } + + end = crt_end = p + len; + crt->raw.len = crt_end - buf; + if( make_copy != 0 ) + { + /* Create and populate a new buffer for the raw field. */ + crt->raw.p = p = mbedtls_calloc( 1, crt->raw.len ); + if( crt->raw.p == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + memcpy( crt->raw.p, buf, crt->raw.len ); + crt->own_buffer = 1; + + p += crt->raw.len - len; + end = crt_end = p + len; + } + else + { + crt->raw.p = (unsigned char*) buf; + crt->own_buffer = 0; + } + + /* + * TBSCertificate ::= SEQUENCE { + */ + crt->tbs.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + end = p + len; + crt->tbs.len = end - crt->tbs.p; + + /* + * Version ::= INTEGER { v1(0), v2(1), v3(2) } + * + * CertificateSerialNumber ::= INTEGER + * + * signature AlgorithmIdentifier + */ + if( ( ret = x509_get_version( &p, end, &crt->version ) ) != 0 || + ( ret = mbedtls_x509_get_serial( &p, end, &crt->serial ) ) != 0 || + ( ret = mbedtls_x509_get_alg( &p, end, &crt->sig_oid, + &sig_params1 ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + if( crt->version < 0 || crt->version > 2 ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_UNKNOWN_VERSION ); + } + + crt->version++; + + if( ( ret = mbedtls_x509_get_sig_alg( &crt->sig_oid, &sig_params1, + &crt->sig_md, &crt->sig_pk, + &crt->sig_opts ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + /* + * issuer Name + */ + crt->issuer_raw.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + if( ( ret = mbedtls_x509_get_name( &p, p + len, &crt->issuer ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + crt->issuer_raw.len = p - crt->issuer_raw.p; + + /* + * Validity ::= SEQUENCE { + * notBefore Time, + * notAfter Time } + * + */ + if( ( ret = x509_get_dates( &p, end, &crt->valid_from, + &crt->valid_to ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + /* + * subject Name + */ + crt->subject_raw.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + if( len && ( ret = mbedtls_x509_get_name( &p, p + len, &crt->subject ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + crt->subject_raw.len = p - crt->subject_raw.p; + + /* + * SubjectPublicKeyInfo + */ + crt->pk_raw.p = p; + if( ( ret = mbedtls_pk_parse_subpubkey( &p, end, &crt->pk ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + crt->pk_raw.len = p - crt->pk_raw.p; + + /* + * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, + * -- If present, version shall be v2 or v3 + * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, + * -- If present, version shall be v2 or v3 + * extensions [3] EXPLICIT Extensions OPTIONAL + * -- If present, version shall be v3 + */ + if( crt->version == 2 || crt->version == 3 ) + { + ret = x509_get_uid( &p, end, &crt->issuer_id, 1 ); + if( ret != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + } + + if( crt->version == 2 || crt->version == 3 ) + { + ret = x509_get_uid( &p, end, &crt->subject_id, 2 ); + if( ret != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + } + +#if !defined(MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3) + if( crt->version == 3 ) +#endif + { + ret = x509_get_crt_ext( &p, end, crt, cb, p_ctx ); + if( ret != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + } + + if( p != end ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + + end = crt_end; + + /* + * } + * -- end of TBSCertificate + * + * signatureAlgorithm AlgorithmIdentifier, + * signatureValue BIT STRING + */ + if( ( ret = mbedtls_x509_get_alg( &p, end, &sig_oid2, &sig_params2 ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + if( crt->sig_oid.len != sig_oid2.len || + memcmp( crt->sig_oid.p, sig_oid2.p, crt->sig_oid.len ) != 0 || + sig_params1.len != sig_params2.len || + ( sig_params1.len != 0 && + memcmp( sig_params1.p, sig_params2.p, sig_params1.len ) != 0 ) ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_SIG_MISMATCH ); + } + + if( ( ret = mbedtls_x509_get_sig( &p, end, &crt->sig ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + if( p != end ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + + return( 0 ); +} + +/* + * Parse one X.509 certificate in DER format from a buffer and add them to a + * chained list + */ +static int mbedtls_x509_crt_parse_der_internal( mbedtls_x509_crt *chain, + const unsigned char *buf, + size_t buflen, + int make_copy, + mbedtls_x509_crt_ext_cb_t cb, + void *p_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_x509_crt *crt = chain, *prev = NULL; + + /* + * Check for valid input + */ + if( crt == NULL || buf == NULL ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + while( crt->version != 0 && crt->next != NULL ) + { + prev = crt; + crt = crt->next; + } + + /* + * Add new certificate on the end of the chain if needed. + */ + if( crt->version != 0 && crt->next == NULL ) + { + crt->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) ); + + if( crt->next == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + prev = crt; + mbedtls_x509_crt_init( crt->next ); + crt = crt->next; + } + + ret = x509_crt_parse_der_core( crt, buf, buflen, make_copy, cb, p_ctx ); + if( ret != 0 ) + { + if( prev ) + prev->next = NULL; + + if( crt != chain ) + mbedtls_free( crt ); + + return( ret ); + } + + return( 0 ); +} + +int mbedtls_x509_crt_parse_der_nocopy( mbedtls_x509_crt *chain, + const unsigned char *buf, + size_t buflen ) +{ + return( mbedtls_x509_crt_parse_der_internal( chain, buf, buflen, 0, NULL, NULL ) ); +} + +int mbedtls_x509_crt_parse_der_with_ext_cb( mbedtls_x509_crt *chain, + const unsigned char *buf, + size_t buflen, + int make_copy, + mbedtls_x509_crt_ext_cb_t cb, + void *p_ctx ) +{ + return( mbedtls_x509_crt_parse_der_internal( chain, buf, buflen, make_copy, cb, p_ctx ) ); +} + +int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain, + const unsigned char *buf, + size_t buflen ) +{ + return( mbedtls_x509_crt_parse_der_internal( chain, buf, buflen, 1, NULL, NULL ) ); +} + +/* + * Parse one or more PEM certificates from a buffer and add them to the chained + * list + */ +int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, + const unsigned char *buf, + size_t buflen ) +{ +#if defined(MBEDTLS_PEM_PARSE_C) + int success = 0, first_error = 0, total_failed = 0; + int buf_format = MBEDTLS_X509_FORMAT_DER; +#endif + + /* + * Check for valid input + */ + if( chain == NULL || buf == NULL ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + /* + * Determine buffer content. Buffer contains either one DER certificate or + * one or more PEM certificates. + */ +#if defined(MBEDTLS_PEM_PARSE_C) + if( buflen != 0 && buf[buflen - 1] == '\0' && + strstr( (const char *) buf, "-----BEGIN CERTIFICATE-----" ) != NULL ) + { + buf_format = MBEDTLS_X509_FORMAT_PEM; + } + + if( buf_format == MBEDTLS_X509_FORMAT_DER ) + return mbedtls_x509_crt_parse_der( chain, buf, buflen ); +#else + return mbedtls_x509_crt_parse_der( chain, buf, buflen ); +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) + if( buf_format == MBEDTLS_X509_FORMAT_PEM ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_pem_context pem; + + /* 1 rather than 0 since the terminating NULL byte is counted in */ + while( buflen > 1 ) + { + size_t use_len; + mbedtls_pem_init( &pem ); + + /* If we get there, we know the string is null-terminated */ + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN CERTIFICATE-----", + "-----END CERTIFICATE-----", + buf, NULL, 0, &use_len ); + + if( ret == 0 ) + { + /* + * Was PEM encoded + */ + buflen -= use_len; + buf += use_len; + } + else if( ret == MBEDTLS_ERR_PEM_BAD_INPUT_DATA ) + { + return( ret ); + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + mbedtls_pem_free( &pem ); + + /* + * PEM header and footer were found + */ + buflen -= use_len; + buf += use_len; + + if( first_error == 0 ) + first_error = ret; + + total_failed++; + continue; + } + else + break; + + ret = mbedtls_x509_crt_parse_der( chain, pem.buf, pem.buflen ); + + mbedtls_pem_free( &pem ); + + if( ret != 0 ) + { + /* + * Quit parsing on a memory error + */ + if( ret == MBEDTLS_ERR_X509_ALLOC_FAILED ) + return( ret ); + + if( first_error == 0 ) + first_error = ret; + + total_failed++; + continue; + } + + success = 1; + } + } + + if( success ) + return( total_failed ); + else if( first_error ) + return( first_error ); + else + return( MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT ); +#endif /* MBEDTLS_PEM_PARSE_C */ +} + +#if defined(MBEDTLS_FS_IO) +/* + * Load one or more certificates and add them to the chained list + */ +int mbedtls_x509_crt_parse_file( mbedtls_x509_crt *chain, const char *path ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n; + unsigned char *buf; + + if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = mbedtls_x509_crt_parse( chain, buf, n ); + + mbedtls_platform_zeroize( buf, n ); + mbedtls_free( buf ); + + return( ret ); +} + +int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ) +{ + int ret = 0; +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + int w_ret; + WCHAR szDir[MAX_PATH]; + char filename[MAX_PATH]; + char *p; + size_t len = strlen( path ); + + WIN32_FIND_DATAW file_data; + HANDLE hFind; + + if( len > MAX_PATH - 3 ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + memset( szDir, 0, sizeof(szDir) ); + memset( filename, 0, MAX_PATH ); + memcpy( filename, path, len ); + filename[len++] = '\\'; + p = filename + len; + filename[len++] = '*'; + + w_ret = MultiByteToWideChar( CP_ACP, 0, filename, (int)len, szDir, + MAX_PATH - 3 ); + if( w_ret == 0 ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + hFind = FindFirstFileW( szDir, &file_data ); + if( hFind == INVALID_HANDLE_VALUE ) + return( MBEDTLS_ERR_X509_FILE_IO_ERROR ); + + len = MAX_PATH - len; + do + { + memset( p, 0, len ); + + if( file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) + continue; + + w_ret = WideCharToMultiByte( CP_ACP, 0, file_data.cFileName, + lstrlenW( file_data.cFileName ), + p, (int) len - 1, + NULL, NULL ); + if( w_ret == 0 ) + { + ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; + goto cleanup; + } + + w_ret = mbedtls_x509_crt_parse_file( chain, filename ); + if( w_ret < 0 ) + ret++; + else + ret += w_ret; + } + while( FindNextFileW( hFind, &file_data ) != 0 ); + + if( GetLastError() != ERROR_NO_MORE_FILES ) + ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; + +cleanup: + FindClose( hFind ); +#else /* _WIN32 */ + int t_ret; + int snp_ret; + struct stat sb; + struct dirent *entry; + char entry_name[MBEDTLS_X509_MAX_FILE_PATH_LEN]; + DIR *dir = opendir( path ); + + if( dir == NULL ) + return( MBEDTLS_ERR_X509_FILE_IO_ERROR ); + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &mbedtls_threading_readdir_mutex ) ) != 0 ) + { + closedir( dir ); + return( ret ); + } +#endif /* MBEDTLS_THREADING_C */ + + while( ( entry = readdir( dir ) ) != NULL ) + { + snp_ret = mbedtls_snprintf( entry_name, sizeof entry_name, + "%s/%s", path, entry->d_name ); + + if( snp_ret < 0 || (size_t)snp_ret >= sizeof entry_name ) + { + ret = MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; + goto cleanup; + } + else if( stat( entry_name, &sb ) == -1 ) + { + ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; + goto cleanup; + } + + if( !S_ISREG( sb.st_mode ) ) + continue; + + // Ignore parse errors + // + t_ret = mbedtls_x509_crt_parse_file( chain, entry_name ); + if( t_ret < 0 ) + ret++; + else + ret += t_ret; + } + +cleanup: + closedir( dir ); + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &mbedtls_threading_readdir_mutex ) != 0 ) + ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; +#endif /* MBEDTLS_THREADING_C */ + +#endif /* _WIN32 */ + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + +/* + * OtherName ::= SEQUENCE { + * type-id OBJECT IDENTIFIER, + * value [0] EXPLICIT ANY DEFINED BY type-id } + * + * HardwareModuleName ::= SEQUENCE { + * hwType OBJECT IDENTIFIER, + * hwSerialNum OCTET STRING } + * + * NOTE: we currently only parse and use otherName of type HwModuleName, + * as defined in RFC 4108. + */ +static int x509_get_other_name( const mbedtls_x509_buf *subject_alt_name, + mbedtls_x509_san_other_name *other_name ) +{ + int ret = 0; + size_t len; + unsigned char *p = subject_alt_name->p; + const unsigned char *end = p + subject_alt_name->len; + mbedtls_x509_buf cur_oid; + + if( ( subject_alt_name->tag & + ( MBEDTLS_ASN1_TAG_CLASS_MASK | MBEDTLS_ASN1_TAG_VALUE_MASK ) ) != + ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME ) ) + { + /* + * The given subject alternative name is not of type "othername". + */ + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + } + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_OID ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + cur_oid.tag = MBEDTLS_ASN1_OID; + cur_oid.p = p; + cur_oid.len = len; + + /* + * Only HwModuleName is currently supported. + */ + if( MBEDTLS_OID_CMP( MBEDTLS_OID_ON_HW_MODULE_NAME, &cur_oid ) != 0 ) + { + return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE ); + } + + if( p + len >= end ) + { + mbedtls_platform_zeroize( other_name, sizeof( *other_name ) ); + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + p += len; + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OID ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + other_name->value.hardware_module_name.oid.tag = MBEDTLS_ASN1_OID; + other_name->value.hardware_module_name.oid.p = p; + other_name->value.hardware_module_name.oid.len = len; + + if( p + len >= end ) + { + mbedtls_platform_zeroize( other_name, sizeof( *other_name ) ); + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + p += len; + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + other_name->value.hardware_module_name.val.tag = MBEDTLS_ASN1_OCTET_STRING; + other_name->value.hardware_module_name.val.p = p; + other_name->value.hardware_module_name.val.len = len; + p += len; + if( p != end ) + { + mbedtls_platform_zeroize( other_name, + sizeof( *other_name ) ); + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + return( 0 ); +} + +static int x509_info_subject_alt_name( char **buf, size_t *size, + const mbedtls_x509_sequence + *subject_alt_name, + const char *prefix ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n = *size; + char *p = *buf; + const mbedtls_x509_sequence *cur = subject_alt_name; + mbedtls_x509_subject_alternative_name san; + int parse_ret; + + while( cur != NULL ) + { + memset( &san, 0, sizeof( san ) ); + parse_ret = mbedtls_x509_parse_subject_alt_name( &cur->buf, &san ); + if( parse_ret != 0 ) + { + if( parse_ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE ) + { + ret = mbedtls_snprintf( p, n, "\n%s ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + } + else + { + ret = mbedtls_snprintf( p, n, "\n%s ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + } + cur = cur->next; + continue; + } + + switch( san.type ) + { + /* + * otherName + */ + case MBEDTLS_X509_SAN_OTHER_NAME: + { + mbedtls_x509_san_other_name *other_name = &san.san.other_name; + + ret = mbedtls_snprintf( p, n, "\n%s otherName :", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( MBEDTLS_OID_CMP( MBEDTLS_OID_ON_HW_MODULE_NAME, + &other_name->value.hardware_module_name.oid ) != 0 ) + { + ret = mbedtls_snprintf( p, n, "\n%s hardware module name :", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + ret = mbedtls_snprintf( p, n, "\n%s hardware type : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_oid_get_numeric_string( p, n, &other_name->value.hardware_module_name.oid ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%s hardware serial number : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( other_name->value.hardware_module_name.val.len >= n ) + { + *p = '\0'; + return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL ); + } + + memcpy( p, other_name->value.hardware_module_name.val.p, + other_name->value.hardware_module_name.val.len ); + p += other_name->value.hardware_module_name.val.len; + + n -= other_name->value.hardware_module_name.val.len; + + }/* MBEDTLS_OID_ON_HW_MODULE_NAME */ + } + break; + + /* + * dNSName + */ + case MBEDTLS_X509_SAN_DNS_NAME: + { + ret = mbedtls_snprintf( p, n, "\n%s dNSName : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + if( san.san.unstructured_name.len >= n ) + { + *p = '\0'; + return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL ); + } + + memcpy( p, san.san.unstructured_name.p, san.san.unstructured_name.len ); + p += san.san.unstructured_name.len; + n -= san.san.unstructured_name.len; + } + break; + + /* + * Type not supported, skip item. + */ + default: + ret = mbedtls_snprintf( p, n, "\n%s ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + break; + } + + cur = cur->next; + } + + *p = '\0'; + + *size = n; + *buf = p; + + return( 0 ); +} + +int mbedtls_x509_parse_subject_alt_name( const mbedtls_x509_buf *san_buf, + mbedtls_x509_subject_alternative_name *san ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + switch( san_buf->tag & + ( MBEDTLS_ASN1_TAG_CLASS_MASK | + MBEDTLS_ASN1_TAG_VALUE_MASK ) ) + { + /* + * otherName + */ + case( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME ): + { + mbedtls_x509_san_other_name other_name; + + ret = x509_get_other_name( san_buf, &other_name ); + if( ret != 0 ) + return( ret ); + + memset( san, 0, sizeof( mbedtls_x509_subject_alternative_name ) ); + san->type = MBEDTLS_X509_SAN_OTHER_NAME; + memcpy( &san->san.other_name, + &other_name, sizeof( other_name ) ); + + } + break; + + /* + * dNSName + */ + case( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_DNS_NAME ): + { + memset( san, 0, sizeof( mbedtls_x509_subject_alternative_name ) ); + san->type = MBEDTLS_X509_SAN_DNS_NAME; + + memcpy( &san->san.unstructured_name, + san_buf, sizeof( *san_buf ) ); + + } + break; + + /* + * Type not supported + */ + default: + return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE ); + } + return( 0 ); +} + +#define PRINT_ITEM(i) \ + { \ + ret = mbedtls_snprintf( p, n, "%s" i, sep ); \ + MBEDTLS_X509_SAFE_SNPRINTF; \ + sep = ", "; \ + } + +#define CERT_TYPE(type,name) \ + if( ns_cert_type & (type) ) \ + PRINT_ITEM( name ); + +static int x509_info_cert_type( char **buf, size_t *size, + unsigned char ns_cert_type ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n = *size; + char *p = *buf; + const char *sep = ""; + + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT, "SSL Client" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER, "SSL Server" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_EMAIL, "Email" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING, "Object Signing" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_RESERVED, "Reserved" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_CA, "SSL CA" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA, "Email CA" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA, "Object Signing CA" ); + + *size = n; + *buf = p; + + return( 0 ); +} + +#define KEY_USAGE(code,name) \ + if( key_usage & (code) ) \ + PRINT_ITEM( name ); + +static int x509_info_key_usage( char **buf, size_t *size, + unsigned int key_usage ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n = *size; + char *p = *buf; + const char *sep = ""; + + KEY_USAGE( MBEDTLS_X509_KU_DIGITAL_SIGNATURE, "Digital Signature" ); + KEY_USAGE( MBEDTLS_X509_KU_NON_REPUDIATION, "Non Repudiation" ); + KEY_USAGE( MBEDTLS_X509_KU_KEY_ENCIPHERMENT, "Key Encipherment" ); + KEY_USAGE( MBEDTLS_X509_KU_DATA_ENCIPHERMENT, "Data Encipherment" ); + KEY_USAGE( MBEDTLS_X509_KU_KEY_AGREEMENT, "Key Agreement" ); + KEY_USAGE( MBEDTLS_X509_KU_KEY_CERT_SIGN, "Key Cert Sign" ); + KEY_USAGE( MBEDTLS_X509_KU_CRL_SIGN, "CRL Sign" ); + KEY_USAGE( MBEDTLS_X509_KU_ENCIPHER_ONLY, "Encipher Only" ); + KEY_USAGE( MBEDTLS_X509_KU_DECIPHER_ONLY, "Decipher Only" ); + + *size = n; + *buf = p; + + return( 0 ); +} + +static int x509_info_ext_key_usage( char **buf, size_t *size, + const mbedtls_x509_sequence *extended_key_usage ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const char *desc; + size_t n = *size; + char *p = *buf; + const mbedtls_x509_sequence *cur = extended_key_usage; + const char *sep = ""; + + while( cur != NULL ) + { + if( mbedtls_oid_get_extended_key_usage( &cur->buf, &desc ) != 0 ) + desc = "???"; + + ret = mbedtls_snprintf( p, n, "%s%s", sep, desc ); + MBEDTLS_X509_SAFE_SNPRINTF; + + sep = ", "; + + cur = cur->next; + } + + *size = n; + *buf = p; + + return( 0 ); +} + +static int x509_info_cert_policies( char **buf, size_t *size, + const mbedtls_x509_sequence *certificate_policies ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const char *desc; + size_t n = *size; + char *p = *buf; + const mbedtls_x509_sequence *cur = certificate_policies; + const char *sep = ""; + + while( cur != NULL ) + { + if( mbedtls_oid_get_certificate_policies( &cur->buf, &desc ) != 0 ) + desc = "???"; + + ret = mbedtls_snprintf( p, n, "%s%s", sep, desc ); + MBEDTLS_X509_SAFE_SNPRINTF; + + sep = ", "; + + cur = cur->next; + } + + *size = n; + *buf = p; + + return( 0 ); +} + +/* + * Return an informational string about the certificate. + */ +#define BEFORE_COLON 18 +#define BC "18" +int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix, + const mbedtls_x509_crt *crt ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n; + char *p; + char key_size_str[BEFORE_COLON]; + + p = buf; + n = size; + + if( NULL == crt ) + { + ret = mbedtls_snprintf( p, n, "\nCertificate is uninitialised!\n" ); + MBEDTLS_X509_SAFE_SNPRINTF; + + return( (int) ( size - n ) ); + } + + ret = mbedtls_snprintf( p, n, "%scert. version : %d\n", + prefix, crt->version ); + MBEDTLS_X509_SAFE_SNPRINTF; + ret = mbedtls_snprintf( p, n, "%sserial number : ", + prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_x509_serial_gets( p, n, &crt->serial ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%sissuer name : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + ret = mbedtls_x509_dn_gets( p, n, &crt->issuer ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%ssubject name : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + ret = mbedtls_x509_dn_gets( p, n, &crt->subject ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%sissued on : " \ + "%04d-%02d-%02d %02d:%02d:%02d", prefix, + crt->valid_from.year, crt->valid_from.mon, + crt->valid_from.day, crt->valid_from.hour, + crt->valid_from.min, crt->valid_from.sec ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%sexpires on : " \ + "%04d-%02d-%02d %02d:%02d:%02d", prefix, + crt->valid_to.year, crt->valid_to.mon, + crt->valid_to.day, crt->valid_to.hour, + crt->valid_to.min, crt->valid_to.sec ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%ssigned using : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_x509_sig_alg_gets( p, n, &crt->sig_oid, crt->sig_pk, + crt->sig_md, crt->sig_opts ); + MBEDTLS_X509_SAFE_SNPRINTF; + + /* Key size */ + if( ( ret = mbedtls_x509_key_size_helper( key_size_str, BEFORE_COLON, + mbedtls_pk_get_name( &crt->pk ) ) ) != 0 ) + { + return( ret ); + } + + ret = mbedtls_snprintf( p, n, "\n%s%-" BC "s: %d bits", prefix, key_size_str, + (int) mbedtls_pk_get_bitlen( &crt->pk ) ); + MBEDTLS_X509_SAFE_SNPRINTF; + + /* + * Optional extensions + */ + + if( crt->ext_types & MBEDTLS_X509_EXT_BASIC_CONSTRAINTS ) + { + ret = mbedtls_snprintf( p, n, "\n%sbasic constraints : CA=%s", prefix, + crt->ca_istrue ? "true" : "false" ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( crt->max_pathlen > 0 ) + { + ret = mbedtls_snprintf( p, n, ", max_pathlen=%d", crt->max_pathlen - 1 ); + MBEDTLS_X509_SAFE_SNPRINTF; + } + } + + if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME ) + { + ret = mbedtls_snprintf( p, n, "\n%ssubject alt name :", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( ( ret = x509_info_subject_alt_name( &p, &n, + &crt->subject_alt_names, + prefix ) ) != 0 ) + return( ret ); + } + + if( crt->ext_types & MBEDTLS_X509_EXT_NS_CERT_TYPE ) + { + ret = mbedtls_snprintf( p, n, "\n%scert. type : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( ( ret = x509_info_cert_type( &p, &n, crt->ns_cert_type ) ) != 0 ) + return( ret ); + } + + if( crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE ) + { + ret = mbedtls_snprintf( p, n, "\n%skey usage : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( ( ret = x509_info_key_usage( &p, &n, crt->key_usage ) ) != 0 ) + return( ret ); + } + + if( crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE ) + { + ret = mbedtls_snprintf( p, n, "\n%sext key usage : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( ( ret = x509_info_ext_key_usage( &p, &n, + &crt->ext_key_usage ) ) != 0 ) + return( ret ); + } + + if( crt->ext_types & MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES ) + { + ret = mbedtls_snprintf( p, n, "\n%scertificate policies : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( ( ret = x509_info_cert_policies( &p, &n, + &crt->certificate_policies ) ) != 0 ) + return( ret ); + } + + ret = mbedtls_snprintf( p, n, "\n" ); + MBEDTLS_X509_SAFE_SNPRINTF; + + return( (int) ( size - n ) ); +} + +struct x509_crt_verify_string { + int code; + const char *string; +}; + +static const struct x509_crt_verify_string x509_crt_verify_strings[] = { + { MBEDTLS_X509_BADCERT_EXPIRED, "The certificate validity has expired" }, + { MBEDTLS_X509_BADCERT_REVOKED, "The certificate has been revoked (is on a CRL)" }, + { MBEDTLS_X509_BADCERT_CN_MISMATCH, "The certificate Common Name (CN) does not match with the expected CN" }, + { MBEDTLS_X509_BADCERT_NOT_TRUSTED, "The certificate is not correctly signed by the trusted CA" }, + { MBEDTLS_X509_BADCRL_NOT_TRUSTED, "The CRL is not correctly signed by the trusted CA" }, + { MBEDTLS_X509_BADCRL_EXPIRED, "The CRL is expired" }, + { MBEDTLS_X509_BADCERT_MISSING, "Certificate was missing" }, + { MBEDTLS_X509_BADCERT_SKIP_VERIFY, "Certificate verification was skipped" }, + { MBEDTLS_X509_BADCERT_OTHER, "Other reason (can be used by verify callback)" }, + { MBEDTLS_X509_BADCERT_FUTURE, "The certificate validity starts in the future" }, + { MBEDTLS_X509_BADCRL_FUTURE, "The CRL is from the future" }, + { MBEDTLS_X509_BADCERT_KEY_USAGE, "Usage does not match the keyUsage extension" }, + { MBEDTLS_X509_BADCERT_EXT_KEY_USAGE, "Usage does not match the extendedKeyUsage extension" }, + { MBEDTLS_X509_BADCERT_NS_CERT_TYPE, "Usage does not match the nsCertType extension" }, + { MBEDTLS_X509_BADCERT_BAD_MD, "The certificate is signed with an unacceptable hash." }, + { MBEDTLS_X509_BADCERT_BAD_PK, "The certificate is signed with an unacceptable PK alg (eg RSA vs ECDSA)." }, + { MBEDTLS_X509_BADCERT_BAD_KEY, "The certificate is signed with an unacceptable key (eg bad curve, RSA too short)." }, + { MBEDTLS_X509_BADCRL_BAD_MD, "The CRL is signed with an unacceptable hash." }, + { MBEDTLS_X509_BADCRL_BAD_PK, "The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA)." }, + { MBEDTLS_X509_BADCRL_BAD_KEY, "The CRL is signed with an unacceptable key (eg bad curve, RSA too short)." }, + { 0, NULL } +}; + +int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix, + uint32_t flags ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const struct x509_crt_verify_string *cur; + char *p = buf; + size_t n = size; + + for( cur = x509_crt_verify_strings; cur->string != NULL ; cur++ ) + { + if( ( flags & cur->code ) == 0 ) + continue; + + ret = mbedtls_snprintf( p, n, "%s%s\n", prefix, cur->string ); + MBEDTLS_X509_SAFE_SNPRINTF; + flags ^= cur->code; + } + + if( flags != 0 ) + { + ret = mbedtls_snprintf( p, n, "%sUnknown reason " + "(this should not happen)\n", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + } + + return( (int) ( size - n ) ); +} + +#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) +int mbedtls_x509_crt_check_key_usage( const mbedtls_x509_crt *crt, + unsigned int usage ) +{ + unsigned int usage_must, usage_may; + unsigned int may_mask = MBEDTLS_X509_KU_ENCIPHER_ONLY + | MBEDTLS_X509_KU_DECIPHER_ONLY; + + if( ( crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE ) == 0 ) + return( 0 ); + + usage_must = usage & ~may_mask; + + if( ( ( crt->key_usage & ~may_mask ) & usage_must ) != usage_must ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + usage_may = usage & may_mask; + + if( ( ( crt->key_usage & may_mask ) | usage_may ) != usage_may ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + return( 0 ); +} +#endif + +#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) +int mbedtls_x509_crt_check_extended_key_usage( const mbedtls_x509_crt *crt, + const char *usage_oid, + size_t usage_len ) +{ + const mbedtls_x509_sequence *cur; + + /* Extension is not mandatory, absent means no restriction */ + if( ( crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE ) == 0 ) + return( 0 ); + + /* + * Look for the requested usage (or wildcard ANY) in our list + */ + for( cur = &crt->ext_key_usage; cur != NULL; cur = cur->next ) + { + const mbedtls_x509_buf *cur_oid = &cur->buf; + + if( cur_oid->len == usage_len && + memcmp( cur_oid->p, usage_oid, usage_len ) == 0 ) + { + return( 0 ); + } + + if( MBEDTLS_OID_CMP( MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE, cur_oid ) == 0 ) + return( 0 ); + } + + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); +} +#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */ + +#if defined(MBEDTLS_X509_CRL_PARSE_C) +/* + * Return 1 if the certificate is revoked, or 0 otherwise. + */ +int mbedtls_x509_crt_is_revoked( const mbedtls_x509_crt *crt, const mbedtls_x509_crl *crl ) +{ + const mbedtls_x509_crl_entry *cur = &crl->entry; + + while( cur != NULL && cur->serial.len != 0 ) + { + if( crt->serial.len == cur->serial.len && + memcmp( crt->serial.p, cur->serial.p, crt->serial.len ) == 0 ) + { + return( 1 ); + } + + cur = cur->next; + } + + return( 0 ); +} + +/* + * Check that the given certificate is not revoked according to the CRL. + * Skip validation if no CRL for the given CA is present. + */ +static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca, + mbedtls_x509_crl *crl_list, + const mbedtls_x509_crt_profile *profile ) +{ + int flags = 0; + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; + const mbedtls_md_info_t *md_info; + + if( ca == NULL ) + return( flags ); + + while( crl_list != NULL ) + { + if( crl_list->version == 0 || + x509_name_cmp( &crl_list->issuer, &ca->subject ) != 0 ) + { + crl_list = crl_list->next; + continue; + } + + /* + * Check if the CA is configured to sign CRLs + */ +#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) + if( mbedtls_x509_crt_check_key_usage( ca, + MBEDTLS_X509_KU_CRL_SIGN ) != 0 ) + { + flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; + break; + } +#endif + + /* + * Check if CRL is correctly signed by the trusted CA + */ + if( x509_profile_check_md_alg( profile, crl_list->sig_md ) != 0 ) + flags |= MBEDTLS_X509_BADCRL_BAD_MD; + + if( x509_profile_check_pk_alg( profile, crl_list->sig_pk ) != 0 ) + flags |= MBEDTLS_X509_BADCRL_BAD_PK; + + md_info = mbedtls_md_info_from_type( crl_list->sig_md ); + if( mbedtls_md( md_info, crl_list->tbs.p, crl_list->tbs.len, hash ) != 0 ) + { + /* Note: this can't happen except after an internal error */ + flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; + break; + } + + if( x509_profile_check_key( profile, &ca->pk ) != 0 ) + flags |= MBEDTLS_X509_BADCERT_BAD_KEY; + + if( mbedtls_pk_verify_ext( crl_list->sig_pk, crl_list->sig_opts, &ca->pk, + crl_list->sig_md, hash, mbedtls_md_get_size( md_info ), + crl_list->sig.p, crl_list->sig.len ) != 0 ) + { + flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; + break; + } + + /* + * Check for validity of CRL (Do not drop out) + */ + if( mbedtls_x509_time_is_past( &crl_list->next_update ) ) + flags |= MBEDTLS_X509_BADCRL_EXPIRED; + + if( mbedtls_x509_time_is_future( &crl_list->this_update ) ) + flags |= MBEDTLS_X509_BADCRL_FUTURE; + + /* + * Check if certificate is revoked + */ + if( mbedtls_x509_crt_is_revoked( crt, crl_list ) ) + { + flags |= MBEDTLS_X509_BADCERT_REVOKED; + break; + } + + crl_list = crl_list->next; + } + + return( flags ); +} +#endif /* MBEDTLS_X509_CRL_PARSE_C */ + +/* + * Check the signature of a certificate by its parent + */ +static int x509_crt_check_signature( const mbedtls_x509_crt *child, + mbedtls_x509_crt *parent, + mbedtls_x509_crt_restart_ctx *rs_ctx ) +{ + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; + size_t hash_len; +#if !defined(MBEDTLS_USE_PSA_CRYPTO) + const mbedtls_md_info_t *md_info; + md_info = mbedtls_md_info_from_type( child->sig_md ); + hash_len = mbedtls_md_get_size( md_info ); + + /* Note: hash errors can happen only after an internal error */ + if( mbedtls_md( md_info, child->tbs.p, child->tbs.len, hash ) != 0 ) + return( -1 ); +#else + psa_hash_operation_t hash_operation = PSA_HASH_OPERATION_INIT; + psa_algorithm_t hash_alg = mbedtls_psa_translate_md( child->sig_md ); + + if( psa_hash_setup( &hash_operation, hash_alg ) != PSA_SUCCESS ) + return( -1 ); + + if( psa_hash_update( &hash_operation, child->tbs.p, child->tbs.len ) + != PSA_SUCCESS ) + { + return( -1 ); + } + + if( psa_hash_finish( &hash_operation, hash, sizeof( hash ), &hash_len ) + != PSA_SUCCESS ) + { + return( -1 ); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + /* Skip expensive computation on obvious mismatch */ + if( ! mbedtls_pk_can_do( &parent->pk, child->sig_pk ) ) + return( -1 ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && child->sig_pk == MBEDTLS_PK_ECDSA ) + { + return( mbedtls_pk_verify_restartable( &parent->pk, + child->sig_md, hash, hash_len, + child->sig.p, child->sig.len, &rs_ctx->pk ) ); + } +#else + (void) rs_ctx; +#endif + + return( mbedtls_pk_verify_ext( child->sig_pk, child->sig_opts, &parent->pk, + child->sig_md, hash, hash_len, + child->sig.p, child->sig.len ) ); +} + +/* + * Check if 'parent' is a suitable parent (signing CA) for 'child'. + * Return 0 if yes, -1 if not. + * + * top means parent is a locally-trusted certificate + */ +static int x509_crt_check_parent( const mbedtls_x509_crt *child, + const mbedtls_x509_crt *parent, + int top ) +{ + int need_ca_bit; + + /* Parent must be the issuer */ + if( x509_name_cmp( &child->issuer, &parent->subject ) != 0 ) + return( -1 ); + + /* Parent must have the basicConstraints CA bit set as a general rule */ + need_ca_bit = 1; + + /* Exception: v1/v2 certificates that are locally trusted. */ + if( top && parent->version < 3 ) + need_ca_bit = 0; + + if( need_ca_bit && ! parent->ca_istrue ) + return( -1 ); + +#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) + if( need_ca_bit && + mbedtls_x509_crt_check_key_usage( parent, MBEDTLS_X509_KU_KEY_CERT_SIGN ) != 0 ) + { + return( -1 ); + } +#endif + + return( 0 ); +} + +/* + * Find a suitable parent for child in candidates, or return NULL. + * + * Here suitable is defined as: + * 1. subject name matches child's issuer + * 2. if necessary, the CA bit is set and key usage allows signing certs + * 3. for trusted roots, the signature is correct + * (for intermediates, the signature is checked and the result reported) + * 4. pathlen constraints are satisfied + * + * If there's a suitable candidate which is also time-valid, return the first + * such. Otherwise, return the first suitable candidate (or NULL if there is + * none). + * + * The rationale for this rule is that someone could have a list of trusted + * roots with two versions on the same root with different validity periods. + * (At least one user reported having such a list and wanted it to just work.) + * The reason we don't just require time-validity is that generally there is + * only one version, and if it's expired we want the flags to state that + * rather than NOT_TRUSTED, as would be the case if we required it here. + * + * The rationale for rule 3 (signature for trusted roots) is that users might + * have two versions of the same CA with different keys in their list, and the + * way we select the correct one is by checking the signature (as we don't + * rely on key identifier extensions). (This is one way users might choose to + * handle key rollover, another relies on self-issued certs, see [SIRO].) + * + * Arguments: + * - [in] child: certificate for which we're looking for a parent + * - [in] candidates: chained list of potential parents + * - [out] r_parent: parent found (or NULL) + * - [out] r_signature_is_good: 1 if child signature by parent is valid, or 0 + * - [in] top: 1 if candidates consists of trusted roots, ie we're at the top + * of the chain, 0 otherwise + * - [in] path_cnt: number of intermediates seen so far + * - [in] self_cnt: number of self-signed intermediates seen so far + * (will never be greater than path_cnt) + * - [in-out] rs_ctx: context for restarting operations + * + * Return value: + * - 0 on success + * - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise + */ +static int x509_crt_find_parent_in( + mbedtls_x509_crt *child, + mbedtls_x509_crt *candidates, + mbedtls_x509_crt **r_parent, + int *r_signature_is_good, + int top, + unsigned path_cnt, + unsigned self_cnt, + mbedtls_x509_crt_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_x509_crt *parent, *fallback_parent; + int signature_is_good = 0, fallback_signature_is_good; + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /* did we have something in progress? */ + if( rs_ctx != NULL && rs_ctx->parent != NULL ) + { + /* restore saved state */ + parent = rs_ctx->parent; + fallback_parent = rs_ctx->fallback_parent; + fallback_signature_is_good = rs_ctx->fallback_signature_is_good; + + /* clear saved state */ + rs_ctx->parent = NULL; + rs_ctx->fallback_parent = NULL; + rs_ctx->fallback_signature_is_good = 0; + + /* resume where we left */ + goto check_signature; + } +#endif + + fallback_parent = NULL; + fallback_signature_is_good = 0; + + for( parent = candidates; parent != NULL; parent = parent->next ) + { + /* basic parenting skills (name, CA bit, key usage) */ + if( x509_crt_check_parent( child, parent, top ) != 0 ) + continue; + + /* +1 because stored max_pathlen is 1 higher that the actual value */ + if( parent->max_pathlen > 0 && + (size_t) parent->max_pathlen < 1 + path_cnt - self_cnt ) + { + continue; + } + + /* Signature */ +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +check_signature: +#endif + ret = x509_crt_check_signature( child, parent, rs_ctx ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + { + /* save state */ + rs_ctx->parent = parent; + rs_ctx->fallback_parent = fallback_parent; + rs_ctx->fallback_signature_is_good = fallback_signature_is_good; + + return( ret ); + } +#else + (void) ret; +#endif + + signature_is_good = ret == 0; + if( top && ! signature_is_good ) + continue; + + /* optional time check */ + if( mbedtls_x509_time_is_past( &parent->valid_to ) || + mbedtls_x509_time_is_future( &parent->valid_from ) ) + { + if( fallback_parent == NULL ) + { + fallback_parent = parent; + fallback_signature_is_good = signature_is_good; + } + + continue; + } + + *r_parent = parent; + *r_signature_is_good = signature_is_good; + + break; + } + + if( parent == NULL ) + { + *r_parent = fallback_parent; + *r_signature_is_good = fallback_signature_is_good; + } + + return( 0 ); +} + +/* + * Find a parent in trusted CAs or the provided chain, or return NULL. + * + * Searches in trusted CAs first, and return the first suitable parent found + * (see find_parent_in() for definition of suitable). + * + * Arguments: + * - [in] child: certificate for which we're looking for a parent, followed + * by a chain of possible intermediates + * - [in] trust_ca: list of locally trusted certificates + * - [out] parent: parent found (or NULL) + * - [out] parent_is_trusted: 1 if returned `parent` is trusted, or 0 + * - [out] signature_is_good: 1 if child signature by parent is valid, or 0 + * - [in] path_cnt: number of links in the chain so far (EE -> ... -> child) + * - [in] self_cnt: number of self-signed certs in the chain so far + * (will always be no greater than path_cnt) + * - [in-out] rs_ctx: context for restarting operations + * + * Return value: + * - 0 on success + * - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise + */ +static int x509_crt_find_parent( + mbedtls_x509_crt *child, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crt **parent, + int *parent_is_trusted, + int *signature_is_good, + unsigned path_cnt, + unsigned self_cnt, + mbedtls_x509_crt_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_x509_crt *search_list; + + *parent_is_trusted = 1; + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /* restore then clear saved state if we have some stored */ + if( rs_ctx != NULL && rs_ctx->parent_is_trusted != -1 ) + { + *parent_is_trusted = rs_ctx->parent_is_trusted; + rs_ctx->parent_is_trusted = -1; + } +#endif + + while( 1 ) { + search_list = *parent_is_trusted ? trust_ca : child->next; + + ret = x509_crt_find_parent_in( child, search_list, + parent, signature_is_good, + *parent_is_trusted, + path_cnt, self_cnt, rs_ctx ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + { + /* save state */ + rs_ctx->parent_is_trusted = *parent_is_trusted; + return( ret ); + } +#else + (void) ret; +#endif + + /* stop here if found or already in second iteration */ + if( *parent != NULL || *parent_is_trusted == 0 ) + break; + + /* prepare second iteration */ + *parent_is_trusted = 0; + } + + /* extra precaution against mistakes in the caller */ + if( *parent == NULL ) + { + *parent_is_trusted = 0; + *signature_is_good = 0; + } + + return( 0 ); +} + +/* + * Check if an end-entity certificate is locally trusted + * + * Currently we require such certificates to be self-signed (actually only + * check for self-issued as self-signatures are not checked) + */ +static int x509_crt_check_ee_locally_trusted( + mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca ) +{ + mbedtls_x509_crt *cur; + + /* must be self-issued */ + if( x509_name_cmp( &crt->issuer, &crt->subject ) != 0 ) + return( -1 ); + + /* look for an exact match with trusted cert */ + for( cur = trust_ca; cur != NULL; cur = cur->next ) + { + if( crt->raw.len == cur->raw.len && + memcmp( crt->raw.p, cur->raw.p, crt->raw.len ) == 0 ) + { + return( 0 ); + } + } + + /* too bad */ + return( -1 ); +} + +/* + * Build and verify a certificate chain + * + * Given a peer-provided list of certificates EE, C1, ..., Cn and + * a list of trusted certs R1, ... Rp, try to build and verify a chain + * EE, Ci1, ... Ciq [, Rj] + * such that every cert in the chain is a child of the next one, + * jumping to a trusted root as early as possible. + * + * Verify that chain and return it with flags for all issues found. + * + * Special cases: + * - EE == Rj -> return a one-element list containing it + * - EE, Ci1, ..., Ciq cannot be continued with a trusted root + * -> return that chain with NOT_TRUSTED set on Ciq + * + * Tests for (aspects of) this function should include at least: + * - trusted EE + * - EE -> trusted root + * - EE -> intermediate CA -> trusted root + * - if relevant: EE untrusted + * - if relevant: EE -> intermediate, untrusted + * with the aspect under test checked at each relevant level (EE, int, root). + * For some aspects longer chains are required, but usually length 2 is + * enough (but length 1 is not in general). + * + * Arguments: + * - [in] crt: the cert list EE, C1, ..., Cn + * - [in] trust_ca: the trusted list R1, ..., Rp + * - [in] ca_crl, profile: as in verify_with_profile() + * - [out] ver_chain: the built and verified chain + * Only valid when return value is 0, may contain garbage otherwise! + * Restart note: need not be the same when calling again to resume. + * - [in-out] rs_ctx: context for restarting operations + * + * Return value: + * - non-zero if the chain could not be fully built and examined + * - 0 is the chain was successfully built and examined, + * even if it was found to be invalid + */ +static int x509_crt_verify_chain( + mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + mbedtls_x509_crt_ca_cb_t f_ca_cb, + void *p_ca_cb, + const mbedtls_x509_crt_profile *profile, + mbedtls_x509_crt_verify_chain *ver_chain, + mbedtls_x509_crt_restart_ctx *rs_ctx ) +{ + /* Don't initialize any of those variables here, so that the compiler can + * catch potential issues with jumping ahead when restarting */ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + uint32_t *flags; + mbedtls_x509_crt_verify_chain_item *cur; + mbedtls_x509_crt *child; + mbedtls_x509_crt *parent; + int parent_is_trusted; + int child_is_trusted; + int signature_is_good; + unsigned self_cnt; + mbedtls_x509_crt *cur_trust_ca = NULL; + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /* resume if we had an operation in progress */ + if( rs_ctx != NULL && rs_ctx->in_progress == x509_crt_rs_find_parent ) + { + /* restore saved state */ + *ver_chain = rs_ctx->ver_chain; /* struct copy */ + self_cnt = rs_ctx->self_cnt; + + /* restore derived state */ + cur = &ver_chain->items[ver_chain->len - 1]; + child = cur->crt; + flags = &cur->flags; + + goto find_parent; + } +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + + child = crt; + self_cnt = 0; + parent_is_trusted = 0; + child_is_trusted = 0; + + while( 1 ) { + /* Add certificate to the verification chain */ + cur = &ver_chain->items[ver_chain->len]; + cur->crt = child; + cur->flags = 0; + ver_chain->len++; + flags = &cur->flags; + + /* Check time-validity (all certificates) */ + if( mbedtls_x509_time_is_past( &child->valid_to ) ) + *flags |= MBEDTLS_X509_BADCERT_EXPIRED; + + if( mbedtls_x509_time_is_future( &child->valid_from ) ) + *flags |= MBEDTLS_X509_BADCERT_FUTURE; + + /* Stop here for trusted roots (but not for trusted EE certs) */ + if( child_is_trusted ) + return( 0 ); + + /* Check signature algorithm: MD & PK algs */ + if( x509_profile_check_md_alg( profile, child->sig_md ) != 0 ) + *flags |= MBEDTLS_X509_BADCERT_BAD_MD; + + if( x509_profile_check_pk_alg( profile, child->sig_pk ) != 0 ) + *flags |= MBEDTLS_X509_BADCERT_BAD_PK; + + /* Special case: EE certs that are locally trusted */ + if( ver_chain->len == 1 && + x509_crt_check_ee_locally_trusted( child, trust_ca ) == 0 ) + { + return( 0 ); + } + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +find_parent: +#endif + + /* Obtain list of potential trusted signers from CA callback, + * or use statically provided list. */ +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + if( f_ca_cb != NULL ) + { + mbedtls_x509_crt_free( ver_chain->trust_ca_cb_result ); + mbedtls_free( ver_chain->trust_ca_cb_result ); + ver_chain->trust_ca_cb_result = NULL; + + ret = f_ca_cb( p_ca_cb, child, &ver_chain->trust_ca_cb_result ); + if( ret != 0 ) + return( MBEDTLS_ERR_X509_FATAL_ERROR ); + + cur_trust_ca = ver_chain->trust_ca_cb_result; + } + else +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ + { + ((void) f_ca_cb); + ((void) p_ca_cb); + cur_trust_ca = trust_ca; + } + + /* Look for a parent in trusted CAs or up the chain */ + ret = x509_crt_find_parent( child, cur_trust_ca, &parent, + &parent_is_trusted, &signature_is_good, + ver_chain->len - 1, self_cnt, rs_ctx ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + { + /* save state */ + rs_ctx->in_progress = x509_crt_rs_find_parent; + rs_ctx->self_cnt = self_cnt; + rs_ctx->ver_chain = *ver_chain; /* struct copy */ + + return( ret ); + } +#else + (void) ret; +#endif + + /* No parent? We're done here */ + if( parent == NULL ) + { + *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; + return( 0 ); + } + + /* Count intermediate self-issued (not necessarily self-signed) certs. + * These can occur with some strategies for key rollover, see [SIRO], + * and should be excluded from max_pathlen checks. */ + if( ver_chain->len != 1 && + x509_name_cmp( &child->issuer, &child->subject ) == 0 ) + { + self_cnt++; + } + + /* path_cnt is 0 for the first intermediate CA, + * and if parent is trusted it's not an intermediate CA */ + if( ! parent_is_trusted && + ver_chain->len > MBEDTLS_X509_MAX_INTERMEDIATE_CA ) + { + /* return immediately to avoid overflow the chain array */ + return( MBEDTLS_ERR_X509_FATAL_ERROR ); + } + + /* signature was checked while searching parent */ + if( ! signature_is_good ) + *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; + + /* check size of signing key */ + if( x509_profile_check_key( profile, &parent->pk ) != 0 ) + *flags |= MBEDTLS_X509_BADCERT_BAD_KEY; + +#if defined(MBEDTLS_X509_CRL_PARSE_C) + /* Check trusted CA's CRL for the given crt */ + *flags |= x509_crt_verifycrl( child, parent, ca_crl, profile ); +#else + (void) ca_crl; +#endif + + /* prepare for next iteration */ + child = parent; + parent = NULL; + child_is_trusted = parent_is_trusted; + signature_is_good = 0; + } +} + +/* + * Check for CN match + */ +static int x509_crt_check_cn( const mbedtls_x509_buf *name, + const char *cn, size_t cn_len ) +{ + /* try exact match */ + if( name->len == cn_len && + x509_memcasecmp( cn, name->p, cn_len ) == 0 ) + { + return( 0 ); + } + + /* try wildcard match */ + if( x509_check_wildcard( cn, name ) == 0 ) + { + return( 0 ); + } + + return( -1 ); +} + +/* + * Check for SAN match, see RFC 5280 Section 4.2.1.6 + */ +static int x509_crt_check_san( const mbedtls_x509_buf *name, + const char *cn, size_t cn_len ) +{ + const unsigned char san_type = (unsigned char) name->tag & + MBEDTLS_ASN1_TAG_VALUE_MASK; + + /* dNSName */ + if( san_type == MBEDTLS_X509_SAN_DNS_NAME ) + return( x509_crt_check_cn( name, cn, cn_len ) ); + + /* (We may handle other types here later.) */ + + /* Unrecognized type */ + return( -1 ); +} + +/* + * Verify the requested CN - only call this if cn is not NULL! + */ +static void x509_crt_verify_name( const mbedtls_x509_crt *crt, + const char *cn, + uint32_t *flags ) +{ + const mbedtls_x509_name *name; + const mbedtls_x509_sequence *cur; + size_t cn_len = strlen( cn ); + + if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME ) + { + for( cur = &crt->subject_alt_names; cur != NULL; cur = cur->next ) + { + if( x509_crt_check_san( &cur->buf, cn, cn_len ) == 0 ) + break; + } + + if( cur == NULL ) + *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; + } + else + { + for( name = &crt->subject; name != NULL; name = name->next ) + { + if( MBEDTLS_OID_CMP( MBEDTLS_OID_AT_CN, &name->oid ) == 0 && + x509_crt_check_cn( &name->val, cn, cn_len ) == 0 ) + { + break; + } + } + + if( name == NULL ) + *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; + } +} + +/* + * Merge the flags for all certs in the chain, after calling callback + */ +static int x509_crt_merge_flags_with_cb( + uint32_t *flags, + const mbedtls_x509_crt_verify_chain *ver_chain, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned i; + uint32_t cur_flags; + const mbedtls_x509_crt_verify_chain_item *cur; + + for( i = ver_chain->len; i != 0; --i ) + { + cur = &ver_chain->items[i-1]; + cur_flags = cur->flags; + + if( NULL != f_vrfy ) + if( ( ret = f_vrfy( p_vrfy, cur->crt, (int) i-1, &cur_flags ) ) != 0 ) + return( ret ); + + *flags |= cur_flags; + } + + return( 0 ); +} + +/* + * Verify the certificate validity, with profile, restartable version + * + * This function: + * - checks the requested CN (if any) + * - checks the type and size of the EE cert's key, + * as that isn't done as part of chain building/verification currently + * - builds and verifies the chain + * - then calls the callback and merges the flags + * + * The parameters pairs `trust_ca`, `ca_crl` and `f_ca_cb`, `p_ca_cb` + * are mutually exclusive: If `f_ca_cb != NULL`, it will be used by the + * verification routine to search for trusted signers, and CRLs will + * be disabled. Otherwise, `trust_ca` will be used as the static list + * of trusted signers, and `ca_crl` will be use as the static list + * of CRLs. + */ +static int x509_crt_verify_restartable_ca_cb( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + mbedtls_x509_crt_ca_cb_t f_ca_cb, + void *p_ca_cb, + const mbedtls_x509_crt_profile *profile, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy, + mbedtls_x509_crt_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_pk_type_t pk_type; + mbedtls_x509_crt_verify_chain ver_chain; + uint32_t ee_flags; + + *flags = 0; + ee_flags = 0; + x509_crt_verify_chain_reset( &ver_chain ); + + if( profile == NULL ) + { + ret = MBEDTLS_ERR_X509_BAD_INPUT_DATA; + goto exit; + } + + /* check name if requested */ + if( cn != NULL ) + x509_crt_verify_name( crt, cn, &ee_flags ); + + /* Check the type and size of the key */ + pk_type = mbedtls_pk_get_type( &crt->pk ); + + if( x509_profile_check_pk_alg( profile, pk_type ) != 0 ) + ee_flags |= MBEDTLS_X509_BADCERT_BAD_PK; + + if( x509_profile_check_key( profile, &crt->pk ) != 0 ) + ee_flags |= MBEDTLS_X509_BADCERT_BAD_KEY; + + /* Check the chain */ + ret = x509_crt_verify_chain( crt, trust_ca, ca_crl, + f_ca_cb, p_ca_cb, profile, + &ver_chain, rs_ctx ); + + if( ret != 0 ) + goto exit; + + /* Merge end-entity flags */ + ver_chain.items[0].flags |= ee_flags; + + /* Build final flags, calling callback on the way if any */ + ret = x509_crt_merge_flags_with_cb( flags, &ver_chain, f_vrfy, p_vrfy ); + +exit: + +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + mbedtls_x509_crt_free( ver_chain.trust_ca_cb_result ); + mbedtls_free( ver_chain.trust_ca_cb_result ); + ver_chain.trust_ca_cb_result = NULL; +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) + mbedtls_x509_crt_restart_free( rs_ctx ); +#endif + + /* prevent misuse of the vrfy callback - VERIFY_FAILED would be ignored by + * the SSL module for authmode optional, but non-zero return from the + * callback means a fatal error so it shouldn't be ignored */ + if( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ) + ret = MBEDTLS_ERR_X509_FATAL_ERROR; + + if( ret != 0 ) + { + *flags = (uint32_t) -1; + return( ret ); + } + + if( *flags != 0 ) + return( MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ); + + return( 0 ); +} + + +/* + * Verify the certificate validity (default profile, not restartable) + */ +int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ) +{ + return( x509_crt_verify_restartable_ca_cb( crt, trust_ca, ca_crl, + NULL, NULL, + &mbedtls_x509_crt_profile_default, + cn, flags, + f_vrfy, p_vrfy, NULL ) ); +} + +/* + * Verify the certificate validity (user-chosen profile, not restartable) + */ +int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const mbedtls_x509_crt_profile *profile, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ) +{ + return( x509_crt_verify_restartable_ca_cb( crt, trust_ca, ca_crl, + NULL, NULL, + profile, cn, flags, + f_vrfy, p_vrfy, NULL ) ); +} + +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) +/* + * Verify the certificate validity (user-chosen profile, CA callback, + * not restartable). + */ +int mbedtls_x509_crt_verify_with_ca_cb( mbedtls_x509_crt *crt, + mbedtls_x509_crt_ca_cb_t f_ca_cb, + void *p_ca_cb, + const mbedtls_x509_crt_profile *profile, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ) +{ + return( x509_crt_verify_restartable_ca_cb( crt, NULL, NULL, + f_ca_cb, p_ca_cb, + profile, cn, flags, + f_vrfy, p_vrfy, NULL ) ); +} +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ + +int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const mbedtls_x509_crt_profile *profile, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy, + mbedtls_x509_crt_restart_ctx *rs_ctx ) +{ + return( x509_crt_verify_restartable_ca_cb( crt, trust_ca, ca_crl, + NULL, NULL, + profile, cn, flags, + f_vrfy, p_vrfy, rs_ctx ) ); +} + + +/* + * Initialize a certificate chain + */ +void mbedtls_x509_crt_init( mbedtls_x509_crt *crt ) +{ + memset( crt, 0, sizeof(mbedtls_x509_crt) ); +} + +/* + * Unallocate all certificate data + */ +void mbedtls_x509_crt_free( mbedtls_x509_crt *crt ) +{ + mbedtls_x509_crt *cert_cur = crt; + mbedtls_x509_crt *cert_prv; + mbedtls_x509_name *name_cur; + mbedtls_x509_name *name_prv; + mbedtls_x509_sequence *seq_cur; + mbedtls_x509_sequence *seq_prv; + + if( crt == NULL ) + return; + + do + { + mbedtls_pk_free( &cert_cur->pk ); + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + mbedtls_free( cert_cur->sig_opts ); +#endif + + name_cur = cert_cur->issuer.next; + while( name_cur != NULL ) + { + name_prv = name_cur; + name_cur = name_cur->next; + mbedtls_platform_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); + mbedtls_free( name_prv ); + } + + name_cur = cert_cur->subject.next; + while( name_cur != NULL ) + { + name_prv = name_cur; + name_cur = name_cur->next; + mbedtls_platform_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); + mbedtls_free( name_prv ); + } + + seq_cur = cert_cur->ext_key_usage.next; + while( seq_cur != NULL ) + { + seq_prv = seq_cur; + seq_cur = seq_cur->next; + mbedtls_platform_zeroize( seq_prv, + sizeof( mbedtls_x509_sequence ) ); + mbedtls_free( seq_prv ); + } + + seq_cur = cert_cur->subject_alt_names.next; + while( seq_cur != NULL ) + { + seq_prv = seq_cur; + seq_cur = seq_cur->next; + mbedtls_platform_zeroize( seq_prv, + sizeof( mbedtls_x509_sequence ) ); + mbedtls_free( seq_prv ); + } + + seq_cur = cert_cur->certificate_policies.next; + while( seq_cur != NULL ) + { + seq_prv = seq_cur; + seq_cur = seq_cur->next; + mbedtls_platform_zeroize( seq_prv, + sizeof( mbedtls_x509_sequence ) ); + mbedtls_free( seq_prv ); + } + + if( cert_cur->raw.p != NULL && cert_cur->own_buffer ) + { + mbedtls_platform_zeroize( cert_cur->raw.p, cert_cur->raw.len ); + mbedtls_free( cert_cur->raw.p ); + } + + cert_cur = cert_cur->next; + } + while( cert_cur != NULL ); + + cert_cur = crt; + do + { + cert_prv = cert_cur; + cert_cur = cert_cur->next; + + mbedtls_platform_zeroize( cert_prv, sizeof( mbedtls_x509_crt ) ); + if( cert_prv != crt ) + mbedtls_free( cert_prv ); + } + while( cert_cur != NULL ); +} + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +/* + * Initialize a restart context + */ +void mbedtls_x509_crt_restart_init( mbedtls_x509_crt_restart_ctx *ctx ) +{ + mbedtls_pk_restart_init( &ctx->pk ); + + ctx->parent = NULL; + ctx->fallback_parent = NULL; + ctx->fallback_signature_is_good = 0; + + ctx->parent_is_trusted = -1; + + ctx->in_progress = x509_crt_rs_none; + ctx->self_cnt = 0; + x509_crt_verify_chain_reset( &ctx->ver_chain ); +} + +/* + * Free the components of a restart context + */ +void mbedtls_x509_crt_restart_free( mbedtls_x509_crt_restart_ctx *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_pk_restart_free( &ctx->pk ); + mbedtls_x509_crt_restart_init( ctx ); +} +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + +#endif /* MBEDTLS_X509_CRT_PARSE_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/x509_csr.c b/Android/Level4/app/src/main/c/mbedtls/library/x509_csr.c new file mode 100644 index 0000000..5463f8a --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/x509_csr.c @@ -0,0 +1,414 @@ +/* + * X.509 Certificate Signing Request (CSR) parsing + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ +/* + * The ITU-T X.509 standard defines a certificate format for PKI. + * + * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) + * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) + * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) + * + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf + */ + +#include "common.h" + +#if defined(MBEDTLS_X509_CSR_PARSE_C) + +#include "mbedtls/x509_csr.h" +#include "mbedtls/error.h" +#include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_PEM_PARSE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_free free +#define mbedtls_calloc calloc +#define mbedtls_snprintf snprintf +#endif + +#if defined(MBEDTLS_FS_IO) || defined(EFIX64) || defined(EFI32) +#include +#endif + +/* + * Version ::= INTEGER { v1(0) } + */ +static int x509_csr_get_version( unsigned char **p, + const unsigned char *end, + int *ver ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + { + *ver = 0; + return( 0 ); + } + + return( MBEDTLS_ERR_X509_INVALID_VERSION + ret ); + } + + return( 0 ); +} + +/* + * Parse a CSR in DER format + */ +int mbedtls_x509_csr_parse_der( mbedtls_x509_csr *csr, + const unsigned char *buf, size_t buflen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + unsigned char *p, *end; + mbedtls_x509_buf sig_params; + + memset( &sig_params, 0, sizeof( mbedtls_x509_buf ) ); + + /* + * Check for valid input + */ + if( csr == NULL || buf == NULL || buflen == 0 ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + mbedtls_x509_csr_init( csr ); + + /* + * first copy the raw DER data + */ + p = mbedtls_calloc( 1, len = buflen ); + + if( p == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + memcpy( p, buf, buflen ); + + csr->raw.p = p; + csr->raw.len = len; + end = p + len; + + /* + * CertificationRequest ::= SEQUENCE { + * certificationRequestInfo CertificationRequestInfo, + * signatureAlgorithm AlgorithmIdentifier, + * signature BIT STRING + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT ); + } + + if( len != (size_t) ( end - p ) ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + + /* + * CertificationRequestInfo ::= SEQUENCE { + */ + csr->cri.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + end = p + len; + csr->cri.len = end - csr->cri.p; + + /* + * Version ::= INTEGER { v1(0) } + */ + if( ( ret = x509_csr_get_version( &p, end, &csr->version ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( ret ); + } + + if( csr->version != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERR_X509_UNKNOWN_VERSION ); + } + + csr->version++; + + /* + * subject Name + */ + csr->subject_raw.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + if( ( ret = mbedtls_x509_get_name( &p, p + len, &csr->subject ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( ret ); + } + + csr->subject_raw.len = p - csr->subject_raw.p; + + /* + * subjectPKInfo SubjectPublicKeyInfo + */ + if( ( ret = mbedtls_pk_parse_subpubkey( &p, end, &csr->pk ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( ret ); + } + + /* + * attributes [0] Attributes + * + * The list of possible attributes is open-ended, though RFC 2985 + * (PKCS#9) defines a few in section 5.4. We currently don't support any, + * so we just ignore them. This is a safe thing to do as the worst thing + * that could happen is that we issue a certificate that does not match + * the requester's expectations - this cannot cause a violation of our + * signature policies. + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + p += len; + + end = csr->raw.p + csr->raw.len; + + /* + * signatureAlgorithm AlgorithmIdentifier, + * signature BIT STRING + */ + if( ( ret = mbedtls_x509_get_alg( &p, end, &csr->sig_oid, &sig_params ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( ret ); + } + + if( ( ret = mbedtls_x509_get_sig_alg( &csr->sig_oid, &sig_params, + &csr->sig_md, &csr->sig_pk, + &csr->sig_opts ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG ); + } + + if( ( ret = mbedtls_x509_get_sig( &p, end, &csr->sig ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( ret ); + } + + if( p != end ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + + return( 0 ); +} + +/* + * Parse a CSR, allowing for PEM or raw DER encoding + */ +int mbedtls_x509_csr_parse( mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen ) +{ +#if defined(MBEDTLS_PEM_PARSE_C) + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t use_len; + mbedtls_pem_context pem; +#endif + + /* + * Check for valid input + */ + if( csr == NULL || buf == NULL || buflen == 0 ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_PEM_PARSE_C) + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( buf[buflen - 1] == '\0' ) + { + mbedtls_pem_init( &pem ); + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN CERTIFICATE REQUEST-----", + "-----END CERTIFICATE REQUEST-----", + buf, NULL, 0, &use_len ); + if( ret == MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN NEW CERTIFICATE REQUEST-----", + "-----END NEW CERTIFICATE REQUEST-----", + buf, NULL, 0, &use_len ); + } + + if( ret == 0 ) + { + /* + * Was PEM encoded, parse the result + */ + ret = mbedtls_x509_csr_parse_der( csr, pem.buf, pem.buflen ); + } + + mbedtls_pem_free( &pem ); + if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); + } +#endif /* MBEDTLS_PEM_PARSE_C */ + return( mbedtls_x509_csr_parse_der( csr, buf, buflen ) ); +} + +#if defined(MBEDTLS_FS_IO) +/* + * Load a CSR into the structure + */ +int mbedtls_x509_csr_parse_file( mbedtls_x509_csr *csr, const char *path ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n; + unsigned char *buf; + + if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = mbedtls_x509_csr_parse( csr, buf, n ); + + mbedtls_platform_zeroize( buf, n ); + mbedtls_free( buf ); + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + +#define BEFORE_COLON 14 +#define BC "14" +/* + * Return an informational string about the CSR. + */ +int mbedtls_x509_csr_info( char *buf, size_t size, const char *prefix, + const mbedtls_x509_csr *csr ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n; + char *p; + char key_size_str[BEFORE_COLON]; + + p = buf; + n = size; + + ret = mbedtls_snprintf( p, n, "%sCSR version : %d", + prefix, csr->version ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%ssubject name : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + ret = mbedtls_x509_dn_gets( p, n, &csr->subject ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%ssigned using : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_x509_sig_alg_gets( p, n, &csr->sig_oid, csr->sig_pk, csr->sig_md, + csr->sig_opts ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( ( ret = mbedtls_x509_key_size_helper( key_size_str, BEFORE_COLON, + mbedtls_pk_get_name( &csr->pk ) ) ) != 0 ) + { + return( ret ); + } + + ret = mbedtls_snprintf( p, n, "\n%s%-" BC "s: %d bits\n", prefix, key_size_str, + (int) mbedtls_pk_get_bitlen( &csr->pk ) ); + MBEDTLS_X509_SAFE_SNPRINTF; + + return( (int) ( size - n ) ); +} + +/* + * Initialize a CSR + */ +void mbedtls_x509_csr_init( mbedtls_x509_csr *csr ) +{ + memset( csr, 0, sizeof(mbedtls_x509_csr) ); +} + +/* + * Unallocate all CSR data + */ +void mbedtls_x509_csr_free( mbedtls_x509_csr *csr ) +{ + mbedtls_x509_name *name_cur; + mbedtls_x509_name *name_prv; + + if( csr == NULL ) + return; + + mbedtls_pk_free( &csr->pk ); + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + mbedtls_free( csr->sig_opts ); +#endif + + name_cur = csr->subject.next; + while( name_cur != NULL ) + { + name_prv = name_cur; + name_cur = name_cur->next; + mbedtls_platform_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); + mbedtls_free( name_prv ); + } + + if( csr->raw.p != NULL ) + { + mbedtls_platform_zeroize( csr->raw.p, csr->raw.len ); + mbedtls_free( csr->raw.p ); + } + + mbedtls_platform_zeroize( csr, sizeof( mbedtls_x509_csr ) ); +} + +#endif /* MBEDTLS_X509_CSR_PARSE_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/x509write_crt.c b/Android/Level4/app/src/main/c/mbedtls/library/x509write_crt.c new file mode 100644 index 0000000..32c6550 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/x509write_crt.c @@ -0,0 +1,544 @@ +/* + * X.509 certificate writing + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ +/* + * References: + * - certificates: RFC 5280, updated by RFC 6818 + * - CSRs: PKCS#10 v1.7 aka RFC 2986 + * - attributes: PKCS#9 v2.0 aka RFC 2985 + */ + +#include "common.h" + +#if defined(MBEDTLS_X509_CRT_WRITE_C) + +#include "mbedtls/x509_crt.h" +#include "mbedtls/asn1write.h" +#include "mbedtls/error.h" +#include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/sha1.h" + +#include + +#if defined(MBEDTLS_PEM_WRITE_C) +#include "mbedtls/pem.h" +#endif /* MBEDTLS_PEM_WRITE_C */ + +void mbedtls_x509write_crt_init( mbedtls_x509write_cert *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_x509write_cert ) ); + + mbedtls_mpi_init( &ctx->serial ); + ctx->version = MBEDTLS_X509_CRT_VERSION_3; +} + +void mbedtls_x509write_crt_free( mbedtls_x509write_cert *ctx ) +{ + mbedtls_mpi_free( &ctx->serial ); + + mbedtls_asn1_free_named_data_list( &ctx->subject ); + mbedtls_asn1_free_named_data_list( &ctx->issuer ); + mbedtls_asn1_free_named_data_list( &ctx->extensions ); + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_x509write_cert ) ); +} + +void mbedtls_x509write_crt_set_version( mbedtls_x509write_cert *ctx, + int version ) +{ + ctx->version = version; +} + +void mbedtls_x509write_crt_set_md_alg( mbedtls_x509write_cert *ctx, + mbedtls_md_type_t md_alg ) +{ + ctx->md_alg = md_alg; +} + +void mbedtls_x509write_crt_set_subject_key( mbedtls_x509write_cert *ctx, + mbedtls_pk_context *key ) +{ + ctx->subject_key = key; +} + +void mbedtls_x509write_crt_set_issuer_key( mbedtls_x509write_cert *ctx, + mbedtls_pk_context *key ) +{ + ctx->issuer_key = key; +} + +int mbedtls_x509write_crt_set_subject_name( mbedtls_x509write_cert *ctx, + const char *subject_name ) +{ + return mbedtls_x509_string_to_names( &ctx->subject, subject_name ); +} + +int mbedtls_x509write_crt_set_issuer_name( mbedtls_x509write_cert *ctx, + const char *issuer_name ) +{ + return mbedtls_x509_string_to_names( &ctx->issuer, issuer_name ); +} + +int mbedtls_x509write_crt_set_serial( mbedtls_x509write_cert *ctx, + const mbedtls_mpi *serial ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ( ret = mbedtls_mpi_copy( &ctx->serial, serial ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +int mbedtls_x509write_crt_set_validity( mbedtls_x509write_cert *ctx, + const char *not_before, + const char *not_after ) +{ + if( strlen( not_before ) != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 || + strlen( not_after ) != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 ) + { + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + } + strncpy( ctx->not_before, not_before, MBEDTLS_X509_RFC5280_UTC_TIME_LEN ); + strncpy( ctx->not_after , not_after , MBEDTLS_X509_RFC5280_UTC_TIME_LEN ); + ctx->not_before[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z'; + ctx->not_after[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z'; + + return( 0 ); +} + +int mbedtls_x509write_crt_set_extension( mbedtls_x509write_cert *ctx, + const char *oid, size_t oid_len, + int critical, + const unsigned char *val, size_t val_len ) +{ + return( mbedtls_x509_set_extension( &ctx->extensions, oid, oid_len, + critical, val, val_len ) ); +} + +int mbedtls_x509write_crt_set_basic_constraints( mbedtls_x509write_cert *ctx, + int is_ca, int max_pathlen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char buf[9]; + unsigned char *c = buf + sizeof(buf); + size_t len = 0; + + memset( buf, 0, sizeof(buf) ); + + if( is_ca && max_pathlen > 127 ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + if( is_ca ) + { + if( max_pathlen >= 0 ) + { + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, + max_pathlen ) ); + } + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_bool( &c, buf, 1 ) ); + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + return( + mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_BASIC_CONSTRAINTS, + MBEDTLS_OID_SIZE( MBEDTLS_OID_BASIC_CONSTRAINTS ), + 0, buf + sizeof(buf) - len, len ) ); +} + +#if defined(MBEDTLS_SHA1_C) +int mbedtls_x509write_crt_set_subject_key_identifier( mbedtls_x509write_cert *ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */ + unsigned char *c = buf + sizeof(buf); + size_t len = 0; + + memset( buf, 0, sizeof(buf) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_pk_write_pubkey( &c, buf, ctx->subject_key ) ); + + ret = mbedtls_sha1_ret( buf + sizeof( buf ) - len, len, + buf + sizeof( buf ) - 20 ); + if( ret != 0 ) + return( ret ); + c = buf + sizeof( buf ) - 20; + len = 20; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_OCTET_STRING ) ); + + return mbedtls_x509write_crt_set_extension( ctx, + MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER, + MBEDTLS_OID_SIZE( MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER ), + 0, buf + sizeof(buf) - len, len ); +} + +int mbedtls_x509write_crt_set_authority_key_identifier( mbedtls_x509write_cert *ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */ + unsigned char *c = buf + sizeof( buf ); + size_t len = 0; + + memset( buf, 0, sizeof(buf) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_pk_write_pubkey( &c, buf, ctx->issuer_key ) ); + + ret = mbedtls_sha1_ret( buf + sizeof( buf ) - len, len, + buf + sizeof( buf ) - 20 ); + if( ret != 0 ) + return( ret ); + c = buf + sizeof( buf ) - 20; + len = 20; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | 0 ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + return mbedtls_x509write_crt_set_extension( + ctx, MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER, + MBEDTLS_OID_SIZE( MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER ), + 0, buf + sizeof( buf ) - len, len ); +} +#endif /* MBEDTLS_SHA1_C */ + +int mbedtls_x509write_crt_set_key_usage( mbedtls_x509write_cert *ctx, + unsigned int key_usage ) +{ + unsigned char buf[5], ku[2]; + unsigned char *c; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const unsigned int allowed_bits = MBEDTLS_X509_KU_DIGITAL_SIGNATURE | + MBEDTLS_X509_KU_NON_REPUDIATION | + MBEDTLS_X509_KU_KEY_ENCIPHERMENT | + MBEDTLS_X509_KU_DATA_ENCIPHERMENT | + MBEDTLS_X509_KU_KEY_AGREEMENT | + MBEDTLS_X509_KU_KEY_CERT_SIGN | + MBEDTLS_X509_KU_CRL_SIGN | + MBEDTLS_X509_KU_ENCIPHER_ONLY | + MBEDTLS_X509_KU_DECIPHER_ONLY; + + /* Check that nothing other than the allowed flags is set */ + if( ( key_usage & ~allowed_bits ) != 0 ) + return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE ); + + c = buf + 5; + ku[0] = (unsigned char)( key_usage ); + ku[1] = (unsigned char)( key_usage >> 8 ); + ret = mbedtls_asn1_write_named_bitstring( &c, buf, ku, 9 ); + + if( ret < 0 ) + return( ret ); + else if( ret < 3 || ret > 5 ) + return( MBEDTLS_ERR_X509_INVALID_FORMAT ); + + ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_KEY_USAGE, + MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ), + 1, c, (size_t)ret ); + if( ret != 0 ) + return( ret ); + + return( 0 ); +} + +int mbedtls_x509write_crt_set_ns_cert_type( mbedtls_x509write_cert *ctx, + unsigned char ns_cert_type ) +{ + unsigned char buf[4]; + unsigned char *c; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + c = buf + 4; + + ret = mbedtls_asn1_write_named_bitstring( &c, buf, &ns_cert_type, 8 ); + if( ret < 3 || ret > 4 ) + return( ret ); + + ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE, + MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ), + 0, c, (size_t)ret ); + if( ret != 0 ) + return( ret ); + + return( 0 ); +} + +static int x509_write_time( unsigned char **p, unsigned char *start, + const char *t, size_t size ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + /* + * write MBEDTLS_ASN1_UTC_TIME if year < 2050 (2 bytes shorter) + */ + if( t[0] == '2' && t[1] == '0' && t[2] < '5' ) + { + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, + (const unsigned char *) t + 2, + size - 2 ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, + MBEDTLS_ASN1_UTC_TIME ) ); + } + else + { + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, + (const unsigned char *) t, + size ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, + MBEDTLS_ASN1_GENERALIZED_TIME ) ); + } + + return( (int) len ); +} + +int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx, + unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const char *sig_oid; + size_t sig_oid_len = 0; + unsigned char *c, *c2; + unsigned char hash[64]; + unsigned char sig[MBEDTLS_PK_SIGNATURE_MAX_SIZE]; + size_t sub_len = 0, pub_len = 0, sig_and_oid_len = 0, sig_len; + size_t len = 0; + mbedtls_pk_type_t pk_alg; + + /* + * Prepare data to be signed at the end of the target buffer + */ + c = buf + size; + + /* Signature algorithm needed in TBS, and later for actual signature */ + + /* There's no direct way of extracting a signature algorithm + * (represented as an element of mbedtls_pk_type_t) from a PK instance. */ + if( mbedtls_pk_can_do( ctx->issuer_key, MBEDTLS_PK_RSA ) ) + pk_alg = MBEDTLS_PK_RSA; + else if( mbedtls_pk_can_do( ctx->issuer_key, MBEDTLS_PK_ECDSA ) ) + pk_alg = MBEDTLS_PK_ECDSA; + else + return( MBEDTLS_ERR_X509_INVALID_ALG ); + + if( ( ret = mbedtls_oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg, + &sig_oid, &sig_oid_len ) ) != 0 ) + { + return( ret ); + } + + /* + * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension + */ + + /* Only for v3 */ + if( ctx->version == MBEDTLS_X509_CRT_VERSION_3 ) + { + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_x509_write_extensions( &c, + buf, ctx->extensions ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( &c, buf, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | + MBEDTLS_ASN1_CONSTRUCTED | 3 ) ); + } + + /* + * SubjectPublicKeyInfo + */ + MBEDTLS_ASN1_CHK_ADD( pub_len, + mbedtls_pk_write_pubkey_der( ctx->subject_key, + buf, c - buf ) ); + c -= pub_len; + len += pub_len; + + /* + * Subject ::= Name + */ + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_x509_write_names( &c, buf, + ctx->subject ) ); + + /* + * Validity ::= SEQUENCE { + * notBefore Time, + * notAfter Time } + */ + sub_len = 0; + + MBEDTLS_ASN1_CHK_ADD( sub_len, + x509_write_time( &c, buf, ctx->not_after, + MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) ); + + MBEDTLS_ASN1_CHK_ADD( sub_len, + x509_write_time( &c, buf, ctx->not_before, + MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) ); + + len += sub_len; + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, sub_len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + /* + * Issuer ::= Name + */ + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, buf, + ctx->issuer ) ); + + /* + * Signature ::= AlgorithmIdentifier + */ + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_algorithm_identifier( &c, buf, + sig_oid, strlen( sig_oid ), 0 ) ); + + /* + * Serial ::= INTEGER + */ + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, + &ctx->serial ) ); + + /* + * Version ::= INTEGER { v1(0), v2(1), v3(2) } + */ + + /* Can be omitted for v1 */ + if( ctx->version != MBEDTLS_X509_CRT_VERSION_1 ) + { + sub_len = 0; + MBEDTLS_ASN1_CHK_ADD( sub_len, + mbedtls_asn1_write_int( &c, buf, ctx->version ) ); + len += sub_len; + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_len( &c, buf, sub_len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( &c, buf, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | + MBEDTLS_ASN1_CONSTRUCTED | 0 ) ); + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + /* + * Make signature + */ + + /* Compute hash of CRT. */ + if( ( ret = mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, + len, hash ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = mbedtls_pk_sign( ctx->issuer_key, ctx->md_alg, + hash, 0, sig, &sig_len, + f_rng, p_rng ) ) != 0 ) + { + return( ret ); + } + + /* Move CRT to the front of the buffer to have space + * for the signature. */ + memmove( buf, c, len ); + c = buf + len; + + /* Add signature at the end of the buffer, + * making sure that it doesn't underflow + * into the CRT buffer. */ + c2 = buf + size; + MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len, mbedtls_x509_write_sig( &c2, c, + sig_oid, sig_oid_len, sig, sig_len ) ); + + /* + * Memory layout after this step: + * + * buf c=buf+len c2 buf+size + * [CRT0,...,CRTn, UNUSED, ..., UNUSED, SIG0, ..., SIGm] + */ + + /* Move raw CRT to just before the signature. */ + c = c2 - len; + memmove( c, buf, len ); + + len += sig_and_oid_len; + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + return( (int) len ); +} + +#define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----\n" +#define PEM_END_CRT "-----END CERTIFICATE-----\n" + +#if defined(MBEDTLS_PEM_WRITE_C) +int mbedtls_x509write_crt_pem( mbedtls_x509write_cert *crt, + unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t olen; + + if( ( ret = mbedtls_x509write_crt_der( crt, buf, size, + f_rng, p_rng ) ) < 0 ) + { + return( ret ); + } + + if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_CRT, PEM_END_CRT, + buf + size - ret, ret, + buf, size, &olen ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_PEM_WRITE_C */ + +#endif /* MBEDTLS_X509_CRT_WRITE_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/x509write_csr.c b/Android/Level4/app/src/main/c/mbedtls/library/x509write_csr.c new file mode 100644 index 0000000..c7c8032 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/x509write_csr.c @@ -0,0 +1,341 @@ +/* + * X.509 Certificate Signing Request writing + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ +/* + * References: + * - CSRs: PKCS#10 v1.7 aka RFC 2986 + * - attributes: PKCS#9 v2.0 aka RFC 2985 + */ + +#include "common.h" + +#if defined(MBEDTLS_X509_CSR_WRITE_C) + +#include "mbedtls/x509_csr.h" +#include "mbedtls/asn1write.h" +#include "mbedtls/error.h" +#include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#include "mbedtls/psa_util.h" +#endif + +#include +#include + +#if defined(MBEDTLS_PEM_WRITE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +void mbedtls_x509write_csr_init( mbedtls_x509write_csr *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_x509write_csr ) ); +} + +void mbedtls_x509write_csr_free( mbedtls_x509write_csr *ctx ) +{ + mbedtls_asn1_free_named_data_list( &ctx->subject ); + mbedtls_asn1_free_named_data_list( &ctx->extensions ); + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_x509write_csr ) ); +} + +void mbedtls_x509write_csr_set_md_alg( mbedtls_x509write_csr *ctx, mbedtls_md_type_t md_alg ) +{ + ctx->md_alg = md_alg; +} + +void mbedtls_x509write_csr_set_key( mbedtls_x509write_csr *ctx, mbedtls_pk_context *key ) +{ + ctx->key = key; +} + +int mbedtls_x509write_csr_set_subject_name( mbedtls_x509write_csr *ctx, + const char *subject_name ) +{ + return mbedtls_x509_string_to_names( &ctx->subject, subject_name ); +} + +int mbedtls_x509write_csr_set_extension( mbedtls_x509write_csr *ctx, + const char *oid, size_t oid_len, + const unsigned char *val, size_t val_len ) +{ + return mbedtls_x509_set_extension( &ctx->extensions, oid, oid_len, + 0, val, val_len ); +} + +int mbedtls_x509write_csr_set_key_usage( mbedtls_x509write_csr *ctx, unsigned char key_usage ) +{ + unsigned char buf[4]; + unsigned char *c; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + c = buf + 4; + + ret = mbedtls_asn1_write_named_bitstring( &c, buf, &key_usage, 8 ); + if( ret < 3 || ret > 4 ) + return( ret ); + + ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_KEY_USAGE, + MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ), + c, (size_t)ret ); + if( ret != 0 ) + return( ret ); + + return( 0 ); +} + +int mbedtls_x509write_csr_set_ns_cert_type( mbedtls_x509write_csr *ctx, + unsigned char ns_cert_type ) +{ + unsigned char buf[4]; + unsigned char *c; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + c = buf + 4; + + ret = mbedtls_asn1_write_named_bitstring( &c, buf, &ns_cert_type, 8 ); + if( ret < 3 || ret > 4 ) + return( ret ); + + ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE, + MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ), + c, (size_t)ret ); + if( ret != 0 ) + return( ret ); + + return( 0 ); +} + +static int x509write_csr_der_internal( mbedtls_x509write_csr *ctx, + unsigned char *buf, + size_t size, + unsigned char *sig, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const char *sig_oid; + size_t sig_oid_len = 0; + unsigned char *c, *c2; + unsigned char hash[64]; + size_t pub_len = 0, sig_and_oid_len = 0, sig_len; + size_t len = 0; + mbedtls_pk_type_t pk_alg; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_hash_operation_t hash_operation = PSA_HASH_OPERATION_INIT; + size_t hash_len; + psa_algorithm_t hash_alg = mbedtls_psa_translate_md( ctx->md_alg ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + /* Write the CSR backwards starting from the end of buf */ + c = buf + size; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_extensions( &c, buf, + ctx->extensions ) ); + + if( len ) + { + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( + &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( + &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET ) ); + + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_oid( + &c, buf, MBEDTLS_OID_PKCS9_CSR_EXT_REQ, + MBEDTLS_OID_SIZE( MBEDTLS_OID_PKCS9_CSR_EXT_REQ ) ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( + &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( + &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ); + + MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_pk_write_pubkey_der( ctx->key, + buf, c - buf ) ); + c -= pub_len; + len += pub_len; + + /* + * Subject ::= Name + */ + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, buf, + ctx->subject ) ); + + /* + * Version ::= INTEGER { v1(0), v2(1), v3(2) } + */ + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 0 ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( + &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); + + /* + * Sign the written CSR data into the sig buffer + * Note: hash errors can happen only after an internal error + */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( psa_hash_setup( &hash_operation, hash_alg ) != PSA_SUCCESS ) + return( MBEDTLS_ERR_X509_FATAL_ERROR ); + + if( psa_hash_update( &hash_operation, c, len ) != PSA_SUCCESS ) + return( MBEDTLS_ERR_X509_FATAL_ERROR ); + + if( psa_hash_finish( &hash_operation, hash, sizeof( hash ), &hash_len ) + != PSA_SUCCESS ) + { + return( MBEDTLS_ERR_X509_FATAL_ERROR ); + } +#else /* MBEDTLS_USE_PSA_CRYPTO */ + ret = mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, len, hash ); + if( ret != 0 ) + return( ret ); +#endif + if( ( ret = mbedtls_pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len, + f_rng, p_rng ) ) != 0 ) + { + return( ret ); + } + + if( mbedtls_pk_can_do( ctx->key, MBEDTLS_PK_RSA ) ) + pk_alg = MBEDTLS_PK_RSA; + else if( mbedtls_pk_can_do( ctx->key, MBEDTLS_PK_ECDSA ) ) + pk_alg = MBEDTLS_PK_ECDSA; + else + return( MBEDTLS_ERR_X509_INVALID_ALG ); + + if( ( ret = mbedtls_oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg, + &sig_oid, &sig_oid_len ) ) != 0 ) + { + return( ret ); + } + + /* + * Move the written CSR data to the start of buf to create space for + * writing the signature into buf. + */ + memmove( buf, c, len ); + + /* + * Write sig and its OID into buf backwards from the end of buf. + * Note: mbedtls_x509_write_sig will check for c2 - ( buf + len ) < sig_len + * and return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL if needed. + */ + c2 = buf + size; + MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len, + mbedtls_x509_write_sig( &c2, buf + len, sig_oid, sig_oid_len, + sig, sig_len ) ); + + /* + * Compact the space between the CSR data and signature by moving the + * CSR data to the start of the signature. + */ + c2 -= len; + memmove( c2, buf, len ); + + /* ASN encode the total size and tag the CSR data with it. */ + len += sig_and_oid_len; + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c2, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( + &c2, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); + + /* Zero the unused bytes at the start of buf */ + memset( buf, 0, c2 - buf); + + return( (int) len ); +} + +int mbedtls_x509write_csr_der( mbedtls_x509write_csr *ctx, unsigned char *buf, + size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + unsigned char *sig; + + if( ( sig = mbedtls_calloc( 1, MBEDTLS_PK_SIGNATURE_MAX_SIZE ) ) == NULL ) + { + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + } + + ret = x509write_csr_der_internal( ctx, buf, size, sig, f_rng, p_rng ); + + mbedtls_free( sig ); + + return( ret ); +} + +#define PEM_BEGIN_CSR "-----BEGIN CERTIFICATE REQUEST-----\n" +#define PEM_END_CSR "-----END CERTIFICATE REQUEST-----\n" + +#if defined(MBEDTLS_PEM_WRITE_C) +int mbedtls_x509write_csr_pem( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t olen = 0; + + if( ( ret = mbedtls_x509write_csr_der( ctx, buf, size, + f_rng, p_rng ) ) < 0 ) + { + return( ret ); + } + + if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_CSR, PEM_END_CSR, + buf + size - ret, + ret, buf, size, &olen ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_PEM_WRITE_C */ + +#endif /* MBEDTLS_X509_CSR_WRITE_C */ diff --git a/Android/Level4/app/src/main/c/mbedtls/library/xtea.c b/Android/Level4/app/src/main/c/mbedtls/library/xtea.c new file mode 100644 index 0000000..4b8c9c0 --- /dev/null +++ b/Android/Level4/app/src/main/c/mbedtls/library/xtea.c @@ -0,0 +1,271 @@ +/* + * An 32-bit implementation of the XTEA algorithm + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 "common.h" + +#if defined(MBEDTLS_XTEA_C) + +#include "mbedtls/xtea.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_XTEA_ALT) + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +void mbedtls_xtea_init( mbedtls_xtea_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_xtea_context ) ); +} + +void mbedtls_xtea_free( mbedtls_xtea_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_xtea_context ) ); +} + +/* + * XTEA key schedule + */ +void mbedtls_xtea_setup( mbedtls_xtea_context *ctx, const unsigned char key[16] ) +{ + int i; + + memset( ctx, 0, sizeof(mbedtls_xtea_context) ); + + for( i = 0; i < 4; i++ ) + { + GET_UINT32_BE( ctx->k[i], key, i << 2 ); + } +} + +/* + * XTEA encrypt function + */ +int mbedtls_xtea_crypt_ecb( mbedtls_xtea_context *ctx, int mode, + const unsigned char input[8], unsigned char output[8]) +{ + uint32_t *k, v0, v1, i; + + k = ctx->k; + + GET_UINT32_BE( v0, input, 0 ); + GET_UINT32_BE( v1, input, 4 ); + + if( mode == MBEDTLS_XTEA_ENCRYPT ) + { + uint32_t sum = 0, delta = 0x9E3779B9; + + for( i = 0; i < 32; i++ ) + { + v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]); + sum += delta; + v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]); + } + } + else /* MBEDTLS_XTEA_DECRYPT */ + { + uint32_t delta = 0x9E3779B9, sum = delta * 32; + + for( i = 0; i < 32; i++ ) + { + v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]); + sum -= delta; + v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]); + } + } + + PUT_UINT32_BE( v0, output, 0 ); + PUT_UINT32_BE( v1, output, 4 ); + + return( 0 ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/* + * XTEA-CBC buffer encryption/decryption + */ +int mbedtls_xtea_crypt_cbc( mbedtls_xtea_context *ctx, int mode, size_t length, + unsigned char iv[8], const unsigned char *input, + unsigned char *output) +{ + int i; + unsigned char temp[8]; + + if( length % 8 ) + return( MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH ); + + if( mode == MBEDTLS_XTEA_DECRYPT ) + { + while( length > 0 ) + { + memcpy( temp, input, 8 ); + mbedtls_xtea_crypt_ecb( ctx, mode, input, output ); + + for( i = 0; i < 8; i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, 8 ); + + input += 8; + output += 8; + length -= 8; + } + } + else + { + while( length > 0 ) + { + for( i = 0; i < 8; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + mbedtls_xtea_crypt_ecb( ctx, mode, output, output ); + memcpy( iv, output, 8 ); + + input += 8; + output += 8; + length -= 8; + } + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* !MBEDTLS_XTEA_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +/* + * XTEA tests vectors (non-official) + */ + +static const unsigned char xtea_test_key[6][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 }, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 } +}; + +static const unsigned char xtea_test_pt[6][8] = +{ + { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 }, + { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }, + { 0x5a, 0x5b, 0x6e, 0x27, 0x89, 0x48, 0xd7, 0x7f }, + { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 }, + { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }, + { 0x70, 0xe1, 0x22, 0x5d, 0x6e, 0x4e, 0x76, 0x55 } +}; + +static const unsigned char xtea_test_ct[6][8] = +{ + { 0x49, 0x7d, 0xf3, 0xd0, 0x72, 0x61, 0x2c, 0xb5 }, + { 0xe7, 0x8f, 0x2d, 0x13, 0x74, 0x43, 0x41, 0xd8 }, + { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }, + { 0xa0, 0x39, 0x05, 0x89, 0xf8, 0xb8, 0xef, 0xa5 }, + { 0xed, 0x23, 0x37, 0x5a, 0x82, 0x1a, 0x8c, 0x2d }, + { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 } +}; + +/* + * Checkup routine + */ +int mbedtls_xtea_self_test( int verbose ) +{ + int i, ret = 0; + unsigned char buf[8]; + mbedtls_xtea_context ctx; + + mbedtls_xtea_init( &ctx ); + for( i = 0; i < 6; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " XTEA test #%d: ", i + 1 ); + + memcpy( buf, xtea_test_pt[i], 8 ); + + mbedtls_xtea_setup( &ctx, xtea_test_key[i] ); + mbedtls_xtea_crypt_ecb( &ctx, MBEDTLS_XTEA_ENCRYPT, buf, buf ); + + if( memcmp( buf, xtea_test_ct[i], 8 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +exit: + mbedtls_xtea_free( &ctx ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_XTEA_C */ diff --git a/Android/Level4/app/src/main/c/mylibc.h b/Android/Level4/app/src/main/c/mylibc.h new file mode 100644 index 0000000..7c1d3f9 --- /dev/null +++ b/Android/Level4/app/src/main/c/mylibc.h @@ -0,0 +1,176 @@ +#ifndef DETECTFRIDA_MYLIBC_H +#define DETECTFRIDA_MYLIBC_H +/* + * These functions are copied from glibc, android libc, apple libc open source code. + * This is to avoid easy bypass through libc functions + */ + +__attribute__((always_inline)) +static inline size_t +my_strlcpy(char *dst, const char *src, size_t siz) +{ + char *d = dst; + const char *s = src; + size_t n = siz; + /* Copy as many bytes as will fit */ + if (n != 0) { + while (--n != 0) { + if ((*d++ = *s++) == '\0') + break; + } + } + /* Not enough room in dst, add NUL and traverse rest of src */ + if (n == 0) { + if (siz != 0) + *d = '\0'; /* NUL-terminate dst */ + while (*s++) + ; + } + return(s - src - 1); /* count does not include NUL */ +} + +__attribute__((always_inline)) +static inline +size_t my_strlen(const char *s) +{ + size_t len = 0; + while(*s++) len++; + return len; +} + +__attribute__((always_inline)) +static inline int +my_strncmp(const char *s1, const char *s2, size_t n) +{ + if (n == 0) + return (0); + do { + if (*s1 != *s2++) + return (*(unsigned char *)s1 - *(unsigned char *)--s2); + if (*s1++ == 0) + break; + } while (--n != 0); + return (0); +} + +__attribute__((always_inline)) +static inline char * +my_strstr(const char *s, const char *find) +{ + char c, sc; + size_t len; + + if ((c = *find++) != '\0') { + len = my_strlen(find); + do { + do { + if ((sc = *s++) == '\0') + return (NULL); + } while (sc != c); + } while (my_strncmp(s, find, len) != 0); + s--; + } + return ((char *)s); +} + +__attribute__((always_inline)) +static inline +void* my_memset(void* dst, int c, size_t n) +{ + char* q = (char*)dst; + char* end = q + n; + for (;;) { + if (q >= end) break; *q++ = (char) c; + if (q >= end) break; *q++ = (char) c; + if (q >= end) break; *q++ = (char) c; + if (q >= end) break; *q++ = (char) c; + } + return dst; +} + +__attribute__((always_inline)) +static inline int +my_strcmp(const char *s1, const char *s2) +{ + while (*s1 == *s2++) + if (*s1++ == 0) + return (0); + return (*(unsigned char *)s1 - *(unsigned char *)--s2); +} + +__attribute__((always_inline)) +static inline int my_atoi(const char *s) +{ + int n=0, neg=0; + while (isspace(*s)) s++; + switch (*s) { + case '-': neg=1; + case '+': s++; + } + /* Compute n as a negative number to avoid overflow on INT_MIN */ + while (isdigit(*s)) + n = 10*n - (*s++ - '0'); + return neg ? n : -n; +} + +__attribute__((always_inline)) +int +my_memcmp(const void *s1, const void *s2, size_t n) +{ + if (n != 0) { + const unsigned char *p1 = (const unsigned char *)s1; + const unsigned char *p2 = (const unsigned char *)s2; + + do { + if (*p1++ != *p2++) + return (*--p1 - *--p2); + } while (--n != 0); + } + return (0); +} + +__attribute__((always_inline)) +char * +my_strtok_r(char *s, const char *delim, char **last) +{ + char *spanp; + int c, sc; + char *tok; + if (s == NULL && (s = *last) == NULL) + return (NULL); + /* + * Skip (span) leading delimiters (s += strspn(s, delim), sort of). + */ + cont: + c = *s++; + for (spanp = (char *)delim; (sc = *spanp++) != 0;) { + if (c == sc) + goto cont; + } + if (c == 0) { /* no non-delimiter characters */ + *last = NULL; + return (NULL); + } + tok = s - 1; + /* + * Scan token (scan for delimiters: s += strcspn(s, delim), sort of). + * Note that delim must have one NUL; we stop if we see that, too. + */ + for (;;) { + c = *s++; + spanp = (char *)delim; + do { + if ((sc = *spanp++) == c) { + if (c == 0) + s = NULL; + else + s[-1] = 0; + *last = s; + return (tok); + } + } while (sc != 0); + } + /* NOTREACHED */ +} + +#endif //DETECTFRIDA_MYLIBC_H diff --git a/Android/Level4/app/src/main/c/native-lib.c b/Android/Level4/app/src/main/c/native-lib.c new file mode 100644 index 0000000..9c1a9d0 --- /dev/null +++ b/Android/Level4/app/src/main/c/native-lib.c @@ -0,0 +1,673 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +// Syscalls +#include "syscall_arch.h" +#include "syscalls.h" +#include "mylibc.h" + +// Crypto +#include "mbedtls/md.h" +#include "whitebox/aes_table.c" +#include "swcrypto/pbkdf2.h" + +#include "rootdetector/rootdetector.h" +#include + + +// Android +#include +#include + +#ifdef DEBUG_ENABLED +#define cprintf(...) __android_log_print(ANDROID_LOG_INFO, "PWNME", __VA_ARGS__) +#else +#define cprintf(...) +#endif + +/*Frida Detection Strings-Start*/ +static const char *FRIDA_THREAD_GMAIN = "gmain"; + +/*Debug Detection*/ +static const char *TRACER_PID = "TracerPid"; +static const char *PROC_MAPS = "/proc/self/maps"; +static const char *PROC_STATUS = "/proc/self/task/%s/status"; +static const char *PROC_TASK = "/proc/self/task"; +static const char *PROC_SELF_STATUS = "/proc/self/status"; + +static const char *LIBC = "libc.so"; + +//Structure to hold the checksum of executable section of library +typedef struct stTextSection { + unsigned long offset; + unsigned long memsize; + unsigned long checksum; +} textSection; + +#ifdef _32_BIT +typedef Elf32_Ehdr Elf_Ehdr; +typedef Elf32_Shdr Elf_Shdr; +#elif _64_BIT +typedef Elf64_Ehdr Elf_Ehdr; +typedef Elf64_Shdr Elf_Shdr; +#endif + +static const uint8_t salt[16] = {0x4a, 0xd8, 0x91, 0x93, 0x4b, 0x99, 0xc3, 0xa0, + 0x44, 0x5f, 0x66, 0xad, 0x76, 0xea, 0xa1, 0x06}; + +static const uint8_t pin_hash[32] = {0xb7, 0x0e, 0x29, 0xf6, 0x61, 0xf7, 0x8d, 0xac, + 0xf5, 0x41, 0x78, 0x7d, 0xf5, 0x9b, 0xa2, 0x25, + 0xe1, 0x44, 0x62, 0x84, 0x88, 0xb4, 0x6b, 0x4c, + 0x60, 0x47, 0xd4, 0xce, 0xd3, 0x8a, 0x3a, 0xf7}; + +/* Extern from libc to manipulate the process name */ +extern const char *__progname; + +#define MAX_LINE 512 +#define MAX_LENGTH 256 + +static void change_process_name(); + +static bool is_debugger_attached(); + +static bool is_fridathreads_detected(); + +static bool is_libc_tampered(const char *library, struct stTextSection *stTextSection); + +static ssize_t read_one_line(int fd, char *buf, unsigned int max_len); + +static unsigned long checksum(void *buffer, size_t len); + +static int check_execsection_tampered(char *map, textSection *pElfSectArr); + +static char *parse_proc_maps_to_fetch_path(const char *lib); + +static bool fetch_checksum_of_library(const char *filePath, textSection **pTextSection); + +static void detect_threat_loop(void *pargs); + +static void detect_root_loop(void *pargs); + +static int crash(int randomval); + +static int verifyPin(uint8_t *pin); + +static void detect_threat_1(); + +static void detect_threat_2(); + +static jbyteArray +gXftm3iswpkVgBNDUp( + JNIEnv *env, + jobject thiz, + jbyteArray inBuff, + jbyte rt); + +unsigned int gpCrash = 0xfab972ad; +unsigned int gTamperedFridaState = 0; +unsigned int gTamperedRootState = 0x11111111; +bool gLibcIsRX = false; +textSection *elfSectionArr = 0; + +/* + * Constructor function which will invoke all detection mechanisms when native library is loaded + */ +__attribute__((constructor)) +void init() { + gTamperedFridaState |= 0x00000001; + + if (!gLibcIsRX) { + // This first to mprotect --x segments with r-x permissions + char *filepath = parse_proc_maps_to_fetch_path(LIBC); + fetch_checksum_of_library(filepath, &elfSectionArr); + } + + pthread_t t1; + pthread_create(&t1, NULL, (void *) detect_threat_loop, NULL); +} + +__attribute__((constructor)) +void init2() { + + if (!gLibcIsRX) { + // This first to mprotect --x segments with r-x permissions + char *filepath = parse_proc_maps_to_fetch_path(LIBC); + fetch_checksum_of_library(filepath, &elfSectionArr); + } + + pthread_t t2; + pthread_create(&t2, NULL, (void *) detect_root_loop, NULL); + + gTamperedRootState &= 0x01111111; +} + +//HARDCODED PIN VALUE: 5971 +static jbyteArray +gXftm3iswpkVgBNDUp( + JNIEnv *env, + jobject thiz, + jbyteArray inBuff, + jbyte rt) { + + // Pin and amount data + char *buffer; + char pin[4 + 1]; + char amount[8 + 1]; + uint8_t pinResult = 0x51; + + // Whitebox crypto + const int block_size = 16; + uint8_t outBuff[block_size] = {0}; + + // Convert Java to native + jsize num_bytes = (*env)->GetArrayLength(env, inBuff); + buffer = (char *) malloc(num_bytes); + jbyte *jinBuff = (*env)->GetByteArrayElements(env, inBuff, 0); + + unsigned char rooted = (unsigned char) rt; + if (rooted >= 0xFF) + crash(0x34ED); + + memcpy(buffer, jinBuff, num_bytes); + + memcpy(pin, buffer + 4, 4); + pin[4] = '\0'; + memcpy(amount, buffer + 8, 8); + amount[8] = '\0'; + + if (gTamperedFridaState < 1) + crash(0x207A); + + if (gTamperedRootState == 0) + crash(0x7A20); + + int ret = verifyPin(pin); + + if (ret == 0) { + pinResult = 0x23; + } + + if (gTamperedFridaState == 0) + crash(0x9218); + + detect_threat_1(); + detect_threat_2(); + aes_128_table_encrypt(buffer, outBuff); // Encrypt the pin+amount with whitebox aes crypto + + // Convert native to Java + // block_size + 1 for passing the output encrypted data and pin result as 1 byte + jbyteArray jout = (*env)->NewByteArray(env, block_size + 1); + (*env)->SetByteArrayRegion(env, jout, 0, 1, &pinResult); + (*env)->SetByteArrayRegion(env, jout, 1, block_size, outBuff); + + // Memory cleanup + free(buffer); + my_memset(outBuff, 0, block_size + 1); + (*env)->ReleaseByteArrayElements(env, inBuff, jinBuff, JNI_ABORT); + + return jout; +} + +static JNINativeMethod methods[] = { + {"gXftm3iswpkVgBNDUp", "([BB)[B", gXftm3iswpkVgBNDUp}, +}; + +jint JNI_OnLoad(JavaVM *jvm, void *v __unused) { + JNIEnv *env; + jclass clazz; + + if ((*jvm)->GetEnv(jvm, (void **) &env, JNI_VERSION_1_6) != JNI_OK) { + return JNI_ERR; + } + + if ((clazz = (*env)->FindClass(env, "re/pwnme/MainActivity")) == NULL) { + return JNI_ERR; + } + + if ((*env)->RegisterNatives(env, clazz, methods, 1) < 0) { + return JNI_ERR; + } + + return JNI_VERSION_1_6; +} + +/* PIN Hashing and Verification */ +__attribute__((always_inline)) +static inline int verifyPin(uint8_t *pin) { + int ret = -1; + unsigned char *out = (unsigned char *) malloc(32 * sizeof(unsigned char)); + + ret = pbkdf2(pin, 4, salt, 16, 32, 32, out); + + if (ret == 0) + ret = my_memcmp(out, pin_hash, 32); + + return ret; +} + +__attribute__((always_inline)) +static inline void detect_threat_loop(void *pargs) { + if (gTamperedFridaState == 0x00000001) + gTamperedFridaState |= 0x00000010; + + while (1) { + bool bRet = false; + + if (gTamperedFridaState != 0x00000011) { + crash(0x8190); + } + + change_process_name(); + + gTamperedFridaState |= 0x00000100; + bRet = is_debugger_attached(); + if (bRet) + crash(0xFE0A); + + + if (gTamperedFridaState != 0x00000111) + crash(0x7FCA); + + + gTamperedFridaState |= 0x00001000; + bRet = is_fridathreads_detected(); + if (bRet) + crash(0x1AD9); + + if (gTamperedFridaState != 0x00001111) + crash(0xA4FC); + + + gTamperedFridaState |= 0x00010000; + + char ch[10] = "", ch1[10] = ""; + __system_property_get("ro.build.version.release", ch); + __system_property_get("ro.system.build.version.release", ch1); + int version = my_atoi(ch); + int version1 = my_atoi(ch1); + if (version < 10 || version1 < 10) { + bRet = is_libc_tampered(LIBC, elfSectionArr); + if (bRet) + crash(0xF085); + } + + gTamperedFridaState |= 0x00100000; + // Code removed + gTamperedFridaState |= 0x01000000; + + struct timespec timereq; + timereq.tv_sec = 1; + timereq.tv_nsec = 0; + + nanosleep(&timereq, NULL); + if (gTamperedFridaState != 0x01111111) { + crash(0xAEFD); + } + gTamperedFridaState = 0x00000011; + } +} + + +__attribute__((always_inline)) +static inline void detect_root_loop(void *pargs) { + + if (gTamperedRootState == 0x01111111) { + gTamperedRootState &= 0x00111111; + } + + bool bRet = false; + + bRet = is_supath_detected(); + if (bRet) + crash(0x33E4); + + bRet = is_systempaths_writeable(); + if (bRet) + crash(0x9891); + + if (gTamperedRootState != 0x00111111) + crash(0x6848); + + gTamperedRootState &= 0x00011111; + + struct timespec timereq; + timereq.tv_sec = 1; + timereq.tv_nsec = 0; + + nanosleep(&timereq, NULL); + + if (gTamperedRootState != 0x00011111) + crash(0x4324); +} + +__attribute__((always_inline)) +static inline int crash(int randomval) { + volatile int *p = gpCrash; + p += randomval * 2; + p += *p + randomval; + p = 0; + p += *p; + + return *p; +} + +/* + * Change process name to confuse the reverse engineers which process to attach. + * This function can be called any number of times. + * Note: its just a fun function to change the process name, not really a protection mechanism + */ +__attribute__((always_inline)) +static inline void change_process_name() { + const char *processName[] = { + "com.google.vr.vrcore", + "android.process.media", + "com.google.android.gms", + "com.google.android.apps.turbo", + "com.android.systemui", + "com.google.android.googlequicksearch", + "com.google.process.gservices", + "com.google.android.gm", + "com.google.android.videos", + "com.android.chrome:sandboxed_process0" + }; + if (NULL != __progname) { + int value = rand() % (sizeof(processName) / sizeof(processName[0])); + char *currProcName = (char *) __progname; + my_strlcpy(currProcName, processName[value], my_strlen(processName[value]) + 1); + currProcName[my_strlen(processName[value])] = '\0'; + + } +} + + +/* + * Detects if gdb/lldb/ptrace is attached to the process using the value of TracerPid in + * /proc/self/status. If it is 0, then no debugger is attached. + */ +__attribute__((always_inline)) +static inline bool is_debugger_attached() { + bool bRet = false; + int fd = my_openat(AT_FDCWD, PROC_SELF_STATUS, O_RDONLY | O_CLOEXEC, 0); + if (fd != 0) { + char map[MAX_LINE]; + while ((read_one_line(fd, map, MAX_LINE)) > 0) { + + if (NULL != my_strstr(map, TRACER_PID)) { + char *saveptr1; + char *str_pid = my_strtok_r(map, ":", &saveptr1); + int pid = my_atoi(saveptr1); + if (pid != 0) { + bRet = true; + } + break; + } + } + my_close(fd); + } + + return bRet; +} + + +/* + * Detects the presence of frida specific threads + */ +__attribute__((always_inline)) +static inline bool is_fridathreads_detected() { + + DIR *dir = opendir(PROC_TASK); + bool bRet = false; + + if (dir != NULL) { + struct dirent *entry = NULL; + while ((entry = readdir(dir)) != NULL) { + char filePath[MAX_LENGTH]; + my_memset(filePath, 0, MAX_LENGTH); + + if (0 == my_strcmp(entry->d_name, ".") || 0 == my_strcmp(entry->d_name, "..")) { + continue; + } + snprintf(filePath, sizeof(filePath), PROC_STATUS, entry->d_name); + + int fd = my_openat(AT_FDCWD, filePath, O_RDONLY | O_CLOEXEC, 0); + if (fd != 0) { + char buf[MAX_LENGTH]; + read_one_line(fd, buf, MAX_LENGTH); + if (my_strstr(buf, FRIDA_THREAD_GMAIN)) { + bRet = true; + break; + } + my_close(fd); + } + + } + closedir(dir); + } + + return bRet; +} + + +/* + * Detects if libc is tampered + */ +__attribute__((always_inline)) +static inline bool is_libc_tampered(const char *library, struct stTextSection *stTextSection) { + bool bRet = false; + int fd = 0; + char map[MAX_LINE]; + + if ((fd = my_openat(AT_FDCWD, PROC_MAPS, O_RDONLY | O_CLOEXEC, 0)) != 0) { + while ((read_one_line(fd, map, MAX_LINE)) > 0) { + if (my_strstr(map, library) != NULL) { + int ret = check_execsection_tampered(map, stTextSection); + if (ret != -1) { + if (ret == 0) { + bRet = true; + } + break; + } + } + } + } + my_close(fd); + + return bRet; +} + + +/* Utility Functions - Start */ + +__attribute__((always_inline)) +static inline void detect_threat_1() { + + if (is_debugger_attached()) + crash(0x17a3); +} + +__attribute__((always_inline)) +static inline void detect_threat_2() { + + if (is_fridathreads_detected()) + crash(0x81c6); +} + +__attribute__((always_inline)) +static inline ssize_t read_one_line(int fd, char *buf, unsigned int max_len) { + char b; + ssize_t ret; + ssize_t bytes_read = 0; + + my_memset(buf, 0, max_len); + + do { + ret = my_read(fd, &b, 1); + + if (ret != 1) { + if (bytes_read == 0) { + // error or EOF + return -1; + } else { + return bytes_read; + } + } + + if (b == '\n') { + return bytes_read; + } + + *(buf++) = b; + bytes_read += 1; + + } while (bytes_read < max_len - 1); + + return bytes_read; +} + + +__attribute__((always_inline)) +static inline unsigned long checksum(void *buffer, size_t len) { + unsigned long seed = 0; + uint8_t *buf = (uint8_t *) buffer; + size_t i; + for (i = 0; i < len; ++i) + seed += (unsigned long) (*buf++); + return seed; +} + + +__attribute__((always_inline)) +static inline int check_execsection_tampered(char *map, textSection *pElfSectArr) { + int ret = -1; + unsigned long start, end; + char buf[MAX_LINE]; + char path[MAX_LENGTH]; + char tmp[100]; + + my_memset(buf, 0, MAX_LINE); + my_memset(path, 0, MAX_LENGTH); + my_memset(tmp, 0, 100); + + sscanf(map, "%lx-%lx %s %s %s %s %s", &start, &end, buf, tmp, tmp, tmp, path); + + if (buf[2] == 'x') { + ret = 1; + + uint8_t *buffer = (uint8_t *) start; + unsigned long memsize = end - start; + + if (memsize >= (pElfSectArr->offset + pElfSectArr->memsize)) { + buffer = (uint8_t *) (start + pElfSectArr->offset); + } + memsize = pElfSectArr->memsize; + unsigned long output = checksum(buffer, + memsize); // TODO memsize is overwritten and goes OOB + if (output != pElfSectArr->checksum) { + ret = 0; + } + } + + return ret; +} + + +__attribute__((always_inline)) +static inline char *parse_proc_maps_to_fetch_path(const char *lib) { + int fd = 0; + char map[MAX_LINE]; + unsigned long start, end; + char *filepath = NULL; + if ((fd = my_openat(AT_FDCWD, PROC_MAPS, O_RDONLY | O_CLOEXEC, 0)) != 0) { + + while ((read_one_line(fd, map, MAX_LINE)) > 0) { + if (my_strstr(map, lib) != NULL) { + char tmp[MAX_LENGTH]; + char path[MAX_LENGTH]; + char buf[5]; + my_memset(tmp, 0, MAX_LENGTH); + my_memset(path, 0, MAX_LENGTH); + my_memset(buf, 0, 5); + sscanf(map, "%lx-%lx %s %s %s %s %s", &start, &end, buf, tmp, tmp, tmp, path); + if (buf[2] == 'x') { + if (buf[0] != 'r') { + int out = mprotect(start, (end - start), PROT_READ | PROT_EXEC); + gLibcIsRX = true; + } + size_t size = my_strlen(path) + 1; + filepath = malloc(size); + my_strlcpy(filepath, path, size); + } + } + } + my_close(fd); + } + + return filepath; +} + + +__attribute__((always_inline)) +static inline bool fetch_checksum_of_library(const char *filePath, textSection **pTextSection) { + + Elf_Ehdr ehdr; + Elf_Shdr sectHdr; + int fd; + + fd = my_openat(AT_FDCWD, filePath, O_RDONLY | O_CLOEXEC, 0); + if (fd < 0) { + return NULL; + } + + my_read(fd, &ehdr, sizeof(Elf_Ehdr)); + my_lseek(fd, (off_t) ehdr.e_shoff, SEEK_SET); + + unsigned long memsize = 0; + unsigned long offset = 0; + for (int i = 0; i < ehdr.e_shnum; i++) { + my_memset(§Hdr, 0, sizeof(Elf_Shdr)); + my_read(fd, §Hdr, sizeof(Elf_Shdr)); + + //Typically PLT and Text Sections are executable sections which are protected + if (sectHdr.sh_flags & SHF_ALLOC && sectHdr.sh_flags & SHF_EXECINSTR) { + memsize = sectHdr.sh_size; + offset = sectHdr.sh_offset; + break; + } + } + if (memsize == 0) { + my_close(fd); + return false; + } + + *pTextSection = malloc(sizeof(textSection)); + my_lseek(fd, offset, SEEK_SET); + uint8_t *buffer = malloc(memsize * sizeof(uint8_t)); + my_read(fd, buffer, memsize); + (*pTextSection)->memsize = memsize; + (*pTextSection)->offset = offset; + (*pTextSection)->checksum = checksum(buffer, memsize); + + free(buffer); + my_close(fd); + + return true; +} + +/* Utility Functions - End */ \ No newline at end of file diff --git a/Android/Level4/app/src/main/c/rootdetector/rootdetector.h b/Android/Level4/app/src/main/c/rootdetector/rootdetector.h new file mode 100644 index 0000000..cf69018 --- /dev/null +++ b/Android/Level4/app/src/main/c/rootdetector/rootdetector.h @@ -0,0 +1,69 @@ +#ifndef PWNME_ROOTDETECTOR_H +#define PWNME_ROOTDETECTOR_H + +static const char* suPaths[] ={ + "/data/local/su", + "/data/local/bin/su", + "/data/local/xbin/su", + "/sbin/su", + "/su/bin/su", + "/system/bin/su", + "/system/bin/.ext/su", + "/system/bin/failsafe/su", + "/system/sd/xbin/su", + "/system/usr/we-need-root/su", + "/system/xbin/su", + "/cache/su", + "/data/su", + "/dev/su" +}; + + +static const char* pathsThatShouldNotBeWritable[] = { + "/system", + "/system/bin", + "/system/sbin", + "/system/xbin", + "/vendor/bin", + "/sbin", + "/etc", + +}; +__attribute__((always_inline)) +static inline bool is_supath_detected(){ + int len = sizeof(suPaths) / sizeof(suPaths[0]); + bool bRet = false; + + for(int i = 0; i < len; i++){ + if(open(suPaths[i], O_RDONLY) >= 0){ + bRet = true; + break; + } + if(my_openat(AT_FDCWD, suPaths[i], O_RDONLY, 0) >= 0){ + bRet = true; + break; + } + if(0 == my_access(0, suPaths[i], R_OK, 0 )){ + bRet = true; + break; + } + } + + return bRet; +} + +__attribute__((always_inline)) +static inline bool is_systempaths_writeable(){ + int len = sizeof(pathsThatShouldNotBeWritable) / sizeof(pathsThatShouldNotBeWritable[0]); + bool bRet = false; + for(int i = 0; i < len; i++){ + + if(0 == my_access(AT_FDCWD, pathsThatShouldNotBeWritable[i], W_OK, 0 )){ + bRet = true; + break; + } + } + + return bRet; +} +#endif //PWNME_ROOTDETECTOR_H diff --git a/Android/Level4/app/src/main/c/swcrypto/pbkdf2.h b/Android/Level4/app/src/main/c/swcrypto/pbkdf2.h new file mode 100644 index 0000000..786ebde --- /dev/null +++ b/Android/Level4/app/src/main/c/swcrypto/pbkdf2.h @@ -0,0 +1,29 @@ +#ifndef PBKDF2_H +#define PBKDF2_H +#include "mbedtls/pkcs5.h" +#include "mbedtls/sha256.h" + +__attribute__((always_inline)) +static inline int pbkdf2(const char* password, int passlen, const unsigned char* salt, int saltlen, int iter, int outlen, unsigned char *out){ + int ret = -1; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + + do { + mbedtls_md_init(&md_ctx); + md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); + + if ((ret = mbedtls_md_setup(&md_ctx, md_info, 1)) != 0) + break; + + if ((ret = mbedtls_pkcs5_pbkdf2_hmac(&md_ctx, password, passlen, salt, saltlen, + iter, outlen, out)) != 0) { + break; + } + } while (0); + + return ret; + +} + +#endif //PBKDF2_H \ No newline at end of file diff --git a/Android/Level4/app/src/main/c/syscalls.h b/Android/Level4/app/src/main/c/syscalls.h new file mode 100644 index 0000000..da27ff8 --- /dev/null +++ b/Android/Level4/app/src/main/c/syscalls.h @@ -0,0 +1,42 @@ +#ifndef DETECTFRIDA_SYSCALLS_H +#define DETECTFRIDA_SYSCALLS_H +/* + * System calls such as file operations, sleep are converted to syscalls to avoid easy bypass + * through readymade scripts hooking onto libc calls. + */ +__attribute__((always_inline)) +static inline int my_openat(int __dir_fd, const void* __path, int __flags, int __mode ){ + return (int)__syscall4(__NR_openat, __dir_fd, (long)__path, __flags, __mode); +} + +__attribute__((always_inline)) +static inline ssize_t my_read(int __fd, void* __buf, size_t __count){ + return __syscall3(__NR_read, __fd, (long)__buf, (long)__count); +} + +__attribute__((always_inline)) +static inline off_t my_lseek(int __fd, off_t __offset, int __whence){ + return __syscall3(__NR_lseek, __fd, __offset, __whence); +} + +__attribute__((always_inline)) +static inline int my_close(int __fd){ + return (int)__syscall1(__NR_close, __fd); +} + +__attribute__((always_inline)) +static inline int my_nanosleep(const struct timespec* __request, struct timespec* __remainder){ + return (int)__syscall2(__NR_nanosleep, (long)__request, (long)__remainder); +} + +__attribute__((always_inline)) +static inline ssize_t my_readlinkat(int __dir_fd, const char* __path, char* __buf, size_t __buf_size){ + return __syscall4(__NR_readlinkat, __dir_fd, (long)__path, (long)__buf,(long)__buf_size); +} + +__attribute__((always_inline)) +static inline int my_access(int __dir_fd, const void* __path, int __mode, int __flags ){ + return (int)__syscall4(__NR_faccessat, __dir_fd, __path, __mode, __flags); +} + +#endif //DETECTFRIDA_SYSCALLS_H \ No newline at end of file diff --git a/Android/Level4/app/src/main/c/whitebox/Makefile b/Android/Level4/app/src/main/c/whitebox/Makefile new file mode 100644 index 0000000..3509e89 --- /dev/null +++ b/Android/Level4/app/src/main/c/whitebox/Makefile @@ -0,0 +1,47 @@ +CSOURCES := main.c aes.c +CXXSOURCES := genTables.cpp RandMat.cpp aes.c +OBJECTS := $(CSOURCES:.c=.o) +OBJECTS2 := $(CXXSOURCES:.cpp=.o) +OBJECTS2 := $(CXXSOURCES:.c=.o) +CFLAGS = -Wall -Wextra -std=c99 -O2 +CPPFLAGS = -lntl -lgmp -lm +LDFLAGS = +EXEC := whitebox +EXEC2 := genTables + +.PHONY.: all tables clean mrproper help + +all: $(EXEC) + +$(EXEC): $(OBJECTS) + $(CC) -o $@ $(CSOURCES) $(CFLAGS) $(LDFLAGS) + +tables: $(EXEC2) + +$(EXEC2): $(OBJECTS2) + g++ -o $@ $(OBJECTS2) $(OBJECTS3) $(CPPFLAGS) + + +%.o: %.c %.h + $(CC) -o $@ -c $< $(CFLAGS) + +%.o: %.cpp %.h + g++ -o $@ -c $< $(CPPFLAGS) + +clean: + @rm -f *.o + @echo "Deleted all .o files" + +mrproper: clean + @rm -f $(EXEC) + @echo "$(EXEC) has been deleted" + @rm -f $(EXEC2) + @echo "$(EXEC2) has been deleted" + +help: + @echo -e "make all\tBuilds the whitebox" + @echo -e "make genTables\tGenerates the tables" + @echo -e "make clean\tRemoves all .o files" + @echo -e "make mrproper\tDoes a clean and removes the executable file" + + diff --git a/Android/Level4/app/src/main/c/whitebox/README.md b/Android/Level4/app/src/main/c/whitebox/README.md new file mode 100644 index 0000000..44a2860 --- /dev/null +++ b/Android/Level4/app/src/main/c/whitebox/README.md @@ -0,0 +1,30 @@ +# WhiteBox AES + +This is a basic implementation of [Chow et al's][1] scheme, following [Muir's][2] tutorial. + +[1]: https://www.cs.colorado.edu/~jrblack/class/csci7000/s03/project/oorschot-whitebox.pdf +[2]: https://eprint.iacr.org/2013/104.pdf + +## How to use + +* **aes.c** and **aes.h** implement the standard aes encryption + +* **genTables.cpp**, **RandMat.cpp** and **RandMat.h** contain the functions used to generate the whitebox + +* **aes_table.c** and **main.c** implement aes with lookup-tables, protected or not + +Compile with `make` to build the whitebox generator: + + $ make tables + + $ ./genTables + +Then you can compile the whitebox: + + $ make + $ ./whitebox + + +## To Do + +* Find a way to pass encodings through the non-linear sbox diff --git a/Android/Level4/app/src/main/c/whitebox/RandMat.cpp b/Android/Level4/app/src/main/c/whitebox/RandMat.cpp new file mode 100644 index 0000000..00347ec --- /dev/null +++ b/Android/Level4/app/src/main/c/whitebox/RandMat.cpp @@ -0,0 +1,61 @@ +#include "RandMat.h" + +RandMat::RandMat() {} + +void RandMat::init(int dim, int is_mb) +{ + mat_GF2 mat; + int hw; + mat.SetDims(dim, dim); + this->dim = dim; + do { + for (int i = 0; i < dim; i++) + { + do + { + hw = 0; + for (int j = 0; j < dim; j++) + { + mat[i][j] = random_GF2(); + if (mat[i][j] == 1) + hw += 1; + } + } while (hw == 1); + } + this->mat = mat; + if (is_mb == 0) { + return; + } + } while (determinant(mat) == 0); + + this->invMat = inv(mat); +} + +ostream& operator<<(ostream& stream, const RandMat& rMat) +{ + cout << "Dim=" << rMat.dim << endl; + for (int i = 0; i < rMat.dim; i++) + { + for (int j = 0; j < rMat.dim; j++) + { + cout << rMat.mat[i][j] << " "; + } + cout << endl; + } + + cout << endl; + + if (determinant(rMat.mat) == 0) + return stream; + + for (int i = 0; i < rMat.dim; i++) + { + for (int j = 0; j < rMat.dim; j++) + { + cout << rMat.invMat[i][j] << " "; + } + cout << endl; + } + + return stream; +} \ No newline at end of file diff --git a/Android/Level4/app/src/main/c/whitebox/RandMat.h b/Android/Level4/app/src/main/c/whitebox/RandMat.h new file mode 100644 index 0000000..e0fcba2 --- /dev/null +++ b/Android/Level4/app/src/main/c/whitebox/RandMat.h @@ -0,0 +1,23 @@ +#ifndef UTILS_HPP +#define UTILS_HPP + +#include +#include +#include + +using namespace std; +using namespace NTL; + +class RandMat { +public: + RandMat(); + void init(int dim, int is_mb = 1); + friend ostream& operator<< (ostream& stream, const RandMat& rMat); + int dim; + mat_GF2 mat; + mat_GF2 invMat; +}; + + + +#endif // UTILS_HPP \ No newline at end of file diff --git a/Android/Level4/app/src/main/c/whitebox/aes.c b/Android/Level4/app/src/main/c/whitebox/aes.c new file mode 100644 index 0000000..b6011b3 --- /dev/null +++ b/Android/Level4/app/src/main/c/whitebox/aes.c @@ -0,0 +1,139 @@ +#include "aes.h" + +void initialize_aes_sbox(u8 sbox[256]) { + u8 p = 1, q = 1; + + /* loop invariant: p * q == 1 in the Galois field */ + do { + /* multiply p by 3 */ + p = p ^ (p << 1) ^ (p & 0x80 ? 0x1B : 0); + + /* divide q by 3 (equals multiplication by 0xf6) */ + q ^= q << 1; + q ^= q << 2; + q ^= q << 4; + q ^= q & 0x80 ? 0x09 : 0; + + /* compute the affine transformation */ + u8 xformed = q ^ ROTL8(q, 1) ^ ROTL8(q, 2) ^ ROTL8(q, 3) ^ ROTL8(q, 4); + + sbox[p] = xformed ^ 0x63; + } while (p != 1); + + /* 0 is a special case since it has no inverse */ + sbox[0] = 0x63; +} + +void printState (u8 in[16]) { + for(int i=0; i < 4; i++) { + printf("%.2X %.2X %.2X %.2X\n", in[i], in[i+4], in[i+8], in[i+12]); + } + printf("\n"); +} + +void subBytes (u8 state[16]) { + for (int i = 0; i < 16; i++) + state[i] = SBox[state[i]]; +} + +__attribute__((always_inline)) +void shiftRows (u8 state[16]) { + u8 out[16]; + int shiftTab[16] = {0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 1, 6, 11}; + for (int i = 0; i < 16; i++) { + out[i] = state[shiftTab[i]]; + } + memcpy(state, out, sizeof(out)); +} + +void addRoundKey (u8 state[16], u8 roundKey[16]) { + for (int i = 0; i < 16; i++) + state[i] ^= roundKey[i]; +} + +u8 gMul (u8 a, u8 b) { + u8 p = 0; + u8 hi_bit_set; + + for (int i = 0; i < 8; i++) { + if ((b & 1) == 1) + p ^= a; + hi_bit_set = (a & 0x80); + a <<= 1; + if (hi_bit_set == 0x80) + a ^= 0x1b; + b >>= 1; + } + return p; +} +void mixColumns (u8 state[16]) { + u8 out[16]; + for (int i = 0; i < 4; i++) { + out[4*i] = gMul(2, state[4*i]) ^ gMul(3, state[4*i + 1]) ^ state[4*i + 2] ^ state[4*i + 3]; + out[4*i + 1] = state[4*i] ^ gMul(2, state[4*i + 1]) ^ gMul(3, state[4*i + 2]) ^ state[4*i + 3]; + out[4*i + 2] = state[4*i] ^ state[4*i + 1] ^ gMul(2, state[4*i + 2]) ^ gMul(3, state[4*i + 3]); + out[4*i + 3] = gMul(3, state[4*i]) ^ state[4*i+1] ^ state[4*i + 2] ^ gMul(2, state[4*i + 3]); + } + + memcpy(state, out, sizeof(out)); +} + +void expandKey (u8 key[16], u8 expandedKey[176]) { + u8 tmp[4]; + int i = 0; + + for (i = 0; i < 4; i++) { + expandedKey[4*i] = key[4*i]; + expandedKey[4*i + 1] = key[4*i + 1]; + expandedKey[4*i + 2] = key[4*i + 2]; + expandedKey[4*i + 3] = key[4*i + 3]; + } + + for (i = 4; i < 44; i++) { + tmp[0] = expandedKey[4*(i-1)]; + tmp[1] = expandedKey[4*(i-1) + 1]; + tmp[2] = expandedKey[4*(i-1) + 2]; + tmp[3] = expandedKey[4*(i-1) + 3]; + + if (i % 4 == 0) { + int k = tmp[0]; + tmp[0] = SBox[tmp[1]] ^ rCon[i/4]; + tmp[1] = SBox[tmp[2]]; + tmp[2] = SBox[tmp[3]]; + tmp[3] = SBox[k]; + + } + expandedKey[4*i] = expandedKey[4*(i-4)] ^ tmp[0]; + expandedKey[4*i + 1] = expandedKey[4*(i-4) + 1] ^ tmp[1]; + expandedKey[4*i + 2] = expandedKey[4*(i-4) + 2] ^ tmp[2]; + expandedKey[4*i + 3] = expandedKey[4*(i-4) + 3] ^ tmp[3]; + } +} + + +void aes_128_encrypt (u8 input[16], u8 output[16]) { + u8 expandedKey[176]; + u8 key[16] = {0}; + + expandKey (key, expandedKey); + + for (int i = 0; i < 9; i++) { + + shiftRows (input); + shiftRows (expandedKey+16*i); + addRoundKey (input, expandedKey + 16*i); + subBytes (input); + mixColumns (input); + + } + + shiftRows (input); + shiftRows (expandedKey + 144); + addRoundKey (input, expandedKey + 144); + subBytes (input); + addRoundKey (input, expandedKey + 160); + + for (int i = 0; i < 16; i++) + output[i] = input[i]; + +} diff --git a/Android/Level4/app/src/main/c/whitebox/aes.h b/Android/Level4/app/src/main/c/whitebox/aes.h new file mode 100644 index 0000000..6ccfbb5 --- /dev/null +++ b/Android/Level4/app/src/main/c/whitebox/aes.h @@ -0,0 +1,51 @@ +#ifndef AES_H +#define AES_H + +#include +#include +#include +#include + +#define ROTL8(x,shift) ((u8) ((x) << (shift)) | ((x) >> (8 - (shift)))) + +typedef unsigned char u8; +typedef unsigned int u32; + +u8 sbox[256]; + +static const u8 SBox[256] = { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, + 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, + 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, + 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, + 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, + 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, + 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, + 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, + 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, + 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, + 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 +}; + +static const u8 rCon[11] = { + 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, + 0x20, 0x40, 0x80, 0x1b, 0x36 +}; + +void printState (u8 in[16]); +u8 gMul (u8 a, u8 b); +void subBytes (u8 state[16]); +void shiftRows (u8 state[16]); +void addRoundKey (u8 state[16], u8 roundKey[16]); +void mixColumns (u8 state[16]); +void expandKey (u8 key[16], u8 expandedKey[176]); +void aes_128_encrypt (u8 input[16], u8 output[16]); + + +#endif // AES_H diff --git a/Android/Level4/app/src/main/c/whitebox/aes_table.c b/Android/Level4/app/src/main/c/whitebox/aes_table.c new file mode 100644 index 0000000..536da06 --- /dev/null +++ b/Android/Level4/app/src/main/c/whitebox/aes_table.c @@ -0,0 +1,101 @@ +#include "aes.h" +#include "tables.h" + +//#include "../syscalls.h" +//#include "../mylibc.h" + +__attribute__((always_inline)) +void mixColumns_table(u8 state[16]) { + u8 out[16]; + u32 tmp; + for (int j = 0; j < 4; j++) + { + tmp = TyiTables[0][state[4*j]] ^ TyiTables[1][state[4*j + 1]] + ^ TyiTables[2][state[4*j + 2]] ^ TyiTables[3][state[4*j + 3]]; + out[4*j + 0] = (u8) (tmp >> 24); + out[4*j + 1] = (u8) (tmp >> 16); + out[4*j + 2] = (u8) (tmp >> 8); + out[4*j + 3] = (u8) (tmp >> 0); + } + + memcpy(state, out, sizeof(out)); +} + +__attribute__((always_inline)) +void aes_128_table_encrypt (u8 input[16], u8 output[16]) { + u8 shit[16]; + u32 a, b, c, d, aa, bb, cc, dd; + for (int i = 0; i < 9; i++) { + shiftRows (input); + + for (int j = 0; j < 4; j++) + { + a = TyiBoxes[i][4*j + 0][input[4*j + 0]]; + b = TyiBoxes[i][4*j + 1][input[4*j + 1]]; + c = TyiBoxes[i][4*j + 2][input[4*j + 2]]; + d = TyiBoxes[i][4*j + 3][input[4*j + 3]]; + + aa = xorTable[i][24*j + 0][(a >> 28) & 0xf][(b >> 28) & 0xf]; + bb = xorTable[i][24*j + 1][(c >> 28) & 0xf][(d >> 28) & 0xf]; + cc = xorTable[i][24*j + 2][(a >> 24) & 0xf][(b >> 24) & 0xf]; + dd = xorTable[i][24*j + 3][(c >> 24) & 0xf][(d >> 24) & 0xf]; + input[4*j + 0] = (xorTable[i][24*j + 4][aa][bb] << 4) | xorTable[i][24*j + 5][cc][dd]; + + aa = xorTable[i][24*j + 6][(a >> 20) & 0xf][(b >> 20) & 0xf]; + bb = xorTable[i][24*j + 7][(c >> 20) & 0xf][(d >> 20) & 0xf]; + cc = xorTable[i][24*j + 8][(a >> 16) & 0xf][(b >> 16) & 0xf]; + dd = xorTable[i][24*j + 9][(c >> 16) & 0xf][(d >> 16) & 0xf]; + input[4*j + 1] = (xorTable[i][24*j + 10][aa][bb] << 4) | xorTable[i][24*j + 11][cc][dd]; + + aa = xorTable[i][24*j + 12][(a >> 12) & 0xf][(b >> 12) & 0xf]; + bb = xorTable[i][24*j + 13][(c >> 12) & 0xf][(d >> 12) & 0xf]; + cc = xorTable[i][24*j + 14][(a >> 8) & 0xf][(b >> 8) & 0xf]; + dd = xorTable[i][24*j + 15][(c >> 8) & 0xf][(d >> 8) & 0xf]; + input[4*j + 2] = (xorTable[i][24*j + 16][aa][bb] << 4) | xorTable[i][24*j + 17][cc][dd]; + + aa = xorTable[i][24*j + 18][(a >> 4) & 0xf][(b >> 4) & 0xf]; + bb = xorTable[i][24*j + 19][(c >> 4) & 0xf][(d >> 4) & 0xf]; + cc = xorTable[i][24*j + 20][(a >> 0) & 0xf][(b >> 0) & 0xf]; + dd = xorTable[i][24*j + 21][(c >> 0) & 0xf][(d >> 0) & 0xf]; + input[4*j + 3] = (xorTable[i][24*j + 22][aa][bb] << 4) | xorTable[i][24*j + 23][cc][dd]; + + + a = mixBijOut[i][4*j + 0][input[4*j + 0]]; + b = mixBijOut[i][4*j + 1][input[4*j + 1]]; + c = mixBijOut[i][4*j + 2][input[4*j + 2]]; + d = mixBijOut[i][4*j + 3][input[4*j + 3]]; + + aa = xorTable[i][24*j + 0][(a >> 28) & 0xf][(b >> 28) & 0xf]; + bb = xorTable[i][24*j + 1][(c >> 28) & 0xf][(d >> 28) & 0xf]; + cc = xorTable[i][24*j + 2][(a >> 24) & 0xf][(b >> 24) & 0xf]; + dd = xorTable[i][24*j + 3][(c >> 24) & 0xf][(d >> 24) & 0xf]; + input[4*j + 0] = (xorTable[i][24*j + 4][aa][bb] << 4) | xorTable[i][24*j + 5][cc][dd]; + + aa = xorTable[i][24*j + 6][(a >> 20) & 0xf][(b >> 20) & 0xf]; + bb = xorTable[i][24*j + 7][(c >> 20) & 0xf][(d >> 20) & 0xf]; + cc = xorTable[i][24*j + 8][(a >> 16) & 0xf][(b >> 16) & 0xf]; + dd = xorTable[i][24*j + 9][(c >> 16) & 0xf][(d >> 16) & 0xf]; + input[4*j + 1] = (xorTable[i][24*j + 10][aa][bb] << 4) | xorTable[i][24*j + 11][cc][dd]; + + aa = xorTable[i][24*j + 12][(a >> 12) & 0xf][(b >> 12) & 0xf]; + bb = xorTable[i][24*j + 13][(c >> 12) & 0xf][(d >> 12) & 0xf]; + cc = xorTable[i][24*j + 14][(a >> 8) & 0xf][(b >> 8) & 0xf]; + dd = xorTable[i][24*j + 15][(c >> 8) & 0xf][(d >> 8) & 0xf]; + input[4*j + 2] = (xorTable[i][24*j + 16][aa][bb] << 4) | xorTable[i][24*j + 17][cc][dd]; + + aa = xorTable[i][24*j + 18][(a >> 4) & 0xf][(b >> 4) & 0xf]; + bb = xorTable[i][24*j + 19][(c >> 4) & 0xf][(d >> 4) & 0xf]; + cc = xorTable[i][24*j + 20][(a >> 0) & 0xf][(b >> 0) & 0xf]; + dd = xorTable[i][24*j + 21][(c >> 0) & 0xf][(d >> 0) & 0xf]; + input[4*j + 3] = (xorTable[i][24*j + 22][aa][bb] << 4) | xorTable[i][24*j + 23][cc][dd]; + } + } + shiftRows(input); + for (int j = 0; j < 16; j++) { + input[j] = TBoxes[9][j][input[j]]; + } + + for (int i = 0; i < 16; i++) + output[i] = input[i]; + +} \ No newline at end of file diff --git a/Android/Level4/app/src/main/c/whitebox/genTables.cpp b/Android/Level4/app/src/main/c/whitebox/genTables.cpp new file mode 100644 index 0000000..d88e5d1 --- /dev/null +++ b/Android/Level4/app/src/main/c/whitebox/genTables.cpp @@ -0,0 +1,301 @@ +extern "C" { +#include "aes.h" +} +#include "RandMat.h" + +u8 TBoxes[10][16][256]; +u32 TyiTables[4][256]; +u32 TyiBoxes[9][16][256]; +u32 mixBijIn[10][16][256]; +u32 mixBijOut[10][16][256]; +u8 xorTable[9][96][16][16]; + +typedef union { + u8 bytes[4]; + u32 all; +} tyi; + +vec_GF2 int2vec (u32 iIn, int size) +{ + vec_GF2 vOut; + vOut.SetLength(size); + for (int i = 0; i < size; i++) + { + if ((iIn >> i) % 2 == 1) + { + vOut[size-1 - i] = 1; + } + else + { + vOut[size-1 - i] = 0; + } + } + return vOut; +} + +u32 vec2int (vec_GF2 vIn, int size) +{ + u32 iOut = 0; + for (int i = 0; i < size; i++) + { + iOut *= 2; + if (vIn[i] == 1) + iOut += 1; + } + return iOut; +} + +void computeTables (u8 expandedKey[176]) +{ + // Tyi tables implement MixColumns + for (int j = 0; j < 4; j++) + { + for (int x = 0; x < 256; x++) + { + TyiTables[0][x] = (gMul(2, x) << 24) | (x << 16) | (x << 8) | gMul(3, x); + TyiTables[1][x] = (gMul(3, x) << 24) | (gMul(2, x) << 16) | (x << 8) | x; + TyiTables[2][x] = (x << 24) | (gMul(3, x) << 16) | (gMul(2, x) << 8) | x; + TyiTables[3][x] = (x << 24) | (x << 16) | (gMul(3, x) << 8) | gMul(2, x); + } + } + + vec_GF2 vAA, vBB, vCC, vDD; + u32 aa, bb, cc, dd; + RandMat mb_8x8[10][16], mb_32x32[10][4]; + + // Initialize random mixing bijections + for (int i = 0; i < 10; i++) + { + for (int k = 0; k < 4; k++) { + mb_32x32[i][k].init(32); + } + + for (int k = 0; k < 16; k++) { + mb_8x8[i][k].init(8); + } + } + // Compute tboxes and compose them at their output with Tyi tables + for (int i = 0; i < 10; i++) + { + shiftRows (expandedKey + 16*i); + + for (int j = 0; j < 16; j++) + { + for (int x = 0; x < 256; x++) + { + mixBijIn[i][j][x] = vec2int(mb_8x8[i][j].mat * int2vec(x, 8), 8); + } + for (int x = 0; x < 256; x++) + { + u32 tmp = x; + // Input mixing bijection + if ((i > 0) && (i < 9)) { + tmp = vec2int(mb_8x8[i-1][j].invMat * int2vec(x, 8), 8); + } + + if ((i > 0) && (i < 9)) + { + tmp = mixBijIn[i-1][j][tmp]; + } + tmp = SBox[tmp ^ expandedKey[16 * i + j]]; + TBoxes[i][j][x] = tmp; + + if (i == 9) + { + TBoxes[i][j][x] ^= expandedKey[160 + j]; + } + else + { + TyiBoxes[i][j][x] = TyiTables[j % 4][tmp]; + } + } + } + } + + for (int i = 0; i < 10; i++) + { + for (int j = 0; j < 4; j++) + { + for (int x = 0; x < 256; x++) + { + if (i < 9) + { + mixBijIn[i][4*j + 0][x] = vec2int(mb_8x8[i][4*j + 0].mat * int2vec(x, 8), 8); + mixBijIn[i][4*j + 1][x] = vec2int(mb_8x8[i][4*j + 1].mat * int2vec(x, 8), 8); + mixBijIn[i][4*j + 2][x] = vec2int(mb_8x8[i][4*j + 2].mat * int2vec(x, 8), 8); + mixBijIn[i][4*j + 3][x] = vec2int(mb_8x8[i][4*j + 3].mat * int2vec(x, 8), 8); + + mixBijIn[i][4*j + 0][x] = x; + mixBijIn[i][4*j + 1][x] = x; + mixBijIn[i][4*j + 2][x] = x; + mixBijIn[i][4*j + 3][x] = x; + } + } + + for (int x = 0; x < 256; x++) + { + if (i < 9) + { + vAA = int2vec(TyiBoxes[i][4*j + 0][x], 32); + vBB = int2vec(TyiBoxes[i][4*j + 1][x], 32); + vCC = int2vec(TyiBoxes[i][4*j + 2][x], 32); + vDD = int2vec(TyiBoxes[i][4*j + 3][x], 32); + + TyiBoxes[i][4*j + 0][x] = vec2int(mb_32x32[i][j].mat * vAA, 32); + TyiBoxes[i][4*j + 1][x] = vec2int(mb_32x32[i][j].mat * vBB, 32); + TyiBoxes[i][4*j + 2][x] = vec2int(mb_32x32[i][j].mat * vCC, 32); + TyiBoxes[i][4*j + 3][x] = vec2int(mb_32x32[i][j].mat * vDD, 32); + + vAA = int2vec(x << 24, 32); + vBB = int2vec(x << 16, 32); + vCC = int2vec(x << 8, 32); + vDD = int2vec(x << 0, 32); + + aa = vec2int(mb_32x32[i][j].invMat * vAA, 32); + bb = vec2int(mb_32x32[i][j].invMat * vBB, 32); + cc = vec2int(mb_32x32[i][j].invMat * vCC, 32); + dd = vec2int(mb_32x32[i][j].invMat * vDD, 32); + + mixBijOut[i][4*j + 0][x] = (mixBijIn[i][4*j + 0][(aa >> 24) & 0xff] << 24) + | (mixBijIn[i][4*j + 1][(aa >> 16) & 0xff] << 16) + | (mixBijIn[i][4*j + 2][(aa >> 8) & 0xff] << 8) + | (mixBijIn[i][4*j + 3][(aa >> 0) & 0xff] << 0); + mixBijOut[i][4*j + 1][x] = (mixBijIn[i][4*j + 0][(bb >> 24) & 0xff] << 24) + | (mixBijIn[i][4*j + 1][(bb >> 16) & 0xff] << 16) + | (mixBijIn[i][4*j + 2][(bb >> 8) & 0xff] << 8) + | (mixBijIn[i][4*j + 3][(bb >> 0) & 0xff] << 0); + mixBijOut[i][4*j + 2][x] = (mixBijIn[i][4*j + 0][(cc >> 24) & 0xff] << 24) + | (mixBijIn[i][4*j + 1][(cc >> 16) & 0xff] << 16) + | (mixBijIn[i][4*j + 2][(cc >> 8) & 0xff] << 8) + | (mixBijIn[i][4*j + 3][(cc >> 0) & 0xff] << 0); + mixBijOut[i][4*j + 3][x] = (mixBijIn[i][4*j + 0][(dd >> 24) & 0xff] << 24) + | (mixBijIn[i][4*j + 1][(dd >> 16) & 0xff] << 16) + | (mixBijIn[i][4*j + 2][(dd >> 8) & 0xff] << 8) + | (mixBijIn[i][4*j + 3][(dd >> 0) & 0xff] << 0); + } + } + + } + } + for (int i = 0; i < 9; i++) + { + for (int j = 0; j < 96; j++) + { + for (int x = 0; x < 16; x++) + { + for (int y = 0; y < 16; y++) + { + xorTable[i][j][x][y] = x ^ y; + } + } + } + } +} + +void printTables() +{ + FILE *tables = fopen ("tables.h", "w"); + fprintf(tables, "unsigned char TBoxes[10][16][256] =\n{\n\t"); + for (int i = 0; i < 10; i++) + { + fprintf(tables, "{\n\t\t"); + for (int j = 0; j < 16; j++) + { + fprintf(tables, "{\n\t\t\t"); + for (int x = 0; x < 256; x++) + { + fprintf(tables, "0x%.2x%s", TBoxes[i][j][x], (x != 255) ? ", " : ""); + } + fprintf(tables, "\n\t\t}%s\n\t\t", (j != 15) ? ", " : ""); + } + fprintf(tables, "}%s\n", (i != 9) ? ", " : ""); + } + fprintf (tables, "};\n"); + + fprintf(tables, "unsigned int TyiTables[4][256] =\n{\n\t"); + for (int j = 0; j < 4; j++) + { + fprintf(tables, "{\n\t\t\t"); + for (int x = 0; x < 256; x++) + { + fprintf(tables, "0x%.8x%s", TyiTables[j][x], (x != 255) ? ", " : ""); + } + fprintf(tables, "\n\t\t}%s\n\t\t", (j != 3) ? ", " : ""); + } + fprintf(tables, "};\n"); + + fprintf(tables, "unsigned int TyiBoxes[9][16][256] =\n{\n\t"); + for (int i = 0; i < 9; i++) + { + fprintf(tables, "{\n\t\t"); + for (int j = 0; j < 16; j++) + { + fprintf(tables, "{\n\t\t\t"); + for (int x = 0; x < 256; x++) + { + fprintf(tables, "0x%.8x%s", TyiBoxes[i][j][x], (x != 255) ? ", " : ""); + } + fprintf(tables, "\n\t\t}%s\n\t\t", (j != 15) ? ", " : ""); + } + fprintf(tables, "}%s\n", (i != 8) ? ", " : ""); + } + fprintf (tables, "};\n"); + + fprintf(tables, "unsigned int mixBijOut[10][16][256] =\n{\n\t"); + for (int i = 0; i < 10; i++) + { + fprintf(tables, "{\n\t\t"); + for (int j = 0; j < 16; j++) + { + fprintf(tables, "{\n\t\t\t"); + for (int x = 0; x < 256; x++) + { + fprintf(tables, "0x%.8x%s", mixBijOut[i][j][x], (x != 255) ? ", " : ""); + } + fprintf(tables, "\n\t\t}%s\n\t\t", (j != 15) ? ", " : ""); + } + fprintf(tables, "}%s\n", (i != 9) ? ", " : ""); + } + fprintf (tables, "};\n"); + + fprintf(tables, "unsigned char xorTable[9][96][16][16] =\n{\n\t"); + for (int i = 0; i < 9; i++) + { + fprintf(tables, "{\n\t\t"); + for (int j = 0; j < 96; j++) + { + fprintf(tables, "{\n\t\t"); + for (int x = 0; x < 16; x++) + { + fprintf(tables, "{\n\t\t\t"); + for (int y = 0; y < 16; y++) + { + fprintf(tables, "0x%.1x%s", xorTable[i][j][x][y], (y != 15) ? ", " : ""); + } + fprintf(tables, "\n\t\t}%s\n\t\t", (x != 15) ? ", " : ""); + } + fprintf(tables, "\n\t\t}%s\n\t\t", (j != 95) ? ", " : ""); + } + fprintf(tables, "}%s\n", (i != 8) ? ", " : ""); + } + fprintf(tables, "};\n"); + + fclose (tables); +} + + + +int main(void) { + u8 expandedKey[176]; + + // key: r2p4y1sN0wSecur3 + u8 key[16] = {0x72,0x32,0x70,0x34,0x79, 0x31,0x73,0x4e,0x30,0x77,0x53,0x65,0x63,0x75,0x72,0x33}; + + printf("Generating tables.h...\n"); + expandKey (key, expandedKey); + computeTables(expandedKey); + printTables(); + printf("Done!\n"); + + return 0; +} \ No newline at end of file diff --git a/Android/Level4/app/src/main/c/whitebox/tables.h b/Android/Level4/app/src/main/c/whitebox/tables.h new file mode 100644 index 0000000..b22d1c1 --- /dev/null +++ b/Android/Level4/app/src/main/c/whitebox/tables.h @@ -0,0 +1,45559 @@ +unsigned char TBoxes[10][16][256] = +{ +{ +{ +0x40, 0x8f, 0x51, 0xa3, 0x38, 0xf5, 0x92, 0x9d, 0xda, 0x21, 0xbc, 0xb6, 0xf3, 0xd2, 0x10, 0xff, 0xaa, 0xfb, 0xd0, 0xef, 0x33, 0x85, 0x43, 0x4d, 0x02, 0x7f, 0x45, 0xf9, 0x9f, 0xa8, 0x50, 0x3c, 0x00, 0xed, 0x53, 0xd1, 0xb1, 0x5b, 0x20, 0xfc, 0xbe, 0x39, 0x6a, 0xcb, 0x58, 0xcf, 0x4a, 0x4c, 0x2c, 0x1a, 0x09, 0x83, 0x5a, 0xa0, 0x1b, 0x6e, 0xd6, 0xb3, 0x52, 0x3b, 0x2f, 0x84, 0x29, 0xe3, 0x23, 0xc3, 0x04, 0xc7, 0x05, 0x9a, 0x18, 0x96, 0x80, 0xe2, 0x07, 0x12, 0xb2, 0x75, 0xeb, 0x27, 0x93, 0x26, 0xb7, 0xfd, 0xf7, 0xcc, 0x36, 0x3f, 0xe5, 0xf1, 0x34, 0xa5, 0x31, 0x15, 0x71, 0xd8, 0xc9, 0x7d, 0xca, 0x82, 0x47, 0xf0, 0xfa, 0x59, 0xa2, 0xaf, 0xad, 0xd4, 0x72, 0xc0, 0x9c, 0xa4, 0x77, 0x7b, 0x63, 0x7c, 0x6f, 0xc5, 0xf2, 0x6b, 0x67, 0x2b, 0x30, 0x01, 0xab, 0x76, 0xfe, 0xd7, 0x89, 0x0d, 0x8c, 0xa1, 0x42, 0x68, 0xbf, 0xe6, 0x2d, 0x0f, 0x41, 0x99, 0xbb, 0x16, 0xb0, 0x54, 0x98, 0x11, 0xe1, 0xf8, 0x8e, 0x94, 0x69, 0xd9, 0x87, 0xe9, 0x9b, 0x1e, 0x28, 0xdf, 0xce, 0x55, 0xb5, 0x66, 0x70, 0x3e, 0xf6, 0x0e, 0x48, 0x03, 0x57, 0xb9, 0x61, 0x35, 0x1d, 0x9e, 0x86, 0xc1, 0x25, 0x2e, 0xba, 0x78, 0xb4, 0xc6, 0x1c, 0xa6, 0x74, 0x1f, 0xe8, 0xdd, 0x8b, 0x8a, 0x4b, 0xbd, 0x37, 0x6d, 0xe7, 0xc8, 0x4e, 0xa9, 0x8d, 0xd5, 0xf4, 0xea, 0x6c, 0x56, 0xae, 0x08, 0x65, 0x7a, 0x3a, 0x0a, 0xe0, 0x32, 0x24, 0x5c, 0x49, 0x06, 0xac, 0x62, 0xc2, 0xd3, 0xe4, 0x79, 0x91, 0x95, 0x4f, 0xdc, 0x60, 0x81, 0x90, 0x88, 0x22, 0x2a, 0xb8, 0x14, 0x46, 0xee, 0x0b, 0xdb, 0xde, 0x5e, 0x13, 0xec, 0xcd, 0x0c, 0x44, 0x17, 0x5f, 0x97, 0x7e, 0x3d, 0xc4, 0xa7, 0x19, 0x73, 0x64, 0x5d +}, +{ +0xc7, 0x04, 0xc3, 0x23, 0x96, 0x18, 0x9a, 0x05, 0x12, 0x07, 0xe2, 0x80, 0x27, 0xeb, 0x75, 0xb2, 0xfd, 0xb7, 0x26, 0x93, 0x3f, 0x36, 0xcc, 0xf7, 0xa5, 0x34, 0xf1, 0xe5, 0xd8, 0x71, 0x15, 0x31, 0x82, 0xca, 0x7d, 0xc9, 0x59, 0xfa, 0xf0, 0x47, 0xd4, 0xad, 0xaf, 0xa2, 0xa4, 0x9c, 0xc0, 0x72, 0x7c, 0x63, 0x7b, 0x77, 0x6b, 0xf2, 0xc5, 0x6f, 0x01, 0x30, 0x2b, 0x67, 0xd7, 0xfe, 0x76, 0xab, 0xa3, 0x51, 0x8f, 0x40, 0x9d, 0x92, 0xf5, 0x38, 0xb6, 0xbc, 0x21, 0xda, 0xff, 0x10, 0xd2, 0xf3, 0xef, 0xd0, 0xfb, 0xaa, 0x4d, 0x43, 0x85, 0x33, 0xf9, 0x45, 0x7f, 0x02, 0x3c, 0x50, 0xa8, 0x9f, 0xd1, 0x53, 0xed, 0x00, 0xfc, 0x20, 0x5b, 0xb1, 0xcb, 0x6a, 0x39, 0xbe, 0x4c, 0x4a, 0xcf, 0x58, 0x83, 0x09, 0x1a, 0x2c, 0x6e, 0x1b, 0xa0, 0x5a, 0x3b, 0x52, 0xb3, 0xd6, 0xe3, 0x29, 0x84, 0x2f, 0xc8, 0xe7, 0x6d, 0x37, 0xd5, 0x8d, 0xa9, 0x4e, 0x56, 0x6c, 0xea, 0xf4, 0x7a, 0x65, 0x08, 0xae, 0x32, 0xe0, 0x0a, 0x3a, 0x06, 0x49, 0x5c, 0x24, 0xd3, 0xc2, 0x62, 0xac, 0x95, 0x91, 0x79, 0xe4, 0x81, 0x60, 0xdc, 0x4f, 0x2a, 0x22, 0x88, 0x90, 0xee, 0x46, 0x14, 0xb8, 0x5e, 0xde, 0xdb, 0x0b, 0x0c, 0xcd, 0xec, 0x13, 0x97, 0x5f, 0x17, 0x44, 0xa7, 0xc4, 0x3d, 0x7e, 0x5d, 0x64, 0x73, 0x19, 0xa1, 0x8c, 0x0d, 0x89, 0xe6, 0xbf, 0x68, 0x42, 0x99, 0x41, 0x0f, 0x2d, 0x54, 0xb0, 0x16, 0xbb, 0xf8, 0xe1, 0x11, 0x98, 0xd9, 0x69, 0x94, 0x8e, 0x1e, 0x9b, 0xe9, 0x87, 0x55, 0xce, 0xdf, 0x28, 0x3e, 0x70, 0x66, 0xb5, 0x03, 0x48, 0x0e, 0xf6, 0x35, 0x61, 0xb9, 0x57, 0xc1, 0x86, 0x9e, 0x1d, 0x78, 0xba, 0x2e, 0x25, 0xa6, 0x1c, 0xc6, 0xb4, 0xdd, 0xe8, 0x1f, 0x74, 0xbd, 0x4b, 0x8a, 0x8b +}, +{ +0xed, 0x00, 0xd1, 0x53, 0x5b, 0xb1, 0xfc, 0x20, 0x39, 0xbe, 0xcb, 0x6a, 0xcf, 0x58, 0x4c, 0x4a, 0x1a, 0x2c, 0x83, 0x09, 0xa0, 0x5a, 0x6e, 0x1b, 0xb3, 0xd6, 0x3b, 0x52, 0x84, 0x2f, 0xe3, 0x29, 0x8f, 0x40, 0xa3, 0x51, 0xf5, 0x38, 0x9d, 0x92, 0x21, 0xda, 0xb6, 0xbc, 0xd2, 0xf3, 0xff, 0x10, 0xfb, 0xaa, 0xef, 0xd0, 0x85, 0x33, 0x4d, 0x43, 0x7f, 0x02, 0xf9, 0x45, 0xa8, 0x9f, 0x3c, 0x50, 0x7d, 0xc9, 0x82, 0xca, 0xf0, 0x47, 0x59, 0xfa, 0xaf, 0xa2, 0xd4, 0xad, 0xc0, 0x72, 0xa4, 0x9c, 0x7b, 0x77, 0x7c, 0x63, 0xc5, 0x6f, 0x6b, 0xf2, 0x2b, 0x67, 0x01, 0x30, 0x76, 0xab, 0xd7, 0xfe, 0xc3, 0x23, 0xc7, 0x04, 0x9a, 0x05, 0x96, 0x18, 0xe2, 0x80, 0x12, 0x07, 0x75, 0xb2, 0x27, 0xeb, 0x26, 0x93, 0xfd, 0xb7, 0xcc, 0xf7, 0x3f, 0x36, 0xf1, 0xe5, 0xa5, 0x34, 0x15, 0x31, 0xd8, 0x71, 0x66, 0xb5, 0x3e, 0x70, 0x0e, 0xf6, 0x03, 0x48, 0xb9, 0x57, 0x35, 0x61, 0x9e, 0x1d, 0xc1, 0x86, 0x2e, 0x25, 0x78, 0xba, 0xc6, 0xb4, 0xa6, 0x1c, 0x1f, 0x74, 0xdd, 0xe8, 0x8a, 0x8b, 0xbd, 0x4b, 0x0d, 0x89, 0xa1, 0x8c, 0x68, 0x42, 0xe6, 0xbf, 0x0f, 0x2d, 0x99, 0x41, 0x16, 0xbb, 0x54, 0xb0, 0x11, 0x98, 0xf8, 0xe1, 0x94, 0x8e, 0xd9, 0x69, 0xe9, 0x87, 0x1e, 0x9b, 0xdf, 0x28, 0x55, 0xce, 0xdc, 0x4f, 0x81, 0x60, 0x88, 0x90, 0x2a, 0x22, 0x14, 0xb8, 0xee, 0x46, 0xdb, 0x0b, 0x5e, 0xde, 0xec, 0x13, 0x0c, 0xcd, 0x17, 0x44, 0x97, 0x5f, 0x3d, 0x7e, 0xa7, 0xc4, 0x73, 0x19, 0x5d, 0x64, 0x6d, 0x37, 0xc8, 0xe7, 0xa9, 0x4e, 0xd5, 0x8d, 0xea, 0xf4, 0x56, 0x6c, 0x08, 0xae, 0x7a, 0x65, 0x0a, 0x3a, 0x32, 0xe0, 0x5c, 0x24, 0x06, 0x49, 0x62, 0xac, 0xd3, 0xc2, 0x79, 0xe4, 0x95, 0x91 +}, +{ +0xc3, 0x23, 0xc7, 0x04, 0x9a, 0x05, 0x96, 0x18, 0xe2, 0x80, 0x12, 0x07, 0x75, 0xb2, 0x27, 0xeb, 0x26, 0x93, 0xfd, 0xb7, 0xcc, 0xf7, 0x3f, 0x36, 0xf1, 0xe5, 0xa5, 0x34, 0x15, 0x31, 0xd8, 0x71, 0x7d, 0xc9, 0x82, 0xca, 0xf0, 0x47, 0x59, 0xfa, 0xaf, 0xa2, 0xd4, 0xad, 0xc0, 0x72, 0xa4, 0x9c, 0x7b, 0x77, 0x7c, 0x63, 0xc5, 0x6f, 0x6b, 0xf2, 0x2b, 0x67, 0x01, 0x30, 0x76, 0xab, 0xd7, 0xfe, 0x8f, 0x40, 0xa3, 0x51, 0xf5, 0x38, 0x9d, 0x92, 0x21, 0xda, 0xb6, 0xbc, 0xd2, 0xf3, 0xff, 0x10, 0xfb, 0xaa, 0xef, 0xd0, 0x85, 0x33, 0x4d, 0x43, 0x7f, 0x02, 0xf9, 0x45, 0xa8, 0x9f, 0x3c, 0x50, 0xed, 0x00, 0xd1, 0x53, 0x5b, 0xb1, 0xfc, 0x20, 0x39, 0xbe, 0xcb, 0x6a, 0xcf, 0x58, 0x4c, 0x4a, 0x1a, 0x2c, 0x83, 0x09, 0xa0, 0x5a, 0x6e, 0x1b, 0xb3, 0xd6, 0x3b, 0x52, 0x84, 0x2f, 0xe3, 0x29, 0x6d, 0x37, 0xc8, 0xe7, 0xa9, 0x4e, 0xd5, 0x8d, 0xea, 0xf4, 0x56, 0x6c, 0x08, 0xae, 0x7a, 0x65, 0x0a, 0x3a, 0x32, 0xe0, 0x5c, 0x24, 0x06, 0x49, 0x62, 0xac, 0xd3, 0xc2, 0x79, 0xe4, 0x95, 0x91, 0xdc, 0x4f, 0x81, 0x60, 0x88, 0x90, 0x2a, 0x22, 0x14, 0xb8, 0xee, 0x46, 0xdb, 0x0b, 0x5e, 0xde, 0xec, 0x13, 0x0c, 0xcd, 0x17, 0x44, 0x97, 0x5f, 0x3d, 0x7e, 0xa7, 0xc4, 0x73, 0x19, 0x5d, 0x64, 0x0d, 0x89, 0xa1, 0x8c, 0x68, 0x42, 0xe6, 0xbf, 0x0f, 0x2d, 0x99, 0x41, 0x16, 0xbb, 0x54, 0xb0, 0x11, 0x98, 0xf8, 0xe1, 0x94, 0x8e, 0xd9, 0x69, 0xe9, 0x87, 0x1e, 0x9b, 0xdf, 0x28, 0x55, 0xce, 0x66, 0xb5, 0x3e, 0x70, 0x0e, 0xf6, 0x03, 0x48, 0xb9, 0x57, 0x35, 0x61, 0x9e, 0x1d, 0xc1, 0x86, 0x2e, 0x25, 0x78, 0xba, 0xc6, 0xb4, 0xa6, 0x1c, 0x1f, 0x74, 0xdd, 0xe8, 0x8a, 0x8b, 0xbd, 0x4b +}, +{ +0xb6, 0xbc, 0x21, 0xda, 0xff, 0x10, 0xd2, 0xf3, 0xa3, 0x51, 0x8f, 0x40, 0x9d, 0x92, 0xf5, 0x38, 0xf9, 0x45, 0x7f, 0x02, 0x3c, 0x50, 0xa8, 0x9f, 0xef, 0xd0, 0xfb, 0xaa, 0x4d, 0x43, 0x85, 0x33, 0xcb, 0x6a, 0x39, 0xbe, 0x4c, 0x4a, 0xcf, 0x58, 0xd1, 0x53, 0xed, 0x00, 0xfc, 0x20, 0x5b, 0xb1, 0x3b, 0x52, 0xb3, 0xd6, 0xe3, 0x29, 0x84, 0x2f, 0x83, 0x09, 0x1a, 0x2c, 0x6e, 0x1b, 0xa0, 0x5a, 0x12, 0x07, 0xe2, 0x80, 0x27, 0xeb, 0x75, 0xb2, 0xc7, 0x04, 0xc3, 0x23, 0x96, 0x18, 0x9a, 0x05, 0xa5, 0x34, 0xf1, 0xe5, 0xd8, 0x71, 0x15, 0x31, 0xfd, 0xb7, 0x26, 0x93, 0x3f, 0x36, 0xcc, 0xf7, 0xd4, 0xad, 0xaf, 0xa2, 0xa4, 0x9c, 0xc0, 0x72, 0x82, 0xca, 0x7d, 0xc9, 0x59, 0xfa, 0xf0, 0x47, 0x01, 0x30, 0x2b, 0x67, 0xd7, 0xfe, 0x76, 0xab, 0x7c, 0x63, 0x7b, 0x77, 0x6b, 0xf2, 0xc5, 0x6f, 0x99, 0x41, 0x0f, 0x2d, 0x54, 0xb0, 0x16, 0xbb, 0xa1, 0x8c, 0x0d, 0x89, 0xe6, 0xbf, 0x68, 0x42, 0x1e, 0x9b, 0xe9, 0x87, 0x55, 0xce, 0xdf, 0x28, 0xf8, 0xe1, 0x11, 0x98, 0xd9, 0x69, 0x94, 0x8e, 0x35, 0x61, 0xb9, 0x57, 0xc1, 0x86, 0x9e, 0x1d, 0x3e, 0x70, 0x66, 0xb5, 0x03, 0x48, 0x0e, 0xf6, 0xdd, 0xe8, 0x1f, 0x74, 0xbd, 0x4b, 0x8a, 0x8b, 0x78, 0xba, 0x2e, 0x25, 0xa6, 0x1c, 0xc6, 0xb4, 0x56, 0x6c, 0xea, 0xf4, 0x7a, 0x65, 0x08, 0xae, 0xc8, 0xe7, 0x6d, 0x37, 0xd5, 0x8d, 0xa9, 0x4e, 0xd3, 0xc2, 0x62, 0xac, 0x95, 0x91, 0x79, 0xe4, 0x32, 0xe0, 0x0a, 0x3a, 0x06, 0x49, 0x5c, 0x24, 0xee, 0x46, 0x14, 0xb8, 0x5e, 0xde, 0xdb, 0x0b, 0x81, 0x60, 0xdc, 0x4f, 0x2a, 0x22, 0x88, 0x90, 0xa7, 0xc4, 0x3d, 0x7e, 0x5d, 0x64, 0x73, 0x19, 0x0c, 0xcd, 0xec, 0x13, 0x97, 0x5f, 0x17, 0x44 +}, +{ +0xf5, 0x38, 0x9d, 0x92, 0x8f, 0x40, 0xa3, 0x51, 0xd2, 0xf3, 0xff, 0x10, 0x21, 0xda, 0xb6, 0xbc, 0x85, 0x33, 0x4d, 0x43, 0xfb, 0xaa, 0xef, 0xd0, 0xa8, 0x9f, 0x3c, 0x50, 0x7f, 0x02, 0xf9, 0x45, 0x5b, 0xb1, 0xfc, 0x20, 0xed, 0x00, 0xd1, 0x53, 0xcf, 0x58, 0x4c, 0x4a, 0x39, 0xbe, 0xcb, 0x6a, 0xa0, 0x5a, 0x6e, 0x1b, 0x1a, 0x2c, 0x83, 0x09, 0x84, 0x2f, 0xe3, 0x29, 0xb3, 0xd6, 0x3b, 0x52, 0x9a, 0x05, 0x96, 0x18, 0xc3, 0x23, 0xc7, 0x04, 0x75, 0xb2, 0x27, 0xeb, 0xe2, 0x80, 0x12, 0x07, 0xcc, 0xf7, 0x3f, 0x36, 0x26, 0x93, 0xfd, 0xb7, 0x15, 0x31, 0xd8, 0x71, 0xf1, 0xe5, 0xa5, 0x34, 0xf0, 0x47, 0x59, 0xfa, 0x7d, 0xc9, 0x82, 0xca, 0xc0, 0x72, 0xa4, 0x9c, 0xaf, 0xa2, 0xd4, 0xad, 0xc5, 0x6f, 0x6b, 0xf2, 0x7b, 0x77, 0x7c, 0x63, 0x76, 0xab, 0xd7, 0xfe, 0x2b, 0x67, 0x01, 0x30, 0x68, 0x42, 0xe6, 0xbf, 0x0d, 0x89, 0xa1, 0x8c, 0x16, 0xbb, 0x54, 0xb0, 0x0f, 0x2d, 0x99, 0x41, 0x94, 0x8e, 0xd9, 0x69, 0x11, 0x98, 0xf8, 0xe1, 0xdf, 0x28, 0x55, 0xce, 0xe9, 0x87, 0x1e, 0x9b, 0x0e, 0xf6, 0x03, 0x48, 0x66, 0xb5, 0x3e, 0x70, 0x9e, 0x1d, 0xc1, 0x86, 0xb9, 0x57, 0x35, 0x61, 0xc6, 0xb4, 0xa6, 0x1c, 0x2e, 0x25, 0x78, 0xba, 0x8a, 0x8b, 0xbd, 0x4b, 0x1f, 0x74, 0xdd, 0xe8, 0xa9, 0x4e, 0xd5, 0x8d, 0x6d, 0x37, 0xc8, 0xe7, 0x08, 0xae, 0x7a, 0x65, 0xea, 0xf4, 0x56, 0x6c, 0x5c, 0x24, 0x06, 0x49, 0x0a, 0x3a, 0x32, 0xe0, 0x79, 0xe4, 0x95, 0x91, 0x62, 0xac, 0xd3, 0xc2, 0x88, 0x90, 0x2a, 0x22, 0xdc, 0x4f, 0x81, 0x60, 0xdb, 0x0b, 0x5e, 0xde, 0x14, 0xb8, 0xee, 0x46, 0x17, 0x44, 0x97, 0x5f, 0xec, 0x13, 0x0c, 0xcd, 0x73, 0x19, 0x5d, 0x64, 0x3d, 0x7e, 0xa7, 0xc4 +}, +{ +0x40, 0x8f, 0x51, 0xa3, 0x38, 0xf5, 0x92, 0x9d, 0xda, 0x21, 0xbc, 0xb6, 0xf3, 0xd2, 0x10, 0xff, 0xaa, 0xfb, 0xd0, 0xef, 0x33, 0x85, 0x43, 0x4d, 0x02, 0x7f, 0x45, 0xf9, 0x9f, 0xa8, 0x50, 0x3c, 0x00, 0xed, 0x53, 0xd1, 0xb1, 0x5b, 0x20, 0xfc, 0xbe, 0x39, 0x6a, 0xcb, 0x58, 0xcf, 0x4a, 0x4c, 0x2c, 0x1a, 0x09, 0x83, 0x5a, 0xa0, 0x1b, 0x6e, 0xd6, 0xb3, 0x52, 0x3b, 0x2f, 0x84, 0x29, 0xe3, 0x23, 0xc3, 0x04, 0xc7, 0x05, 0x9a, 0x18, 0x96, 0x80, 0xe2, 0x07, 0x12, 0xb2, 0x75, 0xeb, 0x27, 0x93, 0x26, 0xb7, 0xfd, 0xf7, 0xcc, 0x36, 0x3f, 0xe5, 0xf1, 0x34, 0xa5, 0x31, 0x15, 0x71, 0xd8, 0xc9, 0x7d, 0xca, 0x82, 0x47, 0xf0, 0xfa, 0x59, 0xa2, 0xaf, 0xad, 0xd4, 0x72, 0xc0, 0x9c, 0xa4, 0x77, 0x7b, 0x63, 0x7c, 0x6f, 0xc5, 0xf2, 0x6b, 0x67, 0x2b, 0x30, 0x01, 0xab, 0x76, 0xfe, 0xd7, 0x89, 0x0d, 0x8c, 0xa1, 0x42, 0x68, 0xbf, 0xe6, 0x2d, 0x0f, 0x41, 0x99, 0xbb, 0x16, 0xb0, 0x54, 0x98, 0x11, 0xe1, 0xf8, 0x8e, 0x94, 0x69, 0xd9, 0x87, 0xe9, 0x9b, 0x1e, 0x28, 0xdf, 0xce, 0x55, 0xb5, 0x66, 0x70, 0x3e, 0xf6, 0x0e, 0x48, 0x03, 0x57, 0xb9, 0x61, 0x35, 0x1d, 0x9e, 0x86, 0xc1, 0x25, 0x2e, 0xba, 0x78, 0xb4, 0xc6, 0x1c, 0xa6, 0x74, 0x1f, 0xe8, 0xdd, 0x8b, 0x8a, 0x4b, 0xbd, 0x37, 0x6d, 0xe7, 0xc8, 0x4e, 0xa9, 0x8d, 0xd5, 0xf4, 0xea, 0x6c, 0x56, 0xae, 0x08, 0x65, 0x7a, 0x3a, 0x0a, 0xe0, 0x32, 0x24, 0x5c, 0x49, 0x06, 0xac, 0x62, 0xc2, 0xd3, 0xe4, 0x79, 0x91, 0x95, 0x4f, 0xdc, 0x60, 0x81, 0x90, 0x88, 0x22, 0x2a, 0xb8, 0x14, 0x46, 0xee, 0x0b, 0xdb, 0xde, 0x5e, 0x13, 0xec, 0xcd, 0x0c, 0x44, 0x17, 0x5f, 0x97, 0x7e, 0x3d, 0xc4, 0xa7, 0x19, 0x73, 0x64, 0x5d +}, +{ +0x18, 0x96, 0x05, 0x9a, 0x04, 0xc7, 0x23, 0xc3, 0xeb, 0x27, 0xb2, 0x75, 0x07, 0x12, 0x80, 0xe2, 0x36, 0x3f, 0xf7, 0xcc, 0xb7, 0xfd, 0x93, 0x26, 0x71, 0xd8, 0x31, 0x15, 0x34, 0xa5, 0xe5, 0xf1, 0xfa, 0x59, 0x47, 0xf0, 0xca, 0x82, 0xc9, 0x7d, 0x9c, 0xa4, 0x72, 0xc0, 0xad, 0xd4, 0xa2, 0xaf, 0xf2, 0x6b, 0x6f, 0xc5, 0x63, 0x7c, 0x77, 0x7b, 0xfe, 0xd7, 0xab, 0x76, 0x30, 0x01, 0x67, 0x2b, 0x92, 0x9d, 0x38, 0xf5, 0x51, 0xa3, 0x40, 0x8f, 0x10, 0xff, 0xf3, 0xd2, 0xbc, 0xb6, 0xda, 0x21, 0x43, 0x4d, 0x33, 0x85, 0xd0, 0xef, 0xaa, 0xfb, 0x50, 0x3c, 0x9f, 0xa8, 0x45, 0xf9, 0x02, 0x7f, 0x20, 0xfc, 0xb1, 0x5b, 0x53, 0xd1, 0x00, 0xed, 0x4a, 0x4c, 0x58, 0xcf, 0x6a, 0xcb, 0xbe, 0x39, 0x1b, 0x6e, 0x5a, 0xa0, 0x09, 0x83, 0x2c, 0x1a, 0x29, 0xe3, 0x2f, 0x84, 0x52, 0x3b, 0xd6, 0xb3, 0x8d, 0xd5, 0x4e, 0xa9, 0xe7, 0xc8, 0x37, 0x6d, 0x65, 0x7a, 0xae, 0x08, 0x6c, 0x56, 0xf4, 0xea, 0x49, 0x06, 0x24, 0x5c, 0xe0, 0x32, 0x3a, 0x0a, 0x91, 0x95, 0xe4, 0x79, 0xc2, 0xd3, 0xac, 0x62, 0x22, 0x2a, 0x90, 0x88, 0x60, 0x81, 0x4f, 0xdc, 0xde, 0x5e, 0x0b, 0xdb, 0x46, 0xee, 0xb8, 0x14, 0x5f, 0x97, 0x44, 0x17, 0xcd, 0x0c, 0x13, 0xec, 0x64, 0x5d, 0x19, 0x73, 0xc4, 0xa7, 0x7e, 0x3d, 0xbf, 0xe6, 0x42, 0x68, 0x8c, 0xa1, 0x89, 0x0d, 0xb0, 0x54, 0xbb, 0x16, 0x41, 0x99, 0x2d, 0x0f, 0x69, 0xd9, 0x8e, 0x94, 0xe1, 0xf8, 0x98, 0x11, 0xce, 0x55, 0x28, 0xdf, 0x9b, 0x1e, 0x87, 0xe9, 0x48, 0x03, 0xf6, 0x0e, 0x70, 0x3e, 0xb5, 0x66, 0x86, 0xc1, 0x1d, 0x9e, 0x61, 0x35, 0x57, 0xb9, 0x1c, 0xa6, 0xb4, 0xc6, 0xba, 0x78, 0x25, 0x2e, 0x4b, 0xbd, 0x8b, 0x8a, 0xe8, 0xdd, 0x74, 0x1f +}, +{ +0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a +}, +{ +0x9d, 0x92, 0xf5, 0x38, 0xa3, 0x51, 0x8f, 0x40, 0xff, 0x10, 0xd2, 0xf3, 0xb6, 0xbc, 0x21, 0xda, 0x4d, 0x43, 0x85, 0x33, 0xef, 0xd0, 0xfb, 0xaa, 0x3c, 0x50, 0xa8, 0x9f, 0xf9, 0x45, 0x7f, 0x02, 0xfc, 0x20, 0x5b, 0xb1, 0xd1, 0x53, 0xed, 0x00, 0x4c, 0x4a, 0xcf, 0x58, 0xcb, 0x6a, 0x39, 0xbe, 0x6e, 0x1b, 0xa0, 0x5a, 0x83, 0x09, 0x1a, 0x2c, 0xe3, 0x29, 0x84, 0x2f, 0x3b, 0x52, 0xb3, 0xd6, 0x96, 0x18, 0x9a, 0x05, 0xc7, 0x04, 0xc3, 0x23, 0x27, 0xeb, 0x75, 0xb2, 0x12, 0x07, 0xe2, 0x80, 0x3f, 0x36, 0xcc, 0xf7, 0xfd, 0xb7, 0x26, 0x93, 0xd8, 0x71, 0x15, 0x31, 0xa5, 0x34, 0xf1, 0xe5, 0x59, 0xfa, 0xf0, 0x47, 0x82, 0xca, 0x7d, 0xc9, 0xa4, 0x9c, 0xc0, 0x72, 0xd4, 0xad, 0xaf, 0xa2, 0x6b, 0xf2, 0xc5, 0x6f, 0x7c, 0x63, 0x7b, 0x77, 0xd7, 0xfe, 0x76, 0xab, 0x01, 0x30, 0x2b, 0x67, 0xe6, 0xbf, 0x68, 0x42, 0xa1, 0x8c, 0x0d, 0x89, 0x54, 0xb0, 0x16, 0xbb, 0x99, 0x41, 0x0f, 0x2d, 0xd9, 0x69, 0x94, 0x8e, 0xf8, 0xe1, 0x11, 0x98, 0x55, 0xce, 0xdf, 0x28, 0x1e, 0x9b, 0xe9, 0x87, 0x03, 0x48, 0x0e, 0xf6, 0x3e, 0x70, 0x66, 0xb5, 0xc1, 0x86, 0x9e, 0x1d, 0x35, 0x61, 0xb9, 0x57, 0xa6, 0x1c, 0xc6, 0xb4, 0x78, 0xba, 0x2e, 0x25, 0xbd, 0x4b, 0x8a, 0x8b, 0xdd, 0xe8, 0x1f, 0x74, 0xd5, 0x8d, 0xa9, 0x4e, 0xc8, 0xe7, 0x6d, 0x37, 0x7a, 0x65, 0x08, 0xae, 0x56, 0x6c, 0xea, 0xf4, 0x06, 0x49, 0x5c, 0x24, 0x32, 0xe0, 0x0a, 0x3a, 0x95, 0x91, 0x79, 0xe4, 0xd3, 0xc2, 0x62, 0xac, 0x2a, 0x22, 0x88, 0x90, 0x81, 0x60, 0xdc, 0x4f, 0x5e, 0xde, 0xdb, 0x0b, 0xee, 0x46, 0x14, 0xb8, 0x97, 0x5f, 0x17, 0x44, 0x0c, 0xcd, 0xec, 0x13, 0x5d, 0x64, 0x73, 0x19, 0xa7, 0xc4, 0x3d, 0x7e +}, +{ +0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73 +}, +{ +0x2f, 0x84, 0x29, 0xe3, 0xd6, 0xb3, 0x52, 0x3b, 0x5a, 0xa0, 0x1b, 0x6e, 0x2c, 0x1a, 0x09, 0x83, 0x58, 0xcf, 0x4a, 0x4c, 0xbe, 0x39, 0x6a, 0xcb, 0xb1, 0x5b, 0x20, 0xfc, 0x00, 0xed, 0x53, 0xd1, 0x9f, 0xa8, 0x50, 0x3c, 0x02, 0x7f, 0x45, 0xf9, 0x33, 0x85, 0x43, 0x4d, 0xaa, 0xfb, 0xd0, 0xef, 0xf3, 0xd2, 0x10, 0xff, 0xda, 0x21, 0xbc, 0xb6, 0x38, 0xf5, 0x92, 0x9d, 0x40, 0x8f, 0x51, 0xa3, 0xab, 0x76, 0xfe, 0xd7, 0x67, 0x2b, 0x30, 0x01, 0x6f, 0xc5, 0xf2, 0x6b, 0x77, 0x7b, 0x63, 0x7c, 0x72, 0xc0, 0x9c, 0xa4, 0xa2, 0xaf, 0xad, 0xd4, 0x47, 0xf0, 0xfa, 0x59, 0xc9, 0x7d, 0xca, 0x82, 0x31, 0x15, 0x71, 0xd8, 0xe5, 0xf1, 0x34, 0xa5, 0xf7, 0xcc, 0x36, 0x3f, 0x93, 0x26, 0xb7, 0xfd, 0xb2, 0x75, 0xeb, 0x27, 0x80, 0xe2, 0x07, 0x12, 0x05, 0x9a, 0x18, 0x96, 0x23, 0xc3, 0x04, 0xc7, 0x8b, 0x8a, 0x4b, 0xbd, 0x74, 0x1f, 0xe8, 0xdd, 0xb4, 0xc6, 0x1c, 0xa6, 0x25, 0x2e, 0xba, 0x78, 0x1d, 0x9e, 0x86, 0xc1, 0x57, 0xb9, 0x61, 0x35, 0xf6, 0x0e, 0x48, 0x03, 0xb5, 0x66, 0x70, 0x3e, 0x28, 0xdf, 0xce, 0x55, 0x87, 0xe9, 0x9b, 0x1e, 0x8e, 0x94, 0x69, 0xd9, 0x98, 0x11, 0xe1, 0xf8, 0xbb, 0x16, 0xb0, 0x54, 0x2d, 0x0f, 0x41, 0x99, 0x42, 0x68, 0xbf, 0xe6, 0x89, 0x0d, 0x8c, 0xa1, 0x19, 0x73, 0x64, 0x5d, 0x7e, 0x3d, 0xc4, 0xa7, 0x44, 0x17, 0x5f, 0x97, 0x13, 0xec, 0xcd, 0x0c, 0x0b, 0xdb, 0xde, 0x5e, 0xb8, 0x14, 0x46, 0xee, 0x90, 0x88, 0x22, 0x2a, 0x4f, 0xdc, 0x60, 0x81, 0xe4, 0x79, 0x91, 0x95, 0xac, 0x62, 0xc2, 0xd3, 0x24, 0x5c, 0x49, 0x06, 0x3a, 0x0a, 0xe0, 0x32, 0xae, 0x08, 0x65, 0x7a, 0xf4, 0xea, 0x6c, 0x56, 0x4e, 0xa9, 0x8d, 0xd5, 0x37, 0x6d, 0xe7, 0xc8 +}, +{ +0xfb, 0xaa, 0xef, 0xd0, 0x85, 0x33, 0x4d, 0x43, 0x7f, 0x02, 0xf9, 0x45, 0xa8, 0x9f, 0x3c, 0x50, 0x8f, 0x40, 0xa3, 0x51, 0xf5, 0x38, 0x9d, 0x92, 0x21, 0xda, 0xb6, 0xbc, 0xd2, 0xf3, 0xff, 0x10, 0x1a, 0x2c, 0x83, 0x09, 0xa0, 0x5a, 0x6e, 0x1b, 0xb3, 0xd6, 0x3b, 0x52, 0x84, 0x2f, 0xe3, 0x29, 0xed, 0x00, 0xd1, 0x53, 0x5b, 0xb1, 0xfc, 0x20, 0x39, 0xbe, 0xcb, 0x6a, 0xcf, 0x58, 0x4c, 0x4a, 0x26, 0x93, 0xfd, 0xb7, 0xcc, 0xf7, 0x3f, 0x36, 0xf1, 0xe5, 0xa5, 0x34, 0x15, 0x31, 0xd8, 0x71, 0xc3, 0x23, 0xc7, 0x04, 0x9a, 0x05, 0x96, 0x18, 0xe2, 0x80, 0x12, 0x07, 0x75, 0xb2, 0x27, 0xeb, 0x7b, 0x77, 0x7c, 0x63, 0xc5, 0x6f, 0x6b, 0xf2, 0x2b, 0x67, 0x01, 0x30, 0x76, 0xab, 0xd7, 0xfe, 0x7d, 0xc9, 0x82, 0xca, 0xf0, 0x47, 0x59, 0xfa, 0xaf, 0xa2, 0xd4, 0xad, 0xc0, 0x72, 0xa4, 0x9c, 0x11, 0x98, 0xf8, 0xe1, 0x94, 0x8e, 0xd9, 0x69, 0xe9, 0x87, 0x1e, 0x9b, 0xdf, 0x28, 0x55, 0xce, 0x0d, 0x89, 0xa1, 0x8c, 0x68, 0x42, 0xe6, 0xbf, 0x0f, 0x2d, 0x99, 0x41, 0x16, 0xbb, 0x54, 0xb0, 0x2e, 0x25, 0x78, 0xba, 0xc6, 0xb4, 0xa6, 0x1c, 0x1f, 0x74, 0xdd, 0xe8, 0x8a, 0x8b, 0xbd, 0x4b, 0x66, 0xb5, 0x3e, 0x70, 0x0e, 0xf6, 0x03, 0x48, 0xb9, 0x57, 0x35, 0x61, 0x9e, 0x1d, 0xc1, 0x86, 0x0a, 0x3a, 0x32, 0xe0, 0x5c, 0x24, 0x06, 0x49, 0x62, 0xac, 0xd3, 0xc2, 0x79, 0xe4, 0x95, 0x91, 0x6d, 0x37, 0xc8, 0xe7, 0xa9, 0x4e, 0xd5, 0x8d, 0xea, 0xf4, 0x56, 0x6c, 0x08, 0xae, 0x7a, 0x65, 0xec, 0x13, 0x0c, 0xcd, 0x17, 0x44, 0x97, 0x5f, 0x3d, 0x7e, 0xa7, 0xc4, 0x73, 0x19, 0x5d, 0x64, 0xdc, 0x4f, 0x81, 0x60, 0x88, 0x90, 0x2a, 0x22, 0x14, 0xb8, 0xee, 0x46, 0xdb, 0x0b, 0x5e, 0xde +}, +{ +0x23, 0xc3, 0x04, 0xc7, 0x05, 0x9a, 0x18, 0x96, 0x80, 0xe2, 0x07, 0x12, 0xb2, 0x75, 0xeb, 0x27, 0x93, 0x26, 0xb7, 0xfd, 0xf7, 0xcc, 0x36, 0x3f, 0xe5, 0xf1, 0x34, 0xa5, 0x31, 0x15, 0x71, 0xd8, 0xc9, 0x7d, 0xca, 0x82, 0x47, 0xf0, 0xfa, 0x59, 0xa2, 0xaf, 0xad, 0xd4, 0x72, 0xc0, 0x9c, 0xa4, 0x77, 0x7b, 0x63, 0x7c, 0x6f, 0xc5, 0xf2, 0x6b, 0x67, 0x2b, 0x30, 0x01, 0xab, 0x76, 0xfe, 0xd7, 0x40, 0x8f, 0x51, 0xa3, 0x38, 0xf5, 0x92, 0x9d, 0xda, 0x21, 0xbc, 0xb6, 0xf3, 0xd2, 0x10, 0xff, 0xaa, 0xfb, 0xd0, 0xef, 0x33, 0x85, 0x43, 0x4d, 0x02, 0x7f, 0x45, 0xf9, 0x9f, 0xa8, 0x50, 0x3c, 0x00, 0xed, 0x53, 0xd1, 0xb1, 0x5b, 0x20, 0xfc, 0xbe, 0x39, 0x6a, 0xcb, 0x58, 0xcf, 0x4a, 0x4c, 0x2c, 0x1a, 0x09, 0x83, 0x5a, 0xa0, 0x1b, 0x6e, 0xd6, 0xb3, 0x52, 0x3b, 0x2f, 0x84, 0x29, 0xe3, 0x37, 0x6d, 0xe7, 0xc8, 0x4e, 0xa9, 0x8d, 0xd5, 0xf4, 0xea, 0x6c, 0x56, 0xae, 0x08, 0x65, 0x7a, 0x3a, 0x0a, 0xe0, 0x32, 0x24, 0x5c, 0x49, 0x06, 0xac, 0x62, 0xc2, 0xd3, 0xe4, 0x79, 0x91, 0x95, 0x4f, 0xdc, 0x60, 0x81, 0x90, 0x88, 0x22, 0x2a, 0xb8, 0x14, 0x46, 0xee, 0x0b, 0xdb, 0xde, 0x5e, 0x13, 0xec, 0xcd, 0x0c, 0x44, 0x17, 0x5f, 0x97, 0x7e, 0x3d, 0xc4, 0xa7, 0x19, 0x73, 0x64, 0x5d, 0x89, 0x0d, 0x8c, 0xa1, 0x42, 0x68, 0xbf, 0xe6, 0x2d, 0x0f, 0x41, 0x99, 0xbb, 0x16, 0xb0, 0x54, 0x98, 0x11, 0xe1, 0xf8, 0x8e, 0x94, 0x69, 0xd9, 0x87, 0xe9, 0x9b, 0x1e, 0x28, 0xdf, 0xce, 0x55, 0xb5, 0x66, 0x70, 0x3e, 0xf6, 0x0e, 0x48, 0x03, 0x57, 0xb9, 0x61, 0x35, 0x1d, 0x9e, 0x86, 0xc1, 0x25, 0x2e, 0xba, 0x78, 0xb4, 0xc6, 0x1c, 0xa6, 0x74, 0x1f, 0xe8, 0xdd, 0x8b, 0x8a, 0x4b, 0xbd +}, +{ +0x8f, 0x40, 0xa3, 0x51, 0xf5, 0x38, 0x9d, 0x92, 0x21, 0xda, 0xb6, 0xbc, 0xd2, 0xf3, 0xff, 0x10, 0xfb, 0xaa, 0xef, 0xd0, 0x85, 0x33, 0x4d, 0x43, 0x7f, 0x02, 0xf9, 0x45, 0xa8, 0x9f, 0x3c, 0x50, 0xed, 0x00, 0xd1, 0x53, 0x5b, 0xb1, 0xfc, 0x20, 0x39, 0xbe, 0xcb, 0x6a, 0xcf, 0x58, 0x4c, 0x4a, 0x1a, 0x2c, 0x83, 0x09, 0xa0, 0x5a, 0x6e, 0x1b, 0xb3, 0xd6, 0x3b, 0x52, 0x84, 0x2f, 0xe3, 0x29, 0xc3, 0x23, 0xc7, 0x04, 0x9a, 0x05, 0x96, 0x18, 0xe2, 0x80, 0x12, 0x07, 0x75, 0xb2, 0x27, 0xeb, 0x26, 0x93, 0xfd, 0xb7, 0xcc, 0xf7, 0x3f, 0x36, 0xf1, 0xe5, 0xa5, 0x34, 0x15, 0x31, 0xd8, 0x71, 0x7d, 0xc9, 0x82, 0xca, 0xf0, 0x47, 0x59, 0xfa, 0xaf, 0xa2, 0xd4, 0xad, 0xc0, 0x72, 0xa4, 0x9c, 0x7b, 0x77, 0x7c, 0x63, 0xc5, 0x6f, 0x6b, 0xf2, 0x2b, 0x67, 0x01, 0x30, 0x76, 0xab, 0xd7, 0xfe, 0x0d, 0x89, 0xa1, 0x8c, 0x68, 0x42, 0xe6, 0xbf, 0x0f, 0x2d, 0x99, 0x41, 0x16, 0xbb, 0x54, 0xb0, 0x11, 0x98, 0xf8, 0xe1, 0x94, 0x8e, 0xd9, 0x69, 0xe9, 0x87, 0x1e, 0x9b, 0xdf, 0x28, 0x55, 0xce, 0x66, 0xb5, 0x3e, 0x70, 0x0e, 0xf6, 0x03, 0x48, 0xb9, 0x57, 0x35, 0x61, 0x9e, 0x1d, 0xc1, 0x86, 0x2e, 0x25, 0x78, 0xba, 0xc6, 0xb4, 0xa6, 0x1c, 0x1f, 0x74, 0xdd, 0xe8, 0x8a, 0x8b, 0xbd, 0x4b, 0x6d, 0x37, 0xc8, 0xe7, 0xa9, 0x4e, 0xd5, 0x8d, 0xea, 0xf4, 0x56, 0x6c, 0x08, 0xae, 0x7a, 0x65, 0x0a, 0x3a, 0x32, 0xe0, 0x5c, 0x24, 0x06, 0x49, 0x62, 0xac, 0xd3, 0xc2, 0x79, 0xe4, 0x95, 0x91, 0xdc, 0x4f, 0x81, 0x60, 0x88, 0x90, 0x2a, 0x22, 0x14, 0xb8, 0xee, 0x46, 0xdb, 0x0b, 0x5e, 0xde, 0xec, 0x13, 0x0c, 0xcd, 0x17, 0x44, 0x97, 0x5f, 0x3d, 0x7e, 0xa7, 0xc4, 0x73, 0x19, 0x5d, 0x64 +}, +{ +0x4d, 0x43, 0x85, 0x33, 0xef, 0xd0, 0xfb, 0xaa, 0x3c, 0x50, 0xa8, 0x9f, 0xf9, 0x45, 0x7f, 0x02, 0x9d, 0x92, 0xf5, 0x38, 0xa3, 0x51, 0x8f, 0x40, 0xff, 0x10, 0xd2, 0xf3, 0xb6, 0xbc, 0x21, 0xda, 0x6e, 0x1b, 0xa0, 0x5a, 0x83, 0x09, 0x1a, 0x2c, 0xe3, 0x29, 0x84, 0x2f, 0x3b, 0x52, 0xb3, 0xd6, 0xfc, 0x20, 0x5b, 0xb1, 0xd1, 0x53, 0xed, 0x00, 0x4c, 0x4a, 0xcf, 0x58, 0xcb, 0x6a, 0x39, 0xbe, 0x3f, 0x36, 0xcc, 0xf7, 0xfd, 0xb7, 0x26, 0x93, 0xd8, 0x71, 0x15, 0x31, 0xa5, 0x34, 0xf1, 0xe5, 0x96, 0x18, 0x9a, 0x05, 0xc7, 0x04, 0xc3, 0x23, 0x27, 0xeb, 0x75, 0xb2, 0x12, 0x07, 0xe2, 0x80, 0x6b, 0xf2, 0xc5, 0x6f, 0x7c, 0x63, 0x7b, 0x77, 0xd7, 0xfe, 0x76, 0xab, 0x01, 0x30, 0x2b, 0x67, 0x59, 0xfa, 0xf0, 0x47, 0x82, 0xca, 0x7d, 0xc9, 0xa4, 0x9c, 0xc0, 0x72, 0xd4, 0xad, 0xaf, 0xa2, 0xd9, 0x69, 0x94, 0x8e, 0xf8, 0xe1, 0x11, 0x98, 0x55, 0xce, 0xdf, 0x28, 0x1e, 0x9b, 0xe9, 0x87, 0xe6, 0xbf, 0x68, 0x42, 0xa1, 0x8c, 0x0d, 0x89, 0x54, 0xb0, 0x16, 0xbb, 0x99, 0x41, 0x0f, 0x2d, 0xa6, 0x1c, 0xc6, 0xb4, 0x78, 0xba, 0x2e, 0x25, 0xbd, 0x4b, 0x8a, 0x8b, 0xdd, 0xe8, 0x1f, 0x74, 0x03, 0x48, 0x0e, 0xf6, 0x3e, 0x70, 0x66, 0xb5, 0xc1, 0x86, 0x9e, 0x1d, 0x35, 0x61, 0xb9, 0x57, 0x06, 0x49, 0x5c, 0x24, 0x32, 0xe0, 0x0a, 0x3a, 0x95, 0x91, 0x79, 0xe4, 0xd3, 0xc2, 0x62, 0xac, 0xd5, 0x8d, 0xa9, 0x4e, 0xc8, 0xe7, 0x6d, 0x37, 0x7a, 0x65, 0x08, 0xae, 0x56, 0x6c, 0xea, 0xf4, 0x97, 0x5f, 0x17, 0x44, 0x0c, 0xcd, 0xec, 0x13, 0x5d, 0x64, 0x73, 0x19, 0xa7, 0xc4, 0x3d, 0x7e, 0x2a, 0x22, 0x88, 0x90, 0x81, 0x60, 0xdc, 0x4f, 0x5e, 0xde, 0xdb, 0x0b, 0xee, 0x46, 0x14, 0xb8 +} +}, +{ +{ +0x28, 0xdf, 0xce, 0x55, 0x87, 0xe9, 0x9b, 0x1e, 0x8e, 0x94, 0x69, 0xd9, 0x98, 0x11, 0xe1, 0xf8, 0xbb, 0x16, 0xb0, 0x54, 0x2d, 0x0f, 0x41, 0x99, 0x42, 0x68, 0xbf, 0xe6, 0x89, 0x0d, 0x8c, 0xa1, 0x8b, 0x8a, 0x4b, 0xbd, 0x74, 0x1f, 0xe8, 0xdd, 0xb4, 0xc6, 0x1c, 0xa6, 0x25, 0x2e, 0xba, 0x78, 0x1d, 0x9e, 0x86, 0xc1, 0x57, 0xb9, 0x61, 0x35, 0xf6, 0x0e, 0x48, 0x03, 0xb5, 0x66, 0x70, 0x3e, 0xe4, 0x79, 0x91, 0x95, 0xac, 0x62, 0xc2, 0xd3, 0x24, 0x5c, 0x49, 0x06, 0x3a, 0x0a, 0xe0, 0x32, 0xae, 0x08, 0x65, 0x7a, 0xf4, 0xea, 0x6c, 0x56, 0x4e, 0xa9, 0x8d, 0xd5, 0x37, 0x6d, 0xe7, 0xc8, 0x19, 0x73, 0x64, 0x5d, 0x7e, 0x3d, 0xc4, 0xa7, 0x44, 0x17, 0x5f, 0x97, 0x13, 0xec, 0xcd, 0x0c, 0x0b, 0xdb, 0xde, 0x5e, 0xb8, 0x14, 0x46, 0xee, 0x90, 0x88, 0x22, 0x2a, 0x4f, 0xdc, 0x60, 0x81, 0x9f, 0xa8, 0x50, 0x3c, 0x02, 0x7f, 0x45, 0xf9, 0x33, 0x85, 0x43, 0x4d, 0xaa, 0xfb, 0xd0, 0xef, 0xf3, 0xd2, 0x10, 0xff, 0xda, 0x21, 0xbc, 0xb6, 0x38, 0xf5, 0x92, 0x9d, 0x40, 0x8f, 0x51, 0xa3, 0x2f, 0x84, 0x29, 0xe3, 0xd6, 0xb3, 0x52, 0x3b, 0x5a, 0xa0, 0x1b, 0x6e, 0x2c, 0x1a, 0x09, 0x83, 0x58, 0xcf, 0x4a, 0x4c, 0xbe, 0x39, 0x6a, 0xcb, 0xb1, 0x5b, 0x20, 0xfc, 0x00, 0xed, 0x53, 0xd1, 0x31, 0x15, 0x71, 0xd8, 0xe5, 0xf1, 0x34, 0xa5, 0xf7, 0xcc, 0x36, 0x3f, 0x93, 0x26, 0xb7, 0xfd, 0xb2, 0x75, 0xeb, 0x27, 0x80, 0xe2, 0x07, 0x12, 0x05, 0x9a, 0x18, 0x96, 0x23, 0xc3, 0x04, 0xc7, 0xab, 0x76, 0xfe, 0xd7, 0x67, 0x2b, 0x30, 0x01, 0x6f, 0xc5, 0xf2, 0x6b, 0x77, 0x7b, 0x63, 0x7c, 0x72, 0xc0, 0x9c, 0xa4, 0xa2, 0xaf, 0xad, 0xd4, 0x47, 0xf0, 0xfa, 0x59, 0xc9, 0x7d, 0xca, 0x82 +}, +{ +0x1a, 0x2c, 0x83, 0x09, 0xa0, 0x5a, 0x6e, 0x1b, 0xb3, 0xd6, 0x3b, 0x52, 0x84, 0x2f, 0xe3, 0x29, 0xed, 0x00, 0xd1, 0x53, 0x5b, 0xb1, 0xfc, 0x20, 0x39, 0xbe, 0xcb, 0x6a, 0xcf, 0x58, 0x4c, 0x4a, 0xfb, 0xaa, 0xef, 0xd0, 0x85, 0x33, 0x4d, 0x43, 0x7f, 0x02, 0xf9, 0x45, 0xa8, 0x9f, 0x3c, 0x50, 0x8f, 0x40, 0xa3, 0x51, 0xf5, 0x38, 0x9d, 0x92, 0x21, 0xda, 0xb6, 0xbc, 0xd2, 0xf3, 0xff, 0x10, 0x7b, 0x77, 0x7c, 0x63, 0xc5, 0x6f, 0x6b, 0xf2, 0x2b, 0x67, 0x01, 0x30, 0x76, 0xab, 0xd7, 0xfe, 0x7d, 0xc9, 0x82, 0xca, 0xf0, 0x47, 0x59, 0xfa, 0xaf, 0xa2, 0xd4, 0xad, 0xc0, 0x72, 0xa4, 0x9c, 0x26, 0x93, 0xfd, 0xb7, 0xcc, 0xf7, 0x3f, 0x36, 0xf1, 0xe5, 0xa5, 0x34, 0x15, 0x31, 0xd8, 0x71, 0xc3, 0x23, 0xc7, 0x04, 0x9a, 0x05, 0x96, 0x18, 0xe2, 0x80, 0x12, 0x07, 0x75, 0xb2, 0x27, 0xeb, 0x2e, 0x25, 0x78, 0xba, 0xc6, 0xb4, 0xa6, 0x1c, 0x1f, 0x74, 0xdd, 0xe8, 0x8a, 0x8b, 0xbd, 0x4b, 0x66, 0xb5, 0x3e, 0x70, 0x0e, 0xf6, 0x03, 0x48, 0xb9, 0x57, 0x35, 0x61, 0x9e, 0x1d, 0xc1, 0x86, 0x11, 0x98, 0xf8, 0xe1, 0x94, 0x8e, 0xd9, 0x69, 0xe9, 0x87, 0x1e, 0x9b, 0xdf, 0x28, 0x55, 0xce, 0x0d, 0x89, 0xa1, 0x8c, 0x68, 0x42, 0xe6, 0xbf, 0x0f, 0x2d, 0x99, 0x41, 0x16, 0xbb, 0x54, 0xb0, 0xec, 0x13, 0x0c, 0xcd, 0x17, 0x44, 0x97, 0x5f, 0x3d, 0x7e, 0xa7, 0xc4, 0x73, 0x19, 0x5d, 0x64, 0xdc, 0x4f, 0x81, 0x60, 0x88, 0x90, 0x2a, 0x22, 0x14, 0xb8, 0xee, 0x46, 0xdb, 0x0b, 0x5e, 0xde, 0x0a, 0x3a, 0x32, 0xe0, 0x5c, 0x24, 0x06, 0x49, 0x62, 0xac, 0xd3, 0xc2, 0x79, 0xe4, 0x95, 0x91, 0x6d, 0x37, 0xc8, 0xe7, 0xa9, 0x4e, 0xd5, 0x8d, 0xea, 0xf4, 0x56, 0x6c, 0x08, 0xae, 0x7a, 0x65 +}, +{ +0xdc, 0x4f, 0x81, 0x60, 0x88, 0x90, 0x2a, 0x22, 0x14, 0xb8, 0xee, 0x46, 0xdb, 0x0b, 0x5e, 0xde, 0xec, 0x13, 0x0c, 0xcd, 0x17, 0x44, 0x97, 0x5f, 0x3d, 0x7e, 0xa7, 0xc4, 0x73, 0x19, 0x5d, 0x64, 0x6d, 0x37, 0xc8, 0xe7, 0xa9, 0x4e, 0xd5, 0x8d, 0xea, 0xf4, 0x56, 0x6c, 0x08, 0xae, 0x7a, 0x65, 0x0a, 0x3a, 0x32, 0xe0, 0x5c, 0x24, 0x06, 0x49, 0x62, 0xac, 0xd3, 0xc2, 0x79, 0xe4, 0x95, 0x91, 0x66, 0xb5, 0x3e, 0x70, 0x0e, 0xf6, 0x03, 0x48, 0xb9, 0x57, 0x35, 0x61, 0x9e, 0x1d, 0xc1, 0x86, 0x2e, 0x25, 0x78, 0xba, 0xc6, 0xb4, 0xa6, 0x1c, 0x1f, 0x74, 0xdd, 0xe8, 0x8a, 0x8b, 0xbd, 0x4b, 0x0d, 0x89, 0xa1, 0x8c, 0x68, 0x42, 0xe6, 0xbf, 0x0f, 0x2d, 0x99, 0x41, 0x16, 0xbb, 0x54, 0xb0, 0x11, 0x98, 0xf8, 0xe1, 0x94, 0x8e, 0xd9, 0x69, 0xe9, 0x87, 0x1e, 0x9b, 0xdf, 0x28, 0x55, 0xce, 0x7d, 0xc9, 0x82, 0xca, 0xf0, 0x47, 0x59, 0xfa, 0xaf, 0xa2, 0xd4, 0xad, 0xc0, 0x72, 0xa4, 0x9c, 0x7b, 0x77, 0x7c, 0x63, 0xc5, 0x6f, 0x6b, 0xf2, 0x2b, 0x67, 0x01, 0x30, 0x76, 0xab, 0xd7, 0xfe, 0xc3, 0x23, 0xc7, 0x04, 0x9a, 0x05, 0x96, 0x18, 0xe2, 0x80, 0x12, 0x07, 0x75, 0xb2, 0x27, 0xeb, 0x26, 0x93, 0xfd, 0xb7, 0xcc, 0xf7, 0x3f, 0x36, 0xf1, 0xe5, 0xa5, 0x34, 0x15, 0x31, 0xd8, 0x71, 0xed, 0x00, 0xd1, 0x53, 0x5b, 0xb1, 0xfc, 0x20, 0x39, 0xbe, 0xcb, 0x6a, 0xcf, 0x58, 0x4c, 0x4a, 0x1a, 0x2c, 0x83, 0x09, 0xa0, 0x5a, 0x6e, 0x1b, 0xb3, 0xd6, 0x3b, 0x52, 0x84, 0x2f, 0xe3, 0x29, 0x8f, 0x40, 0xa3, 0x51, 0xf5, 0x38, 0x9d, 0x92, 0x21, 0xda, 0xb6, 0xbc, 0xd2, 0xf3, 0xff, 0x10, 0xfb, 0xaa, 0xef, 0xd0, 0x85, 0x33, 0x4d, 0x43, 0x7f, 0x02, 0xf9, 0x45, 0xa8, 0x9f, 0x3c, 0x50 +}, +{ +0x0e, 0xf6, 0x03, 0x48, 0x66, 0xb5, 0x3e, 0x70, 0x9e, 0x1d, 0xc1, 0x86, 0xb9, 0x57, 0x35, 0x61, 0xc6, 0xb4, 0xa6, 0x1c, 0x2e, 0x25, 0x78, 0xba, 0x8a, 0x8b, 0xbd, 0x4b, 0x1f, 0x74, 0xdd, 0xe8, 0x68, 0x42, 0xe6, 0xbf, 0x0d, 0x89, 0xa1, 0x8c, 0x16, 0xbb, 0x54, 0xb0, 0x0f, 0x2d, 0x99, 0x41, 0x94, 0x8e, 0xd9, 0x69, 0x11, 0x98, 0xf8, 0xe1, 0xdf, 0x28, 0x55, 0xce, 0xe9, 0x87, 0x1e, 0x9b, 0x88, 0x90, 0x2a, 0x22, 0xdc, 0x4f, 0x81, 0x60, 0xdb, 0x0b, 0x5e, 0xde, 0x14, 0xb8, 0xee, 0x46, 0x17, 0x44, 0x97, 0x5f, 0xec, 0x13, 0x0c, 0xcd, 0x73, 0x19, 0x5d, 0x64, 0x3d, 0x7e, 0xa7, 0xc4, 0xa9, 0x4e, 0xd5, 0x8d, 0x6d, 0x37, 0xc8, 0xe7, 0x08, 0xae, 0x7a, 0x65, 0xea, 0xf4, 0x56, 0x6c, 0x5c, 0x24, 0x06, 0x49, 0x0a, 0x3a, 0x32, 0xe0, 0x79, 0xe4, 0x95, 0x91, 0x62, 0xac, 0xd3, 0xc2, 0x5b, 0xb1, 0xfc, 0x20, 0xed, 0x00, 0xd1, 0x53, 0xcf, 0x58, 0x4c, 0x4a, 0x39, 0xbe, 0xcb, 0x6a, 0xa0, 0x5a, 0x6e, 0x1b, 0x1a, 0x2c, 0x83, 0x09, 0x84, 0x2f, 0xe3, 0x29, 0xb3, 0xd6, 0x3b, 0x52, 0xf5, 0x38, 0x9d, 0x92, 0x8f, 0x40, 0xa3, 0x51, 0xd2, 0xf3, 0xff, 0x10, 0x21, 0xda, 0xb6, 0xbc, 0x85, 0x33, 0x4d, 0x43, 0xfb, 0xaa, 0xef, 0xd0, 0xa8, 0x9f, 0x3c, 0x50, 0x7f, 0x02, 0xf9, 0x45, 0xf0, 0x47, 0x59, 0xfa, 0x7d, 0xc9, 0x82, 0xca, 0xc0, 0x72, 0xa4, 0x9c, 0xaf, 0xa2, 0xd4, 0xad, 0xc5, 0x6f, 0x6b, 0xf2, 0x7b, 0x77, 0x7c, 0x63, 0x76, 0xab, 0xd7, 0xfe, 0x2b, 0x67, 0x01, 0x30, 0x9a, 0x05, 0x96, 0x18, 0xc3, 0x23, 0xc7, 0x04, 0x75, 0xb2, 0x27, 0xeb, 0xe2, 0x80, 0x12, 0x07, 0xcc, 0xf7, 0x3f, 0x36, 0x26, 0x93, 0xfd, 0xb7, 0x15, 0x31, 0xd8, 0x71, 0xf1, 0xe5, 0xa5, 0x34 +}, +{ +0x88, 0x90, 0x2a, 0x22, 0xdc, 0x4f, 0x81, 0x60, 0xdb, 0x0b, 0x5e, 0xde, 0x14, 0xb8, 0xee, 0x46, 0x17, 0x44, 0x97, 0x5f, 0xec, 0x13, 0x0c, 0xcd, 0x73, 0x19, 0x5d, 0x64, 0x3d, 0x7e, 0xa7, 0xc4, 0xa9, 0x4e, 0xd5, 0x8d, 0x6d, 0x37, 0xc8, 0xe7, 0x08, 0xae, 0x7a, 0x65, 0xea, 0xf4, 0x56, 0x6c, 0x5c, 0x24, 0x06, 0x49, 0x0a, 0x3a, 0x32, 0xe0, 0x79, 0xe4, 0x95, 0x91, 0x62, 0xac, 0xd3, 0xc2, 0x0e, 0xf6, 0x03, 0x48, 0x66, 0xb5, 0x3e, 0x70, 0x9e, 0x1d, 0xc1, 0x86, 0xb9, 0x57, 0x35, 0x61, 0xc6, 0xb4, 0xa6, 0x1c, 0x2e, 0x25, 0x78, 0xba, 0x8a, 0x8b, 0xbd, 0x4b, 0x1f, 0x74, 0xdd, 0xe8, 0x68, 0x42, 0xe6, 0xbf, 0x0d, 0x89, 0xa1, 0x8c, 0x16, 0xbb, 0x54, 0xb0, 0x0f, 0x2d, 0x99, 0x41, 0x94, 0x8e, 0xd9, 0x69, 0x11, 0x98, 0xf8, 0xe1, 0xdf, 0x28, 0x55, 0xce, 0xe9, 0x87, 0x1e, 0x9b, 0xf0, 0x47, 0x59, 0xfa, 0x7d, 0xc9, 0x82, 0xca, 0xc0, 0x72, 0xa4, 0x9c, 0xaf, 0xa2, 0xd4, 0xad, 0xc5, 0x6f, 0x6b, 0xf2, 0x7b, 0x77, 0x7c, 0x63, 0x76, 0xab, 0xd7, 0xfe, 0x2b, 0x67, 0x01, 0x30, 0x9a, 0x05, 0x96, 0x18, 0xc3, 0x23, 0xc7, 0x04, 0x75, 0xb2, 0x27, 0xeb, 0xe2, 0x80, 0x12, 0x07, 0xcc, 0xf7, 0x3f, 0x36, 0x26, 0x93, 0xfd, 0xb7, 0x15, 0x31, 0xd8, 0x71, 0xf1, 0xe5, 0xa5, 0x34, 0x5b, 0xb1, 0xfc, 0x20, 0xed, 0x00, 0xd1, 0x53, 0xcf, 0x58, 0x4c, 0x4a, 0x39, 0xbe, 0xcb, 0x6a, 0xa0, 0x5a, 0x6e, 0x1b, 0x1a, 0x2c, 0x83, 0x09, 0x84, 0x2f, 0xe3, 0x29, 0xb3, 0xd6, 0x3b, 0x52, 0xf5, 0x38, 0x9d, 0x92, 0x8f, 0x40, 0xa3, 0x51, 0xd2, 0xf3, 0xff, 0x10, 0x21, 0xda, 0xb6, 0xbc, 0x85, 0x33, 0x4d, 0x43, 0xfb, 0xaa, 0xef, 0xd0, 0xa8, 0x9f, 0x3c, 0x50, 0x7f, 0x02, 0xf9, 0x45 +}, +{ +0x18, 0x96, 0x05, 0x9a, 0x04, 0xc7, 0x23, 0xc3, 0xeb, 0x27, 0xb2, 0x75, 0x07, 0x12, 0x80, 0xe2, 0x36, 0x3f, 0xf7, 0xcc, 0xb7, 0xfd, 0x93, 0x26, 0x71, 0xd8, 0x31, 0x15, 0x34, 0xa5, 0xe5, 0xf1, 0xfa, 0x59, 0x47, 0xf0, 0xca, 0x82, 0xc9, 0x7d, 0x9c, 0xa4, 0x72, 0xc0, 0xad, 0xd4, 0xa2, 0xaf, 0xf2, 0x6b, 0x6f, 0xc5, 0x63, 0x7c, 0x77, 0x7b, 0xfe, 0xd7, 0xab, 0x76, 0x30, 0x01, 0x67, 0x2b, 0x92, 0x9d, 0x38, 0xf5, 0x51, 0xa3, 0x40, 0x8f, 0x10, 0xff, 0xf3, 0xd2, 0xbc, 0xb6, 0xda, 0x21, 0x43, 0x4d, 0x33, 0x85, 0xd0, 0xef, 0xaa, 0xfb, 0x50, 0x3c, 0x9f, 0xa8, 0x45, 0xf9, 0x02, 0x7f, 0x20, 0xfc, 0xb1, 0x5b, 0x53, 0xd1, 0x00, 0xed, 0x4a, 0x4c, 0x58, 0xcf, 0x6a, 0xcb, 0xbe, 0x39, 0x1b, 0x6e, 0x5a, 0xa0, 0x09, 0x83, 0x2c, 0x1a, 0x29, 0xe3, 0x2f, 0x84, 0x52, 0x3b, 0xd6, 0xb3, 0x8d, 0xd5, 0x4e, 0xa9, 0xe7, 0xc8, 0x37, 0x6d, 0x65, 0x7a, 0xae, 0x08, 0x6c, 0x56, 0xf4, 0xea, 0x49, 0x06, 0x24, 0x5c, 0xe0, 0x32, 0x3a, 0x0a, 0x91, 0x95, 0xe4, 0x79, 0xc2, 0xd3, 0xac, 0x62, 0x22, 0x2a, 0x90, 0x88, 0x60, 0x81, 0x4f, 0xdc, 0xde, 0x5e, 0x0b, 0xdb, 0x46, 0xee, 0xb8, 0x14, 0x5f, 0x97, 0x44, 0x17, 0xcd, 0x0c, 0x13, 0xec, 0x64, 0x5d, 0x19, 0x73, 0xc4, 0xa7, 0x7e, 0x3d, 0xbf, 0xe6, 0x42, 0x68, 0x8c, 0xa1, 0x89, 0x0d, 0xb0, 0x54, 0xbb, 0x16, 0x41, 0x99, 0x2d, 0x0f, 0x69, 0xd9, 0x8e, 0x94, 0xe1, 0xf8, 0x98, 0x11, 0xce, 0x55, 0x28, 0xdf, 0x9b, 0x1e, 0x87, 0xe9, 0x48, 0x03, 0xf6, 0x0e, 0x70, 0x3e, 0xb5, 0x66, 0x86, 0xc1, 0x1d, 0x9e, 0x61, 0x35, 0x57, 0xb9, 0x1c, 0xa6, 0xb4, 0xc6, 0xba, 0x78, 0x25, 0x2e, 0x4b, 0xbd, 0x8b, 0x8a, 0xe8, 0xdd, 0x74, 0x1f +}, +{ +0xf8, 0xe1, 0x11, 0x98, 0xd9, 0x69, 0x94, 0x8e, 0x1e, 0x9b, 0xe9, 0x87, 0x55, 0xce, 0xdf, 0x28, 0xa1, 0x8c, 0x0d, 0x89, 0xe6, 0xbf, 0x68, 0x42, 0x99, 0x41, 0x0f, 0x2d, 0x54, 0xb0, 0x16, 0xbb, 0x78, 0xba, 0x2e, 0x25, 0xa6, 0x1c, 0xc6, 0xb4, 0xdd, 0xe8, 0x1f, 0x74, 0xbd, 0x4b, 0x8a, 0x8b, 0x3e, 0x70, 0x66, 0xb5, 0x03, 0x48, 0x0e, 0xf6, 0x35, 0x61, 0xb9, 0x57, 0xc1, 0x86, 0x9e, 0x1d, 0x32, 0xe0, 0x0a, 0x3a, 0x06, 0x49, 0x5c, 0x24, 0xd3, 0xc2, 0x62, 0xac, 0x95, 0x91, 0x79, 0xe4, 0xc8, 0xe7, 0x6d, 0x37, 0xd5, 0x8d, 0xa9, 0x4e, 0x56, 0x6c, 0xea, 0xf4, 0x7a, 0x65, 0x08, 0xae, 0x0c, 0xcd, 0xec, 0x13, 0x97, 0x5f, 0x17, 0x44, 0xa7, 0xc4, 0x3d, 0x7e, 0x5d, 0x64, 0x73, 0x19, 0x81, 0x60, 0xdc, 0x4f, 0x2a, 0x22, 0x88, 0x90, 0xee, 0x46, 0x14, 0xb8, 0x5e, 0xde, 0xdb, 0x0b, 0xef, 0xd0, 0xfb, 0xaa, 0x4d, 0x43, 0x85, 0x33, 0xf9, 0x45, 0x7f, 0x02, 0x3c, 0x50, 0xa8, 0x9f, 0xa3, 0x51, 0x8f, 0x40, 0x9d, 0x92, 0xf5, 0x38, 0xb6, 0xbc, 0x21, 0xda, 0xff, 0x10, 0xd2, 0xf3, 0x83, 0x09, 0x1a, 0x2c, 0x6e, 0x1b, 0xa0, 0x5a, 0x3b, 0x52, 0xb3, 0xd6, 0xe3, 0x29, 0x84, 0x2f, 0xd1, 0x53, 0xed, 0x00, 0xfc, 0x20, 0x5b, 0xb1, 0xcb, 0x6a, 0x39, 0xbe, 0x4c, 0x4a, 0xcf, 0x58, 0xfd, 0xb7, 0x26, 0x93, 0x3f, 0x36, 0xcc, 0xf7, 0xa5, 0x34, 0xf1, 0xe5, 0xd8, 0x71, 0x15, 0x31, 0xc7, 0x04, 0xc3, 0x23, 0x96, 0x18, 0x9a, 0x05, 0x12, 0x07, 0xe2, 0x80, 0x27, 0xeb, 0x75, 0xb2, 0x7c, 0x63, 0x7b, 0x77, 0x6b, 0xf2, 0xc5, 0x6f, 0x01, 0x30, 0x2b, 0x67, 0xd7, 0xfe, 0x76, 0xab, 0x82, 0xca, 0x7d, 0xc9, 0x59, 0xfa, 0xf0, 0x47, 0xd4, 0xad, 0xaf, 0xa2, 0xa4, 0x9c, 0xc0, 0x72 +}, +{ +0x8a, 0x8b, 0xbd, 0x4b, 0x1f, 0x74, 0xdd, 0xe8, 0xc6, 0xb4, 0xa6, 0x1c, 0x2e, 0x25, 0x78, 0xba, 0x9e, 0x1d, 0xc1, 0x86, 0xb9, 0x57, 0x35, 0x61, 0x0e, 0xf6, 0x03, 0x48, 0x66, 0xb5, 0x3e, 0x70, 0xdf, 0x28, 0x55, 0xce, 0xe9, 0x87, 0x1e, 0x9b, 0x94, 0x8e, 0xd9, 0x69, 0x11, 0x98, 0xf8, 0xe1, 0x16, 0xbb, 0x54, 0xb0, 0x0f, 0x2d, 0x99, 0x41, 0x68, 0x42, 0xe6, 0xbf, 0x0d, 0x89, 0xa1, 0x8c, 0x73, 0x19, 0x5d, 0x64, 0x3d, 0x7e, 0xa7, 0xc4, 0x17, 0x44, 0x97, 0x5f, 0xec, 0x13, 0x0c, 0xcd, 0xdb, 0x0b, 0x5e, 0xde, 0x14, 0xb8, 0xee, 0x46, 0x88, 0x90, 0x2a, 0x22, 0xdc, 0x4f, 0x81, 0x60, 0x79, 0xe4, 0x95, 0x91, 0x62, 0xac, 0xd3, 0xc2, 0x5c, 0x24, 0x06, 0x49, 0x0a, 0x3a, 0x32, 0xe0, 0x08, 0xae, 0x7a, 0x65, 0xea, 0xf4, 0x56, 0x6c, 0xa9, 0x4e, 0xd5, 0x8d, 0x6d, 0x37, 0xc8, 0xe7, 0x84, 0x2f, 0xe3, 0x29, 0xb3, 0xd6, 0x3b, 0x52, 0xa0, 0x5a, 0x6e, 0x1b, 0x1a, 0x2c, 0x83, 0x09, 0xcf, 0x58, 0x4c, 0x4a, 0x39, 0xbe, 0xcb, 0x6a, 0x5b, 0xb1, 0xfc, 0x20, 0xed, 0x00, 0xd1, 0x53, 0xa8, 0x9f, 0x3c, 0x50, 0x7f, 0x02, 0xf9, 0x45, 0x85, 0x33, 0x4d, 0x43, 0xfb, 0xaa, 0xef, 0xd0, 0xd2, 0xf3, 0xff, 0x10, 0x21, 0xda, 0xb6, 0xbc, 0xf5, 0x38, 0x9d, 0x92, 0x8f, 0x40, 0xa3, 0x51, 0x76, 0xab, 0xd7, 0xfe, 0x2b, 0x67, 0x01, 0x30, 0xc5, 0x6f, 0x6b, 0xf2, 0x7b, 0x77, 0x7c, 0x63, 0xc0, 0x72, 0xa4, 0x9c, 0xaf, 0xa2, 0xd4, 0xad, 0xf0, 0x47, 0x59, 0xfa, 0x7d, 0xc9, 0x82, 0xca, 0x15, 0x31, 0xd8, 0x71, 0xf1, 0xe5, 0xa5, 0x34, 0xcc, 0xf7, 0x3f, 0x36, 0x26, 0x93, 0xfd, 0xb7, 0x75, 0xb2, 0x27, 0xeb, 0xe2, 0x80, 0x12, 0x07, 0x9a, 0x05, 0x96, 0x18, 0xc3, 0x23, 0xc7, 0x04 +}, +{ +0x5c, 0x24, 0x06, 0x49, 0x0a, 0x3a, 0x32, 0xe0, 0x79, 0xe4, 0x95, 0x91, 0x62, 0xac, 0xd3, 0xc2, 0xa9, 0x4e, 0xd5, 0x8d, 0x6d, 0x37, 0xc8, 0xe7, 0x08, 0xae, 0x7a, 0x65, 0xea, 0xf4, 0x56, 0x6c, 0x17, 0x44, 0x97, 0x5f, 0xec, 0x13, 0x0c, 0xcd, 0x73, 0x19, 0x5d, 0x64, 0x3d, 0x7e, 0xa7, 0xc4, 0x88, 0x90, 0x2a, 0x22, 0xdc, 0x4f, 0x81, 0x60, 0xdb, 0x0b, 0x5e, 0xde, 0x14, 0xb8, 0xee, 0x46, 0x94, 0x8e, 0xd9, 0x69, 0x11, 0x98, 0xf8, 0xe1, 0xdf, 0x28, 0x55, 0xce, 0xe9, 0x87, 0x1e, 0x9b, 0x68, 0x42, 0xe6, 0xbf, 0x0d, 0x89, 0xa1, 0x8c, 0x16, 0xbb, 0x54, 0xb0, 0x0f, 0x2d, 0x99, 0x41, 0xc6, 0xb4, 0xa6, 0x1c, 0x2e, 0x25, 0x78, 0xba, 0x8a, 0x8b, 0xbd, 0x4b, 0x1f, 0x74, 0xdd, 0xe8, 0x0e, 0xf6, 0x03, 0x48, 0x66, 0xb5, 0x3e, 0x70, 0x9e, 0x1d, 0xc1, 0x86, 0xb9, 0x57, 0x35, 0x61, 0xcc, 0xf7, 0x3f, 0x36, 0x26, 0x93, 0xfd, 0xb7, 0x15, 0x31, 0xd8, 0x71, 0xf1, 0xe5, 0xa5, 0x34, 0x9a, 0x05, 0x96, 0x18, 0xc3, 0x23, 0xc7, 0x04, 0x75, 0xb2, 0x27, 0xeb, 0xe2, 0x80, 0x12, 0x07, 0xc5, 0x6f, 0x6b, 0xf2, 0x7b, 0x77, 0x7c, 0x63, 0x76, 0xab, 0xd7, 0xfe, 0x2b, 0x67, 0x01, 0x30, 0xf0, 0x47, 0x59, 0xfa, 0x7d, 0xc9, 0x82, 0xca, 0xc0, 0x72, 0xa4, 0x9c, 0xaf, 0xa2, 0xd4, 0xad, 0x85, 0x33, 0x4d, 0x43, 0xfb, 0xaa, 0xef, 0xd0, 0xa8, 0x9f, 0x3c, 0x50, 0x7f, 0x02, 0xf9, 0x45, 0xf5, 0x38, 0x9d, 0x92, 0x8f, 0x40, 0xa3, 0x51, 0xd2, 0xf3, 0xff, 0x10, 0x21, 0xda, 0xb6, 0xbc, 0xa0, 0x5a, 0x6e, 0x1b, 0x1a, 0x2c, 0x83, 0x09, 0x84, 0x2f, 0xe3, 0x29, 0xb3, 0xd6, 0x3b, 0x52, 0x5b, 0xb1, 0xfc, 0x20, 0xed, 0x00, 0xd1, 0x53, 0xcf, 0x58, 0x4c, 0x4a, 0x39, 0xbe, 0xcb, 0x6a +}, +{ +0x83, 0x09, 0x1a, 0x2c, 0x6e, 0x1b, 0xa0, 0x5a, 0x3b, 0x52, 0xb3, 0xd6, 0xe3, 0x29, 0x84, 0x2f, 0xd1, 0x53, 0xed, 0x00, 0xfc, 0x20, 0x5b, 0xb1, 0xcb, 0x6a, 0x39, 0xbe, 0x4c, 0x4a, 0xcf, 0x58, 0xef, 0xd0, 0xfb, 0xaa, 0x4d, 0x43, 0x85, 0x33, 0xf9, 0x45, 0x7f, 0x02, 0x3c, 0x50, 0xa8, 0x9f, 0xa3, 0x51, 0x8f, 0x40, 0x9d, 0x92, 0xf5, 0x38, 0xb6, 0xbc, 0x21, 0xda, 0xff, 0x10, 0xd2, 0xf3, 0x7c, 0x63, 0x7b, 0x77, 0x6b, 0xf2, 0xc5, 0x6f, 0x01, 0x30, 0x2b, 0x67, 0xd7, 0xfe, 0x76, 0xab, 0x82, 0xca, 0x7d, 0xc9, 0x59, 0xfa, 0xf0, 0x47, 0xd4, 0xad, 0xaf, 0xa2, 0xa4, 0x9c, 0xc0, 0x72, 0xfd, 0xb7, 0x26, 0x93, 0x3f, 0x36, 0xcc, 0xf7, 0xa5, 0x34, 0xf1, 0xe5, 0xd8, 0x71, 0x15, 0x31, 0xc7, 0x04, 0xc3, 0x23, 0x96, 0x18, 0x9a, 0x05, 0x12, 0x07, 0xe2, 0x80, 0x27, 0xeb, 0x75, 0xb2, 0x78, 0xba, 0x2e, 0x25, 0xa6, 0x1c, 0xc6, 0xb4, 0xdd, 0xe8, 0x1f, 0x74, 0xbd, 0x4b, 0x8a, 0x8b, 0x3e, 0x70, 0x66, 0xb5, 0x03, 0x48, 0x0e, 0xf6, 0x35, 0x61, 0xb9, 0x57, 0xc1, 0x86, 0x9e, 0x1d, 0xf8, 0xe1, 0x11, 0x98, 0xd9, 0x69, 0x94, 0x8e, 0x1e, 0x9b, 0xe9, 0x87, 0x55, 0xce, 0xdf, 0x28, 0xa1, 0x8c, 0x0d, 0x89, 0xe6, 0xbf, 0x68, 0x42, 0x99, 0x41, 0x0f, 0x2d, 0x54, 0xb0, 0x16, 0xbb, 0x0c, 0xcd, 0xec, 0x13, 0x97, 0x5f, 0x17, 0x44, 0xa7, 0xc4, 0x3d, 0x7e, 0x5d, 0x64, 0x73, 0x19, 0x81, 0x60, 0xdc, 0x4f, 0x2a, 0x22, 0x88, 0x90, 0xee, 0x46, 0x14, 0xb8, 0x5e, 0xde, 0xdb, 0x0b, 0x32, 0xe0, 0x0a, 0x3a, 0x06, 0x49, 0x5c, 0x24, 0xd3, 0xc2, 0x62, 0xac, 0x95, 0x91, 0x79, 0xe4, 0xc8, 0xe7, 0x6d, 0x37, 0xd5, 0x8d, 0xa9, 0x4e, 0x56, 0x6c, 0xea, 0xf4, 0x7a, 0x65, 0x08, 0xae +}, +{ +0x6d, 0x37, 0xc8, 0xe7, 0xa9, 0x4e, 0xd5, 0x8d, 0xea, 0xf4, 0x56, 0x6c, 0x08, 0xae, 0x7a, 0x65, 0x0a, 0x3a, 0x32, 0xe0, 0x5c, 0x24, 0x06, 0x49, 0x62, 0xac, 0xd3, 0xc2, 0x79, 0xe4, 0x95, 0x91, 0xdc, 0x4f, 0x81, 0x60, 0x88, 0x90, 0x2a, 0x22, 0x14, 0xb8, 0xee, 0x46, 0xdb, 0x0b, 0x5e, 0xde, 0xec, 0x13, 0x0c, 0xcd, 0x17, 0x44, 0x97, 0x5f, 0x3d, 0x7e, 0xa7, 0xc4, 0x73, 0x19, 0x5d, 0x64, 0x0d, 0x89, 0xa1, 0x8c, 0x68, 0x42, 0xe6, 0xbf, 0x0f, 0x2d, 0x99, 0x41, 0x16, 0xbb, 0x54, 0xb0, 0x11, 0x98, 0xf8, 0xe1, 0x94, 0x8e, 0xd9, 0x69, 0xe9, 0x87, 0x1e, 0x9b, 0xdf, 0x28, 0x55, 0xce, 0x66, 0xb5, 0x3e, 0x70, 0x0e, 0xf6, 0x03, 0x48, 0xb9, 0x57, 0x35, 0x61, 0x9e, 0x1d, 0xc1, 0x86, 0x2e, 0x25, 0x78, 0xba, 0xc6, 0xb4, 0xa6, 0x1c, 0x1f, 0x74, 0xdd, 0xe8, 0x8a, 0x8b, 0xbd, 0x4b, 0xc3, 0x23, 0xc7, 0x04, 0x9a, 0x05, 0x96, 0x18, 0xe2, 0x80, 0x12, 0x07, 0x75, 0xb2, 0x27, 0xeb, 0x26, 0x93, 0xfd, 0xb7, 0xcc, 0xf7, 0x3f, 0x36, 0xf1, 0xe5, 0xa5, 0x34, 0x15, 0x31, 0xd8, 0x71, 0x7d, 0xc9, 0x82, 0xca, 0xf0, 0x47, 0x59, 0xfa, 0xaf, 0xa2, 0xd4, 0xad, 0xc0, 0x72, 0xa4, 0x9c, 0x7b, 0x77, 0x7c, 0x63, 0xc5, 0x6f, 0x6b, 0xf2, 0x2b, 0x67, 0x01, 0x30, 0x76, 0xab, 0xd7, 0xfe, 0x8f, 0x40, 0xa3, 0x51, 0xf5, 0x38, 0x9d, 0x92, 0x21, 0xda, 0xb6, 0xbc, 0xd2, 0xf3, 0xff, 0x10, 0xfb, 0xaa, 0xef, 0xd0, 0x85, 0x33, 0x4d, 0x43, 0x7f, 0x02, 0xf9, 0x45, 0xa8, 0x9f, 0x3c, 0x50, 0xed, 0x00, 0xd1, 0x53, 0x5b, 0xb1, 0xfc, 0x20, 0x39, 0xbe, 0xcb, 0x6a, 0xcf, 0x58, 0x4c, 0x4a, 0x1a, 0x2c, 0x83, 0x09, 0xa0, 0x5a, 0x6e, 0x1b, 0xb3, 0xd6, 0x3b, 0x52, 0x84, 0x2f, 0xe3, 0x29 +}, +{ +0x0c, 0xcd, 0xec, 0x13, 0x97, 0x5f, 0x17, 0x44, 0xa7, 0xc4, 0x3d, 0x7e, 0x5d, 0x64, 0x73, 0x19, 0x81, 0x60, 0xdc, 0x4f, 0x2a, 0x22, 0x88, 0x90, 0xee, 0x46, 0x14, 0xb8, 0x5e, 0xde, 0xdb, 0x0b, 0x32, 0xe0, 0x0a, 0x3a, 0x06, 0x49, 0x5c, 0x24, 0xd3, 0xc2, 0x62, 0xac, 0x95, 0x91, 0x79, 0xe4, 0xc8, 0xe7, 0x6d, 0x37, 0xd5, 0x8d, 0xa9, 0x4e, 0x56, 0x6c, 0xea, 0xf4, 0x7a, 0x65, 0x08, 0xae, 0x78, 0xba, 0x2e, 0x25, 0xa6, 0x1c, 0xc6, 0xb4, 0xdd, 0xe8, 0x1f, 0x74, 0xbd, 0x4b, 0x8a, 0x8b, 0x3e, 0x70, 0x66, 0xb5, 0x03, 0x48, 0x0e, 0xf6, 0x35, 0x61, 0xb9, 0x57, 0xc1, 0x86, 0x9e, 0x1d, 0xf8, 0xe1, 0x11, 0x98, 0xd9, 0x69, 0x94, 0x8e, 0x1e, 0x9b, 0xe9, 0x87, 0x55, 0xce, 0xdf, 0x28, 0xa1, 0x8c, 0x0d, 0x89, 0xe6, 0xbf, 0x68, 0x42, 0x99, 0x41, 0x0f, 0x2d, 0x54, 0xb0, 0x16, 0xbb, 0x7c, 0x63, 0x7b, 0x77, 0x6b, 0xf2, 0xc5, 0x6f, 0x01, 0x30, 0x2b, 0x67, 0xd7, 0xfe, 0x76, 0xab, 0x82, 0xca, 0x7d, 0xc9, 0x59, 0xfa, 0xf0, 0x47, 0xd4, 0xad, 0xaf, 0xa2, 0xa4, 0x9c, 0xc0, 0x72, 0xfd, 0xb7, 0x26, 0x93, 0x3f, 0x36, 0xcc, 0xf7, 0xa5, 0x34, 0xf1, 0xe5, 0xd8, 0x71, 0x15, 0x31, 0xc7, 0x04, 0xc3, 0x23, 0x96, 0x18, 0x9a, 0x05, 0x12, 0x07, 0xe2, 0x80, 0x27, 0xeb, 0x75, 0xb2, 0x83, 0x09, 0x1a, 0x2c, 0x6e, 0x1b, 0xa0, 0x5a, 0x3b, 0x52, 0xb3, 0xd6, 0xe3, 0x29, 0x84, 0x2f, 0xd1, 0x53, 0xed, 0x00, 0xfc, 0x20, 0x5b, 0xb1, 0xcb, 0x6a, 0x39, 0xbe, 0x4c, 0x4a, 0xcf, 0x58, 0xef, 0xd0, 0xfb, 0xaa, 0x4d, 0x43, 0x85, 0x33, 0xf9, 0x45, 0x7f, 0x02, 0x3c, 0x50, 0xa8, 0x9f, 0xa3, 0x51, 0x8f, 0x40, 0x9d, 0x92, 0xf5, 0x38, 0xb6, 0xbc, 0x21, 0xda, 0xff, 0x10, 0xd2, 0xf3 +}, +{ +0x1c, 0xa6, 0xb4, 0xc6, 0xba, 0x78, 0x25, 0x2e, 0x4b, 0xbd, 0x8b, 0x8a, 0xe8, 0xdd, 0x74, 0x1f, 0x48, 0x03, 0xf6, 0x0e, 0x70, 0x3e, 0xb5, 0x66, 0x86, 0xc1, 0x1d, 0x9e, 0x61, 0x35, 0x57, 0xb9, 0x69, 0xd9, 0x8e, 0x94, 0xe1, 0xf8, 0x98, 0x11, 0xce, 0x55, 0x28, 0xdf, 0x9b, 0x1e, 0x87, 0xe9, 0xbf, 0xe6, 0x42, 0x68, 0x8c, 0xa1, 0x89, 0x0d, 0xb0, 0x54, 0xbb, 0x16, 0x41, 0x99, 0x2d, 0x0f, 0x5f, 0x97, 0x44, 0x17, 0xcd, 0x0c, 0x13, 0xec, 0x64, 0x5d, 0x19, 0x73, 0xc4, 0xa7, 0x7e, 0x3d, 0x22, 0x2a, 0x90, 0x88, 0x60, 0x81, 0x4f, 0xdc, 0xde, 0x5e, 0x0b, 0xdb, 0x46, 0xee, 0xb8, 0x14, 0x49, 0x06, 0x24, 0x5c, 0xe0, 0x32, 0x3a, 0x0a, 0x91, 0x95, 0xe4, 0x79, 0xc2, 0xd3, 0xac, 0x62, 0x8d, 0xd5, 0x4e, 0xa9, 0xe7, 0xc8, 0x37, 0x6d, 0x65, 0x7a, 0xae, 0x08, 0x6c, 0x56, 0xf4, 0xea, 0x1b, 0x6e, 0x5a, 0xa0, 0x09, 0x83, 0x2c, 0x1a, 0x29, 0xe3, 0x2f, 0x84, 0x52, 0x3b, 0xd6, 0xb3, 0x20, 0xfc, 0xb1, 0x5b, 0x53, 0xd1, 0x00, 0xed, 0x4a, 0x4c, 0x58, 0xcf, 0x6a, 0xcb, 0xbe, 0x39, 0x43, 0x4d, 0x33, 0x85, 0xd0, 0xef, 0xaa, 0xfb, 0x50, 0x3c, 0x9f, 0xa8, 0x45, 0xf9, 0x02, 0x7f, 0x92, 0x9d, 0x38, 0xf5, 0x51, 0xa3, 0x40, 0x8f, 0x10, 0xff, 0xf3, 0xd2, 0xbc, 0xb6, 0xda, 0x21, 0xf2, 0x6b, 0x6f, 0xc5, 0x63, 0x7c, 0x77, 0x7b, 0xfe, 0xd7, 0xab, 0x76, 0x30, 0x01, 0x67, 0x2b, 0xfa, 0x59, 0x47, 0xf0, 0xca, 0x82, 0xc9, 0x7d, 0x9c, 0xa4, 0x72, 0xc0, 0xad, 0xd4, 0xa2, 0xaf, 0x36, 0x3f, 0xf7, 0xcc, 0xb7, 0xfd, 0x93, 0x26, 0x71, 0xd8, 0x31, 0x15, 0x34, 0xa5, 0xe5, 0xf1, 0x18, 0x96, 0x05, 0x9a, 0x04, 0xc7, 0x23, 0xc3, 0xeb, 0x27, 0xb2, 0x75, 0x07, 0x12, 0x80, 0xe2 +}, +{ +0x40, 0x8f, 0x51, 0xa3, 0x38, 0xf5, 0x92, 0x9d, 0xda, 0x21, 0xbc, 0xb6, 0xf3, 0xd2, 0x10, 0xff, 0xaa, 0xfb, 0xd0, 0xef, 0x33, 0x85, 0x43, 0x4d, 0x02, 0x7f, 0x45, 0xf9, 0x9f, 0xa8, 0x50, 0x3c, 0x00, 0xed, 0x53, 0xd1, 0xb1, 0x5b, 0x20, 0xfc, 0xbe, 0x39, 0x6a, 0xcb, 0x58, 0xcf, 0x4a, 0x4c, 0x2c, 0x1a, 0x09, 0x83, 0x5a, 0xa0, 0x1b, 0x6e, 0xd6, 0xb3, 0x52, 0x3b, 0x2f, 0x84, 0x29, 0xe3, 0x23, 0xc3, 0x04, 0xc7, 0x05, 0x9a, 0x18, 0x96, 0x80, 0xe2, 0x07, 0x12, 0xb2, 0x75, 0xeb, 0x27, 0x93, 0x26, 0xb7, 0xfd, 0xf7, 0xcc, 0x36, 0x3f, 0xe5, 0xf1, 0x34, 0xa5, 0x31, 0x15, 0x71, 0xd8, 0xc9, 0x7d, 0xca, 0x82, 0x47, 0xf0, 0xfa, 0x59, 0xa2, 0xaf, 0xad, 0xd4, 0x72, 0xc0, 0x9c, 0xa4, 0x77, 0x7b, 0x63, 0x7c, 0x6f, 0xc5, 0xf2, 0x6b, 0x67, 0x2b, 0x30, 0x01, 0xab, 0x76, 0xfe, 0xd7, 0x89, 0x0d, 0x8c, 0xa1, 0x42, 0x68, 0xbf, 0xe6, 0x2d, 0x0f, 0x41, 0x99, 0xbb, 0x16, 0xb0, 0x54, 0x98, 0x11, 0xe1, 0xf8, 0x8e, 0x94, 0x69, 0xd9, 0x87, 0xe9, 0x9b, 0x1e, 0x28, 0xdf, 0xce, 0x55, 0xb5, 0x66, 0x70, 0x3e, 0xf6, 0x0e, 0x48, 0x03, 0x57, 0xb9, 0x61, 0x35, 0x1d, 0x9e, 0x86, 0xc1, 0x25, 0x2e, 0xba, 0x78, 0xb4, 0xc6, 0x1c, 0xa6, 0x74, 0x1f, 0xe8, 0xdd, 0x8b, 0x8a, 0x4b, 0xbd, 0x37, 0x6d, 0xe7, 0xc8, 0x4e, 0xa9, 0x8d, 0xd5, 0xf4, 0xea, 0x6c, 0x56, 0xae, 0x08, 0x65, 0x7a, 0x3a, 0x0a, 0xe0, 0x32, 0x24, 0x5c, 0x49, 0x06, 0xac, 0x62, 0xc2, 0xd3, 0xe4, 0x79, 0x91, 0x95, 0x4f, 0xdc, 0x60, 0x81, 0x90, 0x88, 0x22, 0x2a, 0xb8, 0x14, 0x46, 0xee, 0x0b, 0xdb, 0xde, 0x5e, 0x13, 0xec, 0xcd, 0x0c, 0x44, 0x17, 0x5f, 0x97, 0x7e, 0x3d, 0xc4, 0xa7, 0x19, 0x73, 0x64, 0x5d +}, +{ +0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75 +}, +{ +0x69, 0xd9, 0x8e, 0x94, 0xe1, 0xf8, 0x98, 0x11, 0xce, 0x55, 0x28, 0xdf, 0x9b, 0x1e, 0x87, 0xe9, 0xbf, 0xe6, 0x42, 0x68, 0x8c, 0xa1, 0x89, 0x0d, 0xb0, 0x54, 0xbb, 0x16, 0x41, 0x99, 0x2d, 0x0f, 0x1c, 0xa6, 0xb4, 0xc6, 0xba, 0x78, 0x25, 0x2e, 0x4b, 0xbd, 0x8b, 0x8a, 0xe8, 0xdd, 0x74, 0x1f, 0x48, 0x03, 0xf6, 0x0e, 0x70, 0x3e, 0xb5, 0x66, 0x86, 0xc1, 0x1d, 0x9e, 0x61, 0x35, 0x57, 0xb9, 0x49, 0x06, 0x24, 0x5c, 0xe0, 0x32, 0x3a, 0x0a, 0x91, 0x95, 0xe4, 0x79, 0xc2, 0xd3, 0xac, 0x62, 0x8d, 0xd5, 0x4e, 0xa9, 0xe7, 0xc8, 0x37, 0x6d, 0x65, 0x7a, 0xae, 0x08, 0x6c, 0x56, 0xf4, 0xea, 0x5f, 0x97, 0x44, 0x17, 0xcd, 0x0c, 0x13, 0xec, 0x64, 0x5d, 0x19, 0x73, 0xc4, 0xa7, 0x7e, 0x3d, 0x22, 0x2a, 0x90, 0x88, 0x60, 0x81, 0x4f, 0xdc, 0xde, 0x5e, 0x0b, 0xdb, 0x46, 0xee, 0xb8, 0x14, 0x43, 0x4d, 0x33, 0x85, 0xd0, 0xef, 0xaa, 0xfb, 0x50, 0x3c, 0x9f, 0xa8, 0x45, 0xf9, 0x02, 0x7f, 0x92, 0x9d, 0x38, 0xf5, 0x51, 0xa3, 0x40, 0x8f, 0x10, 0xff, 0xf3, 0xd2, 0xbc, 0xb6, 0xda, 0x21, 0x1b, 0x6e, 0x5a, 0xa0, 0x09, 0x83, 0x2c, 0x1a, 0x29, 0xe3, 0x2f, 0x84, 0x52, 0x3b, 0xd6, 0xb3, 0x20, 0xfc, 0xb1, 0x5b, 0x53, 0xd1, 0x00, 0xed, 0x4a, 0x4c, 0x58, 0xcf, 0x6a, 0xcb, 0xbe, 0x39, 0x36, 0x3f, 0xf7, 0xcc, 0xb7, 0xfd, 0x93, 0x26, 0x71, 0xd8, 0x31, 0x15, 0x34, 0xa5, 0xe5, 0xf1, 0x18, 0x96, 0x05, 0x9a, 0x04, 0xc7, 0x23, 0xc3, 0xeb, 0x27, 0xb2, 0x75, 0x07, 0x12, 0x80, 0xe2, 0xf2, 0x6b, 0x6f, 0xc5, 0x63, 0x7c, 0x77, 0x7b, 0xfe, 0xd7, 0xab, 0x76, 0x30, 0x01, 0x67, 0x2b, 0xfa, 0x59, 0x47, 0xf0, 0xca, 0x82, 0xc9, 0x7d, 0x9c, 0xa4, 0x72, 0xc0, 0xad, 0xd4, 0xa2, 0xaf +} +}, +{ +{ +0xa8, 0x9f, 0x3c, 0x50, 0x7f, 0x02, 0xf9, 0x45, 0x85, 0x33, 0x4d, 0x43, 0xfb, 0xaa, 0xef, 0xd0, 0xd2, 0xf3, 0xff, 0x10, 0x21, 0xda, 0xb6, 0xbc, 0xf5, 0x38, 0x9d, 0x92, 0x8f, 0x40, 0xa3, 0x51, 0x84, 0x2f, 0xe3, 0x29, 0xb3, 0xd6, 0x3b, 0x52, 0xa0, 0x5a, 0x6e, 0x1b, 0x1a, 0x2c, 0x83, 0x09, 0xcf, 0x58, 0x4c, 0x4a, 0x39, 0xbe, 0xcb, 0x6a, 0x5b, 0xb1, 0xfc, 0x20, 0xed, 0x00, 0xd1, 0x53, 0x15, 0x31, 0xd8, 0x71, 0xf1, 0xe5, 0xa5, 0x34, 0xcc, 0xf7, 0x3f, 0x36, 0x26, 0x93, 0xfd, 0xb7, 0x75, 0xb2, 0x27, 0xeb, 0xe2, 0x80, 0x12, 0x07, 0x9a, 0x05, 0x96, 0x18, 0xc3, 0x23, 0xc7, 0x04, 0x76, 0xab, 0xd7, 0xfe, 0x2b, 0x67, 0x01, 0x30, 0xc5, 0x6f, 0x6b, 0xf2, 0x7b, 0x77, 0x7c, 0x63, 0xc0, 0x72, 0xa4, 0x9c, 0xaf, 0xa2, 0xd4, 0xad, 0xf0, 0x47, 0x59, 0xfa, 0x7d, 0xc9, 0x82, 0xca, 0xdf, 0x28, 0x55, 0xce, 0xe9, 0x87, 0x1e, 0x9b, 0x94, 0x8e, 0xd9, 0x69, 0x11, 0x98, 0xf8, 0xe1, 0x16, 0xbb, 0x54, 0xb0, 0x0f, 0x2d, 0x99, 0x41, 0x68, 0x42, 0xe6, 0xbf, 0x0d, 0x89, 0xa1, 0x8c, 0x8a, 0x8b, 0xbd, 0x4b, 0x1f, 0x74, 0xdd, 0xe8, 0xc6, 0xb4, 0xa6, 0x1c, 0x2e, 0x25, 0x78, 0xba, 0x9e, 0x1d, 0xc1, 0x86, 0xb9, 0x57, 0x35, 0x61, 0x0e, 0xf6, 0x03, 0x48, 0x66, 0xb5, 0x3e, 0x70, 0x79, 0xe4, 0x95, 0x91, 0x62, 0xac, 0xd3, 0xc2, 0x5c, 0x24, 0x06, 0x49, 0x0a, 0x3a, 0x32, 0xe0, 0x08, 0xae, 0x7a, 0x65, 0xea, 0xf4, 0x56, 0x6c, 0xa9, 0x4e, 0xd5, 0x8d, 0x6d, 0x37, 0xc8, 0xe7, 0x73, 0x19, 0x5d, 0x64, 0x3d, 0x7e, 0xa7, 0xc4, 0x17, 0x44, 0x97, 0x5f, 0xec, 0x13, 0x0c, 0xcd, 0xdb, 0x0b, 0x5e, 0xde, 0x14, 0xb8, 0xee, 0x46, 0x88, 0x90, 0x2a, 0x22, 0xdc, 0x4f, 0x81, 0x60 +}, +{ +0xdd, 0xe8, 0x1f, 0x74, 0xbd, 0x4b, 0x8a, 0x8b, 0x78, 0xba, 0x2e, 0x25, 0xa6, 0x1c, 0xc6, 0xb4, 0x35, 0x61, 0xb9, 0x57, 0xc1, 0x86, 0x9e, 0x1d, 0x3e, 0x70, 0x66, 0xb5, 0x03, 0x48, 0x0e, 0xf6, 0x1e, 0x9b, 0xe9, 0x87, 0x55, 0xce, 0xdf, 0x28, 0xf8, 0xe1, 0x11, 0x98, 0xd9, 0x69, 0x94, 0x8e, 0x99, 0x41, 0x0f, 0x2d, 0x54, 0xb0, 0x16, 0xbb, 0xa1, 0x8c, 0x0d, 0x89, 0xe6, 0xbf, 0x68, 0x42, 0xa7, 0xc4, 0x3d, 0x7e, 0x5d, 0x64, 0x73, 0x19, 0x0c, 0xcd, 0xec, 0x13, 0x97, 0x5f, 0x17, 0x44, 0xee, 0x46, 0x14, 0xb8, 0x5e, 0xde, 0xdb, 0x0b, 0x81, 0x60, 0xdc, 0x4f, 0x2a, 0x22, 0x88, 0x90, 0xd3, 0xc2, 0x62, 0xac, 0x95, 0x91, 0x79, 0xe4, 0x32, 0xe0, 0x0a, 0x3a, 0x06, 0x49, 0x5c, 0x24, 0x56, 0x6c, 0xea, 0xf4, 0x7a, 0x65, 0x08, 0xae, 0xc8, 0xe7, 0x6d, 0x37, 0xd5, 0x8d, 0xa9, 0x4e, 0x3b, 0x52, 0xb3, 0xd6, 0xe3, 0x29, 0x84, 0x2f, 0x83, 0x09, 0x1a, 0x2c, 0x6e, 0x1b, 0xa0, 0x5a, 0xcb, 0x6a, 0x39, 0xbe, 0x4c, 0x4a, 0xcf, 0x58, 0xd1, 0x53, 0xed, 0x00, 0xfc, 0x20, 0x5b, 0xb1, 0xf9, 0x45, 0x7f, 0x02, 0x3c, 0x50, 0xa8, 0x9f, 0xef, 0xd0, 0xfb, 0xaa, 0x4d, 0x43, 0x85, 0x33, 0xb6, 0xbc, 0x21, 0xda, 0xff, 0x10, 0xd2, 0xf3, 0xa3, 0x51, 0x8f, 0x40, 0x9d, 0x92, 0xf5, 0x38, 0x01, 0x30, 0x2b, 0x67, 0xd7, 0xfe, 0x76, 0xab, 0x7c, 0x63, 0x7b, 0x77, 0x6b, 0xf2, 0xc5, 0x6f, 0xd4, 0xad, 0xaf, 0xa2, 0xa4, 0x9c, 0xc0, 0x72, 0x82, 0xca, 0x7d, 0xc9, 0x59, 0xfa, 0xf0, 0x47, 0xa5, 0x34, 0xf1, 0xe5, 0xd8, 0x71, 0x15, 0x31, 0xfd, 0xb7, 0x26, 0x93, 0x3f, 0x36, 0xcc, 0xf7, 0x12, 0x07, 0xe2, 0x80, 0x27, 0xeb, 0x75, 0xb2, 0xc7, 0x04, 0xc3, 0x23, 0x96, 0x18, 0x9a, 0x05 +}, +{ +0x28, 0xdf, 0xce, 0x55, 0x87, 0xe9, 0x9b, 0x1e, 0x8e, 0x94, 0x69, 0xd9, 0x98, 0x11, 0xe1, 0xf8, 0xbb, 0x16, 0xb0, 0x54, 0x2d, 0x0f, 0x41, 0x99, 0x42, 0x68, 0xbf, 0xe6, 0x89, 0x0d, 0x8c, 0xa1, 0x8b, 0x8a, 0x4b, 0xbd, 0x74, 0x1f, 0xe8, 0xdd, 0xb4, 0xc6, 0x1c, 0xa6, 0x25, 0x2e, 0xba, 0x78, 0x1d, 0x9e, 0x86, 0xc1, 0x57, 0xb9, 0x61, 0x35, 0xf6, 0x0e, 0x48, 0x03, 0xb5, 0x66, 0x70, 0x3e, 0xe4, 0x79, 0x91, 0x95, 0xac, 0x62, 0xc2, 0xd3, 0x24, 0x5c, 0x49, 0x06, 0x3a, 0x0a, 0xe0, 0x32, 0xae, 0x08, 0x65, 0x7a, 0xf4, 0xea, 0x6c, 0x56, 0x4e, 0xa9, 0x8d, 0xd5, 0x37, 0x6d, 0xe7, 0xc8, 0x19, 0x73, 0x64, 0x5d, 0x7e, 0x3d, 0xc4, 0xa7, 0x44, 0x17, 0x5f, 0x97, 0x13, 0xec, 0xcd, 0x0c, 0x0b, 0xdb, 0xde, 0x5e, 0xb8, 0x14, 0x46, 0xee, 0x90, 0x88, 0x22, 0x2a, 0x4f, 0xdc, 0x60, 0x81, 0x9f, 0xa8, 0x50, 0x3c, 0x02, 0x7f, 0x45, 0xf9, 0x33, 0x85, 0x43, 0x4d, 0xaa, 0xfb, 0xd0, 0xef, 0xf3, 0xd2, 0x10, 0xff, 0xda, 0x21, 0xbc, 0xb6, 0x38, 0xf5, 0x92, 0x9d, 0x40, 0x8f, 0x51, 0xa3, 0x2f, 0x84, 0x29, 0xe3, 0xd6, 0xb3, 0x52, 0x3b, 0x5a, 0xa0, 0x1b, 0x6e, 0x2c, 0x1a, 0x09, 0x83, 0x58, 0xcf, 0x4a, 0x4c, 0xbe, 0x39, 0x6a, 0xcb, 0xb1, 0x5b, 0x20, 0xfc, 0x00, 0xed, 0x53, 0xd1, 0x31, 0x15, 0x71, 0xd8, 0xe5, 0xf1, 0x34, 0xa5, 0xf7, 0xcc, 0x36, 0x3f, 0x93, 0x26, 0xb7, 0xfd, 0xb2, 0x75, 0xeb, 0x27, 0x80, 0xe2, 0x07, 0x12, 0x05, 0x9a, 0x18, 0x96, 0x23, 0xc3, 0x04, 0xc7, 0xab, 0x76, 0xfe, 0xd7, 0x67, 0x2b, 0x30, 0x01, 0x6f, 0xc5, 0xf2, 0x6b, 0x77, 0x7b, 0x63, 0x7c, 0x72, 0xc0, 0x9c, 0xa4, 0xa2, 0xaf, 0xad, 0xd4, 0x47, 0xf0, 0xfa, 0x59, 0xc9, 0x7d, 0xca, 0x82 +}, +{ +0xef, 0xd0, 0xfb, 0xaa, 0x4d, 0x43, 0x85, 0x33, 0xf9, 0x45, 0x7f, 0x02, 0x3c, 0x50, 0xa8, 0x9f, 0xa3, 0x51, 0x8f, 0x40, 0x9d, 0x92, 0xf5, 0x38, 0xb6, 0xbc, 0x21, 0xda, 0xff, 0x10, 0xd2, 0xf3, 0x83, 0x09, 0x1a, 0x2c, 0x6e, 0x1b, 0xa0, 0x5a, 0x3b, 0x52, 0xb3, 0xd6, 0xe3, 0x29, 0x84, 0x2f, 0xd1, 0x53, 0xed, 0x00, 0xfc, 0x20, 0x5b, 0xb1, 0xcb, 0x6a, 0x39, 0xbe, 0x4c, 0x4a, 0xcf, 0x58, 0xfd, 0xb7, 0x26, 0x93, 0x3f, 0x36, 0xcc, 0xf7, 0xa5, 0x34, 0xf1, 0xe5, 0xd8, 0x71, 0x15, 0x31, 0xc7, 0x04, 0xc3, 0x23, 0x96, 0x18, 0x9a, 0x05, 0x12, 0x07, 0xe2, 0x80, 0x27, 0xeb, 0x75, 0xb2, 0x7c, 0x63, 0x7b, 0x77, 0x6b, 0xf2, 0xc5, 0x6f, 0x01, 0x30, 0x2b, 0x67, 0xd7, 0xfe, 0x76, 0xab, 0x82, 0xca, 0x7d, 0xc9, 0x59, 0xfa, 0xf0, 0x47, 0xd4, 0xad, 0xaf, 0xa2, 0xa4, 0x9c, 0xc0, 0x72, 0xf8, 0xe1, 0x11, 0x98, 0xd9, 0x69, 0x94, 0x8e, 0x1e, 0x9b, 0xe9, 0x87, 0x55, 0xce, 0xdf, 0x28, 0xa1, 0x8c, 0x0d, 0x89, 0xe6, 0xbf, 0x68, 0x42, 0x99, 0x41, 0x0f, 0x2d, 0x54, 0xb0, 0x16, 0xbb, 0x78, 0xba, 0x2e, 0x25, 0xa6, 0x1c, 0xc6, 0xb4, 0xdd, 0xe8, 0x1f, 0x74, 0xbd, 0x4b, 0x8a, 0x8b, 0x3e, 0x70, 0x66, 0xb5, 0x03, 0x48, 0x0e, 0xf6, 0x35, 0x61, 0xb9, 0x57, 0xc1, 0x86, 0x9e, 0x1d, 0x32, 0xe0, 0x0a, 0x3a, 0x06, 0x49, 0x5c, 0x24, 0xd3, 0xc2, 0x62, 0xac, 0x95, 0x91, 0x79, 0xe4, 0xc8, 0xe7, 0x6d, 0x37, 0xd5, 0x8d, 0xa9, 0x4e, 0x56, 0x6c, 0xea, 0xf4, 0x7a, 0x65, 0x08, 0xae, 0x0c, 0xcd, 0xec, 0x13, 0x97, 0x5f, 0x17, 0x44, 0xa7, 0xc4, 0x3d, 0x7e, 0x5d, 0x64, 0x73, 0x19, 0x81, 0x60, 0xdc, 0x4f, 0x2a, 0x22, 0x88, 0x90, 0xee, 0x46, 0x14, 0xb8, 0x5e, 0xde, 0xdb, 0x0b +}, +{ +0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5 +}, +{ +0x54, 0xb0, 0x16, 0xbb, 0x99, 0x41, 0x0f, 0x2d, 0xe6, 0xbf, 0x68, 0x42, 0xa1, 0x8c, 0x0d, 0x89, 0x55, 0xce, 0xdf, 0x28, 0x1e, 0x9b, 0xe9, 0x87, 0xd9, 0x69, 0x94, 0x8e, 0xf8, 0xe1, 0x11, 0x98, 0xc1, 0x86, 0x9e, 0x1d, 0x35, 0x61, 0xb9, 0x57, 0x03, 0x48, 0x0e, 0xf6, 0x3e, 0x70, 0x66, 0xb5, 0xbd, 0x4b, 0x8a, 0x8b, 0xdd, 0xe8, 0x1f, 0x74, 0xa6, 0x1c, 0xc6, 0xb4, 0x78, 0xba, 0x2e, 0x25, 0x7a, 0x65, 0x08, 0xae, 0x56, 0x6c, 0xea, 0xf4, 0xd5, 0x8d, 0xa9, 0x4e, 0xc8, 0xe7, 0x6d, 0x37, 0x95, 0x91, 0x79, 0xe4, 0xd3, 0xc2, 0x62, 0xac, 0x06, 0x49, 0x5c, 0x24, 0x32, 0xe0, 0x0a, 0x3a, 0x5e, 0xde, 0xdb, 0x0b, 0xee, 0x46, 0x14, 0xb8, 0x2a, 0x22, 0x88, 0x90, 0x81, 0x60, 0xdc, 0x4f, 0x5d, 0x64, 0x73, 0x19, 0xa7, 0xc4, 0x3d, 0x7e, 0x97, 0x5f, 0x17, 0x44, 0x0c, 0xcd, 0xec, 0x13, 0xff, 0x10, 0xd2, 0xf3, 0xb6, 0xbc, 0x21, 0xda, 0x9d, 0x92, 0xf5, 0x38, 0xa3, 0x51, 0x8f, 0x40, 0x3c, 0x50, 0xa8, 0x9f, 0xf9, 0x45, 0x7f, 0x02, 0x4d, 0x43, 0x85, 0x33, 0xef, 0xd0, 0xfb, 0xaa, 0x4c, 0x4a, 0xcf, 0x58, 0xcb, 0x6a, 0x39, 0xbe, 0xfc, 0x20, 0x5b, 0xb1, 0xd1, 0x53, 0xed, 0x00, 0xe3, 0x29, 0x84, 0x2f, 0x3b, 0x52, 0xb3, 0xd6, 0x6e, 0x1b, 0xa0, 0x5a, 0x83, 0x09, 0x1a, 0x2c, 0x27, 0xeb, 0x75, 0xb2, 0x12, 0x07, 0xe2, 0x80, 0x96, 0x18, 0x9a, 0x05, 0xc7, 0x04, 0xc3, 0x23, 0xd8, 0x71, 0x15, 0x31, 0xa5, 0x34, 0xf1, 0xe5, 0x3f, 0x36, 0xcc, 0xf7, 0xfd, 0xb7, 0x26, 0x93, 0xa4, 0x9c, 0xc0, 0x72, 0xd4, 0xad, 0xaf, 0xa2, 0x59, 0xfa, 0xf0, 0x47, 0x82, 0xca, 0x7d, 0xc9, 0xd7, 0xfe, 0x76, 0xab, 0x01, 0x30, 0x2b, 0x67, 0x6b, 0xf2, 0xc5, 0x6f, 0x7c, 0x63, 0x7b, 0x77 +}, +{ +0x76, 0xab, 0xd7, 0xfe, 0x2b, 0x67, 0x01, 0x30, 0xc5, 0x6f, 0x6b, 0xf2, 0x7b, 0x77, 0x7c, 0x63, 0xc0, 0x72, 0xa4, 0x9c, 0xaf, 0xa2, 0xd4, 0xad, 0xf0, 0x47, 0x59, 0xfa, 0x7d, 0xc9, 0x82, 0xca, 0x15, 0x31, 0xd8, 0x71, 0xf1, 0xe5, 0xa5, 0x34, 0xcc, 0xf7, 0x3f, 0x36, 0x26, 0x93, 0xfd, 0xb7, 0x75, 0xb2, 0x27, 0xeb, 0xe2, 0x80, 0x12, 0x07, 0x9a, 0x05, 0x96, 0x18, 0xc3, 0x23, 0xc7, 0x04, 0x84, 0x2f, 0xe3, 0x29, 0xb3, 0xd6, 0x3b, 0x52, 0xa0, 0x5a, 0x6e, 0x1b, 0x1a, 0x2c, 0x83, 0x09, 0xcf, 0x58, 0x4c, 0x4a, 0x39, 0xbe, 0xcb, 0x6a, 0x5b, 0xb1, 0xfc, 0x20, 0xed, 0x00, 0xd1, 0x53, 0xa8, 0x9f, 0x3c, 0x50, 0x7f, 0x02, 0xf9, 0x45, 0x85, 0x33, 0x4d, 0x43, 0xfb, 0xaa, 0xef, 0xd0, 0xd2, 0xf3, 0xff, 0x10, 0x21, 0xda, 0xb6, 0xbc, 0xf5, 0x38, 0x9d, 0x92, 0x8f, 0x40, 0xa3, 0x51, 0x73, 0x19, 0x5d, 0x64, 0x3d, 0x7e, 0xa7, 0xc4, 0x17, 0x44, 0x97, 0x5f, 0xec, 0x13, 0x0c, 0xcd, 0xdb, 0x0b, 0x5e, 0xde, 0x14, 0xb8, 0xee, 0x46, 0x88, 0x90, 0x2a, 0x22, 0xdc, 0x4f, 0x81, 0x60, 0x79, 0xe4, 0x95, 0x91, 0x62, 0xac, 0xd3, 0xc2, 0x5c, 0x24, 0x06, 0x49, 0x0a, 0x3a, 0x32, 0xe0, 0x08, 0xae, 0x7a, 0x65, 0xea, 0xf4, 0x56, 0x6c, 0xa9, 0x4e, 0xd5, 0x8d, 0x6d, 0x37, 0xc8, 0xe7, 0x8a, 0x8b, 0xbd, 0x4b, 0x1f, 0x74, 0xdd, 0xe8, 0xc6, 0xb4, 0xa6, 0x1c, 0x2e, 0x25, 0x78, 0xba, 0x9e, 0x1d, 0xc1, 0x86, 0xb9, 0x57, 0x35, 0x61, 0x0e, 0xf6, 0x03, 0x48, 0x66, 0xb5, 0x3e, 0x70, 0xdf, 0x28, 0x55, 0xce, 0xe9, 0x87, 0x1e, 0x9b, 0x94, 0x8e, 0xd9, 0x69, 0x11, 0x98, 0xf8, 0xe1, 0x16, 0xbb, 0x54, 0xb0, 0x0f, 0x2d, 0x99, 0x41, 0x68, 0x42, 0xe6, 0xbf, 0x0d, 0x89, 0xa1, 0x8c +}, +{ +0x66, 0xb5, 0x3e, 0x70, 0x0e, 0xf6, 0x03, 0x48, 0xb9, 0x57, 0x35, 0x61, 0x9e, 0x1d, 0xc1, 0x86, 0x2e, 0x25, 0x78, 0xba, 0xc6, 0xb4, 0xa6, 0x1c, 0x1f, 0x74, 0xdd, 0xe8, 0x8a, 0x8b, 0xbd, 0x4b, 0x0d, 0x89, 0xa1, 0x8c, 0x68, 0x42, 0xe6, 0xbf, 0x0f, 0x2d, 0x99, 0x41, 0x16, 0xbb, 0x54, 0xb0, 0x11, 0x98, 0xf8, 0xe1, 0x94, 0x8e, 0xd9, 0x69, 0xe9, 0x87, 0x1e, 0x9b, 0xdf, 0x28, 0x55, 0xce, 0xdc, 0x4f, 0x81, 0x60, 0x88, 0x90, 0x2a, 0x22, 0x14, 0xb8, 0xee, 0x46, 0xdb, 0x0b, 0x5e, 0xde, 0xec, 0x13, 0x0c, 0xcd, 0x17, 0x44, 0x97, 0x5f, 0x3d, 0x7e, 0xa7, 0xc4, 0x73, 0x19, 0x5d, 0x64, 0x6d, 0x37, 0xc8, 0xe7, 0xa9, 0x4e, 0xd5, 0x8d, 0xea, 0xf4, 0x56, 0x6c, 0x08, 0xae, 0x7a, 0x65, 0x0a, 0x3a, 0x32, 0xe0, 0x5c, 0x24, 0x06, 0x49, 0x62, 0xac, 0xd3, 0xc2, 0x79, 0xe4, 0x95, 0x91, 0xed, 0x00, 0xd1, 0x53, 0x5b, 0xb1, 0xfc, 0x20, 0x39, 0xbe, 0xcb, 0x6a, 0xcf, 0x58, 0x4c, 0x4a, 0x1a, 0x2c, 0x83, 0x09, 0xa0, 0x5a, 0x6e, 0x1b, 0xb3, 0xd6, 0x3b, 0x52, 0x84, 0x2f, 0xe3, 0x29, 0x8f, 0x40, 0xa3, 0x51, 0xf5, 0x38, 0x9d, 0x92, 0x21, 0xda, 0xb6, 0xbc, 0xd2, 0xf3, 0xff, 0x10, 0xfb, 0xaa, 0xef, 0xd0, 0x85, 0x33, 0x4d, 0x43, 0x7f, 0x02, 0xf9, 0x45, 0xa8, 0x9f, 0x3c, 0x50, 0x7d, 0xc9, 0x82, 0xca, 0xf0, 0x47, 0x59, 0xfa, 0xaf, 0xa2, 0xd4, 0xad, 0xc0, 0x72, 0xa4, 0x9c, 0x7b, 0x77, 0x7c, 0x63, 0xc5, 0x6f, 0x6b, 0xf2, 0x2b, 0x67, 0x01, 0x30, 0x76, 0xab, 0xd7, 0xfe, 0xc3, 0x23, 0xc7, 0x04, 0x9a, 0x05, 0x96, 0x18, 0xe2, 0x80, 0x12, 0x07, 0x75, 0xb2, 0x27, 0xeb, 0x26, 0x93, 0xfd, 0xb7, 0xcc, 0xf7, 0x3f, 0x36, 0xf1, 0xe5, 0xa5, 0x34, 0x15, 0x31, 0xd8, 0x71 +}, +{ +0xcf, 0x58, 0x4c, 0x4a, 0x39, 0xbe, 0xcb, 0x6a, 0x5b, 0xb1, 0xfc, 0x20, 0xed, 0x00, 0xd1, 0x53, 0x84, 0x2f, 0xe3, 0x29, 0xb3, 0xd6, 0x3b, 0x52, 0xa0, 0x5a, 0x6e, 0x1b, 0x1a, 0x2c, 0x83, 0x09, 0xd2, 0xf3, 0xff, 0x10, 0x21, 0xda, 0xb6, 0xbc, 0xf5, 0x38, 0x9d, 0x92, 0x8f, 0x40, 0xa3, 0x51, 0xa8, 0x9f, 0x3c, 0x50, 0x7f, 0x02, 0xf9, 0x45, 0x85, 0x33, 0x4d, 0x43, 0xfb, 0xaa, 0xef, 0xd0, 0xc0, 0x72, 0xa4, 0x9c, 0xaf, 0xa2, 0xd4, 0xad, 0xf0, 0x47, 0x59, 0xfa, 0x7d, 0xc9, 0x82, 0xca, 0x76, 0xab, 0xd7, 0xfe, 0x2b, 0x67, 0x01, 0x30, 0xc5, 0x6f, 0x6b, 0xf2, 0x7b, 0x77, 0x7c, 0x63, 0x75, 0xb2, 0x27, 0xeb, 0xe2, 0x80, 0x12, 0x07, 0x9a, 0x05, 0x96, 0x18, 0xc3, 0x23, 0xc7, 0x04, 0x15, 0x31, 0xd8, 0x71, 0xf1, 0xe5, 0xa5, 0x34, 0xcc, 0xf7, 0x3f, 0x36, 0x26, 0x93, 0xfd, 0xb7, 0x9e, 0x1d, 0xc1, 0x86, 0xb9, 0x57, 0x35, 0x61, 0x0e, 0xf6, 0x03, 0x48, 0x66, 0xb5, 0x3e, 0x70, 0x8a, 0x8b, 0xbd, 0x4b, 0x1f, 0x74, 0xdd, 0xe8, 0xc6, 0xb4, 0xa6, 0x1c, 0x2e, 0x25, 0x78, 0xba, 0x16, 0xbb, 0x54, 0xb0, 0x0f, 0x2d, 0x99, 0x41, 0x68, 0x42, 0xe6, 0xbf, 0x0d, 0x89, 0xa1, 0x8c, 0xdf, 0x28, 0x55, 0xce, 0xe9, 0x87, 0x1e, 0x9b, 0x94, 0x8e, 0xd9, 0x69, 0x11, 0x98, 0xf8, 0xe1, 0xdb, 0x0b, 0x5e, 0xde, 0x14, 0xb8, 0xee, 0x46, 0x88, 0x90, 0x2a, 0x22, 0xdc, 0x4f, 0x81, 0x60, 0x73, 0x19, 0x5d, 0x64, 0x3d, 0x7e, 0xa7, 0xc4, 0x17, 0x44, 0x97, 0x5f, 0xec, 0x13, 0x0c, 0xcd, 0x08, 0xae, 0x7a, 0x65, 0xea, 0xf4, 0x56, 0x6c, 0xa9, 0x4e, 0xd5, 0x8d, 0x6d, 0x37, 0xc8, 0xe7, 0x79, 0xe4, 0x95, 0x91, 0x62, 0xac, 0xd3, 0xc2, 0x5c, 0x24, 0x06, 0x49, 0x0a, 0x3a, 0x32, 0xe0 +}, +{ +0x65, 0x7a, 0xae, 0x08, 0x6c, 0x56, 0xf4, 0xea, 0x8d, 0xd5, 0x4e, 0xa9, 0xe7, 0xc8, 0x37, 0x6d, 0x91, 0x95, 0xe4, 0x79, 0xc2, 0xd3, 0xac, 0x62, 0x49, 0x06, 0x24, 0x5c, 0xe0, 0x32, 0x3a, 0x0a, 0xde, 0x5e, 0x0b, 0xdb, 0x46, 0xee, 0xb8, 0x14, 0x22, 0x2a, 0x90, 0x88, 0x60, 0x81, 0x4f, 0xdc, 0x64, 0x5d, 0x19, 0x73, 0xc4, 0xa7, 0x7e, 0x3d, 0x5f, 0x97, 0x44, 0x17, 0xcd, 0x0c, 0x13, 0xec, 0xb0, 0x54, 0xbb, 0x16, 0x41, 0x99, 0x2d, 0x0f, 0xbf, 0xe6, 0x42, 0x68, 0x8c, 0xa1, 0x89, 0x0d, 0xce, 0x55, 0x28, 0xdf, 0x9b, 0x1e, 0x87, 0xe9, 0x69, 0xd9, 0x8e, 0x94, 0xe1, 0xf8, 0x98, 0x11, 0x86, 0xc1, 0x1d, 0x9e, 0x61, 0x35, 0x57, 0xb9, 0x48, 0x03, 0xf6, 0x0e, 0x70, 0x3e, 0xb5, 0x66, 0x4b, 0xbd, 0x8b, 0x8a, 0xe8, 0xdd, 0x74, 0x1f, 0x1c, 0xa6, 0xb4, 0xc6, 0xba, 0x78, 0x25, 0x2e, 0xeb, 0x27, 0xb2, 0x75, 0x07, 0x12, 0x80, 0xe2, 0x18, 0x96, 0x05, 0x9a, 0x04, 0xc7, 0x23, 0xc3, 0x71, 0xd8, 0x31, 0x15, 0x34, 0xa5, 0xe5, 0xf1, 0x36, 0x3f, 0xf7, 0xcc, 0xb7, 0xfd, 0x93, 0x26, 0x9c, 0xa4, 0x72, 0xc0, 0xad, 0xd4, 0xa2, 0xaf, 0xfa, 0x59, 0x47, 0xf0, 0xca, 0x82, 0xc9, 0x7d, 0xfe, 0xd7, 0xab, 0x76, 0x30, 0x01, 0x67, 0x2b, 0xf2, 0x6b, 0x6f, 0xc5, 0x63, 0x7c, 0x77, 0x7b, 0x10, 0xff, 0xf3, 0xd2, 0xbc, 0xb6, 0xda, 0x21, 0x92, 0x9d, 0x38, 0xf5, 0x51, 0xa3, 0x40, 0x8f, 0x50, 0x3c, 0x9f, 0xa8, 0x45, 0xf9, 0x02, 0x7f, 0x43, 0x4d, 0x33, 0x85, 0xd0, 0xef, 0xaa, 0xfb, 0x4a, 0x4c, 0x58, 0xcf, 0x6a, 0xcb, 0xbe, 0x39, 0x20, 0xfc, 0xb1, 0x5b, 0x53, 0xd1, 0x00, 0xed, 0x29, 0xe3, 0x2f, 0x84, 0x52, 0x3b, 0xd6, 0xb3, 0x1b, 0x6e, 0x5a, 0xa0, 0x09, 0x83, 0x2c, 0x1a +}, +{ +0x7a, 0x65, 0x08, 0xae, 0x56, 0x6c, 0xea, 0xf4, 0xd5, 0x8d, 0xa9, 0x4e, 0xc8, 0xe7, 0x6d, 0x37, 0x95, 0x91, 0x79, 0xe4, 0xd3, 0xc2, 0x62, 0xac, 0x06, 0x49, 0x5c, 0x24, 0x32, 0xe0, 0x0a, 0x3a, 0x5e, 0xde, 0xdb, 0x0b, 0xee, 0x46, 0x14, 0xb8, 0x2a, 0x22, 0x88, 0x90, 0x81, 0x60, 0xdc, 0x4f, 0x5d, 0x64, 0x73, 0x19, 0xa7, 0xc4, 0x3d, 0x7e, 0x97, 0x5f, 0x17, 0x44, 0x0c, 0xcd, 0xec, 0x13, 0x54, 0xb0, 0x16, 0xbb, 0x99, 0x41, 0x0f, 0x2d, 0xe6, 0xbf, 0x68, 0x42, 0xa1, 0x8c, 0x0d, 0x89, 0x55, 0xce, 0xdf, 0x28, 0x1e, 0x9b, 0xe9, 0x87, 0xd9, 0x69, 0x94, 0x8e, 0xf8, 0xe1, 0x11, 0x98, 0xc1, 0x86, 0x9e, 0x1d, 0x35, 0x61, 0xb9, 0x57, 0x03, 0x48, 0x0e, 0xf6, 0x3e, 0x70, 0x66, 0xb5, 0xbd, 0x4b, 0x8a, 0x8b, 0xdd, 0xe8, 0x1f, 0x74, 0xa6, 0x1c, 0xc6, 0xb4, 0x78, 0xba, 0x2e, 0x25, 0x27, 0xeb, 0x75, 0xb2, 0x12, 0x07, 0xe2, 0x80, 0x96, 0x18, 0x9a, 0x05, 0xc7, 0x04, 0xc3, 0x23, 0xd8, 0x71, 0x15, 0x31, 0xa5, 0x34, 0xf1, 0xe5, 0x3f, 0x36, 0xcc, 0xf7, 0xfd, 0xb7, 0x26, 0x93, 0xa4, 0x9c, 0xc0, 0x72, 0xd4, 0xad, 0xaf, 0xa2, 0x59, 0xfa, 0xf0, 0x47, 0x82, 0xca, 0x7d, 0xc9, 0xd7, 0xfe, 0x76, 0xab, 0x01, 0x30, 0x2b, 0x67, 0x6b, 0xf2, 0xc5, 0x6f, 0x7c, 0x63, 0x7b, 0x77, 0xff, 0x10, 0xd2, 0xf3, 0xb6, 0xbc, 0x21, 0xda, 0x9d, 0x92, 0xf5, 0x38, 0xa3, 0x51, 0x8f, 0x40, 0x3c, 0x50, 0xa8, 0x9f, 0xf9, 0x45, 0x7f, 0x02, 0x4d, 0x43, 0x85, 0x33, 0xef, 0xd0, 0xfb, 0xaa, 0x4c, 0x4a, 0xcf, 0x58, 0xcb, 0x6a, 0x39, 0xbe, 0xfc, 0x20, 0x5b, 0xb1, 0xd1, 0x53, 0xed, 0x00, 0xe3, 0x29, 0x84, 0x2f, 0x3b, 0x52, 0xb3, 0xd6, 0x6e, 0x1b, 0xa0, 0x5a, 0x83, 0x09, 0x1a, 0x2c +}, +{ +0x00, 0xed, 0x53, 0xd1, 0xb1, 0x5b, 0x20, 0xfc, 0xbe, 0x39, 0x6a, 0xcb, 0x58, 0xcf, 0x4a, 0x4c, 0x2c, 0x1a, 0x09, 0x83, 0x5a, 0xa0, 0x1b, 0x6e, 0xd6, 0xb3, 0x52, 0x3b, 0x2f, 0x84, 0x29, 0xe3, 0x40, 0x8f, 0x51, 0xa3, 0x38, 0xf5, 0x92, 0x9d, 0xda, 0x21, 0xbc, 0xb6, 0xf3, 0xd2, 0x10, 0xff, 0xaa, 0xfb, 0xd0, 0xef, 0x33, 0x85, 0x43, 0x4d, 0x02, 0x7f, 0x45, 0xf9, 0x9f, 0xa8, 0x50, 0x3c, 0xc9, 0x7d, 0xca, 0x82, 0x47, 0xf0, 0xfa, 0x59, 0xa2, 0xaf, 0xad, 0xd4, 0x72, 0xc0, 0x9c, 0xa4, 0x77, 0x7b, 0x63, 0x7c, 0x6f, 0xc5, 0xf2, 0x6b, 0x67, 0x2b, 0x30, 0x01, 0xab, 0x76, 0xfe, 0xd7, 0x23, 0xc3, 0x04, 0xc7, 0x05, 0x9a, 0x18, 0x96, 0x80, 0xe2, 0x07, 0x12, 0xb2, 0x75, 0xeb, 0x27, 0x93, 0x26, 0xb7, 0xfd, 0xf7, 0xcc, 0x36, 0x3f, 0xe5, 0xf1, 0x34, 0xa5, 0x31, 0x15, 0x71, 0xd8, 0xb5, 0x66, 0x70, 0x3e, 0xf6, 0x0e, 0x48, 0x03, 0x57, 0xb9, 0x61, 0x35, 0x1d, 0x9e, 0x86, 0xc1, 0x25, 0x2e, 0xba, 0x78, 0xb4, 0xc6, 0x1c, 0xa6, 0x74, 0x1f, 0xe8, 0xdd, 0x8b, 0x8a, 0x4b, 0xbd, 0x89, 0x0d, 0x8c, 0xa1, 0x42, 0x68, 0xbf, 0xe6, 0x2d, 0x0f, 0x41, 0x99, 0xbb, 0x16, 0xb0, 0x54, 0x98, 0x11, 0xe1, 0xf8, 0x8e, 0x94, 0x69, 0xd9, 0x87, 0xe9, 0x9b, 0x1e, 0x28, 0xdf, 0xce, 0x55, 0x4f, 0xdc, 0x60, 0x81, 0x90, 0x88, 0x22, 0x2a, 0xb8, 0x14, 0x46, 0xee, 0x0b, 0xdb, 0xde, 0x5e, 0x13, 0xec, 0xcd, 0x0c, 0x44, 0x17, 0x5f, 0x97, 0x7e, 0x3d, 0xc4, 0xa7, 0x19, 0x73, 0x64, 0x5d, 0x37, 0x6d, 0xe7, 0xc8, 0x4e, 0xa9, 0x8d, 0xd5, 0xf4, 0xea, 0x6c, 0x56, 0xae, 0x08, 0x65, 0x7a, 0x3a, 0x0a, 0xe0, 0x32, 0x24, 0x5c, 0x49, 0x06, 0xac, 0x62, 0xc2, 0xd3, 0xe4, 0x79, 0x91, 0x95 +}, +{ +0x14, 0xb8, 0xee, 0x46, 0xdb, 0x0b, 0x5e, 0xde, 0xdc, 0x4f, 0x81, 0x60, 0x88, 0x90, 0x2a, 0x22, 0x3d, 0x7e, 0xa7, 0xc4, 0x73, 0x19, 0x5d, 0x64, 0xec, 0x13, 0x0c, 0xcd, 0x17, 0x44, 0x97, 0x5f, 0xea, 0xf4, 0x56, 0x6c, 0x08, 0xae, 0x7a, 0x65, 0x6d, 0x37, 0xc8, 0xe7, 0xa9, 0x4e, 0xd5, 0x8d, 0x62, 0xac, 0xd3, 0xc2, 0x79, 0xe4, 0x95, 0x91, 0x0a, 0x3a, 0x32, 0xe0, 0x5c, 0x24, 0x06, 0x49, 0xb9, 0x57, 0x35, 0x61, 0x9e, 0x1d, 0xc1, 0x86, 0x66, 0xb5, 0x3e, 0x70, 0x0e, 0xf6, 0x03, 0x48, 0x1f, 0x74, 0xdd, 0xe8, 0x8a, 0x8b, 0xbd, 0x4b, 0x2e, 0x25, 0x78, 0xba, 0xc6, 0xb4, 0xa6, 0x1c, 0x0f, 0x2d, 0x99, 0x41, 0x16, 0xbb, 0x54, 0xb0, 0x0d, 0x89, 0xa1, 0x8c, 0x68, 0x42, 0xe6, 0xbf, 0xe9, 0x87, 0x1e, 0x9b, 0xdf, 0x28, 0x55, 0xce, 0x11, 0x98, 0xf8, 0xe1, 0x94, 0x8e, 0xd9, 0x69, 0xaf, 0xa2, 0xd4, 0xad, 0xc0, 0x72, 0xa4, 0x9c, 0x7d, 0xc9, 0x82, 0xca, 0xf0, 0x47, 0x59, 0xfa, 0x2b, 0x67, 0x01, 0x30, 0x76, 0xab, 0xd7, 0xfe, 0x7b, 0x77, 0x7c, 0x63, 0xc5, 0x6f, 0x6b, 0xf2, 0xe2, 0x80, 0x12, 0x07, 0x75, 0xb2, 0x27, 0xeb, 0xc3, 0x23, 0xc7, 0x04, 0x9a, 0x05, 0x96, 0x18, 0xf1, 0xe5, 0xa5, 0x34, 0x15, 0x31, 0xd8, 0x71, 0x26, 0x93, 0xfd, 0xb7, 0xcc, 0xf7, 0x3f, 0x36, 0x39, 0xbe, 0xcb, 0x6a, 0xcf, 0x58, 0x4c, 0x4a, 0xed, 0x00, 0xd1, 0x53, 0x5b, 0xb1, 0xfc, 0x20, 0xb3, 0xd6, 0x3b, 0x52, 0x84, 0x2f, 0xe3, 0x29, 0x1a, 0x2c, 0x83, 0x09, 0xa0, 0x5a, 0x6e, 0x1b, 0x21, 0xda, 0xb6, 0xbc, 0xd2, 0xf3, 0xff, 0x10, 0x8f, 0x40, 0xa3, 0x51, 0xf5, 0x38, 0x9d, 0x92, 0x7f, 0x02, 0xf9, 0x45, 0xa8, 0x9f, 0x3c, 0x50, 0xfb, 0xaa, 0xef, 0xd0, 0x85, 0x33, 0x4d, 0x43 +}, +{ +0x7e, 0x3d, 0xc4, 0xa7, 0x19, 0x73, 0x64, 0x5d, 0x13, 0xec, 0xcd, 0x0c, 0x44, 0x17, 0x5f, 0x97, 0xb8, 0x14, 0x46, 0xee, 0x0b, 0xdb, 0xde, 0x5e, 0x4f, 0xdc, 0x60, 0x81, 0x90, 0x88, 0x22, 0x2a, 0xac, 0x62, 0xc2, 0xd3, 0xe4, 0x79, 0x91, 0x95, 0x3a, 0x0a, 0xe0, 0x32, 0x24, 0x5c, 0x49, 0x06, 0xf4, 0xea, 0x6c, 0x56, 0xae, 0x08, 0x65, 0x7a, 0x37, 0x6d, 0xe7, 0xc8, 0x4e, 0xa9, 0x8d, 0xd5, 0x74, 0x1f, 0xe8, 0xdd, 0x8b, 0x8a, 0x4b, 0xbd, 0x25, 0x2e, 0xba, 0x78, 0xb4, 0xc6, 0x1c, 0xa6, 0x57, 0xb9, 0x61, 0x35, 0x1d, 0x9e, 0x86, 0xc1, 0xb5, 0x66, 0x70, 0x3e, 0xf6, 0x0e, 0x48, 0x03, 0x87, 0xe9, 0x9b, 0x1e, 0x28, 0xdf, 0xce, 0x55, 0x98, 0x11, 0xe1, 0xf8, 0x8e, 0x94, 0x69, 0xd9, 0x2d, 0x0f, 0x41, 0x99, 0xbb, 0x16, 0xb0, 0x54, 0x89, 0x0d, 0x8c, 0xa1, 0x42, 0x68, 0xbf, 0xe6, 0x67, 0x2b, 0x30, 0x01, 0xab, 0x76, 0xfe, 0xd7, 0x77, 0x7b, 0x63, 0x7c, 0x6f, 0xc5, 0xf2, 0x6b, 0xa2, 0xaf, 0xad, 0xd4, 0x72, 0xc0, 0x9c, 0xa4, 0xc9, 0x7d, 0xca, 0x82, 0x47, 0xf0, 0xfa, 0x59, 0xe5, 0xf1, 0x34, 0xa5, 0x31, 0x15, 0x71, 0xd8, 0x93, 0x26, 0xb7, 0xfd, 0xf7, 0xcc, 0x36, 0x3f, 0x80, 0xe2, 0x07, 0x12, 0xb2, 0x75, 0xeb, 0x27, 0x23, 0xc3, 0x04, 0xc7, 0x05, 0x9a, 0x18, 0x96, 0xd6, 0xb3, 0x52, 0x3b, 0x2f, 0x84, 0x29, 0xe3, 0x2c, 0x1a, 0x09, 0x83, 0x5a, 0xa0, 0x1b, 0x6e, 0xbe, 0x39, 0x6a, 0xcb, 0x58, 0xcf, 0x4a, 0x4c, 0x00, 0xed, 0x53, 0xd1, 0xb1, 0x5b, 0x20, 0xfc, 0x02, 0x7f, 0x45, 0xf9, 0x9f, 0xa8, 0x50, 0x3c, 0xaa, 0xfb, 0xd0, 0xef, 0x33, 0x85, 0x43, 0x4d, 0xda, 0x21, 0xbc, 0xb6, 0xf3, 0xd2, 0x10, 0xff, 0x40, 0x8f, 0x51, 0xa3, 0x38, 0xf5, 0x92, 0x9d +}, +{ +0xff, 0x10, 0xd2, 0xf3, 0xb6, 0xbc, 0x21, 0xda, 0x9d, 0x92, 0xf5, 0x38, 0xa3, 0x51, 0x8f, 0x40, 0x3c, 0x50, 0xa8, 0x9f, 0xf9, 0x45, 0x7f, 0x02, 0x4d, 0x43, 0x85, 0x33, 0xef, 0xd0, 0xfb, 0xaa, 0x4c, 0x4a, 0xcf, 0x58, 0xcb, 0x6a, 0x39, 0xbe, 0xfc, 0x20, 0x5b, 0xb1, 0xd1, 0x53, 0xed, 0x00, 0xe3, 0x29, 0x84, 0x2f, 0x3b, 0x52, 0xb3, 0xd6, 0x6e, 0x1b, 0xa0, 0x5a, 0x83, 0x09, 0x1a, 0x2c, 0x27, 0xeb, 0x75, 0xb2, 0x12, 0x07, 0xe2, 0x80, 0x96, 0x18, 0x9a, 0x05, 0xc7, 0x04, 0xc3, 0x23, 0xd8, 0x71, 0x15, 0x31, 0xa5, 0x34, 0xf1, 0xe5, 0x3f, 0x36, 0xcc, 0xf7, 0xfd, 0xb7, 0x26, 0x93, 0xa4, 0x9c, 0xc0, 0x72, 0xd4, 0xad, 0xaf, 0xa2, 0x59, 0xfa, 0xf0, 0x47, 0x82, 0xca, 0x7d, 0xc9, 0xd7, 0xfe, 0x76, 0xab, 0x01, 0x30, 0x2b, 0x67, 0x6b, 0xf2, 0xc5, 0x6f, 0x7c, 0x63, 0x7b, 0x77, 0x54, 0xb0, 0x16, 0xbb, 0x99, 0x41, 0x0f, 0x2d, 0xe6, 0xbf, 0x68, 0x42, 0xa1, 0x8c, 0x0d, 0x89, 0x55, 0xce, 0xdf, 0x28, 0x1e, 0x9b, 0xe9, 0x87, 0xd9, 0x69, 0x94, 0x8e, 0xf8, 0xe1, 0x11, 0x98, 0xc1, 0x86, 0x9e, 0x1d, 0x35, 0x61, 0xb9, 0x57, 0x03, 0x48, 0x0e, 0xf6, 0x3e, 0x70, 0x66, 0xb5, 0xbd, 0x4b, 0x8a, 0x8b, 0xdd, 0xe8, 0x1f, 0x74, 0xa6, 0x1c, 0xc6, 0xb4, 0x78, 0xba, 0x2e, 0x25, 0x7a, 0x65, 0x08, 0xae, 0x56, 0x6c, 0xea, 0xf4, 0xd5, 0x8d, 0xa9, 0x4e, 0xc8, 0xe7, 0x6d, 0x37, 0x95, 0x91, 0x79, 0xe4, 0xd3, 0xc2, 0x62, 0xac, 0x06, 0x49, 0x5c, 0x24, 0x32, 0xe0, 0x0a, 0x3a, 0x5e, 0xde, 0xdb, 0x0b, 0xee, 0x46, 0x14, 0xb8, 0x2a, 0x22, 0x88, 0x90, 0x81, 0x60, 0xdc, 0x4f, 0x5d, 0x64, 0x73, 0x19, 0xa7, 0xc4, 0x3d, 0x7e, 0x97, 0x5f, 0x17, 0x44, 0x0c, 0xcd, 0xec, 0x13 +}, +{ +0x4e, 0xa9, 0x8d, 0xd5, 0x37, 0x6d, 0xe7, 0xc8, 0xae, 0x08, 0x65, 0x7a, 0xf4, 0xea, 0x6c, 0x56, 0x24, 0x5c, 0x49, 0x06, 0x3a, 0x0a, 0xe0, 0x32, 0xe4, 0x79, 0x91, 0x95, 0xac, 0x62, 0xc2, 0xd3, 0x90, 0x88, 0x22, 0x2a, 0x4f, 0xdc, 0x60, 0x81, 0x0b, 0xdb, 0xde, 0x5e, 0xb8, 0x14, 0x46, 0xee, 0x44, 0x17, 0x5f, 0x97, 0x13, 0xec, 0xcd, 0x0c, 0x19, 0x73, 0x64, 0x5d, 0x7e, 0x3d, 0xc4, 0xa7, 0x42, 0x68, 0xbf, 0xe6, 0x89, 0x0d, 0x8c, 0xa1, 0xbb, 0x16, 0xb0, 0x54, 0x2d, 0x0f, 0x41, 0x99, 0x8e, 0x94, 0x69, 0xd9, 0x98, 0x11, 0xe1, 0xf8, 0x28, 0xdf, 0xce, 0x55, 0x87, 0xe9, 0x9b, 0x1e, 0xf6, 0x0e, 0x48, 0x03, 0xb5, 0x66, 0x70, 0x3e, 0x1d, 0x9e, 0x86, 0xc1, 0x57, 0xb9, 0x61, 0x35, 0xb4, 0xc6, 0x1c, 0xa6, 0x25, 0x2e, 0xba, 0x78, 0x8b, 0x8a, 0x4b, 0xbd, 0x74, 0x1f, 0xe8, 0xdd, 0x05, 0x9a, 0x18, 0x96, 0x23, 0xc3, 0x04, 0xc7, 0xb2, 0x75, 0xeb, 0x27, 0x80, 0xe2, 0x07, 0x12, 0xf7, 0xcc, 0x36, 0x3f, 0x93, 0x26, 0xb7, 0xfd, 0x31, 0x15, 0x71, 0xd8, 0xe5, 0xf1, 0x34, 0xa5, 0x47, 0xf0, 0xfa, 0x59, 0xc9, 0x7d, 0xca, 0x82, 0x72, 0xc0, 0x9c, 0xa4, 0xa2, 0xaf, 0xad, 0xd4, 0x6f, 0xc5, 0xf2, 0x6b, 0x77, 0x7b, 0x63, 0x7c, 0xab, 0x76, 0xfe, 0xd7, 0x67, 0x2b, 0x30, 0x01, 0x38, 0xf5, 0x92, 0x9d, 0x40, 0x8f, 0x51, 0xa3, 0xf3, 0xd2, 0x10, 0xff, 0xda, 0x21, 0xbc, 0xb6, 0x33, 0x85, 0x43, 0x4d, 0xaa, 0xfb, 0xd0, 0xef, 0x9f, 0xa8, 0x50, 0x3c, 0x02, 0x7f, 0x45, 0xf9, 0xb1, 0x5b, 0x20, 0xfc, 0x00, 0xed, 0x53, 0xd1, 0x58, 0xcf, 0x4a, 0x4c, 0xbe, 0x39, 0x6a, 0xcb, 0x5a, 0xa0, 0x1b, 0x6e, 0x2c, 0x1a, 0x09, 0x83, 0x2f, 0x84, 0x29, 0xe3, 0xd6, 0xb3, 0x52, 0x3b +} +}, +{ +{ +0xab, 0x76, 0xfe, 0xd7, 0x67, 0x2b, 0x30, 0x01, 0x6f, 0xc5, 0xf2, 0x6b, 0x77, 0x7b, 0x63, 0x7c, 0x72, 0xc0, 0x9c, 0xa4, 0xa2, 0xaf, 0xad, 0xd4, 0x47, 0xf0, 0xfa, 0x59, 0xc9, 0x7d, 0xca, 0x82, 0x31, 0x15, 0x71, 0xd8, 0xe5, 0xf1, 0x34, 0xa5, 0xf7, 0xcc, 0x36, 0x3f, 0x93, 0x26, 0xb7, 0xfd, 0xb2, 0x75, 0xeb, 0x27, 0x80, 0xe2, 0x07, 0x12, 0x05, 0x9a, 0x18, 0x96, 0x23, 0xc3, 0x04, 0xc7, 0x2f, 0x84, 0x29, 0xe3, 0xd6, 0xb3, 0x52, 0x3b, 0x5a, 0xa0, 0x1b, 0x6e, 0x2c, 0x1a, 0x09, 0x83, 0x58, 0xcf, 0x4a, 0x4c, 0xbe, 0x39, 0x6a, 0xcb, 0xb1, 0x5b, 0x20, 0xfc, 0x00, 0xed, 0x53, 0xd1, 0x9f, 0xa8, 0x50, 0x3c, 0x02, 0x7f, 0x45, 0xf9, 0x33, 0x85, 0x43, 0x4d, 0xaa, 0xfb, 0xd0, 0xef, 0xf3, 0xd2, 0x10, 0xff, 0xda, 0x21, 0xbc, 0xb6, 0x38, 0xf5, 0x92, 0x9d, 0x40, 0x8f, 0x51, 0xa3, 0x19, 0x73, 0x64, 0x5d, 0x7e, 0x3d, 0xc4, 0xa7, 0x44, 0x17, 0x5f, 0x97, 0x13, 0xec, 0xcd, 0x0c, 0x0b, 0xdb, 0xde, 0x5e, 0xb8, 0x14, 0x46, 0xee, 0x90, 0x88, 0x22, 0x2a, 0x4f, 0xdc, 0x60, 0x81, 0xe4, 0x79, 0x91, 0x95, 0xac, 0x62, 0xc2, 0xd3, 0x24, 0x5c, 0x49, 0x06, 0x3a, 0x0a, 0xe0, 0x32, 0xae, 0x08, 0x65, 0x7a, 0xf4, 0xea, 0x6c, 0x56, 0x4e, 0xa9, 0x8d, 0xd5, 0x37, 0x6d, 0xe7, 0xc8, 0x8b, 0x8a, 0x4b, 0xbd, 0x74, 0x1f, 0xe8, 0xdd, 0xb4, 0xc6, 0x1c, 0xa6, 0x25, 0x2e, 0xba, 0x78, 0x1d, 0x9e, 0x86, 0xc1, 0x57, 0xb9, 0x61, 0x35, 0xf6, 0x0e, 0x48, 0x03, 0xb5, 0x66, 0x70, 0x3e, 0x28, 0xdf, 0xce, 0x55, 0x87, 0xe9, 0x9b, 0x1e, 0x8e, 0x94, 0x69, 0xd9, 0x98, 0x11, 0xe1, 0xf8, 0xbb, 0x16, 0xb0, 0x54, 0x2d, 0x0f, 0x41, 0x99, 0x42, 0x68, 0xbf, 0xe6, 0x89, 0x0d, 0x8c, 0xa1 +}, +{ +0x96, 0x18, 0x9a, 0x05, 0xc7, 0x04, 0xc3, 0x23, 0x27, 0xeb, 0x75, 0xb2, 0x12, 0x07, 0xe2, 0x80, 0x3f, 0x36, 0xcc, 0xf7, 0xfd, 0xb7, 0x26, 0x93, 0xd8, 0x71, 0x15, 0x31, 0xa5, 0x34, 0xf1, 0xe5, 0x59, 0xfa, 0xf0, 0x47, 0x82, 0xca, 0x7d, 0xc9, 0xa4, 0x9c, 0xc0, 0x72, 0xd4, 0xad, 0xaf, 0xa2, 0x6b, 0xf2, 0xc5, 0x6f, 0x7c, 0x63, 0x7b, 0x77, 0xd7, 0xfe, 0x76, 0xab, 0x01, 0x30, 0x2b, 0x67, 0x9d, 0x92, 0xf5, 0x38, 0xa3, 0x51, 0x8f, 0x40, 0xff, 0x10, 0xd2, 0xf3, 0xb6, 0xbc, 0x21, 0xda, 0x4d, 0x43, 0x85, 0x33, 0xef, 0xd0, 0xfb, 0xaa, 0x3c, 0x50, 0xa8, 0x9f, 0xf9, 0x45, 0x7f, 0x02, 0xfc, 0x20, 0x5b, 0xb1, 0xd1, 0x53, 0xed, 0x00, 0x4c, 0x4a, 0xcf, 0x58, 0xcb, 0x6a, 0x39, 0xbe, 0x6e, 0x1b, 0xa0, 0x5a, 0x83, 0x09, 0x1a, 0x2c, 0xe3, 0x29, 0x84, 0x2f, 0x3b, 0x52, 0xb3, 0xd6, 0xd5, 0x8d, 0xa9, 0x4e, 0xc8, 0xe7, 0x6d, 0x37, 0x7a, 0x65, 0x08, 0xae, 0x56, 0x6c, 0xea, 0xf4, 0x06, 0x49, 0x5c, 0x24, 0x32, 0xe0, 0x0a, 0x3a, 0x95, 0x91, 0x79, 0xe4, 0xd3, 0xc2, 0x62, 0xac, 0x2a, 0x22, 0x88, 0x90, 0x81, 0x60, 0xdc, 0x4f, 0x5e, 0xde, 0xdb, 0x0b, 0xee, 0x46, 0x14, 0xb8, 0x97, 0x5f, 0x17, 0x44, 0x0c, 0xcd, 0xec, 0x13, 0x5d, 0x64, 0x73, 0x19, 0xa7, 0xc4, 0x3d, 0x7e, 0xe6, 0xbf, 0x68, 0x42, 0xa1, 0x8c, 0x0d, 0x89, 0x54, 0xb0, 0x16, 0xbb, 0x99, 0x41, 0x0f, 0x2d, 0xd9, 0x69, 0x94, 0x8e, 0xf8, 0xe1, 0x11, 0x98, 0x55, 0xce, 0xdf, 0x28, 0x1e, 0x9b, 0xe9, 0x87, 0x03, 0x48, 0x0e, 0xf6, 0x3e, 0x70, 0x66, 0xb5, 0xc1, 0x86, 0x9e, 0x1d, 0x35, 0x61, 0xb9, 0x57, 0xa6, 0x1c, 0xc6, 0xb4, 0x78, 0xba, 0x2e, 0x25, 0xbd, 0x4b, 0x8a, 0x8b, 0xdd, 0xe8, 0x1f, 0x74 +}, +{ +0x78, 0xba, 0x2e, 0x25, 0xa6, 0x1c, 0xc6, 0xb4, 0xdd, 0xe8, 0x1f, 0x74, 0xbd, 0x4b, 0x8a, 0x8b, 0x3e, 0x70, 0x66, 0xb5, 0x03, 0x48, 0x0e, 0xf6, 0x35, 0x61, 0xb9, 0x57, 0xc1, 0x86, 0x9e, 0x1d, 0xf8, 0xe1, 0x11, 0x98, 0xd9, 0x69, 0x94, 0x8e, 0x1e, 0x9b, 0xe9, 0x87, 0x55, 0xce, 0xdf, 0x28, 0xa1, 0x8c, 0x0d, 0x89, 0xe6, 0xbf, 0x68, 0x42, 0x99, 0x41, 0x0f, 0x2d, 0x54, 0xb0, 0x16, 0xbb, 0x0c, 0xcd, 0xec, 0x13, 0x97, 0x5f, 0x17, 0x44, 0xa7, 0xc4, 0x3d, 0x7e, 0x5d, 0x64, 0x73, 0x19, 0x81, 0x60, 0xdc, 0x4f, 0x2a, 0x22, 0x88, 0x90, 0xee, 0x46, 0x14, 0xb8, 0x5e, 0xde, 0xdb, 0x0b, 0x32, 0xe0, 0x0a, 0x3a, 0x06, 0x49, 0x5c, 0x24, 0xd3, 0xc2, 0x62, 0xac, 0x95, 0x91, 0x79, 0xe4, 0xc8, 0xe7, 0x6d, 0x37, 0xd5, 0x8d, 0xa9, 0x4e, 0x56, 0x6c, 0xea, 0xf4, 0x7a, 0x65, 0x08, 0xae, 0x83, 0x09, 0x1a, 0x2c, 0x6e, 0x1b, 0xa0, 0x5a, 0x3b, 0x52, 0xb3, 0xd6, 0xe3, 0x29, 0x84, 0x2f, 0xd1, 0x53, 0xed, 0x00, 0xfc, 0x20, 0x5b, 0xb1, 0xcb, 0x6a, 0x39, 0xbe, 0x4c, 0x4a, 0xcf, 0x58, 0xef, 0xd0, 0xfb, 0xaa, 0x4d, 0x43, 0x85, 0x33, 0xf9, 0x45, 0x7f, 0x02, 0x3c, 0x50, 0xa8, 0x9f, 0xa3, 0x51, 0x8f, 0x40, 0x9d, 0x92, 0xf5, 0x38, 0xb6, 0xbc, 0x21, 0xda, 0xff, 0x10, 0xd2, 0xf3, 0x7c, 0x63, 0x7b, 0x77, 0x6b, 0xf2, 0xc5, 0x6f, 0x01, 0x30, 0x2b, 0x67, 0xd7, 0xfe, 0x76, 0xab, 0x82, 0xca, 0x7d, 0xc9, 0x59, 0xfa, 0xf0, 0x47, 0xd4, 0xad, 0xaf, 0xa2, 0xa4, 0x9c, 0xc0, 0x72, 0xfd, 0xb7, 0x26, 0x93, 0x3f, 0x36, 0xcc, 0xf7, 0xa5, 0x34, 0xf1, 0xe5, 0xd8, 0x71, 0x15, 0x31, 0xc7, 0x04, 0xc3, 0x23, 0x96, 0x18, 0x9a, 0x05, 0x12, 0x07, 0xe2, 0x80, 0x27, 0xeb, 0x75, 0xb2 +}, +{ +0x2c, 0x1a, 0x09, 0x83, 0x5a, 0xa0, 0x1b, 0x6e, 0xd6, 0xb3, 0x52, 0x3b, 0x2f, 0x84, 0x29, 0xe3, 0x00, 0xed, 0x53, 0xd1, 0xb1, 0x5b, 0x20, 0xfc, 0xbe, 0x39, 0x6a, 0xcb, 0x58, 0xcf, 0x4a, 0x4c, 0xaa, 0xfb, 0xd0, 0xef, 0x33, 0x85, 0x43, 0x4d, 0x02, 0x7f, 0x45, 0xf9, 0x9f, 0xa8, 0x50, 0x3c, 0x40, 0x8f, 0x51, 0xa3, 0x38, 0xf5, 0x92, 0x9d, 0xda, 0x21, 0xbc, 0xb6, 0xf3, 0xd2, 0x10, 0xff, 0x77, 0x7b, 0x63, 0x7c, 0x6f, 0xc5, 0xf2, 0x6b, 0x67, 0x2b, 0x30, 0x01, 0xab, 0x76, 0xfe, 0xd7, 0xc9, 0x7d, 0xca, 0x82, 0x47, 0xf0, 0xfa, 0x59, 0xa2, 0xaf, 0xad, 0xd4, 0x72, 0xc0, 0x9c, 0xa4, 0x93, 0x26, 0xb7, 0xfd, 0xf7, 0xcc, 0x36, 0x3f, 0xe5, 0xf1, 0x34, 0xa5, 0x31, 0x15, 0x71, 0xd8, 0x23, 0xc3, 0x04, 0xc7, 0x05, 0x9a, 0x18, 0x96, 0x80, 0xe2, 0x07, 0x12, 0xb2, 0x75, 0xeb, 0x27, 0x25, 0x2e, 0xba, 0x78, 0xb4, 0xc6, 0x1c, 0xa6, 0x74, 0x1f, 0xe8, 0xdd, 0x8b, 0x8a, 0x4b, 0xbd, 0xb5, 0x66, 0x70, 0x3e, 0xf6, 0x0e, 0x48, 0x03, 0x57, 0xb9, 0x61, 0x35, 0x1d, 0x9e, 0x86, 0xc1, 0x98, 0x11, 0xe1, 0xf8, 0x8e, 0x94, 0x69, 0xd9, 0x87, 0xe9, 0x9b, 0x1e, 0x28, 0xdf, 0xce, 0x55, 0x89, 0x0d, 0x8c, 0xa1, 0x42, 0x68, 0xbf, 0xe6, 0x2d, 0x0f, 0x41, 0x99, 0xbb, 0x16, 0xb0, 0x54, 0x13, 0xec, 0xcd, 0x0c, 0x44, 0x17, 0x5f, 0x97, 0x7e, 0x3d, 0xc4, 0xa7, 0x19, 0x73, 0x64, 0x5d, 0x4f, 0xdc, 0x60, 0x81, 0x90, 0x88, 0x22, 0x2a, 0xb8, 0x14, 0x46, 0xee, 0x0b, 0xdb, 0xde, 0x5e, 0x3a, 0x0a, 0xe0, 0x32, 0x24, 0x5c, 0x49, 0x06, 0xac, 0x62, 0xc2, 0xd3, 0xe4, 0x79, 0x91, 0x95, 0x37, 0x6d, 0xe7, 0xc8, 0x4e, 0xa9, 0x8d, 0xd5, 0xf4, 0xea, 0x6c, 0x56, 0xae, 0x08, 0x65, 0x7a +}, +{ +0x42, 0x68, 0xbf, 0xe6, 0x89, 0x0d, 0x8c, 0xa1, 0xbb, 0x16, 0xb0, 0x54, 0x2d, 0x0f, 0x41, 0x99, 0x8e, 0x94, 0x69, 0xd9, 0x98, 0x11, 0xe1, 0xf8, 0x28, 0xdf, 0xce, 0x55, 0x87, 0xe9, 0x9b, 0x1e, 0xf6, 0x0e, 0x48, 0x03, 0xb5, 0x66, 0x70, 0x3e, 0x1d, 0x9e, 0x86, 0xc1, 0x57, 0xb9, 0x61, 0x35, 0xb4, 0xc6, 0x1c, 0xa6, 0x25, 0x2e, 0xba, 0x78, 0x8b, 0x8a, 0x4b, 0xbd, 0x74, 0x1f, 0xe8, 0xdd, 0x4e, 0xa9, 0x8d, 0xd5, 0x37, 0x6d, 0xe7, 0xc8, 0xae, 0x08, 0x65, 0x7a, 0xf4, 0xea, 0x6c, 0x56, 0x24, 0x5c, 0x49, 0x06, 0x3a, 0x0a, 0xe0, 0x32, 0xe4, 0x79, 0x91, 0x95, 0xac, 0x62, 0xc2, 0xd3, 0x90, 0x88, 0x22, 0x2a, 0x4f, 0xdc, 0x60, 0x81, 0x0b, 0xdb, 0xde, 0x5e, 0xb8, 0x14, 0x46, 0xee, 0x44, 0x17, 0x5f, 0x97, 0x13, 0xec, 0xcd, 0x0c, 0x19, 0x73, 0x64, 0x5d, 0x7e, 0x3d, 0xc4, 0xa7, 0x38, 0xf5, 0x92, 0x9d, 0x40, 0x8f, 0x51, 0xa3, 0xf3, 0xd2, 0x10, 0xff, 0xda, 0x21, 0xbc, 0xb6, 0x33, 0x85, 0x43, 0x4d, 0xaa, 0xfb, 0xd0, 0xef, 0x9f, 0xa8, 0x50, 0x3c, 0x02, 0x7f, 0x45, 0xf9, 0xb1, 0x5b, 0x20, 0xfc, 0x00, 0xed, 0x53, 0xd1, 0x58, 0xcf, 0x4a, 0x4c, 0xbe, 0x39, 0x6a, 0xcb, 0x5a, 0xa0, 0x1b, 0x6e, 0x2c, 0x1a, 0x09, 0x83, 0x2f, 0x84, 0x29, 0xe3, 0xd6, 0xb3, 0x52, 0x3b, 0x05, 0x9a, 0x18, 0x96, 0x23, 0xc3, 0x04, 0xc7, 0xb2, 0x75, 0xeb, 0x27, 0x80, 0xe2, 0x07, 0x12, 0xf7, 0xcc, 0x36, 0x3f, 0x93, 0x26, 0xb7, 0xfd, 0x31, 0x15, 0x71, 0xd8, 0xe5, 0xf1, 0x34, 0xa5, 0x47, 0xf0, 0xfa, 0x59, 0xc9, 0x7d, 0xca, 0x82, 0x72, 0xc0, 0x9c, 0xa4, 0xa2, 0xaf, 0xad, 0xd4, 0x6f, 0xc5, 0xf2, 0x6b, 0x77, 0x7b, 0x63, 0x7c, 0xab, 0x76, 0xfe, 0xd7, 0x67, 0x2b, 0x30, 0x01 +}, +{ +0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a +}, +{ +0x8b, 0x8a, 0x4b, 0xbd, 0x74, 0x1f, 0xe8, 0xdd, 0xb4, 0xc6, 0x1c, 0xa6, 0x25, 0x2e, 0xba, 0x78, 0x1d, 0x9e, 0x86, 0xc1, 0x57, 0xb9, 0x61, 0x35, 0xf6, 0x0e, 0x48, 0x03, 0xb5, 0x66, 0x70, 0x3e, 0x28, 0xdf, 0xce, 0x55, 0x87, 0xe9, 0x9b, 0x1e, 0x8e, 0x94, 0x69, 0xd9, 0x98, 0x11, 0xe1, 0xf8, 0xbb, 0x16, 0xb0, 0x54, 0x2d, 0x0f, 0x41, 0x99, 0x42, 0x68, 0xbf, 0xe6, 0x89, 0x0d, 0x8c, 0xa1, 0x19, 0x73, 0x64, 0x5d, 0x7e, 0x3d, 0xc4, 0xa7, 0x44, 0x17, 0x5f, 0x97, 0x13, 0xec, 0xcd, 0x0c, 0x0b, 0xdb, 0xde, 0x5e, 0xb8, 0x14, 0x46, 0xee, 0x90, 0x88, 0x22, 0x2a, 0x4f, 0xdc, 0x60, 0x81, 0xe4, 0x79, 0x91, 0x95, 0xac, 0x62, 0xc2, 0xd3, 0x24, 0x5c, 0x49, 0x06, 0x3a, 0x0a, 0xe0, 0x32, 0xae, 0x08, 0x65, 0x7a, 0xf4, 0xea, 0x6c, 0x56, 0x4e, 0xa9, 0x8d, 0xd5, 0x37, 0x6d, 0xe7, 0xc8, 0x2f, 0x84, 0x29, 0xe3, 0xd6, 0xb3, 0x52, 0x3b, 0x5a, 0xa0, 0x1b, 0x6e, 0x2c, 0x1a, 0x09, 0x83, 0x58, 0xcf, 0x4a, 0x4c, 0xbe, 0x39, 0x6a, 0xcb, 0xb1, 0x5b, 0x20, 0xfc, 0x00, 0xed, 0x53, 0xd1, 0x9f, 0xa8, 0x50, 0x3c, 0x02, 0x7f, 0x45, 0xf9, 0x33, 0x85, 0x43, 0x4d, 0xaa, 0xfb, 0xd0, 0xef, 0xf3, 0xd2, 0x10, 0xff, 0xda, 0x21, 0xbc, 0xb6, 0x38, 0xf5, 0x92, 0x9d, 0x40, 0x8f, 0x51, 0xa3, 0xab, 0x76, 0xfe, 0xd7, 0x67, 0x2b, 0x30, 0x01, 0x6f, 0xc5, 0xf2, 0x6b, 0x77, 0x7b, 0x63, 0x7c, 0x72, 0xc0, 0x9c, 0xa4, 0xa2, 0xaf, 0xad, 0xd4, 0x47, 0xf0, 0xfa, 0x59, 0xc9, 0x7d, 0xca, 0x82, 0x31, 0x15, 0x71, 0xd8, 0xe5, 0xf1, 0x34, 0xa5, 0xf7, 0xcc, 0x36, 0x3f, 0x93, 0x26, 0xb7, 0xfd, 0xb2, 0x75, 0xeb, 0x27, 0x80, 0xe2, 0x07, 0x12, 0x05, 0x9a, 0x18, 0x96, 0x23, 0xc3, 0x04, 0xc7 +}, +{ +0xc6, 0xb4, 0xa6, 0x1c, 0x2e, 0x25, 0x78, 0xba, 0x8a, 0x8b, 0xbd, 0x4b, 0x1f, 0x74, 0xdd, 0xe8, 0x0e, 0xf6, 0x03, 0x48, 0x66, 0xb5, 0x3e, 0x70, 0x9e, 0x1d, 0xc1, 0x86, 0xb9, 0x57, 0x35, 0x61, 0x94, 0x8e, 0xd9, 0x69, 0x11, 0x98, 0xf8, 0xe1, 0xdf, 0x28, 0x55, 0xce, 0xe9, 0x87, 0x1e, 0x9b, 0x68, 0x42, 0xe6, 0xbf, 0x0d, 0x89, 0xa1, 0x8c, 0x16, 0xbb, 0x54, 0xb0, 0x0f, 0x2d, 0x99, 0x41, 0x17, 0x44, 0x97, 0x5f, 0xec, 0x13, 0x0c, 0xcd, 0x73, 0x19, 0x5d, 0x64, 0x3d, 0x7e, 0xa7, 0xc4, 0x88, 0x90, 0x2a, 0x22, 0xdc, 0x4f, 0x81, 0x60, 0xdb, 0x0b, 0x5e, 0xde, 0x14, 0xb8, 0xee, 0x46, 0x5c, 0x24, 0x06, 0x49, 0x0a, 0x3a, 0x32, 0xe0, 0x79, 0xe4, 0x95, 0x91, 0x62, 0xac, 0xd3, 0xc2, 0xa9, 0x4e, 0xd5, 0x8d, 0x6d, 0x37, 0xc8, 0xe7, 0x08, 0xae, 0x7a, 0x65, 0xea, 0xf4, 0x56, 0x6c, 0xa0, 0x5a, 0x6e, 0x1b, 0x1a, 0x2c, 0x83, 0x09, 0x84, 0x2f, 0xe3, 0x29, 0xb3, 0xd6, 0x3b, 0x52, 0x5b, 0xb1, 0xfc, 0x20, 0xed, 0x00, 0xd1, 0x53, 0xcf, 0x58, 0x4c, 0x4a, 0x39, 0xbe, 0xcb, 0x6a, 0x85, 0x33, 0x4d, 0x43, 0xfb, 0xaa, 0xef, 0xd0, 0xa8, 0x9f, 0x3c, 0x50, 0x7f, 0x02, 0xf9, 0x45, 0xf5, 0x38, 0x9d, 0x92, 0x8f, 0x40, 0xa3, 0x51, 0xd2, 0xf3, 0xff, 0x10, 0x21, 0xda, 0xb6, 0xbc, 0xc5, 0x6f, 0x6b, 0xf2, 0x7b, 0x77, 0x7c, 0x63, 0x76, 0xab, 0xd7, 0xfe, 0x2b, 0x67, 0x01, 0x30, 0xf0, 0x47, 0x59, 0xfa, 0x7d, 0xc9, 0x82, 0xca, 0xc0, 0x72, 0xa4, 0x9c, 0xaf, 0xa2, 0xd4, 0xad, 0xcc, 0xf7, 0x3f, 0x36, 0x26, 0x93, 0xfd, 0xb7, 0x15, 0x31, 0xd8, 0x71, 0xf1, 0xe5, 0xa5, 0x34, 0x9a, 0x05, 0x96, 0x18, 0xc3, 0x23, 0xc7, 0x04, 0x75, 0xb2, 0x27, 0xeb, 0xe2, 0x80, 0x12, 0x07 +}, +{ +0xd3, 0xc2, 0x62, 0xac, 0x95, 0x91, 0x79, 0xe4, 0x32, 0xe0, 0x0a, 0x3a, 0x06, 0x49, 0x5c, 0x24, 0x56, 0x6c, 0xea, 0xf4, 0x7a, 0x65, 0x08, 0xae, 0xc8, 0xe7, 0x6d, 0x37, 0xd5, 0x8d, 0xa9, 0x4e, 0xa7, 0xc4, 0x3d, 0x7e, 0x5d, 0x64, 0x73, 0x19, 0x0c, 0xcd, 0xec, 0x13, 0x97, 0x5f, 0x17, 0x44, 0xee, 0x46, 0x14, 0xb8, 0x5e, 0xde, 0xdb, 0x0b, 0x81, 0x60, 0xdc, 0x4f, 0x2a, 0x22, 0x88, 0x90, 0x1e, 0x9b, 0xe9, 0x87, 0x55, 0xce, 0xdf, 0x28, 0xf8, 0xe1, 0x11, 0x98, 0xd9, 0x69, 0x94, 0x8e, 0x99, 0x41, 0x0f, 0x2d, 0x54, 0xb0, 0x16, 0xbb, 0xa1, 0x8c, 0x0d, 0x89, 0xe6, 0xbf, 0x68, 0x42, 0xdd, 0xe8, 0x1f, 0x74, 0xbd, 0x4b, 0x8a, 0x8b, 0x78, 0xba, 0x2e, 0x25, 0xa6, 0x1c, 0xc6, 0xb4, 0x35, 0x61, 0xb9, 0x57, 0xc1, 0x86, 0x9e, 0x1d, 0x3e, 0x70, 0x66, 0xb5, 0x03, 0x48, 0x0e, 0xf6, 0xa5, 0x34, 0xf1, 0xe5, 0xd8, 0x71, 0x15, 0x31, 0xfd, 0xb7, 0x26, 0x93, 0x3f, 0x36, 0xcc, 0xf7, 0x12, 0x07, 0xe2, 0x80, 0x27, 0xeb, 0x75, 0xb2, 0xc7, 0x04, 0xc3, 0x23, 0x96, 0x18, 0x9a, 0x05, 0x01, 0x30, 0x2b, 0x67, 0xd7, 0xfe, 0x76, 0xab, 0x7c, 0x63, 0x7b, 0x77, 0x6b, 0xf2, 0xc5, 0x6f, 0xd4, 0xad, 0xaf, 0xa2, 0xa4, 0x9c, 0xc0, 0x72, 0x82, 0xca, 0x7d, 0xc9, 0x59, 0xfa, 0xf0, 0x47, 0xf9, 0x45, 0x7f, 0x02, 0x3c, 0x50, 0xa8, 0x9f, 0xef, 0xd0, 0xfb, 0xaa, 0x4d, 0x43, 0x85, 0x33, 0xb6, 0xbc, 0x21, 0xda, 0xff, 0x10, 0xd2, 0xf3, 0xa3, 0x51, 0x8f, 0x40, 0x9d, 0x92, 0xf5, 0x38, 0x3b, 0x52, 0xb3, 0xd6, 0xe3, 0x29, 0x84, 0x2f, 0x83, 0x09, 0x1a, 0x2c, 0x6e, 0x1b, 0xa0, 0x5a, 0xcb, 0x6a, 0x39, 0xbe, 0x4c, 0x4a, 0xcf, 0x58, 0xd1, 0x53, 0xed, 0x00, 0xfc, 0x20, 0x5b, 0xb1 +}, +{ +0x92, 0x9d, 0x38, 0xf5, 0x51, 0xa3, 0x40, 0x8f, 0x10, 0xff, 0xf3, 0xd2, 0xbc, 0xb6, 0xda, 0x21, 0x43, 0x4d, 0x33, 0x85, 0xd0, 0xef, 0xaa, 0xfb, 0x50, 0x3c, 0x9f, 0xa8, 0x45, 0xf9, 0x02, 0x7f, 0x20, 0xfc, 0xb1, 0x5b, 0x53, 0xd1, 0x00, 0xed, 0x4a, 0x4c, 0x58, 0xcf, 0x6a, 0xcb, 0xbe, 0x39, 0x1b, 0x6e, 0x5a, 0xa0, 0x09, 0x83, 0x2c, 0x1a, 0x29, 0xe3, 0x2f, 0x84, 0x52, 0x3b, 0xd6, 0xb3, 0x18, 0x96, 0x05, 0x9a, 0x04, 0xc7, 0x23, 0xc3, 0xeb, 0x27, 0xb2, 0x75, 0x07, 0x12, 0x80, 0xe2, 0x36, 0x3f, 0xf7, 0xcc, 0xb7, 0xfd, 0x93, 0x26, 0x71, 0xd8, 0x31, 0x15, 0x34, 0xa5, 0xe5, 0xf1, 0xfa, 0x59, 0x47, 0xf0, 0xca, 0x82, 0xc9, 0x7d, 0x9c, 0xa4, 0x72, 0xc0, 0xad, 0xd4, 0xa2, 0xaf, 0xf2, 0x6b, 0x6f, 0xc5, 0x63, 0x7c, 0x77, 0x7b, 0xfe, 0xd7, 0xab, 0x76, 0x30, 0x01, 0x67, 0x2b, 0xbf, 0xe6, 0x42, 0x68, 0x8c, 0xa1, 0x89, 0x0d, 0xb0, 0x54, 0xbb, 0x16, 0x41, 0x99, 0x2d, 0x0f, 0x69, 0xd9, 0x8e, 0x94, 0xe1, 0xf8, 0x98, 0x11, 0xce, 0x55, 0x28, 0xdf, 0x9b, 0x1e, 0x87, 0xe9, 0x48, 0x03, 0xf6, 0x0e, 0x70, 0x3e, 0xb5, 0x66, 0x86, 0xc1, 0x1d, 0x9e, 0x61, 0x35, 0x57, 0xb9, 0x1c, 0xa6, 0xb4, 0xc6, 0xba, 0x78, 0x25, 0x2e, 0x4b, 0xbd, 0x8b, 0x8a, 0xe8, 0xdd, 0x74, 0x1f, 0x8d, 0xd5, 0x4e, 0xa9, 0xe7, 0xc8, 0x37, 0x6d, 0x65, 0x7a, 0xae, 0x08, 0x6c, 0x56, 0xf4, 0xea, 0x49, 0x06, 0x24, 0x5c, 0xe0, 0x32, 0x3a, 0x0a, 0x91, 0x95, 0xe4, 0x79, 0xc2, 0xd3, 0xac, 0x62, 0x22, 0x2a, 0x90, 0x88, 0x60, 0x81, 0x4f, 0xdc, 0xde, 0x5e, 0x0b, 0xdb, 0x46, 0xee, 0xb8, 0x14, 0x5f, 0x97, 0x44, 0x17, 0xcd, 0x0c, 0x13, 0xec, 0x64, 0x5d, 0x19, 0x73, 0xc4, 0xa7, 0x7e, 0x3d +}, +{ +0x00, 0xed, 0x53, 0xd1, 0xb1, 0x5b, 0x20, 0xfc, 0xbe, 0x39, 0x6a, 0xcb, 0x58, 0xcf, 0x4a, 0x4c, 0x2c, 0x1a, 0x09, 0x83, 0x5a, 0xa0, 0x1b, 0x6e, 0xd6, 0xb3, 0x52, 0x3b, 0x2f, 0x84, 0x29, 0xe3, 0x40, 0x8f, 0x51, 0xa3, 0x38, 0xf5, 0x92, 0x9d, 0xda, 0x21, 0xbc, 0xb6, 0xf3, 0xd2, 0x10, 0xff, 0xaa, 0xfb, 0xd0, 0xef, 0x33, 0x85, 0x43, 0x4d, 0x02, 0x7f, 0x45, 0xf9, 0x9f, 0xa8, 0x50, 0x3c, 0xc9, 0x7d, 0xca, 0x82, 0x47, 0xf0, 0xfa, 0x59, 0xa2, 0xaf, 0xad, 0xd4, 0x72, 0xc0, 0x9c, 0xa4, 0x77, 0x7b, 0x63, 0x7c, 0x6f, 0xc5, 0xf2, 0x6b, 0x67, 0x2b, 0x30, 0x01, 0xab, 0x76, 0xfe, 0xd7, 0x23, 0xc3, 0x04, 0xc7, 0x05, 0x9a, 0x18, 0x96, 0x80, 0xe2, 0x07, 0x12, 0xb2, 0x75, 0xeb, 0x27, 0x93, 0x26, 0xb7, 0xfd, 0xf7, 0xcc, 0x36, 0x3f, 0xe5, 0xf1, 0x34, 0xa5, 0x31, 0x15, 0x71, 0xd8, 0xb5, 0x66, 0x70, 0x3e, 0xf6, 0x0e, 0x48, 0x03, 0x57, 0xb9, 0x61, 0x35, 0x1d, 0x9e, 0x86, 0xc1, 0x25, 0x2e, 0xba, 0x78, 0xb4, 0xc6, 0x1c, 0xa6, 0x74, 0x1f, 0xe8, 0xdd, 0x8b, 0x8a, 0x4b, 0xbd, 0x89, 0x0d, 0x8c, 0xa1, 0x42, 0x68, 0xbf, 0xe6, 0x2d, 0x0f, 0x41, 0x99, 0xbb, 0x16, 0xb0, 0x54, 0x98, 0x11, 0xe1, 0xf8, 0x8e, 0x94, 0x69, 0xd9, 0x87, 0xe9, 0x9b, 0x1e, 0x28, 0xdf, 0xce, 0x55, 0x4f, 0xdc, 0x60, 0x81, 0x90, 0x88, 0x22, 0x2a, 0xb8, 0x14, 0x46, 0xee, 0x0b, 0xdb, 0xde, 0x5e, 0x13, 0xec, 0xcd, 0x0c, 0x44, 0x17, 0x5f, 0x97, 0x7e, 0x3d, 0xc4, 0xa7, 0x19, 0x73, 0x64, 0x5d, 0x37, 0x6d, 0xe7, 0xc8, 0x4e, 0xa9, 0x8d, 0xd5, 0xf4, 0xea, 0x6c, 0x56, 0xae, 0x08, 0x65, 0x7a, 0x3a, 0x0a, 0xe0, 0x32, 0x24, 0x5c, 0x49, 0x06, 0xac, 0x62, 0xc2, 0xd3, 0xe4, 0x79, 0x91, 0x95 +}, +{ +0x2a, 0x22, 0x88, 0x90, 0x81, 0x60, 0xdc, 0x4f, 0x5e, 0xde, 0xdb, 0x0b, 0xee, 0x46, 0x14, 0xb8, 0x97, 0x5f, 0x17, 0x44, 0x0c, 0xcd, 0xec, 0x13, 0x5d, 0x64, 0x73, 0x19, 0xa7, 0xc4, 0x3d, 0x7e, 0xd5, 0x8d, 0xa9, 0x4e, 0xc8, 0xe7, 0x6d, 0x37, 0x7a, 0x65, 0x08, 0xae, 0x56, 0x6c, 0xea, 0xf4, 0x06, 0x49, 0x5c, 0x24, 0x32, 0xe0, 0x0a, 0x3a, 0x95, 0x91, 0x79, 0xe4, 0xd3, 0xc2, 0x62, 0xac, 0x03, 0x48, 0x0e, 0xf6, 0x3e, 0x70, 0x66, 0xb5, 0xc1, 0x86, 0x9e, 0x1d, 0x35, 0x61, 0xb9, 0x57, 0xa6, 0x1c, 0xc6, 0xb4, 0x78, 0xba, 0x2e, 0x25, 0xbd, 0x4b, 0x8a, 0x8b, 0xdd, 0xe8, 0x1f, 0x74, 0xe6, 0xbf, 0x68, 0x42, 0xa1, 0x8c, 0x0d, 0x89, 0x54, 0xb0, 0x16, 0xbb, 0x99, 0x41, 0x0f, 0x2d, 0xd9, 0x69, 0x94, 0x8e, 0xf8, 0xe1, 0x11, 0x98, 0x55, 0xce, 0xdf, 0x28, 0x1e, 0x9b, 0xe9, 0x87, 0x59, 0xfa, 0xf0, 0x47, 0x82, 0xca, 0x7d, 0xc9, 0xa4, 0x9c, 0xc0, 0x72, 0xd4, 0xad, 0xaf, 0xa2, 0x6b, 0xf2, 0xc5, 0x6f, 0x7c, 0x63, 0x7b, 0x77, 0xd7, 0xfe, 0x76, 0xab, 0x01, 0x30, 0x2b, 0x67, 0x96, 0x18, 0x9a, 0x05, 0xc7, 0x04, 0xc3, 0x23, 0x27, 0xeb, 0x75, 0xb2, 0x12, 0x07, 0xe2, 0x80, 0x3f, 0x36, 0xcc, 0xf7, 0xfd, 0xb7, 0x26, 0x93, 0xd8, 0x71, 0x15, 0x31, 0xa5, 0x34, 0xf1, 0xe5, 0xfc, 0x20, 0x5b, 0xb1, 0xd1, 0x53, 0xed, 0x00, 0x4c, 0x4a, 0xcf, 0x58, 0xcb, 0x6a, 0x39, 0xbe, 0x6e, 0x1b, 0xa0, 0x5a, 0x83, 0x09, 0x1a, 0x2c, 0xe3, 0x29, 0x84, 0x2f, 0x3b, 0x52, 0xb3, 0xd6, 0x9d, 0x92, 0xf5, 0x38, 0xa3, 0x51, 0x8f, 0x40, 0xff, 0x10, 0xd2, 0xf3, 0xb6, 0xbc, 0x21, 0xda, 0x4d, 0x43, 0x85, 0x33, 0xef, 0xd0, 0xfb, 0xaa, 0x3c, 0x50, 0xa8, 0x9f, 0xf9, 0x45, 0x7f, 0x02 +}, +{ +0x23, 0xc3, 0x04, 0xc7, 0x05, 0x9a, 0x18, 0x96, 0x80, 0xe2, 0x07, 0x12, 0xb2, 0x75, 0xeb, 0x27, 0x93, 0x26, 0xb7, 0xfd, 0xf7, 0xcc, 0x36, 0x3f, 0xe5, 0xf1, 0x34, 0xa5, 0x31, 0x15, 0x71, 0xd8, 0xc9, 0x7d, 0xca, 0x82, 0x47, 0xf0, 0xfa, 0x59, 0xa2, 0xaf, 0xad, 0xd4, 0x72, 0xc0, 0x9c, 0xa4, 0x77, 0x7b, 0x63, 0x7c, 0x6f, 0xc5, 0xf2, 0x6b, 0x67, 0x2b, 0x30, 0x01, 0xab, 0x76, 0xfe, 0xd7, 0x40, 0x8f, 0x51, 0xa3, 0x38, 0xf5, 0x92, 0x9d, 0xda, 0x21, 0xbc, 0xb6, 0xf3, 0xd2, 0x10, 0xff, 0xaa, 0xfb, 0xd0, 0xef, 0x33, 0x85, 0x43, 0x4d, 0x02, 0x7f, 0x45, 0xf9, 0x9f, 0xa8, 0x50, 0x3c, 0x00, 0xed, 0x53, 0xd1, 0xb1, 0x5b, 0x20, 0xfc, 0xbe, 0x39, 0x6a, 0xcb, 0x58, 0xcf, 0x4a, 0x4c, 0x2c, 0x1a, 0x09, 0x83, 0x5a, 0xa0, 0x1b, 0x6e, 0xd6, 0xb3, 0x52, 0x3b, 0x2f, 0x84, 0x29, 0xe3, 0x37, 0x6d, 0xe7, 0xc8, 0x4e, 0xa9, 0x8d, 0xd5, 0xf4, 0xea, 0x6c, 0x56, 0xae, 0x08, 0x65, 0x7a, 0x3a, 0x0a, 0xe0, 0x32, 0x24, 0x5c, 0x49, 0x06, 0xac, 0x62, 0xc2, 0xd3, 0xe4, 0x79, 0x91, 0x95, 0x4f, 0xdc, 0x60, 0x81, 0x90, 0x88, 0x22, 0x2a, 0xb8, 0x14, 0x46, 0xee, 0x0b, 0xdb, 0xde, 0x5e, 0x13, 0xec, 0xcd, 0x0c, 0x44, 0x17, 0x5f, 0x97, 0x7e, 0x3d, 0xc4, 0xa7, 0x19, 0x73, 0x64, 0x5d, 0x89, 0x0d, 0x8c, 0xa1, 0x42, 0x68, 0xbf, 0xe6, 0x2d, 0x0f, 0x41, 0x99, 0xbb, 0x16, 0xb0, 0x54, 0x98, 0x11, 0xe1, 0xf8, 0x8e, 0x94, 0x69, 0xd9, 0x87, 0xe9, 0x9b, 0x1e, 0x28, 0xdf, 0xce, 0x55, 0xb5, 0x66, 0x70, 0x3e, 0xf6, 0x0e, 0x48, 0x03, 0x57, 0xb9, 0x61, 0x35, 0x1d, 0x9e, 0x86, 0xc1, 0x25, 0x2e, 0xba, 0x78, 0xb4, 0xc6, 0x1c, 0xa6, 0x74, 0x1f, 0xe8, 0xdd, 0x8b, 0x8a, 0x4b, 0xbd +}, +{ +0xb0, 0x54, 0xbb, 0x16, 0x41, 0x99, 0x2d, 0x0f, 0xbf, 0xe6, 0x42, 0x68, 0x8c, 0xa1, 0x89, 0x0d, 0xce, 0x55, 0x28, 0xdf, 0x9b, 0x1e, 0x87, 0xe9, 0x69, 0xd9, 0x8e, 0x94, 0xe1, 0xf8, 0x98, 0x11, 0x86, 0xc1, 0x1d, 0x9e, 0x61, 0x35, 0x57, 0xb9, 0x48, 0x03, 0xf6, 0x0e, 0x70, 0x3e, 0xb5, 0x66, 0x4b, 0xbd, 0x8b, 0x8a, 0xe8, 0xdd, 0x74, 0x1f, 0x1c, 0xa6, 0xb4, 0xc6, 0xba, 0x78, 0x25, 0x2e, 0x65, 0x7a, 0xae, 0x08, 0x6c, 0x56, 0xf4, 0xea, 0x8d, 0xd5, 0x4e, 0xa9, 0xe7, 0xc8, 0x37, 0x6d, 0x91, 0x95, 0xe4, 0x79, 0xc2, 0xd3, 0xac, 0x62, 0x49, 0x06, 0x24, 0x5c, 0xe0, 0x32, 0x3a, 0x0a, 0xde, 0x5e, 0x0b, 0xdb, 0x46, 0xee, 0xb8, 0x14, 0x22, 0x2a, 0x90, 0x88, 0x60, 0x81, 0x4f, 0xdc, 0x64, 0x5d, 0x19, 0x73, 0xc4, 0xa7, 0x7e, 0x3d, 0x5f, 0x97, 0x44, 0x17, 0xcd, 0x0c, 0x13, 0xec, 0x10, 0xff, 0xf3, 0xd2, 0xbc, 0xb6, 0xda, 0x21, 0x92, 0x9d, 0x38, 0xf5, 0x51, 0xa3, 0x40, 0x8f, 0x50, 0x3c, 0x9f, 0xa8, 0x45, 0xf9, 0x02, 0x7f, 0x43, 0x4d, 0x33, 0x85, 0xd0, 0xef, 0xaa, 0xfb, 0x4a, 0x4c, 0x58, 0xcf, 0x6a, 0xcb, 0xbe, 0x39, 0x20, 0xfc, 0xb1, 0x5b, 0x53, 0xd1, 0x00, 0xed, 0x29, 0xe3, 0x2f, 0x84, 0x52, 0x3b, 0xd6, 0xb3, 0x1b, 0x6e, 0x5a, 0xa0, 0x09, 0x83, 0x2c, 0x1a, 0xeb, 0x27, 0xb2, 0x75, 0x07, 0x12, 0x80, 0xe2, 0x18, 0x96, 0x05, 0x9a, 0x04, 0xc7, 0x23, 0xc3, 0x71, 0xd8, 0x31, 0x15, 0x34, 0xa5, 0xe5, 0xf1, 0x36, 0x3f, 0xf7, 0xcc, 0xb7, 0xfd, 0x93, 0x26, 0x9c, 0xa4, 0x72, 0xc0, 0xad, 0xd4, 0xa2, 0xaf, 0xfa, 0x59, 0x47, 0xf0, 0xca, 0x82, 0xc9, 0x7d, 0xfe, 0xd7, 0xab, 0x76, 0x30, 0x01, 0x67, 0x2b, 0xf2, 0x6b, 0x6f, 0xc5, 0x63, 0x7c, 0x77, 0x7b +}, +{ +0x15, 0x31, 0xd8, 0x71, 0xf1, 0xe5, 0xa5, 0x34, 0xcc, 0xf7, 0x3f, 0x36, 0x26, 0x93, 0xfd, 0xb7, 0x75, 0xb2, 0x27, 0xeb, 0xe2, 0x80, 0x12, 0x07, 0x9a, 0x05, 0x96, 0x18, 0xc3, 0x23, 0xc7, 0x04, 0x76, 0xab, 0xd7, 0xfe, 0x2b, 0x67, 0x01, 0x30, 0xc5, 0x6f, 0x6b, 0xf2, 0x7b, 0x77, 0x7c, 0x63, 0xc0, 0x72, 0xa4, 0x9c, 0xaf, 0xa2, 0xd4, 0xad, 0xf0, 0x47, 0x59, 0xfa, 0x7d, 0xc9, 0x82, 0xca, 0xa8, 0x9f, 0x3c, 0x50, 0x7f, 0x02, 0xf9, 0x45, 0x85, 0x33, 0x4d, 0x43, 0xfb, 0xaa, 0xef, 0xd0, 0xd2, 0xf3, 0xff, 0x10, 0x21, 0xda, 0xb6, 0xbc, 0xf5, 0x38, 0x9d, 0x92, 0x8f, 0x40, 0xa3, 0x51, 0x84, 0x2f, 0xe3, 0x29, 0xb3, 0xd6, 0x3b, 0x52, 0xa0, 0x5a, 0x6e, 0x1b, 0x1a, 0x2c, 0x83, 0x09, 0xcf, 0x58, 0x4c, 0x4a, 0x39, 0xbe, 0xcb, 0x6a, 0x5b, 0xb1, 0xfc, 0x20, 0xed, 0x00, 0xd1, 0x53, 0x79, 0xe4, 0x95, 0x91, 0x62, 0xac, 0xd3, 0xc2, 0x5c, 0x24, 0x06, 0x49, 0x0a, 0x3a, 0x32, 0xe0, 0x08, 0xae, 0x7a, 0x65, 0xea, 0xf4, 0x56, 0x6c, 0xa9, 0x4e, 0xd5, 0x8d, 0x6d, 0x37, 0xc8, 0xe7, 0x73, 0x19, 0x5d, 0x64, 0x3d, 0x7e, 0xa7, 0xc4, 0x17, 0x44, 0x97, 0x5f, 0xec, 0x13, 0x0c, 0xcd, 0xdb, 0x0b, 0x5e, 0xde, 0x14, 0xb8, 0xee, 0x46, 0x88, 0x90, 0x2a, 0x22, 0xdc, 0x4f, 0x81, 0x60, 0xdf, 0x28, 0x55, 0xce, 0xe9, 0x87, 0x1e, 0x9b, 0x94, 0x8e, 0xd9, 0x69, 0x11, 0x98, 0xf8, 0xe1, 0x16, 0xbb, 0x54, 0xb0, 0x0f, 0x2d, 0x99, 0x41, 0x68, 0x42, 0xe6, 0xbf, 0x0d, 0x89, 0xa1, 0x8c, 0x8a, 0x8b, 0xbd, 0x4b, 0x1f, 0x74, 0xdd, 0xe8, 0xc6, 0xb4, 0xa6, 0x1c, 0x2e, 0x25, 0x78, 0xba, 0x9e, 0x1d, 0xc1, 0x86, 0xb9, 0x57, 0x35, 0x61, 0x0e, 0xf6, 0x03, 0x48, 0x66, 0xb5, 0x3e, 0x70 +}, +{ +0x26, 0x93, 0xfd, 0xb7, 0xcc, 0xf7, 0x3f, 0x36, 0xf1, 0xe5, 0xa5, 0x34, 0x15, 0x31, 0xd8, 0x71, 0xc3, 0x23, 0xc7, 0x04, 0x9a, 0x05, 0x96, 0x18, 0xe2, 0x80, 0x12, 0x07, 0x75, 0xb2, 0x27, 0xeb, 0x7b, 0x77, 0x7c, 0x63, 0xc5, 0x6f, 0x6b, 0xf2, 0x2b, 0x67, 0x01, 0x30, 0x76, 0xab, 0xd7, 0xfe, 0x7d, 0xc9, 0x82, 0xca, 0xf0, 0x47, 0x59, 0xfa, 0xaf, 0xa2, 0xd4, 0xad, 0xc0, 0x72, 0xa4, 0x9c, 0xfb, 0xaa, 0xef, 0xd0, 0x85, 0x33, 0x4d, 0x43, 0x7f, 0x02, 0xf9, 0x45, 0xa8, 0x9f, 0x3c, 0x50, 0x8f, 0x40, 0xa3, 0x51, 0xf5, 0x38, 0x9d, 0x92, 0x21, 0xda, 0xb6, 0xbc, 0xd2, 0xf3, 0xff, 0x10, 0x1a, 0x2c, 0x83, 0x09, 0xa0, 0x5a, 0x6e, 0x1b, 0xb3, 0xd6, 0x3b, 0x52, 0x84, 0x2f, 0xe3, 0x29, 0xed, 0x00, 0xd1, 0x53, 0x5b, 0xb1, 0xfc, 0x20, 0x39, 0xbe, 0xcb, 0x6a, 0xcf, 0x58, 0x4c, 0x4a, 0x0a, 0x3a, 0x32, 0xe0, 0x5c, 0x24, 0x06, 0x49, 0x62, 0xac, 0xd3, 0xc2, 0x79, 0xe4, 0x95, 0x91, 0x6d, 0x37, 0xc8, 0xe7, 0xa9, 0x4e, 0xd5, 0x8d, 0xea, 0xf4, 0x56, 0x6c, 0x08, 0xae, 0x7a, 0x65, 0xec, 0x13, 0x0c, 0xcd, 0x17, 0x44, 0x97, 0x5f, 0x3d, 0x7e, 0xa7, 0xc4, 0x73, 0x19, 0x5d, 0x64, 0xdc, 0x4f, 0x81, 0x60, 0x88, 0x90, 0x2a, 0x22, 0x14, 0xb8, 0xee, 0x46, 0xdb, 0x0b, 0x5e, 0xde, 0x11, 0x98, 0xf8, 0xe1, 0x94, 0x8e, 0xd9, 0x69, 0xe9, 0x87, 0x1e, 0x9b, 0xdf, 0x28, 0x55, 0xce, 0x0d, 0x89, 0xa1, 0x8c, 0x68, 0x42, 0xe6, 0xbf, 0x0f, 0x2d, 0x99, 0x41, 0x16, 0xbb, 0x54, 0xb0, 0x2e, 0x25, 0x78, 0xba, 0xc6, 0xb4, 0xa6, 0x1c, 0x1f, 0x74, 0xdd, 0xe8, 0x8a, 0x8b, 0xbd, 0x4b, 0x66, 0xb5, 0x3e, 0x70, 0x0e, 0xf6, 0x03, 0x48, 0xb9, 0x57, 0x35, 0x61, 0x9e, 0x1d, 0xc1, 0x86 +} +}, +{ +{ +0x22, 0x2a, 0x90, 0x88, 0x60, 0x81, 0x4f, 0xdc, 0xde, 0x5e, 0x0b, 0xdb, 0x46, 0xee, 0xb8, 0x14, 0x5f, 0x97, 0x44, 0x17, 0xcd, 0x0c, 0x13, 0xec, 0x64, 0x5d, 0x19, 0x73, 0xc4, 0xa7, 0x7e, 0x3d, 0x8d, 0xd5, 0x4e, 0xa9, 0xe7, 0xc8, 0x37, 0x6d, 0x65, 0x7a, 0xae, 0x08, 0x6c, 0x56, 0xf4, 0xea, 0x49, 0x06, 0x24, 0x5c, 0xe0, 0x32, 0x3a, 0x0a, 0x91, 0x95, 0xe4, 0x79, 0xc2, 0xd3, 0xac, 0x62, 0x48, 0x03, 0xf6, 0x0e, 0x70, 0x3e, 0xb5, 0x66, 0x86, 0xc1, 0x1d, 0x9e, 0x61, 0x35, 0x57, 0xb9, 0x1c, 0xa6, 0xb4, 0xc6, 0xba, 0x78, 0x25, 0x2e, 0x4b, 0xbd, 0x8b, 0x8a, 0xe8, 0xdd, 0x74, 0x1f, 0xbf, 0xe6, 0x42, 0x68, 0x8c, 0xa1, 0x89, 0x0d, 0xb0, 0x54, 0xbb, 0x16, 0x41, 0x99, 0x2d, 0x0f, 0x69, 0xd9, 0x8e, 0x94, 0xe1, 0xf8, 0x98, 0x11, 0xce, 0x55, 0x28, 0xdf, 0x9b, 0x1e, 0x87, 0xe9, 0xfa, 0x59, 0x47, 0xf0, 0xca, 0x82, 0xc9, 0x7d, 0x9c, 0xa4, 0x72, 0xc0, 0xad, 0xd4, 0xa2, 0xaf, 0xf2, 0x6b, 0x6f, 0xc5, 0x63, 0x7c, 0x77, 0x7b, 0xfe, 0xd7, 0xab, 0x76, 0x30, 0x01, 0x67, 0x2b, 0x18, 0x96, 0x05, 0x9a, 0x04, 0xc7, 0x23, 0xc3, 0xeb, 0x27, 0xb2, 0x75, 0x07, 0x12, 0x80, 0xe2, 0x36, 0x3f, 0xf7, 0xcc, 0xb7, 0xfd, 0x93, 0x26, 0x71, 0xd8, 0x31, 0x15, 0x34, 0xa5, 0xe5, 0xf1, 0x20, 0xfc, 0xb1, 0x5b, 0x53, 0xd1, 0x00, 0xed, 0x4a, 0x4c, 0x58, 0xcf, 0x6a, 0xcb, 0xbe, 0x39, 0x1b, 0x6e, 0x5a, 0xa0, 0x09, 0x83, 0x2c, 0x1a, 0x29, 0xe3, 0x2f, 0x84, 0x52, 0x3b, 0xd6, 0xb3, 0x92, 0x9d, 0x38, 0xf5, 0x51, 0xa3, 0x40, 0x8f, 0x10, 0xff, 0xf3, 0xd2, 0xbc, 0xb6, 0xda, 0x21, 0x43, 0x4d, 0x33, 0x85, 0xd0, 0xef, 0xaa, 0xfb, 0x50, 0x3c, 0x9f, 0xa8, 0x45, 0xf9, 0x02, 0x7f +}, +{ +0x2c, 0x1a, 0x09, 0x83, 0x5a, 0xa0, 0x1b, 0x6e, 0xd6, 0xb3, 0x52, 0x3b, 0x2f, 0x84, 0x29, 0xe3, 0x00, 0xed, 0x53, 0xd1, 0xb1, 0x5b, 0x20, 0xfc, 0xbe, 0x39, 0x6a, 0xcb, 0x58, 0xcf, 0x4a, 0x4c, 0xaa, 0xfb, 0xd0, 0xef, 0x33, 0x85, 0x43, 0x4d, 0x02, 0x7f, 0x45, 0xf9, 0x9f, 0xa8, 0x50, 0x3c, 0x40, 0x8f, 0x51, 0xa3, 0x38, 0xf5, 0x92, 0x9d, 0xda, 0x21, 0xbc, 0xb6, 0xf3, 0xd2, 0x10, 0xff, 0x77, 0x7b, 0x63, 0x7c, 0x6f, 0xc5, 0xf2, 0x6b, 0x67, 0x2b, 0x30, 0x01, 0xab, 0x76, 0xfe, 0xd7, 0xc9, 0x7d, 0xca, 0x82, 0x47, 0xf0, 0xfa, 0x59, 0xa2, 0xaf, 0xad, 0xd4, 0x72, 0xc0, 0x9c, 0xa4, 0x93, 0x26, 0xb7, 0xfd, 0xf7, 0xcc, 0x36, 0x3f, 0xe5, 0xf1, 0x34, 0xa5, 0x31, 0x15, 0x71, 0xd8, 0x23, 0xc3, 0x04, 0xc7, 0x05, 0x9a, 0x18, 0x96, 0x80, 0xe2, 0x07, 0x12, 0xb2, 0x75, 0xeb, 0x27, 0x25, 0x2e, 0xba, 0x78, 0xb4, 0xc6, 0x1c, 0xa6, 0x74, 0x1f, 0xe8, 0xdd, 0x8b, 0x8a, 0x4b, 0xbd, 0xb5, 0x66, 0x70, 0x3e, 0xf6, 0x0e, 0x48, 0x03, 0x57, 0xb9, 0x61, 0x35, 0x1d, 0x9e, 0x86, 0xc1, 0x98, 0x11, 0xe1, 0xf8, 0x8e, 0x94, 0x69, 0xd9, 0x87, 0xe9, 0x9b, 0x1e, 0x28, 0xdf, 0xce, 0x55, 0x89, 0x0d, 0x8c, 0xa1, 0x42, 0x68, 0xbf, 0xe6, 0x2d, 0x0f, 0x41, 0x99, 0xbb, 0x16, 0xb0, 0x54, 0x13, 0xec, 0xcd, 0x0c, 0x44, 0x17, 0x5f, 0x97, 0x7e, 0x3d, 0xc4, 0xa7, 0x19, 0x73, 0x64, 0x5d, 0x4f, 0xdc, 0x60, 0x81, 0x90, 0x88, 0x22, 0x2a, 0xb8, 0x14, 0x46, 0xee, 0x0b, 0xdb, 0xde, 0x5e, 0x3a, 0x0a, 0xe0, 0x32, 0x24, 0x5c, 0x49, 0x06, 0xac, 0x62, 0xc2, 0xd3, 0xe4, 0x79, 0x91, 0x95, 0x37, 0x6d, 0xe7, 0xc8, 0x4e, 0xa9, 0x8d, 0xd5, 0xf4, 0xea, 0x6c, 0x56, 0xae, 0x08, 0x65, 0x7a +}, +{ +0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8 +}, +{ +0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf +}, +{ +0xaa, 0xfb, 0xd0, 0xef, 0x33, 0x85, 0x43, 0x4d, 0x02, 0x7f, 0x45, 0xf9, 0x9f, 0xa8, 0x50, 0x3c, 0x40, 0x8f, 0x51, 0xa3, 0x38, 0xf5, 0x92, 0x9d, 0xda, 0x21, 0xbc, 0xb6, 0xf3, 0xd2, 0x10, 0xff, 0x2c, 0x1a, 0x09, 0x83, 0x5a, 0xa0, 0x1b, 0x6e, 0xd6, 0xb3, 0x52, 0x3b, 0x2f, 0x84, 0x29, 0xe3, 0x00, 0xed, 0x53, 0xd1, 0xb1, 0x5b, 0x20, 0xfc, 0xbe, 0x39, 0x6a, 0xcb, 0x58, 0xcf, 0x4a, 0x4c, 0x93, 0x26, 0xb7, 0xfd, 0xf7, 0xcc, 0x36, 0x3f, 0xe5, 0xf1, 0x34, 0xa5, 0x31, 0x15, 0x71, 0xd8, 0x23, 0xc3, 0x04, 0xc7, 0x05, 0x9a, 0x18, 0x96, 0x80, 0xe2, 0x07, 0x12, 0xb2, 0x75, 0xeb, 0x27, 0x77, 0x7b, 0x63, 0x7c, 0x6f, 0xc5, 0xf2, 0x6b, 0x67, 0x2b, 0x30, 0x01, 0xab, 0x76, 0xfe, 0xd7, 0xc9, 0x7d, 0xca, 0x82, 0x47, 0xf0, 0xfa, 0x59, 0xa2, 0xaf, 0xad, 0xd4, 0x72, 0xc0, 0x9c, 0xa4, 0x98, 0x11, 0xe1, 0xf8, 0x8e, 0x94, 0x69, 0xd9, 0x87, 0xe9, 0x9b, 0x1e, 0x28, 0xdf, 0xce, 0x55, 0x89, 0x0d, 0x8c, 0xa1, 0x42, 0x68, 0xbf, 0xe6, 0x2d, 0x0f, 0x41, 0x99, 0xbb, 0x16, 0xb0, 0x54, 0x25, 0x2e, 0xba, 0x78, 0xb4, 0xc6, 0x1c, 0xa6, 0x74, 0x1f, 0xe8, 0xdd, 0x8b, 0x8a, 0x4b, 0xbd, 0xb5, 0x66, 0x70, 0x3e, 0xf6, 0x0e, 0x48, 0x03, 0x57, 0xb9, 0x61, 0x35, 0x1d, 0x9e, 0x86, 0xc1, 0x3a, 0x0a, 0xe0, 0x32, 0x24, 0x5c, 0x49, 0x06, 0xac, 0x62, 0xc2, 0xd3, 0xe4, 0x79, 0x91, 0x95, 0x37, 0x6d, 0xe7, 0xc8, 0x4e, 0xa9, 0x8d, 0xd5, 0xf4, 0xea, 0x6c, 0x56, 0xae, 0x08, 0x65, 0x7a, 0x13, 0xec, 0xcd, 0x0c, 0x44, 0x17, 0x5f, 0x97, 0x7e, 0x3d, 0xc4, 0xa7, 0x19, 0x73, 0x64, 0x5d, 0x4f, 0xdc, 0x60, 0x81, 0x90, 0x88, 0x22, 0x2a, 0xb8, 0x14, 0x46, 0xee, 0x0b, 0xdb, 0xde, 0x5e +}, +{ +0x7e, 0x3d, 0xc4, 0xa7, 0x19, 0x73, 0x64, 0x5d, 0x13, 0xec, 0xcd, 0x0c, 0x44, 0x17, 0x5f, 0x97, 0xb8, 0x14, 0x46, 0xee, 0x0b, 0xdb, 0xde, 0x5e, 0x4f, 0xdc, 0x60, 0x81, 0x90, 0x88, 0x22, 0x2a, 0xac, 0x62, 0xc2, 0xd3, 0xe4, 0x79, 0x91, 0x95, 0x3a, 0x0a, 0xe0, 0x32, 0x24, 0x5c, 0x49, 0x06, 0xf4, 0xea, 0x6c, 0x56, 0xae, 0x08, 0x65, 0x7a, 0x37, 0x6d, 0xe7, 0xc8, 0x4e, 0xa9, 0x8d, 0xd5, 0x74, 0x1f, 0xe8, 0xdd, 0x8b, 0x8a, 0x4b, 0xbd, 0x25, 0x2e, 0xba, 0x78, 0xb4, 0xc6, 0x1c, 0xa6, 0x57, 0xb9, 0x61, 0x35, 0x1d, 0x9e, 0x86, 0xc1, 0xb5, 0x66, 0x70, 0x3e, 0xf6, 0x0e, 0x48, 0x03, 0x87, 0xe9, 0x9b, 0x1e, 0x28, 0xdf, 0xce, 0x55, 0x98, 0x11, 0xe1, 0xf8, 0x8e, 0x94, 0x69, 0xd9, 0x2d, 0x0f, 0x41, 0x99, 0xbb, 0x16, 0xb0, 0x54, 0x89, 0x0d, 0x8c, 0xa1, 0x42, 0x68, 0xbf, 0xe6, 0x67, 0x2b, 0x30, 0x01, 0xab, 0x76, 0xfe, 0xd7, 0x77, 0x7b, 0x63, 0x7c, 0x6f, 0xc5, 0xf2, 0x6b, 0xa2, 0xaf, 0xad, 0xd4, 0x72, 0xc0, 0x9c, 0xa4, 0xc9, 0x7d, 0xca, 0x82, 0x47, 0xf0, 0xfa, 0x59, 0xe5, 0xf1, 0x34, 0xa5, 0x31, 0x15, 0x71, 0xd8, 0x93, 0x26, 0xb7, 0xfd, 0xf7, 0xcc, 0x36, 0x3f, 0x80, 0xe2, 0x07, 0x12, 0xb2, 0x75, 0xeb, 0x27, 0x23, 0xc3, 0x04, 0xc7, 0x05, 0x9a, 0x18, 0x96, 0xd6, 0xb3, 0x52, 0x3b, 0x2f, 0x84, 0x29, 0xe3, 0x2c, 0x1a, 0x09, 0x83, 0x5a, 0xa0, 0x1b, 0x6e, 0xbe, 0x39, 0x6a, 0xcb, 0x58, 0xcf, 0x4a, 0x4c, 0x00, 0xed, 0x53, 0xd1, 0xb1, 0x5b, 0x20, 0xfc, 0x02, 0x7f, 0x45, 0xf9, 0x9f, 0xa8, 0x50, 0x3c, 0xaa, 0xfb, 0xd0, 0xef, 0x33, 0x85, 0x43, 0x4d, 0xda, 0x21, 0xbc, 0xb6, 0xf3, 0xd2, 0x10, 0xff, 0x40, 0x8f, 0x51, 0xa3, 0x38, 0xf5, 0x92, 0x9d +}, +{ +0x58, 0xcf, 0x4a, 0x4c, 0xbe, 0x39, 0x6a, 0xcb, 0xb1, 0x5b, 0x20, 0xfc, 0x00, 0xed, 0x53, 0xd1, 0x2f, 0x84, 0x29, 0xe3, 0xd6, 0xb3, 0x52, 0x3b, 0x5a, 0xa0, 0x1b, 0x6e, 0x2c, 0x1a, 0x09, 0x83, 0xf3, 0xd2, 0x10, 0xff, 0xda, 0x21, 0xbc, 0xb6, 0x38, 0xf5, 0x92, 0x9d, 0x40, 0x8f, 0x51, 0xa3, 0x9f, 0xa8, 0x50, 0x3c, 0x02, 0x7f, 0x45, 0xf9, 0x33, 0x85, 0x43, 0x4d, 0xaa, 0xfb, 0xd0, 0xef, 0x72, 0xc0, 0x9c, 0xa4, 0xa2, 0xaf, 0xad, 0xd4, 0x47, 0xf0, 0xfa, 0x59, 0xc9, 0x7d, 0xca, 0x82, 0xab, 0x76, 0xfe, 0xd7, 0x67, 0x2b, 0x30, 0x01, 0x6f, 0xc5, 0xf2, 0x6b, 0x77, 0x7b, 0x63, 0x7c, 0xb2, 0x75, 0xeb, 0x27, 0x80, 0xe2, 0x07, 0x12, 0x05, 0x9a, 0x18, 0x96, 0x23, 0xc3, 0x04, 0xc7, 0x31, 0x15, 0x71, 0xd8, 0xe5, 0xf1, 0x34, 0xa5, 0xf7, 0xcc, 0x36, 0x3f, 0x93, 0x26, 0xb7, 0xfd, 0x1d, 0x9e, 0x86, 0xc1, 0x57, 0xb9, 0x61, 0x35, 0xf6, 0x0e, 0x48, 0x03, 0xb5, 0x66, 0x70, 0x3e, 0x8b, 0x8a, 0x4b, 0xbd, 0x74, 0x1f, 0xe8, 0xdd, 0xb4, 0xc6, 0x1c, 0xa6, 0x25, 0x2e, 0xba, 0x78, 0xbb, 0x16, 0xb0, 0x54, 0x2d, 0x0f, 0x41, 0x99, 0x42, 0x68, 0xbf, 0xe6, 0x89, 0x0d, 0x8c, 0xa1, 0x28, 0xdf, 0xce, 0x55, 0x87, 0xe9, 0x9b, 0x1e, 0x8e, 0x94, 0x69, 0xd9, 0x98, 0x11, 0xe1, 0xf8, 0x0b, 0xdb, 0xde, 0x5e, 0xb8, 0x14, 0x46, 0xee, 0x90, 0x88, 0x22, 0x2a, 0x4f, 0xdc, 0x60, 0x81, 0x19, 0x73, 0x64, 0x5d, 0x7e, 0x3d, 0xc4, 0xa7, 0x44, 0x17, 0x5f, 0x97, 0x13, 0xec, 0xcd, 0x0c, 0xae, 0x08, 0x65, 0x7a, 0xf4, 0xea, 0x6c, 0x56, 0x4e, 0xa9, 0x8d, 0xd5, 0x37, 0x6d, 0xe7, 0xc8, 0xe4, 0x79, 0x91, 0x95, 0xac, 0x62, 0xc2, 0xd3, 0x24, 0x5c, 0x49, 0x06, 0x3a, 0x0a, 0xe0, 0x32 +}, +{ +0x69, 0xd9, 0x8e, 0x94, 0xe1, 0xf8, 0x98, 0x11, 0xce, 0x55, 0x28, 0xdf, 0x9b, 0x1e, 0x87, 0xe9, 0xbf, 0xe6, 0x42, 0x68, 0x8c, 0xa1, 0x89, 0x0d, 0xb0, 0x54, 0xbb, 0x16, 0x41, 0x99, 0x2d, 0x0f, 0x1c, 0xa6, 0xb4, 0xc6, 0xba, 0x78, 0x25, 0x2e, 0x4b, 0xbd, 0x8b, 0x8a, 0xe8, 0xdd, 0x74, 0x1f, 0x48, 0x03, 0xf6, 0x0e, 0x70, 0x3e, 0xb5, 0x66, 0x86, 0xc1, 0x1d, 0x9e, 0x61, 0x35, 0x57, 0xb9, 0x49, 0x06, 0x24, 0x5c, 0xe0, 0x32, 0x3a, 0x0a, 0x91, 0x95, 0xe4, 0x79, 0xc2, 0xd3, 0xac, 0x62, 0x8d, 0xd5, 0x4e, 0xa9, 0xe7, 0xc8, 0x37, 0x6d, 0x65, 0x7a, 0xae, 0x08, 0x6c, 0x56, 0xf4, 0xea, 0x5f, 0x97, 0x44, 0x17, 0xcd, 0x0c, 0x13, 0xec, 0x64, 0x5d, 0x19, 0x73, 0xc4, 0xa7, 0x7e, 0x3d, 0x22, 0x2a, 0x90, 0x88, 0x60, 0x81, 0x4f, 0xdc, 0xde, 0x5e, 0x0b, 0xdb, 0x46, 0xee, 0xb8, 0x14, 0x43, 0x4d, 0x33, 0x85, 0xd0, 0xef, 0xaa, 0xfb, 0x50, 0x3c, 0x9f, 0xa8, 0x45, 0xf9, 0x02, 0x7f, 0x92, 0x9d, 0x38, 0xf5, 0x51, 0xa3, 0x40, 0x8f, 0x10, 0xff, 0xf3, 0xd2, 0xbc, 0xb6, 0xda, 0x21, 0x1b, 0x6e, 0x5a, 0xa0, 0x09, 0x83, 0x2c, 0x1a, 0x29, 0xe3, 0x2f, 0x84, 0x52, 0x3b, 0xd6, 0xb3, 0x20, 0xfc, 0xb1, 0x5b, 0x53, 0xd1, 0x00, 0xed, 0x4a, 0x4c, 0x58, 0xcf, 0x6a, 0xcb, 0xbe, 0x39, 0x36, 0x3f, 0xf7, 0xcc, 0xb7, 0xfd, 0x93, 0x26, 0x71, 0xd8, 0x31, 0x15, 0x34, 0xa5, 0xe5, 0xf1, 0x18, 0x96, 0x05, 0x9a, 0x04, 0xc7, 0x23, 0xc3, 0xeb, 0x27, 0xb2, 0x75, 0x07, 0x12, 0x80, 0xe2, 0xf2, 0x6b, 0x6f, 0xc5, 0x63, 0x7c, 0x77, 0x7b, 0xfe, 0xd7, 0xab, 0x76, 0x30, 0x01, 0x67, 0x2b, 0xfa, 0x59, 0x47, 0xf0, 0xca, 0x82, 0xc9, 0x7d, 0x9c, 0xa4, 0x72, 0xc0, 0xad, 0xd4, 0xa2, 0xaf +}, +{ +0x1f, 0x74, 0xdd, 0xe8, 0x8a, 0x8b, 0xbd, 0x4b, 0x2e, 0x25, 0x78, 0xba, 0xc6, 0xb4, 0xa6, 0x1c, 0xb9, 0x57, 0x35, 0x61, 0x9e, 0x1d, 0xc1, 0x86, 0x66, 0xb5, 0x3e, 0x70, 0x0e, 0xf6, 0x03, 0x48, 0xe9, 0x87, 0x1e, 0x9b, 0xdf, 0x28, 0x55, 0xce, 0x11, 0x98, 0xf8, 0xe1, 0x94, 0x8e, 0xd9, 0x69, 0x0f, 0x2d, 0x99, 0x41, 0x16, 0xbb, 0x54, 0xb0, 0x0d, 0x89, 0xa1, 0x8c, 0x68, 0x42, 0xe6, 0xbf, 0x3d, 0x7e, 0xa7, 0xc4, 0x73, 0x19, 0x5d, 0x64, 0xec, 0x13, 0x0c, 0xcd, 0x17, 0x44, 0x97, 0x5f, 0x14, 0xb8, 0xee, 0x46, 0xdb, 0x0b, 0x5e, 0xde, 0xdc, 0x4f, 0x81, 0x60, 0x88, 0x90, 0x2a, 0x22, 0x62, 0xac, 0xd3, 0xc2, 0x79, 0xe4, 0x95, 0x91, 0x0a, 0x3a, 0x32, 0xe0, 0x5c, 0x24, 0x06, 0x49, 0xea, 0xf4, 0x56, 0x6c, 0x08, 0xae, 0x7a, 0x65, 0x6d, 0x37, 0xc8, 0xe7, 0xa9, 0x4e, 0xd5, 0x8d, 0xb3, 0xd6, 0x3b, 0x52, 0x84, 0x2f, 0xe3, 0x29, 0x1a, 0x2c, 0x83, 0x09, 0xa0, 0x5a, 0x6e, 0x1b, 0x39, 0xbe, 0xcb, 0x6a, 0xcf, 0x58, 0x4c, 0x4a, 0xed, 0x00, 0xd1, 0x53, 0x5b, 0xb1, 0xfc, 0x20, 0x7f, 0x02, 0xf9, 0x45, 0xa8, 0x9f, 0x3c, 0x50, 0xfb, 0xaa, 0xef, 0xd0, 0x85, 0x33, 0x4d, 0x43, 0x21, 0xda, 0xb6, 0xbc, 0xd2, 0xf3, 0xff, 0x10, 0x8f, 0x40, 0xa3, 0x51, 0xf5, 0x38, 0x9d, 0x92, 0x2b, 0x67, 0x01, 0x30, 0x76, 0xab, 0xd7, 0xfe, 0x7b, 0x77, 0x7c, 0x63, 0xc5, 0x6f, 0x6b, 0xf2, 0xaf, 0xa2, 0xd4, 0xad, 0xc0, 0x72, 0xa4, 0x9c, 0x7d, 0xc9, 0x82, 0xca, 0xf0, 0x47, 0x59, 0xfa, 0xf1, 0xe5, 0xa5, 0x34, 0x15, 0x31, 0xd8, 0x71, 0x26, 0x93, 0xfd, 0xb7, 0xcc, 0xf7, 0x3f, 0x36, 0xe2, 0x80, 0x12, 0x07, 0x75, 0xb2, 0x27, 0xeb, 0xc3, 0x23, 0xc7, 0x04, 0x9a, 0x05, 0x96, 0x18 +}, +{ +0xbb, 0x16, 0xb0, 0x54, 0x2d, 0x0f, 0x41, 0x99, 0x42, 0x68, 0xbf, 0xe6, 0x89, 0x0d, 0x8c, 0xa1, 0x28, 0xdf, 0xce, 0x55, 0x87, 0xe9, 0x9b, 0x1e, 0x8e, 0x94, 0x69, 0xd9, 0x98, 0x11, 0xe1, 0xf8, 0x1d, 0x9e, 0x86, 0xc1, 0x57, 0xb9, 0x61, 0x35, 0xf6, 0x0e, 0x48, 0x03, 0xb5, 0x66, 0x70, 0x3e, 0x8b, 0x8a, 0x4b, 0xbd, 0x74, 0x1f, 0xe8, 0xdd, 0xb4, 0xc6, 0x1c, 0xa6, 0x25, 0x2e, 0xba, 0x78, 0xae, 0x08, 0x65, 0x7a, 0xf4, 0xea, 0x6c, 0x56, 0x4e, 0xa9, 0x8d, 0xd5, 0x37, 0x6d, 0xe7, 0xc8, 0xe4, 0x79, 0x91, 0x95, 0xac, 0x62, 0xc2, 0xd3, 0x24, 0x5c, 0x49, 0x06, 0x3a, 0x0a, 0xe0, 0x32, 0x0b, 0xdb, 0xde, 0x5e, 0xb8, 0x14, 0x46, 0xee, 0x90, 0x88, 0x22, 0x2a, 0x4f, 0xdc, 0x60, 0x81, 0x19, 0x73, 0x64, 0x5d, 0x7e, 0x3d, 0xc4, 0xa7, 0x44, 0x17, 0x5f, 0x97, 0x13, 0xec, 0xcd, 0x0c, 0xf3, 0xd2, 0x10, 0xff, 0xda, 0x21, 0xbc, 0xb6, 0x38, 0xf5, 0x92, 0x9d, 0x40, 0x8f, 0x51, 0xa3, 0x9f, 0xa8, 0x50, 0x3c, 0x02, 0x7f, 0x45, 0xf9, 0x33, 0x85, 0x43, 0x4d, 0xaa, 0xfb, 0xd0, 0xef, 0x58, 0xcf, 0x4a, 0x4c, 0xbe, 0x39, 0x6a, 0xcb, 0xb1, 0x5b, 0x20, 0xfc, 0x00, 0xed, 0x53, 0xd1, 0x2f, 0x84, 0x29, 0xe3, 0xd6, 0xb3, 0x52, 0x3b, 0x5a, 0xa0, 0x1b, 0x6e, 0x2c, 0x1a, 0x09, 0x83, 0xb2, 0x75, 0xeb, 0x27, 0x80, 0xe2, 0x07, 0x12, 0x05, 0x9a, 0x18, 0x96, 0x23, 0xc3, 0x04, 0xc7, 0x31, 0x15, 0x71, 0xd8, 0xe5, 0xf1, 0x34, 0xa5, 0xf7, 0xcc, 0x36, 0x3f, 0x93, 0x26, 0xb7, 0xfd, 0x72, 0xc0, 0x9c, 0xa4, 0xa2, 0xaf, 0xad, 0xd4, 0x47, 0xf0, 0xfa, 0x59, 0xc9, 0x7d, 0xca, 0x82, 0xab, 0x76, 0xfe, 0xd7, 0x67, 0x2b, 0x30, 0x01, 0x6f, 0xc5, 0xf2, 0x6b, 0x77, 0x7b, 0x63, 0x7c +}, +{ +0xf3, 0xd2, 0x10, 0xff, 0xda, 0x21, 0xbc, 0xb6, 0x38, 0xf5, 0x92, 0x9d, 0x40, 0x8f, 0x51, 0xa3, 0x9f, 0xa8, 0x50, 0x3c, 0x02, 0x7f, 0x45, 0xf9, 0x33, 0x85, 0x43, 0x4d, 0xaa, 0xfb, 0xd0, 0xef, 0x58, 0xcf, 0x4a, 0x4c, 0xbe, 0x39, 0x6a, 0xcb, 0xb1, 0x5b, 0x20, 0xfc, 0x00, 0xed, 0x53, 0xd1, 0x2f, 0x84, 0x29, 0xe3, 0xd6, 0xb3, 0x52, 0x3b, 0x5a, 0xa0, 0x1b, 0x6e, 0x2c, 0x1a, 0x09, 0x83, 0xb2, 0x75, 0xeb, 0x27, 0x80, 0xe2, 0x07, 0x12, 0x05, 0x9a, 0x18, 0x96, 0x23, 0xc3, 0x04, 0xc7, 0x31, 0x15, 0x71, 0xd8, 0xe5, 0xf1, 0x34, 0xa5, 0xf7, 0xcc, 0x36, 0x3f, 0x93, 0x26, 0xb7, 0xfd, 0x72, 0xc0, 0x9c, 0xa4, 0xa2, 0xaf, 0xad, 0xd4, 0x47, 0xf0, 0xfa, 0x59, 0xc9, 0x7d, 0xca, 0x82, 0xab, 0x76, 0xfe, 0xd7, 0x67, 0x2b, 0x30, 0x01, 0x6f, 0xc5, 0xf2, 0x6b, 0x77, 0x7b, 0x63, 0x7c, 0xbb, 0x16, 0xb0, 0x54, 0x2d, 0x0f, 0x41, 0x99, 0x42, 0x68, 0xbf, 0xe6, 0x89, 0x0d, 0x8c, 0xa1, 0x28, 0xdf, 0xce, 0x55, 0x87, 0xe9, 0x9b, 0x1e, 0x8e, 0x94, 0x69, 0xd9, 0x98, 0x11, 0xe1, 0xf8, 0x1d, 0x9e, 0x86, 0xc1, 0x57, 0xb9, 0x61, 0x35, 0xf6, 0x0e, 0x48, 0x03, 0xb5, 0x66, 0x70, 0x3e, 0x8b, 0x8a, 0x4b, 0xbd, 0x74, 0x1f, 0xe8, 0xdd, 0xb4, 0xc6, 0x1c, 0xa6, 0x25, 0x2e, 0xba, 0x78, 0xae, 0x08, 0x65, 0x7a, 0xf4, 0xea, 0x6c, 0x56, 0x4e, 0xa9, 0x8d, 0xd5, 0x37, 0x6d, 0xe7, 0xc8, 0xe4, 0x79, 0x91, 0x95, 0xac, 0x62, 0xc2, 0xd3, 0x24, 0x5c, 0x49, 0x06, 0x3a, 0x0a, 0xe0, 0x32, 0x0b, 0xdb, 0xde, 0x5e, 0xb8, 0x14, 0x46, 0xee, 0x90, 0x88, 0x22, 0x2a, 0x4f, 0xdc, 0x60, 0x81, 0x19, 0x73, 0x64, 0x5d, 0x7e, 0x3d, 0xc4, 0xa7, 0x44, 0x17, 0x5f, 0x97, 0x13, 0xec, 0xcd, 0x0c +}, +{ +0xa3, 0x51, 0x8f, 0x40, 0x9d, 0x92, 0xf5, 0x38, 0xb6, 0xbc, 0x21, 0xda, 0xff, 0x10, 0xd2, 0xf3, 0xef, 0xd0, 0xfb, 0xaa, 0x4d, 0x43, 0x85, 0x33, 0xf9, 0x45, 0x7f, 0x02, 0x3c, 0x50, 0xa8, 0x9f, 0xd1, 0x53, 0xed, 0x00, 0xfc, 0x20, 0x5b, 0xb1, 0xcb, 0x6a, 0x39, 0xbe, 0x4c, 0x4a, 0xcf, 0x58, 0x83, 0x09, 0x1a, 0x2c, 0x6e, 0x1b, 0xa0, 0x5a, 0x3b, 0x52, 0xb3, 0xd6, 0xe3, 0x29, 0x84, 0x2f, 0xc7, 0x04, 0xc3, 0x23, 0x96, 0x18, 0x9a, 0x05, 0x12, 0x07, 0xe2, 0x80, 0x27, 0xeb, 0x75, 0xb2, 0xfd, 0xb7, 0x26, 0x93, 0x3f, 0x36, 0xcc, 0xf7, 0xa5, 0x34, 0xf1, 0xe5, 0xd8, 0x71, 0x15, 0x31, 0x82, 0xca, 0x7d, 0xc9, 0x59, 0xfa, 0xf0, 0x47, 0xd4, 0xad, 0xaf, 0xa2, 0xa4, 0x9c, 0xc0, 0x72, 0x7c, 0x63, 0x7b, 0x77, 0x6b, 0xf2, 0xc5, 0x6f, 0x01, 0x30, 0x2b, 0x67, 0xd7, 0xfe, 0x76, 0xab, 0xa1, 0x8c, 0x0d, 0x89, 0xe6, 0xbf, 0x68, 0x42, 0x99, 0x41, 0x0f, 0x2d, 0x54, 0xb0, 0x16, 0xbb, 0xf8, 0xe1, 0x11, 0x98, 0xd9, 0x69, 0x94, 0x8e, 0x1e, 0x9b, 0xe9, 0x87, 0x55, 0xce, 0xdf, 0x28, 0x3e, 0x70, 0x66, 0xb5, 0x03, 0x48, 0x0e, 0xf6, 0x35, 0x61, 0xb9, 0x57, 0xc1, 0x86, 0x9e, 0x1d, 0x78, 0xba, 0x2e, 0x25, 0xa6, 0x1c, 0xc6, 0xb4, 0xdd, 0xe8, 0x1f, 0x74, 0xbd, 0x4b, 0x8a, 0x8b, 0xc8, 0xe7, 0x6d, 0x37, 0xd5, 0x8d, 0xa9, 0x4e, 0x56, 0x6c, 0xea, 0xf4, 0x7a, 0x65, 0x08, 0xae, 0x32, 0xe0, 0x0a, 0x3a, 0x06, 0x49, 0x5c, 0x24, 0xd3, 0xc2, 0x62, 0xac, 0x95, 0x91, 0x79, 0xe4, 0x81, 0x60, 0xdc, 0x4f, 0x2a, 0x22, 0x88, 0x90, 0xee, 0x46, 0x14, 0xb8, 0x5e, 0xde, 0xdb, 0x0b, 0x0c, 0xcd, 0xec, 0x13, 0x97, 0x5f, 0x17, 0x44, 0xa7, 0xc4, 0x3d, 0x7e, 0x5d, 0x64, 0x73, 0x19 +}, +{ +0x99, 0x41, 0x0f, 0x2d, 0x54, 0xb0, 0x16, 0xbb, 0xa1, 0x8c, 0x0d, 0x89, 0xe6, 0xbf, 0x68, 0x42, 0x1e, 0x9b, 0xe9, 0x87, 0x55, 0xce, 0xdf, 0x28, 0xf8, 0xe1, 0x11, 0x98, 0xd9, 0x69, 0x94, 0x8e, 0x35, 0x61, 0xb9, 0x57, 0xc1, 0x86, 0x9e, 0x1d, 0x3e, 0x70, 0x66, 0xb5, 0x03, 0x48, 0x0e, 0xf6, 0xdd, 0xe8, 0x1f, 0x74, 0xbd, 0x4b, 0x8a, 0x8b, 0x78, 0xba, 0x2e, 0x25, 0xa6, 0x1c, 0xc6, 0xb4, 0x56, 0x6c, 0xea, 0xf4, 0x7a, 0x65, 0x08, 0xae, 0xc8, 0xe7, 0x6d, 0x37, 0xd5, 0x8d, 0xa9, 0x4e, 0xd3, 0xc2, 0x62, 0xac, 0x95, 0x91, 0x79, 0xe4, 0x32, 0xe0, 0x0a, 0x3a, 0x06, 0x49, 0x5c, 0x24, 0xee, 0x46, 0x14, 0xb8, 0x5e, 0xde, 0xdb, 0x0b, 0x81, 0x60, 0xdc, 0x4f, 0x2a, 0x22, 0x88, 0x90, 0xa7, 0xc4, 0x3d, 0x7e, 0x5d, 0x64, 0x73, 0x19, 0x0c, 0xcd, 0xec, 0x13, 0x97, 0x5f, 0x17, 0x44, 0xb6, 0xbc, 0x21, 0xda, 0xff, 0x10, 0xd2, 0xf3, 0xa3, 0x51, 0x8f, 0x40, 0x9d, 0x92, 0xf5, 0x38, 0xf9, 0x45, 0x7f, 0x02, 0x3c, 0x50, 0xa8, 0x9f, 0xef, 0xd0, 0xfb, 0xaa, 0x4d, 0x43, 0x85, 0x33, 0xcb, 0x6a, 0x39, 0xbe, 0x4c, 0x4a, 0xcf, 0x58, 0xd1, 0x53, 0xed, 0x00, 0xfc, 0x20, 0x5b, 0xb1, 0x3b, 0x52, 0xb3, 0xd6, 0xe3, 0x29, 0x84, 0x2f, 0x83, 0x09, 0x1a, 0x2c, 0x6e, 0x1b, 0xa0, 0x5a, 0x12, 0x07, 0xe2, 0x80, 0x27, 0xeb, 0x75, 0xb2, 0xc7, 0x04, 0xc3, 0x23, 0x96, 0x18, 0x9a, 0x05, 0xa5, 0x34, 0xf1, 0xe5, 0xd8, 0x71, 0x15, 0x31, 0xfd, 0xb7, 0x26, 0x93, 0x3f, 0x36, 0xcc, 0xf7, 0xd4, 0xad, 0xaf, 0xa2, 0xa4, 0x9c, 0xc0, 0x72, 0x82, 0xca, 0x7d, 0xc9, 0x59, 0xfa, 0xf0, 0x47, 0x01, 0x30, 0x2b, 0x67, 0xd7, 0xfe, 0x76, 0xab, 0x7c, 0x63, 0x7b, 0x77, 0x6b, 0xf2, 0xc5, 0x6f +}, +{ +0xf5, 0x38, 0x9d, 0x92, 0x8f, 0x40, 0xa3, 0x51, 0xd2, 0xf3, 0xff, 0x10, 0x21, 0xda, 0xb6, 0xbc, 0x85, 0x33, 0x4d, 0x43, 0xfb, 0xaa, 0xef, 0xd0, 0xa8, 0x9f, 0x3c, 0x50, 0x7f, 0x02, 0xf9, 0x45, 0x5b, 0xb1, 0xfc, 0x20, 0xed, 0x00, 0xd1, 0x53, 0xcf, 0x58, 0x4c, 0x4a, 0x39, 0xbe, 0xcb, 0x6a, 0xa0, 0x5a, 0x6e, 0x1b, 0x1a, 0x2c, 0x83, 0x09, 0x84, 0x2f, 0xe3, 0x29, 0xb3, 0xd6, 0x3b, 0x52, 0x9a, 0x05, 0x96, 0x18, 0xc3, 0x23, 0xc7, 0x04, 0x75, 0xb2, 0x27, 0xeb, 0xe2, 0x80, 0x12, 0x07, 0xcc, 0xf7, 0x3f, 0x36, 0x26, 0x93, 0xfd, 0xb7, 0x15, 0x31, 0xd8, 0x71, 0xf1, 0xe5, 0xa5, 0x34, 0xf0, 0x47, 0x59, 0xfa, 0x7d, 0xc9, 0x82, 0xca, 0xc0, 0x72, 0xa4, 0x9c, 0xaf, 0xa2, 0xd4, 0xad, 0xc5, 0x6f, 0x6b, 0xf2, 0x7b, 0x77, 0x7c, 0x63, 0x76, 0xab, 0xd7, 0xfe, 0x2b, 0x67, 0x01, 0x30, 0x68, 0x42, 0xe6, 0xbf, 0x0d, 0x89, 0xa1, 0x8c, 0x16, 0xbb, 0x54, 0xb0, 0x0f, 0x2d, 0x99, 0x41, 0x94, 0x8e, 0xd9, 0x69, 0x11, 0x98, 0xf8, 0xe1, 0xdf, 0x28, 0x55, 0xce, 0xe9, 0x87, 0x1e, 0x9b, 0x0e, 0xf6, 0x03, 0x48, 0x66, 0xb5, 0x3e, 0x70, 0x9e, 0x1d, 0xc1, 0x86, 0xb9, 0x57, 0x35, 0x61, 0xc6, 0xb4, 0xa6, 0x1c, 0x2e, 0x25, 0x78, 0xba, 0x8a, 0x8b, 0xbd, 0x4b, 0x1f, 0x74, 0xdd, 0xe8, 0xa9, 0x4e, 0xd5, 0x8d, 0x6d, 0x37, 0xc8, 0xe7, 0x08, 0xae, 0x7a, 0x65, 0xea, 0xf4, 0x56, 0x6c, 0x5c, 0x24, 0x06, 0x49, 0x0a, 0x3a, 0x32, 0xe0, 0x79, 0xe4, 0x95, 0x91, 0x62, 0xac, 0xd3, 0xc2, 0x88, 0x90, 0x2a, 0x22, 0xdc, 0x4f, 0x81, 0x60, 0xdb, 0x0b, 0x5e, 0xde, 0x14, 0xb8, 0xee, 0x46, 0x17, 0x44, 0x97, 0x5f, 0xec, 0x13, 0x0c, 0xcd, 0x73, 0x19, 0x5d, 0x64, 0x3d, 0x7e, 0xa7, 0xc4 +}, +{ +0xd1, 0x53, 0xed, 0x00, 0xfc, 0x20, 0x5b, 0xb1, 0xcb, 0x6a, 0x39, 0xbe, 0x4c, 0x4a, 0xcf, 0x58, 0x83, 0x09, 0x1a, 0x2c, 0x6e, 0x1b, 0xa0, 0x5a, 0x3b, 0x52, 0xb3, 0xd6, 0xe3, 0x29, 0x84, 0x2f, 0xa3, 0x51, 0x8f, 0x40, 0x9d, 0x92, 0xf5, 0x38, 0xb6, 0xbc, 0x21, 0xda, 0xff, 0x10, 0xd2, 0xf3, 0xef, 0xd0, 0xfb, 0xaa, 0x4d, 0x43, 0x85, 0x33, 0xf9, 0x45, 0x7f, 0x02, 0x3c, 0x50, 0xa8, 0x9f, 0x82, 0xca, 0x7d, 0xc9, 0x59, 0xfa, 0xf0, 0x47, 0xd4, 0xad, 0xaf, 0xa2, 0xa4, 0x9c, 0xc0, 0x72, 0x7c, 0x63, 0x7b, 0x77, 0x6b, 0xf2, 0xc5, 0x6f, 0x01, 0x30, 0x2b, 0x67, 0xd7, 0xfe, 0x76, 0xab, 0xc7, 0x04, 0xc3, 0x23, 0x96, 0x18, 0x9a, 0x05, 0x12, 0x07, 0xe2, 0x80, 0x27, 0xeb, 0x75, 0xb2, 0xfd, 0xb7, 0x26, 0x93, 0x3f, 0x36, 0xcc, 0xf7, 0xa5, 0x34, 0xf1, 0xe5, 0xd8, 0x71, 0x15, 0x31, 0x3e, 0x70, 0x66, 0xb5, 0x03, 0x48, 0x0e, 0xf6, 0x35, 0x61, 0xb9, 0x57, 0xc1, 0x86, 0x9e, 0x1d, 0x78, 0xba, 0x2e, 0x25, 0xa6, 0x1c, 0xc6, 0xb4, 0xdd, 0xe8, 0x1f, 0x74, 0xbd, 0x4b, 0x8a, 0x8b, 0xa1, 0x8c, 0x0d, 0x89, 0xe6, 0xbf, 0x68, 0x42, 0x99, 0x41, 0x0f, 0x2d, 0x54, 0xb0, 0x16, 0xbb, 0xf8, 0xe1, 0x11, 0x98, 0xd9, 0x69, 0x94, 0x8e, 0x1e, 0x9b, 0xe9, 0x87, 0x55, 0xce, 0xdf, 0x28, 0x81, 0x60, 0xdc, 0x4f, 0x2a, 0x22, 0x88, 0x90, 0xee, 0x46, 0x14, 0xb8, 0x5e, 0xde, 0xdb, 0x0b, 0x0c, 0xcd, 0xec, 0x13, 0x97, 0x5f, 0x17, 0x44, 0xa7, 0xc4, 0x3d, 0x7e, 0x5d, 0x64, 0x73, 0x19, 0xc8, 0xe7, 0x6d, 0x37, 0xd5, 0x8d, 0xa9, 0x4e, 0x56, 0x6c, 0xea, 0xf4, 0x7a, 0x65, 0x08, 0xae, 0x32, 0xe0, 0x0a, 0x3a, 0x06, 0x49, 0x5c, 0x24, 0xd3, 0xc2, 0x62, 0xac, 0x95, 0x91, 0x79, 0xe4 +}, +{ +0x00, 0xed, 0x53, 0xd1, 0xb1, 0x5b, 0x20, 0xfc, 0xbe, 0x39, 0x6a, 0xcb, 0x58, 0xcf, 0x4a, 0x4c, 0x2c, 0x1a, 0x09, 0x83, 0x5a, 0xa0, 0x1b, 0x6e, 0xd6, 0xb3, 0x52, 0x3b, 0x2f, 0x84, 0x29, 0xe3, 0x40, 0x8f, 0x51, 0xa3, 0x38, 0xf5, 0x92, 0x9d, 0xda, 0x21, 0xbc, 0xb6, 0xf3, 0xd2, 0x10, 0xff, 0xaa, 0xfb, 0xd0, 0xef, 0x33, 0x85, 0x43, 0x4d, 0x02, 0x7f, 0x45, 0xf9, 0x9f, 0xa8, 0x50, 0x3c, 0xc9, 0x7d, 0xca, 0x82, 0x47, 0xf0, 0xfa, 0x59, 0xa2, 0xaf, 0xad, 0xd4, 0x72, 0xc0, 0x9c, 0xa4, 0x77, 0x7b, 0x63, 0x7c, 0x6f, 0xc5, 0xf2, 0x6b, 0x67, 0x2b, 0x30, 0x01, 0xab, 0x76, 0xfe, 0xd7, 0x23, 0xc3, 0x04, 0xc7, 0x05, 0x9a, 0x18, 0x96, 0x80, 0xe2, 0x07, 0x12, 0xb2, 0x75, 0xeb, 0x27, 0x93, 0x26, 0xb7, 0xfd, 0xf7, 0xcc, 0x36, 0x3f, 0xe5, 0xf1, 0x34, 0xa5, 0x31, 0x15, 0x71, 0xd8, 0xb5, 0x66, 0x70, 0x3e, 0xf6, 0x0e, 0x48, 0x03, 0x57, 0xb9, 0x61, 0x35, 0x1d, 0x9e, 0x86, 0xc1, 0x25, 0x2e, 0xba, 0x78, 0xb4, 0xc6, 0x1c, 0xa6, 0x74, 0x1f, 0xe8, 0xdd, 0x8b, 0x8a, 0x4b, 0xbd, 0x89, 0x0d, 0x8c, 0xa1, 0x42, 0x68, 0xbf, 0xe6, 0x2d, 0x0f, 0x41, 0x99, 0xbb, 0x16, 0xb0, 0x54, 0x98, 0x11, 0xe1, 0xf8, 0x8e, 0x94, 0x69, 0xd9, 0x87, 0xe9, 0x9b, 0x1e, 0x28, 0xdf, 0xce, 0x55, 0x4f, 0xdc, 0x60, 0x81, 0x90, 0x88, 0x22, 0x2a, 0xb8, 0x14, 0x46, 0xee, 0x0b, 0xdb, 0xde, 0x5e, 0x13, 0xec, 0xcd, 0x0c, 0x44, 0x17, 0x5f, 0x97, 0x7e, 0x3d, 0xc4, 0xa7, 0x19, 0x73, 0x64, 0x5d, 0x37, 0x6d, 0xe7, 0xc8, 0x4e, 0xa9, 0x8d, 0xd5, 0xf4, 0xea, 0x6c, 0x56, 0xae, 0x08, 0x65, 0x7a, 0x3a, 0x0a, 0xe0, 0x32, 0x24, 0x5c, 0x49, 0x06, 0xac, 0x62, 0xc2, 0xd3, 0xe4, 0x79, 0x91, 0x95 +} +}, +{ +{ +0x75, 0xb2, 0x27, 0xeb, 0xe2, 0x80, 0x12, 0x07, 0x9a, 0x05, 0x96, 0x18, 0xc3, 0x23, 0xc7, 0x04, 0x15, 0x31, 0xd8, 0x71, 0xf1, 0xe5, 0xa5, 0x34, 0xcc, 0xf7, 0x3f, 0x36, 0x26, 0x93, 0xfd, 0xb7, 0xc0, 0x72, 0xa4, 0x9c, 0xaf, 0xa2, 0xd4, 0xad, 0xf0, 0x47, 0x59, 0xfa, 0x7d, 0xc9, 0x82, 0xca, 0x76, 0xab, 0xd7, 0xfe, 0x2b, 0x67, 0x01, 0x30, 0xc5, 0x6f, 0x6b, 0xf2, 0x7b, 0x77, 0x7c, 0x63, 0xd2, 0xf3, 0xff, 0x10, 0x21, 0xda, 0xb6, 0xbc, 0xf5, 0x38, 0x9d, 0x92, 0x8f, 0x40, 0xa3, 0x51, 0xa8, 0x9f, 0x3c, 0x50, 0x7f, 0x02, 0xf9, 0x45, 0x85, 0x33, 0x4d, 0x43, 0xfb, 0xaa, 0xef, 0xd0, 0xcf, 0x58, 0x4c, 0x4a, 0x39, 0xbe, 0xcb, 0x6a, 0x5b, 0xb1, 0xfc, 0x20, 0xed, 0x00, 0xd1, 0x53, 0x84, 0x2f, 0xe3, 0x29, 0xb3, 0xd6, 0x3b, 0x52, 0xa0, 0x5a, 0x6e, 0x1b, 0x1a, 0x2c, 0x83, 0x09, 0x08, 0xae, 0x7a, 0x65, 0xea, 0xf4, 0x56, 0x6c, 0xa9, 0x4e, 0xd5, 0x8d, 0x6d, 0x37, 0xc8, 0xe7, 0x79, 0xe4, 0x95, 0x91, 0x62, 0xac, 0xd3, 0xc2, 0x5c, 0x24, 0x06, 0x49, 0x0a, 0x3a, 0x32, 0xe0, 0xdb, 0x0b, 0x5e, 0xde, 0x14, 0xb8, 0xee, 0x46, 0x88, 0x90, 0x2a, 0x22, 0xdc, 0x4f, 0x81, 0x60, 0x73, 0x19, 0x5d, 0x64, 0x3d, 0x7e, 0xa7, 0xc4, 0x17, 0x44, 0x97, 0x5f, 0xec, 0x13, 0x0c, 0xcd, 0x16, 0xbb, 0x54, 0xb0, 0x0f, 0x2d, 0x99, 0x41, 0x68, 0x42, 0xe6, 0xbf, 0x0d, 0x89, 0xa1, 0x8c, 0xdf, 0x28, 0x55, 0xce, 0xe9, 0x87, 0x1e, 0x9b, 0x94, 0x8e, 0xd9, 0x69, 0x11, 0x98, 0xf8, 0xe1, 0x9e, 0x1d, 0xc1, 0x86, 0xb9, 0x57, 0x35, 0x61, 0x0e, 0xf6, 0x03, 0x48, 0x66, 0xb5, 0x3e, 0x70, 0x8a, 0x8b, 0xbd, 0x4b, 0x1f, 0x74, 0xdd, 0xe8, 0xc6, 0xb4, 0xa6, 0x1c, 0x2e, 0x25, 0x78, 0xba +}, +{ +0x3c, 0x50, 0xa8, 0x9f, 0xf9, 0x45, 0x7f, 0x02, 0x4d, 0x43, 0x85, 0x33, 0xef, 0xd0, 0xfb, 0xaa, 0xff, 0x10, 0xd2, 0xf3, 0xb6, 0xbc, 0x21, 0xda, 0x9d, 0x92, 0xf5, 0x38, 0xa3, 0x51, 0x8f, 0x40, 0xe3, 0x29, 0x84, 0x2f, 0x3b, 0x52, 0xb3, 0xd6, 0x6e, 0x1b, 0xa0, 0x5a, 0x83, 0x09, 0x1a, 0x2c, 0x4c, 0x4a, 0xcf, 0x58, 0xcb, 0x6a, 0x39, 0xbe, 0xfc, 0x20, 0x5b, 0xb1, 0xd1, 0x53, 0xed, 0x00, 0xd8, 0x71, 0x15, 0x31, 0xa5, 0x34, 0xf1, 0xe5, 0x3f, 0x36, 0xcc, 0xf7, 0xfd, 0xb7, 0x26, 0x93, 0x27, 0xeb, 0x75, 0xb2, 0x12, 0x07, 0xe2, 0x80, 0x96, 0x18, 0x9a, 0x05, 0xc7, 0x04, 0xc3, 0x23, 0xd7, 0xfe, 0x76, 0xab, 0x01, 0x30, 0x2b, 0x67, 0x6b, 0xf2, 0xc5, 0x6f, 0x7c, 0x63, 0x7b, 0x77, 0xa4, 0x9c, 0xc0, 0x72, 0xd4, 0xad, 0xaf, 0xa2, 0x59, 0xfa, 0xf0, 0x47, 0x82, 0xca, 0x7d, 0xc9, 0x55, 0xce, 0xdf, 0x28, 0x1e, 0x9b, 0xe9, 0x87, 0xd9, 0x69, 0x94, 0x8e, 0xf8, 0xe1, 0x11, 0x98, 0x54, 0xb0, 0x16, 0xbb, 0x99, 0x41, 0x0f, 0x2d, 0xe6, 0xbf, 0x68, 0x42, 0xa1, 0x8c, 0x0d, 0x89, 0xbd, 0x4b, 0x8a, 0x8b, 0xdd, 0xe8, 0x1f, 0x74, 0xa6, 0x1c, 0xc6, 0xb4, 0x78, 0xba, 0x2e, 0x25, 0xc1, 0x86, 0x9e, 0x1d, 0x35, 0x61, 0xb9, 0x57, 0x03, 0x48, 0x0e, 0xf6, 0x3e, 0x70, 0x66, 0xb5, 0x95, 0x91, 0x79, 0xe4, 0xd3, 0xc2, 0x62, 0xac, 0x06, 0x49, 0x5c, 0x24, 0x32, 0xe0, 0x0a, 0x3a, 0x7a, 0x65, 0x08, 0xae, 0x56, 0x6c, 0xea, 0xf4, 0xd5, 0x8d, 0xa9, 0x4e, 0xc8, 0xe7, 0x6d, 0x37, 0x5d, 0x64, 0x73, 0x19, 0xa7, 0xc4, 0x3d, 0x7e, 0x97, 0x5f, 0x17, 0x44, 0x0c, 0xcd, 0xec, 0x13, 0x5e, 0xde, 0xdb, 0x0b, 0xee, 0x46, 0x14, 0xb8, 0x2a, 0x22, 0x88, 0x90, 0x81, 0x60, 0xdc, 0x4f +}, +{ +0x9d, 0x92, 0xf5, 0x38, 0xa3, 0x51, 0x8f, 0x40, 0xff, 0x10, 0xd2, 0xf3, 0xb6, 0xbc, 0x21, 0xda, 0x4d, 0x43, 0x85, 0x33, 0xef, 0xd0, 0xfb, 0xaa, 0x3c, 0x50, 0xa8, 0x9f, 0xf9, 0x45, 0x7f, 0x02, 0xfc, 0x20, 0x5b, 0xb1, 0xd1, 0x53, 0xed, 0x00, 0x4c, 0x4a, 0xcf, 0x58, 0xcb, 0x6a, 0x39, 0xbe, 0x6e, 0x1b, 0xa0, 0x5a, 0x83, 0x09, 0x1a, 0x2c, 0xe3, 0x29, 0x84, 0x2f, 0x3b, 0x52, 0xb3, 0xd6, 0x96, 0x18, 0x9a, 0x05, 0xc7, 0x04, 0xc3, 0x23, 0x27, 0xeb, 0x75, 0xb2, 0x12, 0x07, 0xe2, 0x80, 0x3f, 0x36, 0xcc, 0xf7, 0xfd, 0xb7, 0x26, 0x93, 0xd8, 0x71, 0x15, 0x31, 0xa5, 0x34, 0xf1, 0xe5, 0x59, 0xfa, 0xf0, 0x47, 0x82, 0xca, 0x7d, 0xc9, 0xa4, 0x9c, 0xc0, 0x72, 0xd4, 0xad, 0xaf, 0xa2, 0x6b, 0xf2, 0xc5, 0x6f, 0x7c, 0x63, 0x7b, 0x77, 0xd7, 0xfe, 0x76, 0xab, 0x01, 0x30, 0x2b, 0x67, 0xe6, 0xbf, 0x68, 0x42, 0xa1, 0x8c, 0x0d, 0x89, 0x54, 0xb0, 0x16, 0xbb, 0x99, 0x41, 0x0f, 0x2d, 0xd9, 0x69, 0x94, 0x8e, 0xf8, 0xe1, 0x11, 0x98, 0x55, 0xce, 0xdf, 0x28, 0x1e, 0x9b, 0xe9, 0x87, 0x03, 0x48, 0x0e, 0xf6, 0x3e, 0x70, 0x66, 0xb5, 0xc1, 0x86, 0x9e, 0x1d, 0x35, 0x61, 0xb9, 0x57, 0xa6, 0x1c, 0xc6, 0xb4, 0x78, 0xba, 0x2e, 0x25, 0xbd, 0x4b, 0x8a, 0x8b, 0xdd, 0xe8, 0x1f, 0x74, 0xd5, 0x8d, 0xa9, 0x4e, 0xc8, 0xe7, 0x6d, 0x37, 0x7a, 0x65, 0x08, 0xae, 0x56, 0x6c, 0xea, 0xf4, 0x06, 0x49, 0x5c, 0x24, 0x32, 0xe0, 0x0a, 0x3a, 0x95, 0x91, 0x79, 0xe4, 0xd3, 0xc2, 0x62, 0xac, 0x2a, 0x22, 0x88, 0x90, 0x81, 0x60, 0xdc, 0x4f, 0x5e, 0xde, 0xdb, 0x0b, 0xee, 0x46, 0x14, 0xb8, 0x97, 0x5f, 0x17, 0x44, 0x0c, 0xcd, 0xec, 0x13, 0x5d, 0x64, 0x73, 0x19, 0xa7, 0xc4, 0x3d, 0x7e +}, +{ +0x2f, 0x84, 0x29, 0xe3, 0xd6, 0xb3, 0x52, 0x3b, 0x5a, 0xa0, 0x1b, 0x6e, 0x2c, 0x1a, 0x09, 0x83, 0x58, 0xcf, 0x4a, 0x4c, 0xbe, 0x39, 0x6a, 0xcb, 0xb1, 0x5b, 0x20, 0xfc, 0x00, 0xed, 0x53, 0xd1, 0x9f, 0xa8, 0x50, 0x3c, 0x02, 0x7f, 0x45, 0xf9, 0x33, 0x85, 0x43, 0x4d, 0xaa, 0xfb, 0xd0, 0xef, 0xf3, 0xd2, 0x10, 0xff, 0xda, 0x21, 0xbc, 0xb6, 0x38, 0xf5, 0x92, 0x9d, 0x40, 0x8f, 0x51, 0xa3, 0xab, 0x76, 0xfe, 0xd7, 0x67, 0x2b, 0x30, 0x01, 0x6f, 0xc5, 0xf2, 0x6b, 0x77, 0x7b, 0x63, 0x7c, 0x72, 0xc0, 0x9c, 0xa4, 0xa2, 0xaf, 0xad, 0xd4, 0x47, 0xf0, 0xfa, 0x59, 0xc9, 0x7d, 0xca, 0x82, 0x31, 0x15, 0x71, 0xd8, 0xe5, 0xf1, 0x34, 0xa5, 0xf7, 0xcc, 0x36, 0x3f, 0x93, 0x26, 0xb7, 0xfd, 0xb2, 0x75, 0xeb, 0x27, 0x80, 0xe2, 0x07, 0x12, 0x05, 0x9a, 0x18, 0x96, 0x23, 0xc3, 0x04, 0xc7, 0x8b, 0x8a, 0x4b, 0xbd, 0x74, 0x1f, 0xe8, 0xdd, 0xb4, 0xc6, 0x1c, 0xa6, 0x25, 0x2e, 0xba, 0x78, 0x1d, 0x9e, 0x86, 0xc1, 0x57, 0xb9, 0x61, 0x35, 0xf6, 0x0e, 0x48, 0x03, 0xb5, 0x66, 0x70, 0x3e, 0x28, 0xdf, 0xce, 0x55, 0x87, 0xe9, 0x9b, 0x1e, 0x8e, 0x94, 0x69, 0xd9, 0x98, 0x11, 0xe1, 0xf8, 0xbb, 0x16, 0xb0, 0x54, 0x2d, 0x0f, 0x41, 0x99, 0x42, 0x68, 0xbf, 0xe6, 0x89, 0x0d, 0x8c, 0xa1, 0x19, 0x73, 0x64, 0x5d, 0x7e, 0x3d, 0xc4, 0xa7, 0x44, 0x17, 0x5f, 0x97, 0x13, 0xec, 0xcd, 0x0c, 0x0b, 0xdb, 0xde, 0x5e, 0xb8, 0x14, 0x46, 0xee, 0x90, 0x88, 0x22, 0x2a, 0x4f, 0xdc, 0x60, 0x81, 0xe4, 0x79, 0x91, 0x95, 0xac, 0x62, 0xc2, 0xd3, 0x24, 0x5c, 0x49, 0x06, 0x3a, 0x0a, 0xe0, 0x32, 0xae, 0x08, 0x65, 0x7a, 0xf4, 0xea, 0x6c, 0x56, 0x4e, 0xa9, 0x8d, 0xd5, 0x37, 0x6d, 0xe7, 0xc8 +}, +{ +0x4c, 0x4a, 0xcf, 0x58, 0xcb, 0x6a, 0x39, 0xbe, 0xfc, 0x20, 0x5b, 0xb1, 0xd1, 0x53, 0xed, 0x00, 0xe3, 0x29, 0x84, 0x2f, 0x3b, 0x52, 0xb3, 0xd6, 0x6e, 0x1b, 0xa0, 0x5a, 0x83, 0x09, 0x1a, 0x2c, 0xff, 0x10, 0xd2, 0xf3, 0xb6, 0xbc, 0x21, 0xda, 0x9d, 0x92, 0xf5, 0x38, 0xa3, 0x51, 0x8f, 0x40, 0x3c, 0x50, 0xa8, 0x9f, 0xf9, 0x45, 0x7f, 0x02, 0x4d, 0x43, 0x85, 0x33, 0xef, 0xd0, 0xfb, 0xaa, 0xa4, 0x9c, 0xc0, 0x72, 0xd4, 0xad, 0xaf, 0xa2, 0x59, 0xfa, 0xf0, 0x47, 0x82, 0xca, 0x7d, 0xc9, 0xd7, 0xfe, 0x76, 0xab, 0x01, 0x30, 0x2b, 0x67, 0x6b, 0xf2, 0xc5, 0x6f, 0x7c, 0x63, 0x7b, 0x77, 0x27, 0xeb, 0x75, 0xb2, 0x12, 0x07, 0xe2, 0x80, 0x96, 0x18, 0x9a, 0x05, 0xc7, 0x04, 0xc3, 0x23, 0xd8, 0x71, 0x15, 0x31, 0xa5, 0x34, 0xf1, 0xe5, 0x3f, 0x36, 0xcc, 0xf7, 0xfd, 0xb7, 0x26, 0x93, 0xc1, 0x86, 0x9e, 0x1d, 0x35, 0x61, 0xb9, 0x57, 0x03, 0x48, 0x0e, 0xf6, 0x3e, 0x70, 0x66, 0xb5, 0xbd, 0x4b, 0x8a, 0x8b, 0xdd, 0xe8, 0x1f, 0x74, 0xa6, 0x1c, 0xc6, 0xb4, 0x78, 0xba, 0x2e, 0x25, 0x54, 0xb0, 0x16, 0xbb, 0x99, 0x41, 0x0f, 0x2d, 0xe6, 0xbf, 0x68, 0x42, 0xa1, 0x8c, 0x0d, 0x89, 0x55, 0xce, 0xdf, 0x28, 0x1e, 0x9b, 0xe9, 0x87, 0xd9, 0x69, 0x94, 0x8e, 0xf8, 0xe1, 0x11, 0x98, 0x5e, 0xde, 0xdb, 0x0b, 0xee, 0x46, 0x14, 0xb8, 0x2a, 0x22, 0x88, 0x90, 0x81, 0x60, 0xdc, 0x4f, 0x5d, 0x64, 0x73, 0x19, 0xa7, 0xc4, 0x3d, 0x7e, 0x97, 0x5f, 0x17, 0x44, 0x0c, 0xcd, 0xec, 0x13, 0x7a, 0x65, 0x08, 0xae, 0x56, 0x6c, 0xea, 0xf4, 0xd5, 0x8d, 0xa9, 0x4e, 0xc8, 0xe7, 0x6d, 0x37, 0x95, 0x91, 0x79, 0xe4, 0xd3, 0xc2, 0x62, 0xac, 0x06, 0x49, 0x5c, 0x24, 0x32, 0xe0, 0x0a, 0x3a +}, +{ +0x94, 0x8e, 0xd9, 0x69, 0x11, 0x98, 0xf8, 0xe1, 0xdf, 0x28, 0x55, 0xce, 0xe9, 0x87, 0x1e, 0x9b, 0x68, 0x42, 0xe6, 0xbf, 0x0d, 0x89, 0xa1, 0x8c, 0x16, 0xbb, 0x54, 0xb0, 0x0f, 0x2d, 0x99, 0x41, 0xc6, 0xb4, 0xa6, 0x1c, 0x2e, 0x25, 0x78, 0xba, 0x8a, 0x8b, 0xbd, 0x4b, 0x1f, 0x74, 0xdd, 0xe8, 0x0e, 0xf6, 0x03, 0x48, 0x66, 0xb5, 0x3e, 0x70, 0x9e, 0x1d, 0xc1, 0x86, 0xb9, 0x57, 0x35, 0x61, 0x5c, 0x24, 0x06, 0x49, 0x0a, 0x3a, 0x32, 0xe0, 0x79, 0xe4, 0x95, 0x91, 0x62, 0xac, 0xd3, 0xc2, 0xa9, 0x4e, 0xd5, 0x8d, 0x6d, 0x37, 0xc8, 0xe7, 0x08, 0xae, 0x7a, 0x65, 0xea, 0xf4, 0x56, 0x6c, 0x17, 0x44, 0x97, 0x5f, 0xec, 0x13, 0x0c, 0xcd, 0x73, 0x19, 0x5d, 0x64, 0x3d, 0x7e, 0xa7, 0xc4, 0x88, 0x90, 0x2a, 0x22, 0xdc, 0x4f, 0x81, 0x60, 0xdb, 0x0b, 0x5e, 0xde, 0x14, 0xb8, 0xee, 0x46, 0x85, 0x33, 0x4d, 0x43, 0xfb, 0xaa, 0xef, 0xd0, 0xa8, 0x9f, 0x3c, 0x50, 0x7f, 0x02, 0xf9, 0x45, 0xf5, 0x38, 0x9d, 0x92, 0x8f, 0x40, 0xa3, 0x51, 0xd2, 0xf3, 0xff, 0x10, 0x21, 0xda, 0xb6, 0xbc, 0xa0, 0x5a, 0x6e, 0x1b, 0x1a, 0x2c, 0x83, 0x09, 0x84, 0x2f, 0xe3, 0x29, 0xb3, 0xd6, 0x3b, 0x52, 0x5b, 0xb1, 0xfc, 0x20, 0xed, 0x00, 0xd1, 0x53, 0xcf, 0x58, 0x4c, 0x4a, 0x39, 0xbe, 0xcb, 0x6a, 0xcc, 0xf7, 0x3f, 0x36, 0x26, 0x93, 0xfd, 0xb7, 0x15, 0x31, 0xd8, 0x71, 0xf1, 0xe5, 0xa5, 0x34, 0x9a, 0x05, 0x96, 0x18, 0xc3, 0x23, 0xc7, 0x04, 0x75, 0xb2, 0x27, 0xeb, 0xe2, 0x80, 0x12, 0x07, 0xc5, 0x6f, 0x6b, 0xf2, 0x7b, 0x77, 0x7c, 0x63, 0x76, 0xab, 0xd7, 0xfe, 0x2b, 0x67, 0x01, 0x30, 0xf0, 0x47, 0x59, 0xfa, 0x7d, 0xc9, 0x82, 0xca, 0xc0, 0x72, 0xa4, 0x9c, 0xaf, 0xa2, 0xd4, 0xad +}, +{ +0xf1, 0xe5, 0xa5, 0x34, 0x15, 0x31, 0xd8, 0x71, 0x26, 0x93, 0xfd, 0xb7, 0xcc, 0xf7, 0x3f, 0x36, 0xe2, 0x80, 0x12, 0x07, 0x75, 0xb2, 0x27, 0xeb, 0xc3, 0x23, 0xc7, 0x04, 0x9a, 0x05, 0x96, 0x18, 0x2b, 0x67, 0x01, 0x30, 0x76, 0xab, 0xd7, 0xfe, 0x7b, 0x77, 0x7c, 0x63, 0xc5, 0x6f, 0x6b, 0xf2, 0xaf, 0xa2, 0xd4, 0xad, 0xc0, 0x72, 0xa4, 0x9c, 0x7d, 0xc9, 0x82, 0xca, 0xf0, 0x47, 0x59, 0xfa, 0x7f, 0x02, 0xf9, 0x45, 0xa8, 0x9f, 0x3c, 0x50, 0xfb, 0xaa, 0xef, 0xd0, 0x85, 0x33, 0x4d, 0x43, 0x21, 0xda, 0xb6, 0xbc, 0xd2, 0xf3, 0xff, 0x10, 0x8f, 0x40, 0xa3, 0x51, 0xf5, 0x38, 0x9d, 0x92, 0xb3, 0xd6, 0x3b, 0x52, 0x84, 0x2f, 0xe3, 0x29, 0x1a, 0x2c, 0x83, 0x09, 0xa0, 0x5a, 0x6e, 0x1b, 0x39, 0xbe, 0xcb, 0x6a, 0xcf, 0x58, 0x4c, 0x4a, 0xed, 0x00, 0xd1, 0x53, 0x5b, 0xb1, 0xfc, 0x20, 0x62, 0xac, 0xd3, 0xc2, 0x79, 0xe4, 0x95, 0x91, 0x0a, 0x3a, 0x32, 0xe0, 0x5c, 0x24, 0x06, 0x49, 0xea, 0xf4, 0x56, 0x6c, 0x08, 0xae, 0x7a, 0x65, 0x6d, 0x37, 0xc8, 0xe7, 0xa9, 0x4e, 0xd5, 0x8d, 0x3d, 0x7e, 0xa7, 0xc4, 0x73, 0x19, 0x5d, 0x64, 0xec, 0x13, 0x0c, 0xcd, 0x17, 0x44, 0x97, 0x5f, 0x14, 0xb8, 0xee, 0x46, 0xdb, 0x0b, 0x5e, 0xde, 0xdc, 0x4f, 0x81, 0x60, 0x88, 0x90, 0x2a, 0x22, 0xe9, 0x87, 0x1e, 0x9b, 0xdf, 0x28, 0x55, 0xce, 0x11, 0x98, 0xf8, 0xe1, 0x94, 0x8e, 0xd9, 0x69, 0x0f, 0x2d, 0x99, 0x41, 0x16, 0xbb, 0x54, 0xb0, 0x0d, 0x89, 0xa1, 0x8c, 0x68, 0x42, 0xe6, 0xbf, 0x1f, 0x74, 0xdd, 0xe8, 0x8a, 0x8b, 0xbd, 0x4b, 0x2e, 0x25, 0x78, 0xba, 0xc6, 0xb4, 0xa6, 0x1c, 0xb9, 0x57, 0x35, 0x61, 0x9e, 0x1d, 0xc1, 0x86, 0x66, 0xb5, 0x3e, 0x70, 0x0e, 0xf6, 0x03, 0x48 +}, +{ +0xff, 0x10, 0xd2, 0xf3, 0xb6, 0xbc, 0x21, 0xda, 0x9d, 0x92, 0xf5, 0x38, 0xa3, 0x51, 0x8f, 0x40, 0x3c, 0x50, 0xa8, 0x9f, 0xf9, 0x45, 0x7f, 0x02, 0x4d, 0x43, 0x85, 0x33, 0xef, 0xd0, 0xfb, 0xaa, 0x4c, 0x4a, 0xcf, 0x58, 0xcb, 0x6a, 0x39, 0xbe, 0xfc, 0x20, 0x5b, 0xb1, 0xd1, 0x53, 0xed, 0x00, 0xe3, 0x29, 0x84, 0x2f, 0x3b, 0x52, 0xb3, 0xd6, 0x6e, 0x1b, 0xa0, 0x5a, 0x83, 0x09, 0x1a, 0x2c, 0x27, 0xeb, 0x75, 0xb2, 0x12, 0x07, 0xe2, 0x80, 0x96, 0x18, 0x9a, 0x05, 0xc7, 0x04, 0xc3, 0x23, 0xd8, 0x71, 0x15, 0x31, 0xa5, 0x34, 0xf1, 0xe5, 0x3f, 0x36, 0xcc, 0xf7, 0xfd, 0xb7, 0x26, 0x93, 0xa4, 0x9c, 0xc0, 0x72, 0xd4, 0xad, 0xaf, 0xa2, 0x59, 0xfa, 0xf0, 0x47, 0x82, 0xca, 0x7d, 0xc9, 0xd7, 0xfe, 0x76, 0xab, 0x01, 0x30, 0x2b, 0x67, 0x6b, 0xf2, 0xc5, 0x6f, 0x7c, 0x63, 0x7b, 0x77, 0x54, 0xb0, 0x16, 0xbb, 0x99, 0x41, 0x0f, 0x2d, 0xe6, 0xbf, 0x68, 0x42, 0xa1, 0x8c, 0x0d, 0x89, 0x55, 0xce, 0xdf, 0x28, 0x1e, 0x9b, 0xe9, 0x87, 0xd9, 0x69, 0x94, 0x8e, 0xf8, 0xe1, 0x11, 0x98, 0xc1, 0x86, 0x9e, 0x1d, 0x35, 0x61, 0xb9, 0x57, 0x03, 0x48, 0x0e, 0xf6, 0x3e, 0x70, 0x66, 0xb5, 0xbd, 0x4b, 0x8a, 0x8b, 0xdd, 0xe8, 0x1f, 0x74, 0xa6, 0x1c, 0xc6, 0xb4, 0x78, 0xba, 0x2e, 0x25, 0x7a, 0x65, 0x08, 0xae, 0x56, 0x6c, 0xea, 0xf4, 0xd5, 0x8d, 0xa9, 0x4e, 0xc8, 0xe7, 0x6d, 0x37, 0x95, 0x91, 0x79, 0xe4, 0xd3, 0xc2, 0x62, 0xac, 0x06, 0x49, 0x5c, 0x24, 0x32, 0xe0, 0x0a, 0x3a, 0x5e, 0xde, 0xdb, 0x0b, 0xee, 0x46, 0x14, 0xb8, 0x2a, 0x22, 0x88, 0x90, 0x81, 0x60, 0xdc, 0x4f, 0x5d, 0x64, 0x73, 0x19, 0xa7, 0xc4, 0x3d, 0x7e, 0x97, 0x5f, 0x17, 0x44, 0x0c, 0xcd, 0xec, 0x13 +}, +{ +0x90, 0x88, 0x22, 0x2a, 0x4f, 0xdc, 0x60, 0x81, 0x0b, 0xdb, 0xde, 0x5e, 0xb8, 0x14, 0x46, 0xee, 0x44, 0x17, 0x5f, 0x97, 0x13, 0xec, 0xcd, 0x0c, 0x19, 0x73, 0x64, 0x5d, 0x7e, 0x3d, 0xc4, 0xa7, 0x4e, 0xa9, 0x8d, 0xd5, 0x37, 0x6d, 0xe7, 0xc8, 0xae, 0x08, 0x65, 0x7a, 0xf4, 0xea, 0x6c, 0x56, 0x24, 0x5c, 0x49, 0x06, 0x3a, 0x0a, 0xe0, 0x32, 0xe4, 0x79, 0x91, 0x95, 0xac, 0x62, 0xc2, 0xd3, 0xf6, 0x0e, 0x48, 0x03, 0xb5, 0x66, 0x70, 0x3e, 0x1d, 0x9e, 0x86, 0xc1, 0x57, 0xb9, 0x61, 0x35, 0xb4, 0xc6, 0x1c, 0xa6, 0x25, 0x2e, 0xba, 0x78, 0x8b, 0x8a, 0x4b, 0xbd, 0x74, 0x1f, 0xe8, 0xdd, 0x42, 0x68, 0xbf, 0xe6, 0x89, 0x0d, 0x8c, 0xa1, 0xbb, 0x16, 0xb0, 0x54, 0x2d, 0x0f, 0x41, 0x99, 0x8e, 0x94, 0x69, 0xd9, 0x98, 0x11, 0xe1, 0xf8, 0x28, 0xdf, 0xce, 0x55, 0x87, 0xe9, 0x9b, 0x1e, 0x47, 0xf0, 0xfa, 0x59, 0xc9, 0x7d, 0xca, 0x82, 0x72, 0xc0, 0x9c, 0xa4, 0xa2, 0xaf, 0xad, 0xd4, 0x6f, 0xc5, 0xf2, 0x6b, 0x77, 0x7b, 0x63, 0x7c, 0xab, 0x76, 0xfe, 0xd7, 0x67, 0x2b, 0x30, 0x01, 0x05, 0x9a, 0x18, 0x96, 0x23, 0xc3, 0x04, 0xc7, 0xb2, 0x75, 0xeb, 0x27, 0x80, 0xe2, 0x07, 0x12, 0xf7, 0xcc, 0x36, 0x3f, 0x93, 0x26, 0xb7, 0xfd, 0x31, 0x15, 0x71, 0xd8, 0xe5, 0xf1, 0x34, 0xa5, 0xb1, 0x5b, 0x20, 0xfc, 0x00, 0xed, 0x53, 0xd1, 0x58, 0xcf, 0x4a, 0x4c, 0xbe, 0x39, 0x6a, 0xcb, 0x5a, 0xa0, 0x1b, 0x6e, 0x2c, 0x1a, 0x09, 0x83, 0x2f, 0x84, 0x29, 0xe3, 0xd6, 0xb3, 0x52, 0x3b, 0x38, 0xf5, 0x92, 0x9d, 0x40, 0x8f, 0x51, 0xa3, 0xf3, 0xd2, 0x10, 0xff, 0xda, 0x21, 0xbc, 0xb6, 0x33, 0x85, 0x43, 0x4d, 0xaa, 0xfb, 0xd0, 0xef, 0x9f, 0xa8, 0x50, 0x3c, 0x02, 0x7f, 0x45, 0xf9 +}, +{ +0xd4, 0xad, 0xaf, 0xa2, 0xa4, 0x9c, 0xc0, 0x72, 0x82, 0xca, 0x7d, 0xc9, 0x59, 0xfa, 0xf0, 0x47, 0x01, 0x30, 0x2b, 0x67, 0xd7, 0xfe, 0x76, 0xab, 0x7c, 0x63, 0x7b, 0x77, 0x6b, 0xf2, 0xc5, 0x6f, 0x12, 0x07, 0xe2, 0x80, 0x27, 0xeb, 0x75, 0xb2, 0xc7, 0x04, 0xc3, 0x23, 0x96, 0x18, 0x9a, 0x05, 0xa5, 0x34, 0xf1, 0xe5, 0xd8, 0x71, 0x15, 0x31, 0xfd, 0xb7, 0x26, 0x93, 0x3f, 0x36, 0xcc, 0xf7, 0xcb, 0x6a, 0x39, 0xbe, 0x4c, 0x4a, 0xcf, 0x58, 0xd1, 0x53, 0xed, 0x00, 0xfc, 0x20, 0x5b, 0xb1, 0x3b, 0x52, 0xb3, 0xd6, 0xe3, 0x29, 0x84, 0x2f, 0x83, 0x09, 0x1a, 0x2c, 0x6e, 0x1b, 0xa0, 0x5a, 0xb6, 0xbc, 0x21, 0xda, 0xff, 0x10, 0xd2, 0xf3, 0xa3, 0x51, 0x8f, 0x40, 0x9d, 0x92, 0xf5, 0x38, 0xf9, 0x45, 0x7f, 0x02, 0x3c, 0x50, 0xa8, 0x9f, 0xef, 0xd0, 0xfb, 0xaa, 0x4d, 0x43, 0x85, 0x33, 0xee, 0x46, 0x14, 0xb8, 0x5e, 0xde, 0xdb, 0x0b, 0x81, 0x60, 0xdc, 0x4f, 0x2a, 0x22, 0x88, 0x90, 0xa7, 0xc4, 0x3d, 0x7e, 0x5d, 0x64, 0x73, 0x19, 0x0c, 0xcd, 0xec, 0x13, 0x97, 0x5f, 0x17, 0x44, 0x56, 0x6c, 0xea, 0xf4, 0x7a, 0x65, 0x08, 0xae, 0xc8, 0xe7, 0x6d, 0x37, 0xd5, 0x8d, 0xa9, 0x4e, 0xd3, 0xc2, 0x62, 0xac, 0x95, 0x91, 0x79, 0xe4, 0x32, 0xe0, 0x0a, 0x3a, 0x06, 0x49, 0x5c, 0x24, 0x35, 0x61, 0xb9, 0x57, 0xc1, 0x86, 0x9e, 0x1d, 0x3e, 0x70, 0x66, 0xb5, 0x03, 0x48, 0x0e, 0xf6, 0xdd, 0xe8, 0x1f, 0x74, 0xbd, 0x4b, 0x8a, 0x8b, 0x78, 0xba, 0x2e, 0x25, 0xa6, 0x1c, 0xc6, 0xb4, 0x99, 0x41, 0x0f, 0x2d, 0x54, 0xb0, 0x16, 0xbb, 0xa1, 0x8c, 0x0d, 0x89, 0xe6, 0xbf, 0x68, 0x42, 0x1e, 0x9b, 0xe9, 0x87, 0x55, 0xce, 0xdf, 0x28, 0xf8, 0xe1, 0x11, 0x98, 0xd9, 0x69, 0x94, 0x8e +}, +{ +0x8d, 0xd5, 0x4e, 0xa9, 0xe7, 0xc8, 0x37, 0x6d, 0x65, 0x7a, 0xae, 0x08, 0x6c, 0x56, 0xf4, 0xea, 0x49, 0x06, 0x24, 0x5c, 0xe0, 0x32, 0x3a, 0x0a, 0x91, 0x95, 0xe4, 0x79, 0xc2, 0xd3, 0xac, 0x62, 0x22, 0x2a, 0x90, 0x88, 0x60, 0x81, 0x4f, 0xdc, 0xde, 0x5e, 0x0b, 0xdb, 0x46, 0xee, 0xb8, 0x14, 0x5f, 0x97, 0x44, 0x17, 0xcd, 0x0c, 0x13, 0xec, 0x64, 0x5d, 0x19, 0x73, 0xc4, 0xa7, 0x7e, 0x3d, 0xbf, 0xe6, 0x42, 0x68, 0x8c, 0xa1, 0x89, 0x0d, 0xb0, 0x54, 0xbb, 0x16, 0x41, 0x99, 0x2d, 0x0f, 0x69, 0xd9, 0x8e, 0x94, 0xe1, 0xf8, 0x98, 0x11, 0xce, 0x55, 0x28, 0xdf, 0x9b, 0x1e, 0x87, 0xe9, 0x48, 0x03, 0xf6, 0x0e, 0x70, 0x3e, 0xb5, 0x66, 0x86, 0xc1, 0x1d, 0x9e, 0x61, 0x35, 0x57, 0xb9, 0x1c, 0xa6, 0xb4, 0xc6, 0xba, 0x78, 0x25, 0x2e, 0x4b, 0xbd, 0x8b, 0x8a, 0xe8, 0xdd, 0x74, 0x1f, 0x18, 0x96, 0x05, 0x9a, 0x04, 0xc7, 0x23, 0xc3, 0xeb, 0x27, 0xb2, 0x75, 0x07, 0x12, 0x80, 0xe2, 0x36, 0x3f, 0xf7, 0xcc, 0xb7, 0xfd, 0x93, 0x26, 0x71, 0xd8, 0x31, 0x15, 0x34, 0xa5, 0xe5, 0xf1, 0xfa, 0x59, 0x47, 0xf0, 0xca, 0x82, 0xc9, 0x7d, 0x9c, 0xa4, 0x72, 0xc0, 0xad, 0xd4, 0xa2, 0xaf, 0xf2, 0x6b, 0x6f, 0xc5, 0x63, 0x7c, 0x77, 0x7b, 0xfe, 0xd7, 0xab, 0x76, 0x30, 0x01, 0x67, 0x2b, 0x92, 0x9d, 0x38, 0xf5, 0x51, 0xa3, 0x40, 0x8f, 0x10, 0xff, 0xf3, 0xd2, 0xbc, 0xb6, 0xda, 0x21, 0x43, 0x4d, 0x33, 0x85, 0xd0, 0xef, 0xaa, 0xfb, 0x50, 0x3c, 0x9f, 0xa8, 0x45, 0xf9, 0x02, 0x7f, 0x20, 0xfc, 0xb1, 0x5b, 0x53, 0xd1, 0x00, 0xed, 0x4a, 0x4c, 0x58, 0xcf, 0x6a, 0xcb, 0xbe, 0x39, 0x1b, 0x6e, 0x5a, 0xa0, 0x09, 0x83, 0x2c, 0x1a, 0x29, 0xe3, 0x2f, 0x84, 0x52, 0x3b, 0xd6, 0xb3 +}, +{ +0xfe, 0xd7, 0xab, 0x76, 0x30, 0x01, 0x67, 0x2b, 0xf2, 0x6b, 0x6f, 0xc5, 0x63, 0x7c, 0x77, 0x7b, 0x9c, 0xa4, 0x72, 0xc0, 0xad, 0xd4, 0xa2, 0xaf, 0xfa, 0x59, 0x47, 0xf0, 0xca, 0x82, 0xc9, 0x7d, 0x71, 0xd8, 0x31, 0x15, 0x34, 0xa5, 0xe5, 0xf1, 0x36, 0x3f, 0xf7, 0xcc, 0xb7, 0xfd, 0x93, 0x26, 0xeb, 0x27, 0xb2, 0x75, 0x07, 0x12, 0x80, 0xe2, 0x18, 0x96, 0x05, 0x9a, 0x04, 0xc7, 0x23, 0xc3, 0x29, 0xe3, 0x2f, 0x84, 0x52, 0x3b, 0xd6, 0xb3, 0x1b, 0x6e, 0x5a, 0xa0, 0x09, 0x83, 0x2c, 0x1a, 0x4a, 0x4c, 0x58, 0xcf, 0x6a, 0xcb, 0xbe, 0x39, 0x20, 0xfc, 0xb1, 0x5b, 0x53, 0xd1, 0x00, 0xed, 0x50, 0x3c, 0x9f, 0xa8, 0x45, 0xf9, 0x02, 0x7f, 0x43, 0x4d, 0x33, 0x85, 0xd0, 0xef, 0xaa, 0xfb, 0x10, 0xff, 0xf3, 0xd2, 0xbc, 0xb6, 0xda, 0x21, 0x92, 0x9d, 0x38, 0xf5, 0x51, 0xa3, 0x40, 0x8f, 0x64, 0x5d, 0x19, 0x73, 0xc4, 0xa7, 0x7e, 0x3d, 0x5f, 0x97, 0x44, 0x17, 0xcd, 0x0c, 0x13, 0xec, 0xde, 0x5e, 0x0b, 0xdb, 0x46, 0xee, 0xb8, 0x14, 0x22, 0x2a, 0x90, 0x88, 0x60, 0x81, 0x4f, 0xdc, 0x91, 0x95, 0xe4, 0x79, 0xc2, 0xd3, 0xac, 0x62, 0x49, 0x06, 0x24, 0x5c, 0xe0, 0x32, 0x3a, 0x0a, 0x65, 0x7a, 0xae, 0x08, 0x6c, 0x56, 0xf4, 0xea, 0x8d, 0xd5, 0x4e, 0xa9, 0xe7, 0xc8, 0x37, 0x6d, 0x4b, 0xbd, 0x8b, 0x8a, 0xe8, 0xdd, 0x74, 0x1f, 0x1c, 0xa6, 0xb4, 0xc6, 0xba, 0x78, 0x25, 0x2e, 0x86, 0xc1, 0x1d, 0x9e, 0x61, 0x35, 0x57, 0xb9, 0x48, 0x03, 0xf6, 0x0e, 0x70, 0x3e, 0xb5, 0x66, 0xce, 0x55, 0x28, 0xdf, 0x9b, 0x1e, 0x87, 0xe9, 0x69, 0xd9, 0x8e, 0x94, 0xe1, 0xf8, 0x98, 0x11, 0xb0, 0x54, 0xbb, 0x16, 0x41, 0x99, 0x2d, 0x0f, 0xbf, 0xe6, 0x42, 0x68, 0x8c, 0xa1, 0x89, 0x0d +}, +{ +0xa8, 0x9f, 0x3c, 0x50, 0x7f, 0x02, 0xf9, 0x45, 0x85, 0x33, 0x4d, 0x43, 0xfb, 0xaa, 0xef, 0xd0, 0xd2, 0xf3, 0xff, 0x10, 0x21, 0xda, 0xb6, 0xbc, 0xf5, 0x38, 0x9d, 0x92, 0x8f, 0x40, 0xa3, 0x51, 0x84, 0x2f, 0xe3, 0x29, 0xb3, 0xd6, 0x3b, 0x52, 0xa0, 0x5a, 0x6e, 0x1b, 0x1a, 0x2c, 0x83, 0x09, 0xcf, 0x58, 0x4c, 0x4a, 0x39, 0xbe, 0xcb, 0x6a, 0x5b, 0xb1, 0xfc, 0x20, 0xed, 0x00, 0xd1, 0x53, 0x15, 0x31, 0xd8, 0x71, 0xf1, 0xe5, 0xa5, 0x34, 0xcc, 0xf7, 0x3f, 0x36, 0x26, 0x93, 0xfd, 0xb7, 0x75, 0xb2, 0x27, 0xeb, 0xe2, 0x80, 0x12, 0x07, 0x9a, 0x05, 0x96, 0x18, 0xc3, 0x23, 0xc7, 0x04, 0x76, 0xab, 0xd7, 0xfe, 0x2b, 0x67, 0x01, 0x30, 0xc5, 0x6f, 0x6b, 0xf2, 0x7b, 0x77, 0x7c, 0x63, 0xc0, 0x72, 0xa4, 0x9c, 0xaf, 0xa2, 0xd4, 0xad, 0xf0, 0x47, 0x59, 0xfa, 0x7d, 0xc9, 0x82, 0xca, 0xdf, 0x28, 0x55, 0xce, 0xe9, 0x87, 0x1e, 0x9b, 0x94, 0x8e, 0xd9, 0x69, 0x11, 0x98, 0xf8, 0xe1, 0x16, 0xbb, 0x54, 0xb0, 0x0f, 0x2d, 0x99, 0x41, 0x68, 0x42, 0xe6, 0xbf, 0x0d, 0x89, 0xa1, 0x8c, 0x8a, 0x8b, 0xbd, 0x4b, 0x1f, 0x74, 0xdd, 0xe8, 0xc6, 0xb4, 0xa6, 0x1c, 0x2e, 0x25, 0x78, 0xba, 0x9e, 0x1d, 0xc1, 0x86, 0xb9, 0x57, 0x35, 0x61, 0x0e, 0xf6, 0x03, 0x48, 0x66, 0xb5, 0x3e, 0x70, 0x79, 0xe4, 0x95, 0x91, 0x62, 0xac, 0xd3, 0xc2, 0x5c, 0x24, 0x06, 0x49, 0x0a, 0x3a, 0x32, 0xe0, 0x08, 0xae, 0x7a, 0x65, 0xea, 0xf4, 0x56, 0x6c, 0xa9, 0x4e, 0xd5, 0x8d, 0x6d, 0x37, 0xc8, 0xe7, 0x73, 0x19, 0x5d, 0x64, 0x3d, 0x7e, 0xa7, 0xc4, 0x17, 0x44, 0x97, 0x5f, 0xec, 0x13, 0x0c, 0xcd, 0xdb, 0x0b, 0x5e, 0xde, 0x14, 0xb8, 0xee, 0x46, 0x88, 0x90, 0x2a, 0x22, 0xdc, 0x4f, 0x81, 0x60 +}, +{ +0x15, 0x31, 0xd8, 0x71, 0xf1, 0xe5, 0xa5, 0x34, 0xcc, 0xf7, 0x3f, 0x36, 0x26, 0x93, 0xfd, 0xb7, 0x75, 0xb2, 0x27, 0xeb, 0xe2, 0x80, 0x12, 0x07, 0x9a, 0x05, 0x96, 0x18, 0xc3, 0x23, 0xc7, 0x04, 0x76, 0xab, 0xd7, 0xfe, 0x2b, 0x67, 0x01, 0x30, 0xc5, 0x6f, 0x6b, 0xf2, 0x7b, 0x77, 0x7c, 0x63, 0xc0, 0x72, 0xa4, 0x9c, 0xaf, 0xa2, 0xd4, 0xad, 0xf0, 0x47, 0x59, 0xfa, 0x7d, 0xc9, 0x82, 0xca, 0xa8, 0x9f, 0x3c, 0x50, 0x7f, 0x02, 0xf9, 0x45, 0x85, 0x33, 0x4d, 0x43, 0xfb, 0xaa, 0xef, 0xd0, 0xd2, 0xf3, 0xff, 0x10, 0x21, 0xda, 0xb6, 0xbc, 0xf5, 0x38, 0x9d, 0x92, 0x8f, 0x40, 0xa3, 0x51, 0x84, 0x2f, 0xe3, 0x29, 0xb3, 0xd6, 0x3b, 0x52, 0xa0, 0x5a, 0x6e, 0x1b, 0x1a, 0x2c, 0x83, 0x09, 0xcf, 0x58, 0x4c, 0x4a, 0x39, 0xbe, 0xcb, 0x6a, 0x5b, 0xb1, 0xfc, 0x20, 0xed, 0x00, 0xd1, 0x53, 0x79, 0xe4, 0x95, 0x91, 0x62, 0xac, 0xd3, 0xc2, 0x5c, 0x24, 0x06, 0x49, 0x0a, 0x3a, 0x32, 0xe0, 0x08, 0xae, 0x7a, 0x65, 0xea, 0xf4, 0x56, 0x6c, 0xa9, 0x4e, 0xd5, 0x8d, 0x6d, 0x37, 0xc8, 0xe7, 0x73, 0x19, 0x5d, 0x64, 0x3d, 0x7e, 0xa7, 0xc4, 0x17, 0x44, 0x97, 0x5f, 0xec, 0x13, 0x0c, 0xcd, 0xdb, 0x0b, 0x5e, 0xde, 0x14, 0xb8, 0xee, 0x46, 0x88, 0x90, 0x2a, 0x22, 0xdc, 0x4f, 0x81, 0x60, 0xdf, 0x28, 0x55, 0xce, 0xe9, 0x87, 0x1e, 0x9b, 0x94, 0x8e, 0xd9, 0x69, 0x11, 0x98, 0xf8, 0xe1, 0x16, 0xbb, 0x54, 0xb0, 0x0f, 0x2d, 0x99, 0x41, 0x68, 0x42, 0xe6, 0xbf, 0x0d, 0x89, 0xa1, 0x8c, 0x8a, 0x8b, 0xbd, 0x4b, 0x1f, 0x74, 0xdd, 0xe8, 0xc6, 0xb4, 0xa6, 0x1c, 0x2e, 0x25, 0x78, 0xba, 0x9e, 0x1d, 0xc1, 0x86, 0xb9, 0x57, 0x35, 0x61, 0x0e, 0xf6, 0x03, 0x48, 0x66, 0xb5, 0x3e, 0x70 +}, +{ +0xd9, 0x69, 0x94, 0x8e, 0xf8, 0xe1, 0x11, 0x98, 0x55, 0xce, 0xdf, 0x28, 0x1e, 0x9b, 0xe9, 0x87, 0xe6, 0xbf, 0x68, 0x42, 0xa1, 0x8c, 0x0d, 0x89, 0x54, 0xb0, 0x16, 0xbb, 0x99, 0x41, 0x0f, 0x2d, 0xa6, 0x1c, 0xc6, 0xb4, 0x78, 0xba, 0x2e, 0x25, 0xbd, 0x4b, 0x8a, 0x8b, 0xdd, 0xe8, 0x1f, 0x74, 0x03, 0x48, 0x0e, 0xf6, 0x3e, 0x70, 0x66, 0xb5, 0xc1, 0x86, 0x9e, 0x1d, 0x35, 0x61, 0xb9, 0x57, 0x06, 0x49, 0x5c, 0x24, 0x32, 0xe0, 0x0a, 0x3a, 0x95, 0x91, 0x79, 0xe4, 0xd3, 0xc2, 0x62, 0xac, 0xd5, 0x8d, 0xa9, 0x4e, 0xc8, 0xe7, 0x6d, 0x37, 0x7a, 0x65, 0x08, 0xae, 0x56, 0x6c, 0xea, 0xf4, 0x97, 0x5f, 0x17, 0x44, 0x0c, 0xcd, 0xec, 0x13, 0x5d, 0x64, 0x73, 0x19, 0xa7, 0xc4, 0x3d, 0x7e, 0x2a, 0x22, 0x88, 0x90, 0x81, 0x60, 0xdc, 0x4f, 0x5e, 0xde, 0xdb, 0x0b, 0xee, 0x46, 0x14, 0xb8, 0x4d, 0x43, 0x85, 0x33, 0xef, 0xd0, 0xfb, 0xaa, 0x3c, 0x50, 0xa8, 0x9f, 0xf9, 0x45, 0x7f, 0x02, 0x9d, 0x92, 0xf5, 0x38, 0xa3, 0x51, 0x8f, 0x40, 0xff, 0x10, 0xd2, 0xf3, 0xb6, 0xbc, 0x21, 0xda, 0x6e, 0x1b, 0xa0, 0x5a, 0x83, 0x09, 0x1a, 0x2c, 0xe3, 0x29, 0x84, 0x2f, 0x3b, 0x52, 0xb3, 0xd6, 0xfc, 0x20, 0x5b, 0xb1, 0xd1, 0x53, 0xed, 0x00, 0x4c, 0x4a, 0xcf, 0x58, 0xcb, 0x6a, 0x39, 0xbe, 0x3f, 0x36, 0xcc, 0xf7, 0xfd, 0xb7, 0x26, 0x93, 0xd8, 0x71, 0x15, 0x31, 0xa5, 0x34, 0xf1, 0xe5, 0x96, 0x18, 0x9a, 0x05, 0xc7, 0x04, 0xc3, 0x23, 0x27, 0xeb, 0x75, 0xb2, 0x12, 0x07, 0xe2, 0x80, 0x6b, 0xf2, 0xc5, 0x6f, 0x7c, 0x63, 0x7b, 0x77, 0xd7, 0xfe, 0x76, 0xab, 0x01, 0x30, 0x2b, 0x67, 0x59, 0xfa, 0xf0, 0x47, 0x82, 0xca, 0x7d, 0xc9, 0xa4, 0x9c, 0xc0, 0x72, 0xd4, 0xad, 0xaf, 0xa2 +}, +{ +0x58, 0xcf, 0x4a, 0x4c, 0xbe, 0x39, 0x6a, 0xcb, 0xb1, 0x5b, 0x20, 0xfc, 0x00, 0xed, 0x53, 0xd1, 0x2f, 0x84, 0x29, 0xe3, 0xd6, 0xb3, 0x52, 0x3b, 0x5a, 0xa0, 0x1b, 0x6e, 0x2c, 0x1a, 0x09, 0x83, 0xf3, 0xd2, 0x10, 0xff, 0xda, 0x21, 0xbc, 0xb6, 0x38, 0xf5, 0x92, 0x9d, 0x40, 0x8f, 0x51, 0xa3, 0x9f, 0xa8, 0x50, 0x3c, 0x02, 0x7f, 0x45, 0xf9, 0x33, 0x85, 0x43, 0x4d, 0xaa, 0xfb, 0xd0, 0xef, 0x72, 0xc0, 0x9c, 0xa4, 0xa2, 0xaf, 0xad, 0xd4, 0x47, 0xf0, 0xfa, 0x59, 0xc9, 0x7d, 0xca, 0x82, 0xab, 0x76, 0xfe, 0xd7, 0x67, 0x2b, 0x30, 0x01, 0x6f, 0xc5, 0xf2, 0x6b, 0x77, 0x7b, 0x63, 0x7c, 0xb2, 0x75, 0xeb, 0x27, 0x80, 0xe2, 0x07, 0x12, 0x05, 0x9a, 0x18, 0x96, 0x23, 0xc3, 0x04, 0xc7, 0x31, 0x15, 0x71, 0xd8, 0xe5, 0xf1, 0x34, 0xa5, 0xf7, 0xcc, 0x36, 0x3f, 0x93, 0x26, 0xb7, 0xfd, 0x1d, 0x9e, 0x86, 0xc1, 0x57, 0xb9, 0x61, 0x35, 0xf6, 0x0e, 0x48, 0x03, 0xb5, 0x66, 0x70, 0x3e, 0x8b, 0x8a, 0x4b, 0xbd, 0x74, 0x1f, 0xe8, 0xdd, 0xb4, 0xc6, 0x1c, 0xa6, 0x25, 0x2e, 0xba, 0x78, 0xbb, 0x16, 0xb0, 0x54, 0x2d, 0x0f, 0x41, 0x99, 0x42, 0x68, 0xbf, 0xe6, 0x89, 0x0d, 0x8c, 0xa1, 0x28, 0xdf, 0xce, 0x55, 0x87, 0xe9, 0x9b, 0x1e, 0x8e, 0x94, 0x69, 0xd9, 0x98, 0x11, 0xe1, 0xf8, 0x0b, 0xdb, 0xde, 0x5e, 0xb8, 0x14, 0x46, 0xee, 0x90, 0x88, 0x22, 0x2a, 0x4f, 0xdc, 0x60, 0x81, 0x19, 0x73, 0x64, 0x5d, 0x7e, 0x3d, 0xc4, 0xa7, 0x44, 0x17, 0x5f, 0x97, 0x13, 0xec, 0xcd, 0x0c, 0xae, 0x08, 0x65, 0x7a, 0xf4, 0xea, 0x6c, 0x56, 0x4e, 0xa9, 0x8d, 0xd5, 0x37, 0x6d, 0xe7, 0xc8, 0xe4, 0x79, 0x91, 0x95, 0xac, 0x62, 0xc2, 0xd3, 0x24, 0x5c, 0x49, 0x06, 0x3a, 0x0a, 0xe0, 0x32 +} +}, +{ +{ +0x1f, 0x74, 0xdd, 0xe8, 0x8a, 0x8b, 0xbd, 0x4b, 0x2e, 0x25, 0x78, 0xba, 0xc6, 0xb4, 0xa6, 0x1c, 0xb9, 0x57, 0x35, 0x61, 0x9e, 0x1d, 0xc1, 0x86, 0x66, 0xb5, 0x3e, 0x70, 0x0e, 0xf6, 0x03, 0x48, 0xe9, 0x87, 0x1e, 0x9b, 0xdf, 0x28, 0x55, 0xce, 0x11, 0x98, 0xf8, 0xe1, 0x94, 0x8e, 0xd9, 0x69, 0x0f, 0x2d, 0x99, 0x41, 0x16, 0xbb, 0x54, 0xb0, 0x0d, 0x89, 0xa1, 0x8c, 0x68, 0x42, 0xe6, 0xbf, 0x3d, 0x7e, 0xa7, 0xc4, 0x73, 0x19, 0x5d, 0x64, 0xec, 0x13, 0x0c, 0xcd, 0x17, 0x44, 0x97, 0x5f, 0x14, 0xb8, 0xee, 0x46, 0xdb, 0x0b, 0x5e, 0xde, 0xdc, 0x4f, 0x81, 0x60, 0x88, 0x90, 0x2a, 0x22, 0x62, 0xac, 0xd3, 0xc2, 0x79, 0xe4, 0x95, 0x91, 0x0a, 0x3a, 0x32, 0xe0, 0x5c, 0x24, 0x06, 0x49, 0xea, 0xf4, 0x56, 0x6c, 0x08, 0xae, 0x7a, 0x65, 0x6d, 0x37, 0xc8, 0xe7, 0xa9, 0x4e, 0xd5, 0x8d, 0xb3, 0xd6, 0x3b, 0x52, 0x84, 0x2f, 0xe3, 0x29, 0x1a, 0x2c, 0x83, 0x09, 0xa0, 0x5a, 0x6e, 0x1b, 0x39, 0xbe, 0xcb, 0x6a, 0xcf, 0x58, 0x4c, 0x4a, 0xed, 0x00, 0xd1, 0x53, 0x5b, 0xb1, 0xfc, 0x20, 0x7f, 0x02, 0xf9, 0x45, 0xa8, 0x9f, 0x3c, 0x50, 0xfb, 0xaa, 0xef, 0xd0, 0x85, 0x33, 0x4d, 0x43, 0x21, 0xda, 0xb6, 0xbc, 0xd2, 0xf3, 0xff, 0x10, 0x8f, 0x40, 0xa3, 0x51, 0xf5, 0x38, 0x9d, 0x92, 0x2b, 0x67, 0x01, 0x30, 0x76, 0xab, 0xd7, 0xfe, 0x7b, 0x77, 0x7c, 0x63, 0xc5, 0x6f, 0x6b, 0xf2, 0xaf, 0xa2, 0xd4, 0xad, 0xc0, 0x72, 0xa4, 0x9c, 0x7d, 0xc9, 0x82, 0xca, 0xf0, 0x47, 0x59, 0xfa, 0xf1, 0xe5, 0xa5, 0x34, 0x15, 0x31, 0xd8, 0x71, 0x26, 0x93, 0xfd, 0xb7, 0xcc, 0xf7, 0x3f, 0x36, 0xe2, 0x80, 0x12, 0x07, 0x75, 0xb2, 0x27, 0xeb, 0xc3, 0x23, 0xc7, 0x04, 0x9a, 0x05, 0x96, 0x18 +}, +{ +0x6d, 0x37, 0xc8, 0xe7, 0xa9, 0x4e, 0xd5, 0x8d, 0xea, 0xf4, 0x56, 0x6c, 0x08, 0xae, 0x7a, 0x65, 0x0a, 0x3a, 0x32, 0xe0, 0x5c, 0x24, 0x06, 0x49, 0x62, 0xac, 0xd3, 0xc2, 0x79, 0xe4, 0x95, 0x91, 0xdc, 0x4f, 0x81, 0x60, 0x88, 0x90, 0x2a, 0x22, 0x14, 0xb8, 0xee, 0x46, 0xdb, 0x0b, 0x5e, 0xde, 0xec, 0x13, 0x0c, 0xcd, 0x17, 0x44, 0x97, 0x5f, 0x3d, 0x7e, 0xa7, 0xc4, 0x73, 0x19, 0x5d, 0x64, 0x0d, 0x89, 0xa1, 0x8c, 0x68, 0x42, 0xe6, 0xbf, 0x0f, 0x2d, 0x99, 0x41, 0x16, 0xbb, 0x54, 0xb0, 0x11, 0x98, 0xf8, 0xe1, 0x94, 0x8e, 0xd9, 0x69, 0xe9, 0x87, 0x1e, 0x9b, 0xdf, 0x28, 0x55, 0xce, 0x66, 0xb5, 0x3e, 0x70, 0x0e, 0xf6, 0x03, 0x48, 0xb9, 0x57, 0x35, 0x61, 0x9e, 0x1d, 0xc1, 0x86, 0x2e, 0x25, 0x78, 0xba, 0xc6, 0xb4, 0xa6, 0x1c, 0x1f, 0x74, 0xdd, 0xe8, 0x8a, 0x8b, 0xbd, 0x4b, 0xc3, 0x23, 0xc7, 0x04, 0x9a, 0x05, 0x96, 0x18, 0xe2, 0x80, 0x12, 0x07, 0x75, 0xb2, 0x27, 0xeb, 0x26, 0x93, 0xfd, 0xb7, 0xcc, 0xf7, 0x3f, 0x36, 0xf1, 0xe5, 0xa5, 0x34, 0x15, 0x31, 0xd8, 0x71, 0x7d, 0xc9, 0x82, 0xca, 0xf0, 0x47, 0x59, 0xfa, 0xaf, 0xa2, 0xd4, 0xad, 0xc0, 0x72, 0xa4, 0x9c, 0x7b, 0x77, 0x7c, 0x63, 0xc5, 0x6f, 0x6b, 0xf2, 0x2b, 0x67, 0x01, 0x30, 0x76, 0xab, 0xd7, 0xfe, 0x8f, 0x40, 0xa3, 0x51, 0xf5, 0x38, 0x9d, 0x92, 0x21, 0xda, 0xb6, 0xbc, 0xd2, 0xf3, 0xff, 0x10, 0xfb, 0xaa, 0xef, 0xd0, 0x85, 0x33, 0x4d, 0x43, 0x7f, 0x02, 0xf9, 0x45, 0xa8, 0x9f, 0x3c, 0x50, 0xed, 0x00, 0xd1, 0x53, 0x5b, 0xb1, 0xfc, 0x20, 0x39, 0xbe, 0xcb, 0x6a, 0xcf, 0x58, 0x4c, 0x4a, 0x1a, 0x2c, 0x83, 0x09, 0xa0, 0x5a, 0x6e, 0x1b, 0xb3, 0xd6, 0x3b, 0x52, 0x84, 0x2f, 0xe3, 0x29 +}, +{ +0x2b, 0x67, 0x01, 0x30, 0x76, 0xab, 0xd7, 0xfe, 0x7b, 0x77, 0x7c, 0x63, 0xc5, 0x6f, 0x6b, 0xf2, 0xaf, 0xa2, 0xd4, 0xad, 0xc0, 0x72, 0xa4, 0x9c, 0x7d, 0xc9, 0x82, 0xca, 0xf0, 0x47, 0x59, 0xfa, 0xf1, 0xe5, 0xa5, 0x34, 0x15, 0x31, 0xd8, 0x71, 0x26, 0x93, 0xfd, 0xb7, 0xcc, 0xf7, 0x3f, 0x36, 0xe2, 0x80, 0x12, 0x07, 0x75, 0xb2, 0x27, 0xeb, 0xc3, 0x23, 0xc7, 0x04, 0x9a, 0x05, 0x96, 0x18, 0xb3, 0xd6, 0x3b, 0x52, 0x84, 0x2f, 0xe3, 0x29, 0x1a, 0x2c, 0x83, 0x09, 0xa0, 0x5a, 0x6e, 0x1b, 0x39, 0xbe, 0xcb, 0x6a, 0xcf, 0x58, 0x4c, 0x4a, 0xed, 0x00, 0xd1, 0x53, 0x5b, 0xb1, 0xfc, 0x20, 0x7f, 0x02, 0xf9, 0x45, 0xa8, 0x9f, 0x3c, 0x50, 0xfb, 0xaa, 0xef, 0xd0, 0x85, 0x33, 0x4d, 0x43, 0x21, 0xda, 0xb6, 0xbc, 0xd2, 0xf3, 0xff, 0x10, 0x8f, 0x40, 0xa3, 0x51, 0xf5, 0x38, 0x9d, 0x92, 0x3d, 0x7e, 0xa7, 0xc4, 0x73, 0x19, 0x5d, 0x64, 0xec, 0x13, 0x0c, 0xcd, 0x17, 0x44, 0x97, 0x5f, 0x14, 0xb8, 0xee, 0x46, 0xdb, 0x0b, 0x5e, 0xde, 0xdc, 0x4f, 0x81, 0x60, 0x88, 0x90, 0x2a, 0x22, 0x62, 0xac, 0xd3, 0xc2, 0x79, 0xe4, 0x95, 0x91, 0x0a, 0x3a, 0x32, 0xe0, 0x5c, 0x24, 0x06, 0x49, 0xea, 0xf4, 0x56, 0x6c, 0x08, 0xae, 0x7a, 0x65, 0x6d, 0x37, 0xc8, 0xe7, 0xa9, 0x4e, 0xd5, 0x8d, 0x1f, 0x74, 0xdd, 0xe8, 0x8a, 0x8b, 0xbd, 0x4b, 0x2e, 0x25, 0x78, 0xba, 0xc6, 0xb4, 0xa6, 0x1c, 0xb9, 0x57, 0x35, 0x61, 0x9e, 0x1d, 0xc1, 0x86, 0x66, 0xb5, 0x3e, 0x70, 0x0e, 0xf6, 0x03, 0x48, 0xe9, 0x87, 0x1e, 0x9b, 0xdf, 0x28, 0x55, 0xce, 0x11, 0x98, 0xf8, 0xe1, 0x94, 0x8e, 0xd9, 0x69, 0x0f, 0x2d, 0x99, 0x41, 0x16, 0xbb, 0x54, 0xb0, 0x0d, 0x89, 0xa1, 0x8c, 0x68, 0x42, 0xe6, 0xbf +}, +{ +0xdd, 0xe8, 0x1f, 0x74, 0xbd, 0x4b, 0x8a, 0x8b, 0x78, 0xba, 0x2e, 0x25, 0xa6, 0x1c, 0xc6, 0xb4, 0x35, 0x61, 0xb9, 0x57, 0xc1, 0x86, 0x9e, 0x1d, 0x3e, 0x70, 0x66, 0xb5, 0x03, 0x48, 0x0e, 0xf6, 0x1e, 0x9b, 0xe9, 0x87, 0x55, 0xce, 0xdf, 0x28, 0xf8, 0xe1, 0x11, 0x98, 0xd9, 0x69, 0x94, 0x8e, 0x99, 0x41, 0x0f, 0x2d, 0x54, 0xb0, 0x16, 0xbb, 0xa1, 0x8c, 0x0d, 0x89, 0xe6, 0xbf, 0x68, 0x42, 0xa7, 0xc4, 0x3d, 0x7e, 0x5d, 0x64, 0x73, 0x19, 0x0c, 0xcd, 0xec, 0x13, 0x97, 0x5f, 0x17, 0x44, 0xee, 0x46, 0x14, 0xb8, 0x5e, 0xde, 0xdb, 0x0b, 0x81, 0x60, 0xdc, 0x4f, 0x2a, 0x22, 0x88, 0x90, 0xd3, 0xc2, 0x62, 0xac, 0x95, 0x91, 0x79, 0xe4, 0x32, 0xe0, 0x0a, 0x3a, 0x06, 0x49, 0x5c, 0x24, 0x56, 0x6c, 0xea, 0xf4, 0x7a, 0x65, 0x08, 0xae, 0xc8, 0xe7, 0x6d, 0x37, 0xd5, 0x8d, 0xa9, 0x4e, 0x3b, 0x52, 0xb3, 0xd6, 0xe3, 0x29, 0x84, 0x2f, 0x83, 0x09, 0x1a, 0x2c, 0x6e, 0x1b, 0xa0, 0x5a, 0xcb, 0x6a, 0x39, 0xbe, 0x4c, 0x4a, 0xcf, 0x58, 0xd1, 0x53, 0xed, 0x00, 0xfc, 0x20, 0x5b, 0xb1, 0xf9, 0x45, 0x7f, 0x02, 0x3c, 0x50, 0xa8, 0x9f, 0xef, 0xd0, 0xfb, 0xaa, 0x4d, 0x43, 0x85, 0x33, 0xb6, 0xbc, 0x21, 0xda, 0xff, 0x10, 0xd2, 0xf3, 0xa3, 0x51, 0x8f, 0x40, 0x9d, 0x92, 0xf5, 0x38, 0x01, 0x30, 0x2b, 0x67, 0xd7, 0xfe, 0x76, 0xab, 0x7c, 0x63, 0x7b, 0x77, 0x6b, 0xf2, 0xc5, 0x6f, 0xd4, 0xad, 0xaf, 0xa2, 0xa4, 0x9c, 0xc0, 0x72, 0x82, 0xca, 0x7d, 0xc9, 0x59, 0xfa, 0xf0, 0x47, 0xa5, 0x34, 0xf1, 0xe5, 0xd8, 0x71, 0x15, 0x31, 0xfd, 0xb7, 0x26, 0x93, 0x3f, 0x36, 0xcc, 0xf7, 0x12, 0x07, 0xe2, 0x80, 0x27, 0xeb, 0x75, 0xb2, 0xc7, 0x04, 0xc3, 0x23, 0x96, 0x18, 0x9a, 0x05 +}, +{ +0x90, 0x88, 0x22, 0x2a, 0x4f, 0xdc, 0x60, 0x81, 0x0b, 0xdb, 0xde, 0x5e, 0xb8, 0x14, 0x46, 0xee, 0x44, 0x17, 0x5f, 0x97, 0x13, 0xec, 0xcd, 0x0c, 0x19, 0x73, 0x64, 0x5d, 0x7e, 0x3d, 0xc4, 0xa7, 0x4e, 0xa9, 0x8d, 0xd5, 0x37, 0x6d, 0xe7, 0xc8, 0xae, 0x08, 0x65, 0x7a, 0xf4, 0xea, 0x6c, 0x56, 0x24, 0x5c, 0x49, 0x06, 0x3a, 0x0a, 0xe0, 0x32, 0xe4, 0x79, 0x91, 0x95, 0xac, 0x62, 0xc2, 0xd3, 0xf6, 0x0e, 0x48, 0x03, 0xb5, 0x66, 0x70, 0x3e, 0x1d, 0x9e, 0x86, 0xc1, 0x57, 0xb9, 0x61, 0x35, 0xb4, 0xc6, 0x1c, 0xa6, 0x25, 0x2e, 0xba, 0x78, 0x8b, 0x8a, 0x4b, 0xbd, 0x74, 0x1f, 0xe8, 0xdd, 0x42, 0x68, 0xbf, 0xe6, 0x89, 0x0d, 0x8c, 0xa1, 0xbb, 0x16, 0xb0, 0x54, 0x2d, 0x0f, 0x41, 0x99, 0x8e, 0x94, 0x69, 0xd9, 0x98, 0x11, 0xe1, 0xf8, 0x28, 0xdf, 0xce, 0x55, 0x87, 0xe9, 0x9b, 0x1e, 0x47, 0xf0, 0xfa, 0x59, 0xc9, 0x7d, 0xca, 0x82, 0x72, 0xc0, 0x9c, 0xa4, 0xa2, 0xaf, 0xad, 0xd4, 0x6f, 0xc5, 0xf2, 0x6b, 0x77, 0x7b, 0x63, 0x7c, 0xab, 0x76, 0xfe, 0xd7, 0x67, 0x2b, 0x30, 0x01, 0x05, 0x9a, 0x18, 0x96, 0x23, 0xc3, 0x04, 0xc7, 0xb2, 0x75, 0xeb, 0x27, 0x80, 0xe2, 0x07, 0x12, 0xf7, 0xcc, 0x36, 0x3f, 0x93, 0x26, 0xb7, 0xfd, 0x31, 0x15, 0x71, 0xd8, 0xe5, 0xf1, 0x34, 0xa5, 0xb1, 0x5b, 0x20, 0xfc, 0x00, 0xed, 0x53, 0xd1, 0x58, 0xcf, 0x4a, 0x4c, 0xbe, 0x39, 0x6a, 0xcb, 0x5a, 0xa0, 0x1b, 0x6e, 0x2c, 0x1a, 0x09, 0x83, 0x2f, 0x84, 0x29, 0xe3, 0xd6, 0xb3, 0x52, 0x3b, 0x38, 0xf5, 0x92, 0x9d, 0x40, 0x8f, 0x51, 0xa3, 0xf3, 0xd2, 0x10, 0xff, 0xda, 0x21, 0xbc, 0xb6, 0x33, 0x85, 0x43, 0x4d, 0xaa, 0xfb, 0xd0, 0xef, 0x9f, 0xa8, 0x50, 0x3c, 0x02, 0x7f, 0x45, 0xf9 +}, +{ +0x20, 0xfc, 0xb1, 0x5b, 0x53, 0xd1, 0x00, 0xed, 0x4a, 0x4c, 0x58, 0xcf, 0x6a, 0xcb, 0xbe, 0x39, 0x1b, 0x6e, 0x5a, 0xa0, 0x09, 0x83, 0x2c, 0x1a, 0x29, 0xe3, 0x2f, 0x84, 0x52, 0x3b, 0xd6, 0xb3, 0x92, 0x9d, 0x38, 0xf5, 0x51, 0xa3, 0x40, 0x8f, 0x10, 0xff, 0xf3, 0xd2, 0xbc, 0xb6, 0xda, 0x21, 0x43, 0x4d, 0x33, 0x85, 0xd0, 0xef, 0xaa, 0xfb, 0x50, 0x3c, 0x9f, 0xa8, 0x45, 0xf9, 0x02, 0x7f, 0xfa, 0x59, 0x47, 0xf0, 0xca, 0x82, 0xc9, 0x7d, 0x9c, 0xa4, 0x72, 0xc0, 0xad, 0xd4, 0xa2, 0xaf, 0xf2, 0x6b, 0x6f, 0xc5, 0x63, 0x7c, 0x77, 0x7b, 0xfe, 0xd7, 0xab, 0x76, 0x30, 0x01, 0x67, 0x2b, 0x18, 0x96, 0x05, 0x9a, 0x04, 0xc7, 0x23, 0xc3, 0xeb, 0x27, 0xb2, 0x75, 0x07, 0x12, 0x80, 0xe2, 0x36, 0x3f, 0xf7, 0xcc, 0xb7, 0xfd, 0x93, 0x26, 0x71, 0xd8, 0x31, 0x15, 0x34, 0xa5, 0xe5, 0xf1, 0x48, 0x03, 0xf6, 0x0e, 0x70, 0x3e, 0xb5, 0x66, 0x86, 0xc1, 0x1d, 0x9e, 0x61, 0x35, 0x57, 0xb9, 0x1c, 0xa6, 0xb4, 0xc6, 0xba, 0x78, 0x25, 0x2e, 0x4b, 0xbd, 0x8b, 0x8a, 0xe8, 0xdd, 0x74, 0x1f, 0xbf, 0xe6, 0x42, 0x68, 0x8c, 0xa1, 0x89, 0x0d, 0xb0, 0x54, 0xbb, 0x16, 0x41, 0x99, 0x2d, 0x0f, 0x69, 0xd9, 0x8e, 0x94, 0xe1, 0xf8, 0x98, 0x11, 0xce, 0x55, 0x28, 0xdf, 0x9b, 0x1e, 0x87, 0xe9, 0x22, 0x2a, 0x90, 0x88, 0x60, 0x81, 0x4f, 0xdc, 0xde, 0x5e, 0x0b, 0xdb, 0x46, 0xee, 0xb8, 0x14, 0x5f, 0x97, 0x44, 0x17, 0xcd, 0x0c, 0x13, 0xec, 0x64, 0x5d, 0x19, 0x73, 0xc4, 0xa7, 0x7e, 0x3d, 0x8d, 0xd5, 0x4e, 0xa9, 0xe7, 0xc8, 0x37, 0x6d, 0x65, 0x7a, 0xae, 0x08, 0x6c, 0x56, 0xf4, 0xea, 0x49, 0x06, 0x24, 0x5c, 0xe0, 0x32, 0x3a, 0x0a, 0x91, 0x95, 0xe4, 0x79, 0xc2, 0xd3, 0xac, 0x62 +}, +{ +0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e +}, +{ +0x03, 0x48, 0x0e, 0xf6, 0x3e, 0x70, 0x66, 0xb5, 0xc1, 0x86, 0x9e, 0x1d, 0x35, 0x61, 0xb9, 0x57, 0xa6, 0x1c, 0xc6, 0xb4, 0x78, 0xba, 0x2e, 0x25, 0xbd, 0x4b, 0x8a, 0x8b, 0xdd, 0xe8, 0x1f, 0x74, 0xe6, 0xbf, 0x68, 0x42, 0xa1, 0x8c, 0x0d, 0x89, 0x54, 0xb0, 0x16, 0xbb, 0x99, 0x41, 0x0f, 0x2d, 0xd9, 0x69, 0x94, 0x8e, 0xf8, 0xe1, 0x11, 0x98, 0x55, 0xce, 0xdf, 0x28, 0x1e, 0x9b, 0xe9, 0x87, 0x2a, 0x22, 0x88, 0x90, 0x81, 0x60, 0xdc, 0x4f, 0x5e, 0xde, 0xdb, 0x0b, 0xee, 0x46, 0x14, 0xb8, 0x97, 0x5f, 0x17, 0x44, 0x0c, 0xcd, 0xec, 0x13, 0x5d, 0x64, 0x73, 0x19, 0xa7, 0xc4, 0x3d, 0x7e, 0xd5, 0x8d, 0xa9, 0x4e, 0xc8, 0xe7, 0x6d, 0x37, 0x7a, 0x65, 0x08, 0xae, 0x56, 0x6c, 0xea, 0xf4, 0x06, 0x49, 0x5c, 0x24, 0x32, 0xe0, 0x0a, 0x3a, 0x95, 0x91, 0x79, 0xe4, 0xd3, 0xc2, 0x62, 0xac, 0xfc, 0x20, 0x5b, 0xb1, 0xd1, 0x53, 0xed, 0x00, 0x4c, 0x4a, 0xcf, 0x58, 0xcb, 0x6a, 0x39, 0xbe, 0x6e, 0x1b, 0xa0, 0x5a, 0x83, 0x09, 0x1a, 0x2c, 0xe3, 0x29, 0x84, 0x2f, 0x3b, 0x52, 0xb3, 0xd6, 0x9d, 0x92, 0xf5, 0x38, 0xa3, 0x51, 0x8f, 0x40, 0xff, 0x10, 0xd2, 0xf3, 0xb6, 0xbc, 0x21, 0xda, 0x4d, 0x43, 0x85, 0x33, 0xef, 0xd0, 0xfb, 0xaa, 0x3c, 0x50, 0xa8, 0x9f, 0xf9, 0x45, 0x7f, 0x02, 0x59, 0xfa, 0xf0, 0x47, 0x82, 0xca, 0x7d, 0xc9, 0xa4, 0x9c, 0xc0, 0x72, 0xd4, 0xad, 0xaf, 0xa2, 0x6b, 0xf2, 0xc5, 0x6f, 0x7c, 0x63, 0x7b, 0x77, 0xd7, 0xfe, 0x76, 0xab, 0x01, 0x30, 0x2b, 0x67, 0x96, 0x18, 0x9a, 0x05, 0xc7, 0x04, 0xc3, 0x23, 0x27, 0xeb, 0x75, 0xb2, 0x12, 0x07, 0xe2, 0x80, 0x3f, 0x36, 0xcc, 0xf7, 0xfd, 0xb7, 0x26, 0x93, 0xd8, 0x71, 0x15, 0x31, 0xa5, 0x34, 0xf1, 0xe5 +}, +{ +0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 +}, +{ +0xe3, 0x29, 0x84, 0x2f, 0x3b, 0x52, 0xb3, 0xd6, 0x6e, 0x1b, 0xa0, 0x5a, 0x83, 0x09, 0x1a, 0x2c, 0x4c, 0x4a, 0xcf, 0x58, 0xcb, 0x6a, 0x39, 0xbe, 0xfc, 0x20, 0x5b, 0xb1, 0xd1, 0x53, 0xed, 0x00, 0x3c, 0x50, 0xa8, 0x9f, 0xf9, 0x45, 0x7f, 0x02, 0x4d, 0x43, 0x85, 0x33, 0xef, 0xd0, 0xfb, 0xaa, 0xff, 0x10, 0xd2, 0xf3, 0xb6, 0xbc, 0x21, 0xda, 0x9d, 0x92, 0xf5, 0x38, 0xa3, 0x51, 0x8f, 0x40, 0xd7, 0xfe, 0x76, 0xab, 0x01, 0x30, 0x2b, 0x67, 0x6b, 0xf2, 0xc5, 0x6f, 0x7c, 0x63, 0x7b, 0x77, 0xa4, 0x9c, 0xc0, 0x72, 0xd4, 0xad, 0xaf, 0xa2, 0x59, 0xfa, 0xf0, 0x47, 0x82, 0xca, 0x7d, 0xc9, 0xd8, 0x71, 0x15, 0x31, 0xa5, 0x34, 0xf1, 0xe5, 0x3f, 0x36, 0xcc, 0xf7, 0xfd, 0xb7, 0x26, 0x93, 0x27, 0xeb, 0x75, 0xb2, 0x12, 0x07, 0xe2, 0x80, 0x96, 0x18, 0x9a, 0x05, 0xc7, 0x04, 0xc3, 0x23, 0xbd, 0x4b, 0x8a, 0x8b, 0xdd, 0xe8, 0x1f, 0x74, 0xa6, 0x1c, 0xc6, 0xb4, 0x78, 0xba, 0x2e, 0x25, 0xc1, 0x86, 0x9e, 0x1d, 0x35, 0x61, 0xb9, 0x57, 0x03, 0x48, 0x0e, 0xf6, 0x3e, 0x70, 0x66, 0xb5, 0x55, 0xce, 0xdf, 0x28, 0x1e, 0x9b, 0xe9, 0x87, 0xd9, 0x69, 0x94, 0x8e, 0xf8, 0xe1, 0x11, 0x98, 0x54, 0xb0, 0x16, 0xbb, 0x99, 0x41, 0x0f, 0x2d, 0xe6, 0xbf, 0x68, 0x42, 0xa1, 0x8c, 0x0d, 0x89, 0x5d, 0x64, 0x73, 0x19, 0xa7, 0xc4, 0x3d, 0x7e, 0x97, 0x5f, 0x17, 0x44, 0x0c, 0xcd, 0xec, 0x13, 0x5e, 0xde, 0xdb, 0x0b, 0xee, 0x46, 0x14, 0xb8, 0x2a, 0x22, 0x88, 0x90, 0x81, 0x60, 0xdc, 0x4f, 0x95, 0x91, 0x79, 0xe4, 0xd3, 0xc2, 0x62, 0xac, 0x06, 0x49, 0x5c, 0x24, 0x32, 0xe0, 0x0a, 0x3a, 0x7a, 0x65, 0x08, 0xae, 0x56, 0x6c, 0xea, 0xf4, 0xd5, 0x8d, 0xa9, 0x4e, 0xc8, 0xe7, 0x6d, 0x37 +}, +{ +0x14, 0xb8, 0xee, 0x46, 0xdb, 0x0b, 0x5e, 0xde, 0xdc, 0x4f, 0x81, 0x60, 0x88, 0x90, 0x2a, 0x22, 0x3d, 0x7e, 0xa7, 0xc4, 0x73, 0x19, 0x5d, 0x64, 0xec, 0x13, 0x0c, 0xcd, 0x17, 0x44, 0x97, 0x5f, 0xea, 0xf4, 0x56, 0x6c, 0x08, 0xae, 0x7a, 0x65, 0x6d, 0x37, 0xc8, 0xe7, 0xa9, 0x4e, 0xd5, 0x8d, 0x62, 0xac, 0xd3, 0xc2, 0x79, 0xe4, 0x95, 0x91, 0x0a, 0x3a, 0x32, 0xe0, 0x5c, 0x24, 0x06, 0x49, 0xb9, 0x57, 0x35, 0x61, 0x9e, 0x1d, 0xc1, 0x86, 0x66, 0xb5, 0x3e, 0x70, 0x0e, 0xf6, 0x03, 0x48, 0x1f, 0x74, 0xdd, 0xe8, 0x8a, 0x8b, 0xbd, 0x4b, 0x2e, 0x25, 0x78, 0xba, 0xc6, 0xb4, 0xa6, 0x1c, 0x0f, 0x2d, 0x99, 0x41, 0x16, 0xbb, 0x54, 0xb0, 0x0d, 0x89, 0xa1, 0x8c, 0x68, 0x42, 0xe6, 0xbf, 0xe9, 0x87, 0x1e, 0x9b, 0xdf, 0x28, 0x55, 0xce, 0x11, 0x98, 0xf8, 0xe1, 0x94, 0x8e, 0xd9, 0x69, 0xaf, 0xa2, 0xd4, 0xad, 0xc0, 0x72, 0xa4, 0x9c, 0x7d, 0xc9, 0x82, 0xca, 0xf0, 0x47, 0x59, 0xfa, 0x2b, 0x67, 0x01, 0x30, 0x76, 0xab, 0xd7, 0xfe, 0x7b, 0x77, 0x7c, 0x63, 0xc5, 0x6f, 0x6b, 0xf2, 0xe2, 0x80, 0x12, 0x07, 0x75, 0xb2, 0x27, 0xeb, 0xc3, 0x23, 0xc7, 0x04, 0x9a, 0x05, 0x96, 0x18, 0xf1, 0xe5, 0xa5, 0x34, 0x15, 0x31, 0xd8, 0x71, 0x26, 0x93, 0xfd, 0xb7, 0xcc, 0xf7, 0x3f, 0x36, 0x39, 0xbe, 0xcb, 0x6a, 0xcf, 0x58, 0x4c, 0x4a, 0xed, 0x00, 0xd1, 0x53, 0x5b, 0xb1, 0xfc, 0x20, 0xb3, 0xd6, 0x3b, 0x52, 0x84, 0x2f, 0xe3, 0x29, 0x1a, 0x2c, 0x83, 0x09, 0xa0, 0x5a, 0x6e, 0x1b, 0x21, 0xda, 0xb6, 0xbc, 0xd2, 0xf3, 0xff, 0x10, 0x8f, 0x40, 0xa3, 0x51, 0xf5, 0x38, 0x9d, 0x92, 0x7f, 0x02, 0xf9, 0x45, 0xa8, 0x9f, 0x3c, 0x50, 0xfb, 0xaa, 0xef, 0xd0, 0x85, 0x33, 0x4d, 0x43 +}, +{ +0x35, 0x61, 0xb9, 0x57, 0xc1, 0x86, 0x9e, 0x1d, 0x3e, 0x70, 0x66, 0xb5, 0x03, 0x48, 0x0e, 0xf6, 0xdd, 0xe8, 0x1f, 0x74, 0xbd, 0x4b, 0x8a, 0x8b, 0x78, 0xba, 0x2e, 0x25, 0xa6, 0x1c, 0xc6, 0xb4, 0x99, 0x41, 0x0f, 0x2d, 0x54, 0xb0, 0x16, 0xbb, 0xa1, 0x8c, 0x0d, 0x89, 0xe6, 0xbf, 0x68, 0x42, 0x1e, 0x9b, 0xe9, 0x87, 0x55, 0xce, 0xdf, 0x28, 0xf8, 0xe1, 0x11, 0x98, 0xd9, 0x69, 0x94, 0x8e, 0xee, 0x46, 0x14, 0xb8, 0x5e, 0xde, 0xdb, 0x0b, 0x81, 0x60, 0xdc, 0x4f, 0x2a, 0x22, 0x88, 0x90, 0xa7, 0xc4, 0x3d, 0x7e, 0x5d, 0x64, 0x73, 0x19, 0x0c, 0xcd, 0xec, 0x13, 0x97, 0x5f, 0x17, 0x44, 0x56, 0x6c, 0xea, 0xf4, 0x7a, 0x65, 0x08, 0xae, 0xc8, 0xe7, 0x6d, 0x37, 0xd5, 0x8d, 0xa9, 0x4e, 0xd3, 0xc2, 0x62, 0xac, 0x95, 0x91, 0x79, 0xe4, 0x32, 0xe0, 0x0a, 0x3a, 0x06, 0x49, 0x5c, 0x24, 0xcb, 0x6a, 0x39, 0xbe, 0x4c, 0x4a, 0xcf, 0x58, 0xd1, 0x53, 0xed, 0x00, 0xfc, 0x20, 0x5b, 0xb1, 0x3b, 0x52, 0xb3, 0xd6, 0xe3, 0x29, 0x84, 0x2f, 0x83, 0x09, 0x1a, 0x2c, 0x6e, 0x1b, 0xa0, 0x5a, 0xb6, 0xbc, 0x21, 0xda, 0xff, 0x10, 0xd2, 0xf3, 0xa3, 0x51, 0x8f, 0x40, 0x9d, 0x92, 0xf5, 0x38, 0xf9, 0x45, 0x7f, 0x02, 0x3c, 0x50, 0xa8, 0x9f, 0xef, 0xd0, 0xfb, 0xaa, 0x4d, 0x43, 0x85, 0x33, 0xd4, 0xad, 0xaf, 0xa2, 0xa4, 0x9c, 0xc0, 0x72, 0x82, 0xca, 0x7d, 0xc9, 0x59, 0xfa, 0xf0, 0x47, 0x01, 0x30, 0x2b, 0x67, 0xd7, 0xfe, 0x76, 0xab, 0x7c, 0x63, 0x7b, 0x77, 0x6b, 0xf2, 0xc5, 0x6f, 0x12, 0x07, 0xe2, 0x80, 0x27, 0xeb, 0x75, 0xb2, 0xc7, 0x04, 0xc3, 0x23, 0x96, 0x18, 0x9a, 0x05, 0xa5, 0x34, 0xf1, 0xe5, 0xd8, 0x71, 0x15, 0x31, 0xfd, 0xb7, 0x26, 0x93, 0x3f, 0x36, 0xcc, 0xf7 +}, +{ +0xa8, 0x9f, 0x3c, 0x50, 0x7f, 0x02, 0xf9, 0x45, 0x85, 0x33, 0x4d, 0x43, 0xfb, 0xaa, 0xef, 0xd0, 0xd2, 0xf3, 0xff, 0x10, 0x21, 0xda, 0xb6, 0xbc, 0xf5, 0x38, 0x9d, 0x92, 0x8f, 0x40, 0xa3, 0x51, 0x84, 0x2f, 0xe3, 0x29, 0xb3, 0xd6, 0x3b, 0x52, 0xa0, 0x5a, 0x6e, 0x1b, 0x1a, 0x2c, 0x83, 0x09, 0xcf, 0x58, 0x4c, 0x4a, 0x39, 0xbe, 0xcb, 0x6a, 0x5b, 0xb1, 0xfc, 0x20, 0xed, 0x00, 0xd1, 0x53, 0x15, 0x31, 0xd8, 0x71, 0xf1, 0xe5, 0xa5, 0x34, 0xcc, 0xf7, 0x3f, 0x36, 0x26, 0x93, 0xfd, 0xb7, 0x75, 0xb2, 0x27, 0xeb, 0xe2, 0x80, 0x12, 0x07, 0x9a, 0x05, 0x96, 0x18, 0xc3, 0x23, 0xc7, 0x04, 0x76, 0xab, 0xd7, 0xfe, 0x2b, 0x67, 0x01, 0x30, 0xc5, 0x6f, 0x6b, 0xf2, 0x7b, 0x77, 0x7c, 0x63, 0xc0, 0x72, 0xa4, 0x9c, 0xaf, 0xa2, 0xd4, 0xad, 0xf0, 0x47, 0x59, 0xfa, 0x7d, 0xc9, 0x82, 0xca, 0xdf, 0x28, 0x55, 0xce, 0xe9, 0x87, 0x1e, 0x9b, 0x94, 0x8e, 0xd9, 0x69, 0x11, 0x98, 0xf8, 0xe1, 0x16, 0xbb, 0x54, 0xb0, 0x0f, 0x2d, 0x99, 0x41, 0x68, 0x42, 0xe6, 0xbf, 0x0d, 0x89, 0xa1, 0x8c, 0x8a, 0x8b, 0xbd, 0x4b, 0x1f, 0x74, 0xdd, 0xe8, 0xc6, 0xb4, 0xa6, 0x1c, 0x2e, 0x25, 0x78, 0xba, 0x9e, 0x1d, 0xc1, 0x86, 0xb9, 0x57, 0x35, 0x61, 0x0e, 0xf6, 0x03, 0x48, 0x66, 0xb5, 0x3e, 0x70, 0x79, 0xe4, 0x95, 0x91, 0x62, 0xac, 0xd3, 0xc2, 0x5c, 0x24, 0x06, 0x49, 0x0a, 0x3a, 0x32, 0xe0, 0x08, 0xae, 0x7a, 0x65, 0xea, 0xf4, 0x56, 0x6c, 0xa9, 0x4e, 0xd5, 0x8d, 0x6d, 0x37, 0xc8, 0xe7, 0x73, 0x19, 0x5d, 0x64, 0x3d, 0x7e, 0xa7, 0xc4, 0x17, 0x44, 0x97, 0x5f, 0xec, 0x13, 0x0c, 0xcd, 0xdb, 0x0b, 0x5e, 0xde, 0x14, 0xb8, 0xee, 0x46, 0x88, 0x90, 0x2a, 0x22, 0xdc, 0x4f, 0x81, 0x60 +}, +{ +0x1d, 0x9e, 0x86, 0xc1, 0x57, 0xb9, 0x61, 0x35, 0xf6, 0x0e, 0x48, 0x03, 0xb5, 0x66, 0x70, 0x3e, 0x8b, 0x8a, 0x4b, 0xbd, 0x74, 0x1f, 0xe8, 0xdd, 0xb4, 0xc6, 0x1c, 0xa6, 0x25, 0x2e, 0xba, 0x78, 0xbb, 0x16, 0xb0, 0x54, 0x2d, 0x0f, 0x41, 0x99, 0x42, 0x68, 0xbf, 0xe6, 0x89, 0x0d, 0x8c, 0xa1, 0x28, 0xdf, 0xce, 0x55, 0x87, 0xe9, 0x9b, 0x1e, 0x8e, 0x94, 0x69, 0xd9, 0x98, 0x11, 0xe1, 0xf8, 0x0b, 0xdb, 0xde, 0x5e, 0xb8, 0x14, 0x46, 0xee, 0x90, 0x88, 0x22, 0x2a, 0x4f, 0xdc, 0x60, 0x81, 0x19, 0x73, 0x64, 0x5d, 0x7e, 0x3d, 0xc4, 0xa7, 0x44, 0x17, 0x5f, 0x97, 0x13, 0xec, 0xcd, 0x0c, 0xae, 0x08, 0x65, 0x7a, 0xf4, 0xea, 0x6c, 0x56, 0x4e, 0xa9, 0x8d, 0xd5, 0x37, 0x6d, 0xe7, 0xc8, 0xe4, 0x79, 0x91, 0x95, 0xac, 0x62, 0xc2, 0xd3, 0x24, 0x5c, 0x49, 0x06, 0x3a, 0x0a, 0xe0, 0x32, 0x58, 0xcf, 0x4a, 0x4c, 0xbe, 0x39, 0x6a, 0xcb, 0xb1, 0x5b, 0x20, 0xfc, 0x00, 0xed, 0x53, 0xd1, 0x2f, 0x84, 0x29, 0xe3, 0xd6, 0xb3, 0x52, 0x3b, 0x5a, 0xa0, 0x1b, 0x6e, 0x2c, 0x1a, 0x09, 0x83, 0xf3, 0xd2, 0x10, 0xff, 0xda, 0x21, 0xbc, 0xb6, 0x38, 0xf5, 0x92, 0x9d, 0x40, 0x8f, 0x51, 0xa3, 0x9f, 0xa8, 0x50, 0x3c, 0x02, 0x7f, 0x45, 0xf9, 0x33, 0x85, 0x43, 0x4d, 0xaa, 0xfb, 0xd0, 0xef, 0x72, 0xc0, 0x9c, 0xa4, 0xa2, 0xaf, 0xad, 0xd4, 0x47, 0xf0, 0xfa, 0x59, 0xc9, 0x7d, 0xca, 0x82, 0xab, 0x76, 0xfe, 0xd7, 0x67, 0x2b, 0x30, 0x01, 0x6f, 0xc5, 0xf2, 0x6b, 0x77, 0x7b, 0x63, 0x7c, 0xb2, 0x75, 0xeb, 0x27, 0x80, 0xe2, 0x07, 0x12, 0x05, 0x9a, 0x18, 0x96, 0x23, 0xc3, 0x04, 0xc7, 0x31, 0x15, 0x71, 0xd8, 0xe5, 0xf1, 0x34, 0xa5, 0xf7, 0xcc, 0x36, 0x3f, 0x93, 0x26, 0xb7, 0xfd +}, +{ +0xf3, 0xd2, 0x10, 0xff, 0xda, 0x21, 0xbc, 0xb6, 0x38, 0xf5, 0x92, 0x9d, 0x40, 0x8f, 0x51, 0xa3, 0x9f, 0xa8, 0x50, 0x3c, 0x02, 0x7f, 0x45, 0xf9, 0x33, 0x85, 0x43, 0x4d, 0xaa, 0xfb, 0xd0, 0xef, 0x58, 0xcf, 0x4a, 0x4c, 0xbe, 0x39, 0x6a, 0xcb, 0xb1, 0x5b, 0x20, 0xfc, 0x00, 0xed, 0x53, 0xd1, 0x2f, 0x84, 0x29, 0xe3, 0xd6, 0xb3, 0x52, 0x3b, 0x5a, 0xa0, 0x1b, 0x6e, 0x2c, 0x1a, 0x09, 0x83, 0xb2, 0x75, 0xeb, 0x27, 0x80, 0xe2, 0x07, 0x12, 0x05, 0x9a, 0x18, 0x96, 0x23, 0xc3, 0x04, 0xc7, 0x31, 0x15, 0x71, 0xd8, 0xe5, 0xf1, 0x34, 0xa5, 0xf7, 0xcc, 0x36, 0x3f, 0x93, 0x26, 0xb7, 0xfd, 0x72, 0xc0, 0x9c, 0xa4, 0xa2, 0xaf, 0xad, 0xd4, 0x47, 0xf0, 0xfa, 0x59, 0xc9, 0x7d, 0xca, 0x82, 0xab, 0x76, 0xfe, 0xd7, 0x67, 0x2b, 0x30, 0x01, 0x6f, 0xc5, 0xf2, 0x6b, 0x77, 0x7b, 0x63, 0x7c, 0xbb, 0x16, 0xb0, 0x54, 0x2d, 0x0f, 0x41, 0x99, 0x42, 0x68, 0xbf, 0xe6, 0x89, 0x0d, 0x8c, 0xa1, 0x28, 0xdf, 0xce, 0x55, 0x87, 0xe9, 0x9b, 0x1e, 0x8e, 0x94, 0x69, 0xd9, 0x98, 0x11, 0xe1, 0xf8, 0x1d, 0x9e, 0x86, 0xc1, 0x57, 0xb9, 0x61, 0x35, 0xf6, 0x0e, 0x48, 0x03, 0xb5, 0x66, 0x70, 0x3e, 0x8b, 0x8a, 0x4b, 0xbd, 0x74, 0x1f, 0xe8, 0xdd, 0xb4, 0xc6, 0x1c, 0xa6, 0x25, 0x2e, 0xba, 0x78, 0xae, 0x08, 0x65, 0x7a, 0xf4, 0xea, 0x6c, 0x56, 0x4e, 0xa9, 0x8d, 0xd5, 0x37, 0x6d, 0xe7, 0xc8, 0xe4, 0x79, 0x91, 0x95, 0xac, 0x62, 0xc2, 0xd3, 0x24, 0x5c, 0x49, 0x06, 0x3a, 0x0a, 0xe0, 0x32, 0x0b, 0xdb, 0xde, 0x5e, 0xb8, 0x14, 0x46, 0xee, 0x90, 0x88, 0x22, 0x2a, 0x4f, 0xdc, 0x60, 0x81, 0x19, 0x73, 0x64, 0x5d, 0x7e, 0x3d, 0xc4, 0xa7, 0x44, 0x17, 0x5f, 0x97, 0x13, 0xec, 0xcd, 0x0c +}, +{ +0x17, 0x44, 0x97, 0x5f, 0xec, 0x13, 0x0c, 0xcd, 0x73, 0x19, 0x5d, 0x64, 0x3d, 0x7e, 0xa7, 0xc4, 0x88, 0x90, 0x2a, 0x22, 0xdc, 0x4f, 0x81, 0x60, 0xdb, 0x0b, 0x5e, 0xde, 0x14, 0xb8, 0xee, 0x46, 0x5c, 0x24, 0x06, 0x49, 0x0a, 0x3a, 0x32, 0xe0, 0x79, 0xe4, 0x95, 0x91, 0x62, 0xac, 0xd3, 0xc2, 0xa9, 0x4e, 0xd5, 0x8d, 0x6d, 0x37, 0xc8, 0xe7, 0x08, 0xae, 0x7a, 0x65, 0xea, 0xf4, 0x56, 0x6c, 0xc6, 0xb4, 0xa6, 0x1c, 0x2e, 0x25, 0x78, 0xba, 0x8a, 0x8b, 0xbd, 0x4b, 0x1f, 0x74, 0xdd, 0xe8, 0x0e, 0xf6, 0x03, 0x48, 0x66, 0xb5, 0x3e, 0x70, 0x9e, 0x1d, 0xc1, 0x86, 0xb9, 0x57, 0x35, 0x61, 0x94, 0x8e, 0xd9, 0x69, 0x11, 0x98, 0xf8, 0xe1, 0xdf, 0x28, 0x55, 0xce, 0xe9, 0x87, 0x1e, 0x9b, 0x68, 0x42, 0xe6, 0xbf, 0x0d, 0x89, 0xa1, 0x8c, 0x16, 0xbb, 0x54, 0xb0, 0x0f, 0x2d, 0x99, 0x41, 0xc5, 0x6f, 0x6b, 0xf2, 0x7b, 0x77, 0x7c, 0x63, 0x76, 0xab, 0xd7, 0xfe, 0x2b, 0x67, 0x01, 0x30, 0xf0, 0x47, 0x59, 0xfa, 0x7d, 0xc9, 0x82, 0xca, 0xc0, 0x72, 0xa4, 0x9c, 0xaf, 0xa2, 0xd4, 0xad, 0xcc, 0xf7, 0x3f, 0x36, 0x26, 0x93, 0xfd, 0xb7, 0x15, 0x31, 0xd8, 0x71, 0xf1, 0xe5, 0xa5, 0x34, 0x9a, 0x05, 0x96, 0x18, 0xc3, 0x23, 0xc7, 0x04, 0x75, 0xb2, 0x27, 0xeb, 0xe2, 0x80, 0x12, 0x07, 0xa0, 0x5a, 0x6e, 0x1b, 0x1a, 0x2c, 0x83, 0x09, 0x84, 0x2f, 0xe3, 0x29, 0xb3, 0xd6, 0x3b, 0x52, 0x5b, 0xb1, 0xfc, 0x20, 0xed, 0x00, 0xd1, 0x53, 0xcf, 0x58, 0x4c, 0x4a, 0x39, 0xbe, 0xcb, 0x6a, 0x85, 0x33, 0x4d, 0x43, 0xfb, 0xaa, 0xef, 0xd0, 0xa8, 0x9f, 0x3c, 0x50, 0x7f, 0x02, 0xf9, 0x45, 0xf5, 0x38, 0x9d, 0x92, 0x8f, 0x40, 0xa3, 0x51, 0xd2, 0xf3, 0xff, 0x10, 0x21, 0xda, 0xb6, 0xbc +} +}, +{ +{ +0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88 +}, +{ +0x57, 0xb9, 0x61, 0x35, 0x1d, 0x9e, 0x86, 0xc1, 0xb5, 0x66, 0x70, 0x3e, 0xf6, 0x0e, 0x48, 0x03, 0x74, 0x1f, 0xe8, 0xdd, 0x8b, 0x8a, 0x4b, 0xbd, 0x25, 0x2e, 0xba, 0x78, 0xb4, 0xc6, 0x1c, 0xa6, 0x2d, 0x0f, 0x41, 0x99, 0xbb, 0x16, 0xb0, 0x54, 0x89, 0x0d, 0x8c, 0xa1, 0x42, 0x68, 0xbf, 0xe6, 0x87, 0xe9, 0x9b, 0x1e, 0x28, 0xdf, 0xce, 0x55, 0x98, 0x11, 0xe1, 0xf8, 0x8e, 0x94, 0x69, 0xd9, 0xb8, 0x14, 0x46, 0xee, 0x0b, 0xdb, 0xde, 0x5e, 0x4f, 0xdc, 0x60, 0x81, 0x90, 0x88, 0x22, 0x2a, 0x7e, 0x3d, 0xc4, 0xa7, 0x19, 0x73, 0x64, 0x5d, 0x13, 0xec, 0xcd, 0x0c, 0x44, 0x17, 0x5f, 0x97, 0xf4, 0xea, 0x6c, 0x56, 0xae, 0x08, 0x65, 0x7a, 0x37, 0x6d, 0xe7, 0xc8, 0x4e, 0xa9, 0x8d, 0xd5, 0xac, 0x62, 0xc2, 0xd3, 0xe4, 0x79, 0x91, 0x95, 0x3a, 0x0a, 0xe0, 0x32, 0x24, 0x5c, 0x49, 0x06, 0xbe, 0x39, 0x6a, 0xcb, 0x58, 0xcf, 0x4a, 0x4c, 0x00, 0xed, 0x53, 0xd1, 0xb1, 0x5b, 0x20, 0xfc, 0xd6, 0xb3, 0x52, 0x3b, 0x2f, 0x84, 0x29, 0xe3, 0x2c, 0x1a, 0x09, 0x83, 0x5a, 0xa0, 0x1b, 0x6e, 0xda, 0x21, 0xbc, 0xb6, 0xf3, 0xd2, 0x10, 0xff, 0x40, 0x8f, 0x51, 0xa3, 0x38, 0xf5, 0x92, 0x9d, 0x02, 0x7f, 0x45, 0xf9, 0x9f, 0xa8, 0x50, 0x3c, 0xaa, 0xfb, 0xd0, 0xef, 0x33, 0x85, 0x43, 0x4d, 0xa2, 0xaf, 0xad, 0xd4, 0x72, 0xc0, 0x9c, 0xa4, 0xc9, 0x7d, 0xca, 0x82, 0x47, 0xf0, 0xfa, 0x59, 0x67, 0x2b, 0x30, 0x01, 0xab, 0x76, 0xfe, 0xd7, 0x77, 0x7b, 0x63, 0x7c, 0x6f, 0xc5, 0xf2, 0x6b, 0x80, 0xe2, 0x07, 0x12, 0xb2, 0x75, 0xeb, 0x27, 0x23, 0xc3, 0x04, 0xc7, 0x05, 0x9a, 0x18, 0x96, 0xe5, 0xf1, 0x34, 0xa5, 0x31, 0x15, 0x71, 0xd8, 0x93, 0x26, 0xb7, 0xfd, 0xf7, 0xcc, 0x36, 0x3f +}, +{ +0xc3, 0x23, 0xc7, 0x04, 0x9a, 0x05, 0x96, 0x18, 0xe2, 0x80, 0x12, 0x07, 0x75, 0xb2, 0x27, 0xeb, 0x26, 0x93, 0xfd, 0xb7, 0xcc, 0xf7, 0x3f, 0x36, 0xf1, 0xe5, 0xa5, 0x34, 0x15, 0x31, 0xd8, 0x71, 0x7d, 0xc9, 0x82, 0xca, 0xf0, 0x47, 0x59, 0xfa, 0xaf, 0xa2, 0xd4, 0xad, 0xc0, 0x72, 0xa4, 0x9c, 0x7b, 0x77, 0x7c, 0x63, 0xc5, 0x6f, 0x6b, 0xf2, 0x2b, 0x67, 0x01, 0x30, 0x76, 0xab, 0xd7, 0xfe, 0x8f, 0x40, 0xa3, 0x51, 0xf5, 0x38, 0x9d, 0x92, 0x21, 0xda, 0xb6, 0xbc, 0xd2, 0xf3, 0xff, 0x10, 0xfb, 0xaa, 0xef, 0xd0, 0x85, 0x33, 0x4d, 0x43, 0x7f, 0x02, 0xf9, 0x45, 0xa8, 0x9f, 0x3c, 0x50, 0xed, 0x00, 0xd1, 0x53, 0x5b, 0xb1, 0xfc, 0x20, 0x39, 0xbe, 0xcb, 0x6a, 0xcf, 0x58, 0x4c, 0x4a, 0x1a, 0x2c, 0x83, 0x09, 0xa0, 0x5a, 0x6e, 0x1b, 0xb3, 0xd6, 0x3b, 0x52, 0x84, 0x2f, 0xe3, 0x29, 0x6d, 0x37, 0xc8, 0xe7, 0xa9, 0x4e, 0xd5, 0x8d, 0xea, 0xf4, 0x56, 0x6c, 0x08, 0xae, 0x7a, 0x65, 0x0a, 0x3a, 0x32, 0xe0, 0x5c, 0x24, 0x06, 0x49, 0x62, 0xac, 0xd3, 0xc2, 0x79, 0xe4, 0x95, 0x91, 0xdc, 0x4f, 0x81, 0x60, 0x88, 0x90, 0x2a, 0x22, 0x14, 0xb8, 0xee, 0x46, 0xdb, 0x0b, 0x5e, 0xde, 0xec, 0x13, 0x0c, 0xcd, 0x17, 0x44, 0x97, 0x5f, 0x3d, 0x7e, 0xa7, 0xc4, 0x73, 0x19, 0x5d, 0x64, 0x0d, 0x89, 0xa1, 0x8c, 0x68, 0x42, 0xe6, 0xbf, 0x0f, 0x2d, 0x99, 0x41, 0x16, 0xbb, 0x54, 0xb0, 0x11, 0x98, 0xf8, 0xe1, 0x94, 0x8e, 0xd9, 0x69, 0xe9, 0x87, 0x1e, 0x9b, 0xdf, 0x28, 0x55, 0xce, 0x66, 0xb5, 0x3e, 0x70, 0x0e, 0xf6, 0x03, 0x48, 0xb9, 0x57, 0x35, 0x61, 0x9e, 0x1d, 0xc1, 0x86, 0x2e, 0x25, 0x78, 0xba, 0xc6, 0xb4, 0xa6, 0x1c, 0x1f, 0x74, 0xdd, 0xe8, 0x8a, 0x8b, 0xbd, 0x4b +}, +{ +0x87, 0xe9, 0x9b, 0x1e, 0x28, 0xdf, 0xce, 0x55, 0x98, 0x11, 0xe1, 0xf8, 0x8e, 0x94, 0x69, 0xd9, 0x2d, 0x0f, 0x41, 0x99, 0xbb, 0x16, 0xb0, 0x54, 0x89, 0x0d, 0x8c, 0xa1, 0x42, 0x68, 0xbf, 0xe6, 0x74, 0x1f, 0xe8, 0xdd, 0x8b, 0x8a, 0x4b, 0xbd, 0x25, 0x2e, 0xba, 0x78, 0xb4, 0xc6, 0x1c, 0xa6, 0x57, 0xb9, 0x61, 0x35, 0x1d, 0x9e, 0x86, 0xc1, 0xb5, 0x66, 0x70, 0x3e, 0xf6, 0x0e, 0x48, 0x03, 0xac, 0x62, 0xc2, 0xd3, 0xe4, 0x79, 0x91, 0x95, 0x3a, 0x0a, 0xe0, 0x32, 0x24, 0x5c, 0x49, 0x06, 0xf4, 0xea, 0x6c, 0x56, 0xae, 0x08, 0x65, 0x7a, 0x37, 0x6d, 0xe7, 0xc8, 0x4e, 0xa9, 0x8d, 0xd5, 0x7e, 0x3d, 0xc4, 0xa7, 0x19, 0x73, 0x64, 0x5d, 0x13, 0xec, 0xcd, 0x0c, 0x44, 0x17, 0x5f, 0x97, 0xb8, 0x14, 0x46, 0xee, 0x0b, 0xdb, 0xde, 0x5e, 0x4f, 0xdc, 0x60, 0x81, 0x90, 0x88, 0x22, 0x2a, 0x02, 0x7f, 0x45, 0xf9, 0x9f, 0xa8, 0x50, 0x3c, 0xaa, 0xfb, 0xd0, 0xef, 0x33, 0x85, 0x43, 0x4d, 0xda, 0x21, 0xbc, 0xb6, 0xf3, 0xd2, 0x10, 0xff, 0x40, 0x8f, 0x51, 0xa3, 0x38, 0xf5, 0x92, 0x9d, 0xd6, 0xb3, 0x52, 0x3b, 0x2f, 0x84, 0x29, 0xe3, 0x2c, 0x1a, 0x09, 0x83, 0x5a, 0xa0, 0x1b, 0x6e, 0xbe, 0x39, 0x6a, 0xcb, 0x58, 0xcf, 0x4a, 0x4c, 0x00, 0xed, 0x53, 0xd1, 0xb1, 0x5b, 0x20, 0xfc, 0xe5, 0xf1, 0x34, 0xa5, 0x31, 0x15, 0x71, 0xd8, 0x93, 0x26, 0xb7, 0xfd, 0xf7, 0xcc, 0x36, 0x3f, 0x80, 0xe2, 0x07, 0x12, 0xb2, 0x75, 0xeb, 0x27, 0x23, 0xc3, 0x04, 0xc7, 0x05, 0x9a, 0x18, 0x96, 0x67, 0x2b, 0x30, 0x01, 0xab, 0x76, 0xfe, 0xd7, 0x77, 0x7b, 0x63, 0x7c, 0x6f, 0xc5, 0xf2, 0x6b, 0xa2, 0xaf, 0xad, 0xd4, 0x72, 0xc0, 0x9c, 0xa4, 0xc9, 0x7d, 0xca, 0x82, 0x47, 0xf0, 0xfa, 0x59 +}, +{ +0xbb, 0x16, 0xb0, 0x54, 0x2d, 0x0f, 0x41, 0x99, 0x42, 0x68, 0xbf, 0xe6, 0x89, 0x0d, 0x8c, 0xa1, 0x28, 0xdf, 0xce, 0x55, 0x87, 0xe9, 0x9b, 0x1e, 0x8e, 0x94, 0x69, 0xd9, 0x98, 0x11, 0xe1, 0xf8, 0x1d, 0x9e, 0x86, 0xc1, 0x57, 0xb9, 0x61, 0x35, 0xf6, 0x0e, 0x48, 0x03, 0xb5, 0x66, 0x70, 0x3e, 0x8b, 0x8a, 0x4b, 0xbd, 0x74, 0x1f, 0xe8, 0xdd, 0xb4, 0xc6, 0x1c, 0xa6, 0x25, 0x2e, 0xba, 0x78, 0xae, 0x08, 0x65, 0x7a, 0xf4, 0xea, 0x6c, 0x56, 0x4e, 0xa9, 0x8d, 0xd5, 0x37, 0x6d, 0xe7, 0xc8, 0xe4, 0x79, 0x91, 0x95, 0xac, 0x62, 0xc2, 0xd3, 0x24, 0x5c, 0x49, 0x06, 0x3a, 0x0a, 0xe0, 0x32, 0x0b, 0xdb, 0xde, 0x5e, 0xb8, 0x14, 0x46, 0xee, 0x90, 0x88, 0x22, 0x2a, 0x4f, 0xdc, 0x60, 0x81, 0x19, 0x73, 0x64, 0x5d, 0x7e, 0x3d, 0xc4, 0xa7, 0x44, 0x17, 0x5f, 0x97, 0x13, 0xec, 0xcd, 0x0c, 0xf3, 0xd2, 0x10, 0xff, 0xda, 0x21, 0xbc, 0xb6, 0x38, 0xf5, 0x92, 0x9d, 0x40, 0x8f, 0x51, 0xa3, 0x9f, 0xa8, 0x50, 0x3c, 0x02, 0x7f, 0x45, 0xf9, 0x33, 0x85, 0x43, 0x4d, 0xaa, 0xfb, 0xd0, 0xef, 0x58, 0xcf, 0x4a, 0x4c, 0xbe, 0x39, 0x6a, 0xcb, 0xb1, 0x5b, 0x20, 0xfc, 0x00, 0xed, 0x53, 0xd1, 0x2f, 0x84, 0x29, 0xe3, 0xd6, 0xb3, 0x52, 0x3b, 0x5a, 0xa0, 0x1b, 0x6e, 0x2c, 0x1a, 0x09, 0x83, 0xb2, 0x75, 0xeb, 0x27, 0x80, 0xe2, 0x07, 0x12, 0x05, 0x9a, 0x18, 0x96, 0x23, 0xc3, 0x04, 0xc7, 0x31, 0x15, 0x71, 0xd8, 0xe5, 0xf1, 0x34, 0xa5, 0xf7, 0xcc, 0x36, 0x3f, 0x93, 0x26, 0xb7, 0xfd, 0x72, 0xc0, 0x9c, 0xa4, 0xa2, 0xaf, 0xad, 0xd4, 0x47, 0xf0, 0xfa, 0x59, 0xc9, 0x7d, 0xca, 0x82, 0xab, 0x76, 0xfe, 0xd7, 0x67, 0x2b, 0x30, 0x01, 0x6f, 0xc5, 0xf2, 0x6b, 0x77, 0x7b, 0x63, 0x7c +}, +{ +0x19, 0x73, 0x64, 0x5d, 0x7e, 0x3d, 0xc4, 0xa7, 0x44, 0x17, 0x5f, 0x97, 0x13, 0xec, 0xcd, 0x0c, 0x0b, 0xdb, 0xde, 0x5e, 0xb8, 0x14, 0x46, 0xee, 0x90, 0x88, 0x22, 0x2a, 0x4f, 0xdc, 0x60, 0x81, 0xe4, 0x79, 0x91, 0x95, 0xac, 0x62, 0xc2, 0xd3, 0x24, 0x5c, 0x49, 0x06, 0x3a, 0x0a, 0xe0, 0x32, 0xae, 0x08, 0x65, 0x7a, 0xf4, 0xea, 0x6c, 0x56, 0x4e, 0xa9, 0x8d, 0xd5, 0x37, 0x6d, 0xe7, 0xc8, 0x8b, 0x8a, 0x4b, 0xbd, 0x74, 0x1f, 0xe8, 0xdd, 0xb4, 0xc6, 0x1c, 0xa6, 0x25, 0x2e, 0xba, 0x78, 0x1d, 0x9e, 0x86, 0xc1, 0x57, 0xb9, 0x61, 0x35, 0xf6, 0x0e, 0x48, 0x03, 0xb5, 0x66, 0x70, 0x3e, 0x28, 0xdf, 0xce, 0x55, 0x87, 0xe9, 0x9b, 0x1e, 0x8e, 0x94, 0x69, 0xd9, 0x98, 0x11, 0xe1, 0xf8, 0xbb, 0x16, 0xb0, 0x54, 0x2d, 0x0f, 0x41, 0x99, 0x42, 0x68, 0xbf, 0xe6, 0x89, 0x0d, 0x8c, 0xa1, 0xab, 0x76, 0xfe, 0xd7, 0x67, 0x2b, 0x30, 0x01, 0x6f, 0xc5, 0xf2, 0x6b, 0x77, 0x7b, 0x63, 0x7c, 0x72, 0xc0, 0x9c, 0xa4, 0xa2, 0xaf, 0xad, 0xd4, 0x47, 0xf0, 0xfa, 0x59, 0xc9, 0x7d, 0xca, 0x82, 0x31, 0x15, 0x71, 0xd8, 0xe5, 0xf1, 0x34, 0xa5, 0xf7, 0xcc, 0x36, 0x3f, 0x93, 0x26, 0xb7, 0xfd, 0xb2, 0x75, 0xeb, 0x27, 0x80, 0xe2, 0x07, 0x12, 0x05, 0x9a, 0x18, 0x96, 0x23, 0xc3, 0x04, 0xc7, 0x2f, 0x84, 0x29, 0xe3, 0xd6, 0xb3, 0x52, 0x3b, 0x5a, 0xa0, 0x1b, 0x6e, 0x2c, 0x1a, 0x09, 0x83, 0x58, 0xcf, 0x4a, 0x4c, 0xbe, 0x39, 0x6a, 0xcb, 0xb1, 0x5b, 0x20, 0xfc, 0x00, 0xed, 0x53, 0xd1, 0x9f, 0xa8, 0x50, 0x3c, 0x02, 0x7f, 0x45, 0xf9, 0x33, 0x85, 0x43, 0x4d, 0xaa, 0xfb, 0xd0, 0xef, 0xf3, 0xd2, 0x10, 0xff, 0xda, 0x21, 0xbc, 0xb6, 0x38, 0xf5, 0x92, 0x9d, 0x40, 0x8f, 0x51, 0xa3 +}, +{ +0x7d, 0xc9, 0x82, 0xca, 0xf0, 0x47, 0x59, 0xfa, 0xaf, 0xa2, 0xd4, 0xad, 0xc0, 0x72, 0xa4, 0x9c, 0x7b, 0x77, 0x7c, 0x63, 0xc5, 0x6f, 0x6b, 0xf2, 0x2b, 0x67, 0x01, 0x30, 0x76, 0xab, 0xd7, 0xfe, 0xc3, 0x23, 0xc7, 0x04, 0x9a, 0x05, 0x96, 0x18, 0xe2, 0x80, 0x12, 0x07, 0x75, 0xb2, 0x27, 0xeb, 0x26, 0x93, 0xfd, 0xb7, 0xcc, 0xf7, 0x3f, 0x36, 0xf1, 0xe5, 0xa5, 0x34, 0x15, 0x31, 0xd8, 0x71, 0xed, 0x00, 0xd1, 0x53, 0x5b, 0xb1, 0xfc, 0x20, 0x39, 0xbe, 0xcb, 0x6a, 0xcf, 0x58, 0x4c, 0x4a, 0x1a, 0x2c, 0x83, 0x09, 0xa0, 0x5a, 0x6e, 0x1b, 0xb3, 0xd6, 0x3b, 0x52, 0x84, 0x2f, 0xe3, 0x29, 0x8f, 0x40, 0xa3, 0x51, 0xf5, 0x38, 0x9d, 0x92, 0x21, 0xda, 0xb6, 0xbc, 0xd2, 0xf3, 0xff, 0x10, 0xfb, 0xaa, 0xef, 0xd0, 0x85, 0x33, 0x4d, 0x43, 0x7f, 0x02, 0xf9, 0x45, 0xa8, 0x9f, 0x3c, 0x50, 0xdc, 0x4f, 0x81, 0x60, 0x88, 0x90, 0x2a, 0x22, 0x14, 0xb8, 0xee, 0x46, 0xdb, 0x0b, 0x5e, 0xde, 0xec, 0x13, 0x0c, 0xcd, 0x17, 0x44, 0x97, 0x5f, 0x3d, 0x7e, 0xa7, 0xc4, 0x73, 0x19, 0x5d, 0x64, 0x6d, 0x37, 0xc8, 0xe7, 0xa9, 0x4e, 0xd5, 0x8d, 0xea, 0xf4, 0x56, 0x6c, 0x08, 0xae, 0x7a, 0x65, 0x0a, 0x3a, 0x32, 0xe0, 0x5c, 0x24, 0x06, 0x49, 0x62, 0xac, 0xd3, 0xc2, 0x79, 0xe4, 0x95, 0x91, 0x66, 0xb5, 0x3e, 0x70, 0x0e, 0xf6, 0x03, 0x48, 0xb9, 0x57, 0x35, 0x61, 0x9e, 0x1d, 0xc1, 0x86, 0x2e, 0x25, 0x78, 0xba, 0xc6, 0xb4, 0xa6, 0x1c, 0x1f, 0x74, 0xdd, 0xe8, 0x8a, 0x8b, 0xbd, 0x4b, 0x0d, 0x89, 0xa1, 0x8c, 0x68, 0x42, 0xe6, 0xbf, 0x0f, 0x2d, 0x99, 0x41, 0x16, 0xbb, 0x54, 0xb0, 0x11, 0x98, 0xf8, 0xe1, 0x94, 0x8e, 0xd9, 0x69, 0xe9, 0x87, 0x1e, 0x9b, 0xdf, 0x28, 0x55, 0xce +}, +{ +0xff, 0x10, 0xd2, 0xf3, 0xb6, 0xbc, 0x21, 0xda, 0x9d, 0x92, 0xf5, 0x38, 0xa3, 0x51, 0x8f, 0x40, 0x3c, 0x50, 0xa8, 0x9f, 0xf9, 0x45, 0x7f, 0x02, 0x4d, 0x43, 0x85, 0x33, 0xef, 0xd0, 0xfb, 0xaa, 0x4c, 0x4a, 0xcf, 0x58, 0xcb, 0x6a, 0x39, 0xbe, 0xfc, 0x20, 0x5b, 0xb1, 0xd1, 0x53, 0xed, 0x00, 0xe3, 0x29, 0x84, 0x2f, 0x3b, 0x52, 0xb3, 0xd6, 0x6e, 0x1b, 0xa0, 0x5a, 0x83, 0x09, 0x1a, 0x2c, 0x27, 0xeb, 0x75, 0xb2, 0x12, 0x07, 0xe2, 0x80, 0x96, 0x18, 0x9a, 0x05, 0xc7, 0x04, 0xc3, 0x23, 0xd8, 0x71, 0x15, 0x31, 0xa5, 0x34, 0xf1, 0xe5, 0x3f, 0x36, 0xcc, 0xf7, 0xfd, 0xb7, 0x26, 0x93, 0xa4, 0x9c, 0xc0, 0x72, 0xd4, 0xad, 0xaf, 0xa2, 0x59, 0xfa, 0xf0, 0x47, 0x82, 0xca, 0x7d, 0xc9, 0xd7, 0xfe, 0x76, 0xab, 0x01, 0x30, 0x2b, 0x67, 0x6b, 0xf2, 0xc5, 0x6f, 0x7c, 0x63, 0x7b, 0x77, 0x54, 0xb0, 0x16, 0xbb, 0x99, 0x41, 0x0f, 0x2d, 0xe6, 0xbf, 0x68, 0x42, 0xa1, 0x8c, 0x0d, 0x89, 0x55, 0xce, 0xdf, 0x28, 0x1e, 0x9b, 0xe9, 0x87, 0xd9, 0x69, 0x94, 0x8e, 0xf8, 0xe1, 0x11, 0x98, 0xc1, 0x86, 0x9e, 0x1d, 0x35, 0x61, 0xb9, 0x57, 0x03, 0x48, 0x0e, 0xf6, 0x3e, 0x70, 0x66, 0xb5, 0xbd, 0x4b, 0x8a, 0x8b, 0xdd, 0xe8, 0x1f, 0x74, 0xa6, 0x1c, 0xc6, 0xb4, 0x78, 0xba, 0x2e, 0x25, 0x7a, 0x65, 0x08, 0xae, 0x56, 0x6c, 0xea, 0xf4, 0xd5, 0x8d, 0xa9, 0x4e, 0xc8, 0xe7, 0x6d, 0x37, 0x95, 0x91, 0x79, 0xe4, 0xd3, 0xc2, 0x62, 0xac, 0x06, 0x49, 0x5c, 0x24, 0x32, 0xe0, 0x0a, 0x3a, 0x5e, 0xde, 0xdb, 0x0b, 0xee, 0x46, 0x14, 0xb8, 0x2a, 0x22, 0x88, 0x90, 0x81, 0x60, 0xdc, 0x4f, 0x5d, 0x64, 0x73, 0x19, 0xa7, 0xc4, 0x3d, 0x7e, 0x97, 0x5f, 0x17, 0x44, 0x0c, 0xcd, 0xec, 0x13 +}, +{ +0xbb, 0x16, 0xb0, 0x54, 0x2d, 0x0f, 0x41, 0x99, 0x42, 0x68, 0xbf, 0xe6, 0x89, 0x0d, 0x8c, 0xa1, 0x28, 0xdf, 0xce, 0x55, 0x87, 0xe9, 0x9b, 0x1e, 0x8e, 0x94, 0x69, 0xd9, 0x98, 0x11, 0xe1, 0xf8, 0x1d, 0x9e, 0x86, 0xc1, 0x57, 0xb9, 0x61, 0x35, 0xf6, 0x0e, 0x48, 0x03, 0xb5, 0x66, 0x70, 0x3e, 0x8b, 0x8a, 0x4b, 0xbd, 0x74, 0x1f, 0xe8, 0xdd, 0xb4, 0xc6, 0x1c, 0xa6, 0x25, 0x2e, 0xba, 0x78, 0xae, 0x08, 0x65, 0x7a, 0xf4, 0xea, 0x6c, 0x56, 0x4e, 0xa9, 0x8d, 0xd5, 0x37, 0x6d, 0xe7, 0xc8, 0xe4, 0x79, 0x91, 0x95, 0xac, 0x62, 0xc2, 0xd3, 0x24, 0x5c, 0x49, 0x06, 0x3a, 0x0a, 0xe0, 0x32, 0x0b, 0xdb, 0xde, 0x5e, 0xb8, 0x14, 0x46, 0xee, 0x90, 0x88, 0x22, 0x2a, 0x4f, 0xdc, 0x60, 0x81, 0x19, 0x73, 0x64, 0x5d, 0x7e, 0x3d, 0xc4, 0xa7, 0x44, 0x17, 0x5f, 0x97, 0x13, 0xec, 0xcd, 0x0c, 0xf3, 0xd2, 0x10, 0xff, 0xda, 0x21, 0xbc, 0xb6, 0x38, 0xf5, 0x92, 0x9d, 0x40, 0x8f, 0x51, 0xa3, 0x9f, 0xa8, 0x50, 0x3c, 0x02, 0x7f, 0x45, 0xf9, 0x33, 0x85, 0x43, 0x4d, 0xaa, 0xfb, 0xd0, 0xef, 0x58, 0xcf, 0x4a, 0x4c, 0xbe, 0x39, 0x6a, 0xcb, 0xb1, 0x5b, 0x20, 0xfc, 0x00, 0xed, 0x53, 0xd1, 0x2f, 0x84, 0x29, 0xe3, 0xd6, 0xb3, 0x52, 0x3b, 0x5a, 0xa0, 0x1b, 0x6e, 0x2c, 0x1a, 0x09, 0x83, 0xb2, 0x75, 0xeb, 0x27, 0x80, 0xe2, 0x07, 0x12, 0x05, 0x9a, 0x18, 0x96, 0x23, 0xc3, 0x04, 0xc7, 0x31, 0x15, 0x71, 0xd8, 0xe5, 0xf1, 0x34, 0xa5, 0xf7, 0xcc, 0x36, 0x3f, 0x93, 0x26, 0xb7, 0xfd, 0x72, 0xc0, 0x9c, 0xa4, 0xa2, 0xaf, 0xad, 0xd4, 0x47, 0xf0, 0xfa, 0x59, 0xc9, 0x7d, 0xca, 0x82, 0xab, 0x76, 0xfe, 0xd7, 0x67, 0x2b, 0x30, 0x01, 0x6f, 0xc5, 0xf2, 0x6b, 0x77, 0x7b, 0x63, 0x7c +}, +{ +0x2e, 0x25, 0x78, 0xba, 0xc6, 0xb4, 0xa6, 0x1c, 0x1f, 0x74, 0xdd, 0xe8, 0x8a, 0x8b, 0xbd, 0x4b, 0x66, 0xb5, 0x3e, 0x70, 0x0e, 0xf6, 0x03, 0x48, 0xb9, 0x57, 0x35, 0x61, 0x9e, 0x1d, 0xc1, 0x86, 0x11, 0x98, 0xf8, 0xe1, 0x94, 0x8e, 0xd9, 0x69, 0xe9, 0x87, 0x1e, 0x9b, 0xdf, 0x28, 0x55, 0xce, 0x0d, 0x89, 0xa1, 0x8c, 0x68, 0x42, 0xe6, 0xbf, 0x0f, 0x2d, 0x99, 0x41, 0x16, 0xbb, 0x54, 0xb0, 0xec, 0x13, 0x0c, 0xcd, 0x17, 0x44, 0x97, 0x5f, 0x3d, 0x7e, 0xa7, 0xc4, 0x73, 0x19, 0x5d, 0x64, 0xdc, 0x4f, 0x81, 0x60, 0x88, 0x90, 0x2a, 0x22, 0x14, 0xb8, 0xee, 0x46, 0xdb, 0x0b, 0x5e, 0xde, 0x0a, 0x3a, 0x32, 0xe0, 0x5c, 0x24, 0x06, 0x49, 0x62, 0xac, 0xd3, 0xc2, 0x79, 0xe4, 0x95, 0x91, 0x6d, 0x37, 0xc8, 0xe7, 0xa9, 0x4e, 0xd5, 0x8d, 0xea, 0xf4, 0x56, 0x6c, 0x08, 0xae, 0x7a, 0x65, 0x1a, 0x2c, 0x83, 0x09, 0xa0, 0x5a, 0x6e, 0x1b, 0xb3, 0xd6, 0x3b, 0x52, 0x84, 0x2f, 0xe3, 0x29, 0xed, 0x00, 0xd1, 0x53, 0x5b, 0xb1, 0xfc, 0x20, 0x39, 0xbe, 0xcb, 0x6a, 0xcf, 0x58, 0x4c, 0x4a, 0xfb, 0xaa, 0xef, 0xd0, 0x85, 0x33, 0x4d, 0x43, 0x7f, 0x02, 0xf9, 0x45, 0xa8, 0x9f, 0x3c, 0x50, 0x8f, 0x40, 0xa3, 0x51, 0xf5, 0x38, 0x9d, 0x92, 0x21, 0xda, 0xb6, 0xbc, 0xd2, 0xf3, 0xff, 0x10, 0x7b, 0x77, 0x7c, 0x63, 0xc5, 0x6f, 0x6b, 0xf2, 0x2b, 0x67, 0x01, 0x30, 0x76, 0xab, 0xd7, 0xfe, 0x7d, 0xc9, 0x82, 0xca, 0xf0, 0x47, 0x59, 0xfa, 0xaf, 0xa2, 0xd4, 0xad, 0xc0, 0x72, 0xa4, 0x9c, 0x26, 0x93, 0xfd, 0xb7, 0xcc, 0xf7, 0x3f, 0x36, 0xf1, 0xe5, 0xa5, 0x34, 0x15, 0x31, 0xd8, 0x71, 0xc3, 0x23, 0xc7, 0x04, 0x9a, 0x05, 0x96, 0x18, 0xe2, 0x80, 0x12, 0x07, 0x75, 0xb2, 0x27, 0xeb +}, +{ +0x5a, 0xa0, 0x1b, 0x6e, 0x2c, 0x1a, 0x09, 0x83, 0x2f, 0x84, 0x29, 0xe3, 0xd6, 0xb3, 0x52, 0x3b, 0xb1, 0x5b, 0x20, 0xfc, 0x00, 0xed, 0x53, 0xd1, 0x58, 0xcf, 0x4a, 0x4c, 0xbe, 0x39, 0x6a, 0xcb, 0x33, 0x85, 0x43, 0x4d, 0xaa, 0xfb, 0xd0, 0xef, 0x9f, 0xa8, 0x50, 0x3c, 0x02, 0x7f, 0x45, 0xf9, 0x38, 0xf5, 0x92, 0x9d, 0x40, 0x8f, 0x51, 0xa3, 0xf3, 0xd2, 0x10, 0xff, 0xda, 0x21, 0xbc, 0xb6, 0x6f, 0xc5, 0xf2, 0x6b, 0x77, 0x7b, 0x63, 0x7c, 0xab, 0x76, 0xfe, 0xd7, 0x67, 0x2b, 0x30, 0x01, 0x47, 0xf0, 0xfa, 0x59, 0xc9, 0x7d, 0xca, 0x82, 0x72, 0xc0, 0x9c, 0xa4, 0xa2, 0xaf, 0xad, 0xd4, 0xf7, 0xcc, 0x36, 0x3f, 0x93, 0x26, 0xb7, 0xfd, 0x31, 0x15, 0x71, 0xd8, 0xe5, 0xf1, 0x34, 0xa5, 0x05, 0x9a, 0x18, 0x96, 0x23, 0xc3, 0x04, 0xc7, 0xb2, 0x75, 0xeb, 0x27, 0x80, 0xe2, 0x07, 0x12, 0xb4, 0xc6, 0x1c, 0xa6, 0x25, 0x2e, 0xba, 0x78, 0x8b, 0x8a, 0x4b, 0xbd, 0x74, 0x1f, 0xe8, 0xdd, 0xf6, 0x0e, 0x48, 0x03, 0xb5, 0x66, 0x70, 0x3e, 0x1d, 0x9e, 0x86, 0xc1, 0x57, 0xb9, 0x61, 0x35, 0x8e, 0x94, 0x69, 0xd9, 0x98, 0x11, 0xe1, 0xf8, 0x28, 0xdf, 0xce, 0x55, 0x87, 0xe9, 0x9b, 0x1e, 0x42, 0x68, 0xbf, 0xe6, 0x89, 0x0d, 0x8c, 0xa1, 0xbb, 0x16, 0xb0, 0x54, 0x2d, 0x0f, 0x41, 0x99, 0x44, 0x17, 0x5f, 0x97, 0x13, 0xec, 0xcd, 0x0c, 0x19, 0x73, 0x64, 0x5d, 0x7e, 0x3d, 0xc4, 0xa7, 0x90, 0x88, 0x22, 0x2a, 0x4f, 0xdc, 0x60, 0x81, 0x0b, 0xdb, 0xde, 0x5e, 0xb8, 0x14, 0x46, 0xee, 0x24, 0x5c, 0x49, 0x06, 0x3a, 0x0a, 0xe0, 0x32, 0xe4, 0x79, 0x91, 0x95, 0xac, 0x62, 0xc2, 0xd3, 0x4e, 0xa9, 0x8d, 0xd5, 0x37, 0x6d, 0xe7, 0xc8, 0xae, 0x08, 0x65, 0x7a, 0xf4, 0xea, 0x6c, 0x56 +}, +{ +0x49, 0x06, 0x24, 0x5c, 0xe0, 0x32, 0x3a, 0x0a, 0x91, 0x95, 0xe4, 0x79, 0xc2, 0xd3, 0xac, 0x62, 0x8d, 0xd5, 0x4e, 0xa9, 0xe7, 0xc8, 0x37, 0x6d, 0x65, 0x7a, 0xae, 0x08, 0x6c, 0x56, 0xf4, 0xea, 0x5f, 0x97, 0x44, 0x17, 0xcd, 0x0c, 0x13, 0xec, 0x64, 0x5d, 0x19, 0x73, 0xc4, 0xa7, 0x7e, 0x3d, 0x22, 0x2a, 0x90, 0x88, 0x60, 0x81, 0x4f, 0xdc, 0xde, 0x5e, 0x0b, 0xdb, 0x46, 0xee, 0xb8, 0x14, 0x69, 0xd9, 0x8e, 0x94, 0xe1, 0xf8, 0x98, 0x11, 0xce, 0x55, 0x28, 0xdf, 0x9b, 0x1e, 0x87, 0xe9, 0xbf, 0xe6, 0x42, 0x68, 0x8c, 0xa1, 0x89, 0x0d, 0xb0, 0x54, 0xbb, 0x16, 0x41, 0x99, 0x2d, 0x0f, 0x1c, 0xa6, 0xb4, 0xc6, 0xba, 0x78, 0x25, 0x2e, 0x4b, 0xbd, 0x8b, 0x8a, 0xe8, 0xdd, 0x74, 0x1f, 0x48, 0x03, 0xf6, 0x0e, 0x70, 0x3e, 0xb5, 0x66, 0x86, 0xc1, 0x1d, 0x9e, 0x61, 0x35, 0x57, 0xb9, 0x36, 0x3f, 0xf7, 0xcc, 0xb7, 0xfd, 0x93, 0x26, 0x71, 0xd8, 0x31, 0x15, 0x34, 0xa5, 0xe5, 0xf1, 0x18, 0x96, 0x05, 0x9a, 0x04, 0xc7, 0x23, 0xc3, 0xeb, 0x27, 0xb2, 0x75, 0x07, 0x12, 0x80, 0xe2, 0xf2, 0x6b, 0x6f, 0xc5, 0x63, 0x7c, 0x77, 0x7b, 0xfe, 0xd7, 0xab, 0x76, 0x30, 0x01, 0x67, 0x2b, 0xfa, 0x59, 0x47, 0xf0, 0xca, 0x82, 0xc9, 0x7d, 0x9c, 0xa4, 0x72, 0xc0, 0xad, 0xd4, 0xa2, 0xaf, 0x43, 0x4d, 0x33, 0x85, 0xd0, 0xef, 0xaa, 0xfb, 0x50, 0x3c, 0x9f, 0xa8, 0x45, 0xf9, 0x02, 0x7f, 0x92, 0x9d, 0x38, 0xf5, 0x51, 0xa3, 0x40, 0x8f, 0x10, 0xff, 0xf3, 0xd2, 0xbc, 0xb6, 0xda, 0x21, 0x1b, 0x6e, 0x5a, 0xa0, 0x09, 0x83, 0x2c, 0x1a, 0x29, 0xe3, 0x2f, 0x84, 0x52, 0x3b, 0xd6, 0xb3, 0x20, 0xfc, 0xb1, 0x5b, 0x53, 0xd1, 0x00, 0xed, 0x4a, 0x4c, 0x58, 0xcf, 0x6a, 0xcb, 0xbe, 0x39 +}, +{ +0x81, 0x60, 0xdc, 0x4f, 0x2a, 0x22, 0x88, 0x90, 0xee, 0x46, 0x14, 0xb8, 0x5e, 0xde, 0xdb, 0x0b, 0x0c, 0xcd, 0xec, 0x13, 0x97, 0x5f, 0x17, 0x44, 0xa7, 0xc4, 0x3d, 0x7e, 0x5d, 0x64, 0x73, 0x19, 0xc8, 0xe7, 0x6d, 0x37, 0xd5, 0x8d, 0xa9, 0x4e, 0x56, 0x6c, 0xea, 0xf4, 0x7a, 0x65, 0x08, 0xae, 0x32, 0xe0, 0x0a, 0x3a, 0x06, 0x49, 0x5c, 0x24, 0xd3, 0xc2, 0x62, 0xac, 0x95, 0x91, 0x79, 0xe4, 0x3e, 0x70, 0x66, 0xb5, 0x03, 0x48, 0x0e, 0xf6, 0x35, 0x61, 0xb9, 0x57, 0xc1, 0x86, 0x9e, 0x1d, 0x78, 0xba, 0x2e, 0x25, 0xa6, 0x1c, 0xc6, 0xb4, 0xdd, 0xe8, 0x1f, 0x74, 0xbd, 0x4b, 0x8a, 0x8b, 0xa1, 0x8c, 0x0d, 0x89, 0xe6, 0xbf, 0x68, 0x42, 0x99, 0x41, 0x0f, 0x2d, 0x54, 0xb0, 0x16, 0xbb, 0xf8, 0xe1, 0x11, 0x98, 0xd9, 0x69, 0x94, 0x8e, 0x1e, 0x9b, 0xe9, 0x87, 0x55, 0xce, 0xdf, 0x28, 0x82, 0xca, 0x7d, 0xc9, 0x59, 0xfa, 0xf0, 0x47, 0xd4, 0xad, 0xaf, 0xa2, 0xa4, 0x9c, 0xc0, 0x72, 0x7c, 0x63, 0x7b, 0x77, 0x6b, 0xf2, 0xc5, 0x6f, 0x01, 0x30, 0x2b, 0x67, 0xd7, 0xfe, 0x76, 0xab, 0xc7, 0x04, 0xc3, 0x23, 0x96, 0x18, 0x9a, 0x05, 0x12, 0x07, 0xe2, 0x80, 0x27, 0xeb, 0x75, 0xb2, 0xfd, 0xb7, 0x26, 0x93, 0x3f, 0x36, 0xcc, 0xf7, 0xa5, 0x34, 0xf1, 0xe5, 0xd8, 0x71, 0x15, 0x31, 0xd1, 0x53, 0xed, 0x00, 0xfc, 0x20, 0x5b, 0xb1, 0xcb, 0x6a, 0x39, 0xbe, 0x4c, 0x4a, 0xcf, 0x58, 0x83, 0x09, 0x1a, 0x2c, 0x6e, 0x1b, 0xa0, 0x5a, 0x3b, 0x52, 0xb3, 0xd6, 0xe3, 0x29, 0x84, 0x2f, 0xa3, 0x51, 0x8f, 0x40, 0x9d, 0x92, 0xf5, 0x38, 0xb6, 0xbc, 0x21, 0xda, 0xff, 0x10, 0xd2, 0xf3, 0xef, 0xd0, 0xfb, 0xaa, 0x4d, 0x43, 0x85, 0x33, 0xf9, 0x45, 0x7f, 0x02, 0x3c, 0x50, 0xa8, 0x9f +}, +{ +0xf9, 0x45, 0x7f, 0x02, 0x3c, 0x50, 0xa8, 0x9f, 0xef, 0xd0, 0xfb, 0xaa, 0x4d, 0x43, 0x85, 0x33, 0xb6, 0xbc, 0x21, 0xda, 0xff, 0x10, 0xd2, 0xf3, 0xa3, 0x51, 0x8f, 0x40, 0x9d, 0x92, 0xf5, 0x38, 0x3b, 0x52, 0xb3, 0xd6, 0xe3, 0x29, 0x84, 0x2f, 0x83, 0x09, 0x1a, 0x2c, 0x6e, 0x1b, 0xa0, 0x5a, 0xcb, 0x6a, 0x39, 0xbe, 0x4c, 0x4a, 0xcf, 0x58, 0xd1, 0x53, 0xed, 0x00, 0xfc, 0x20, 0x5b, 0xb1, 0xa5, 0x34, 0xf1, 0xe5, 0xd8, 0x71, 0x15, 0x31, 0xfd, 0xb7, 0x26, 0x93, 0x3f, 0x36, 0xcc, 0xf7, 0x12, 0x07, 0xe2, 0x80, 0x27, 0xeb, 0x75, 0xb2, 0xc7, 0x04, 0xc3, 0x23, 0x96, 0x18, 0x9a, 0x05, 0x01, 0x30, 0x2b, 0x67, 0xd7, 0xfe, 0x76, 0xab, 0x7c, 0x63, 0x7b, 0x77, 0x6b, 0xf2, 0xc5, 0x6f, 0xd4, 0xad, 0xaf, 0xa2, 0xa4, 0x9c, 0xc0, 0x72, 0x82, 0xca, 0x7d, 0xc9, 0x59, 0xfa, 0xf0, 0x47, 0x1e, 0x9b, 0xe9, 0x87, 0x55, 0xce, 0xdf, 0x28, 0xf8, 0xe1, 0x11, 0x98, 0xd9, 0x69, 0x94, 0x8e, 0x99, 0x41, 0x0f, 0x2d, 0x54, 0xb0, 0x16, 0xbb, 0xa1, 0x8c, 0x0d, 0x89, 0xe6, 0xbf, 0x68, 0x42, 0xdd, 0xe8, 0x1f, 0x74, 0xbd, 0x4b, 0x8a, 0x8b, 0x78, 0xba, 0x2e, 0x25, 0xa6, 0x1c, 0xc6, 0xb4, 0x35, 0x61, 0xb9, 0x57, 0xc1, 0x86, 0x9e, 0x1d, 0x3e, 0x70, 0x66, 0xb5, 0x03, 0x48, 0x0e, 0xf6, 0xd3, 0xc2, 0x62, 0xac, 0x95, 0x91, 0x79, 0xe4, 0x32, 0xe0, 0x0a, 0x3a, 0x06, 0x49, 0x5c, 0x24, 0x56, 0x6c, 0xea, 0xf4, 0x7a, 0x65, 0x08, 0xae, 0xc8, 0xe7, 0x6d, 0x37, 0xd5, 0x8d, 0xa9, 0x4e, 0xa7, 0xc4, 0x3d, 0x7e, 0x5d, 0x64, 0x73, 0x19, 0x0c, 0xcd, 0xec, 0x13, 0x97, 0x5f, 0x17, 0x44, 0xee, 0x46, 0x14, 0xb8, 0x5e, 0xde, 0xdb, 0x0b, 0x81, 0x60, 0xdc, 0x4f, 0x2a, 0x22, 0x88, 0x90 +}, +{ +0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6 +}, +{ +0x26, 0x93, 0xfd, 0xb7, 0xcc, 0xf7, 0x3f, 0x36, 0xf1, 0xe5, 0xa5, 0x34, 0x15, 0x31, 0xd8, 0x71, 0xc3, 0x23, 0xc7, 0x04, 0x9a, 0x05, 0x96, 0x18, 0xe2, 0x80, 0x12, 0x07, 0x75, 0xb2, 0x27, 0xeb, 0x7b, 0x77, 0x7c, 0x63, 0xc5, 0x6f, 0x6b, 0xf2, 0x2b, 0x67, 0x01, 0x30, 0x76, 0xab, 0xd7, 0xfe, 0x7d, 0xc9, 0x82, 0xca, 0xf0, 0x47, 0x59, 0xfa, 0xaf, 0xa2, 0xd4, 0xad, 0xc0, 0x72, 0xa4, 0x9c, 0xfb, 0xaa, 0xef, 0xd0, 0x85, 0x33, 0x4d, 0x43, 0x7f, 0x02, 0xf9, 0x45, 0xa8, 0x9f, 0x3c, 0x50, 0x8f, 0x40, 0xa3, 0x51, 0xf5, 0x38, 0x9d, 0x92, 0x21, 0xda, 0xb6, 0xbc, 0xd2, 0xf3, 0xff, 0x10, 0x1a, 0x2c, 0x83, 0x09, 0xa0, 0x5a, 0x6e, 0x1b, 0xb3, 0xd6, 0x3b, 0x52, 0x84, 0x2f, 0xe3, 0x29, 0xed, 0x00, 0xd1, 0x53, 0x5b, 0xb1, 0xfc, 0x20, 0x39, 0xbe, 0xcb, 0x6a, 0xcf, 0x58, 0x4c, 0x4a, 0x0a, 0x3a, 0x32, 0xe0, 0x5c, 0x24, 0x06, 0x49, 0x62, 0xac, 0xd3, 0xc2, 0x79, 0xe4, 0x95, 0x91, 0x6d, 0x37, 0xc8, 0xe7, 0xa9, 0x4e, 0xd5, 0x8d, 0xea, 0xf4, 0x56, 0x6c, 0x08, 0xae, 0x7a, 0x65, 0xec, 0x13, 0x0c, 0xcd, 0x17, 0x44, 0x97, 0x5f, 0x3d, 0x7e, 0xa7, 0xc4, 0x73, 0x19, 0x5d, 0x64, 0xdc, 0x4f, 0x81, 0x60, 0x88, 0x90, 0x2a, 0x22, 0x14, 0xb8, 0xee, 0x46, 0xdb, 0x0b, 0x5e, 0xde, 0x11, 0x98, 0xf8, 0xe1, 0x94, 0x8e, 0xd9, 0x69, 0xe9, 0x87, 0x1e, 0x9b, 0xdf, 0x28, 0x55, 0xce, 0x0d, 0x89, 0xa1, 0x8c, 0x68, 0x42, 0xe6, 0xbf, 0x0f, 0x2d, 0x99, 0x41, 0x16, 0xbb, 0x54, 0xb0, 0x2e, 0x25, 0x78, 0xba, 0xc6, 0xb4, 0xa6, 0x1c, 0x1f, 0x74, 0xdd, 0xe8, 0x8a, 0x8b, 0xbd, 0x4b, 0x66, 0xb5, 0x3e, 0x70, 0x0e, 0xf6, 0x03, 0x48, 0xb9, 0x57, 0x35, 0x61, 0x9e, 0x1d, 0xc1, 0x86 +} +}, +{ +{ +0xb4, 0xc6, 0x1c, 0xa6, 0x25, 0x2e, 0xba, 0x78, 0x8b, 0x8a, 0x4b, 0xbd, 0x74, 0x1f, 0xe8, 0xdd, 0xf6, 0x0e, 0x48, 0x03, 0xb5, 0x66, 0x70, 0x3e, 0x1d, 0x9e, 0x86, 0xc1, 0x57, 0xb9, 0x61, 0x35, 0x8e, 0x94, 0x69, 0xd9, 0x98, 0x11, 0xe1, 0xf8, 0x28, 0xdf, 0xce, 0x55, 0x87, 0xe9, 0x9b, 0x1e, 0x42, 0x68, 0xbf, 0xe6, 0x89, 0x0d, 0x8c, 0xa1, 0xbb, 0x16, 0xb0, 0x54, 0x2d, 0x0f, 0x41, 0x99, 0x44, 0x17, 0x5f, 0x97, 0x13, 0xec, 0xcd, 0x0c, 0x19, 0x73, 0x64, 0x5d, 0x7e, 0x3d, 0xc4, 0xa7, 0x90, 0x88, 0x22, 0x2a, 0x4f, 0xdc, 0x60, 0x81, 0x0b, 0xdb, 0xde, 0x5e, 0xb8, 0x14, 0x46, 0xee, 0x24, 0x5c, 0x49, 0x06, 0x3a, 0x0a, 0xe0, 0x32, 0xe4, 0x79, 0x91, 0x95, 0xac, 0x62, 0xc2, 0xd3, 0x4e, 0xa9, 0x8d, 0xd5, 0x37, 0x6d, 0xe7, 0xc8, 0xae, 0x08, 0x65, 0x7a, 0xf4, 0xea, 0x6c, 0x56, 0x5a, 0xa0, 0x1b, 0x6e, 0x2c, 0x1a, 0x09, 0x83, 0x2f, 0x84, 0x29, 0xe3, 0xd6, 0xb3, 0x52, 0x3b, 0xb1, 0x5b, 0x20, 0xfc, 0x00, 0xed, 0x53, 0xd1, 0x58, 0xcf, 0x4a, 0x4c, 0xbe, 0x39, 0x6a, 0xcb, 0x33, 0x85, 0x43, 0x4d, 0xaa, 0xfb, 0xd0, 0xef, 0x9f, 0xa8, 0x50, 0x3c, 0x02, 0x7f, 0x45, 0xf9, 0x38, 0xf5, 0x92, 0x9d, 0x40, 0x8f, 0x51, 0xa3, 0xf3, 0xd2, 0x10, 0xff, 0xda, 0x21, 0xbc, 0xb6, 0x6f, 0xc5, 0xf2, 0x6b, 0x77, 0x7b, 0x63, 0x7c, 0xab, 0x76, 0xfe, 0xd7, 0x67, 0x2b, 0x30, 0x01, 0x47, 0xf0, 0xfa, 0x59, 0xc9, 0x7d, 0xca, 0x82, 0x72, 0xc0, 0x9c, 0xa4, 0xa2, 0xaf, 0xad, 0xd4, 0xf7, 0xcc, 0x36, 0x3f, 0x93, 0x26, 0xb7, 0xfd, 0x31, 0x15, 0x71, 0xd8, 0xe5, 0xf1, 0x34, 0xa5, 0x05, 0x9a, 0x18, 0x96, 0x23, 0xc3, 0x04, 0xc7, 0xb2, 0x75, 0xeb, 0x27, 0x80, 0xe2, 0x07, 0x12 +}, +{ +0x8b, 0x8a, 0x4b, 0xbd, 0x74, 0x1f, 0xe8, 0xdd, 0xb4, 0xc6, 0x1c, 0xa6, 0x25, 0x2e, 0xba, 0x78, 0x1d, 0x9e, 0x86, 0xc1, 0x57, 0xb9, 0x61, 0x35, 0xf6, 0x0e, 0x48, 0x03, 0xb5, 0x66, 0x70, 0x3e, 0x28, 0xdf, 0xce, 0x55, 0x87, 0xe9, 0x9b, 0x1e, 0x8e, 0x94, 0x69, 0xd9, 0x98, 0x11, 0xe1, 0xf8, 0xbb, 0x16, 0xb0, 0x54, 0x2d, 0x0f, 0x41, 0x99, 0x42, 0x68, 0xbf, 0xe6, 0x89, 0x0d, 0x8c, 0xa1, 0x19, 0x73, 0x64, 0x5d, 0x7e, 0x3d, 0xc4, 0xa7, 0x44, 0x17, 0x5f, 0x97, 0x13, 0xec, 0xcd, 0x0c, 0x0b, 0xdb, 0xde, 0x5e, 0xb8, 0x14, 0x46, 0xee, 0x90, 0x88, 0x22, 0x2a, 0x4f, 0xdc, 0x60, 0x81, 0xe4, 0x79, 0x91, 0x95, 0xac, 0x62, 0xc2, 0xd3, 0x24, 0x5c, 0x49, 0x06, 0x3a, 0x0a, 0xe0, 0x32, 0xae, 0x08, 0x65, 0x7a, 0xf4, 0xea, 0x6c, 0x56, 0x4e, 0xa9, 0x8d, 0xd5, 0x37, 0x6d, 0xe7, 0xc8, 0x2f, 0x84, 0x29, 0xe3, 0xd6, 0xb3, 0x52, 0x3b, 0x5a, 0xa0, 0x1b, 0x6e, 0x2c, 0x1a, 0x09, 0x83, 0x58, 0xcf, 0x4a, 0x4c, 0xbe, 0x39, 0x6a, 0xcb, 0xb1, 0x5b, 0x20, 0xfc, 0x00, 0xed, 0x53, 0xd1, 0x9f, 0xa8, 0x50, 0x3c, 0x02, 0x7f, 0x45, 0xf9, 0x33, 0x85, 0x43, 0x4d, 0xaa, 0xfb, 0xd0, 0xef, 0xf3, 0xd2, 0x10, 0xff, 0xda, 0x21, 0xbc, 0xb6, 0x38, 0xf5, 0x92, 0x9d, 0x40, 0x8f, 0x51, 0xa3, 0xab, 0x76, 0xfe, 0xd7, 0x67, 0x2b, 0x30, 0x01, 0x6f, 0xc5, 0xf2, 0x6b, 0x77, 0x7b, 0x63, 0x7c, 0x72, 0xc0, 0x9c, 0xa4, 0xa2, 0xaf, 0xad, 0xd4, 0x47, 0xf0, 0xfa, 0x59, 0xc9, 0x7d, 0xca, 0x82, 0x31, 0x15, 0x71, 0xd8, 0xe5, 0xf1, 0x34, 0xa5, 0xf7, 0xcc, 0x36, 0x3f, 0x93, 0x26, 0xb7, 0xfd, 0xb2, 0x75, 0xeb, 0x27, 0x80, 0xe2, 0x07, 0x12, 0x05, 0x9a, 0x18, 0x96, 0x23, 0xc3, 0x04, 0xc7 +}, +{ +0x74, 0x1f, 0xe8, 0xdd, 0x8b, 0x8a, 0x4b, 0xbd, 0x25, 0x2e, 0xba, 0x78, 0xb4, 0xc6, 0x1c, 0xa6, 0x57, 0xb9, 0x61, 0x35, 0x1d, 0x9e, 0x86, 0xc1, 0xb5, 0x66, 0x70, 0x3e, 0xf6, 0x0e, 0x48, 0x03, 0x87, 0xe9, 0x9b, 0x1e, 0x28, 0xdf, 0xce, 0x55, 0x98, 0x11, 0xe1, 0xf8, 0x8e, 0x94, 0x69, 0xd9, 0x2d, 0x0f, 0x41, 0x99, 0xbb, 0x16, 0xb0, 0x54, 0x89, 0x0d, 0x8c, 0xa1, 0x42, 0x68, 0xbf, 0xe6, 0x7e, 0x3d, 0xc4, 0xa7, 0x19, 0x73, 0x64, 0x5d, 0x13, 0xec, 0xcd, 0x0c, 0x44, 0x17, 0x5f, 0x97, 0xb8, 0x14, 0x46, 0xee, 0x0b, 0xdb, 0xde, 0x5e, 0x4f, 0xdc, 0x60, 0x81, 0x90, 0x88, 0x22, 0x2a, 0xac, 0x62, 0xc2, 0xd3, 0xe4, 0x79, 0x91, 0x95, 0x3a, 0x0a, 0xe0, 0x32, 0x24, 0x5c, 0x49, 0x06, 0xf4, 0xea, 0x6c, 0x56, 0xae, 0x08, 0x65, 0x7a, 0x37, 0x6d, 0xe7, 0xc8, 0x4e, 0xa9, 0x8d, 0xd5, 0xd6, 0xb3, 0x52, 0x3b, 0x2f, 0x84, 0x29, 0xe3, 0x2c, 0x1a, 0x09, 0x83, 0x5a, 0xa0, 0x1b, 0x6e, 0xbe, 0x39, 0x6a, 0xcb, 0x58, 0xcf, 0x4a, 0x4c, 0x00, 0xed, 0x53, 0xd1, 0xb1, 0x5b, 0x20, 0xfc, 0x02, 0x7f, 0x45, 0xf9, 0x9f, 0xa8, 0x50, 0x3c, 0xaa, 0xfb, 0xd0, 0xef, 0x33, 0x85, 0x43, 0x4d, 0xda, 0x21, 0xbc, 0xb6, 0xf3, 0xd2, 0x10, 0xff, 0x40, 0x8f, 0x51, 0xa3, 0x38, 0xf5, 0x92, 0x9d, 0x67, 0x2b, 0x30, 0x01, 0xab, 0x76, 0xfe, 0xd7, 0x77, 0x7b, 0x63, 0x7c, 0x6f, 0xc5, 0xf2, 0x6b, 0xa2, 0xaf, 0xad, 0xd4, 0x72, 0xc0, 0x9c, 0xa4, 0xc9, 0x7d, 0xca, 0x82, 0x47, 0xf0, 0xfa, 0x59, 0xe5, 0xf1, 0x34, 0xa5, 0x31, 0x15, 0x71, 0xd8, 0x93, 0x26, 0xb7, 0xfd, 0xf7, 0xcc, 0x36, 0x3f, 0x80, 0xe2, 0x07, 0x12, 0xb2, 0x75, 0xeb, 0x27, 0x23, 0xc3, 0x04, 0xc7, 0x05, 0x9a, 0x18, 0x96 +}, +{ +0x81, 0x60, 0xdc, 0x4f, 0x2a, 0x22, 0x88, 0x90, 0xee, 0x46, 0x14, 0xb8, 0x5e, 0xde, 0xdb, 0x0b, 0x0c, 0xcd, 0xec, 0x13, 0x97, 0x5f, 0x17, 0x44, 0xa7, 0xc4, 0x3d, 0x7e, 0x5d, 0x64, 0x73, 0x19, 0xc8, 0xe7, 0x6d, 0x37, 0xd5, 0x8d, 0xa9, 0x4e, 0x56, 0x6c, 0xea, 0xf4, 0x7a, 0x65, 0x08, 0xae, 0x32, 0xe0, 0x0a, 0x3a, 0x06, 0x49, 0x5c, 0x24, 0xd3, 0xc2, 0x62, 0xac, 0x95, 0x91, 0x79, 0xe4, 0x3e, 0x70, 0x66, 0xb5, 0x03, 0x48, 0x0e, 0xf6, 0x35, 0x61, 0xb9, 0x57, 0xc1, 0x86, 0x9e, 0x1d, 0x78, 0xba, 0x2e, 0x25, 0xa6, 0x1c, 0xc6, 0xb4, 0xdd, 0xe8, 0x1f, 0x74, 0xbd, 0x4b, 0x8a, 0x8b, 0xa1, 0x8c, 0x0d, 0x89, 0xe6, 0xbf, 0x68, 0x42, 0x99, 0x41, 0x0f, 0x2d, 0x54, 0xb0, 0x16, 0xbb, 0xf8, 0xe1, 0x11, 0x98, 0xd9, 0x69, 0x94, 0x8e, 0x1e, 0x9b, 0xe9, 0x87, 0x55, 0xce, 0xdf, 0x28, 0x82, 0xca, 0x7d, 0xc9, 0x59, 0xfa, 0xf0, 0x47, 0xd4, 0xad, 0xaf, 0xa2, 0xa4, 0x9c, 0xc0, 0x72, 0x7c, 0x63, 0x7b, 0x77, 0x6b, 0xf2, 0xc5, 0x6f, 0x01, 0x30, 0x2b, 0x67, 0xd7, 0xfe, 0x76, 0xab, 0xc7, 0x04, 0xc3, 0x23, 0x96, 0x18, 0x9a, 0x05, 0x12, 0x07, 0xe2, 0x80, 0x27, 0xeb, 0x75, 0xb2, 0xfd, 0xb7, 0x26, 0x93, 0x3f, 0x36, 0xcc, 0xf7, 0xa5, 0x34, 0xf1, 0xe5, 0xd8, 0x71, 0x15, 0x31, 0xd1, 0x53, 0xed, 0x00, 0xfc, 0x20, 0x5b, 0xb1, 0xcb, 0x6a, 0x39, 0xbe, 0x4c, 0x4a, 0xcf, 0x58, 0x83, 0x09, 0x1a, 0x2c, 0x6e, 0x1b, 0xa0, 0x5a, 0x3b, 0x52, 0xb3, 0xd6, 0xe3, 0x29, 0x84, 0x2f, 0xa3, 0x51, 0x8f, 0x40, 0x9d, 0x92, 0xf5, 0x38, 0xb6, 0xbc, 0x21, 0xda, 0xff, 0x10, 0xd2, 0xf3, 0xef, 0xd0, 0xfb, 0xaa, 0x4d, 0x43, 0x85, 0x33, 0xf9, 0x45, 0x7f, 0x02, 0x3c, 0x50, 0xa8, 0x9f +}, +{ +0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6 +}, +{ +0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08 +}, +{ +0x35, 0x61, 0xb9, 0x57, 0xc1, 0x86, 0x9e, 0x1d, 0x3e, 0x70, 0x66, 0xb5, 0x03, 0x48, 0x0e, 0xf6, 0xdd, 0xe8, 0x1f, 0x74, 0xbd, 0x4b, 0x8a, 0x8b, 0x78, 0xba, 0x2e, 0x25, 0xa6, 0x1c, 0xc6, 0xb4, 0x99, 0x41, 0x0f, 0x2d, 0x54, 0xb0, 0x16, 0xbb, 0xa1, 0x8c, 0x0d, 0x89, 0xe6, 0xbf, 0x68, 0x42, 0x1e, 0x9b, 0xe9, 0x87, 0x55, 0xce, 0xdf, 0x28, 0xf8, 0xe1, 0x11, 0x98, 0xd9, 0x69, 0x94, 0x8e, 0xee, 0x46, 0x14, 0xb8, 0x5e, 0xde, 0xdb, 0x0b, 0x81, 0x60, 0xdc, 0x4f, 0x2a, 0x22, 0x88, 0x90, 0xa7, 0xc4, 0x3d, 0x7e, 0x5d, 0x64, 0x73, 0x19, 0x0c, 0xcd, 0xec, 0x13, 0x97, 0x5f, 0x17, 0x44, 0x56, 0x6c, 0xea, 0xf4, 0x7a, 0x65, 0x08, 0xae, 0xc8, 0xe7, 0x6d, 0x37, 0xd5, 0x8d, 0xa9, 0x4e, 0xd3, 0xc2, 0x62, 0xac, 0x95, 0x91, 0x79, 0xe4, 0x32, 0xe0, 0x0a, 0x3a, 0x06, 0x49, 0x5c, 0x24, 0xcb, 0x6a, 0x39, 0xbe, 0x4c, 0x4a, 0xcf, 0x58, 0xd1, 0x53, 0xed, 0x00, 0xfc, 0x20, 0x5b, 0xb1, 0x3b, 0x52, 0xb3, 0xd6, 0xe3, 0x29, 0x84, 0x2f, 0x83, 0x09, 0x1a, 0x2c, 0x6e, 0x1b, 0xa0, 0x5a, 0xb6, 0xbc, 0x21, 0xda, 0xff, 0x10, 0xd2, 0xf3, 0xa3, 0x51, 0x8f, 0x40, 0x9d, 0x92, 0xf5, 0x38, 0xf9, 0x45, 0x7f, 0x02, 0x3c, 0x50, 0xa8, 0x9f, 0xef, 0xd0, 0xfb, 0xaa, 0x4d, 0x43, 0x85, 0x33, 0xd4, 0xad, 0xaf, 0xa2, 0xa4, 0x9c, 0xc0, 0x72, 0x82, 0xca, 0x7d, 0xc9, 0x59, 0xfa, 0xf0, 0x47, 0x01, 0x30, 0x2b, 0x67, 0xd7, 0xfe, 0x76, 0xab, 0x7c, 0x63, 0x7b, 0x77, 0x6b, 0xf2, 0xc5, 0x6f, 0x12, 0x07, 0xe2, 0x80, 0x27, 0xeb, 0x75, 0xb2, 0xc7, 0x04, 0xc3, 0x23, 0x96, 0x18, 0x9a, 0x05, 0xa5, 0x34, 0xf1, 0xe5, 0xd8, 0x71, 0x15, 0x31, 0xfd, 0xb7, 0x26, 0x93, 0x3f, 0x36, 0xcc, 0xf7 +}, +{ +0xb0, 0x54, 0xbb, 0x16, 0x41, 0x99, 0x2d, 0x0f, 0xbf, 0xe6, 0x42, 0x68, 0x8c, 0xa1, 0x89, 0x0d, 0xce, 0x55, 0x28, 0xdf, 0x9b, 0x1e, 0x87, 0xe9, 0x69, 0xd9, 0x8e, 0x94, 0xe1, 0xf8, 0x98, 0x11, 0x86, 0xc1, 0x1d, 0x9e, 0x61, 0x35, 0x57, 0xb9, 0x48, 0x03, 0xf6, 0x0e, 0x70, 0x3e, 0xb5, 0x66, 0x4b, 0xbd, 0x8b, 0x8a, 0xe8, 0xdd, 0x74, 0x1f, 0x1c, 0xa6, 0xb4, 0xc6, 0xba, 0x78, 0x25, 0x2e, 0x65, 0x7a, 0xae, 0x08, 0x6c, 0x56, 0xf4, 0xea, 0x8d, 0xd5, 0x4e, 0xa9, 0xe7, 0xc8, 0x37, 0x6d, 0x91, 0x95, 0xe4, 0x79, 0xc2, 0xd3, 0xac, 0x62, 0x49, 0x06, 0x24, 0x5c, 0xe0, 0x32, 0x3a, 0x0a, 0xde, 0x5e, 0x0b, 0xdb, 0x46, 0xee, 0xb8, 0x14, 0x22, 0x2a, 0x90, 0x88, 0x60, 0x81, 0x4f, 0xdc, 0x64, 0x5d, 0x19, 0x73, 0xc4, 0xa7, 0x7e, 0x3d, 0x5f, 0x97, 0x44, 0x17, 0xcd, 0x0c, 0x13, 0xec, 0x10, 0xff, 0xf3, 0xd2, 0xbc, 0xb6, 0xda, 0x21, 0x92, 0x9d, 0x38, 0xf5, 0x51, 0xa3, 0x40, 0x8f, 0x50, 0x3c, 0x9f, 0xa8, 0x45, 0xf9, 0x02, 0x7f, 0x43, 0x4d, 0x33, 0x85, 0xd0, 0xef, 0xaa, 0xfb, 0x4a, 0x4c, 0x58, 0xcf, 0x6a, 0xcb, 0xbe, 0x39, 0x20, 0xfc, 0xb1, 0x5b, 0x53, 0xd1, 0x00, 0xed, 0x29, 0xe3, 0x2f, 0x84, 0x52, 0x3b, 0xd6, 0xb3, 0x1b, 0x6e, 0x5a, 0xa0, 0x09, 0x83, 0x2c, 0x1a, 0xeb, 0x27, 0xb2, 0x75, 0x07, 0x12, 0x80, 0xe2, 0x18, 0x96, 0x05, 0x9a, 0x04, 0xc7, 0x23, 0xc3, 0x71, 0xd8, 0x31, 0x15, 0x34, 0xa5, 0xe5, 0xf1, 0x36, 0x3f, 0xf7, 0xcc, 0xb7, 0xfd, 0x93, 0x26, 0x9c, 0xa4, 0x72, 0xc0, 0xad, 0xd4, 0xa2, 0xaf, 0xfa, 0x59, 0x47, 0xf0, 0xca, 0x82, 0xc9, 0x7d, 0xfe, 0xd7, 0xab, 0x76, 0x30, 0x01, 0x67, 0x2b, 0xf2, 0x6b, 0x6f, 0xc5, 0x63, 0x7c, 0x77, 0x7b +}, +{ +0xb4, 0xc6, 0x1c, 0xa6, 0x25, 0x2e, 0xba, 0x78, 0x8b, 0x8a, 0x4b, 0xbd, 0x74, 0x1f, 0xe8, 0xdd, 0xf6, 0x0e, 0x48, 0x03, 0xb5, 0x66, 0x70, 0x3e, 0x1d, 0x9e, 0x86, 0xc1, 0x57, 0xb9, 0x61, 0x35, 0x8e, 0x94, 0x69, 0xd9, 0x98, 0x11, 0xe1, 0xf8, 0x28, 0xdf, 0xce, 0x55, 0x87, 0xe9, 0x9b, 0x1e, 0x42, 0x68, 0xbf, 0xe6, 0x89, 0x0d, 0x8c, 0xa1, 0xbb, 0x16, 0xb0, 0x54, 0x2d, 0x0f, 0x41, 0x99, 0x44, 0x17, 0x5f, 0x97, 0x13, 0xec, 0xcd, 0x0c, 0x19, 0x73, 0x64, 0x5d, 0x7e, 0x3d, 0xc4, 0xa7, 0x90, 0x88, 0x22, 0x2a, 0x4f, 0xdc, 0x60, 0x81, 0x0b, 0xdb, 0xde, 0x5e, 0xb8, 0x14, 0x46, 0xee, 0x24, 0x5c, 0x49, 0x06, 0x3a, 0x0a, 0xe0, 0x32, 0xe4, 0x79, 0x91, 0x95, 0xac, 0x62, 0xc2, 0xd3, 0x4e, 0xa9, 0x8d, 0xd5, 0x37, 0x6d, 0xe7, 0xc8, 0xae, 0x08, 0x65, 0x7a, 0xf4, 0xea, 0x6c, 0x56, 0x5a, 0xa0, 0x1b, 0x6e, 0x2c, 0x1a, 0x09, 0x83, 0x2f, 0x84, 0x29, 0xe3, 0xd6, 0xb3, 0x52, 0x3b, 0xb1, 0x5b, 0x20, 0xfc, 0x00, 0xed, 0x53, 0xd1, 0x58, 0xcf, 0x4a, 0x4c, 0xbe, 0x39, 0x6a, 0xcb, 0x33, 0x85, 0x43, 0x4d, 0xaa, 0xfb, 0xd0, 0xef, 0x9f, 0xa8, 0x50, 0x3c, 0x02, 0x7f, 0x45, 0xf9, 0x38, 0xf5, 0x92, 0x9d, 0x40, 0x8f, 0x51, 0xa3, 0xf3, 0xd2, 0x10, 0xff, 0xda, 0x21, 0xbc, 0xb6, 0x6f, 0xc5, 0xf2, 0x6b, 0x77, 0x7b, 0x63, 0x7c, 0xab, 0x76, 0xfe, 0xd7, 0x67, 0x2b, 0x30, 0x01, 0x47, 0xf0, 0xfa, 0x59, 0xc9, 0x7d, 0xca, 0x82, 0x72, 0xc0, 0x9c, 0xa4, 0xa2, 0xaf, 0xad, 0xd4, 0xf7, 0xcc, 0x36, 0x3f, 0x93, 0x26, 0xb7, 0xfd, 0x31, 0x15, 0x71, 0xd8, 0xe5, 0xf1, 0x34, 0xa5, 0x05, 0x9a, 0x18, 0x96, 0x23, 0xc3, 0x04, 0xc7, 0xb2, 0x75, 0xeb, 0x27, 0x80, 0xe2, 0x07, 0x12 +}, +{ +0xec, 0x13, 0x0c, 0xcd, 0x17, 0x44, 0x97, 0x5f, 0x3d, 0x7e, 0xa7, 0xc4, 0x73, 0x19, 0x5d, 0x64, 0xdc, 0x4f, 0x81, 0x60, 0x88, 0x90, 0x2a, 0x22, 0x14, 0xb8, 0xee, 0x46, 0xdb, 0x0b, 0x5e, 0xde, 0x0a, 0x3a, 0x32, 0xe0, 0x5c, 0x24, 0x06, 0x49, 0x62, 0xac, 0xd3, 0xc2, 0x79, 0xe4, 0x95, 0x91, 0x6d, 0x37, 0xc8, 0xe7, 0xa9, 0x4e, 0xd5, 0x8d, 0xea, 0xf4, 0x56, 0x6c, 0x08, 0xae, 0x7a, 0x65, 0x2e, 0x25, 0x78, 0xba, 0xc6, 0xb4, 0xa6, 0x1c, 0x1f, 0x74, 0xdd, 0xe8, 0x8a, 0x8b, 0xbd, 0x4b, 0x66, 0xb5, 0x3e, 0x70, 0x0e, 0xf6, 0x03, 0x48, 0xb9, 0x57, 0x35, 0x61, 0x9e, 0x1d, 0xc1, 0x86, 0x11, 0x98, 0xf8, 0xe1, 0x94, 0x8e, 0xd9, 0x69, 0xe9, 0x87, 0x1e, 0x9b, 0xdf, 0x28, 0x55, 0xce, 0x0d, 0x89, 0xa1, 0x8c, 0x68, 0x42, 0xe6, 0xbf, 0x0f, 0x2d, 0x99, 0x41, 0x16, 0xbb, 0x54, 0xb0, 0x7b, 0x77, 0x7c, 0x63, 0xc5, 0x6f, 0x6b, 0xf2, 0x2b, 0x67, 0x01, 0x30, 0x76, 0xab, 0xd7, 0xfe, 0x7d, 0xc9, 0x82, 0xca, 0xf0, 0x47, 0x59, 0xfa, 0xaf, 0xa2, 0xd4, 0xad, 0xc0, 0x72, 0xa4, 0x9c, 0x26, 0x93, 0xfd, 0xb7, 0xcc, 0xf7, 0x3f, 0x36, 0xf1, 0xe5, 0xa5, 0x34, 0x15, 0x31, 0xd8, 0x71, 0xc3, 0x23, 0xc7, 0x04, 0x9a, 0x05, 0x96, 0x18, 0xe2, 0x80, 0x12, 0x07, 0x75, 0xb2, 0x27, 0xeb, 0x1a, 0x2c, 0x83, 0x09, 0xa0, 0x5a, 0x6e, 0x1b, 0xb3, 0xd6, 0x3b, 0x52, 0x84, 0x2f, 0xe3, 0x29, 0xed, 0x00, 0xd1, 0x53, 0x5b, 0xb1, 0xfc, 0x20, 0x39, 0xbe, 0xcb, 0x6a, 0xcf, 0x58, 0x4c, 0x4a, 0xfb, 0xaa, 0xef, 0xd0, 0x85, 0x33, 0x4d, 0x43, 0x7f, 0x02, 0xf9, 0x45, 0xa8, 0x9f, 0x3c, 0x50, 0x8f, 0x40, 0xa3, 0x51, 0xf5, 0x38, 0x9d, 0x92, 0x21, 0xda, 0xb6, 0xbc, 0xd2, 0xf3, 0xff, 0x10 +}, +{ +0x78, 0xba, 0x2e, 0x25, 0xa6, 0x1c, 0xc6, 0xb4, 0xdd, 0xe8, 0x1f, 0x74, 0xbd, 0x4b, 0x8a, 0x8b, 0x3e, 0x70, 0x66, 0xb5, 0x03, 0x48, 0x0e, 0xf6, 0x35, 0x61, 0xb9, 0x57, 0xc1, 0x86, 0x9e, 0x1d, 0xf8, 0xe1, 0x11, 0x98, 0xd9, 0x69, 0x94, 0x8e, 0x1e, 0x9b, 0xe9, 0x87, 0x55, 0xce, 0xdf, 0x28, 0xa1, 0x8c, 0x0d, 0x89, 0xe6, 0xbf, 0x68, 0x42, 0x99, 0x41, 0x0f, 0x2d, 0x54, 0xb0, 0x16, 0xbb, 0x0c, 0xcd, 0xec, 0x13, 0x97, 0x5f, 0x17, 0x44, 0xa7, 0xc4, 0x3d, 0x7e, 0x5d, 0x64, 0x73, 0x19, 0x81, 0x60, 0xdc, 0x4f, 0x2a, 0x22, 0x88, 0x90, 0xee, 0x46, 0x14, 0xb8, 0x5e, 0xde, 0xdb, 0x0b, 0x32, 0xe0, 0x0a, 0x3a, 0x06, 0x49, 0x5c, 0x24, 0xd3, 0xc2, 0x62, 0xac, 0x95, 0x91, 0x79, 0xe4, 0xc8, 0xe7, 0x6d, 0x37, 0xd5, 0x8d, 0xa9, 0x4e, 0x56, 0x6c, 0xea, 0xf4, 0x7a, 0x65, 0x08, 0xae, 0x83, 0x09, 0x1a, 0x2c, 0x6e, 0x1b, 0xa0, 0x5a, 0x3b, 0x52, 0xb3, 0xd6, 0xe3, 0x29, 0x84, 0x2f, 0xd1, 0x53, 0xed, 0x00, 0xfc, 0x20, 0x5b, 0xb1, 0xcb, 0x6a, 0x39, 0xbe, 0x4c, 0x4a, 0xcf, 0x58, 0xef, 0xd0, 0xfb, 0xaa, 0x4d, 0x43, 0x85, 0x33, 0xf9, 0x45, 0x7f, 0x02, 0x3c, 0x50, 0xa8, 0x9f, 0xa3, 0x51, 0x8f, 0x40, 0x9d, 0x92, 0xf5, 0x38, 0xb6, 0xbc, 0x21, 0xda, 0xff, 0x10, 0xd2, 0xf3, 0x7c, 0x63, 0x7b, 0x77, 0x6b, 0xf2, 0xc5, 0x6f, 0x01, 0x30, 0x2b, 0x67, 0xd7, 0xfe, 0x76, 0xab, 0x82, 0xca, 0x7d, 0xc9, 0x59, 0xfa, 0xf0, 0x47, 0xd4, 0xad, 0xaf, 0xa2, 0xa4, 0x9c, 0xc0, 0x72, 0xfd, 0xb7, 0x26, 0x93, 0x3f, 0x36, 0xcc, 0xf7, 0xa5, 0x34, 0xf1, 0xe5, 0xd8, 0x71, 0x15, 0x31, 0xc7, 0x04, 0xc3, 0x23, 0x96, 0x18, 0x9a, 0x05, 0x12, 0x07, 0xe2, 0x80, 0x27, 0xeb, 0x75, 0xb2 +}, +{ +0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c +}, +{ +0x5b, 0xb1, 0xfc, 0x20, 0xed, 0x00, 0xd1, 0x53, 0xcf, 0x58, 0x4c, 0x4a, 0x39, 0xbe, 0xcb, 0x6a, 0xa0, 0x5a, 0x6e, 0x1b, 0x1a, 0x2c, 0x83, 0x09, 0x84, 0x2f, 0xe3, 0x29, 0xb3, 0xd6, 0x3b, 0x52, 0xf5, 0x38, 0x9d, 0x92, 0x8f, 0x40, 0xa3, 0x51, 0xd2, 0xf3, 0xff, 0x10, 0x21, 0xda, 0xb6, 0xbc, 0x85, 0x33, 0x4d, 0x43, 0xfb, 0xaa, 0xef, 0xd0, 0xa8, 0x9f, 0x3c, 0x50, 0x7f, 0x02, 0xf9, 0x45, 0xf0, 0x47, 0x59, 0xfa, 0x7d, 0xc9, 0x82, 0xca, 0xc0, 0x72, 0xa4, 0x9c, 0xaf, 0xa2, 0xd4, 0xad, 0xc5, 0x6f, 0x6b, 0xf2, 0x7b, 0x77, 0x7c, 0x63, 0x76, 0xab, 0xd7, 0xfe, 0x2b, 0x67, 0x01, 0x30, 0x9a, 0x05, 0x96, 0x18, 0xc3, 0x23, 0xc7, 0x04, 0x75, 0xb2, 0x27, 0xeb, 0xe2, 0x80, 0x12, 0x07, 0xcc, 0xf7, 0x3f, 0x36, 0x26, 0x93, 0xfd, 0xb7, 0x15, 0x31, 0xd8, 0x71, 0xf1, 0xe5, 0xa5, 0x34, 0x0e, 0xf6, 0x03, 0x48, 0x66, 0xb5, 0x3e, 0x70, 0x9e, 0x1d, 0xc1, 0x86, 0xb9, 0x57, 0x35, 0x61, 0xc6, 0xb4, 0xa6, 0x1c, 0x2e, 0x25, 0x78, 0xba, 0x8a, 0x8b, 0xbd, 0x4b, 0x1f, 0x74, 0xdd, 0xe8, 0x68, 0x42, 0xe6, 0xbf, 0x0d, 0x89, 0xa1, 0x8c, 0x16, 0xbb, 0x54, 0xb0, 0x0f, 0x2d, 0x99, 0x41, 0x94, 0x8e, 0xd9, 0x69, 0x11, 0x98, 0xf8, 0xe1, 0xdf, 0x28, 0x55, 0xce, 0xe9, 0x87, 0x1e, 0x9b, 0x88, 0x90, 0x2a, 0x22, 0xdc, 0x4f, 0x81, 0x60, 0xdb, 0x0b, 0x5e, 0xde, 0x14, 0xb8, 0xee, 0x46, 0x17, 0x44, 0x97, 0x5f, 0xec, 0x13, 0x0c, 0xcd, 0x73, 0x19, 0x5d, 0x64, 0x3d, 0x7e, 0xa7, 0xc4, 0xa9, 0x4e, 0xd5, 0x8d, 0x6d, 0x37, 0xc8, 0xe7, 0x08, 0xae, 0x7a, 0x65, 0xea, 0xf4, 0x56, 0x6c, 0x5c, 0x24, 0x06, 0x49, 0x0a, 0x3a, 0x32, 0xe0, 0x79, 0xe4, 0x95, 0x91, 0x62, 0xac, 0xd3, 0xc2 +}, +{ +0xfa, 0x59, 0x47, 0xf0, 0xca, 0x82, 0xc9, 0x7d, 0x9c, 0xa4, 0x72, 0xc0, 0xad, 0xd4, 0xa2, 0xaf, 0xf2, 0x6b, 0x6f, 0xc5, 0x63, 0x7c, 0x77, 0x7b, 0xfe, 0xd7, 0xab, 0x76, 0x30, 0x01, 0x67, 0x2b, 0x18, 0x96, 0x05, 0x9a, 0x04, 0xc7, 0x23, 0xc3, 0xeb, 0x27, 0xb2, 0x75, 0x07, 0x12, 0x80, 0xe2, 0x36, 0x3f, 0xf7, 0xcc, 0xb7, 0xfd, 0x93, 0x26, 0x71, 0xd8, 0x31, 0x15, 0x34, 0xa5, 0xe5, 0xf1, 0x20, 0xfc, 0xb1, 0x5b, 0x53, 0xd1, 0x00, 0xed, 0x4a, 0x4c, 0x58, 0xcf, 0x6a, 0xcb, 0xbe, 0x39, 0x1b, 0x6e, 0x5a, 0xa0, 0x09, 0x83, 0x2c, 0x1a, 0x29, 0xe3, 0x2f, 0x84, 0x52, 0x3b, 0xd6, 0xb3, 0x92, 0x9d, 0x38, 0xf5, 0x51, 0xa3, 0x40, 0x8f, 0x10, 0xff, 0xf3, 0xd2, 0xbc, 0xb6, 0xda, 0x21, 0x43, 0x4d, 0x33, 0x85, 0xd0, 0xef, 0xaa, 0xfb, 0x50, 0x3c, 0x9f, 0xa8, 0x45, 0xf9, 0x02, 0x7f, 0x22, 0x2a, 0x90, 0x88, 0x60, 0x81, 0x4f, 0xdc, 0xde, 0x5e, 0x0b, 0xdb, 0x46, 0xee, 0xb8, 0x14, 0x5f, 0x97, 0x44, 0x17, 0xcd, 0x0c, 0x13, 0xec, 0x64, 0x5d, 0x19, 0x73, 0xc4, 0xa7, 0x7e, 0x3d, 0x8d, 0xd5, 0x4e, 0xa9, 0xe7, 0xc8, 0x37, 0x6d, 0x65, 0x7a, 0xae, 0x08, 0x6c, 0x56, 0xf4, 0xea, 0x49, 0x06, 0x24, 0x5c, 0xe0, 0x32, 0x3a, 0x0a, 0x91, 0x95, 0xe4, 0x79, 0xc2, 0xd3, 0xac, 0x62, 0x48, 0x03, 0xf6, 0x0e, 0x70, 0x3e, 0xb5, 0x66, 0x86, 0xc1, 0x1d, 0x9e, 0x61, 0x35, 0x57, 0xb9, 0x1c, 0xa6, 0xb4, 0xc6, 0xba, 0x78, 0x25, 0x2e, 0x4b, 0xbd, 0x8b, 0x8a, 0xe8, 0xdd, 0x74, 0x1f, 0xbf, 0xe6, 0x42, 0x68, 0x8c, 0xa1, 0x89, 0x0d, 0xb0, 0x54, 0xbb, 0x16, 0x41, 0x99, 0x2d, 0x0f, 0x69, 0xd9, 0x8e, 0x94, 0xe1, 0xf8, 0x98, 0x11, 0xce, 0x55, 0x28, 0xdf, 0x9b, 0x1e, 0x87, 0xe9 +}, +{ +0x99, 0x41, 0x0f, 0x2d, 0x54, 0xb0, 0x16, 0xbb, 0xa1, 0x8c, 0x0d, 0x89, 0xe6, 0xbf, 0x68, 0x42, 0x1e, 0x9b, 0xe9, 0x87, 0x55, 0xce, 0xdf, 0x28, 0xf8, 0xe1, 0x11, 0x98, 0xd9, 0x69, 0x94, 0x8e, 0x35, 0x61, 0xb9, 0x57, 0xc1, 0x86, 0x9e, 0x1d, 0x3e, 0x70, 0x66, 0xb5, 0x03, 0x48, 0x0e, 0xf6, 0xdd, 0xe8, 0x1f, 0x74, 0xbd, 0x4b, 0x8a, 0x8b, 0x78, 0xba, 0x2e, 0x25, 0xa6, 0x1c, 0xc6, 0xb4, 0x56, 0x6c, 0xea, 0xf4, 0x7a, 0x65, 0x08, 0xae, 0xc8, 0xe7, 0x6d, 0x37, 0xd5, 0x8d, 0xa9, 0x4e, 0xd3, 0xc2, 0x62, 0xac, 0x95, 0x91, 0x79, 0xe4, 0x32, 0xe0, 0x0a, 0x3a, 0x06, 0x49, 0x5c, 0x24, 0xee, 0x46, 0x14, 0xb8, 0x5e, 0xde, 0xdb, 0x0b, 0x81, 0x60, 0xdc, 0x4f, 0x2a, 0x22, 0x88, 0x90, 0xa7, 0xc4, 0x3d, 0x7e, 0x5d, 0x64, 0x73, 0x19, 0x0c, 0xcd, 0xec, 0x13, 0x97, 0x5f, 0x17, 0x44, 0xb6, 0xbc, 0x21, 0xda, 0xff, 0x10, 0xd2, 0xf3, 0xa3, 0x51, 0x8f, 0x40, 0x9d, 0x92, 0xf5, 0x38, 0xf9, 0x45, 0x7f, 0x02, 0x3c, 0x50, 0xa8, 0x9f, 0xef, 0xd0, 0xfb, 0xaa, 0x4d, 0x43, 0x85, 0x33, 0xcb, 0x6a, 0x39, 0xbe, 0x4c, 0x4a, 0xcf, 0x58, 0xd1, 0x53, 0xed, 0x00, 0xfc, 0x20, 0x5b, 0xb1, 0x3b, 0x52, 0xb3, 0xd6, 0xe3, 0x29, 0x84, 0x2f, 0x83, 0x09, 0x1a, 0x2c, 0x6e, 0x1b, 0xa0, 0x5a, 0x12, 0x07, 0xe2, 0x80, 0x27, 0xeb, 0x75, 0xb2, 0xc7, 0x04, 0xc3, 0x23, 0x96, 0x18, 0x9a, 0x05, 0xa5, 0x34, 0xf1, 0xe5, 0xd8, 0x71, 0x15, 0x31, 0xfd, 0xb7, 0x26, 0x93, 0x3f, 0x36, 0xcc, 0xf7, 0xd4, 0xad, 0xaf, 0xa2, 0xa4, 0x9c, 0xc0, 0x72, 0x82, 0xca, 0x7d, 0xc9, 0x59, 0xfa, 0xf0, 0x47, 0x01, 0x30, 0x2b, 0x67, 0xd7, 0xfe, 0x76, 0xab, 0x7c, 0x63, 0x7b, 0x77, 0x6b, 0xf2, 0xc5, 0x6f +}, +{ +0x21, 0xda, 0xb6, 0xbc, 0xd2, 0xf3, 0xff, 0x10, 0x8f, 0x40, 0xa3, 0x51, 0xf5, 0x38, 0x9d, 0x92, 0x7f, 0x02, 0xf9, 0x45, 0xa8, 0x9f, 0x3c, 0x50, 0xfb, 0xaa, 0xef, 0xd0, 0x85, 0x33, 0x4d, 0x43, 0x39, 0xbe, 0xcb, 0x6a, 0xcf, 0x58, 0x4c, 0x4a, 0xed, 0x00, 0xd1, 0x53, 0x5b, 0xb1, 0xfc, 0x20, 0xb3, 0xd6, 0x3b, 0x52, 0x84, 0x2f, 0xe3, 0x29, 0x1a, 0x2c, 0x83, 0x09, 0xa0, 0x5a, 0x6e, 0x1b, 0xe2, 0x80, 0x12, 0x07, 0x75, 0xb2, 0x27, 0xeb, 0xc3, 0x23, 0xc7, 0x04, 0x9a, 0x05, 0x96, 0x18, 0xf1, 0xe5, 0xa5, 0x34, 0x15, 0x31, 0xd8, 0x71, 0x26, 0x93, 0xfd, 0xb7, 0xcc, 0xf7, 0x3f, 0x36, 0xaf, 0xa2, 0xd4, 0xad, 0xc0, 0x72, 0xa4, 0x9c, 0x7d, 0xc9, 0x82, 0xca, 0xf0, 0x47, 0x59, 0xfa, 0x2b, 0x67, 0x01, 0x30, 0x76, 0xab, 0xd7, 0xfe, 0x7b, 0x77, 0x7c, 0x63, 0xc5, 0x6f, 0x6b, 0xf2, 0x0f, 0x2d, 0x99, 0x41, 0x16, 0xbb, 0x54, 0xb0, 0x0d, 0x89, 0xa1, 0x8c, 0x68, 0x42, 0xe6, 0xbf, 0xe9, 0x87, 0x1e, 0x9b, 0xdf, 0x28, 0x55, 0xce, 0x11, 0x98, 0xf8, 0xe1, 0x94, 0x8e, 0xd9, 0x69, 0xb9, 0x57, 0x35, 0x61, 0x9e, 0x1d, 0xc1, 0x86, 0x66, 0xb5, 0x3e, 0x70, 0x0e, 0xf6, 0x03, 0x48, 0x1f, 0x74, 0xdd, 0xe8, 0x8a, 0x8b, 0xbd, 0x4b, 0x2e, 0x25, 0x78, 0xba, 0xc6, 0xb4, 0xa6, 0x1c, 0xea, 0xf4, 0x56, 0x6c, 0x08, 0xae, 0x7a, 0x65, 0x6d, 0x37, 0xc8, 0xe7, 0xa9, 0x4e, 0xd5, 0x8d, 0x62, 0xac, 0xd3, 0xc2, 0x79, 0xe4, 0x95, 0x91, 0x0a, 0x3a, 0x32, 0xe0, 0x5c, 0x24, 0x06, 0x49, 0x14, 0xb8, 0xee, 0x46, 0xdb, 0x0b, 0x5e, 0xde, 0xdc, 0x4f, 0x81, 0x60, 0x88, 0x90, 0x2a, 0x22, 0x3d, 0x7e, 0xa7, 0xc4, 0x73, 0x19, 0x5d, 0x64, 0xec, 0x13, 0x0c, 0xcd, 0x17, 0x44, 0x97, 0x5f +} +}, +{ +{ +0xb1, 0x72, 0xb5, 0x55, 0xe0, 0x6e, 0xec, 0x73, 0x64, 0x71, 0x94, 0xf6, 0x51, 0x9d, 0x03, 0xc4, 0x8b, 0xc1, 0x50, 0xe5, 0x49, 0x40, 0xba, 0x81, 0xd3, 0x42, 0x87, 0x93, 0xae, 0x07, 0x63, 0x47, 0xf4, 0xbc, 0x0b, 0xbf, 0x2f, 0x8c, 0x86, 0x31, 0xa2, 0xdb, 0xd9, 0xd4, 0xd2, 0xea, 0xb6, 0x04, 0x0a, 0x15, 0x0d, 0x01, 0x1d, 0x84, 0xb3, 0x19, 0x77, 0x46, 0x5d, 0x11, 0xa1, 0x88, 0x00, 0xdd, 0xd5, 0x27, 0xf9, 0x36, 0xeb, 0xe4, 0x83, 0x4e, 0xc0, 0xca, 0x57, 0xac, 0x89, 0x66, 0xa4, 0x85, 0x99, 0xa6, 0x8d, 0xdc, 0x3b, 0x35, 0xf3, 0x45, 0x8f, 0x33, 0x09, 0x74, 0x4a, 0x26, 0xde, 0xe9, 0xa7, 0x25, 0x9b, 0x76, 0x8a, 0x56, 0x2d, 0xc7, 0xbd, 0x1c, 0x4f, 0xc8, 0x3a, 0x3c, 0xb9, 0x2e, 0xf5, 0x7f, 0x6c, 0x5a, 0x18, 0x6d, 0xd6, 0x2c, 0x4d, 0x24, 0xc5, 0xa0, 0x95, 0x5f, 0xf2, 0x59, 0xbe, 0x91, 0x1b, 0x41, 0xa3, 0xfb, 0xdf, 0x38, 0x20, 0x1a, 0x9c, 0x82, 0x0c, 0x13, 0x7e, 0xd8, 0x44, 0x96, 0x7c, 0x4c, 0x70, 0x3f, 0x2a, 0x52, 0xa5, 0xb4, 0x14, 0xda, 0xe3, 0xe7, 0x0f, 0x92, 0xf7, 0x16, 0xaa, 0x39, 0x5c, 0x54, 0xfe, 0xe6, 0x98, 0x30, 0x62, 0xce, 0x28, 0xa8, 0xad, 0x7d, 0x7a, 0xbb, 0x9a, 0x65, 0xe1, 0x29, 0x61, 0x32, 0xd1, 0xb2, 0x4b, 0x08, 0x2b, 0x12, 0x05, 0x6f, 0xd7, 0xfa, 0x7b, 0xff, 0x90, 0xc9, 0x1e, 0x34, 0xef, 0x37, 0x79, 0x5b, 0x22, 0xc6, 0x60, 0xcd, 0x8e, 0x97, 0x67, 0xee, 0xaf, 0x1f, 0xe2, 0xf8, 0x68, 0xed, 0x9f, 0xf1, 0x23, 0xb8, 0xa9, 0x5e, 0x48, 0x06, 0x10, 0xc3, 0x75, 0x3e, 0x78, 0x80, 0x43, 0x17, 0xcf, 0x21, 0xb7, 0xf0, 0xe8, 0x6b, 0x0e, 0xcc, 0x58, 0x53, 0xd0, 0x6a, 0xb0, 0xc2, 0xab, 0x9e, 0x69, 0x02, 0xcb, 0x3d, 0xfc, 0xfd +}, +{ +0x52, 0xa5, 0xd8, 0x43, 0x64, 0x0a, 0x93, 0x16, 0x19, 0x03, 0x54, 0xe4, 0x9c, 0x15, 0x75, 0x6c, 0x9b, 0x36, 0xd9, 0x3d, 0x82, 0xa0, 0x14, 0xcc, 0xe5, 0xcf, 0x6b, 0x32, 0x80, 0x04, 0x2c, 0x01, 0x07, 0x06, 0x30, 0xc6, 0x92, 0xf9, 0x50, 0x65, 0x4b, 0x39, 0x2b, 0x91, 0xa3, 0xa8, 0xf5, 0x37, 0x13, 0x90, 0x4c, 0x0b, 0x34, 0xda, 0xb8, 0xec, 0x83, 0x7b, 0x8e, 0xc5, 0xeb, 0x38, 0xb3, 0xfd, 0xf4, 0x69, 0x18, 0x1c, 0xef, 0x21, 0x5e, 0x4f, 0xd1, 0xa9, 0x8b, 0xc4, 0x87, 0xb7, 0xbf, 0x6d, 0x85, 0x23, 0xf7, 0xe8, 0x67, 0x79, 0xdb, 0xe1, 0x24, 0xc3, 0x58, 0x00, 0xe0, 0xba, 0x45, 0x6a, 0xfe, 0x94, 0xd0, 0xe9, 0xb0, 0xf3, 0x2a, 0x49, 0x9a, 0xc9, 0x1a, 0xd2, 0x61, 0x9e, 0x81, 0x40, 0x56, 0x86, 0xd3, 0x53, 0x99, 0x35, 0x63, 0xcb, 0x05, 0x1d, 0xa7, 0xaf, 0x51, 0xc2, 0x0c, 0xed, 0x25, 0x12, 0xb1, 0xdd, 0xf2, 0x8f, 0x74, 0xc8, 0x08, 0xbe, 0xc0, 0xce, 0x76, 0x27, 0x62, 0x5d, 0x5f, 0x7e, 0x72, 0x9d, 0xac, 0x57, 0x3b, 0x31, 0x78, 0xb5, 0x10, 0x1f, 0x02, 0xcd, 0x2e, 0xdc, 0x09, 0xa2, 0x6e, 0xa4, 0x3e, 0x5b, 0xb6, 0xdf, 0x2d, 0xd7, 0xe3, 0x96, 0x97, 0xa1, 0x0e, 0x84, 0x42, 0xd5, 0xc1, 0xc7, 0xb4, 0x33, 0x46, 0xe7, 0xd6, 0x3c, 0x71, 0xad, 0x60, 0x8d, 0x5c, 0xde, 0x98, 0xbc, 0x55, 0xfc, 0x7c, 0x68, 0x28, 0xb9, 0x41, 0x7a, 0xb2, 0xbb, 0xab, 0x1e, 0x70, 0x3a, 0xf8, 0x3f, 0xaa, 0x66, 0x6f, 0x0d, 0x9f, 0x8a, 0x17, 0x88, 0x1b, 0x95, 0x4e, 0xae, 0x4a, 0x89, 0xfb, 0x26, 0x5a, 0x73, 0xa6, 0xea, 0x8c, 0xbd, 0x48, 0xe2, 0xe6, 0x7f, 0xf6, 0xfa, 0xf1, 0xee, 0x4d, 0xff, 0x29, 0x11, 0x22, 0x2f, 0x59, 0x20, 0x7d, 0xca, 0xd4, 0x77, 0xf0, 0x44, 0x0f, 0x47 +}, +{ +0x96, 0x59, 0xba, 0x48, 0xec, 0x21, 0x84, 0x8b, 0x38, 0xc3, 0xaf, 0xa5, 0xcb, 0xea, 0xe6, 0x09, 0xe2, 0xb3, 0xf6, 0xc9, 0x9c, 0x2a, 0x54, 0x5a, 0x66, 0x1b, 0xe0, 0x5c, 0xb1, 0x86, 0x25, 0x49, 0xf4, 0x19, 0xc8, 0x4a, 0x42, 0xa8, 0xe5, 0x39, 0x20, 0xa7, 0xd2, 0x73, 0xd6, 0x41, 0x55, 0x53, 0x03, 0x35, 0x9a, 0x10, 0xb9, 0x43, 0x77, 0x02, 0xaa, 0xcf, 0x22, 0x4b, 0x9d, 0x36, 0xfa, 0x30, 0xda, 0x3a, 0xde, 0x1d, 0x83, 0x1c, 0x8f, 0x01, 0xfb, 0x99, 0x0b, 0x1e, 0x6c, 0xab, 0x3e, 0xf2, 0x3f, 0x8a, 0xe4, 0xae, 0xd5, 0xee, 0x26, 0x2f, 0xe8, 0xfc, 0xbc, 0x2d, 0x0c, 0x28, 0xc1, 0x68, 0x64, 0xd0, 0x9b, 0xd3, 0xe9, 0x5e, 0x40, 0xe3, 0xb6, 0xbb, 0xcd, 0xb4, 0xd9, 0x6b, 0xbd, 0x85, 0x62, 0x6e, 0x65, 0x7a, 0xdc, 0x76, 0x72, 0xeb, 0x32, 0x7e, 0x18, 0x29, 0x6f, 0xb2, 0xce, 0xe7, 0x14, 0x90, 0xb8, 0x95, 0x71, 0x5b, 0xff, 0xa6, 0x16, 0x34, 0x80, 0x58, 0x0f, 0xa2, 0x4d, 0xa9, 0x08, 0x81, 0xe1, 0xf8, 0x8d, 0x97, 0xc0, 0x70, 0xf0, 0x9e, 0x07, 0x82, 0xc6, 0x31, 0x4c, 0xd7, 0x7f, 0xac, 0x27, 0x69, 0x17, 0xef, 0x1a, 0x51, 0xa0, 0x4e, 0x2c, 0x78, 0x87, 0x04, 0xd8, 0x9f, 0x37, 0x3c, 0x61, 0xa3, 0xdf, 0xad, 0xbf, 0x05, 0x06, 0x6d, 0xc4, 0xf1, 0x93, 0x92, 0xa4, 0x52, 0x74, 0x2e, 0xd1, 0xfe, 0xb0, 0x57, 0xcc, 0x94, 0xf3, 0xed, 0x4f, 0x75, 0x11, 0xb7, 0x63, 0x7c, 0x13, 0x23, 0x2b, 0xf9, 0x45, 0x3d, 0x1f, 0x50, 0x7b, 0xb5, 0xca, 0xdb, 0x60, 0xfd, 0x8c, 0x88, 0xc5, 0x56, 0x98, 0x79, 0x91, 0x89, 0x33, 0x3b, 0x0d, 0xa1, 0xf7, 0x5f, 0xc2, 0x12, 0x47, 0xc7, 0xf5, 0x0a, 0x15, 0xd4, 0x0e, 0x5d, 0x8e, 0x46, 0x24, 0x67, 0xbe, 0xdd, 0x6a, 0x00, 0x44, 0x7d +}, +{ +0xb8, 0x1b, 0x11, 0xa6, 0x63, 0x2b, 0x9c, 0x28, 0x45, 0x7d, 0x21, 0x93, 0x35, 0x4c, 0x4e, 0x43, 0x8a, 0x13, 0x24, 0x8e, 0x9d, 0x82, 0x9a, 0x96, 0x36, 0x1f, 0x97, 0x4a, 0xe0, 0xd1, 0xca, 0x86, 0x77, 0xf9, 0x7b, 0xe4, 0x26, 0xe5, 0x22, 0xc2, 0xc6, 0x0a, 0x94, 0x53, 0xf3, 0xe6, 0x03, 0x61, 0xde, 0xd7, 0x2d, 0x16, 0x1c, 0x56, 0xc7, 0x72, 0x39, 0x90, 0xf4, 0xd0, 0x44, 0xd5, 0x10, 0x04, 0x1d, 0xc1, 0xba, 0x50, 0x30, 0xb2, 0x0c, 0xe1, 0xad, 0xab, 0x2e, 0xb9, 0x2a, 0x8b, 0xd8, 0x5f, 0x8f, 0xfa, 0x41, 0xbb, 0x62, 0xe8, 0xfb, 0xcd, 0x02, 0xc8, 0x65, 0xce, 0xda, 0xb3, 0x52, 0x37, 0x7c, 0x73, 0x14, 0xd9, 0x42, 0xb0, 0x6e, 0xa1, 0x1e, 0xf1, 0x33, 0x12, 0x57, 0x5d, 0xc0, 0x3b, 0xac, 0xa2, 0x64, 0xd2, 0x0e, 0x31, 0x1a, 0x4b, 0xdd, 0xb1, 0x49, 0x7e, 0x18, 0xa4, 0x9e, 0xe3, 0xcb, 0xc3, 0x69, 0x71, 0x60, 0x81, 0x3d, 0xae, 0xbf, 0x3f, 0x3a, 0xea, 0x0f, 0xa7, 0xf5, 0x59, 0x76, 0xbe, 0xf6, 0xa5, 0xed, 0x2c, 0x0d, 0xf2, 0xbc, 0x85, 0x92, 0xf8, 0x46, 0x25, 0xdc, 0x9f, 0x34, 0x6c, 0x48, 0xaf, 0x29, 0x06, 0x8c, 0xd6, 0x9b, 0x84, 0xe9, 0x4f, 0xb7, 0x8d, 0x0b, 0x15, 0xe7, 0xa8, 0xbd, 0xc5, 0xd3, 0x01, 0xeb, 0xdb, 0x74, 0x70, 0x98, 0x05, 0x32, 0x23, 0x83, 0x4d, 0xe2, 0xa9, 0xef, 0x17, 0xdf, 0x91, 0x87, 0x54, 0x20, 0x67, 0x7f, 0xfc, 0xd4, 0x80, 0x58, 0xb6, 0x47, 0xfd, 0x27, 0x55, 0x99, 0x5b, 0xcf, 0xc4, 0x5c, 0xaa, 0x6b, 0x6a, 0x3c, 0x09, 0xfe, 0x95, 0x07, 0x5e, 0x89, 0xa3, 0x40, 0x6d, 0xec, 0x68, 0xb5, 0x51, 0xf7, 0x5a, 0x78, 0xa0, 0xee, 0xcc, 0x38, 0x88, 0x75, 0x6f, 0x19, 0x00, 0xf0, 0x79, 0xb4, 0x2f, 0x3e, 0xc9, 0xff, 0x7a, 0x08, 0x66 +}, +{ +0x7e, 0x4f, 0x54, 0x18, 0xa8, 0x81, 0x09, 0xd4, 0x03, 0x1c, 0x04, 0x08, 0x14, 0x8d, 0xba, 0x10, 0xab, 0xd2, 0xd0, 0xdd, 0xdb, 0xe3, 0xbf, 0x0d, 0xfd, 0xb5, 0x02, 0xb6, 0x26, 0x85, 0x8f, 0x38, 0xda, 0x4b, 0x8e, 0x9a, 0xa7, 0x0e, 0x6a, 0x4e, 0x82, 0xc8, 0x59, 0xec, 0x40, 0x49, 0xb3, 0x88, 0x6d, 0x78, 0x9d, 0xff, 0x58, 0x94, 0x0a, 0xcd, 0xb8, 0x7b, 0xbc, 0x5c, 0xe9, 0x67, 0xe5, 0x7a, 0x44, 0x2d, 0xcc, 0xa9, 0x9c, 0x56, 0xfb, 0x50, 0xfc, 0x76, 0x65, 0x53, 0x11, 0x64, 0xdf, 0x25, 0xb4, 0x15, 0x46, 0xc1, 0x33, 0x35, 0xb0, 0x27, 0xae, 0x2c, 0x92, 0x7f, 0x83, 0x5f, 0x24, 0xce, 0x86, 0x3a, 0x00, 0x7d, 0x43, 0x2f, 0xd7, 0xe0, 0x90, 0xaf, 0x84, 0xd5, 0x32, 0x3c, 0xfa, 0x4c, 0xc9, 0xc3, 0x5e, 0xa5, 0x80, 0x6f, 0xad, 0x8c, 0xdc, 0x2e, 0xf0, 0x3f, 0xe2, 0xed, 0x8a, 0x47, 0xd8, 0xbb, 0x42, 0x01, 0x22, 0x1b, 0x0c, 0x66, 0x73, 0xb2, 0x93, 0x6c, 0xe8, 0x20, 0x68, 0x3b, 0x91, 0x39, 0x6b, 0xc7, 0x21, 0xa1, 0xa4, 0x74, 0xfe, 0x1f, 0xa3, 0x30, 0x55, 0x5d, 0xf7, 0xef, 0xac, 0xbd, 0x1d, 0xd3, 0xea, 0xee, 0x06, 0x9b, 0x4d, 0x9f, 0x75, 0x45, 0x79, 0x36, 0x23, 0x5b, 0x29, 0x13, 0x95, 0x8b, 0x05, 0x1a, 0x77, 0xd1, 0xb7, 0x98, 0x12, 0x48, 0xaa, 0xf2, 0xd6, 0x31, 0xa2, 0x97, 0x60, 0x0b, 0xc2, 0x34, 0xf5, 0xf4, 0x07, 0xc5, 0x51, 0x5a, 0xd9, 0x63, 0xb9, 0xcb, 0x4a, 0x1e, 0xc6, 0x28, 0xbe, 0xf9, 0xe1, 0x62, 0x41, 0x0f, 0x19, 0xca, 0x7c, 0x37, 0x71, 0x89, 0x61, 0xe4, 0x96, 0xf8, 0x2a, 0xb1, 0xa0, 0x57, 0x87, 0x9e, 0x6e, 0xe7, 0xa6, 0x16, 0xeb, 0xf1, 0xe6, 0x3e, 0x70, 0x52, 0x2b, 0xcf, 0x69, 0xc4, 0xde, 0xf3, 0x72, 0xf6, 0x99, 0xc0, 0x17, 0x3d +}, +{ +0x1b, 0x86, 0xf7, 0xf3, 0x00, 0xce, 0xb1, 0xa0, 0x3e, 0x46, 0x64, 0x2b, 0x68, 0x58, 0x50, 0x82, 0x6a, 0xcc, 0x18, 0x07, 0x88, 0x96, 0x34, 0x0e, 0xcb, 0x2c, 0xb7, 0xef, 0x0f, 0x55, 0xaa, 0x85, 0x11, 0x7b, 0x3f, 0x06, 0x5f, 0x1c, 0xc5, 0xa6, 0x75, 0x26, 0xf5, 0x3d, 0x8e, 0x71, 0x6e, 0xaf, 0xb9, 0x69, 0x3c, 0xbc, 0x76, 0xda, 0x8c, 0x24, 0xea, 0xf2, 0x48, 0x40, 0xbe, 0x2d, 0xe3, 0x02, 0xbd, 0x4a, 0x37, 0xac, 0x8b, 0xe5, 0x7c, 0xf9, 0xf6, 0xec, 0xbb, 0x0b, 0x73, 0xfa, 0x9a, 0x83, 0x74, 0xd9, 0x36, 0xd2, 0x6d, 0x4f, 0xfb, 0x23, 0x0a, 0x20, 0x84, 0xdd, 0x6f, 0xeb, 0xc3, 0xee, 0xe8, 0xe9, 0xdf, 0x29, 0x7d, 0x16, 0xbf, 0x8a, 0xa4, 0xd6, 0xc4, 0x7e, 0x4c, 0x47, 0x1a, 0xd8, 0xfc, 0x7f, 0xa3, 0xe4, 0xdb, 0x35, 0x57, 0x03, 0x6c, 0x94, 0x61, 0x2a, 0x04, 0xd7, 0x5c, 0x12, 0x77, 0x53, 0xba, 0x13, 0x93, 0x87, 0xc7, 0x56, 0xae, 0x95, 0x5d, 0x54, 0x44, 0xf1, 0x9f, 0xd5, 0x17, 0xd0, 0x45, 0x89, 0x80, 0xe2, 0x70, 0x65, 0xf8, 0x67, 0xf4, 0x7a, 0xa1, 0x41, 0xa5, 0x66, 0x14, 0xc9, 0xb5, 0x9c, 0x49, 0x05, 0x63, 0x52, 0xa7, 0x0d, 0x09, 0x90, 0x19, 0x15, 0x1e, 0x01, 0xa2, 0x10, 0xc6, 0xfe, 0xcd, 0xc0, 0xb6, 0xcf, 0x92, 0x25, 0x3b, 0x98, 0x1f, 0xab, 0xe0, 0xa8, 0xca, 0xfd, 0x5e, 0x32, 0x1d, 0x60, 0x9b, 0x27, 0xe7, 0x51, 0x2f, 0x21, 0x99, 0xc8, 0x8d, 0xb2, 0xb0, 0x91, 0x9d, 0x72, 0x43, 0xb8, 0xd4, 0xde, 0x97, 0x5a, 0xff, 0xf0, 0xed, 0x22, 0xc1, 0x33, 0xe6, 0x4d, 0x81, 0x4b, 0xd1, 0xb4, 0x59, 0x30, 0xc2, 0x38, 0x0c, 0x79, 0x78, 0x4e, 0xe1, 0x6b, 0xad, 0x3a, 0x2e, 0x28, 0x5b, 0xdc, 0xa9, 0x08, 0x39, 0xd3, 0x9e, 0x42, 0x8f, 0x62, 0xb3, 0x31 +}, +{ +0x0c, 0xc2, 0x62, 0x73, 0x44, 0xd9, 0x31, 0x35, 0x9a, 0xaa, 0x40, 0x92, 0x84, 0xfc, 0xe9, 0xa6, 0x54, 0x4a, 0xcc, 0xf6, 0x0e, 0xa8, 0xc5, 0xda, 0x97, 0xcd, 0x47, 0x68, 0xee, 0x09, 0x2d, 0x75, 0xde, 0x9d, 0x64, 0x07, 0xb9, 0xd3, 0xc4, 0xfd, 0xb3, 0x4c, 0x6d, 0xac, 0xe4, 0xb7, 0xff, 0x37, 0x18, 0xb4, 0xe6, 0x4e, 0xab, 0x7b, 0x7e, 0xfe, 0xef, 0x7c, 0xc0, 0x21, 0x30, 0x28, 0x82, 0x8a, 0x27, 0x49, 0x3b, 0xbe, 0x88, 0x7f, 0x6e, 0xf5, 0x38, 0xb1, 0x41, 0x58, 0x2e, 0x34, 0xc9, 0x79, 0x8d, 0xaf, 0xe1, 0x39, 0x1b, 0xb6, 0x10, 0xf4, 0x29, 0xad, 0x2c, 0x01, 0xe2, 0xc8, 0x1f, 0x46, 0xd4, 0xbf, 0x48, 0x7d, 0x2b, 0x2a, 0xeb, 0x1d, 0x85, 0x8e, 0x1a, 0xd8, 0x14, 0x66, 0xbc, 0x06, 0xf7, 0x19, 0xc1, 0x95, 0xbd, 0x3e, 0x26, 0x61, 0x15, 0xc6, 0xd0, 0x9e, 0x56, 0xae, 0xe8, 0xa3, 0x45, 0x51, 0x94, 0x05, 0x91, 0xb5, 0xd1, 0x78, 0x33, 0x86, 0x17, 0x5d, 0x57, 0x6c, 0x96, 0x9f, 0x20, 0x42, 0xa7, 0xb2, 0x12, 0xd5, 0x4b, 0x87, 0x83, 0x63, 0xa4, 0x67, 0xa5, 0x3a, 0xb8, 0x36, 0xc7, 0x8b, 0x90, 0xa1, 0x0b, 0xd6, 0x5e, 0x77, 0xd7, 0xdb, 0xc3, 0xdc, 0xcf, 0x65, 0x52, 0xcb, 0x02, 0x0f, 0x0d, 0x74, 0xd2, 0x60, 0x3c, 0x04, 0x69, 0xdd, 0x6a, 0x22, 0xe7, 0x50, 0x5a, 0xf9, 0xa2, 0xdf, 0xe5, 0x59, 0x3f, 0x08, 0xf0, 0x9c, 0x0a, 0x5b, 0x70, 0x4f, 0x93, 0x25, 0xe3, 0xed, 0x7a, 0x81, 0x1c, 0x16, 0x53, 0x72, 0xb0, 0x5f, 0xe0, 0x2f, 0xf1, 0x03, 0x98, 0x55, 0x32, 0x3d, 0x76, 0x13, 0xf2, 0x9b, 0x8f, 0x24, 0x89, 0x43, 0x8c, 0xba, 0xa9, 0x23, 0xfa, 0x00, 0xbb, 0xce, 0x1e, 0x99, 0xca, 0x6b, 0xf8, 0x6f, 0xea, 0xec, 0xa0, 0x4d, 0xf3, 0x71, 0x11, 0xfb, 0x80, 0x5c +}, +{ +0x42, 0x3a, 0x18, 0x57, 0x14, 0x24, 0x2c, 0xfe, 0x67, 0xfa, 0x8b, 0x8f, 0x7c, 0xb2, 0xcd, 0xdc, 0xb7, 0x50, 0xcb, 0x93, 0x73, 0x29, 0xd6, 0xf9, 0x16, 0xb0, 0x64, 0x7b, 0xf4, 0xea, 0x48, 0x72, 0x09, 0x5a, 0x89, 0x41, 0xf2, 0x0d, 0x12, 0xd3, 0x6d, 0x07, 0x43, 0x7a, 0x23, 0x60, 0xb9, 0xda, 0x96, 0x8e, 0x34, 0x3c, 0xc2, 0x51, 0x9f, 0x7e, 0xc5, 0x15, 0x40, 0xc0, 0x0a, 0xa6, 0xf0, 0x58, 0x8a, 0x90, 0xc7, 0x77, 0x0f, 0x86, 0xe6, 0xff, 0xc1, 0x36, 0x4b, 0xd0, 0xf7, 0x99, 0x00, 0x85, 0x76, 0x5c, 0xf8, 0xa1, 0x13, 0x97, 0xbf, 0x92, 0x08, 0xa5, 0x4a, 0xae, 0x11, 0x33, 0x87, 0x5f, 0xd8, 0xaa, 0xb8, 0x02, 0x30, 0x3b, 0x66, 0xa4, 0x94, 0x95, 0xa3, 0x55, 0x01, 0x6a, 0xc3, 0xf6, 0x10, 0xe8, 0x1d, 0x56, 0x78, 0xab, 0x20, 0x6e, 0x80, 0x03, 0xdf, 0x98, 0xa7, 0x49, 0x2b, 0x7f, 0xd2, 0xe9, 0x21, 0x28, 0x38, 0x8d, 0xe3, 0xa9, 0x0b, 0x2f, 0xc6, 0x6f, 0xef, 0xfb, 0xbb, 0x2a, 0x84, 0x1b, 0x88, 0x06, 0xdd, 0x3d, 0xd9, 0x1a, 0x6b, 0xac, 0x39, 0xf5, 0xfc, 0x9e, 0x0c, 0x19, 0xdb, 0x71, 0x75, 0xec, 0x65, 0x69, 0x62, 0x7d, 0x68, 0xb5, 0xc9, 0xe0, 0x35, 0x79, 0x1f, 0x2e, 0xee, 0x59, 0x47, 0xe4, 0x63, 0xd7, 0x9c, 0xd4, 0xde, 0x6c, 0xba, 0x82, 0xb1, 0xbc, 0xca, 0xb3, 0x9b, 0x2d, 0x53, 0x5d, 0xe5, 0xb4, 0xf1, 0xce, 0xb6, 0x81, 0x22, 0x4e, 0x61, 0x1c, 0xe7, 0x5b, 0xeb, 0x26, 0x83, 0x8c, 0x91, 0x5e, 0xbd, 0x4f, 0xcc, 0xed, 0xe1, 0x0e, 0x3f, 0xc4, 0xa8, 0xa2, 0xbe, 0x44, 0x70, 0x05, 0x04, 0x32, 0x9d, 0x17, 0x9a, 0x31, 0xfd, 0x37, 0xad, 0xc8, 0x25, 0x4c, 0x45, 0xaf, 0xe2, 0x3e, 0xf3, 0x1e, 0xcf, 0x4d, 0xd1, 0x46, 0x52, 0x54, 0x27, 0xa0, 0xd5, 0x74 +}, +{ +0x3a, 0x3b, 0x0d, 0xfb, 0xaf, 0xc4, 0x6d, 0x58, 0x76, 0x04, 0x16, 0xac, 0x9e, 0x95, 0xc8, 0x0a, 0x2e, 0xad, 0x71, 0x36, 0x09, 0xe7, 0x85, 0xd1, 0xbe, 0x46, 0xb3, 0xf8, 0xd6, 0x05, 0x8e, 0xc0, 0x6f, 0x98, 0xe5, 0x7e, 0x59, 0x37, 0xae, 0x2b, 0x24, 0x3e, 0x69, 0xd9, 0xa1, 0x28, 0x48, 0x51, 0xa6, 0x0b, 0xe4, 0x00, 0xbf, 0x9d, 0x29, 0xf1, 0xd8, 0xf2, 0x56, 0x0f, 0xbd, 0x39, 0x11, 0x3c, 0xc3, 0xa9, 0xed, 0xd4, 0x8d, 0xce, 0x17, 0x74, 0xa7, 0xf4, 0x27, 0xef, 0x5c, 0xa3, 0xbc, 0x7d, 0x6b, 0xbb, 0xee, 0x6e, 0xa4, 0x08, 0x5e, 0xf6, 0x38, 0x20, 0x9a, 0x92, 0x6c, 0xff, 0x31, 0xd0, 0xc9, 0x54, 0x25, 0x21, 0xd2, 0x1c, 0x63, 0x72, 0xec, 0x94, 0xb6, 0xf9, 0xba, 0x8a, 0x82, 0x50, 0xb8, 0x1e, 0xca, 0xd5, 0x5a, 0x44, 0xe6, 0xdc, 0x19, 0xfe, 0x65, 0x3d, 0xdd, 0x87, 0x78, 0x57, 0x34, 0x9f, 0x53, 0x99, 0x03, 0x66, 0x8b, 0xe2, 0x10, 0xea, 0xde, 0xab, 0xaa, 0x9c, 0x33, 0xb9, 0x7f, 0xe8, 0xfc, 0xfa, 0x89, 0x0e, 0x7b, 0xda, 0xeb, 0x01, 0x4c, 0x90, 0x5d, 0xb0, 0x61, 0xe3, 0x18, 0x2f, 0x8c, 0xe0, 0xcf, 0xb2, 0x49, 0xf5, 0x35, 0x83, 0xfd, 0xf3, 0x4b, 0x1a, 0x5f, 0x60, 0x62, 0x43, 0x4f, 0xa0, 0x91, 0x6a, 0x06, 0x0c, 0x45, 0x88, 0x2d, 0x22, 0x3f, 0xf0, 0x13, 0xe1, 0xc6, 0x1b, 0x67, 0x4e, 0x9b, 0xd7, 0xb1, 0x80, 0x75, 0xdf, 0xdb, 0x42, 0xcb, 0xc7, 0xcc, 0xd3, 0x70, 0xc2, 0x14, 0x2c, 0x1f, 0x12, 0x64, 0x1d, 0x40, 0xf7, 0xe9, 0x4a, 0xcd, 0x79, 0x32, 0x7a, 0xa5, 0x81, 0x68, 0xc1, 0x41, 0x55, 0x15, 0x84, 0x7c, 0x47, 0x8f, 0x86, 0x96, 0x23, 0x4d, 0x07, 0xc5, 0x02, 0x97, 0x5b, 0x52, 0x30, 0xa2, 0xb7, 0x2a, 0xb5, 0x26, 0xa8, 0x73, 0x93, 0x77, 0xb4 +}, +{ +0xbc, 0x15, 0xfc, 0xd8, 0xf9, 0x68, 0x28, 0x3c, 0xfb, 0xf2, 0x3a, 0x01, 0x7a, 0x30, 0x5e, 0xeb, 0x26, 0xea, 0x7f, 0xb8, 0xca, 0xdf, 0x4d, 0x2f, 0xd5, 0x5b, 0xc8, 0x57, 0xc9, 0x0a, 0xee, 0x0e, 0x33, 0x1a, 0x66, 0xbb, 0xfd, 0xcc, 0xaa, 0xe6, 0x3f, 0xa6, 0xa2, 0x08, 0xae, 0xb1, 0xba, 0xb6, 0x51, 0x69, 0xbf, 0x0d, 0x60, 0x19, 0x6f, 0x62, 0x37, 0x94, 0x8a, 0x3d, 0x07, 0x4f, 0x04, 0xb0, 0x9d, 0xf1, 0x52, 0x65, 0x88, 0x34, 0xcf, 0xb2, 0x8e, 0x80, 0xfe, 0x48, 0x1d, 0x22, 0x67, 0x36, 0xdd, 0x32, 0x3e, 0x1f, 0x71, 0x7b, 0x17, 0xec, 0x5f, 0x50, 0xf5, 0x38, 0x9c, 0x6e, 0x8d, 0x42, 0xe4, 0x2e, 0xe2, 0x49, 0x9f, 0xf6, 0x1b, 0x7e, 0xd6, 0xa3, 0x97, 0x6d, 0xc4, 0x4e, 0xe1, 0xd7, 0x87, 0x81, 0x95, 0x02, 0xa7, 0x06, 0x73, 0xf4, 0xed, 0x31, 0x7c, 0x96, 0x9e, 0x1c, 0xcd, 0x20, 0x5c, 0x58, 0x29, 0xb4, 0x0f, 0x1e, 0x61, 0xaf, 0x84, 0xcb, 0xe9, 0x91, 0x2d, 0xff, 0xf7, 0xc7, 0xa8, 0xb7, 0x63, 0xc5, 0xa1, 0x9b, 0x39, 0x27, 0x40, 0x18, 0x83, 0x64, 0x2a, 0x05, 0xfa, 0xa0, 0xa9, 0x90, 0xd4, 0xbe, 0x09, 0x6a, 0xb3, 0xf0, 0x92, 0x5a, 0x89, 0xda, 0x00, 0xc1, 0xde, 0x21, 0x13, 0x93, 0xc6, 0x16, 0x8b, 0x23, 0x75, 0xd9, 0xef, 0xe7, 0x5d, 0x45, 0xad, 0x4c, 0x82, 0x11, 0x03, 0x98, 0xe5, 0x12, 0x56, 0xd3, 0x4a, 0x24, 0xa4, 0x14, 0x43, 0x59, 0x2c, 0x35, 0x55, 0xdc, 0x7d, 0x99, 0x76, 0xdb, 0x8c, 0x54, 0xe0, 0xc2, 0x72, 0x2b, 0x8f, 0xa5, 0x41, 0x6c, 0x44, 0xc0, 0x86, 0x70, 0x46, 0x47, 0x25, 0x10, 0xb9, 0xd2, 0xd1, 0x6b, 0x79, 0x0b, 0x77, 0xb5, 0xe8, 0xe3, 0x4b, 0x0c, 0xd0, 0x53, 0xac, 0xf8, 0x9a, 0x74, 0x85, 0xce, 0x3b, 0xc3, 0xbd, 0xf3, 0x78, 0xab +}, +{ +0xda, 0x50, 0xff, 0xc9, 0xc8, 0xbd, 0x89, 0x73, 0x81, 0xe8, 0x05, 0x60, 0xfa, 0x30, 0xfc, 0x57, 0x80, 0x02, 0xd3, 0x3e, 0xf3, 0x2f, 0x62, 0x88, 0xb9, 0x18, 0x6d, 0xea, 0x99, 0x9f, 0x8b, 0x1c, 0x03, 0x3c, 0x79, 0x28, 0x90, 0x9e, 0xe0, 0x56, 0x96, 0x2a, 0xd1, 0xac, 0x83, 0xef, 0x4c, 0x7b, 0x82, 0x70, 0x93, 0x5c, 0x41, 0x4e, 0xeb, 0x26, 0x6f, 0x65, 0x09, 0xf2, 0xc3, 0x2c, 0x20, 0x01, 0xb0, 0xaf, 0xa4, 0xa8, 0x21, 0xb8, 0xbc, 0x16, 0xe3, 0xd2, 0xb4, 0xf8, 0x2d, 0x04, 0x78, 0xa5, 0x19, 0x51, 0x1a, 0xae, 0x29, 0x8a, 0x94, 0x23, 0x7e, 0x07, 0x71, 0x7c, 0x4f, 0x77, 0xa1, 0x13, 0x64, 0x2e, 0x40, 0xf5, 0xe5, 0xec, 0x24, 0x1f, 0xe7, 0x76, 0x36, 0x22, 0xa2, 0x0b, 0xe2, 0xc6, 0xd7, 0x14, 0xf0, 0x10, 0xcb, 0x45, 0xd6, 0x49, 0xd4, 0xc1, 0x53, 0x31, 0x38, 0xf4, 0x61, 0xa6, 0x69, 0xab, 0xf6, 0xfd, 0xcf, 0x75, 0x67, 0x15, 0x3b, 0x0e, 0xa7, 0xcc, 0x98, 0x6e, 0x58, 0x59, 0xa3, 0xed, 0x66, 0xb5, 0x9b, 0xd0, 0x25, 0xdd, 0xb2, 0xe6, 0x84, 0x6a, 0x55, 0x12, 0xce, 0x4d, 0x32, 0x2b, 0x4b, 0xc2, 0xba, 0x0a, 0x5d, 0x47, 0x48, 0xcd, 0x54, 0x3a, 0x1d, 0x86, 0xfb, 0x0c, 0x5f, 0x72, 0x5a, 0xde, 0x6c, 0x35, 0x91, 0xbb, 0x92, 0x4a, 0xfe, 0xdc, 0x63, 0x87, 0x68, 0xc5, 0x1e, 0xdf, 0xc0, 0x3f, 0x8c, 0x44, 0x97, 0xc4, 0x17, 0x74, 0xad, 0xee, 0xb7, 0x8e, 0xca, 0xa0, 0xb3, 0x52, 0x9c, 0x0f, 0xf1, 0xf9, 0x43, 0x5b, 0x95, 0x3d, 0x6b, 0xc7, 0x0d, 0x8d, 0xd8, 0x08, 0x33, 0xe1, 0xe9, 0xd9, 0x9a, 0xd5, 0xf7, 0x8f, 0x11, 0x00, 0x7f, 0xb1, 0x42, 0x46, 0x37, 0xaa, 0x34, 0x1b, 0xe4, 0xbe, 0x5e, 0x06, 0x9d, 0x7a, 0xbf, 0x85, 0x27, 0x39, 0xb6, 0xa9, 0x7d, 0xdb +}, +{ +0x8c, 0x21, 0xce, 0x2a, 0x95, 0xb7, 0x03, 0xdb, 0xf2, 0xd8, 0x7c, 0x25, 0x97, 0x13, 0x3b, 0x16, 0x45, 0xb2, 0xcf, 0x54, 0x73, 0x1d, 0x84, 0x01, 0x0e, 0x14, 0x43, 0xf3, 0x8b, 0x02, 0x62, 0x7b, 0x04, 0x87, 0x5b, 0x1c, 0x23, 0xcd, 0xaf, 0xfb, 0x94, 0x6c, 0x99, 0xd2, 0xfc, 0x2f, 0xa4, 0xea, 0x10, 0x11, 0x27, 0xd1, 0x85, 0xee, 0x47, 0x72, 0x5c, 0x2e, 0x3c, 0x86, 0xb4, 0xbf, 0xe2, 0x20, 0x92, 0x34, 0xe0, 0xff, 0x70, 0x6e, 0xcc, 0xf6, 0x33, 0xd4, 0x4f, 0x17, 0xf7, 0xad, 0x52, 0x7d, 0xe3, 0x7e, 0x0f, 0x0b, 0xf8, 0x36, 0x49, 0x58, 0xc6, 0xbe, 0x9c, 0xd3, 0x90, 0xa0, 0xa8, 0x7a, 0x41, 0x91, 0xc4, 0x44, 0x8e, 0x22, 0x74, 0xdc, 0x12, 0x0a, 0xb0, 0xb8, 0x46, 0xd5, 0x1b, 0xfa, 0xe9, 0x83, 0xc7, 0xfe, 0xa7, 0xe4, 0x3d, 0x5e, 0x8d, 0xde, 0x0d, 0xc5, 0x76, 0x89, 0x96, 0x57, 0x48, 0x69, 0x65, 0x8a, 0xbb, 0x40, 0x2c, 0x26, 0x6f, 0xa2, 0x07, 0x08, 0x15, 0xda, 0x39, 0xcb, 0x32, 0x05, 0xa6, 0xca, 0xe5, 0x98, 0x63, 0xdf, 0x1f, 0xa9, 0xd7, 0xd9, 0x61, 0x30, 0x75, 0x4a, 0x55, 0xc2, 0xd6, 0xd0, 0xa3, 0x24, 0x51, 0xf0, 0xc1, 0x2b, 0x66, 0xba, 0x77, 0x9a, 0x4b, 0xc9, 0x1e, 0xb5, 0x79, 0xb3, 0x29, 0x4c, 0xa1, 0xc8, 0x3a, 0xc0, 0xf4, 0x81, 0x80, 0xb6, 0x19, 0x93, 0xef, 0x28, 0xbd, 0x71, 0x78, 0x1a, 0x88, 0x9d, 0x00, 0x9f, 0x0c, 0x82, 0x59, 0xb9, 0x5d, 0x9e, 0x8f, 0xab, 0x42, 0xeb, 0x6b, 0x7f, 0x3f, 0xae, 0x56, 0x6d, 0xa5, 0xac, 0xbc, 0x09, 0x67, 0x2d, 0x5a, 0xe8, 0x3e, 0x06, 0x35, 0x38, 0x4e, 0x37, 0x6a, 0xdd, 0xc3, 0x60, 0xe7, 0x53, 0x18, 0x50, 0xec, 0x31, 0x4d, 0x64, 0xb1, 0xfd, 0x9b, 0xaa, 0x5f, 0xf5, 0xf1, 0x68, 0xe1, 0xed, 0xe6, 0xf9 +}, +{ +0x6e, 0xc6, 0x90, 0x3c, 0xf6, 0x76, 0x23, 0xf3, 0x48, 0xa9, 0x67, 0xf4, 0x0a, 0x02, 0xb8, 0xa0, 0xec, 0x8f, 0x56, 0x15, 0x4c, 0x75, 0x31, 0x5b, 0xe5, 0x24, 0x3b, 0xc4, 0x77, 0xbf, 0x6c, 0x3f, 0x44, 0x7e, 0xdc, 0xc2, 0x4d, 0x52, 0x86, 0x20, 0xcf, 0xe0, 0x1f, 0x45, 0xa5, 0xfd, 0x66, 0x81, 0xea, 0xfb, 0x84, 0x4a, 0xb9, 0xbd, 0xcc, 0x51, 0xc8, 0x1a, 0x12, 0x22, 0x61, 0x2e, 0x0c, 0x74, 0x49, 0x1d, 0x7f, 0x91, 0xae, 0xe9, 0x35, 0xb6, 0x58, 0x16, 0x9d, 0x4e, 0x60, 0x2b, 0xde, 0x26, 0xc0, 0xf5, 0x5c, 0x37, 0x63, 0x95, 0xa3, 0xa2, 0x92, 0x50, 0x0d, 0x06, 0x34, 0x8e, 0x9c, 0xee, 0x69, 0xb1, 0x05, 0x27, 0x98, 0x7c, 0x93, 0x3e, 0xa4, 0x89, 0xa1, 0x25, 0x97, 0xce, 0x6a, 0x40, 0xb3, 0x36, 0xaf, 0xc1, 0xe6, 0x7d, 0x00, 0xf7, 0xc9, 0xd0, 0xb0, 0x39, 0x41, 0xf1, 0xa6, 0xbc, 0x85, 0xfc, 0x8a, 0x87, 0xb4, 0x8c, 0x5a, 0xe8, 0xe2, 0xaa, 0xe1, 0x55, 0xd2, 0x71, 0x6f, 0xd8, 0x18, 0x29, 0x4f, 0x03, 0xd6, 0xff, 0x83, 0x5e, 0x4b, 0x54, 0x5f, 0x53, 0xda, 0x43, 0x47, 0xed, 0x2f, 0x3a, 0xa8, 0xca, 0xc3, 0x0f, 0x9a, 0x5d, 0x2c, 0xef, 0x0b, 0xeb, 0x30, 0xbe, 0x2d, 0xb2, 0x1c, 0x8d, 0xcd, 0xd9, 0x59, 0xf0, 0x19, 0x3d, 0x9f, 0xd5, 0xbb, 0x0e, 0x1e, 0x17, 0xdf, 0xe4, 0x42, 0xe3, 0x96, 0x11, 0x62, 0x64, 0x70, 0xe7, 0x7b, 0xf9, 0x28, 0xc5, 0x08, 0xd4, 0x99, 0x73, 0x7a, 0x13, 0xfe, 0x9b, 0x01, 0xcb, 0x07, 0xac, 0x21, 0xab, 0x04, 0x32, 0x33, 0x46, 0x72, 0x88, 0x94, 0x9e, 0xf2, 0x09, 0x38, 0xd7, 0xdb, 0xfa, 0x79, 0x8b, 0x68, 0xa7, 0xba, 0xb5, 0x10, 0xdd, 0x6d, 0xd1, 0x2a, 0x57, 0x78, 0x14, 0xb7, 0x80, 0xf8, 0xc7, 0x82, 0xd3, 0x6b, 0x65, 0x1b, 0xad +}, +{ +0x1c, 0x56, 0xc7, 0x72, 0xde, 0xd7, 0x2d, 0x16, 0x44, 0xd5, 0x10, 0x04, 0x39, 0x90, 0xf4, 0xd0, 0x26, 0xe5, 0x22, 0xc2, 0x77, 0xf9, 0x7b, 0xe4, 0xf3, 0xe6, 0x03, 0x61, 0xc6, 0x0a, 0x94, 0x53, 0x9d, 0x82, 0x9a, 0x96, 0x8a, 0x13, 0x24, 0x8e, 0xe0, 0xd1, 0xca, 0x86, 0x36, 0x1f, 0x97, 0x4a, 0x63, 0x2b, 0x9c, 0x28, 0xb8, 0x1b, 0x11, 0xa6, 0x35, 0x4c, 0x4e, 0x43, 0x45, 0x7d, 0x21, 0x93, 0x0e, 0x31, 0x1a, 0x4b, 0xac, 0xa2, 0x64, 0xd2, 0x18, 0xa4, 0x9e, 0xe3, 0xdd, 0xb1, 0x49, 0x7e, 0x42, 0xb0, 0x6e, 0xa1, 0x7c, 0x73, 0x14, 0xd9, 0x57, 0x5d, 0xc0, 0x3b, 0x1e, 0xf1, 0x33, 0x12, 0x62, 0xe8, 0xfb, 0xcd, 0x8f, 0xfa, 0x41, 0xbb, 0xda, 0xb3, 0x52, 0x37, 0x02, 0xc8, 0x65, 0xce, 0x30, 0xb2, 0x0c, 0xe1, 0x1d, 0xc1, 0xba, 0x50, 0x2a, 0x8b, 0xd8, 0x5f, 0xad, 0xab, 0x2e, 0xb9, 0xd3, 0x01, 0xeb, 0xdb, 0xe7, 0xa8, 0xbd, 0xc5, 0x32, 0x23, 0x83, 0x4d, 0x74, 0x70, 0x98, 0x05, 0x29, 0x06, 0x8c, 0xd6, 0x34, 0x6c, 0x48, 0xaf, 0xb7, 0x8d, 0x0b, 0x15, 0x9b, 0x84, 0xe9, 0x4f, 0xed, 0x2c, 0x0d, 0xf2, 0x76, 0xbe, 0xf6, 0xa5, 0x46, 0x25, 0xdc, 0x9f, 0xbc, 0x85, 0x92, 0xf8, 0x60, 0x81, 0x3d, 0xae, 0xcb, 0xc3, 0x69, 0x71, 0x0f, 0xa7, 0xf5, 0x59, 0xbf, 0x3f, 0x3a, 0xea, 0x19, 0x00, 0xf0, 0x79, 0x38, 0x88, 0x75, 0x6f, 0xff, 0x7a, 0x08, 0x66, 0xb4, 0x2f, 0x3e, 0xc9, 0x40, 0x6d, 0xec, 0x68, 0x07, 0x5e, 0x89, 0xa3, 0x78, 0xa0, 0xee, 0xcc, 0xb5, 0x51, 0xf7, 0x5a, 0x99, 0x5b, 0xcf, 0xc4, 0x47, 0xfd, 0x27, 0x55, 0x3c, 0x09, 0xfe, 0x95, 0x5c, 0xaa, 0x6b, 0x6a, 0xdf, 0x91, 0x87, 0x54, 0xe2, 0xa9, 0xef, 0x17, 0xd4, 0x80, 0x58, 0xb6, 0x20, 0x67, 0x7f, 0xfc +}, +{ +0x2f, 0x15, 0x93, 0x8d, 0x03, 0x1c, 0x71, 0xd7, 0xb1, 0x9e, 0x14, 0x4e, 0xac, 0xf4, 0xd0, 0x37, 0xaa, 0xbb, 0x1b, 0xd5, 0xec, 0xe8, 0x00, 0x9d, 0x4b, 0x99, 0x73, 0x43, 0x7f, 0x30, 0x25, 0x5d, 0x97, 0x3f, 0x6d, 0xc1, 0x27, 0xa7, 0xa2, 0x72, 0xf8, 0x19, 0xa5, 0x36, 0x53, 0x5b, 0xf1, 0xe9, 0xde, 0xbd, 0x44, 0x07, 0x24, 0x1d, 0x0a, 0x60, 0x75, 0xb4, 0x95, 0x6a, 0xee, 0x26, 0x6e, 0x3d, 0xe0, 0x38, 0x76, 0x54, 0x2d, 0xc9, 0x6f, 0xc2, 0xd8, 0xf5, 0x74, 0xf0, 0x9f, 0xc6, 0x11, 0x3b, 0x67, 0xe2, 0x90, 0xfe, 0x2c, 0xb7, 0xa6, 0x51, 0x81, 0x98, 0x68, 0xe1, 0xa0, 0x10, 0xed, 0xf7, 0x4c, 0x18, 0xc0, 0x2e, 0xb8, 0xff, 0xe7, 0x64, 0x47, 0x09, 0x1f, 0xcc, 0x7a, 0x31, 0x77, 0x8f, 0xa4, 0x91, 0x66, 0x0d, 0xc4, 0x32, 0xf3, 0xf2, 0x01, 0xc3, 0x57, 0x5c, 0xdf, 0x65, 0xbf, 0xcd, 0x6b, 0x7e, 0x9b, 0xf9, 0x5e, 0x92, 0x0c, 0xcb, 0xbe, 0x7d, 0xba, 0x5a, 0xef, 0x61, 0xe3, 0x7c, 0xdc, 0x4d, 0x88, 0x9c, 0xa1, 0x08, 0x6c, 0x48, 0x84, 0xce, 0x5f, 0xea, 0x46, 0x4f, 0xb5, 0x8e, 0xad, 0xd4, 0xd6, 0xdb, 0xdd, 0xe5, 0xb9, 0x0b, 0xfb, 0xb3, 0x04, 0xb0, 0x20, 0x83, 0x89, 0x3e, 0x78, 0x49, 0x52, 0x1e, 0xae, 0x87, 0x0f, 0xd2, 0x05, 0x1a, 0x02, 0x0e, 0x12, 0x8b, 0xbc, 0x16, 0xcf, 0xc5, 0x58, 0xa3, 0x86, 0x69, 0xab, 0x8a, 0xda, 0x28, 0xf6, 0x39, 0xe4, 0xeb, 0x8c, 0x41, 0x80, 0x3c, 0x06, 0x7b, 0x45, 0x29, 0xd1, 0xe6, 0x96, 0xa9, 0x82, 0xd3, 0x34, 0x3a, 0xfc, 0x4a, 0xb2, 0x13, 0x40, 0xc7, 0x35, 0x33, 0xb6, 0x21, 0xa8, 0x2a, 0x94, 0x79, 0x85, 0x59, 0x22, 0xc8, 0x42, 0x2b, 0xca, 0xaf, 0x9a, 0x50, 0xfd, 0x56, 0xfa, 0x70, 0x63, 0x55, 0x17, 0x62, 0xd9, 0x23 +}, +{ +0xd0, 0x18, 0xcb, 0x98, 0x42, 0x83, 0x9c, 0x63, 0xeb, 0xd2, 0x96, 0xfc, 0x4b, 0x28, 0xf1, 0xb2, 0xad, 0xa5, 0x1f, 0x07, 0xef, 0x0e, 0xc0, 0x53, 0x51, 0xd1, 0x84, 0x54, 0xc9, 0x61, 0x37, 0x9b, 0xc6, 0x89, 0xab, 0xd3, 0x6f, 0xbd, 0xb5, 0x85, 0x1e, 0x1a, 0x6b, 0xf6, 0x4d, 0x5c, 0x23, 0xed, 0x02, 0x5a, 0xc1, 0x26, 0x68, 0x47, 0xb8, 0xe2, 0xea, 0xf5, 0x21, 0x87, 0xe3, 0xd9, 0x7b, 0x65, 0x93, 0x29, 0x3b, 0x49, 0x35, 0xf7, 0xaa, 0xa1, 0xc4, 0x32, 0x04, 0x05, 0x67, 0x52, 0xfb, 0x90, 0xc7, 0x8c, 0x79, 0x81, 0xff, 0xb1, 0x3a, 0xe9, 0x09, 0x4e, 0x92, 0x11, 0xee, 0xba, 0xd8, 0x36, 0xe6, 0x56, 0x01, 0x1b, 0x6e, 0x77, 0x17, 0x9e, 0x41, 0xda, 0xa7, 0x50, 0x14, 0x91, 0x08, 0x66, 0x30, 0x69, 0xcd, 0xe7, 0x03, 0x2e, 0x06, 0x82, 0x3f, 0xdb, 0x34, 0x99, 0xce, 0x16, 0xa2, 0x80, 0x7d, 0xe4, 0xe0, 0x4a, 0xec, 0xf3, 0xf8, 0xf4, 0x71, 0x58, 0x24, 0xf9, 0xbf, 0x8e, 0xe8, 0xa4, 0x75, 0xd6, 0xc8, 0x7f, 0x45, 0x0d, 0x46, 0xf2, 0x13, 0x2b, 0xfd, 0x4f, 0x22, 0x5b, 0x2d, 0x20, 0xb9, 0xb0, 0x78, 0x43, 0x38, 0x72, 0x1c, 0xa9, 0xfe, 0x57, 0xbe, 0x9a, 0xbb, 0x2a, 0x6a, 0x7e, 0x97, 0x19, 0x8a, 0x15, 0x8b, 0x48, 0xac, 0x4c, 0x64, 0xa8, 0x3d, 0xfa, 0x88, 0x9d, 0x0f, 0x6d, 0x94, 0xe1, 0xd5, 0x2f, 0x86, 0x0c, 0xa3, 0x95, 0xa6, 0x6c, 0xa0, 0x0b, 0xdd, 0xb4, 0x59, 0x3c, 0xaf, 0x73, 0x3e, 0xd4, 0xdc, 0x5e, 0x8f, 0x62, 0xc5, 0xc3, 0xd7, 0x40, 0xe5, 0x44, 0x31, 0xb6, 0xcc, 0xc2, 0xbc, 0x0a, 0x5f, 0x60, 0x25, 0x74, 0xdf, 0xb3, 0x10, 0x27, 0xca, 0x76, 0x8d, 0xf0, 0x1d, 0x12, 0xb7, 0x7a, 0xde, 0x2c, 0xcf, 0x00, 0x9f, 0x70, 0x7c, 0x5d, 0x33, 0x39, 0x55, 0xae +} +} +}; +unsigned int TyiTables[4][256] = +{ +{ +0x00000000, 0x02010103, 0x04020206, 0x06030305, 0x0804040c, 0x0a05050f, 0x0c06060a, 0x0e070709, 0x10080818, 0x1209091b, 0x140a0a1e, 0x160b0b1d, 0x180c0c14, 0x1a0d0d17, 0x1c0e0e12, 0x1e0f0f11, 0x20101030, 0x22111133, 0x24121236, 0x26131335, 0x2814143c, 0x2a15153f, 0x2c16163a, 0x2e171739, 0x30181828, 0x3219192b, 0x341a1a2e, 0x361b1b2d, 0x381c1c24, 0x3a1d1d27, 0x3c1e1e22, 0x3e1f1f21, 0x40202060, 0x42212163, 0x44222266, 0x46232365, 0x4824246c, 0x4a25256f, 0x4c26266a, 0x4e272769, 0x50282878, 0x5229297b, 0x542a2a7e, 0x562b2b7d, 0x582c2c74, 0x5a2d2d77, 0x5c2e2e72, 0x5e2f2f71, 0x60303050, 0x62313153, 0x64323256, 0x66333355, 0x6834345c, 0x6a35355f, 0x6c36365a, 0x6e373759, 0x70383848, 0x7239394b, 0x743a3a4e, 0x763b3b4d, 0x783c3c44, 0x7a3d3d47, 0x7c3e3e42, 0x7e3f3f41, 0x804040c0, 0x824141c3, 0x844242c6, 0x864343c5, 0x884444cc, 0x8a4545cf, 0x8c4646ca, 0x8e4747c9, 0x904848d8, 0x924949db, 0x944a4ade, 0x964b4bdd, 0x984c4cd4, 0x9a4d4dd7, 0x9c4e4ed2, 0x9e4f4fd1, 0xa05050f0, 0xa25151f3, 0xa45252f6, 0xa65353f5, 0xa85454fc, 0xaa5555ff, 0xac5656fa, 0xae5757f9, 0xb05858e8, 0xb25959eb, 0xb45a5aee, 0xb65b5bed, 0xb85c5ce4, 0xba5d5de7, 0xbc5e5ee2, 0xbe5f5fe1, 0xc06060a0, 0xc26161a3, 0xc46262a6, 0xc66363a5, 0xc86464ac, 0xca6565af, 0xcc6666aa, 0xce6767a9, 0xd06868b8, 0xd26969bb, 0xd46a6abe, 0xd66b6bbd, 0xd86c6cb4, 0xda6d6db7, 0xdc6e6eb2, 0xde6f6fb1, 0xe0707090, 0xe2717193, 0xe4727296, 0xe6737395, 0xe874749c, 0xea75759f, 0xec76769a, 0xee777799, 0xf0787888, 0xf279798b, 0xf47a7a8e, 0xf67b7b8d, 0xf87c7c84, 0xfa7d7d87, 0xfc7e7e82, 0xfe7f7f81, 0x1b80809b, 0x19818198, 0x1f82829d, 0x1d83839e, 0x13848497, 0x11858594, 0x17868691, 0x15878792, 0x0b888883, 0x09898980, 0x0f8a8a85, 0x0d8b8b86, 0x038c8c8f, 0x018d8d8c, 0x078e8e89, 0x058f8f8a, 0x3b9090ab, 0x399191a8, 0x3f9292ad, 0x3d9393ae, 0x339494a7, 0x319595a4, 0x379696a1, 0x359797a2, 0x2b9898b3, 0x299999b0, 0x2f9a9ab5, 0x2d9b9bb6, 0x239c9cbf, 0x219d9dbc, 0x279e9eb9, 0x259f9fba, 0x5ba0a0fb, 0x59a1a1f8, 0x5fa2a2fd, 0x5da3a3fe, 0x53a4a4f7, 0x51a5a5f4, 0x57a6a6f1, 0x55a7a7f2, 0x4ba8a8e3, 0x49a9a9e0, 0x4faaaae5, 0x4dababe6, 0x43acacef, 0x41adadec, 0x47aeaee9, 0x45afafea, 0x7bb0b0cb, 0x79b1b1c8, 0x7fb2b2cd, 0x7db3b3ce, 0x73b4b4c7, 0x71b5b5c4, 0x77b6b6c1, 0x75b7b7c2, 0x6bb8b8d3, 0x69b9b9d0, 0x6fbabad5, 0x6dbbbbd6, 0x63bcbcdf, 0x61bdbddc, 0x67bebed9, 0x65bfbfda, 0x9bc0c05b, 0x99c1c158, 0x9fc2c25d, 0x9dc3c35e, 0x93c4c457, 0x91c5c554, 0x97c6c651, 0x95c7c752, 0x8bc8c843, 0x89c9c940, 0x8fcaca45, 0x8dcbcb46, 0x83cccc4f, 0x81cdcd4c, 0x87cece49, 0x85cfcf4a, 0xbbd0d06b, 0xb9d1d168, 0xbfd2d26d, 0xbdd3d36e, 0xb3d4d467, 0xb1d5d564, 0xb7d6d661, 0xb5d7d762, 0xabd8d873, 0xa9d9d970, 0xafdada75, 0xaddbdb76, 0xa3dcdc7f, 0xa1dddd7c, 0xa7dede79, 0xa5dfdf7a, 0xdbe0e03b, 0xd9e1e138, 0xdfe2e23d, 0xdde3e33e, 0xd3e4e437, 0xd1e5e534, 0xd7e6e631, 0xd5e7e732, 0xcbe8e823, 0xc9e9e920, 0xcfeaea25, 0xcdebeb26, 0xc3ecec2f, 0xc1eded2c, 0xc7eeee29, 0xc5efef2a, 0xfbf0f00b, 0xf9f1f108, 0xfff2f20d, 0xfdf3f30e, 0xf3f4f407, 0xf1f5f504, 0xf7f6f601, 0xf5f7f702, 0xebf8f813, 0xe9f9f910, 0xeffafa15, 0xedfbfb16, 0xe3fcfc1f, 0xe1fdfd1c, 0xe7fefe19, 0xe5ffff1a +}, +{ +0x00000000, 0x03020101, 0x06040202, 0x05060303, 0x0c080404, 0x0f0a0505, 0x0a0c0606, 0x090e0707, 0x18100808, 0x1b120909, 0x1e140a0a, 0x1d160b0b, 0x14180c0c, 0x171a0d0d, 0x121c0e0e, 0x111e0f0f, 0x30201010, 0x33221111, 0x36241212, 0x35261313, 0x3c281414, 0x3f2a1515, 0x3a2c1616, 0x392e1717, 0x28301818, 0x2b321919, 0x2e341a1a, 0x2d361b1b, 0x24381c1c, 0x273a1d1d, 0x223c1e1e, 0x213e1f1f, 0x60402020, 0x63422121, 0x66442222, 0x65462323, 0x6c482424, 0x6f4a2525, 0x6a4c2626, 0x694e2727, 0x78502828, 0x7b522929, 0x7e542a2a, 0x7d562b2b, 0x74582c2c, 0x775a2d2d, 0x725c2e2e, 0x715e2f2f, 0x50603030, 0x53623131, 0x56643232, 0x55663333, 0x5c683434, 0x5f6a3535, 0x5a6c3636, 0x596e3737, 0x48703838, 0x4b723939, 0x4e743a3a, 0x4d763b3b, 0x44783c3c, 0x477a3d3d, 0x427c3e3e, 0x417e3f3f, 0xc0804040, 0xc3824141, 0xc6844242, 0xc5864343, 0xcc884444, 0xcf8a4545, 0xca8c4646, 0xc98e4747, 0xd8904848, 0xdb924949, 0xde944a4a, 0xdd964b4b, 0xd4984c4c, 0xd79a4d4d, 0xd29c4e4e, 0xd19e4f4f, 0xf0a05050, 0xf3a25151, 0xf6a45252, 0xf5a65353, 0xfca85454, 0xffaa5555, 0xfaac5656, 0xf9ae5757, 0xe8b05858, 0xebb25959, 0xeeb45a5a, 0xedb65b5b, 0xe4b85c5c, 0xe7ba5d5d, 0xe2bc5e5e, 0xe1be5f5f, 0xa0c06060, 0xa3c26161, 0xa6c46262, 0xa5c66363, 0xacc86464, 0xafca6565, 0xaacc6666, 0xa9ce6767, 0xb8d06868, 0xbbd26969, 0xbed46a6a, 0xbdd66b6b, 0xb4d86c6c, 0xb7da6d6d, 0xb2dc6e6e, 0xb1de6f6f, 0x90e07070, 0x93e27171, 0x96e47272, 0x95e67373, 0x9ce87474, 0x9fea7575, 0x9aec7676, 0x99ee7777, 0x88f07878, 0x8bf27979, 0x8ef47a7a, 0x8df67b7b, 0x84f87c7c, 0x87fa7d7d, 0x82fc7e7e, 0x81fe7f7f, 0x9b1b8080, 0x98198181, 0x9d1f8282, 0x9e1d8383, 0x97138484, 0x94118585, 0x91178686, 0x92158787, 0x830b8888, 0x80098989, 0x850f8a8a, 0x860d8b8b, 0x8f038c8c, 0x8c018d8d, 0x89078e8e, 0x8a058f8f, 0xab3b9090, 0xa8399191, 0xad3f9292, 0xae3d9393, 0xa7339494, 0xa4319595, 0xa1379696, 0xa2359797, 0xb32b9898, 0xb0299999, 0xb52f9a9a, 0xb62d9b9b, 0xbf239c9c, 0xbc219d9d, 0xb9279e9e, 0xba259f9f, 0xfb5ba0a0, 0xf859a1a1, 0xfd5fa2a2, 0xfe5da3a3, 0xf753a4a4, 0xf451a5a5, 0xf157a6a6, 0xf255a7a7, 0xe34ba8a8, 0xe049a9a9, 0xe54faaaa, 0xe64dabab, 0xef43acac, 0xec41adad, 0xe947aeae, 0xea45afaf, 0xcb7bb0b0, 0xc879b1b1, 0xcd7fb2b2, 0xce7db3b3, 0xc773b4b4, 0xc471b5b5, 0xc177b6b6, 0xc275b7b7, 0xd36bb8b8, 0xd069b9b9, 0xd56fbaba, 0xd66dbbbb, 0xdf63bcbc, 0xdc61bdbd, 0xd967bebe, 0xda65bfbf, 0x5b9bc0c0, 0x5899c1c1, 0x5d9fc2c2, 0x5e9dc3c3, 0x5793c4c4, 0x5491c5c5, 0x5197c6c6, 0x5295c7c7, 0x438bc8c8, 0x4089c9c9, 0x458fcaca, 0x468dcbcb, 0x4f83cccc, 0x4c81cdcd, 0x4987cece, 0x4a85cfcf, 0x6bbbd0d0, 0x68b9d1d1, 0x6dbfd2d2, 0x6ebdd3d3, 0x67b3d4d4, 0x64b1d5d5, 0x61b7d6d6, 0x62b5d7d7, 0x73abd8d8, 0x70a9d9d9, 0x75afdada, 0x76addbdb, 0x7fa3dcdc, 0x7ca1dddd, 0x79a7dede, 0x7aa5dfdf, 0x3bdbe0e0, 0x38d9e1e1, 0x3ddfe2e2, 0x3edde3e3, 0x37d3e4e4, 0x34d1e5e5, 0x31d7e6e6, 0x32d5e7e7, 0x23cbe8e8, 0x20c9e9e9, 0x25cfeaea, 0x26cdebeb, 0x2fc3ecec, 0x2cc1eded, 0x29c7eeee, 0x2ac5efef, 0x0bfbf0f0, 0x08f9f1f1, 0x0dfff2f2, 0x0efdf3f3, 0x07f3f4f4, 0x04f1f5f5, 0x01f7f6f6, 0x02f5f7f7, 0x13ebf8f8, 0x10e9f9f9, 0x15effafa, 0x16edfbfb, 0x1fe3fcfc, 0x1ce1fdfd, 0x19e7fefe, 0x1ae5ffff +}, +{ +0x00000000, 0x01030201, 0x02060402, 0x03050603, 0x040c0804, 0x050f0a05, 0x060a0c06, 0x07090e07, 0x08181008, 0x091b1209, 0x0a1e140a, 0x0b1d160b, 0x0c14180c, 0x0d171a0d, 0x0e121c0e, 0x0f111e0f, 0x10302010, 0x11332211, 0x12362412, 0x13352613, 0x143c2814, 0x153f2a15, 0x163a2c16, 0x17392e17, 0x18283018, 0x192b3219, 0x1a2e341a, 0x1b2d361b, 0x1c24381c, 0x1d273a1d, 0x1e223c1e, 0x1f213e1f, 0x20604020, 0x21634221, 0x22664422, 0x23654623, 0x246c4824, 0x256f4a25, 0x266a4c26, 0x27694e27, 0x28785028, 0x297b5229, 0x2a7e542a, 0x2b7d562b, 0x2c74582c, 0x2d775a2d, 0x2e725c2e, 0x2f715e2f, 0x30506030, 0x31536231, 0x32566432, 0x33556633, 0x345c6834, 0x355f6a35, 0x365a6c36, 0x37596e37, 0x38487038, 0x394b7239, 0x3a4e743a, 0x3b4d763b, 0x3c44783c, 0x3d477a3d, 0x3e427c3e, 0x3f417e3f, 0x40c08040, 0x41c38241, 0x42c68442, 0x43c58643, 0x44cc8844, 0x45cf8a45, 0x46ca8c46, 0x47c98e47, 0x48d89048, 0x49db9249, 0x4ade944a, 0x4bdd964b, 0x4cd4984c, 0x4dd79a4d, 0x4ed29c4e, 0x4fd19e4f, 0x50f0a050, 0x51f3a251, 0x52f6a452, 0x53f5a653, 0x54fca854, 0x55ffaa55, 0x56faac56, 0x57f9ae57, 0x58e8b058, 0x59ebb259, 0x5aeeb45a, 0x5bedb65b, 0x5ce4b85c, 0x5de7ba5d, 0x5ee2bc5e, 0x5fe1be5f, 0x60a0c060, 0x61a3c261, 0x62a6c462, 0x63a5c663, 0x64acc864, 0x65afca65, 0x66aacc66, 0x67a9ce67, 0x68b8d068, 0x69bbd269, 0x6abed46a, 0x6bbdd66b, 0x6cb4d86c, 0x6db7da6d, 0x6eb2dc6e, 0x6fb1de6f, 0x7090e070, 0x7193e271, 0x7296e472, 0x7395e673, 0x749ce874, 0x759fea75, 0x769aec76, 0x7799ee77, 0x7888f078, 0x798bf279, 0x7a8ef47a, 0x7b8df67b, 0x7c84f87c, 0x7d87fa7d, 0x7e82fc7e, 0x7f81fe7f, 0x809b1b80, 0x81981981, 0x829d1f82, 0x839e1d83, 0x84971384, 0x85941185, 0x86911786, 0x87921587, 0x88830b88, 0x89800989, 0x8a850f8a, 0x8b860d8b, 0x8c8f038c, 0x8d8c018d, 0x8e89078e, 0x8f8a058f, 0x90ab3b90, 0x91a83991, 0x92ad3f92, 0x93ae3d93, 0x94a73394, 0x95a43195, 0x96a13796, 0x97a23597, 0x98b32b98, 0x99b02999, 0x9ab52f9a, 0x9bb62d9b, 0x9cbf239c, 0x9dbc219d, 0x9eb9279e, 0x9fba259f, 0xa0fb5ba0, 0xa1f859a1, 0xa2fd5fa2, 0xa3fe5da3, 0xa4f753a4, 0xa5f451a5, 0xa6f157a6, 0xa7f255a7, 0xa8e34ba8, 0xa9e049a9, 0xaae54faa, 0xabe64dab, 0xacef43ac, 0xadec41ad, 0xaee947ae, 0xafea45af, 0xb0cb7bb0, 0xb1c879b1, 0xb2cd7fb2, 0xb3ce7db3, 0xb4c773b4, 0xb5c471b5, 0xb6c177b6, 0xb7c275b7, 0xb8d36bb8, 0xb9d069b9, 0xbad56fba, 0xbbd66dbb, 0xbcdf63bc, 0xbddc61bd, 0xbed967be, 0xbfda65bf, 0xc05b9bc0, 0xc15899c1, 0xc25d9fc2, 0xc35e9dc3, 0xc45793c4, 0xc55491c5, 0xc65197c6, 0xc75295c7, 0xc8438bc8, 0xc94089c9, 0xca458fca, 0xcb468dcb, 0xcc4f83cc, 0xcd4c81cd, 0xce4987ce, 0xcf4a85cf, 0xd06bbbd0, 0xd168b9d1, 0xd26dbfd2, 0xd36ebdd3, 0xd467b3d4, 0xd564b1d5, 0xd661b7d6, 0xd762b5d7, 0xd873abd8, 0xd970a9d9, 0xda75afda, 0xdb76addb, 0xdc7fa3dc, 0xdd7ca1dd, 0xde79a7de, 0xdf7aa5df, 0xe03bdbe0, 0xe138d9e1, 0xe23ddfe2, 0xe33edde3, 0xe437d3e4, 0xe534d1e5, 0xe631d7e6, 0xe732d5e7, 0xe823cbe8, 0xe920c9e9, 0xea25cfea, 0xeb26cdeb, 0xec2fc3ec, 0xed2cc1ed, 0xee29c7ee, 0xef2ac5ef, 0xf00bfbf0, 0xf108f9f1, 0xf20dfff2, 0xf30efdf3, 0xf407f3f4, 0xf504f1f5, 0xf601f7f6, 0xf702f5f7, 0xf813ebf8, 0xf910e9f9, 0xfa15effa, 0xfb16edfb, 0xfc1fe3fc, 0xfd1ce1fd, 0xfe19e7fe, 0xff1ae5ff +}, +{ +0x00000000, 0x01010302, 0x02020604, 0x03030506, 0x04040c08, 0x05050f0a, 0x06060a0c, 0x0707090e, 0x08081810, 0x09091b12, 0x0a0a1e14, 0x0b0b1d16, 0x0c0c1418, 0x0d0d171a, 0x0e0e121c, 0x0f0f111e, 0x10103020, 0x11113322, 0x12123624, 0x13133526, 0x14143c28, 0x15153f2a, 0x16163a2c, 0x1717392e, 0x18182830, 0x19192b32, 0x1a1a2e34, 0x1b1b2d36, 0x1c1c2438, 0x1d1d273a, 0x1e1e223c, 0x1f1f213e, 0x20206040, 0x21216342, 0x22226644, 0x23236546, 0x24246c48, 0x25256f4a, 0x26266a4c, 0x2727694e, 0x28287850, 0x29297b52, 0x2a2a7e54, 0x2b2b7d56, 0x2c2c7458, 0x2d2d775a, 0x2e2e725c, 0x2f2f715e, 0x30305060, 0x31315362, 0x32325664, 0x33335566, 0x34345c68, 0x35355f6a, 0x36365a6c, 0x3737596e, 0x38384870, 0x39394b72, 0x3a3a4e74, 0x3b3b4d76, 0x3c3c4478, 0x3d3d477a, 0x3e3e427c, 0x3f3f417e, 0x4040c080, 0x4141c382, 0x4242c684, 0x4343c586, 0x4444cc88, 0x4545cf8a, 0x4646ca8c, 0x4747c98e, 0x4848d890, 0x4949db92, 0x4a4ade94, 0x4b4bdd96, 0x4c4cd498, 0x4d4dd79a, 0x4e4ed29c, 0x4f4fd19e, 0x5050f0a0, 0x5151f3a2, 0x5252f6a4, 0x5353f5a6, 0x5454fca8, 0x5555ffaa, 0x5656faac, 0x5757f9ae, 0x5858e8b0, 0x5959ebb2, 0x5a5aeeb4, 0x5b5bedb6, 0x5c5ce4b8, 0x5d5de7ba, 0x5e5ee2bc, 0x5f5fe1be, 0x6060a0c0, 0x6161a3c2, 0x6262a6c4, 0x6363a5c6, 0x6464acc8, 0x6565afca, 0x6666aacc, 0x6767a9ce, 0x6868b8d0, 0x6969bbd2, 0x6a6abed4, 0x6b6bbdd6, 0x6c6cb4d8, 0x6d6db7da, 0x6e6eb2dc, 0x6f6fb1de, 0x707090e0, 0x717193e2, 0x727296e4, 0x737395e6, 0x74749ce8, 0x75759fea, 0x76769aec, 0x777799ee, 0x787888f0, 0x79798bf2, 0x7a7a8ef4, 0x7b7b8df6, 0x7c7c84f8, 0x7d7d87fa, 0x7e7e82fc, 0x7f7f81fe, 0x80809b1b, 0x81819819, 0x82829d1f, 0x83839e1d, 0x84849713, 0x85859411, 0x86869117, 0x87879215, 0x8888830b, 0x89898009, 0x8a8a850f, 0x8b8b860d, 0x8c8c8f03, 0x8d8d8c01, 0x8e8e8907, 0x8f8f8a05, 0x9090ab3b, 0x9191a839, 0x9292ad3f, 0x9393ae3d, 0x9494a733, 0x9595a431, 0x9696a137, 0x9797a235, 0x9898b32b, 0x9999b029, 0x9a9ab52f, 0x9b9bb62d, 0x9c9cbf23, 0x9d9dbc21, 0x9e9eb927, 0x9f9fba25, 0xa0a0fb5b, 0xa1a1f859, 0xa2a2fd5f, 0xa3a3fe5d, 0xa4a4f753, 0xa5a5f451, 0xa6a6f157, 0xa7a7f255, 0xa8a8e34b, 0xa9a9e049, 0xaaaae54f, 0xababe64d, 0xacacef43, 0xadadec41, 0xaeaee947, 0xafafea45, 0xb0b0cb7b, 0xb1b1c879, 0xb2b2cd7f, 0xb3b3ce7d, 0xb4b4c773, 0xb5b5c471, 0xb6b6c177, 0xb7b7c275, 0xb8b8d36b, 0xb9b9d069, 0xbabad56f, 0xbbbbd66d, 0xbcbcdf63, 0xbdbddc61, 0xbebed967, 0xbfbfda65, 0xc0c05b9b, 0xc1c15899, 0xc2c25d9f, 0xc3c35e9d, 0xc4c45793, 0xc5c55491, 0xc6c65197, 0xc7c75295, 0xc8c8438b, 0xc9c94089, 0xcaca458f, 0xcbcb468d, 0xcccc4f83, 0xcdcd4c81, 0xcece4987, 0xcfcf4a85, 0xd0d06bbb, 0xd1d168b9, 0xd2d26dbf, 0xd3d36ebd, 0xd4d467b3, 0xd5d564b1, 0xd6d661b7, 0xd7d762b5, 0xd8d873ab, 0xd9d970a9, 0xdada75af, 0xdbdb76ad, 0xdcdc7fa3, 0xdddd7ca1, 0xdede79a7, 0xdfdf7aa5, 0xe0e03bdb, 0xe1e138d9, 0xe2e23ddf, 0xe3e33edd, 0xe4e437d3, 0xe5e534d1, 0xe6e631d7, 0xe7e732d5, 0xe8e823cb, 0xe9e920c9, 0xeaea25cf, 0xebeb26cd, 0xecec2fc3, 0xeded2cc1, 0xeeee29c7, 0xefef2ac5, 0xf0f00bfb, 0xf1f108f9, 0xf2f20dff, 0xf3f30efd, 0xf4f407f3, 0xf5f504f1, 0xf6f601f7, 0xf7f702f5, 0xf8f813eb, 0xf9f910e9, 0xfafa15ef, 0xfbfb16ed, 0xfcfc1fe3, 0xfdfd1ce1, 0xfefe19e7, 0xffff1ae5 +} +}; +unsigned int TyiBoxes[9][16][256] = +{ +{ +{ +0x14ea1f49, 0x025e3678, 0x75569d5b, 0xccb185b8, 0x3bd9f35c, 0x67ea6980, 0x6a9de62b, 0x53193895, 0x99fe56bf, 0xbdecde93, 0xeef5e606, 0x43fbfa36, 0xc39b27f1, 0x7e77f962, 0x1bc0bd00, 0xcae475b0, 0x51441577, 0x2412882c, 0x34f04a8f, 0xd124c8b0, 0xecabd07e, 0xaf502a48, 0x241193b6, 0x67e9721a, 0x4a87b3ed, 0xf13e9d76, 0x8060ddc7, 0x6e953bc1, 0x199e8b78, 0x1bc3a69a, 0x0f2aa249, 0xd52f0ec0, 0x00000000, 0x9ba37b5d, 0x3fd12eb6, 0x4e8c759d, 0x9df68b55, 0xd858816b, 0xc790e181, 0xfa1ff94f, 0xa47255eb, 0x41a5cc4e, 0x7e74e2f8, 0xf842d4ad, 0xe8a30d94, 0x16b42931, 0xb9e40379, 0x1d954d08, 0xceefb3c0, 0xb6cea130, 0x9df590cf, 0x0b216439, 0xa224be79, 0xfc4a0947, 0xccb29e22, 0x90821f64, 0x908104fe, 0xd77138b8, 0x45ad11a4, 0x0b227fa3, 0xfe143f3f, 0xd52c155a, 0x5a65714e, 0xd85b9af1, 0xf76b6d7e, 0x1fcb7b70, 0xeef6fd9c, 0xf13d86ec, 0x948ac28e, 0x8d1449f6, 0xfc4912dd, 0x846b1bb7, 0x3bdae8c6, 0xa227a5e3, 0xde0d7163, 0x51470eed, 0xad0d07aa, 0x5c308146, 0x3fd2352c, 0x199d90e2, 0x10e1d939, 0x63e1aff0, 0x3987c524, 0x8063c65d, 0x2d6dda6d, 0x264fa5ce, 0x782112f0, 0xe5d4823f, 0x7c2ad480, 0x891c941c, 0x32a6a11d, 0x68c0cbc9, 0xa62c6393, 0x8f4a7f8e, 0xb2c67cda, 0xd379e552, 0xb2c56740, 0xbbb92e9b, 0x823eebbf, 0x715d5b2b, 0xcae76e2a, 0xf360ab0e, 0x5e6eb73e, 0x92df3286, 0xb6cdbaaa, 0xc5ced7f9, 0x8f496414, 0xda06b713, 0x823df025, 0x2f30f78f, 0x29650787, 0x12bcf4db, 0x16b732ab, 0x1fc860ea, 0xe3817237, 0xc1c51189, 0xeafe2076, 0xbbba3501, 0xb9e718e3, 0x0408ddea, 0x0d778fab, 0x10e2c2a3, 0xdc505c81, 0x7a7c3f12, 0x2b382a65, 0x6ccb0db9, 0xb0984aa2, 0xeafd3bec, 0xa62f7809, 0x73036d53, 0x32a5ba87, 0x86363655, 0x5e6daca4, 0x34f35115, 0xde0e6af9, 0x4cd1587f, 0xb4938cd2, 0x3984debe, 0x6e96205b, 0xbdefc509, 0x30f89765, 0xbfb1f371, 0xe78ab447, 0xe1dc5fd5, 0xc793fa1b, 0x61bc8212, 0x92dc291c, 0x14e904d3, 0x7822096a, 0xceeca85a, 0x4e8f6e07, 0xa905da40, 0xe5d799a5, 0x755586c1, 0xf76876e4, 0x58385cac, 0x20194e5c, 0x0d749431, 0x6cc81623, 0x9ba060c7, 0x730076c9, 0x770bb0b9, 0xc8ba43c8, 0x9fa8bd2d, 0x5711e57f, 0x43f8e1ac, 0xf363b094, 0x30fb8cff, 0xd127d32a, 0x7a7f2488, 0xa906c1da, 0x48da9e0f, 0x68c3d053, 0x63e2b46a, 0x9faba6b7, 0x554cc89d, 0x531a230f, 0x8468002d, 0x4a84a877, 0x2f33ec15, 0x097c49db, 0x8b41b9fe, 0x12bfef41, 0x583b4736, 0x264cbe54, 0x224463be, 0x0f29b9d3, 0x47f327dc, 0xeca8cbe4, 0x96d4f4f6, 0xc3983c6b, 0x9489d914, 0x025d2de2, 0xa079939b, 0x36ad676d, 0xc8b95852, 0x5712fee5, 0x61bf9988, 0x48d98595, 0xa07a8801, 0x1d965692, 0x45ae0a3e, 0xda05ac89, 0xab5bec38, 0xbfb2e8eb, 0xe789afdd, 0x47f03c46, 0x65b45ff8, 0x715e40b1, 0xad0e1c30, 0xe8a0160e, 0x96d7ef6c, 0x29661c1d, 0x0655f008, 0x891f8f86, 0xa4714e71, 0xf5355b06, 0x99fd4d25, 0x65b74462, 0x040bc670, 0x0656eb92, 0x554fd307, 0x5a666ad4, 0xb4909748, 0x2d6ec1f7, 0x3d8f18ce, 0xd37afec8, 0x41a6d7d4, 0x201a55c6, 0xdc53471b, 0x8d17526c, 0x6a9efdb1, 0x00031b9a, 0xf536409c, 0xb09b5138, 0xab58f7a2, 0xd7722322, 0xe38269ad, 0x7708ab23, 0x4cd243e5, 0x2b3b31ff, 0xe1df444f, 0x5c339adc, 0x097f5241, 0xfa1ce2d5, 0xc5cdcc63, 0x36ae7cf7, 0xfe1724a5, 0x8b42a264, 0xaf5331d2, 0xc1c60a13, 0x22477824, 0x86352dcf, 0xf841cf37, 0x3d8c0354, 0x7c29cf1a +}, +{ +0xe9655384, 0xf1fee461, 0x189bb7e5, 0xfb10dab1, 0x4c22e3c8, 0xb62a8cff, 0x612759cf, 0x29349a55, 0x61372577, 0x22d26dbb, 0xe86d9aba, 0xdceb22de, 0x0aee3ed0, 0xec5cbae8, 0x7c850746, 0x95e054c2, 0x7c957bfe, 0xbcd4ce97, 0xd22440e4, 0x6516799d, 0xbcc4b22f, 0xb8f5927d, 0xe6b28438, 0xab88d276, 0xdde3ebe0, 0xb3136593, 0x5190c1f9, 0xcabff701, 0x7d9db2c0, 0x8d7be327, 0x43e548cc, 0x9a27ffc6, 0xd70dd530, 0x1caa97b7, 0xa07e5920, 0xcf861e6d, 0x79bcee2a, 0x5e471645, 0x895abfcd, 0x358e715a, 0x509808c7, 0x0118b586, 0x0afe4268, 0xff31865b, 0x052995d4, 0x9b3f4a40, 0xcbb73e3f, 0x5e576afd, 0x78b42714, 0xec4cc650, 0x5a664aaf, 0x7763f0a8, 0x30b79836, 0x82bc4823, 0xe283a46a, 0xc1497c57, 0xd8ca7e34, 0x42ed81f2, 0x27eb84d7, 0x1db22231, 0x83b4811d, 0xafb9f224, 0xafa98e9c, 0xfb00a609, 0x27fbf86f, 0xa547b04c, 0x22c21103, 0x175c1ce1, 0x43f53474, 0xbddc07a9, 0xa06e2598, 0x9e16df94, 0x641eb0a3, 0xb303192b, 0xf0f62d5f, 0x767b452e, 0x77738c10, 0x6ad1d299, 0xaa801b48, 0x5a763617, 0x1da25e89, 0xa166eca6, 0x868d6871, 0x23cad83d, 0xe293d8d2, 0xc470953b, 0xf5dfb88b, 0x91c10828, 0x8d6b9f9f, 0x3e6886b4, 0xab98aece, 0x0be6f7ee, 0x6fe83bf5, 0x7d8dce78, 0x282c2fd3, 0x4813c39a, 0x79ac9292, 0xaea147a2, 0x1644a967, 0x00000000, 0xa45f05ca, 0x283c536b, 0x725a19c4, 0x46ccdd18, 0xc460e983, 0xe87de602, 0x46dca1a0, 0xb8e5eec5, 0x3a59a6e6, 0xc041b569, 0x359e0de2, 0xa176901e, 0x0fc7ab04, 0x04312052, 0xbdcc7b11, 0x0539e96c, 0x19830263, 0x65060525, 0xf4d771b5, 0xaa9067f0, 0x4d3a564e, 0x766b3996, 0x4d2a2af6, 0x5b7eff29, 0x30a7e48e, 0x2c0d7339, 0x2d15c6bf, 0xd61560b6, 0x174c6059, 0xc15900ef, 0xcaaf8bb9, 0x603fec49, 0x885276f3, 0x2924e6ed, 0xf0e651e7, 0x31bf5108, 0x8795ddf7, 0x1265f58d, 0x3496c4dc, 0x78a45bac, 0x82ac349b, 0x1654d5df, 0xdcfb5e66, 0xd2343c5c, 0x490b761c, 0xe38b6d54, 0xd71da988, 0x95f0287a, 0xfa18138f, 0x136d3cb3, 0x5088747f, 0xd9c2b70a, 0x724a657c, 0xc051c9d1, 0x3486b864, 0xd9d2cbb2, 0x9f0e6a12, 0x6ef08e73, 0x5180bd41, 0x12758935, 0x04215cea, 0x3f604f8a, 0x8c6356a1, 0xe9752f3c, 0xff21fae3, 0x23daa485, 0x00107cb8, 0xb63af047, 0xc56820bd, 0xed440f6e, 0x9b2f36f8, 0x42fdfd4a, 0x5b6e8391, 0x8785a14f, 0xaeb13b1a, 0x0fd7d7bc, 0x2d05ba07, 0x3e78fa0c, 0xce8ed753, 0xb9fd5b43, 0x94e89dfc, 0x83a4fda5, 0x4803bf22, 0xe6a2f880, 0xd6051c0e, 0x3a49da5e, 0xb72245c1, 0x7352d0fa, 0x88420a4b, 0xce9eabeb, 0x869d14c9, 0x6ee0f2cb, 0x2c1d0f81, 0xf1ee98d9, 0xf5cfc433, 0xd8da028c, 0x19937edb, 0x602f90f1, 0xe39b11ec, 0x1cbaeb0f, 0xb20bd015, 0xcf9662d5, 0xfe2933dd, 0xddf39758, 0x8c732a19, 0x9e06a32c, 0x90c9c116, 0x91d17490, 0x55a1e1ab, 0x3b411360, 0xb21bacad, 0x6ac1ae21, 0xa557ccf4, 0x3b516fd8, 0x47c41426, 0xfa086f37, 0x4c329f70, 0xb9ed27fb, 0xe7ba4d06, 0xfe394f65, 0x54b9542d, 0xed5473d6, 0x5f4fdf7b, 0xf4c70d0d, 0x640ecc1b, 0x55b19d13, 0xc5785c05, 0xb7323979, 0xd32c89da, 0xcba74287, 0x26e34de9, 0x7342ac42, 0x6bd91ba7, 0xe7aa31be, 0x9a37837e, 0x5f5fa3c3, 0x137d400b, 0x26f33151, 0x90d9bdae, 0x9f1e16aa, 0x894ac375, 0x491b0aa4, 0x0edf1e82, 0x0108c93e, 0x0ecf623a, 0x47d4689e, 0x31af2db0, 0x6ff8474d, 0x54a92895, 0x3f703332, 0x94f8e144, 0xa44f7972, 0x6bc9671f, 0x188bcb5d, 0x0bf68b56, 0xd33cf562 +}, +{ +0x9d8c2ca9, 0x00000000, 0xbcdb08cf, 0x074f33b0, 0xd9f942b4, 0x8ff32069, 0xac84a5ca, 0x1a88197d, 0xf536e11a, 0x9ac31f19, 0x7c22c5fb, 0xf279d2aa, 0x98e3bedc, 0xf6be77e7, 0x13d73bf8, 0xe8f1cbd7, 0xc0f9cd34, 0x20ff135e, 0x8b348524, 0xee16cf5f, 0xbefba90a, 0xe959fcef, 0x16b8a98d, 0xf059736f, 0x9014ab61, 0x775d46bb, 0xead16a12, 0x37ef8deb, 0x40b2cb50, 0x0fb8260d, 0xb81cad82, 0xf49ed622, 0xb1438f07, 0x29a031db, 0x91bc9c59, 0x18a8b8b8, 0x42926a95, 0xc5965f41, 0xaf0c3337, 0xba3c0c47, 0x2a28a726, 0x4d2a4c98, 0x44756e1d, 0x85249411, 0x939c3d9c, 0xb9b49aba, 0x83c39099, 0x01a83738, 0x6702ebbe, 0x7faa5306, 0x826ba7a1, 0x8c7bb694, 0x7012750b, 0x34671b16, 0x237785a3, 0x06e70488, 0x27b020ee, 0x1fe78b08, 0x78e560b6, 0xfdc1f4a7, 0x604dd80e, 0xb0ebb83f, 0x21572466, 0x280806e3, 0x3857abe6, 0x63c54ef3, 0xbb943b7f, 0x4c827ba0, 0x96f3afe9, 0xe2267faf, 0xc61ec9bc, 0x57a255e5, 0xabcb967a, 0xa11c2202, 0x68bacdb3, 0xb42c1d72, 0x8dd381ac, 0x2d679496, 0x5a3ad22d, 0x9fac8d6c, 0xc3715bc9, 0xf90651ea, 0x08f715bd, 0x1c6f1df5, 0x59b244d0, 0x261817d6, 0xc2d96cf1, 0x891424e1, 0xeb795d2a, 0xf8ae66d2, 0x30a0be5b, 0x1b202e45, 0xc9a6efb1, 0x4f0aed5d, 0x47fdf8e0, 0xb3632ec2, 0xa294b4ff, 0x35cf2c2e, 0x4655cfd8, 0xe4c17b27, 0x648a7d43, 0xd461c57c, 0x5efd7760, 0xdf1e463c, 0x88bc13d9, 0xa473b077, 0x1e4fbc30, 0xcb864e74, 0xe6e1dae2, 0xa0b4153a, 0xd10e5709, 0x66aadc86, 0xe1aee952, 0x8a9cb21c, 0x9c241b91, 0x74d5d046, 0xb7a48b8f, 0x5d75e19d, 0x0e101135, 0xe006de6a, 0xa65311b2, 0x433a5dad, 0x6a9a6c76, 0xffe15562, 0xd5c9f244, 0x2b80901e, 0x52cdc790, 0x0220a1c5, 0xc80ed889, 0x6b325b4e, 0x3eb0af6e, 0x32801f9e, 0x2590812b, 0x6dd55fc6, 0x2f473553, 0xf71640df, 0x5145516d, 0xe38e4897, 0xcf41eb39, 0x038896fd, 0x804b0664, 0x0b7f8340, 0xbd733ff7, 0x5f554058, 0x3f189856, 0xcee9dc01, 0xec366e9a, 0x7e02643e, 0x76f57183, 0x5b92e515, 0x45dd5925, 0x3bdf3d1b, 0x14980848, 0xd64164b9, 0x86ac02ec, 0x49ede9d5, 0x65224a7b, 0x5582f420, 0xb5842a4a, 0xd851758c, 0x0ad7b478, 0x4a657f28, 0x8e5b1751, 0x9e04ba54, 0xed9e59a2, 0x3647bad3, 0x6c7d68fe, 0xaa63a142, 0x15303f70, 0x105fad05, 0x4bcd4810, 0x19008f80, 0xfa8ec717, 0x4ea2da65, 0xccc97dc4, 0xbf539e32, 0x31088963, 0x7b6df64b, 0x4845deed, 0xa7fb268a, 0x411afc68, 0x81e3315c, 0x626d79cb, 0xdd3ee7f9, 0x794d578e, 0x6ff5fe03, 0x2438b613, 0x542ac318, 0x994b89e4, 0xc43e6879, 0xfc69c39f, 0xa8430087, 0xb60cbcb7, 0x3c900eab, 0x94d30e2c, 0x332828a6, 0x7ac5c173, 0xa5db874f, 0xdbd9e371, 0x056f9275, 0xe5694c1f, 0x61e5ef36, 0xb2cb19fa, 0xd286c1f4, 0x7d8af2c3, 0xf1f14457, 0x0d9887c8, 0xa9eb37bf, 0xad2c92f2, 0x2eef026b, 0x3a770a23, 0x870435d4, 0xca2e794c, 0xcd614afc, 0x6e5dc93b, 0x3d383993, 0x11f79a3d, 0x17109eb5, 0x757de77e, 0x6912fa8b, 0x1dc72acd, 0xefbef867, 0x22dfb29b, 0xd7e95381, 0x39ff9cde, 0xd0a66031, 0x5365f0a8, 0x5cddd6a5, 0x50ed6655, 0x0c30b0f0, 0x581a73e8, 0xaea4040f, 0x560a62dd, 0x7232d4ce, 0xd32ef6cc, 0x095f2285, 0xdeb67104, 0x9b6b2821, 0xf3d1e592, 0xe749edda, 0xc151fa0c, 0xda71d449, 0x04c7a54d, 0x975b98d1, 0x127f0cc0, 0xfe49625a, 0xfb26f02f, 0xc7b6fe84, 0x2ccfa3ae, 0x848ca329, 0xa33c83c7, 0x92340aa4, 0xdc96d0c1, 0x739ae3f6, 0x71ba4233, 0x957b3914 +}, +{ +0x837e5e52, 0x77d48ed2, 0x62247e34, 0xe15a2066, 0xbbabf79d, 0xdaca3205, 0x1d6b2648, 0x14632e24, 0xe8e2054d, 0xb3800c74, 0x4fb10a5a, 0xc682e7c8, 0xce193166, 0xac3d4f52, 0x968eaeb4, 0x94e8e69d, 0xad1ebcd7, 0xc7a1144d, 0x3a03cca1, 0x76f77d57, 0x02664829, 0x61d1e8df, 0x82ed8090, 0xfee76340, 0x9cc31d74, 0x2e60e285, 0x3946770d, 0xe2afb68d, 0x8933ed92, 0x38658488, 0xb0c5b7d8, 0x2f431100, 0x8983c0d5, 0xd8ac7a2c, 0xafc8d9b9, 0xff74bd82, 0xa7530f17, 0xd1a47240, 0x38d5a9cf, 0xfc812b69, 0x62945373, 0xffc490c5, 0x1605660d, 0x7edc86be, 0xa4a699fc, 0x089bd6ae, 0x02d6656e, 0x46b90236, 0x7491357e, 0xd251e4ab, 0xb213d2b6, 0x60f21b5a, 0x7e6cabf9, 0xc632ca8f, 0x2768eae9, 0xbb1bdada, 0x304e7f61, 0x81a83b3c, 0x3b901263, 0x03f596eb, 0xe9c1f6c8, 0x83ce7315, 0x31dda1a3, 0x1ddb0b0f, 0x32981a0f, 0x17269588, 0xc45482a6, 0x7f4f587c, 0x7d993d12, 0x446f6758, 0x7d291055, 0xfc31062e, 0x6b9c5b1f, 0xac8d6215, 0x4d676f34, 0x16b54b4a, 0xeb1793a6, 0x808bc8b9, 0x264b196c, 0x53f9df97, 0xc711390a, 0xb85e6176, 0x75b2c6fb, 0xf75f466b, 0x694a3e71, 0x242d5145, 0x8a76563e, 0x30fe5226, 0x95cb1518, 0x1c48d5cd, 0xdb59ecc7, 0xcdeca78d, 0xa416b4bb, 0x6161c598, 0xa535473e, 0x44df4a1f, 0x69fa1336, 0x00000000, 0xcccf5408, 0x63078db1, 0x249d7c02, 0x8be588fc, 0x0193dec2, 0x500c497c, 0x7fff753b, 0x0afd9e87, 0xc4e4afe1, 0x1cf8f88a, 0x25be8f87, 0x0345bbac, 0xb1e6445d, 0x4cf4b1f6, 0x082bfbe9, 0xf6cc98a9, 0x9458cbda, 0x7c0ae3d0, 0xe38c4508, 0x1f0d6e61, 0xfda2d8ec, 0x33bbe98a, 0x97ad5d31, 0x0a4db3c0, 0x63b7a0f6, 0x58979fd2, 0x52da2c12, 0xd1145f07, 0xd372172e, 0x2c06aaac, 0xda7a1f42, 0xc5777123, 0xe33c684f, 0x32283748, 0x9f86a6d8, 0xadae9190, 0x2d95746e, 0x2ed0cfc2, 0xaf78f4fe, 0x46092f71, 0xb9cdbfb4, 0xe1ea0d21, 0x479af1b3, 0x59044110, 0x4f01271d, 0x9de0eef1, 0x5bd2247e, 0x5827b295, 0x1fbd4326, 0xf4aad080, 0xe21f9bca, 0xb156691a, 0xfd12f5ab, 0x6b2c7658, 0x5b620939, 0x454c94dd, 0xd08781c5, 0xb8ee4c31, 0x68d9e0b3, 0x15f0f0e6, 0x3ab3e1e6, 0xdbe9c180, 0x519f97be, 0x963e83f3, 0x88101e17, 0x472adcf4, 0xf41afdc7, 0xe079d3e3, 0x0bde6d02, 0x4c449cb1, 0xb2a3fff1, 0xf7ef6b2c, 0x4e22d498, 0xea346023, 0x971d7076, 0x6042361d, 0xfe574e07, 0x4dd74273, 0x526a0155, 0x74211839, 0xa6c0d1d5, 0x39f65a4a, 0x957b385f, 0xf67cb5ee, 0x26fb342b, 0xc5c75c64, 0x9ea5555d, 0xae5b077b, 0x250ea2c0, 0x45fcb99a, 0x330bc4cd, 0x2ff33c47, 0xd98f89a9, 0xa670fc92, 0x9d50c3b6, 0xcf8aefa4, 0xd81c576b, 0x1540dda1, 0x00b02d47, 0x0b6e4045, 0x09b8252b, 0x316d8ce4, 0x8118167b, 0xcd5c8aca, 0x9c733033, 0x2cb687eb, 0xaeeb2a3c, 0xd037ac82, 0xa5856a79, 0xb0759a9f, 0x6869cdf4, 0xa7e32250, 0xe0c9fea4, 0xcf3ac2e3, 0x0123f385, 0x0908086c, 0x8b55a5bb, 0x3b203f24, 0x88a03350, 0x7502ebbc, 0xe971db8f, 0x803be5fe, 0x76475010, 0x1796b8cf, 0x9e15781a, 0x1e2e9de4, 0xba38295f, 0x6abfa89a, 0xb97d92f3, 0x14d30363, 0xba880418, 0x5a41fabc, 0x27d8c7ae, 0x50bc643b, 0xcc7f794f, 0x825dadd7, 0xd93fa4ee, 0x7cbace97, 0x5af1d7fb, 0xcea91c21, 0x9f368b9f, 0x4e92f9df, 0xea844d64, 0x8ac67b79, 0x5349f2d0, 0xeba7bee1, 0x59b46c57, 0x512fbaf9, 0x1e9eb0a3, 0xf5390e42, 0xd2e1c9ec, 0xf5892305, 0x6a0f85dd, 0xb3302133, 0xe852280a, 0xd3c23a69, 0x2d255929, 0x7764a395 +}, +{ +0x2faec7a6, 0xaeb927e3, 0x94b46e0e, 0xee65c6ea, 0x08765b76, 0x8b2bfa3b, 0x9a1ed342, 0x0eaabd4c, 0xa482b4e9, 0xd8887343, 0x444a463b, 0x2103f39e, 0x3a0d49ed, 0xbb1d20dc, 0x8961bb33, 0x1944fb7b, 0x8fbd5d09, 0x21047aea, 0xcd2c747c, 0xf56cf5ed, 0x6be308e9, 0xaa2809a5, 0x57352e4a, 0xcf61bc00, 0x835da14d, 0x6f7226af, 0x7ad1a8e4, 0xa259dba7, 0x557f6f42, 0xa6cf7c95, 0xc55da67e, 0xeaf361d8, 0x17ee4637, 0x46000733, 0x6be4819d, 0x5bd5d20e, 0x27df15a4, 0xa01413db, 0x6549b5a5, 0xde531c0d, 0x1dd25c49, 0x2de486ae, 0x763154a0, 0x00000000, 0x8fbad47d, 0xe61414e8, 0x599f9306, 0xdac5bb3f, 0x9e887470, 0x5f44fc48, 0x2fa94ed2, 0xe8b920d0, 0x85814777, 0xe0cf7ba6, 0xb7fddc98, 0x67047dd9, 0x4296a001, 0x06db6f4e, 0x0a3c1a7e, 0xe0c8f2d2, 0x34a7f4a1, 0x789c6098, 0x234e3be2, 0x2b3fe9e0, 0x7e470fd6, 0xf56b7c99, 0xf7213d91, 0xc55a2f0a, 0x137f6871, 0xf1fa52df, 0x4c3b9439, 0x5d093434, 0x1132a00d, 0x72a7f392, 0x6395539f, 0x61d89be3, 0xc9bad34e, 0xff50ef93, 0xcf663574, 0x00078974, 0x2349b296, 0x1f981d41, 0xfbc648a1, 0x024a4108, 0x1b093307, 0x3e9c67ab, 0x8b2c734f, 0x1f9f9435, 0xfd1aae9b, 0x5d0ebd40, 0x61df1297, 0xc9bd5a3a, 0xec2f87e2, 0xeaf4e8ac, 0xe2853aae, 0x7c0d4ede, 0x1dd5d53d, 0x5732a73e, 0xa25e52d3, 0xd622ce0f, 0x51e9c870, 0x48ad330b, 0xe459dc94, 0xb950e8a0, 0x3036dae7, 0x654e3cd1, 0x38408191, 0xe282b3da, 0xacf366eb, 0x0871d202, 0x89663247, 0xd4688f07, 0x72a07ae6, 0x6d3feed3, 0x15a38e4b, 0x327c9bef, 0x9a195a36, 0x7ad62190, 0xcbf71b32, 0xd0f9a141, 0x4ae0fb77, 0x40db687d, 0xbf8b87ee, 0xb95761d4, 0x34a07dd5, 0x7c0ac7aa, 0xe45e55e0, 0x46078e47, 0x48aaba7f, 0x53a38978, 0x81106931, 0x92688834, 0xd88ffa37, 0xa865c1d9, 0x0ce0fc44, 0x5bd25b7a, 0x51ee4104, 0xc386c930, 0x747c9cdc, 0xc3814044, 0x8586ce03, 0x2975a8e8, 0xb36cf2de, 0xd46f0673, 0x789be9ec, 0xbdc64f92, 0x0496a732, 0x30315393, 0xaa2f80d1, 0x17e9cf43, 0xee624f9e, 0x926f0140, 0xfd1d27ef, 0x70edb29a, 0xf98b80dd, 0x3a0ac099, 0x69a949e1, 0xc1cc8838, 0x3cd626a3, 0x36ea3cdd, 0x6d3867a7, 0xb5b79d90, 0xaebeae97, 0x5f43753c, 0x96f9a672, 0x42912975, 0xbdc1c6e6, 0xff5766e7, 0x9e8ffd04, 0x4c3c1d4d, 0x40dce109, 0xa86248ad, 0x87cc8f0b, 0x5578e636, 0xf3b013d7, 0x0ead3438, 0x1b0eba73, 0x7636ddd4, 0x0a3b930a, 0x3e9beedf, 0xdc195d05, 0xd2b4693d, 0x444dcf4f, 0x36edb5a9, 0x384708e5, 0x2972219c, 0x15a4073f, 0xe6139d9c, 0xa4853d9d, 0x8df71c01, 0x6392daeb, 0xdac2324b, 0x2de30fda, 0xc1cb014c, 0x835a2839, 0xfbc1c1d5, 0xcd2bfd08, 0xc7106e02, 0x747b15a8, 0xd0fe2835, 0x9022c93c, 0xf726b4e5, 0xb36b7baa, 0x9854924a, 0x6f75afdb, 0xb126b3d6, 0x259554ac, 0xd2b3e049, 0xe8bea9a4, 0x11352979, 0x327b129b, 0x2592ddd8, 0x4e765c45, 0x3cd1afd7, 0x4ae77203, 0x70ea3bee, 0x98531b3e, 0x024dc87c, 0x8117e045, 0xec280e96, 0x87cb067f, 0x27d89cd0, 0xacf4ef9f, 0x94b3e77a, 0xf1fddbab, 0xa6c8f5e1, 0xf98c09a9, 0xdc1ed471, 0x59981a72, 0x9cc23578, 0x9cc5bc0c, 0xf3b79aa3, 0xb7fa55ec, 0xc717e776, 0x69aec095, 0xa0139aaf, 0x6703f4ad, 0x1378e105, 0xb1213aa2, 0x4e71d531, 0xd625477b, 0x96fe2f06, 0x1943720f, 0xbf8c0e9a, 0xde549579, 0xb5b014e4, 0xcbf09246, 0x8df09575, 0x06dce63a, 0x90254048, 0x04912e46, 0x0ce77530, 0xbb1aa9a8, 0x2b386094, 0x7e4086a2, 0x53a4000c +}, +{ +0xc138d4c2, 0xbc965f90, 0x15806975, 0x511a0abd, 0x027b34cb, 0x3f25bc6a, 0x5cc1d440, 0xcebbe209, 0x6e3fb6d7, 0x34ef3667, 0x96105672, 0x570b5e4d, 0x5ad080b0, 0x79e73794, 0x18786b75, 0x4f50e9c5, 0x5553b67b, 0x4d2bdd0e, 0x3b4fdc51, 0xd940bfb7, 0x2337b724, 0xed8c552d, 0xc11b083f, 0x2ecfb524, 0xad7c56de, 0x55706a86, 0x09b1bec6, 0x682ee227, 0xd0f10171, 0x40f003f3, 0x63c7b4d7, 0x2c975d12, 0x999360b9, 0x4b3a89fe, 0x707555af, 0xfc45809e, 0x81eb0bcc, 0x00000000, 0x885ab50a, 0x8e4be1fa, 0x3d5e88a1, 0x7ff66364, 0x9ddadc7f, 0x680d3eda, 0x1a035fbe, 0x0fa0ea36, 0x887969f7, 0x9448be44, 0xbaa4d79d, 0x3f066097, 0x216f5f12, 0xa6b6dcd3, 0x0023dcfd, 0x5ebae08b, 0xa08454de, 0xb14d816d, 0xf3c6b655, 0xb8dfe356, 0x63e4682a, 0x4d0801f3, 0x0bca8a0d, 0xdb185781, 0x5af35c4d, 0x28dee1d4, 0x46c28bfe, 0x13b2e178, 0xe43debeb, 0x40d3df0e, 0x9fa1e8b4, 0x1a208343, 0x2a8609e2, 0xb527e156, 0x87d983c1, 0xad5f8a23, 0xaf076215, 0x743ce969, 0xc5716804, 0x46e15703, 0x17fb5dbe, 0x5342e28b, 0xdb3b8b7c, 0x81c8d731, 0xefd4bd1b, 0x5e993c76, 0x0992623b, 0xf78f0a93, 0xd6e05581, 0xbeed6b5b, 0x44b9bf35, 0x0ddbdefd, 0x39173467, 0x32fe6297, 0x741f3594, 0x96338a8f, 0xa91636e5, 0x1e693f85, 0xd28a35ba, 0x6c675ee1, 0xd963634a, 0x85a2b70a, 0x90010282, 0xc8896a04, 0x061154f0, 0x2eec69d9, 0x79c4eb69, 0xd49b614a, 0x0f8336cb, 0xb315695b, 0xfe3eb455, 0xfa54d46e, 0x9be85472, 0xbeceb7a6, 0x6a760a11, 0x87fa5f3c, 0x32ddbe6a, 0x927a3649, 0x65d6e027, 0xc7298032, 0x369402ac, 0x25053f29, 0x61bc801c, 0x4b195503, 0x7d8d57af, 0x3085565c, 0x0df80200, 0x9022de7f, 0xa695002e, 0xab4eded3, 0xd4b8bdb7, 0x7fd5bf99, 0x70568952, 0xa935ea18, 0x046a603b, 0xf7acd66e, 0x1c31d7b3, 0xe41e3716, 0xa2dcbce8, 0x1c120b4e, 0xdd090371, 0xedaf89d0, 0x449a63c8, 0xf82fe0a5, 0xa0a78823, 0x99b0bc44, 0xa4cde818, 0xa4ee34e5, 0x9f823449, 0x722dbd99, 0xf19e5e63, 0x0632880d, 0xc552b4f9, 0x23146bd9, 0x6a55d6ec, 0xeb9d01dd, 0x7b9c035f, 0x9bcb888f, 0x34ccea9a, 0x15a3b588, 0xb5043dab, 0xe0578bd0, 0xe20f63e6, 0x275dd71f, 0xe66503dd, 0x28fd3d29, 0x36b7de51, 0xfe1d68a8, 0x4941bd35, 0x946b62b9, 0xf3e56aa8, 0x53613e76, 0xdf51eb47, 0xb336b5a6, 0x5ce208bd, 0x3b6c00ac, 0xb8fc3fab, 0x65f53cda, 0x8c1309cc, 0x58886886, 0x4f733538, 0xf5f43e58, 0x1e4ae378, 0xeff761e6, 0x83b3e3fa, 0xba870b60, 0x11c9d5b3, 0xb75cd59d, 0xe9c5e9eb, 0xce983ef4, 0x13913d85, 0x214c83ef, 0x2aa5d51f, 0x9259eab4, 0x0be956f0, 0xdd2adf8c, 0x3d7d545c, 0x428b3738, 0xc70a5ccf, 0xf80c3c58, 0x6e1c6a2a, 0xd6c3897c, 0x17d88143, 0x58abb47b, 0xc343e009, 0xd0d2dd8c, 0xd2a9e947, 0x67add4ec, 0x9df90082, 0x619f5ce1, 0xcad18232, 0x496261c8, 0xf5d7e2a5, 0x8e683d07, 0x572882b0, 0xfc665c63, 0xebbedd20, 0x85816bf7, 0x2526e3d4, 0x30a68aa1, 0x0258e836, 0xb77f0960, 0x83903f07, 0x185bb788, 0xc8aab6f9, 0x3934e89a, 0x5139d640, 0x11ea094e, 0xab6d022e, 0xbcb5836d, 0x8c30d531, 0x7bbfdfa2, 0xe074572d, 0xc3603cf4, 0xdf7237ba, 0xf1bd829e, 0x8a2181c1, 0xccc0d6c2, 0xe22cbf1b, 0xfa770893, 0x678e0811, 0xcaf25ecf, 0x0449bcc6, 0x8a025d3c, 0x42a8ebc5, 0x2cb481ef, 0x277e0be2, 0xb16e5d90, 0xa2ff6015, 0x7dae8b52, 0x720e6164, 0xe646df20, 0x6c44821c, 0x7647dda2, 0xaf24bee8, 0x7664015f, 0xe9e63516, 0xcce30a3f +}, +{ +0xb5a25747, 0x6aa0467e, 0xd90b249c, 0xf6d7e0dc, 0xf8efc137, 0x1bf65ef2, 0x3c22acc1, 0x001d6a97, 0x8195a762, 0x9c53ee08, 0x9c4e849f, 0xa8405687, 0x15d3158e, 0x8980fb86, 0x56a6a215, 0x2ff88cea, 0xc4cd6df6, 0x1dc6496a, 0xb59b757a, 0x795e2eff, 0xf6eec2e1, 0x5eae9466, 0xb3b60875, 0xb5861fed, 0x3c1b8efc, 0x79670cc2, 0xbd934309, 0x21ddc796, 0x3c06e46b, 0xf8d6e30a, 0xe304f552, 0xcad104b7, 0x00000000, 0x4545a003, 0xe510aa60, 0x8f94a4b4, 0x9c6acc35, 0xed05f684, 0xa65c3fc6, 0x29ecd3d8, 0xa0550a63, 0xc2e010f9, 0x27f0ba99, 0xed3cd4b9, 0xeb11a9b6, 0xdf021139, 0x81ac855f, 0x8f89ce23, 0x9c77a6a2, 0x62a8700d, 0x321a8d2a, 0x508bdf1a, 0xd70a274a, 0xf0c3bfee, 0x58a7a1c3, 0x15ce7f19, 0xbbbe3e06, 0xa07142c9, 0xdf1f7bae, 0xfefb9e05, 0x9a63f990, 0x64a145a8, 0x9446b2ec, 0x4375b79b, 0xa04860f4, 0xe529885d, 0x323ec580, 0xd7174ddd, 0x0831144e, 0x3437f025, 0x5eb3fef1, 0x0e1c6941, 0x569f8028, 0x797a6655, 0x342a9ab2, 0x6abd2ce9, 0x9a7e9307, 0x4d69deda, 0x4b60eb7f, 0x9276a574, 0x062d7d0f, 0xa87974ba, 0x924f8749, 0x13e30216, 0x27edd00e, 0xd9164e0b, 0xfedfd6af, 0xccc55b85, 0x4d50fce7, 0x29c89b72, 0xc2c45853, 0xf8f2aba0, 0xcaf54c1d, 0x5e97b65b, 0x7f571b5a, 0xbd8e299e, 0xd1275a45, 0x457c823e, 0xd7330577, 0x6a840ed4, 0x8188cdf5, 0x13c74abc, 0x27c998a4, 0xd11e7878, 0xccd83112, 0xccfc79b8, 0xf0e7f744, 0x87a5b0fa, 0x79434468, 0xe33dd76f, 0x3a12bb59, 0xc2fd7a6e, 0x71725026, 0x4b59c942, 0x15ea37b3, 0x7f7353f0, 0x2fc1aed7, 0xeb0cc321, 0x2fdcc440, 0x1dff6b57, 0x27d4f233, 0xa85d3c10, 0xf0fa9dd3, 0x3a0fd1ce, 0xfec2bc38, 0x4b7d81e8, 0x15f75d24, 0x81b1efc8, 0x64850d02, 0x002448aa, 0x6cb4194c, 0xcacc6e20, 0x89b9d9bb, 0x1beb3465, 0x9a5adbad, 0x4b44a3d5, 0xa678776c, 0x3c3fc656, 0x8fad8689, 0x3223af17, 0xa8641e2d, 0x5883e969, 0xa6651dfb, 0xd13a30d2, 0x082c7ed9, 0x6ca973db, 0x7f6e3967, 0x1bd21658, 0x50af97b0, 0x3207e7bd, 0x21e4e5ab, 0x8781f850, 0x62b51a9a, 0x777b6583, 0x0e3821eb, 0x5096b58d, 0xae496322, 0x89a4b32c, 0xe50dc0f7, 0xeb35e11c, 0xae5409b5, 0x1ddb23fd, 0x4558ca94, 0xf6ca8a4b, 0x1de201c0, 0x06301798, 0xbdb70ba3, 0x06145f32, 0xd72e6fe0, 0x947f90d1, 0x29f1b94f, 0xf8cb899d, 0x5682eabf, 0x060935a5, 0x58bacb54, 0xd93206a1, 0xae6d2b88, 0xa06c285e, 0x926bcfe3, 0x4d4d9670, 0x945bd87b, 0xed189c13, 0x6c8d3b71, 0xfee6f492, 0x77660f14, 0x6a996443, 0x4d74b44d, 0xb5bf3dd0, 0x589e83fe, 0x62915230, 0xbba35491, 0xa6415551, 0xc4d00761, 0x13da202b, 0x714b721b, 0xeb288b8b, 0xb39240df, 0xc2d932c4, 0x56bbc882, 0xbdaa6134, 0x21f98f3c, 0x716f3ab1, 0x29d5f1e5, 0xed21be2e, 0xf6f3a876, 0x08155ce4, 0x1bcf7ccf, 0x7156188c, 0xc4f44fcb, 0x340ed218, 0x4561e8a9, 0xcce1132f, 0x9462fa46, 0xd92f6c36, 0x87b8da6d, 0x0e254b7c, 0xcae8268a, 0x2fe5e67d, 0xdf265993, 0xb38f2a48, 0x775f2d29, 0x774247be, 0x3a36f3f3, 0x08083673, 0x899d9111, 0x8fb0ec1e, 0x13fe6881, 0x6c9051e6, 0x0039223d, 0x5e8adccc, 0x9a47b13a, 0x9252edde, 0xae70411f, 0x64986795, 0xbb871c3b, 0x4351ff31, 0x0e0103d6, 0xbb9a76ac, 0xb3ab62e2, 0xe534e2ca, 0x50b2fd27, 0x7f4a71cd, 0xe3199fc5, 0x3a2b9964, 0x879c92c7, 0x628c38a7, 0xdf3b3304, 0x3413b88f, 0x4368dd0c, 0xf0ded579, 0xd10312ef, 0xc4e9255c, 0x64bc2f3f, 0x434c95a6, 0x21c0ad01, 0xe320bdf8 +}, +{ +0x096c9650, 0x2ada7e92, 0x9afe62f8, 0x713e46a9, 0xedcff22f, 0xe8471cd4, 0x1d6354be, 0x0588eefb, 0xd7e4ca4f, 0xf0aca691, 0xa352621d, 0x4b157ec9, 0x94eb4831, 0xb152768d, 0x7647fa30, 0x16fe908c, 0x38da6a02, 0xf9c030c1, 0x3347ae30, 0x27486cde, 0x39ac00e5, 0x8b794eed, 0xb0241c6a, 0x879d3646, 0xa6da8ce6, 0x75c0c2b5, 0xac312233, 0x25b93ebc, 0x36cf40cb, 0x88fe7668, 0x8215d8bd, 0xd09d76d6, 0x1f9206dc, 0x74b6a852, 0x9e00e6e4, 0xa7ace601, 0xc492b438, 0x7852d0f9, 0xbdb60e26, 0xfd3eb4dd, 0x92e49e4f, 0xffcfe6bf, 0xdffe36f8, 0x7cac54e5, 0x3ed5bc7c, 0x2e24fa8e, 0x1c153e59, 0x30c096b5, 0xa9b9ccc8, 0xa1a3307f, 0x4c6cc250, 0xe652361d, 0x1788fa6b, 0x8a0f240a, 0x45005400, 0x1ee46c3b, 0xf25df4f3, 0x57004090, 0xdd0f649a, 0x3231c4d7, 0xdb00b2e4, 0x773190d7, 0xfa470844, 0xab489eaa, 0xc7158cbd, 0xe5d50e98, 0x6d2b78f0, 0x3d5284f9, 0xc29d6246, 0x6b24ae8e, 0x0aebaed5, 0x54877815, 0xbf475c44, 0x856c6424, 0xde885c1f, 0xcdfe2268, 0xf6a370ef, 0x4e9d9032, 0x7bd5e87c, 0x13767e77, 0x73cf14cb, 0x263e0639, 0xa22408fa, 0xecb998c8, 0xc3eb08a1, 0x3a2b3860, 0xaa3ef44d, 0x68a3960b, 0xb5acf291, 0x80e48adf, 0xebc02451, 0xa42bde84, 0x9015cc2d, 0x66b6bcc2, 0x0e152ac9, 0xf32b9e14, 0x6447eea0, 0xfc48de3a, 0xda76d803, 0x7aa3829b, 0xcc88488f, 0xb4da9876, 0x00000000, 0x343e12a9, 0xb2d54e08, 0x510f96ee, 0x03873885, 0x5e6cd6c0, 0xd692a0a8, 0xb3a324ef, 0xf8b65a26, 0x1a1ae827, 0x70482c4e, 0x3b5d5287, 0x0d92124c, 0x12001490, 0xc11a5ac3, 0x0f63402e, 0x3fa3d69b, 0x0779bc99, 0xa55db463, 0x61cf005b, 0x46876c85, 0x9b88081f, 0xbbb9d858, 0x140fc2ee, 0x2031d047, 0xd463f2ca, 0x5a9252dc, 0x59156a59, 0x5f1abc27, 0xd31a4e53, 0x8c00f274, 0xca879ef1, 0x4febfad5, 0x4279e899, 0xf452228d, 0x69d5fcec, 0x47f10662, 0xb62bca14, 0x3548784e, 0x56762a77, 0x4a63142e, 0xa0d55a98, 0xcbf1f416, 0xe3dad8e6, 0x89881c8f, 0xee48caaa, 0x18ebba45, 0xd515982d, 0x633e5239, 0xb83ee0dd, 0xbe3136a3, 0x53fec48c, 0xf524486a, 0x10f146f2, 0x72b97e2c, 0xbacfb2bf, 0x49e42cab, 0x60b96abc, 0x6a52c469, 0xdc790e7d, 0xc900a674, 0xc06c3024, 0x6eac4075, 0x01766ae7, 0x282b2cf0, 0x980f309a, 0x961a1a53, 0xe05de063, 0xcf0f700a, 0x0ce478ab, 0xe9317633, 0x4d1aa8b7, 0x1b6c82c0, 0x5288ae6b, 0x976c70b4, 0x5debee45, 0xe7245cfa, 0x2bac1475, 0x5079fc09, 0x5be4383b, 0xc663e65a, 0x430f827e, 0x8363b25a, 0x99795a7d, 0x7e5d0687, 0xa8cfa62f, 0x9163a6ca, 0x86eb5ca1, 0x841a0ec3, 0xf7d51a08, 0x8f87caf1, 0xfb3162a3, 0x04fe841c, 0xd8878a61, 0x2da3c20b, 0x65318447, 0xb75da0f3, 0x2cd5a8ec, 0xad4748d4, 0x586300be, 0x624838de, 0x5c9d84a2, 0x7dda3e02, 0x081afcb7, 0x4892464c, 0x22c08225, 0xafb61ab6, 0x02f15262, 0x23b6e8c2, 0x24cf545b, 0x6fda2a92, 0x11872c15, 0x7f2b6c60, 0xc876cc93, 0x295d4617, 0x2f529069, 0xd26c24b4, 0xe12b8a84, 0x060fd67e, 0xeab64eb6, 0xe2acb201, 0xd9f1e086, 0xbcc064c1, 0x7924ba1e, 0x44763ee7, 0x55f112f2, 0xd1eb1c31, 0x8ef1a016, 0x37b92a2c, 0x8d769893, 0x959d22d6, 0x0b9dc432, 0x9392f4a8, 0x9cf1b486, 0x199dd0a2, 0x41fed01c, 0x2147baa0, 0x6c5d1217, 0xe4a3647f, 0xf1dacc76, 0x4088bafb, 0x9f768c03, 0x1579a809, 0x67c0d625, 0xfeb98c58, 0x31b6fc52, 0xc5e4dedf, 0x8192e038, 0xb9488a3a, 0xce791aed, 0xaec07051, 0xef3ea04d, 0x3c24ee1e, 0x9d87de61 +}, +{ +0x433b1b9c, 0x6a7d7587, 0x16453b57, 0x29466e1b, 0x3abb2658, 0x4df8d7ed, 0x4ad83130, 0x9a6d392e, 0x4163fd17, 0xa5ae1f20, 0xab6dd351, 0x34b8996b, 0xa9f54698, 0x557e20cb, 0x1ade11ad, 0x70a3642a, 0x5006209d, 0x4f604224, 0x0720e6dd, 0x5c9d0a67, 0xf288d960, 0x6fc50693, 0xd0757b5c, 0xfc8b6653, 0xf9331547, 0xf5a83fbd, 0x75db647c, 0x98f5ace7, 0x33987fb6, 0x11a5aec8, 0xb3eb2477, 0xe4cde237, 0xb40bb1e8, 0xa0d61f76, 0xb6535763, 0xe40d9175, 0x0e03bf33, 0xb32b5735, 0xc110a6d6, 0x9116864b, 0x6106cae2, 0xc630400b, 0xb4cbc2aa, 0x6abd06c5, 0xd2edee95, 0xfc4b1511, 0x31c0993d, 0x2b1e8890, 0x96366096, 0xedeebbd9, 0x7b18a80d, 0xac8d46ce, 0x9aad4a6c, 0x029895c9, 0x41a38e55, 0x61c6b9a0, 0xba080edb, 0x09e32aac, 0xd50d7b0a, 0x82ebce08, 0x4d38a4af, 0xc468a680, 0x29861d59, 0x72fb82a1, 0x2785a26a, 0xbd28e806, 0x80735bc1, 0x7ea0db19, 0x0ec3cc71, 0xdb0ec439, 0x2ea6fb84, 0xdbceb77b, 0xc6f03349, 0x59e50a31, 0x1a1e62ef, 0x1dfef770, 0xae15d307, 0x44db8e03, 0x934e60c0, 0x8eb097b0, 0x850b5b97, 0xeace5d04, 0x206537f5, 0x07e0959f, 0x822bbd4a, 0x5e059fae, 0xb850e850, 0xe1b5e261, 0xcaab6af1, 0x0c5b59b8, 0x0bbbcc27, 0xefb65d52, 0x2e6688c6, 0x6d9de018, 0xd0b5081e, 0x2bdefbd2, 0x2c3e6e4d, 0x8ce8713b, 0x00000000, 0xe1759123, 0x141ddddc, 0x46836888, 0x1886f726, 0xb8909b12, 0x0b7bbf65, 0xbde89b44, 0xcd4bff6e, 0x2745d128, 0x1f6662b9, 0x57e6b502, 0xbac87d99, 0xfed380d8, 0x9d4ddff3, 0xa93535da, 0xc388331f, 0x3100ea7f, 0x38e3c0d3, 0x4840a4f9, 0xb173b1be, 0xbf700e8d, 0x25dd44e1, 0x2cfe1d0f, 0xcd8b8c2c, 0x133d3b01, 0x8950022f, 0x3d5bb3c7, 0xc1d0d594, 0xe856c8cd, 0x7e60a85b, 0xbfb07dcf, 0xfb6bf3cc, 0x4a184272, 0x751b173e, 0xcfd36aa7, 0x5c5d7925, 0x223dd17e, 0x43fb68de, 0x66e65f7d, 0xd22d9dd7, 0xa0166c34, 0xdeb6b72d, 0xa56e6c62, 0x635e2c69, 0x94aef55f, 0x3f03554c, 0xb1b3c2fc, 0x251d37a3, 0x9f153978, 0x1d3e8432, 0x4880d7bb, 0x5726c640, 0xf9f36605, 0x20a544b7, 0x8753bd1c, 0x68e5e04e, 0x9fd54a3a, 0x0c9b2afa, 0x4fa03166, 0x7c384ed0, 0xa7368ae9, 0x946e861d, 0xa28ef9fd, 0x55be5389, 0x529eb554, 0x1fa611fb, 0x8b08e4a4, 0x05780056, 0x3fc3260e, 0xc8f38c7a, 0xe32d77a8, 0x85cb28d5, 0xed2ec89b, 0x59257973, 0xf248aa22, 0x96f613d4, 0x13fd4843, 0xf5684cff, 0xd795eec3, 0xac4d358c, 0xe896bb8f, 0xfbab808e, 0x441bfd41, 0xc348405d, 0xef762e10, 0x6825930c, 0xfe13f39a, 0xe65577fe, 0x647ecab4, 0xd7559d81, 0xf0104ca9, 0x33580cf4, 0x3823b391, 0x7cf83d92, 0xb6932421, 0x36200ca2, 0xde76c46f, 0xc4a8d5c2, 0x778382f7, 0x8bc897e6, 0x00c07342, 0x8990716d, 0x9835dfa5, 0xca6b19b3, 0xd5cd0848, 0x1165dd8a, 0x6d5d935a, 0x8793ce5e, 0xe69504bc, 0x36e07fe0, 0x05b87314, 0x91d6f509, 0xa7f6f9ab, 0x092359ee, 0x18468464, 0x7743f1b5, 0x46431bca, 0x938e1382, 0x723bf1e3, 0xea0e2e46, 0xa24e8abf, 0xf730aa74, 0x64beb9f6, 0x80b32883, 0x50c653df, 0x3a7b551a, 0x66262c3f, 0x5bbdecba, 0xdcee51a6, 0x14ddae9e, 0x0258e68b, 0xd99651f0, 0xdc2e22e4, 0x9d8dacb1, 0xf0d03feb, 0x6f0575d1, 0x8c280279, 0xe3ed04ea, 0x22fda23c, 0x70631768, 0xd95622b2, 0x8e70e4f2, 0xaed5a045, 0x5ec5ecec, 0xc833ff38, 0x79803dc4, 0xf7f0d936, 0x525ec616, 0x639e5f2b, 0xabada013, 0x5b7d9ff8, 0x79404e86, 0x7bd8db4f, 0x16854815, 0xcf1319e5, 0x3d9bc085, 0x3478ea29 +}, +{ +0x4a8e7e65, 0x357631e2, 0x58157ef2, 0x15186afe, 0x157aa563, 0x94793e75, 0xd9fd4069, 0xb32f4ea1, 0xd924ce55, 0xb4ac24c8, 0x86597f43, 0x12f9cf0a, 0x5f1f7e8b, 0xde2ece2c, 0x94a0b049, 0x20b7d520, 0xeb081be2, 0x070a0079, 0x58ccf0ce, 0x07d38e45, 0x6d88ea9d, 0xa1866587, 0xb4176569, 0x206e5b1c, 0x782bc1c2, 0x07836a69, 0x07b141d8, 0x6d5164a1, 0x93c87fad, 0x4de6b181, 0x7f21c1bb, 0x27df1ac4, 0x6d01808d, 0x075ae455, 0x15488ed2, 0x86099b6f, 0x327c319b, 0xb3a624b1, 0x4a57f059, 0x00000000, 0x78f24ffe, 0x321efe06, 0x6ad20ec8, 0xa16dc00a, 0x07e1a5f4, 0x35441a53, 0x86e23ee2, 0xf9f1d4e8, 0x5877b16f, 0xa667c073, 0xa15febbb, 0x86b2dace, 0x12204136, 0x3514fe7f, 0x359d946f, 0xcc87e50a, 0xa655ebc2, 0x324e1a2a, 0xcb36a4d2, 0x78a2abd2, 0xa13d2426, 0x205c70ad, 0xa1d681ab, 0xeb6ad47f, 0x58459ade, 0x12428eab, 0x93989b81, 0xfec9ff20, 0xcc3ca4ab, 0x6d33ab3c, 0xa10f0f97, 0xb37faa8d, 0xde4c01b1, 0x00bb41a1, 0xfe10711c, 0x322cd5b7, 0x93733e0c, 0xd916e5e4, 0x35afbfde, 0xa6050fee, 0xcc0e8f1a, 0xf91a7165, 0xdef74010, 0x7fca6436, 0xfefbd491, 0xcce52a97, 0x4db655ad, 0xa68c65fe, 0x0768cfe4, 0x9323da20, 0x4a65dbe8, 0x200c9481, 0x5f96149b, 0xdec56ba1, 0x3526d5ce, 0xecb95a3a, 0x32979416, 0x27ed3175, 0xa6dc81d2, 0x6a39ab45, 0x81da152a, 0x941bf1e8, 0x58fedb7f, 0x203ebf30, 0xcc6c4087, 0xd9742a79, 0x152a414f, 0x270694f8, 0xccb5cebb, 0xf978bef8, 0xdea7a43c, 0x8680f17f, 0xa6be4e4f, 0x81039b16, 0xebe3be6f, 0xcb8de573, 0xcb048f63, 0x0050e42c, 0x12126a87, 0xd9cf6bd8, 0x78908063, 0x4ade9a49, 0x4a353fc4, 0xb3940f00, 0x93fa541c, 0xb3f6c09d, 0x159100ee, 0x6d634f10, 0x589c14e2, 0x6a0b80f4, 0x129b0097, 0x94f05465, 0x32a5bfa7, 0x6dd80eb1, 0x58275543, 0x9311f191, 0x6ab0c155, 0x15f3cf73, 0xfe409530, 0x07382bc8, 0x27bdd559, 0x20d51abd, 0x7ff84f87, 0x5f7db116, 0x94929bf8, 0x8161548b, 0x7f9a801a, 0x4a071475, 0x00322bb1, 0x818af106, 0x275670d4, 0xb4478145, 0xf94a9549, 0xf9285ad4, 0xde7e2a00, 0xa1b44e36, 0x58ae3f53, 0x0062cf9d, 0x27645b65, 0x7f13ea0a, 0xb4254ed8, 0x15c1e4c2, 0xec021b9b, 0xec30302a, 0x5ff4db06, 0x00d98e3c, 0xfe991b0c, 0xeb3a3053, 0x86d01553, 0xece9be16, 0xfeab30bd, 0xec8b718b, 0x4d3f3fbd, 0x278ffee8, 0x20e7310c, 0xde958f8d, 0xebb35a43, 0x7f712597, 0x5fc6f0b7, 0x78c0644f, 0xa637245f, 0x94c27fd4, 0xeb58ffce, 0xf9931b75, 0x4dd49a30, 0xa1e4aa1a, 0x2734bf49, 0xb4ceeb55, 0xf9a130c4, 0xb49e0f79, 0xcb546b4f, 0x6dea2500, 0x5f4f9aa7, 0xfe225aad, 0x944b15c4, 0x5f2d553a, 0xb3c4eb2c, 0xcb6640fe, 0xec52ffb7, 0x6ae02579, 0x81e83e9b, 0x4abc55d4, 0xa6eeaa63, 0x4d5df020, 0x4d6fdb91, 0x7fa8abab, 0x934115bd, 0xcbef2aee, 0x4aecb1f8, 0x863bb0de, 0xcc5e6b36, 0x6a694f69, 0x9429da59, 0x1270a51a, 0x8131b0a7, 0x32c7703a, 0xec60d406, 0x81537f3a, 0x35cd7043, 0x7f430e26, 0x15a32b5f, 0x32f55b8b, 0x93aab030, 0x6a82eae4, 0x866b54f2, 0x2085fe91, 0x00eba58d, 0x12a92b26, 0x35ff5bf2, 0xb475aaf4, 0x6a5b64d8, 0xccd70126, 0xeb8171f2, 0x4d847e1c, 0xb34d813c, 0x12cbe4bb, 0xfe72be81, 0xf9c3ff59, 0xd99f8ff4, 0xb31d6510, 0xcbbfcec2, 0x787b25ee, 0x6dbac12c, 0xde1ce59d, 0xcbdd015f, 0x4d0d140c, 0xd9ada445, 0x00896a10, 0x5fa43f2a, 0xd94601c8, 0xb4fcc0e4, 0x81b8dab7, 0x78490e5f, 0x7819ea73, 0xebd195de, 0xecdb95a7 +}, +{ +0xe3547553, 0xfea5cdd2, 0xe608b5e8, 0x6cd7e61d, 0x87971785, 0x4331e7dd, 0x9cfc119f, 0xcb7ec9d5, 0xc8b8b7f5, 0x07ccbd46, 0x73b62361, 0x8b895028, 0xf2bb8a7f, 0x040ac366, 0xea16f245, 0x619fa26d, 0xbcc229d2, 0xf6b14919, 0x1b6b061a, 0xf83f7349, 0xccb27493, 0xfff3ce0f, 0xa46f51e8, 0xa3a3ecae, 0xedda4f03, 0x2562f8f6, 0xdd5d8bbf, 0xac7bd523, 0x14b33f97, 0x60c9a1b0, 0x9e6c6c62, 0xc6368da5, 0x3e09feec, 0x4b256316, 0x00000000, 0x2becc2a6, 0x7c6e1aec, 0x2eb0021d, 0xd143cc12, 0x2c207fe0, 0x5512a5b7, 0x76eae3da, 0x15e53c4a, 0x6b1b5b5b, 0x297cbf5b, 0x081484cb, 0x069abe9b, 0x8adf53f5, 0xe5cecbc8, 0x82cbd73e, 0x92722bcf, 0x3dcf80cc, 0xca28ca08, 0xa9271598, 0xdbc73524, 0xd41f0ca9, 0xc9eeb428, 0xb646d0e4, 0x9daa1242, 0x0c1e47ad, 0x99a0d124, 0x18ad783a, 0xb8c8eab4, 0x5444a66a, 0xfc35b02f, 0x98f6d2f9, 0x56d4db97, 0x64c362d6, 0xe0920b73, 0x7ba2a7aa, 0x0bd2faeb, 0x95be9689, 0xd68f7154, 0x2fe601c0, 0xa8711645, 0xef4a32fe, 0x0a84f936, 0xaae16bb8, 0xfbf90d69, 0x630fdf90, 0xf02bf782, 0xd95748d9, 0x70705d41, 0x5d06217c, 0xafbdab03, 0x4a7360cb, 0x1623426a, 0xa065928e, 0x72e020bc, 0xdfcdf642, 0x39c543aa, 0x374b79fa, 0x9f3a6fbf, 0xaeeba8de, 0x7932da57, 0xf9697094, 0x810da91e, 0x752c9dfa, 0xabb76865, 0x71265e9c, 0x0fd8398d, 0xf17df45f, 0x3087c4bc, 0xc0ac333e, 0xcde4774e, 0x40f799fd, 0x09428716, 0x10b9fcf1, 0xb4d6ad19, 0x282abc86, 0xb580aec4, 0x4e79a3ad, 0xb0dc6e7f, 0x86c11458, 0xbe52542f, 0x504e650c, 0x1df1b881, 0xa2f5ef73, 0x5ec05f5c, 0x45ab5946, 0x8ed59093, 0xf7e74ac4, 0x4ce9de50, 0x44fd5a9b, 0xf3ed89a2, 0x6a4d5886, 0xec8c4cde, 0x49b51eeb, 0x466d2766, 0x23f8466d, 0x4dbfdd8d, 0x19fb7be7, 0xe202768e, 0x137f82d1, 0x3b553e57, 0x884f2e08, 0x11efff2c, 0xbf0457f2, 0x6595610b, 0xc4a6f058, 0x26a486d6, 0xe8868fb8, 0x1e37c6a1, 0xd3d3b1ef, 0xc5f0f385, 0xd285b232, 0x48e31d36, 0x055cc0bb, 0x7fa864cc, 0x590ce21a, 0x9b30acd9, 0xa6ff2c15, 0x6259dc4d, 0xc1fa30e3, 0x7efe6711, 0xd7d97289, 0x7d381931, 0x1f61c57c, 0x6e479be0, 0x7864d98a, 0x68dd257b, 0xbd942a0f, 0x2d767c3d, 0xbb0e9494, 0xf42134e4, 0x2abac17b, 0xe1c408ae, 0x3341ba9c, 0x6d81e5c0, 0x85076a78, 0xc23c4ec3, 0xc36a4d1e, 0x89192dd5, 0xb99ee969, 0xeb40f198, 0x698b26a6, 0xe9d08c65, 0x7af4a477, 0x77bce007, 0x4f2fa070, 0x1ca7bb5c, 0xf5773739, 0xda9136f9, 0x6f11983d, 0x203e384d, 0xa5395235, 0x94e89554, 0x361d7a27, 0xde9bf59f, 0x3f5ffd31, 0x90e25632, 0x67051cf6, 0xe498c815, 0x5c5022a1, 0x585ae1c7, 0x839dd4e3, 0xb18a6da2, 0xb710d339, 0xd5490f74, 0x31d1c761, 0x747a9e27, 0x35db0407, 0x3c998311, 0xfd63b3f2, 0x91b455ef, 0xa7a92fc8, 0xe75eb635, 0x1229810c, 0x3217b941, 0x53881b2c, 0x41a19a20, 0xcf740ab3, 0x03c67e20, 0x21683b90, 0x805baac3, 0xfaaf0eb4, 0x93242812, 0x9678e8a9, 0x3a033d8a, 0x473b24bb, 0xad2dd6fe, 0x511866d1, 0xce22096e, 0x8d13eeb3, 0x9a66af04, 0x5f965c81, 0x22ae45b0, 0x52de18f1, 0xa1339153, 0xb31a105f, 0x5aca9c3a, 0xba589749, 0xc7608e78, 0x015603dd, 0x348d07da, 0x0e8e3a50, 0x8f83934e, 0x27f2850b, 0x38934077, 0x845169a5, 0x5782d84a, 0xee1c3123, 0xd8014b04, 0xdc0b8862, 0xd015cfcf, 0x8c45ed6e, 0x1a3d05c7, 0x2434fb2b, 0xb24c1382, 0x02907dfd, 0x5b9c9fe7, 0x972eeb74, 0x66531f2b, 0x0d484470, 0x177541b7, 0x4267e400 +}, +{ +0xbf081c9c, 0x520c3889, 0x87f16dc0, 0x73a472bf, 0xca80d5eb, 0xf5354bd1, 0x988ced62, 0x4243dcf7, 0x5b12e79d, 0x8da951a1, 0xbb02108f, 0x5f18eb8e, 0x1c3b63d7, 0x062cbbc8, 0x7eb0a1b8, 0xd7dbe292, 0x450f3391, 0x6f9f1168, 0x80bd82a6, 0xb844f3fa, 0xad614f39, 0x5c5e08fb, 0x79fc4ede, 0x497bb438, 0xeb289fdd, 0xe63c4cda, 0xf941cc78, 0xee42c760, 0x00000000, 0x88c3091c, 0x25a24625, 0x4f570ff0, 0xe90e2806, 0x4e375b5e, 0x8691396e, 0xc79406ec, 0x1e1dd40c, 0x399925f2, 0xc6f45242, 0x7588c977, 0x81ddd608, 0xef2293ce, 0xfe0d231e, 0x056a58bd, 0x502a8f52, 0x6b951d7b, 0xf279a4b7, 0x96dedd10, 0xa80b1784, 0xec6470bb, 0xdbaf653b, 0x4d71b82b, 0x2ffa7a44, 0x446f673f, 0xb37c9b35, 0x6eff45c6, 0xe170a3bc, 0x90f266d8, 0xb15a2cee, 0xf713fc0a, 0x5d3e5c55, 0x32a14d3d, 0x3bbf9229, 0x2e9a2eea, 0xed042415, 0x4729844a, 0xf05f136c, 0x77ae7eac, 0x21a84a36, 0x99ecb9cc, 0x22eea943, 0xbd2eab47, 0xe23640c9, 0xb21ccf9b, 0x1525bcc3, 0xc4d2e599, 0xfa072f0d, 0x1f7d80a2, 0x074cef66, 0x9aaa5ab9, 0x61cd211a, 0x29d6c18c, 0x4a3d574d, 0xab4df4f1, 0x93b485ad, 0xcbe08145, 0xd5fd5549, 0xd49d01e7, 0xd8e9864e, 0x0b3868cf, 0xd6bbb63c, 0xf82198d6, 0x57666034, 0x2784f1fe, 0xf4551f7f, 0x6af549d5, 0x9fc00204, 0x40656b2c, 0xc2fe5e51, 0x31e7ae48, 0x4b5d03e3, 0xb616c388, 0x040a0c13, 0x16635fb6, 0x8eefb2d4, 0xccac6e23, 0x1a17d81f, 0x64a779a7, 0x0c7487a9, 0xc1b8bd24, 0xd3d1ee81, 0x536c6c27, 0x481be096, 0xe41afb01, 0xb03a7840, 0x7c961663, 0x74e89dd9, 0xce8ad9f8, 0x85d7da1b, 0xc5b2b137, 0x9bca0e17, 0x72c42611, 0x18316fc4, 0x97be89be, 0x5a72b333, 0x8ae5bec7, 0x26e4a550, 0xac011b97, 0x1445e86d, 0xa96b432a, 0x3d9329e1, 0x0e523072, 0x59345046, 0x9de6b5df, 0x1309070b, 0xaa2da05f, 0x70e291ca, 0x112fb0d0, 0x3ed5ca94, 0xb55020fd, 0x628bc26f, 0x0226b7db, 0x8b85ea69, 0xbc4effe9, 0x83fb61d3, 0x54208341, 0x4c11ec85, 0x94f86acb, 0x0346e375, 0x28b69522, 0x19513b6a, 0xb924a754, 0x33c11993, 0xfb677ba3, 0x9ea056aa, 0xa3337f4b, 0xcdcc3a8d, 0x9c86e171, 0x7fd0f516, 0xd989d2e0, 0x3adfc687, 0xb4307453, 0xd2b1ba2f, 0x1d5b3779, 0xf13f47c2, 0xae27ac4c, 0xcfea8d56, 0x20c81e98, 0x8f8fe67a, 0x89a35db2, 0xdacf3195, 0x8cc9050f, 0x6cd9f21d, 0x6681ce7c, 0x6db9a6b3, 0xc8a66230, 0x36ab412e, 0xe3561467, 0x5606349a, 0xa0759c3e, 0xa115c890, 0x4649d0e4, 0xe010f712, 0xd1f7595a, 0x43238859, 0x67e19ad2, 0x104fe47e, 0xe86e7ca8, 0x0a583c61, 0x585404e8, 0x91923276, 0x3087fae6, 0xa51fc483, 0xdce38a5d, 0x829b357d, 0xdec53d86, 0x84b78eb5, 0x7abaadab, 0x0f3264dc, 0x087e8bba, 0x7bdaf905, 0x5e78bf20, 0xc0d8e98a, 0x2a9022f9, 0x789c1a70, 0x35eda25b, 0x7182c564, 0xe57aafaf, 0x60ad75b4, 0x92d4d103, 0x091edf14, 0x7df642cd, 0x95983e65, 0xfd4bc06b, 0x65c72d09, 0x2bf07657, 0xaf47f8e2, 0xb7769726, 0xe75c1874, 0x24c2128b, 0x1b778cb1, 0x17030b18, 0xa47f902d, 0xc9c6369e, 0xf673a8a4, 0x016054ae, 0x126953a5, 0x348df6f5, 0x68d3fe0e, 0xba624421, 0x37cb1580, 0x514adbfc, 0xdfa56928, 0x63eb96c1, 0x238efded, 0x38f9715c, 0xff6d77b0, 0xdd83def3, 0xd0970df4, 0x3cf37d4f, 0x76ce2a02, 0xc39e0aff, 0x3fb59e3a, 0xa2532be5, 0x2ddccd9f, 0x0d14d307, 0x41053f82, 0xbe684832, 0xa65927f6, 0xf319f019, 0x2cbc9931, 0x69b3aaa0, 0xa7397358, 0xfc2b94c5, 0x5540d7ef, 0xea48cb73 +}, +{ +0x425481ac, 0x897ebff9, 0xb715be88, 0x85e0743e, 0x01d1b0e5, 0x1daa6cf9, 0x5e2f5db0, 0xe83ef4ce, 0xd80b1d74, 0x994e0f31, 0xdb1a8e9d, 0x3e6b0171, 0x1030b0c8, 0x428126bf, 0x3035e9ba, 0x50a41268, 0xf8dbe315, 0xeafed7c2, 0x72b4cf05, 0xcb2a3e55, 0xf44528d2, 0x7f2e1334, 0xdbcf298e, 0xf650accd, 0x3ebea662, 0x7cea27ce, 0x1c7bdc1c, 0xe5718fec, 0x1cae7b0f, 0x2210dd6d, 0x0d4f7b22, 0xba5ac5aa, 0x4350965a, 0x8a6f2c10, 0xd784455a, 0xfbca70fc, 0x7074ec09, 0xa9ae4198, 0xf9dff4e3, 0xd8deba67, 0xc8ee0aaf, 0x53b58181, 0x7dee3038, 0xc9ea1d59, 0x9a5f9cd8, 0x88af0f1c, 0x984a18c7, 0x5efafaa3, 0x2e5bb1b9, 0x00000000, 0x1e6e5803, 0x52643164, 0x32206da5, 0x51a0059e, 0x0f8f582e, 0xa5308a5f, 0xe4a03f09, 0x7c3f80dd, 0x5d3ece59, 0xb6c40e6d, 0x122534d7, 0x30e04ea9, 0xc5a1718d, 0x13f48432, 0x73657fe0, 0x6dde80f0, 0x94017413, 0x87f5f021, 0x10e517db, 0x6d0b27e3, 0x32f5cab6, 0xc93fba4a, 0xbb5ed25c, 0x4e1fed78, 0xa4e13aba, 0x5071b57b, 0x6ecf1319, 0x84e463c8, 0xe5a428ff, 0x6e1ab40a, 0x3d7a9298, 0xa7f0a953, 0x72616816, 0x4f1bfa8e, 0x9614f00c, 0xd495d6b3, 0xb94b5643, 0xda1e996b, 0x03c434fa, 0xd5446656, 0x2314ca9b, 0x4ddbd982, 0x21014e84, 0x53602692, 0xe8eb53dd, 0xf80e4406, 0x9710e7fa, 0xb84f41b5, 0xdacb3e78, 0x4d0e7e91, 0xeb2f6727, 0x6251d8de, 0x2d4a2250, 0xb99ef150, 0xc7b4f592, 0x0215841f, 0x9b8e2c3d, 0x1f6a4ff5, 0x23c16d88, 0x12f093c4, 0xc83badbc, 0x96c1571f, 0x41451245, 0xc470c168, 0x4c0a6967, 0xc6b0e264, 0x20d0fe61, 0xa7250e40, 0xab6e6294, 0xd9daad91, 0x5deb694a, 0xe93ae338, 0xcafb8eb0, 0xc4a5667b, 0x3fbab194, 0x6cda9706, 0x3f6f1687, 0x404105b3, 0x21d4e997, 0x0f5aff3d, 0x4094a2a0, 0x010417f6, 0x20055972, 0x6355cf28, 0x7e2a04c2, 0xb4042d61, 0x61404b37, 0x989fbfd4, 0x0c4b6cd4, 0x0d9adc31, 0xa87ff17d, 0xc574d69e, 0x8431c4db, 0x89ab18ea, 0xb4d18a72, 0x2e8e16aa, 0xebfac034, 0xfa1bc019, 0x2f8a015c, 0x73b0d8f3, 0x4cdfce74, 0xe7b1ace0, 0x2d9f8543, 0x11e1002d, 0x94d4d300, 0x7170fbff, 0x6c0f3015, 0xa8aa566e, 0x1fbfe8e6, 0xca2e29a3, 0x13212321, 0x71a55cec, 0x95d0c4f6, 0x33247a53, 0xe9ef442b, 0x8535d32d, 0xa62119b6, 0x950563e5, 0x97c540e9, 0xba8f62b9, 0x3131fe4c, 0xface670a, 0x2c4e35a6, 0xb7c0199b, 0x7effa3d1, 0x887aa80f, 0x999ba822, 0x1ebbff10, 0xa97be68b, 0xf5949837, 0xb611a97e, 0xf6850bde, 0x02c0230c, 0x8aba8b03, 0x31e4595f, 0x1d7fcbea, 0xcbff9946, 0xd44071a0, 0xd90f0a82, 0x0e8b4fd8, 0xa4349da9, 0x031193e9, 0xf90a53f0, 0xe6601c05, 0x862440c4, 0x9a8a3bcb, 0x7ffbb427, 0xea2b70d1, 0xd655f5bf, 0x1134a73e, 0xd68052ac, 0x5f2b4a46, 0x87205732, 0xa6f4bea5, 0x0e5ee8cb, 0xd591c145, 0xbb8b754f, 0xf4908fc1, 0xfb1fd7ef, 0x52b19677, 0x5ffeed55, 0xd751e249, 0x8bbe9cf5, 0x5cef7ebc, 0x5175a28d, 0x6195ec24, 0x6380683b, 0x6fcb04ef, 0x86f1e7d7, 0x6091fbd2, 0x60445cc1, 0xc6654577, 0x0c9ecbc7, 0x9b5b8b2e, 0xb5d59d84, 0xb89ae6a6, 0x2f5fa64f, 0x8b6b3be6, 0xf7811c28, 0xa5e52d4c, 0x22c57a7e, 0x7d3b972b, 0xabbbc587, 0x43853149, 0x3daf358b, 0x70a14b1a, 0xf754bb3b, 0x4190b556, 0xe475981a, 0x00d5a713, 0xaabfd271, 0xc7615281, 0x4eca4a6b, 0x4fce5d9d, 0xb5003a97, 0x6f1ea3fc, 0x5c3ad9af, 0x3c7e856e, 0xf5413f24, 0xaa6a7562, 0x2c9b92b5, 0x3cab227d, 0xe7640bf3, 0x62847fcd, 0xe6b5bb16, 0x33f1dd40 +}, +{ +0x030d96e2, 0x47cba74a, 0x567afd42, 0x11b15a08, 0x00c98a03, 0x9afb0a94, 0xcb04561f, 0x9b91070c, 0xa7e3f4b3, 0xb2da9990, 0xf6d5223b, 0x6a080efd, 0x6e49b3d5, 0x7ff8e9dd, 0xb3791e0b, 0x55776ba0, 0x9b588d0f, 0x03c41ce1, 0x6e8039d6, 0x8f0bedb4, 0x2e07b556, 0xe60e75ab, 0x9fd0ba24, 0x9e733dbf, 0x440fbbab, 0x8e61e02c, 0x69cc121c, 0x0488372b, 0x6905981f, 0x9cdd2cc6, 0x2982149f, 0x2c602e2c, 0xe6c7ffa8, 0x28e81907, 0x466820d1, 0x51ff5c8b, 0xb652aebb, 0xd8d2976d, 0x79decf8f, 0xdd30adde, 0xf25d1510, 0xa5846fc9, 0x5398c7f1, 0x2d0a23b4, 0x892dcbe6, 0xe7647833, 0x3a9d5fee, 0x523b406a, 0x89e441e5, 0x888e4c7d, 0x438a1a62, 0x7e5b6e46, 0x42e017fa, 0xe7adf230, 0x2ece3f55, 0x149aeab8, 0x15f0e720, 0x541d6638, 0x3fb6ef5e, 0x56b37741, 0xf3fe928b, 0xdf5736a4, 0x2fa432cd, 0x8da5fccd, 0x40878c80, 0x06262652, 0x8a205d04, 0xa4ee6251, 0x68a61f84, 0xd81b1d6e, 0xcdebfa4e, 0x6c2e28af, 0xda7c8614, 0xf5113eda, 0x993f1675, 0x38334e97, 0x787d4814, 0x8d6c76ce, 0x9c14a6c5, 0x7917458c, 0xa54de5ca, 0x2f6db8ce, 0x7b70def6, 0xe503e349, 0x9f193027, 0xa72a7eb0, 0xe02853f9, 0x175ef659, 0xf61ca838, 0xdef4b13f, 0x404e0683, 0xd97110f6, 0x9a328097, 0x53514df2, 0xdc932a45, 0x3edce2c6, 0x00000000, 0x131f4b71, 0x7c3cf53c, 0x2dc3a9b7, 0xcee66cac, 0x2b2c05e6, 0xa3a2499b, 0xd9b89af5, 0x6f23be4d, 0x3e1568c5, 0x42299df9, 0x10db5790, 0x8b83da9f, 0x46a1aad2, 0xe18bd462, 0x41ed8118, 0xa2c84403, 0x3d18fe27, 0x01a3879b, 0x074c2bca, 0x7d9f72a7, 0x0441bd28, 0x6bab8966, 0x145360bb, 0xdb168b8c, 0x38fac494, 0x2a8f827d, 0xc809c0fd, 0x02679b7a, 0xf19909f1, 0xa201ce00, 0xe469eed1, 0xc963cd65, 0xb4fcbfc2, 0xb2131393, 0xb07488e9, 0xb7f12920, 0x05e23ab3, 0xf03a8e6a, 0x7bb954f5, 0x8ea86a2f, 0xe5ca694a, 0xe24fc883, 0x7cf57f3f, 0xf3371888, 0x5710f0da, 0xe3ec4f18, 0xde3d3b3c, 0x9ebab7bc, 0xa10c58e2, 0x44c631a8, 0xc9aa4766, 0xf5d8b4d9, 0xddf927dd, 0x41240b1b, 0xa066557a, 0x052bb0b0, 0x15396d23, 0x1178d00b, 0xdbdf018f, 0x12bcccea, 0x7e92e445, 0x6d442537, 0x3b3ed875, 0xe1425e61, 0x7a1ad36e, 0xe325c51b, 0xf15083f2, 0x3bf75276, 0xf0f30469, 0x55bee1a3, 0x02ae1179, 0xcf45eb37, 0xca6e5b87, 0xe0e1d9fa, 0xb3b09408, 0xf7bf2fa3, 0x8ccff155, 0x8c067b56, 0x2be58fe5, 0x3cbb79bc, 0x45ac3c30, 0xb0bd02ea, 0x016a0d98, 0x16fd71c2, 0x6ac184fe, 0x7d56f8a4, 0xcd22704d, 0x8847c67e, 0x686f9587, 0xb11e8571, 0xf2949f13, 0x9db7215e, 0xdf9ebca7, 0xb55f3859, 0x8b4a509c, 0xa6407328, 0x57d97ad9, 0xa689f92b, 0x52f2ca69, 0xb69b24b8, 0xb43535c1, 0x3990c90c, 0xe4a064d2, 0xf47b3342, 0xa1c5d2e1, 0x1634fbc1, 0x3a54d5ed, 0x6fea344e, 0x3c72f3bf, 0x98551bed, 0x8ae9d707, 0x6ce7a2ac, 0xcaa7d184, 0x127546e9, 0x8fc267b7, 0x50955113, 0x6d8daf34, 0xe2864280, 0x7ad3596d, 0x5136d688, 0x4565b633, 0xcc487dd5, 0x6b620365, 0xf4b2b941, 0xdab50c17, 0x1012dd93, 0xdc5aa046, 0x989c91ee, 0x43439061, 0x7f3163de, 0xc8c04afe, 0x78b4c217, 0xf776a5a0, 0x17977c5a, 0xa0afdf79, 0x2a46087e, 0x99f69c76, 0xb596b25a, 0x3f7f655d, 0xcbcddc1c, 0xcc81f7d6, 0x0785a1c9, 0xb1d70f72, 0xa36bc398, 0x54d4ec3b, 0x3959430f, 0x28219304, 0xce2fe6af, 0x47022d49, 0x9d7eab5d, 0xa427e852, 0x294b9e9c, 0x3dd17424, 0x13d6c172, 0x2ca9a42f, 0x505cdb10, 0x06efac51, 0xb738a323, 0xcf8c6134 +}, +{ +0x7efe1ab0, 0xec8021d3, 0x1a74d869, 0x5a108c5d, 0x384e8d06, 0xb409c3e1, 0x1715bf44, 0x04afbd9a, 0x6909b583, 0x83bf47a5, 0x0bb5a4af, 0x7e1c0ac7, 0xe82f9c49, 0x812629ca, 0x4de7236e, 0x77d2d070, 0xeab6f226, 0xb0a67e7b, 0x3a35f31e, 0xf616e9cd, 0x0b57b4d8, 0x00e21077, 0xe1035689, 0x33fb29a9, 0x20a33b00, 0x1e397584, 0xf48f87a2, 0x8a938d65, 0xae9f0bff, 0x092ccac0, 0x135812a9, 0x9b52f1a3, 0x240c869a, 0x00000000, 0x37549433, 0x4429f9d9, 0x2fb92235, 0x739f7d9d, 0x929c2b14, 0xa84bc87d, 0x754bbe1f, 0x60257f43, 0x352fea2b, 0x316247c6, 0x927e3b63, 0xf0c22a4f, 0x20412b77, 0x99298fbb, 0x027b7e18, 0x648ac2d9, 0xb23f1014, 0xaad2a612, 0xc50fd013, 0xeefb5fcb, 0x9633968e, 0xc33903e6, 0x6da60819, 0x4f7e4d01, 0x6b72cb9b, 0x856b8427, 0xca15c926, 0xbbf1caa3, 0xf6f4f9ba, 0x02996e6f, 0x5ebf31c7, 0x7730c007, 0xf9eee08f, 0xa751d148, 0x6f3f6676, 0x6613acb6, 0xa3fe6cd2, 0x1c420b9c, 0x37b68444, 0x6d44186e, 0x69eba5f4, 0x782ad932, 0x550a9568, 0xace475e7, 0xd061114f, 0x9d642256, 0x11236cb1, 0xc5edc064, 0x53de56ea, 0xcaf7d951, 0x4d053319, 0x2677f882, 0xcc231ad3, 0x66f1bcc1, 0x9f1f5c4e, 0x4f9c5d76, 0xa31c7ca5, 0x78c8c945, 0x11c17cc6, 0x1edb65f3, 0x9d863221, 0xf25b4420, 0x3e9a4e84, 0x2b169faf, 0x737d6dea, 0xf46d97d5, 0x5e5d21b0, 0x94aaf8e1, 0x318057b1, 0x2bf48fd8, 0xd6b5d2cd, 0xdb36a597, 0x51473885, 0xc88ca749, 0x81c439bd, 0x2d204c5a, 0x625e015b, 0xd657c2ba, 0x87f2ea48, 0x4b33e0ec, 0xffd8337a, 0x9bb0e1d4, 0xe7d7950b, 0x5771eb70, 0xf0203a38, 0x40645434, 0x1ca01beb, 0x3ce1309c, 0xc1427dfe, 0xdf99180d, 0x8a719d12, 0x71e40385, 0x8e3c30ff, 0x8ca55e90, 0x0d83775a, 0xc796be7c, 0x044daded, 0xa18512ca, 0x2f5b3242, 0xf2b95457, 0x90e7550c, 0xa16702bd, 0x13ba02de, 0xa5c8bf27, 0xb0446e0c, 0x2dc25c2d, 0xceba74bc, 0x0636d3f5, 0x3c0320eb, 0xb2dd0063, 0xb690ad8e, 0x710613f2, 0x35cdfa5c, 0xe8cd8c3e, 0xbdc71956, 0xbfbc674e, 0x5cc44fdf, 0xee194fbc, 0x835d57d2, 0x156ec15c, 0xa52aaf50, 0xae7d1b88, 0xe5aceb13, 0xc3db1391, 0xfd415d15, 0x533c469d, 0xfda34d62, 0xd4ceacd5, 0x0d61672d, 0x331939de, 0xd2f87f20, 0xe735857c, 0xdf7b087a, 0x8710fa3f, 0x180fa671, 0xe3782891, 0xb98ab4bb, 0x85899450, 0xc86eb73e, 0x7a51a72a, 0x40864443, 0xd42cbca2, 0x7ab3b75d, 0xce5864cb, 0x5889e232, 0xc774ae0b, 0x38ac9d71, 0x158cd12b, 0x7c6774df, 0xbb13dad4, 0x6468d2ae, 0x9448e896, 0xfb959e97, 0x421f2a2c, 0x18edb606, 0xd9afcbf8, 0xbf5e7739, 0x586bf245, 0x49489ef4, 0xa7b3c13f, 0xea54e251, 0x51a528f2, 0x6fdd7601, 0x3e785ef3, 0x9005457b, 0x60c76f34, 0x5c265fa8, 0xf90cf0f8, 0x223a556f, 0x880ae30a, 0x6b90dbec, 0x17f7af33, 0x46b097b6, 0x22d84518, 0x75a9ae68, 0xaa30b665, 0xc1a06d89, 0x298ff1c0, 0x5793fb07, 0x0f1a1935, 0xb968a4cc, 0x465287c1, 0x5af29c2a, 0x09cedab7, 0x296de1b7, 0x9ffd4c39, 0x99cb9fcc, 0x8ede2088, 0x7c8564a8, 0xdbd4b5e0, 0x3ad7e369, 0xff3a230d, 0xac066590, 0x44cbe9ae, 0x06d4c382, 0x1a96c81e, 0xdde26615, 0xb672bdf9, 0xd0830138, 0xd94ddb8f, 0xfb778ee0, 0x55e8851f, 0x42fd3a5b, 0xb4ebd396, 0x49aa8e83, 0x24ee96ed, 0xe54efb64, 0xa8a9d80a, 0xccc10aa4, 0x8c474ee7, 0x0ff80942, 0x4bd1f09b, 0x62bc112c, 0x88e8f37d, 0xd21a6f57, 0xe1e146fe, 0xbd250921, 0x2695e8f5, 0xec6231a4, 0xdd007662, 0x96d186f9, 0xe39a38e6 +}, +{ +0x5aecccd7, 0xaa1dd177, 0xaa21214b, 0x7b5b1d87, 0x8607ce5e, 0x8226e6fd, 0x8b96f01b, 0x02af30e4, 0xfd57c9ff, 0xffc40927, 0x8d241860, 0x574102ae, 0x041dd89f, 0x84a8feba, 0x574a1888, 0x8f8b2884, 0xd8ca2a2a, 0x5ec6fe52, 0x7b67edbb, 0x5c69ceb6, 0xaa16cb51, 0x8939c0ff, 0xfbee3ba2, 0x536b302b, 0x2aa8f752, 0xacaf390c, 0x0dadce79, 0x55d2c276, 0xd17a3ccc, 0x80b52625, 0x587f0c0f, 0xd3e9fc14, 0x8d18e85c, 0x8b9dea3d, 0x53602a0d, 0xae0b13ce, 0x84940e86, 0xa8b9fbb5, 0xfd6023e5, 0x51f8f0f3, 0xf97dfb7a, 0x863b3e62, 0xdcdce893, 0xa88e11af, 0xa51f2fea, 0x704f21a3, 0x06b9f25d, 0xac93c930, 0xd3de160e, 0x2e82c5d7, 0xd8f6da16, 0x8932dad9, 0xf4db2f25, 0x06b2e87b, 0x098ce6da, 0x00000000, 0x2c11050f, 0x02a42ac2, 0xa8850b89, 0x21803b4a, 0x09bb0cc0, 0x2c26ef15, 0x2a94076e, 0x0f3e0ea1, 0x042128a3, 0xac98d316, 0x51f3ead5, 0xf4ecc53f, 0xa523dfd6, 0xa787f514, 0x0037ea1a, 0x283b378a, 0x5c62d490, 0xa7bb0528, 0x7b6cf79d, 0xf4d03503, 0x84a3e49c, 0x2313fb92, 0xda59eaf2, 0xd7c8d4b7, 0xfff8f91b, 0x72eb0b61, 0x8082cc3f, 0xd7c3ce91, 0x76c139e4, 0xa13e0749, 0xd7ff3ead, 0xd7f4248b, 0x76ca23c2, 0x2739c917, 0x06850261, 0x70443b85, 0x23241188, 0x5848e615, 0x8f8032a2, 0x7de2efda, 0x5adb26cd, 0x232f0bae, 0xf94a1160, 0xfbe52184, 0xae3cf9d4, 0x849f14a0, 0xf6741fc1, 0x890e2ae5, 0xda6e00e8, 0x5c553e8a, 0xfff3e33d, 0x7452f93c, 0x76fdc9d8, 0x822dfcdb, 0x09b016e6, 0x25a113e9, 0x577df292, 0xfd6b39c3, 0xaca4232a, 0x0b23d63e, 0xf269c75e, 0x7f46c518, 0xd8c1300c, 0x86302444, 0xf25e2d44, 0xae37e3f2, 0x2e89dff1, 0x5ecde474, 0x2318e1b4, 0x5ae7d6f1, 0xd56cfe75, 0xdceb0289, 0x2a9f1d48, 0xd5500e49, 0x7073d19f, 0x8d13f27a, 0x72e01147, 0x76f6d3fe, 0xda52f0d4, 0x0f09e4bb, 0x2807c7b6, 0xde78c251, 0x042a3285, 0xf0c6f7ba, 0x5c5e24ac, 0xf67f05e7, 0xa8b2e193, 0x25aa09cf, 0x2ebe35eb, 0x79c3c779, 0xa3adc791, 0xdce018af, 0x259de3d5, 0x0298dafe, 0x0987fcfc, 0xd55b146f, 0x5efa0e6e, 0xffcf1301, 0x821a16c1, 0xd8fdc030, 0x79f42d63, 0x2596f9f3, 0x860cd478, 0x2705392b, 0x7dd505c0, 0xd3d50c28, 0x003cf03c, 0x5ef11448, 0x0f02fe9d, 0xae0009e8, 0xde73d877, 0xf9410b46, 0xf648effd, 0x7459e31a, 0x2c2df533, 0x5ad03ceb, 0x8ba11a01, 0xde4f284b, 0x2aa3ed74, 0x7078cbb9, 0xf976e15c, 0x8d2f0246, 0xf0f11da0, 0x82110ce7, 0x72dce17b, 0xd146ccf0, 0x535cda31, 0x280cdd90, 0x58741629, 0x5357c017, 0x21bccb76, 0xa528c5f0, 0x55ee324a, 0x0b143c24, 0x5776e8b4, 0xa78cef32, 0x2eb52fcd, 0xfbd2cb9e, 0x80be3c03, 0x8fbcc29e, 0x0da6d45f, 0x000b1a26, 0x51cf1ae9, 0xd3e2e632, 0x068e1847, 0xa7b01f0e, 0x79ff3745, 0xa1351d6f, 0x7b5007a1, 0xa102f775, 0xf262dd78, 0x2c1a1f29, 0x55e5286c, 0x74651326, 0xfbd9d1b8, 0xa39a2d8b, 0xf0cded9c, 0x5843fc33, 0x746e0900, 0xda651ace, 0x8089d619, 0xaa2a3b6d, 0xde44326d, 0xa39137ad, 0xd17126ea, 0x0293c0d8, 0x51c400cf, 0x0d9a2463, 0x890530c3, 0x79c8dd5f, 0xf4e7df19, 0xf2553762, 0x7f7a3524, 0x270e230d, 0x7f712f02, 0x55d9d850, 0xf643f5db, 0xdcd7f2b5, 0x28302dac, 0x0416c2b9, 0x0b28cc18, 0x8fb7d8b8, 0x8baa0027, 0x21b7d150, 0x7f4ddf3e, 0xa109ed53, 0xa3a6ddb7, 0xd14dd6d6, 0x0b1f2602, 0x7de9f5fc, 0xfd5cd3d9, 0xd567e453, 0x0f351487, 0x72d7fb5d, 0xa51435cc, 0x2732d331, 0xf0fa0786, 0x7dde1fe6, 0x0d913e45, 0x218b216c +} +}, +{ +{ +0x9f482e49, 0x325eafb1, 0x59fb34a0, 0x81a6e79f, 0x4259d80a, 0xe3af5f56, 0xd85dd33f, 0x4eb9deae, 0xc78a4466, 0xfd419680, 0xf4681edc, 0x92917662, 0xf9b146f7, 0x6ba59b11, 0x932d8369, 0x880ac447, 0x37972149, 0x3e3b0291, 0x66f968be, 0x74f7a7cc, 0x1e6b6252, 0x251c45bf, 0x6b203095, 0x0ce006a4, 0x4acca55d, 0x01395e8f, 0x43e52d01, 0xc6b31ae9, 0x9214dde6, 0xf1a19024, 0x133791fd, 0x0d5cf3af, 0x46a9087d, 0xb3f8482e, 0xcf1f3931, 0x9758f89a, 0x9b3d55ba, 0xbbe89efd, 0x16fe1f05, 0xe6e37a2a, 0x128b64f6, 0x2979e89f, 0x9a040b35, 0x58c26a2f, 0x6ee9be6d, 0x3f87f79a, 0xc2c6611a, 0x9fcd85cd, 0x6f554b66, 0x597e9f24, 0xb7089859, 0x7ce7711f, 0x551b3204, 0xe32af4d2, 0x84eac2e3, 0xf01d652f, 0x5847c1ab, 0xd04d05ec, 0xeef3acf9, 0x21ec95c8, 0xe7da24a5, 0xd1745b63, 0xef4f59f2, 0xa1732cd8, 0x120ecf72, 0x6a9cc59e, 0x7c62da9b, 0x0810d6d3, 0xfcfd638b, 0xa506572b, 0x5d0be4d7, 0x36ae7fc6, 0x9bb8fe3e, 0x04757bf3, 0x1ba2ecaa, 0xa0cfd9d3, 0xd5012090, 0xa43f09a4, 0x667cc33a, 0xa583fcaf, 0x2840b610, 0x7082dc3f, 0xf098ceab, 0x4b705056, 0x8cfa1430, 0xc243ca9e, 0x754b52c7, 0xa04a7257, 0x4e3c752a, 0x7dde2f90, 0xe666d1ae, 0x9661a615, 0x24a0b0b4, 0x801a1294, 0x33e25aba, 0xf934ed73, 0x1b27472e, 0xcea3cc3a, 0x05c98ef8, 0xf1243ba0, 0x3f025c1e, 0x809fb910, 0xfdc43d04, 0xad932a7c, 0xea037c8e, 0xcb6a42c2, 0x2599ee3b, 0xdcad0348, 0xbf184e8a, 0x628c134d, 0x7817a168, 0x04f0d077, 0x516e49f7, 0x462ca3f9, 0xc70fefe2, 0xd0c8ae68, 0x167bb481, 0xea86d70a, 0x3ebea915, 0xb631c6d6, 0x89339ac8, 0x67459db5, 0x3b7727ed, 0x4bf5fbd2, 0xbb6d3579, 0x13b23a79, 0x71bb82b0, 0xe29601d9, 0xac2fdf77, 0x888f6fc3, 0x0085ab84, 0x75cef943, 0xd4bdd59b, 0xca531c4d, 0x1f523cdd, 0x7d5b8414, 0x50d2bcfc, 0x96e40d91, 0xbf9de50e, 0x6fd0e0e2, 0x5c32ba58, 0xa9e6518f, 0x1742ea0e, 0x43608685, 0xd9648db0, 0xc3ff3f95, 0x9ef4db42, 0xdd945dc7, 0xb37de3aa, 0x1a9bb225, 0x6209b8c9, 0xc636b16d, 0x01bcf50b, 0x79ab5463, 0x5d8e4f53, 0x78920aec, 0x9e7170c6, 0x32db0435, 0xf5d4ebd7, 0xd9e12634, 0xcad6b7c9, 0x63b54dc2, 0x6a196e1a, 0x479056f2, 0xb78d33dd, 0x4715fd76, 0xd4387e1f, 0x205060c3, 0xa4baa220, 0xf80db3fc, 0xcf9a92b5, 0xa1f6875c, 0xeb3a2201, 0x3acbd2e6, 0x85d39c6c, 0x362bd442, 0x700777bb, 0xacaa74f3, 0x3a4e7962, 0x9a81a0b1, 0xb6b46d52, 0xf4edb558, 0xd5848b14, 0xd8d878bb, 0x93a828ed, 0x51ebe273, 0xefcaf276, 0xfc78c80f, 0x00000000, 0x97dd531e, 0x21693e4c, 0xe213aa5d, 0x846f6967, 0x1fd79759, 0x1a1e19a1, 0x67c03631, 0xe75f8f21, 0x0dd9582b, 0x054c257c, 0x792effe7, 0xad1681f8, 0x8d46e13b, 0xd1f1f0e7, 0x54226c8b, 0xa8df0f00, 0x4f052ba5, 0x3367f13e, 0x0929885c, 0xb244bd25, 0x6e6c15e9, 0x37128acd, 0xba546bf6, 0x17c7418a, 0xb2c116a1, 0x559e9980, 0x4a490ed9, 0x81234c1b, 0x2d0c936c, 0xee76077d, 0x29fc431b, 0xce2667be, 0xa85aa484, 0x74720c48, 0xdc28a8cc, 0xa963fa0b, 0x4f808021, 0x28c51d94, 0x42dc738e, 0x24251b30, 0xbea4bb81, 0x713e2934, 0xf5514053, 0x54a7c70f, 0x08957d57, 0x2c35cde3, 0x20d5cb47, 0xbad1c072, 0xbe211005, 0x50571778, 0xebbf8985, 0x3bf28c69, 0x89b6314c, 0x8dc34abf, 0x8c7fbfb4, 0x2cb06667, 0xdd11f643, 0x09ac23d8, 0x6330e646, 0xcbefe946, 0xf8881878, 0x5cb711dc, 0x855637e8, 0x0c65ad20, 0x1eeec9d6, 0x2d8938e8, 0xc37a9411 +}, +{ +0xae7a7397, 0xe1df6963, 0x8ddb81af, 0x32155a63, 0xe541c61f, 0x41dbb92d, 0xfb55f710, 0x989ec138, 0x792eefeb, 0x45451651, 0x33cb60ee, 0x452a51e1, 0x006f47b0, 0x22108f05, 0xc92feac3, 0x9940fbb5, 0x768e76bf, 0x00000000, 0xc8f1d04e, 0x73cee34e, 0x773f0b82, 0x8c05bb22, 0x1fca0b82, 0xab55a1d6, 0xc6e03427, 0x054095f1, 0x668ba3d9, 0xb52ed769, 0x28f083a0, 0xb4f0ede4, 0xa52b020f, 0x1e7b76bf, 0x927ecd9d, 0x149b7a1a, 0x83a52276, 0xfe1562e1, 0x368bf51f, 0x373a8822, 0x93cfb0a0, 0x2c6e2cdc, 0x92118a2d, 0xf52b54c9, 0x67559954, 0x973e586c, 0xe1b02ed3, 0x98f18688, 0xbe7fa6f1, 0xb0010528, 0xc751491a, 0xefa1caba, 0x268e2079, 0x86e5b787, 0x2ddf51e1, 0xf0048688, 0x6ddad241, 0xe49ffc92, 0x9db11379, 0x0fcfdee4, 0x01b17d3d, 0xf06bc138, 0x0b3e3628, 0x968f2551, 0xdc05ede4, 0x5fa0cf92, 0xdc6aaa54, 0x96e062e1, 0x51de6c4b, 0x873b8d0a, 0xd92a3fa5, 0xcdb145bf, 0x83ca65c6, 0xa06b97fe, 0x6c6baf7c, 0xc940ad73, 0x36e4b2af, 0xf4f56e44, 0xa004d04e, 0x227fc8b5, 0x73a1a4fe, 0xeae15f4b, 0x673adee4, 0x93a0f710, 0xbb3f3300, 0x506f1176, 0x5540c337, 0x62150ca5, 0x82145f4b, 0xa49a7f32, 0x6c04e8cc, 0x106a92d6, 0xb06e4298, 0x992fbc05, 0xa1b5ad73, 0xee7ff037, 0xab3ae666, 0x5b3e60ee, 0x1005d566, 0xd27b4e3d, 0x292eb92d, 0x3755cf92, 0xeb3f65c6, 0xd8f40528, 0x7db04097, 0x4fa51af4, 0x63a47198, 0x727f9e73, 0x9dde54c9, 0xba8e4e3d, 0x273f5d44, 0xc211dceb, 0xfae48a2d, 0x2db01651, 0x627a4b15, 0x689a47b0, 0x2c016b6c, 0x4e7b2079, 0xe06e145e, 0x789f92d6, 0xaae4dceb, 0x5b51275e, 0xffcb586c, 0x4e1467c9, 0xaa8b9b5b, 0x8db4c61f, 0x63cb3628, 0x4fca5d44, 0x26e167c9, 0xcdde020f, 0x14f43daa, 0xd3ca3300, 0x1fa54c32, 0x4b3bb588, 0x1ae5d9c3, 0xf49a29f4, 0x5e11b2af, 0x152a0727, 0xd6e5e141, 0x552f8487, 0x827b18fb, 0x0e11e469, 0xbfcedbcc, 0x892a6963, 0xc68f7397, 0x289fc410, 0xffa41fdc, 0xc27e9b5b, 0x4b54f238, 0x1b54a4fe, 0xbfa19c7c, 0xee10b787, 0xc3cfe666, 0xeb502276, 0x88f453ee, 0x3db5c337, 0x8c6afc92, 0x7210d9c3, 0xae153427, 0x23ceb588, 0x97511fdc, 0xf5441379, 0x69447d3d, 0x15454097, 0x51b12bfb, 0x3c04be0a, 0x5fcf8822, 0xf1b5fbb5, 0xcc003882, 0x76e1310f, 0x38f556c6, 0xc3a0a1d6, 0xe00153ee, 0xd68aa6f1, 0x77504c32, 0xafa4491a, 0xc89e97fe, 0x1e14310f, 0x7c6e7a1a, 0x7c013daa, 0xd3a574b0, 0x049eaf7c, 0x400583a0, 0x1a8a9e73, 0xb1b07815, 0x33a4275e, 0x89452ed3, 0xd73bdbcc, 0x23a1f238, 0xd9457815, 0xe4f0bb22, 0x7ddf0727, 0xfe7a2551, 0xbae1098d, 0x406ac410, 0x9c6f29f4, 0x4a8ac8b5, 0xdddbd769, 0xd214098d, 0xa1daeac3, 0x9c006e44, 0x39442bfb, 0x889b145e, 0xa4f53882, 0x68f50000, 0xefce8d0a, 0xd89b4298, 0x6db595f1, 0xcc6f7f32, 0x0a8f4b15, 0xb49faa54, 0x66e4e469, 0x78f0d566, 0x44f46b6c, 0x4ae58f05, 0x11b4a85b, 0x5a8f1dd3, 0x5e7ef51f, 0x11dbefeb, 0xbe10e141, 0xb54190d9, 0x54f1be0a, 0x392b6c4b, 0xc73e0eaa, 0x0fa09954, 0x41b4fe9d, 0xf1dabc05, 0x052fd241, 0x01de3a8d, 0x0ae00ca5, 0xfa8bcd9d, 0xe52e81af, 0xbb5074b0, 0xddb490d9, 0xb1df3fa5, 0xafcb0eaa, 0x3dda8487, 0x549ef9ba, 0x2941fe9d, 0x449b2cdc, 0x692b3a8d, 0x27501af4, 0x389a1176, 0x7941a85b, 0xa54445bf, 0x8754caba, 0xd7549c7c, 0x500056c6, 0x868af037, 0x327a1dd3, 0xfb3ab0a0, 0x1b3be34e, 0x0b517198, 0x0e7ea3d9, 0x04f1e8cc, 0x5ae05a63, 0xea8e18fb, 0x3c6bf9ba +}, +{ +0x1a0a451c, 0x8fdd609f, 0x04961f9c, 0x8ed2c658, 0xf0a46a5e, 0x463677dc, 0x9cd13482, 0x1e995b4c, 0xdf7efa05, 0x7f7c0b0d, 0x30496c1c, 0x7bef155d, 0x224f9f0a, 0x51a93d91, 0xcd7d08df, 0xbf910d4f, 0x95d2244f, 0xe73b2013, 0x69ece787, 0x58aa2d5c, 0x0c9fa85a, 0xde745d0e, 0x7e73adca, 0xbb0712d3, 0x904e9cd8, 0x767f1bc0, 0xf1abcc99, 0xac98589e, 0x69e9e64b, 0xc0e8078e, 0x1e9c5a80, 0x65764e11, 0x91443bd3, 0xb79dbb45, 0xc574bf19, 0xc47b19de, 0x3ddc634d, 0xf9a77a93, 0xee3830de, 0x6d7af81b, 0xdbede455, 0x234039cd, 0x4f356711, 0xe73e21df, 0x82486fce, 0x0599b95b, 0x9ddb9389, 0x130c541d, 0x27d3279d, 0xa80b46ce, 0x2a432900, 0xfc3ec3c8, 0x68e6408c, 0x50a69b56, 0x4e3fc01a, 0xc1e2a085, 0x2b498e0b, 0xa002f108, 0xa007f0c4, 0xe2a79884, 0x4e3ac1d6, 0x179a4b81, 0xdbe8e599, 0x304c6dd0, 0xc0ed0642, 0x60eaf686, 0x43afce87, 0xba08b414, 0xcc77afd4, 0x86db719e, 0xd3e1525f, 0xb798ba89, 0x09061101, 0x394f7d1d, 0x1206f316, 0xf8a8dc54, 0x8a41d808, 0x2b4c8fc7, 0x3146cadb, 0x3cd3c58a, 0x7775bccb, 0x26dc815a, 0x3840dbda, 0xdae7435e, 0x090310cd, 0x1690ec8a, 0x87d1d695, 0x5d3695cb, 0x8ed7c794, 0x51ac3c5d, 0x6c705f10, 0x7e76ac06, 0x553f220d, 0x23453801, 0xe2a29948, 0x6479e8d6, 0x1f96fd8b, 0x86de7052, 0xbf940c83, 0x1b00e217, 0x0c9aa996, 0x904b9d14, 0xb20103d2, 0x4739d11b, 0xba0db5d8, 0xa494ee94, 0xb204021e, 0x43aacf4b, 0x7ae5b256, 0xac9d5952, 0xeaae2f42, 0xfd3464c3, 0x42a06840, 0xc47e1812, 0x4aacde4a, 0x8a44d9c4, 0xad92ff95, 0xbe9baa44, 0x87d4d759, 0x7ae0b39a, 0x080cb60a, 0x4aa9df86, 0xf8addd98, 0x179f4a4d, 0xc9eb1743, 0x394a7cd1, 0x9cd4354e, 0x8b4b7f03, 0xa59e499f, 0xb30ea515, 0xd7774dc3, 0x60eff74a, 0xc8e4b184, 0x0d950f51, 0xf538d2c9, 0xef379619, 0x73e3a357, 0x6c755edc, 0x98422ad2, 0xd678eb04, 0x473cd0d7, 0x1f93fc47, 0x224a9ec6, 0x2fda905b, 0xeba18985, 0x824d6e02, 0xd3e45393, 0x5d339407, 0xdae24292, 0x34df7380, 0xdf7bfbc9, 0x6d7ff9d7, 0xeaab2e8e, 0xb6971c4e, 0x767a1a0c, 0x8fd86153, 0xf437740e, 0x98472b1e, 0x4ba3788d, 0x04931e50, 0x94dd8288, 0x68e34140, 0x7f790ac1, 0xeba48849, 0x61e55041, 0x9dde9245, 0x0809b7c6, 0xb6921d82, 0x59a58b9b, 0x72ec0590, 0x91413a1f, 0x3845da16, 0x27d62651, 0x58af2c90, 0x8347c909, 0xad97fe59, 0xf53dd305, 0x95d72583, 0xd7724c0f, 0xc571bed5, 0x2ed03750, 0xf0a16b92, 0x35d5d48b, 0xc1e7a149, 0xbe9eab88, 0x61e0518d, 0x543084ca, 0x647ce91a, 0xa904e009, 0xf9a27b5f, 0xf1aecd55, 0xcc72ae18, 0xe3a83e43, 0x00000000, 0x059cb897, 0xd2ebf554, 0x50a39a9a, 0x8b4e7ecf, 0xa1085603, 0xbb02131f, 0x7bea1491, 0x3143cb17, 0x1695ed46, 0xa901e1c5, 0xfd31650f, 0x8342c8c5, 0x5c3c32c0, 0x1203f2da, 0x130955d1, 0xd2eef498, 0xa10d57cf, 0xf43275c2, 0xc9ee168f, 0x26d98096, 0x42a5698c, 0x65734fdd, 0x2ed5369c, 0x3dd96281, 0xde715cc2, 0xa491ef58, 0x99488dd9, 0x010fa6c7, 0x2fdf9197, 0x4f3066dd, 0xc8e1b048, 0x35d0d547, 0x1a0f44d0, 0x7770bd07, 0x553a23c1, 0x0d900e9d, 0x59a08a57, 0xe3ad3f8f, 0xcd780913, 0x54358506, 0xb30ba4d9, 0x94d88344, 0xd67deac8, 0x1b05e3db, 0x72e9045c, 0x34da724c, 0x994d8c15, 0xee3d3112, 0x46337610, 0x73e6a29b, 0xef3297d5, 0x5c39330c, 0x2a4628cc, 0xe6318718, 0x000501cc, 0xa59b4853, 0x3cd6c446, 0xa80e4702, 0x4ba67941, 0xfc3bc204, 0xe63486d4, 0x010aa70b +}, +{ +0x65f9fe5f, 0x7c97ef6a, 0xb8dc4cdb, 0xad7303ed, 0x05cc7220, 0xac903c7d, 0x7ce97eeb, 0x71cb1f78, 0x1ca26315, 0x0973bda2, 0x61b52e76, 0x0d5cf012, 0xd5d6ad2f, 0xb8bfd142, 0x019dae11, 0x01fe3388, 0x65876fde, 0x08f31fab, 0xc01a7f80, 0xad109e74, 0xa8bf71cd, 0xd5cba137, 0xb4638359, 0x6d0ae1f4, 0x741a6140, 0xd0794296, 0x6938a05c, 0x15af4f36, 0x15ccd2af, 0xcd25120b, 0xcca5b002, 0xcd381e13, 0x60358c7f, 0x7464f0c1, 0xa8c1e04c, 0x7587cf51, 0xdd25b284, 0xccc62d9b, 0xc4283e28, 0xd44b033e, 0x74076d58, 0xc969c222, 0x00639d99, 0xb41d12d8, 0xc19add89, 0x10633d16, 0x189022bd, 0xccb8bc1a, 0xc5b59039, 0xc8f46c33, 0x704bbd71, 0xc456afa9, 0x70352cf0, 0xbcf3016b, 0x196e1135, 0xacf3a1e4, 0xd01adf0f, 0x08ee13b3, 0xa400be4f, 0xa02ff3ff, 0x695b3dc5, 0xa93fd3c4, 0xb1aff179, 0x042f4db0, 0x68a50e4d, 0x795b9d4a, 0x14517cbe, 0xd1f9e09f, 0x68c693d4, 0xa9414245, 0x096eb1ba, 0xa59d105e, 0x6cf4d27c, 0x7d74d0fa, 0xd9746eb5, 0x7479fcd9, 0x68b80255, 0x71b58ef9, 0x6d697c6d, 0xc88afdb2, 0xd0644e8e, 0xd43592bf, 0x7d69dce2, 0x7d174d63, 0x71d61360, 0x6c8a43fd, 0x79469152, 0x18f3bf24, 0xc91753a3, 0xb59db0d1, 0x61a8226e, 0x19731d2d, 0xc4353230, 0x1432e127, 0x64795c56, 0x793800d3, 0x0180a209, 0x0d226193, 0x090d2c23, 0x702820e8, 0x78b8a2da, 0x1d22c11c, 0x007e9181, 0x0ca2c39a, 0xc5a89c21, 0x05b2e3a1, 0xa8dcec54, 0xbd103efb, 0xd187711e, 0x60288067, 0x1cdcf294, 0xdcdb810c, 0xc5cb01b8, 0x71a882e1, 0xa051627e, 0x0910203b, 0xd917f32c, 0xc0077398, 0x05afefb9, 0x08908232, 0x1000a08f, 0xb47e8f41, 0x61d6b3ef, 0xdd38be9c, 0xb9227f53, 0x190d8cac, 0xa95c4e5d, 0xd96962ad, 0xc1f94010, 0x107e310e, 0xa5801c46, 0xcd468f92, 0xd5b530b6, 0x00000000, 0xb5e32150, 0x0451dc31, 0x044cd029, 0x79250ccb, 0x119d0e9e, 0xb1cc6ce0, 0x78db3f43, 0xd1e4ec87, 0xb8a2dd5a, 0x7c8ae372, 0x604b1dfe, 0x659a63c6, 0xc064ee01, 0xa922dfdc, 0x0d41fc0a, 0xb4001ec0, 0x15d1deb7, 0x61cbbff7, 0x11e39f1f, 0x0cdc521b, 0xb04ccee9, 0xac8d3065, 0x0cc15e03, 0xb1d160f8, 0x6464504e, 0xa032ffe7, 0xc44ba3b1, 0xdcb81c95, 0xa47e2fce, 0x65e4f247, 0x6c974fe5, 0x68db9fcc, 0xd8975125, 0x18eeb33c, 0x0d3f6d8b, 0x641ac1cf, 0x1d5c509d, 0xd4560f26, 0x6925ac44, 0xc897f1aa, 0x144c70a6, 0xcd5b838a, 0xb580bcc9, 0xa1cccc6f, 0xb5fe2d48, 0xd007d317, 0xa1b25dee, 0xb95ceed2, 0xc90a5fbb, 0x11800286, 0xa5e381df, 0xb8c140c3, 0x605611e6, 0xbc8d90ea, 0xb051c2f1, 0x1cbf6f0d, 0xbd0d32e3, 0x7056b169, 0xdcc68d14, 0x6ce9de64, 0xdd462f1d, 0x05d17e38, 0xaceeadfc, 0xa41db257, 0xb1b2fd61, 0x1cc1fe8c, 0xc5d60da0, 0x6d747075, 0xdca5108d, 0x001d0c18, 0xa1d1c077, 0x7cf472f3, 0xad6e0ff5, 0xbd6eaf7a, 0xdd5b2305, 0x6407cdd7, 0xd8e9c0a4, 0xc079e219, 0x0cbfcf82, 0x75f95ed0, 0x088d8e2a, 0x1d415c85, 0xd19a7d06, 0x1d3fcd04, 0x15b2432e, 0xb93f734b, 0xb0325f68, 0xa1af51f6, 0xa46323d6, 0x191080b4, 0xa04c6e66, 0x188d2ea5, 0xd90aff34, 0x11fe9307, 0x7d0a417b, 0x759ac349, 0xc1e44c08, 0xbcee0d73, 0x694631dd, 0xa8a27dd5, 0xc974ce3a, 0x75e452c8, 0x142fed3f, 0xad0d926c, 0xc8e9602b, 0x043241a8, 0xbc909cf2, 0xd8f4ccbc, 0xd88a5d3d, 0xb941e2ca, 0x6d17edec, 0xc187d191, 0x01e33f90, 0xb02f5370, 0xccdb2183, 0xbd73a362, 0xd4289ea7, 0xd5a83cae, 0x78a5aec2, 0x101dac97, 0x78c6335b, 0xa5fe8dc7 +}, +{ +0x18d8254e, 0x959ff18c, 0x153b569f, 0x0df57d45, 0xfb0a72ab, 0xce132aa8, 0x8c6366d1, 0xff02bdd3, 0xf3d37285, 0xb8488255, 0xd7efbdf5, 0xd7f9b361, 0x3dd656b9, 0xac5766d9, 0x6376f0f6, 0x5aa86937, 0x9d50ff36, 0x765ba8fd, 0x9d46f1a2, 0x5b9ad5b0, 0x4f85313c, 0x350f5697, 0xb091827b, 0xe2f6e5f6, 0xca0deb44, 0x0132bc87, 0x7769147a, 0x575d1472, 0x886ba9a9, 0xf6e9017a, 0x29c9b235, 0x764da669, 0xb5abf184, 0x426642ed, 0x6fb13134, 0x3cf2e4aa, 0xc3e657ed, 0xbc5643b9, 0xc6dc2412, 0xf7cdb369, 0x18ce2bda, 0xbd72f1aa, 0x5eb6a8db, 0xdb287c37, 0xcb295957, 0xc2c2e5fe, 0xcf21962f, 0x4f933fa8, 0xfb1c7c3f, 0x8959152e, 0x84ac686b, 0x4abf42c3, 0x343dea10, 0x80b2a987, 0x987c825d, 0xff14b347, 0xfe300154, 0x574b1ae6, 0xb1b53068, 0x19ea99c9, 0xd3f17c19, 0x91813060, 0xeb1d595f, 0xf2e1ce02, 0x9c6243b1, 0xee312434, 0xa086a98f, 0xc6ca2a86, 0x7baed5b8, 0x90b38ce7, 0x28ed0026, 0x6a8b42cb, 0x09fdb23d, 0xa96d1526, 0x5267678d, 0x84ba66ff, 0x20220e9c, 0x4354fe6a, 0x90a58273, 0x7377d596, 0x5abe67a3, 0x1cc6e4a2, 0xa5bcda70, 0x25187d63, 0xbd64ff3e, 0x052c7d6b, 0x72456911, 0x80a4a713, 0x342be484, 0xb85e8cc1, 0x887da73d, 0x664c8309, 0x859ed4ec, 0xc2d4eb6a, 0x777f1aee, 0xe7da989d, 0xe7cc9609, 0xf2f7c096, 0x7bb8db2c, 0xa48e66f7, 0x3ce4ea3e, 0x94ad4d0b, 0xad65da5e, 0xb0878cef, 0x11259773, 0x0cd1cf56, 0xe3d257e5, 0xb4994d03, 0x10172bf4, 0x1de256b1, 0x0124b213, 0x52716919, 0x3dc0582d, 0x9c744d25, 0xdf20b34f, 0x6bb9fe4c, 0x19fc975d, 0x8d51da56, 0x72536785, 0x7361db02, 0x5b8cdb24, 0x39c89755, 0x6fa73fa0, 0x42704c79, 0x6baff0d8, 0x08cf0eba, 0x09ebbca9, 0x2dd773d9, 0x6a9d4c5f, 0xd6dd0172, 0xdf36bddb, 0x5ea0a64f, 0x566fa8f5, 0x4aa94c57, 0x2ce5cf5e, 0xea2fe5d8, 0xde120fc8, 0x46788301, 0x894f1bba, 0x250e73f7, 0x310799ef, 0x0de373d1, 0xe3c45971, 0x1df45825, 0xfa38ce2c, 0xef159627, 0x474a3f86, 0x466e8d95, 0xd2c3c09e, 0x625242e5, 0xda1ac0b0, 0x5f84145c, 0xee272aa0, 0x9958304e, 0x4342f0fe, 0xf6ff0fee, 0x994e3eda, 0xf7dbbdfd, 0x8c756845, 0xb48f4397, 0xa1a21b9c, 0x242ac1e4, 0x113399e7, 0x8d47d4c2, 0x7e94a647, 0x81801500, 0xd6cb0fe6, 0xa85fa9a1, 0x4ea1832f, 0x986a8cc9, 0x29dfbca1, 0x475c3112, 0xd3e7728d, 0x00160e94, 0xb97a3ed2, 0x08d9002e, 0x6e838db3, 0x62444c71, 0xa4986863, 0x30232bfc, 0xa5aad4e4, 0x35195803, 0x5679a661, 0xbc404d2d, 0xb1a33efc, 0x38fa2bd2, 0x5355db0a, 0xe6fe2a8e, 0xe6e8241a, 0xdb3e72a3, 0x053a73ff, 0x1cd0ea36, 0xf3c57c11, 0x38ec2546, 0xda0cce24, 0x2106bc8f, 0xc3f05979, 0x00000000, 0xc7ee9895, 0xeb0b57cb, 0xce05243c, 0x5343d59e, 0x6e958327, 0xea39eb4c, 0x20340008, 0x28fb0eb2, 0x665a8d9d, 0xcb3f57c3, 0x2110b21b, 0x7fb01454, 0x6360fe62, 0x2dc17d4d, 0xa1b41508, 0x91973ef4, 0xa090a71b, 0x94bb439f, 0xa849a735, 0x3111977b, 0x5f921ac8, 0xb5bdff10, 0x141fe48c, 0xcf3798bb, 0x0cc7c1c2, 0x677e3f8e, 0x4eb78dbb, 0xac41684d, 0xa97b1bb2, 0xb96c3046, 0x10012560, 0xde04015c, 0x81961b94, 0xc7f89601, 0x6768311a, 0xca1be5d0, 0x7a8a67ab, 0x9589ff18, 0xad73d4ca, 0x7fa61ac0, 0x30352568, 0x0408cf78, 0x243ccf70, 0x1409ea18, 0xe2e0eb62, 0x7e82a8d3, 0xd2d5ce0a, 0x152d580b, 0xef0398b3, 0x4b9bf0d0, 0x39de99c1, 0x8588da78, 0x041ec1ec, 0x4b8dfe44, 0x7a9c693f, 0x2cf3c1ca, 0xfe260fc0, 0xfa2ec0b8 +}, +{ +0x2d6403ba, 0x42cf3f06, 0x3ced3272, 0xa8b45cfb, 0x1c0bf510, 0x3af0f09c, 0xe2dc894c, 0x26fb058c, 0xcdb81e37, 0xfed77c5c, 0x43f74740, 0x7907b7dc, 0xe3e4f10a, 0x041d562f, 0x5ad99c39, 0x1b2e4fb8, 0x05252e69, 0xd3b37fe6, 0xfcd7e89d, 0x336f626b, 0x7f1a7532, 0xd5aebd08, 0x7e220d74, 0xde31bb3e, 0x650c42cc, 0xf470022c, 0xe6c1df63, 0xe7f9a725, 0xda2ced11, 0x7b07231d, 0xf8cabeb2, 0x3fd5def5, 0x364a4c02, 0x8e4f5977, 0x60296ca5, 0x1f331997, 0xf06d5403, 0x85d05f41, 0x0f825019, 0x8f772131, 0x6bb66a93, 0x5be1e47f, 0x9ae346d6, 0xd9140196, 0x8d77b5f0, 0x1e0b61d1, 0x98e3d217, 0x527e7688, 0xc03adaef, 0x9761820e, 0x8b6a771e, 0xe5f933e4, 0x611114e3, 0xaf91e653, 0xa60e74a4, 0x4c751759, 0x2a41b912, 0xe1e465cb, 0x4e758398, 0x86e8b3c6, 0xc6271801, 0x20e6c762, 0x7d1ae1f3, 0x14ac1fa1, 0x5ec4ca16, 0x4b50adf1, 0x30578eec, 0x23de2be5, 0x783fcf9a, 0xb8051575, 0x83cd9daf, 0x4f4dfbde, 0xdb149557, 0x0aa77e70, 0xe0dc1d8d, 0xdd0957b9, 0x7685e7c5, 0x5ffcb250, 0x2b79c154, 0x3dd54a34, 0x7c2299b5, 0x49503930, 0x39c81c1b, 0x6634ae4b, 0x020094c1, 0xd1b3eb27, 0x6e9344fa, 0x16ac8b60, 0x58d908f8, 0x2c5c7bfc, 0x94596e89, 0xb19a8782, 0xbf20afdd, 0xc9a54818, 0xdf09c378, 0x507ee249, 0x1d338d56, 0xf5487a6a, 0xbc18435a, 0x51469a0f, 0xa7360ce2, 0x22e653a3, 0x00000000, 0x0eba285f, 0xaab4c83a, 0x69b6fe52, 0xaea99e15, 0xcc806671, 0xb787456c, 0xd08b9361, 0xa98c24bd, 0x10b1498e, 0xd28b07a0, 0xab8cb07c, 0x71a05d6d, 0x47ea116f, 0xd696518f, 0xa5369823, 0xf748eeab, 0xf26dc0c2, 0xcba5dcd9, 0x3bc888da, 0x08a7eab1, 0x46d26929, 0x87d0cb80, 0xcfb88af6, 0xc102a2a9, 0x63118022, 0x904438a6, 0x3eeda6b3, 0xb6bf3d2a, 0x917c40e0, 0x27c37dca, 0x2f64977b, 0x25c3e90b, 0x5463b466, 0xa213228b, 0x6c93d03b, 0x7298b1ea, 0xf67096ed, 0x74857304, 0x9bdb3e90, 0x0338ec87, 0xed5ed955, 0x555bcc20, 0xc3023668, 0x01387846, 0xb2a26b05, 0xc4278cc0, 0x192edb79, 0xef5e4d94, 0x29795595, 0xa12bce0c, 0xbd203b1c, 0xd82c79d0, 0x937cd421, 0x061dc2ee, 0xfdef90db, 0xad917292, 0x41f7d381, 0xc23a4e2e, 0x344ad8c3, 0x81cd096e, 0xaca90ad4, 0x9efe10f9, 0x7a3f5b5b, 0x9659fa48, 0xe87bf73c, 0x37723444, 0x6daba87d, 0x099f92f7, 0x0b9f0636, 0x40cfabc7, 0xf1552c45, 0x6a8e12d5, 0xc71f6047, 0x4d4d6f1f, 0x6229f864, 0x9fc668bf, 0x38f0645d, 0x1389a509, 0xea7b63fd, 0x24fb914d, 0x2e5cef3d, 0x82f5e5e9, 0x9244ac67, 0x0d82c4d8, 0xba0581b4, 0xc51ff486, 0xa40ee065, 0x7098252b, 0x0cbabc9e, 0x896ae3df, 0x0725baa8, 0x5cc45ed7, 0x688e8614, 0xb0a2ffc4, 0x670cd60d, 0x8c4fcdb6, 0xca9da49f, 0x9cfe8438, 0x44d2fde8, 0x956116cf, 0x1816a33f, 0xa32b5acd, 0x575b58e1, 0xd7ae29c9, 0x159467e7, 0x48684176, 0xd496c54e, 0x6fab3cbc, 0x9dc6fc7e, 0xe4c14ba2, 0xe9438f7a, 0x77bd9f83, 0xfbf25235, 0xec66a113, 0x64343a8a, 0xeb431bbb, 0x1794f326, 0x88529b99, 0xee6635d2, 0xb93d6d33, 0x12b1dd4f, 0x75bd0b42, 0xffef041a, 0xdc312fff, 0x3572a085, 0x45ea85ae, 0xf355b884, 0xa013b64a, 0x5dfc2691, 0x99dbaa51, 0xf9f2c6f4, 0x118931c8, 0xb4bfa9eb, 0xbe18d79b, 0xfaca2a73, 0xbb3df9f2, 0x4a68d5b7, 0x316ff6aa, 0x84e82707, 0x80f57128, 0x1a1637fe, 0xb587d1ad, 0xb39a1343, 0x21debf24, 0x28412dd3, 0x8a520f58, 0x566320a7, 0x53460ece, 0x73a0c9ac, 0x32571a2d, 0xc89d305e, 0x59e170be, 0xce80f2b0 +}, +{ +0x968af8eb, 0xd2acdb0f, 0x271ae8bc, 0xe0e53a13, 0x08d0c325, 0xc0e9dde4, 0xfdab2d3f, 0x14d89a2d, 0x97016b66, 0x4db0aee5, 0xb1901057, 0xa25e8531, 0x64e719ba, 0x2957b75f, 0x0e4d5fe3, 0x28dc24d2, 0xef23f67d, 0x6c37da9f, 0xc8f4c368, 0xc7ffd2af, 0x018b938d, 0x78229d1b, 0x155309a0, 0x45606dc0, 0x355fee57, 0xe835f936, 0xb01b83da, 0x83142ce2, 0xb15dcdfe, 0xc8391ec1, 0xf43da03e, 0x0650416f, 0xe7f33558, 0xd3ea952b, 0x2e41b814, 0xe028e7ba, 0x3c04beff, 0xefee2bd4, 0x4a6b7c07, 0xb64bc2b5, 0x76a21f51, 0x642ac413, 0x42bbbf22, 0xfabd2274, 0x00cddda9, 0xf3e672dc, 0x6aaa4659, 0xbf10921d, 0xdce184ec, 0x84cffe00, 0x70f25e3e, 0x63f116f1, 0xad5594f6, 0x5eb3e62a, 0x65a1579e, 0xf32baf75, 0x1288db42, 0xa3d516bc, 0x7ebf01dd, 0x1c085908, 0x994c3485, 0x77e45175, 0xe678a6d5, 0x3a54ff90, 0xc1af93c0, 0x07160f4b, 0x1bd38bea, 0xa2935898, 0x069d9cc6, 0x8b09326e, 0xd26106a6, 0x359233fe, 0x130348cf, 0x3419a073, 0x0e80824a, 0x27d73515, 0x2811f97b, 0x5663250f, 0x3249e11c, 0x7964d33f, 0x2fca2b99, 0xd43147c9, 0xbe9b0190, 0x6a679bf0, 0x159ed409, 0xb98d0edb, 0x8c1f3d25, 0x582e7aec, 0xc9b28d4c, 0x6b21d5d4, 0x1cc584a1, 0x8bc4efc7, 0x9f1c75ea, 0xdda7cac8, 0x633ccb58, 0x5f3875a7, 0x1d4e172c, 0x840223a9, 0x1a581867, 0x5ff5a80e, 0x50feb9c9, 0x7f349250, 0x2187747a, 0x43fdf106, 0xe9be6abb, 0x32843cb5, 0x71b4101a, 0xe16ea99e, 0x07dbd2e2, 0x081d1e8c, 0x299a6af6, 0x442623e4, 0xa4c319f7, 0x766fc2f8, 0xa318cb15, 0x8d94aea8, 0x50336460, 0x330faf38, 0x124506eb, 0x83d9f14b, 0x62b758d5, 0x3b12b1b4, 0x8cd2e08c, 0xab05d599, 0xaa8e4614, 0xdbf78ba7, 0x703f8397, 0xce695fae, 0xb70d8c91, 0xbe56dc39, 0x3bdf6c1d, 0x214aa9d3, 0xf57bee1a, 0x90dab984, 0xdab1c583, 0x14154784, 0x43302caf, 0x96472542, 0x34d47dda, 0x78ef40b2, 0xa40ec45e, 0xcf2f118a, 0x59a5e961, 0x33c27291, 0x97ccb6cf, 0x1a95c5ce, 0xc1624e69, 0x3d8f2d72, 0x4b2d3223, 0xfb36b1f9, 0x5e7e3b83, 0xda7c182a, 0xcea48207, 0xd57709ed, 0x9e5a3bce, 0xa58557d3, 0x45adb069, 0xf2a03cf8, 0xc6b99c8b, 0x58e3a745, 0xdc2c5945, 0xb6861f1c, 0xe973b712, 0x56aef8a6, 0x13ce9566, 0x3cc96356, 0x3a992239, 0xd4fc9a60, 0x77298cdc, 0xb7c05138, 0x656c8a37, 0xb8cb40ff, 0xaa439bbd, 0xfd66f096, 0x0f0b11c7, 0xfbfb6c50, 0x6bec087d, 0x627a857c, 0xcfe2cc23, 0x00000000, 0xe8f8249f, 0x4be0ef8a, 0x01464e24, 0x1d83ca85, 0x829fbf6f, 0x6dbc4912, 0x0fc6cc6e, 0xad98495f, 0x20c13a5e, 0x265ca698, 0xfced631b, 0xac13dad2, 0x3d42f0db, 0x1b1e5643, 0x4d7d734c, 0x2e8c65bd, 0x095b50a8, 0xbfdd4fb4, 0x51b8f7ed, 0x26917b31, 0x91512a09, 0xc7320f06, 0x200ce7f7, 0xacde077b, 0xdd6a1761, 0x51752a44, 0x596834c8, 0x6cfa0736, 0x9fd1a843, 0x7e72dc74, 0xe1a37437, 0xe6b57b7c, 0x85446d8d, 0x919cf7a0, 0x980a7aa1, 0xabc80830, 0x8a4f7c4a, 0xd3274882, 0x7ff94ff9, 0x7179cdb3, 0x98c7a708, 0xc97f50e5, 0x2f07f630, 0xb0d65e73, 0x9981e92c, 0xdb3a560e, 0x4aa6a1ae, 0x57e8b682, 0xb8069d56, 0x8d597301, 0xe73ee8f1, 0xc6744122, 0xd5bad444, 0xb940d372, 0x8589b024, 0xa5488a7a, 0x6d7194bb, 0x9017642d, 0x825262c6, 0xf4f07d97, 0x09968d01, 0x57256b2b, 0x4c3b3d68, 0xfa70ffdd, 0x79a90e96, 0xee65b859, 0xf5b633b3, 0xeea865f0, 0xc024004d, 0xf26de151, 0x8a82a1e3, 0x4276628b, 0x44ebfe4d, 0x9e97e667, 0x4cf6e0c1, 0xfc20beb2 +}, +{ +0xfa150533, 0x13ccae39, 0x23a646c2, 0xb0c19495, 0xc9ba6c81, 0x24bf3806, 0x5d4de2ed, 0xb30415dc, 0x6c1793ce, 0x87b202aa, 0x12fc37e1, 0x1799734b, 0xdf138612, 0x4cfd76ba, 0x9192cac6, 0x056544aa, 0xa041991a, 0xfe40d841, 0x4ad491a6, 0x4f38f7f3, 0xdb465b60, 0xa758e7de, 0xee49f731, 0x97320f25, 0x82d74600, 0x9367d257, 0xde231fca, 0x6ee28b5f, 0xb1f10d4d, 0x6e6ba9a0, 0x7da70799, 0xdc5f25a4, 0x6ab7562d, 0x10092f70, 0x90a2531e, 0x21da7cac, 0x5addbed6, 0xa6e15cf9, 0x2063c78b, 0xb1782fb2, 0xda76c2b8, 0x02f51891, 0xa5adff4f, 0xdaffe047, 0x4b6d2a81, 0x6f5b3078, 0x11b09457, 0x171051b4, 0x6dae28e9, 0xecbcefa0, 0x797bf814, 0x7f521f08, 0x6b0eed0a, 0x013099d8, 0x86829b72, 0xcaf6cf37, 0x33264b4d, 0x14d5d0fd, 0x31d353dc, 0x145cf202, 0x5cf459ca, 0x24361af9, 0x343f3589, 0x350fac51, 0x027c3a6e, 0x06a0c5e3, 0xdd6fbc7c, 0x860bb98d, 0xa3841853, 0x5e8863a4, 0xfb259ceb, 0x5bed270e, 0x847783e3, 0xdbcf799f, 0x0455dd72, 0xea9508bc, 0x4be4087e, 0x7c979e41, 0xb52df2c0, 0xfff96366, 0x92574b8f, 0x93eef0a8, 0x034ca3b6, 0x836efd27, 0x5a549c29, 0x329ff06a, 0x7c1ebcbe, 0xec35cd5f, 0xcdefb1f3, 0x2296df1a, 0x27f39bb0, 0x6a3e74d2, 0xb49449e7, 0x48218937, 0x69fbf59b, 0x7eeba42f, 0x784b61cc, 0x0629e71c, 0x33af69b2, 0xcb4f7410, 0x491110ef, 0x68cb6c43, 0xdf9aa4ed, 0x94f78e6c, 0x34b61776, 0xa524ddb0, 0xcf1aa962, 0x873b2055, 0x7a375ba2, 0x85471a3b, 0xc88af559, 0xfec9fabe, 0x4dcdef62, 0x5f31d883, 0xa6687e06, 0x6fd21287, 0x84fea11c, 0xa49d6697, 0x4e814cd4, 0xcbc656ef, 0x79f2daeb, 0xa1f8223d, 0x10800d8f, 0xdcd6075b, 0x221ffde5, 0xd9b343f1, 0xeec0d5ce, 0xd80af8d6, 0x78c24333, 0x36ca2d18, 0x20eae574, 0xf9d0847a, 0xa17100c2, 0xcea31245, 0x6c9eb131, 0xb6615176, 0xdde69e83, 0xfbacbe14, 0xfc3ce22f, 0x315a7123, 0xd883da29, 0xe8e932d2, 0x5e01415b, 0xa4144468, 0xc803d7a6, 0xcc560ad4, 0x960296fd, 0x59183f9f, 0x5b6405f1, 0xfd855908, 0x30e3ca04, 0x04dcff8d, 0x1275151e, 0x968bb402, 0xe95089f5, 0x5dc4c012, 0xa23da374, 0x00000000, 0xe860102d, 0x5fb8fa7c, 0x902b71e1, 0x49983210, 0x4a5db359, 0x819be5b6, 0xb751c8ae, 0x37fab4c0, 0xf8693f5d, 0x3216d295, 0x911be839, 0x21535e53, 0x7fdb3df7, 0xfd0c7bf7, 0xcf938b9d, 0xa7d1c521, 0x95c717b4, 0x01b9bb27, 0x36430fe7, 0x825e64ff, 0x3773963f, 0xa2b4818b, 0xb41d6b18, 0x7b8ee085, 0xb048b66a, 0xca7fedc8, 0x4d44cd9d, 0xb2bdaefb, 0x7e6286d0, 0x156c6bda, 0xeb2cb39b, 0x232f643d, 0x03c58149, 0x68424ebc, 0x13458cc6, 0x4e086e2b, 0x277ab94f, 0xdeaa3d35, 0xce2a30ba, 0x5828a647, 0xe9d9ab0a, 0xff704199, 0xb2348c04, 0x15e54925, 0xed055487, 0x6b87cff5, 0x4fb1d50c, 0xfa9c27cc, 0x6972d764, 0xa0c8bbe5, 0xa30d3aac, 0xeba59164, 0x25068321, 0x97bb2dda, 0xb6e87389, 0xea1c2a43, 0xf959a685, 0x8112c749, 0x5c7d7b35, 0x05ec6655, 0x258fa1de, 0x264a2097, 0x80ab7c6e, 0x07197ec4, 0xb7d8ea51, 0xd93a610e, 0xb38d3723, 0x16a9ea93, 0x4c745445, 0x35868eae, 0xb5a4d03f, 0xeff04c16, 0xccdf282b, 0x07905c3b, 0x1620c86c, 0x7abe795d, 0x947eac93, 0x306ae8fb, 0x92de6970, 0xfcb5c0d0, 0x008922ff, 0x59911d60, 0xcd66930c, 0x48a8abc8, 0x7b07c27a, 0x6d270a16, 0xc9334e7e, 0x80225e91, 0x954e354b, 0x26c30268, 0x58a184b8, 0x1139b6a8, 0xed8c7678, 0xef796ee9, 0x7d2e2566, 0x83e7dfd8, 0x85ce38c4, 0xf8e01da2 +}, +{ +0x73ba1071, 0xa57aafc7, 0x6d77d54c, 0x8d8eec3d, 0xf8c7df04, 0x3650b6d2, 0xdd33065c, 0xbfa8cb96, 0x431985eb, 0xc17b7150, 0x69014435, 0x17d2fef3, 0x3b391c65, 0xd92ca730, 0xf742f797, 0x77a5b11d, 0x322627ab, 0x7520032c, 0x9a3522db, 0x975c886c, 0x28f443fa, 0x363986c7, 0x8f626e19, 0x47062487, 0xeb63b08e, 0xca88c8ba, 0xc564d03c, 0xc397f374, 0x476f1492, 0xd4450d87, 0x8b7dcf75, 0xbd2d79a7, 0xed9093c6, 0x8de7dc28, 0x7aa52bbf, 0xf5c745a6, 0x2a18c1de, 0x93432900, 0x95b00a48, 0x6468ee82, 0xbbde5aef, 0x6b84f604, 0xe6632a2c, 0x564ec929, 0xcefe59c3, 0xbbb76afa, 0xb4324269, 0x1ad26451, 0x7c5608f7, 0x820bc4ae, 0x236eca05, 0xc80d7a8b, 0xe48fa808, 0xe0f93971, 0x02ec8224, 0x289d73ef, 0x1c214719, 0x6d1ee559, 0x601e7ffb, 0xf72bc782, 0x6bedc611, 0xb2c16121, 0x39bcae54, 0x9e43b3a2, 0xfcd87e68, 0x1121ddbb, 0x0f852893, 0x5627f93c, 0x80e7468a, 0x69687420, 0x41f507cf, 0x2a71f1cb, 0x62f2fddf, 0x30caa58f, 0x0d009aa2, 0xe215bb55, 0xc1124145, 0x6f9b5768, 0x932a1915, 0xef1521f7, 0xc3fec361, 0xe0900964, 0xd2df1eda, 0x4a6f8e30, 0x00693015, 0xe98f32aa, 0xd9459725, 0x0285b231, 0x7849a99b, 0x34bc34f6, 0x98d9a0ff, 0x59a2d1af, 0x13cd5f9f, 0xdbc02514, 0xfcb14e7d, 0x66ed5cb3, 0x09760bdb, 0x27716b69, 0x21eb7834, 0x808e769f, 0x5dbd70c3, 0x30a3959a, 0xd6c0bfb6, 0xa1650eab, 0x6ff2677d, 0xfa2b5d20, 0x59cbe1ba, 0x9e2a83b7, 0x06f32348, 0x4370b5fe, 0x71569255, 0x54cb7b18, 0x861465c2, 0xc7e1620d, 0x867d55d7, 0x1857d660, 0x45eaa6a3, 0xb2a85134, 0x48830c14, 0x3da30f38, 0x041fa16c, 0x15574cc2, 0xf1d8e4ca, 0xfa426d35, 0x27185b7c, 0x1ea4f528, 0x259de94d, 0xbd4449b2, 0xf1b1d4df, 0x52385850, 0xdd5a3649, 0xa3e0bc9a, 0xb6dec04d, 0x04769179, 0xaaff8754, 0xa10c3ebe, 0xfe34fc4c, 0x5b4e538b, 0x9a5c12ce, 0xa87a3565, 0x3f4f8d1c, 0x54a24b0d, 0xa7962de3, 0xb044d310, 0x7acc1baa, 0xeb0a809b, 0xef7c11e2, 0xfe5dcc59, 0xe27c8b40, 0x5dd440d6, 0x9caf3186, 0x7ed3bac6, 0xd6a98fa3, 0x4a06be25, 0x2307fa10, 0xd2b62ecf, 0xac0ca41c, 0x9735b879, 0x069a135d, 0xf8aeef11, 0x8f0b5e0c, 0x3b502c70, 0x458396b6, 0xb932d8cb, 0x50bdea61, 0xc50de029, 0xa8130570, 0xaee02638, 0x50d4da74, 0x21824821, 0x89914d51, 0x2c82d283, 0xb6b7f058, 0xd0339cfe, 0x95d93a5d, 0xce9769d6, 0xaa96b741, 0x0b9a89ff, 0x98b090ea, 0x52516845, 0x3dca3f2d, 0x1abb5444, 0x8491d7f3, 0x9cc60193, 0x6401de97, 0x2e0760b2, 0x324f17be, 0x17bbcee6, 0x5f51f2e7, 0x5f38c2f2, 0x0fec1886, 0x4cf59d6d, 0x7c3f38e2, 0x48ea3c01, 0xf35d56fb, 0x75493339, 0xc7885218, 0xb45b727c, 0xac659409, 0x713fa240, 0xa7ff1df6, 0x91c69b31, 0x5b27639e, 0xe60a1a39, 0x2e6e50a7, 0x13a46f8a, 0xd42c3d92, 0x183ee675, 0x419c37da, 0x25f4d958, 0x8262f4bb, 0x91afab24, 0x84f8e7e6, 0xf33466ee, 0xcae1f8af, 0x73d32064, 0x629bcdca, 0x2cebe296, 0xb95be8de, 0x153e7cd7, 0x4e702f5c, 0x89f87d44, 0x34d504e3, 0xcc12dbe7, 0x4c9cad78, 0x1ecdc53d, 0xae89162d, 0x7820998e, 0xedf9a3d3, 0x4e191f49, 0x1148edae, 0x7eba8ad3, 0xe9e602bf, 0xc8644a9e, 0x39d59e41, 0xa5139fd2, 0xdfdf8478, 0x1c48770c, 0xa3898c8f, 0xf5ae75b3, 0x8b14ff60, 0xcc7bebf2, 0x3f26bd09, 0xdba91501, 0xbfc1fb83, 0x00000000, 0xe4e6981d, 0x60774fee, 0x77cc8108, 0x0d69aab7, 0x66846ca6, 0x0bf3b9ea, 0xb02de305, 0xdfb6b46d, 0x091f3bce, 0xd05aaceb +}, +{ +0xe701da05, 0x3c635fd9, 0x6dbc8836, 0x8f8e10b2, 0x94940136, 0x5fe7ca6f, 0x81d76b7b, 0xacf07d41, 0xd13cddbb, 0xa2c860c1, 0xd008bc94, 0xa2a90688, 0xa89638a6, 0xb2b8480d, 0x00616649, 0x6783b618, 0x45c9bac4, 0x90932298, 0x7395db33, 0x00000000, 0xf81ce82f, 0x8edb17d4, 0x9eab3f18, 0x0a5e5867, 0x287532f2, 0x9bf91bd0, 0x0b6a3948, 0xe306f9ab, 0xc019f211, 0x15220c04, 0x27182814, 0x76a699b2, 0xa9c33fc0, 0x7792f89d, 0x1f7c5463, 0x55b99208, 0xf242b048, 0x294153dd, 0x323a2410, 0xdf04c03b, 0xc52ab090, 0xfc7aadc8, 0x1f1d322a, 0xda56e4f3, 0x365c61f7, 0x789e8432, 0x8fef76fb, 0x5f86ac26, 0x69dacdd1, 0x4ac5c66b, 0xe654dd63, 0xc14cf577, 0x85d048d5, 0x6c88e919, 0xc47fb7f6, 0x39317b11, 0xed3ee42b, 0x39501d58, 0xbc80558d, 0xa3fc01ee, 0x10114e85, 0xb9d27145, 0xadc41c6e, 0x114449e3, 0xf7109480, 0xa79a4409, 0x107028cc, 0x11252faa, 0xa9a25989, 0x231f0bba, 0xf376d167, 0xa6cf436f, 0x325b4259, 0x37096691, 0x68eeacfe, 0xa8f75eef, 0x90f244d1, 0x224a0cdc, 0x237e6df3, 0x67e2d051, 0xd55a985c, 0x1a2e70ab, 0xc54bd6d9, 0xf223d601, 0x44fddbeb, 0x2d27163a, 0xf949ef49, 0x262c493b, 0x78ffe27b, 0xb2d92e44, 0x688fcab7, 0x5b818f88, 0x8eba719d, 0xb78b0a8c, 0xce4089d8, 0x2c137715, 0xca47aa76, 0xdf65a672, 0x5be0e9c1, 0x5ed3ab40, 0xde51c75d, 0xe2329884, 0xcf158ebe, 0x1e295305, 0xbce133c4, 0x38647c77, 0xcb12ad10, 0x7dadc6b3, 0x79aae51d, 0xc41ed1bf, 0x84e429fa, 0x055224c8, 0x29203594, 0x0f6d1ae6, 0x264d2f72, 0x66d6b17e, 0x63e5f3ff, 0xb7ea6cc5, 0x62b0f499, 0x3d3658bf, 0x638495b6, 0xe760bc4c, 0x9acd7aff, 0x0f0c7caf, 0x69bbab98, 0xa6ae2526, 0xcb73cb59, 0xe253fecd, 0xf87d8e66, 0xec6be34d, 0x55d8f441, 0xb3ed4f6b, 0x54ec956e, 0xb8877623, 0x1b7b77cd, 0x376800d8, 0x449cbda2, 0x4ea3838c, 0x508ad089, 0xf9288900, 0x0b0b5f01, 0x27794e5d, 0xdb6285dc, 0xe939c785, 0xec0a8504, 0xf64593e6, 0x9aac1cb6, 0x05334281, 0xe80da6aa, 0xcf74e8f7, 0xdb03e395, 0x2c72115c, 0x0a3f3e2e, 0x7dcca0fa, 0x046645e7, 0x9ffe387e, 0xfc1bcb81, 0xda3782ba, 0x6dddee7f, 0x8adc347a, 0xf771f2c9, 0x72c0dc55, 0x8b89331c, 0xb8e6106a, 0x4bf1a744, 0x73f4bd7a, 0xb9b3170c, 0xd40f9f3a, 0x62d192d0, 0x50ebb6c0, 0x7cf8c1d5, 0xe86cc0e3, 0x45a8dc8d, 0x15436a4d, 0x9eca5951, 0x80e30a54, 0xb38c2922, 0x0e597bc9, 0x330e453f, 0x336f2376, 0x95a06019, 0xd15dbbf2, 0x41afff23, 0x1b1a1184, 0x8abd5233, 0xf317b72e, 0xe958a1cc, 0xbdd552eb, 0x77f39ed4, 0x38051a3e, 0x6ce98f50, 0xde30a114, 0x01550766, 0xfd4ecce7, 0x41ce996a, 0x51dfd7ef, 0x51beb1a6, 0x91c625fe, 0x5eb2cd09, 0xce21ef91, 0x66b7d737, 0xc12d933e, 0x040723ae, 0x2d467073, 0x4b90c10d, 0x40faf845, 0x1e48354c, 0x85b12e9c, 0x3d573ef6, 0x4f97e2a3, 0x76c7fffb, 0x281454bb, 0x5ab5eea7, 0x548df327, 0x0134612f, 0xb6de0dea, 0x9b987d99, 0x14770b62, 0xb6bf6ba3, 0x363d07be, 0xa39d67a7, 0xac911b08, 0x91a743b7, 0xe635bb2a, 0xed5f8262, 0x409b9e0c, 0xd46ef973, 0xe3679fe2, 0xd53bfe15, 0xfd2faaae, 0x79cb8354, 0x81b60d32, 0x9f9f5e37, 0x14166d2b, 0x95c10650, 0x80826c1d, 0x8be85555, 0x84854fb3, 0xca26cc3f, 0x4ff684ea, 0xc0789458, 0xa7fb2240, 0x7c99a79c, 0xd069dadd, 0x4aa4a022, 0x3c023990, 0xbdb434a2, 0x1a4f16e2, 0xada57a27, 0x4ec2e5c5, 0x94f5677f, 0xf624f5af, 0x222b6a95, 0x72a1ba1c, 0x0e381d80, 0x5ad488ee +}, +{ +0x81a328ce, 0x2b8d4cc3, 0x93d56426, 0x700f801e, 0x23acf5ad, 0x53a375b3, 0xee57bfe7, 0x99c1b096, 0xcac18fb3, 0xe1ef89e6, 0x9bf4dd48, 0x0ab79e26, 0x0f1b7c97, 0x4bc1edeb, 0x2e82e4e4, 0x8eb85459, 0xd2a317eb, 0x9143436e, 0x9e583ff9, 0x18629858, 0x4957caa3, 0xba6d453b, 0xe379aeae, 0x3bce6df5, 0xe6d54c1f, 0x96798697, 0x0d2e1149, 0x417673cd, 0x782e3970, 0x26a35d8a, 0x5196186d, 0x6f57ddbf, 0x6a587598, 0xd8b7c35b, 0xa81b09d3, 0x3b6d2763, 0x2c14c3ac, 0xe4436b57, 0x560f9702, 0x5914eb95, 0xf98d11be, 0x6ff49729, 0xf4004a61, 0x5cb80924, 0x02356dde, 0x59b7a103, 0x94efa1df, 0xb7e01ee4, 0x29b8211d, 0x91e009f8, 0x31dab945, 0x2600171c, 0xaf21cc2a, 0x81006258, 0x8c2e7311, 0x1ffb1737, 0xf92e5b28, 0x10432136, 0xcfce2794, 0xa20fdd63, 0xaa8d2e9b, 0x43431e13, 0xc2437c4b, 0x05ace2b1, 0xbace0fad, 0xa7007544, 0x2cb7893a, 0x12d5067e, 0x34765bf4, 0x6279ccf6, 0xfb1b36f6, 0x07998f6f, 0x677664d1, 0x3e628f44, 0x604ca128, 0x34d51162, 0x24357ac2, 0x39584abd, 0x464cb634, 0x60efebbe, 0x4c586284, 0xeb5817c0, 0xd03530a3, 0x93762eb0, 0xda82ae85, 0xcf6d6d02, 0xdf8d06a2, 0xbf62ed1c, 0x9c6d5227, 0x4b62a77d, 0x2b2e0655, 0xbdf4ca54, 0x3cf4a80c, 0x8bb7fc7e, 0xcd5800dc, 0x70acca88, 0xd81489cd, 0xd53a9884, 0xaf8286bc, 0xfc21f30f, 0xec62d239, 0x3c57e29a, 0x56acdd94, 0xb0dadb1d, 0xe4e021c1, 0x10e06ba0, 0xf63527bf, 0xb079918b, 0x0821b96e, 0x7d82dbc1, 0x17daae59, 0xc0761195, 0x68ce52d0, 0x3179f3d3, 0xf33a8f98, 0xb24cfc55, 0x7fb7b61f, 0x5e2e2e6c, 0x44da917c, 0xf6966d29, 0xa03ab0bd, 0xc2e036dd, 0xe14cc370, 0x1779e4cf, 0xf1aca8d0, 0x7ab81e38, 0xda21e413, 0xe6760689, 0xca62c525, 0xd2005d7d, 0xf4a300f7, 0x3ec1c5d2, 0x36e07cbc, 0xb5d5733a, 0x073ac5f9, 0xc857a8fb, 0xc5daf324, 0x230fbf3b, 0x1af4bf10, 0x686d1846, 0x49f48035, 0xbd5780c2, 0xecc198af, 0x41d5395b, 0x67d52e47, 0xb2efb6c3, 0x65e04399, 0x0882f3f8, 0xad14a1f4, 0xb7435472, 0x24963054, 0xa099fa2b, 0x543afadc, 0xadb7eb62, 0x12764ce8, 0x7d219157, 0x7299a756, 0xc8f4e26d, 0x5499b04a, 0x773545e7, 0x46effca2, 0x18c1d2ce, 0xfeb7d447, 0x4e6d0f5a, 0xdf2e4c34, 0xd7acbfcc, 0xfc82b999, 0x0d8d5bdf, 0xc0d55b03, 0x7a1b54ae, 0x6543090f, 0x1d6d307f, 0x9cce18b1, 0x21999873, 0x9962fa00, 0xd599d212, 0xa596520c, 0x944ceb49, 0xcdfb4a4a, 0x6dc1faf7, 0x291b6b8b, 0x5c1b43b2, 0x62da8660, 0x02962748, 0xdd1b21ea, 0x53003f25, 0x8b14b6e8, 0x43e05485, 0x1f585da1, 0xfe149ed1, 0x33efd49b, 0x334c9e0d, 0x4479dbea, 0xbfc1a78a, 0xf10fe246, 0xf399c50e, 0x6afb3f0e, 0x4cfb2812, 0x5e8d64fa, 0x39fb002b, 0x0fb83601, 0x8921db36, 0x83964510, 0x513552fb, 0x863aa7a1, 0x898291a0, 0xb85828e5, 0xc74cd46c, 0x8699ed37, 0x75002839, 0x7f14fc89, 0x5b82ccdd, 0x96dacc01, 0x154c8911, 0x050fa827, 0xe96d7a1e, 0x9b5797de, 0xddb86b7c, 0x5b21864b, 0x0a14d4b0, 0xa8b84345, 0x83350f86, 0x723aedc0, 0x788d73e6, 0xa2ac97f5, 0x00000000, 0xd0967a35, 0x2e21ae72, 0x213ad2e5, 0xebfb5d56, 0xeef4f571, 0x84ac80e9, 0xc7ef9efa, 0x8c8d3987, 0xc579b9b2, 0xe9ce3088, 0xfbb87c60, 0x77960f71, 0x8e1b1ecf, 0x6d62b061, 0x15efc387, 0xb57639ac, 0x75a362af, 0x840fca7f, 0xa7a33fd2, 0xaa2e640d, 0xd70ff55a, 0x9efb756f, 0x3643362a, 0xb8fb6273, 0x1a57f586, 0xa535189a, 0x1dce7ae9, 0xe3dae438, 0x4ece45cc, 0x00a34a96 +}, +{ +0x173bb5af, 0xf8f0e005, 0xaa959431, 0x09f44cd8, 0xc16246f7, 0xba8109ac, 0x83708687, 0x2eca3a84, 0x0710ec33, 0x6cd8faf4, 0xd8de7a6a, 0xe8e47d98, 0x27629b84, 0x75382bb1, 0xf648ad36, 0x09a8a100, 0x4b85a571, 0xffbce1ee, 0x6ce73ef5, 0x2701b25d, 0x5baefced, 0xc611831d, 0xdfadbf80, 0xdf927b81, 0x37760619, 0xb329a8ac, 0x170471ae, 0x19df1544, 0xb3166cad, 0xf104acdd, 0x72170383, 0x09cb88d9, 0x5b9138ec, 0xbdae219e, 0x005cedd8, 0xc62e471c, 0x17675877, 0x3066ea2a, 0x2ef5fe85, 0xd176db6a, 0xefa87c73, 0x7bbfa283, 0x625f73c6, 0x0edb64ea, 0x5c81d4df, 0xd6051e80, 0xf61440ee, 0x372aebc1, 0x7be34f5b, 0xa35e1ce8, 0xe1103140, 0xd88297b2, 0xf8cf2404, 0x5cbe10de, 0x8dc8cbb4, 0x2e96d75c, 0x2ea9135d, 0xe8875441, 0xbdf2cc46, 0xaaaa5030, 0x6260b7c7, 0x7caf4eb0, 0x9dbf7ff0, 0x9338f6c2, 0xff8325ef, 0x843c876c, 0xd12a36b2, 0xd8e1be6b, 0x0e878932, 0x8abb0e5e, 0xf13b68dc, 0x0ee4a0eb, 0x65705bf4, 0x20115e6e, 0x1ecff977, 0xe8b89040, 0x9accba1a, 0xad857802, 0x424e2da8, 0x4bd948a9, 0x4caa8d43, 0x623c5a1f, 0xe8dbb999, 0x0773c5ea, 0x9474f729, 0x39f18f2b, 0x8ad82787, 0x3749c218, 0x4561059a, 0xf62b84ef, 0x10487045, 0x273e765c, 0xefcb55aa, 0x55759807, 0x554a5c06, 0x832c6b5f, 0xbd91e59f, 0xb439449f, 0x9417def0, 0x422d0471, 0xeff491ab, 0x6b94fb1f, 0x5516b1de, 0xc8cae7f7, 0x17589c76, 0xd659f358, 0x29863b6f, 0x5ce2fd06, 0xbadde474, 0x6c84172c, 0xf893c9dc, 0xc64d6ec5, 0x1077b444, 0x552975df, 0x1eacd0ae, 0xd63ada81, 0xaac979e9, 0x072f2832, 0x62039e1e, 0x39ad62f3, 0x4bba6170, 0xadd995da, 0x834f4286, 0x455ec19b, 0xb34a8175, 0x84606ab4, 0x8ae7e386, 0x8dabe26d, 0x7507efb0, 0x6bc816c7, 0x6bf7d2c6, 0x7ccc6769, 0xf6776937, 0xbdcd0847, 0x654f9ff5, 0x7cf3a368, 0x09976501, 0xc672aac4, 0x523999ec, 0xe14cdc98, 0x652cb62c, 0xaaf6bde8, 0x755b0268, 0x102b599c, 0xdff15258, 0xe600dd73, 0x7c908ab1, 0x72742a5a, 0xade651db, 0x207277b7, 0x202e9a6f, 0xbabecdad, 0xf1584105, 0x074c01eb, 0x9aaf93c3, 0x8403436d, 0x93641b1a, 0xc8a9ce2e, 0xe65c30ab, 0xffdfc837, 0x3e824ac1, 0x9a9057c2, 0x4c954942, 0x4be68ca8, 0x453de842, 0xd115f2b3, 0xf1678504, 0x3edea719, 0x9af37e1b, 0x4cf6609b, 0x29b9ff6e, 0x3ebd8ec0, 0xe663f4aa, 0x6bab3f1e, 0x1e9314af, 0xcfe5cfc5, 0xf8ac0ddd, 0x8a84ca5f, 0x7228c782, 0xcf86e61c, 0xc8f523f6, 0x003fc401, 0xdfce9659, 0x8313af5e, 0x006329d9, 0x1ef03d76, 0x204db3b6, 0x4212c070, 0x45022c43, 0xb465a947, 0xe12ff541, 0x1983f89c, 0xd6663759, 0x94281af1, 0x9ddc5629, 0x4cc9a49a, 0x7564c669, 0x944b3328, 0x19e0d145, 0x3992a6f2, 0xcfb9221d, 0xa42dd902, 0x10149d9d, 0x6cbbd32d, 0x29dad6b7, 0xcfda0bc4, 0xc8960a2f, 0xd8bd53b3, 0x724bee5b, 0xadbabc03, 0xa302f130, 0x00000000, 0x37152fc0, 0x5bf21135, 0x3005c3f3, 0x8df70fb5, 0xef97b872, 0xffe00c36, 0x525ab035, 0x0eb84d33, 0xb3754574, 0xa4121d03, 0x6513722d, 0xa47134da, 0x3ee16318, 0x7bdc8b5a, 0x29e512b6, 0x19bc3c9d, 0xbae22075, 0x303a07f2, 0xc1016f2e, 0x52065ded, 0xb406809e, 0x275d5f85, 0xe1731899, 0x9de39228, 0xd1491f6b, 0x39ce4b2a, 0x845faeb5, 0x5cdd3907, 0x8d94266c, 0x30592e2b, 0xc15d82f6, 0xa44ef0db, 0xc13eab2f, 0x4271e9a9, 0xa33d3531, 0x5bcdd534, 0x930732c3, 0x935bdf1b, 0x52657434, 0x7b806682, 0xa361d8e9, 0x9d80bbf1, 0xe63f1972, 0xb45a6d46 +}, +{ +0x95c44642, 0xef3f5530, 0x96e5abcb, 0xb5656cd3, 0x7afb1372, 0xa50e87bb, 0x11ce9d3d, 0x6d658a85, 0xa78a1c67, 0xa988fa9f, 0x3bb9ce42, 0xc19c9959, 0xd800e656, 0xf3d2c37c, 0x0ad679ee, 0x2c2757b5, 0x1e690d90, 0xb9e311f7, 0x0e02e6f8, 0xec1eb8b9, 0x604681f4, 0x57793292, 0x6cc0fcd0, 0x730c8715, 0x6e44670c, 0x6616853e, 0x6fe11159, 0x9110d954, 0xa07f6ef8, 0x2bd2252a, 0x324e5a25, 0xc3180285, 0x653768b7, 0x99423b66, 0xab0c6143, 0x179e99f7, 0xe76db702, 0xe21c5e41, 0xb84667a2, 0xc039ef0c, 0x702d6a9c, 0x71881cc9, 0x44333473, 0xb0148590, 0x01a57655, 0xd60200ae, 0x94613017, 0x2225b14d, 0xea4ebc73, 0x341e5eef, 0x98e74d33, 0x9f123fac, 0xe8ca27af, 0x3c4cbcdd, 0x787f88ae, 0x55fda94e, 0xfc7553d1, 0x8bad4bd2, 0x80de4469, 0x134a06e1, 0x21045cc4, 0x426330b9, 0xd4869b72, 0x163befa2, 0xf7065c6a, 0xae7d8800, 0xb1b1f3c5, 0xe96f51fa, 0xc9ce7b6b, 0xafd8fe55, 0x83ffa9e0, 0xb2901e4c, 0x30cac1f9, 0xb4c01a86, 0x0571e943, 0xd9a59003, 0xf6a32a3f, 0x151a022b, 0x8c58394d, 0xee9a2365, 0xc2bd74d0, 0x07f5729f, 0x7d0e61ed, 0x825adfb5, 0x5a5a39e3, 0xbd378ee1, 0xcd1ae47d, 0x09f79467, 0x4a31d28b, 0x0d230b71, 0x7cab17b8, 0xda847d8a, 0xf277b529, 0xf15658a0, 0x393d559e, 0x508c400d, 0xe44c5a8b, 0x2956bef6, 0xebebca26, 0x4ee54d9d, 0x1d48e019, 0xf8a1ccc7, 0x3de9ca88, 0x868e40a3, 0x872b36f6, 0xedbbceec, 0x77d81803, 0x5f2bd0a0, 0xdff594c9, 0x1fcc7bc5, 0x69b11593, 0x199c7f0f, 0x12ef70b4, 0x369ac533, 0x373fb366, 0xf904ba92, 0xce3b09f4, 0x597bd46a, 0x681463c6, 0x0fa790ad, 0xcaef96e2, 0xe6c8c157, 0x2a77537f, 0xc548064f, 0xf582c7b6, 0xc86b0d3e, 0x4dc4a014, 0x9bc6a0ba, 0x46b7afaf, 0xb644815a, 0x67b3f36b, 0xc669ebc6, 0x3f6d5154, 0xfef1c80d, 0x2ea3cc69, 0xbc92f8b4, 0xbe166368, 0xa4abf1ee, 0x9740dd9e, 0x2d8221e0, 0xa2fbf524, 0xc7cc9d93, 0x8f79d4c4, 0x45964226, 0x817b323c, 0x888ca65b, 0x065004ca, 0x9d96a470, 0x58dea23f, 0x5c0a3d29, 0x00000000, 0x48b54957, 0x5daf4b7c, 0x74f9f58a, 0x2475b587, 0x8a083d87, 0xdcd47940, 0xe098c59d, 0x106beb68, 0x840adb7f, 0x62c21a28, 0x8edca291, 0x02849bdc, 0xd7a776fb, 0xa62f6a32, 0x0b730fbb, 0x40e7ab65, 0x5bff4fb6, 0xe13db3c8, 0x14bf747e, 0x6b358e4f, 0x0321ed89, 0x4b94a4de, 0x1839095a, 0x43c646ec, 0x767d6e56, 0x3ec82701, 0x28f3c8a3, 0x7e2f8c64, 0xb7e1f70f, 0x1b18e4d3, 0x7f8afa31, 0xdb210bdf, 0x51293658, 0x3a1cb817, 0x316fb7ac, 0x9eb749f9, 0xe5e92cde, 0x53adad84, 0xd523ed27, 0x20a12a91, 0x7b5e6527, 0x64921ee2, 0x26f12e5b, 0x4c61d641, 0x0c867d24, 0xe3b92814, 0xcf9e7fa1, 0xb3356819, 0x1ced964c, 0xcb4ae0b7, 0x755c83df, 0xbac2fc7e, 0x49103f02, 0xbb678a2b, 0xfa25571b, 0x8929d00e, 0xfdd02584, 0xa1da18ad, 0xde50e29c, 0x0852e232, 0x2754580e, 0x1abd9286, 0x04d49f16, 0xa35e8371, 0x35bb28ba, 0xd2d69fb8, 0xacf913dc, 0x2380c718, 0x9c33d225, 0x93944288, 0xccbf9228, 0x85afad2a, 0xd0520464, 0x923134dd, 0xad5c6589, 0xf427b1e3, 0x33eb2c70, 0x2f06ba3c, 0x72a9f140, 0xc4ed701a, 0xa82d8cca, 0x9a63d6ef, 0x63676c7d, 0x4142dd30, 0xaaa91716, 0xd1f77231, 0x56dc44c7, 0x8dfd4f18, 0xdd710f15, 0xff54be58, 0x5458df1b, 0x90b5af01, 0xfb80214e, 0x6a90f81a, 0x4f403bc8, 0x389823cb, 0x25d0c3d2, 0x61e3f7a1, 0x5208dbd1, 0xbfb3153d, 0xf0f32ef5, 0xd373e9ed, 0x79dafefb, 0x4712d9fa, 0x5e8ea6f5 +}, +{ +0xe8a72978, 0x107ce76f, 0x676445ce, 0xbd0bd10f, 0x731970c0, 0x3102545b, 0xedfd72f8, 0x0120c848, 0x02ea21aa, 0xfb6a665c, 0xfa4aae14, 0x473a3eb2, 0xfe303ddc, 0x055a5b80, 0xab9cc5ab, 0x8c72c4fd, 0x9ee40238, 0xf98047f6, 0xbf9ab10c, 0x27ee0156, 0xea36497b, 0xad0c77c9, 0x76386ae9, 0xbeba7944, 0xbac0ea8c, 0x70d39922, 0xb90a036e, 0x4340ad7a, 0xbbe022c4, 0x2424e8b4, 0x433becd3, 0x06ebf3cb, 0x00000000, 0x9d2eebda, 0xdda4af42, 0x9bc51811, 0xac57fe28, 0xda14d568, 0xdf35cf41, 0x12ed876c, 0x408a4498, 0x5746d9dd, 0x8ae2769f, 0x8d294d1c, 0x448b96f9, 0xf8dbce17, 0x55d7b9de, 0x9ae5d059, 0xad773660, 0x16ec550d, 0x23efd337, 0x623e1e4e, 0xfe4b7c75, 0x2394929e, 0x32b3fc10, 0xff10f594, 0x70a8d88b, 0x169714a4, 0xf9fb065f, 0xed863351, 0x33e875f1, 0x8953ded4, 0xfcda1c76, 0x55acf877, 0x41aa8cd0, 0x8a993736, 0x75f2830b, 0xff6bb43d, 0x51ad2a16, 0xea4d08d2, 0xac2cbf81, 0x980ff1f3, 0xfca15ddf, 0x71f3516a, 0xeb6dc09a, 0x115c2f27, 0x32c8bdb9, 0xcda30984, 0x521c825d, 0x34580fdb, 0xc9a2dbe5, 0x1007a6c6, 0x636597af, 0x36b22e71, 0x8bc2bed7, 0x66448d86, 0xbb9b636d, 0x9874b05a, 0x9a9e91f0, 0x44f0d750, 0x015b89e1, 0x7239b888, 0x50f6a3f7, 0xfa31efbd, 0xb8518a8f, 0xb82acb26, 0x37e9a790, 0xca1373ae, 0xa976e401, 0x4661b753, 0x03cae9e2, 0x60af7e4d, 0xdddfeeeb, 0x60d43fe4, 0x99547812, 0xcf49282e, 0x7589c2a2, 0xca683207, 0x26cec91e, 0x140674a7, 0x257f6155, 0x56661195, 0x7763e308, 0x05211a29, 0xa90da5a8, 0xee4cdab3, 0xdb4f5c89, 0x45ab5eb1, 0xda6f94c1, 0xaebddf82, 0xdcff26a3, 0x461af6fa, 0x74a90aea, 0x245fa91d, 0xbabbab25, 0x533c4a15, 0xa82d6de0, 0x54f77196, 0xdf4e8ee8, 0x561d503c, 0x8ee3a4fe, 0x07cb3b83, 0x5267c3f4, 0x30229c13, 0x64d5ed85, 0x0401d261, 0x89289f7d, 0xecddbab0, 0xccf88065, 0x74d24b43, 0x11276e8e, 0x64aeac2c, 0x88085735, 0x36c96fd8, 0x508de25e, 0x8fc36cb6, 0xef6c12fb, 0x671f0467, 0x34234e72, 0x22cf1b7f, 0x147d350e, 0x9c75623b, 0x17cc9d45, 0xe8dc68d1, 0xce12a1cf, 0x631ed606, 0xd885b56b, 0x53470bbc, 0xdc84670a, 0x1296c6c5, 0xd9a57d23, 0xf8a08fbe, 0x9c0e2392, 0xbc2b1947, 0xaf9d17ca, 0xc88213ad, 0xef175352, 0x9e9f4391, 0xa8562c49, 0xabe78402, 0x13cd4f24, 0x250420fc, 0xfd819597, 0x9fbf8bd9, 0x33933458, 0x3059ddba, 0x8e98e557, 0x17b7dcec, 0x3578c793, 0x9bbe59b8, 0xfdfad43e, 0xdb341d20, 0xd9de3c8a, 0xeca6fb19, 0xe9fca099, 0x47417f1b, 0xcc83c1cc, 0xe987e130, 0x658e6464, 0x41d1cd79, 0x718810c3, 0xde150709, 0x9fc4ca70, 0x618fb605, 0x205e7b7c, 0x13b60e8d, 0x20253ad5, 0x007b41a9, 0xaabc0de3, 0xee379b1a, 0x155dfd46, 0x76432b40, 0x45d01f18, 0x8c098554, 0xeb168133, 0x07b07a2a, 0x663fcc2f, 0x217eb334, 0xc9d99a4c, 0xbd7090a6, 0xcb33bbe6, 0xce69e066, 0xaac74c4a, 0x317915f2, 0xcb48fa4f, 0xcf326987, 0x51d66bbf, 0x8d520cb5, 0xaec69e2b, 0x2105f29d, 0xbec138ed, 0xbfe1f0a5, 0x73623169, 0x0690b262, 0x047a93c8, 0xcdd8482d, 0x3792e639, 0xd8fef4c2, 0x573d9874, 0xfb1127f5, 0x65f525cd, 0x62455fe7, 0x8fb82d1f, 0xde6e46a0, 0x279540ff, 0x03b1a84b, 0x992f39bb, 0x26b588b7, 0x7718a2a1, 0x8bb9ff7e, 0x3503863a, 0xb97142c7, 0x421b249b, 0x7242f921, 0x9d55aa73, 0x40f10531, 0xafe65663, 0xbc5058ee, 0x548c303f, 0x22b45ad6, 0x61f4f7ac, 0xc8f95204, 0x8873169c, 0x02916003, 0x42606532, 0x1526bcef +}, +{ +0x5714a0ad, 0xf3da978b, 0xdbb5df28, 0xd2dbeb56, 0xa3584995, 0xf44ce938, 0x416b5d65, 0x58ecd19e, 0x8a373ac8, 0xf6ff1d84, 0xf7ff267a, 0x52312aa2, 0x616a1a46, 0x5a5f2522, 0xd7fe6159, 0x34cd4e57, 0x0bddc0c2, 0x75a61332, 0xa258726b, 0x42d89227, 0x90037971, 0xf1696337, 0x3b353f64, 0x167ffdc8, 0x4f9317a8, 0x7cc8274c, 0xc23253d3, 0xa67dc39a, 0x30e8ffa6, 0x55a75411, 0x406b669b, 0x6f92508b, 0x9103428f, 0x2d4ac2ac, 0x81eafa0a, 0x444ed76a, 0xb79440e1, 0x0addfb3c, 0xc8efa8ef, 0x85cf4bfb, 0x7083993d, 0xb10205ac, 0xd3dbd0a8, 0x690415c6, 0xa0eb86d7, 0xd0681fea, 0x3ca341d7, 0xe4a551bd, 0xdab5e4d6, 0xf9076cb7, 0xc5a42d60, 0xe7169eff, 0x4805691b, 0x9c48c700, 0x7a5e6201, 0x54a76fef, 0x8b370136, 0x62d9d504, 0x23b28861, 0xf54cd2c6, 0xbd49bbdd, 0x335b30e4, 0xb4278fa3, 0x490552e5, 0x5182e5e0, 0x0425b1f1, 0x56149b53, 0x7615dc70, 0x3a35049a, 0x74a628cc, 0x9426c880, 0xaa367deb, 0x4ab69da7, 0x177fc636, 0x1da23d0a, 0x84cf7005, 0x5082de1e, 0x286f48a3, 0xbc498023, 0xfab4a3f5, 0xaca038a6, 0x3da37a29, 0x9d48fcfe, 0x15cc328a, 0xd6fe5aa7, 0x2ef90dee, 0x79edad43, 0x2697026e, 0x867c84b9, 0x644f9049, 0x454eec94, 0x5b5f1edc, 0x07967eb3, 0xd9062b94, 0x096e347e, 0x1887b705, 0x72306d81, 0x7183a2c3, 0x8984f58a, 0xea5d1b70, 0x7330567f, 0xee78aa81, 0x3886f026, 0xcb5c67ad, 0xa4ce3726, 0xe080e04c, 0x1e11f248, 0xbefa749f, 0x9ade824d, 0x66fc64f5, 0x8e128b39, 0x10e9b885, 0x7f7be80e, 0x4e932c56, 0x6e926b75, 0x4bb6a659, 0x3986cbd8, 0x0ef84acd, 0x7e7bd3f0, 0x01003bfe, 0xa8858957, 0x21017cdd, 0x296f735d, 0x986d76f1, 0xb3b1f110, 0xe180dbb2, 0x0c4bbe71, 0xf8075749, 0x1b347847, 0x2ff93610, 0xc081a76f, 0x4d20e314, 0xae13cc1a, 0xbadfc56e, 0x2524cd2c, 0x1a3443b9, 0xdd239a65, 0x6ab7da84, 0xff9129fa, 0x4c20d8ea, 0xdf906ed9, 0x83590eb6, 0x31e8c458, 0x22b2b39f, 0x3e10b56b, 0xf2daac75, 0x00000000, 0x9526f37e, 0xc4a4169e, 0xd1682414, 0x5e7a94d3, 0xc617e222, 0x46fd23d6, 0xbffa4f61, 0xab364615, 0x78ed96bd, 0x82593548, 0x6c219fc9, 0x377e8115, 0x43d8a9d9, 0x11e9837b, 0x877cbf47, 0xf06958c9, 0xdc23a19b, 0x996d4d0f, 0x8f12b0c7, 0x92b08dcd, 0xc1819c91, 0x7715e78e, 0xce79eda2, 0x125a4c39, 0xfe911204, 0xcf79d65c, 0x67fc5f0b, 0x8ca17f85, 0xe23314f0, 0x2c4af952, 0xeb5d208e, 0x68042e38, 0x2bdc87e1, 0x6bb7e17a, 0x9efb33bc, 0x9bdeb9b3, 0xca5c5c53, 0xb96c0a2c, 0x5331115c, 0xfbb4980b, 0x27973990, 0xa77df864, 0x20014723, 0x2424f6d2, 0x03b3cf42, 0x5dc95b91, 0x0ff87133, 0x0696454d, 0x02b3f4bc, 0xc717d9dc, 0xa5ce0cd8, 0x59ecea60, 0xa985b2a9, 0x63d9eefa, 0xe3332f0e, 0xa1ebbd29, 0xcdca22e0, 0xc332682d, 0x1ca206f4, 0x135a77c7, 0xe5a56a43, 0x5cc9606f, 0xccca191e, 0xada00358, 0xeccb5e3d, 0x3f108e95, 0xd44dae1b, 0x654fabb7, 0xd54d95e5, 0xfd22dd46, 0xedcb65c3, 0x086e0f80, 0xef78917f, 0x7dc81cb2, 0xe616a501, 0x19878cfb, 0xb6947b1f, 0xb0023e52, 0x325b0b1a, 0x8884ce74, 0x2adcbc1f, 0x8da1447b, 0x96953c3c, 0xd806106a, 0xb2b1caee, 0x9ffb0842, 0x05258a0f, 0x6d21a437, 0x367ebaeb, 0xe8eeefcc, 0xe9eed432, 0x80eac1f4, 0xb86c31d2, 0xfc22e6b8, 0xbbdffe90, 0x35cd75a9, 0x47fd1828, 0x5f7aaf2d, 0x979507c2, 0x1f11c9b6, 0x93b0b633, 0x0d4b858f, 0xb527b45d, 0xde905527, 0x606a21b8, 0x7b5e59ff, 0xc9ef9311, 0xaf13f7e4, 0x14cc0974 +}, +{ +0xb27318c6, 0x6ce40cee, 0xc231f37d, 0x38a7b452, 0x7631c989, 0xc46a83df, 0x96bed6fa, 0x001b91b8, 0x6a8cbf64, 0xb4ff64e7, 0x4829c2d2, 0x6a972edc, 0xde73db83, 0xe6cffe69, 0x2296be9e, 0xc4711267, 0x38437bf9, 0x22a57db6, 0xb297d76d, 0xe0948ecb, 0xd81b6809, 0xde8c8590, 0x96a54742, 0xfcfef4a5, 0xde971428, 0xe618f2ea, 0x241ac2bf, 0x548f2587, 0xfa5ada14, 0xc45940f7, 0x0697ed99, 0xe6d46fd1, 0xfce5651d, 0x8a1831af, 0xc2cead6e, 0xd8cc648a, 0x76fd54b2, 0xb268897e, 0xb4d73677, 0x4e5ae0e0, 0x52309a8e, 0x2269e08d, 0x8c8fdc36, 0xde684a3b, 0x9696846a, 0x70bdb5a8, 0x1c71ebd6, 0xb4286864, 0x1afd97f7, 0x48cd0d79, 0x70597a03, 0xb433f9dc, 0x00285290, 0x1ca6e755, 0x90293b63, 0x54a77717, 0x70712893, 0x8c58d0b5, 0xae02f310, 0x90cdf4c8, 0x0033c328, 0xe62b31c2, 0xaed5ff93, 0x3e3059cb, 0x481a01fa, 0x06732232, 0xe630a07a, 0x54582904, 0x24d65f84, 0xb2bf85fd, 0x00ff5e13, 0xa86a409a, 0x76199b19, 0x6a40225f, 0x388fe6c2, 0xe08f1f73, 0xc495ddcc, 0xc48e4c74, 0x22727135, 0x48fece51, 0x8afcfe04, 0xc2fd6e46, 0x1c8eb5c5, 0x6ccc5e7e, 0x7042ebbb, 0x6cff9d56, 0xfc01aab6, 0xae2aa180, 0x1c6a7a6e, 0xa842120a, 0x3858ea41, 0xb240dbee, 0xfccd378d, 0xfc32699e, 0x6a73e177, 0x8cbc1f1e, 0x1c95247d, 0x706ab92b, 0xb4e4f55f, 0x0668b38a, 0x2241b21d, 0xae1962a8, 0x1a310acc, 0x8acf3d2c, 0x4e8dec63, 0x06bfbf09, 0xb25b4a56, 0x48e55fe9, 0xc2e6fffe, 0xd8ffa7a2, 0xb41bab4c, 0x546bea2c, 0xe0438248, 0x520359a6, 0x24fe0d14, 0xc442d14f, 0x52d45525, 0x24e59cac, 0x4e6923c8, 0x225a23a5, 0x3870b8d1, 0x4e72b270, 0xfa8dd697, 0x76ce979a, 0xaece6e2b, 0x90e5a658, 0x6cd7cfc6, 0x4ea5bef3, 0xe0704160, 0x5443b8bc, 0xe05813f0, 0x38bc25ea, 0x8c43410d, 0xc2023055, 0x24015307, 0x8ca78ea6, 0xfa414bac, 0x068c7c21, 0xc22a62c5, 0x3e2bc873, 0xe6036352, 0x968d15d2, 0x1a2a9b74, 0xe6fc3d41, 0x3ed49660, 0xd800f9b1, 0x1ad5c567, 0x3894777a, 0xa8a6dda1, 0xc4a61ee4, 0xa8bd4c19, 0x90d66570, 0x52fc07b5, 0x90fe37e0, 0x3ee75548, 0x9669da79, 0x708e7680, 0xd8e4361a, 0x24290197, 0xa88e8f31, 0xa871d122, 0xe6e7acf9, 0x522b0b36, 0x8c6b139d, 0xe0a74de3, 0x3ecf07d8, 0x54707b94, 0xfa96472f, 0x1ace54df, 0x6c1b52fd, 0x1cbd76ed, 0x6a5bb3e7, 0xe06bd0d8, 0x5218c81e, 0x8a30633f, 0x965a1951, 0xfa69193c, 0xd8333a99, 0x8c708225, 0x00cc9d3b, 0xb28c46d5, 0xdea4d700, 0x00000000, 0xd828ab21, 0x00d70c83, 0x06a42eb1, 0x48019042, 0x386b2969, 0xfabe15bf, 0x2432902f, 0x6aa4edf4, 0x4832536a, 0xaee63cbb, 0x4e417158, 0x22beec0e, 0x70a62410, 0x8a03a017, 0x8ad4ac94, 0x6c33006d, 0xfc1a3b0e, 0x52cfc49d, 0x3e039ae3, 0xfa728884, 0x1c4228fe, 0xb4cca7cf, 0xc2d53cd6, 0x6a6870cf, 0x24cdce3c, 0xe0bcdc5b, 0x228d2f26, 0x4ebe2f4b, 0x8c944d8e, 0x1c59b946, 0x8a2bf287, 0xb2a41445, 0x96724bc1, 0xde5b8913, 0xaefdad03, 0xc4bd8f5c, 0x4e967ddb, 0x5494b43f, 0x48d69cc1, 0x76020aa1, 0x3efcc4f0, 0x6c00c345, 0xa85983b2, 0xb4003af4, 0x900169f3, 0x1a19585c, 0xae313038, 0x54bce6af, 0xfaa58407, 0xc219a1ed, 0xd8d7f532, 0x76e6c50a, 0x065b70a2, 0xa8951e89, 0x52e7960d, 0x0640e11a, 0x00e4cfab, 0xde4018ab, 0x1ae6064f, 0xfc29f826, 0x762a5831, 0x76d50622, 0x6c2891d5, 0x3e180b5b, 0xfcd6a635, 0x8ae76fbc, 0x9032aadb, 0x1a02c9e4, 0xdebf46b8, 0x7095e738, 0x901af84b, 0x964188e9, 0x6abf7c4c +} +}, +{ +{ +0xe552a468, 0x9dd7ac62, 0xd132584b, 0x07b5b7e9, 0xee253572, 0xe9d1ebe2, 0xf28eed41, 0x6a15b87f, 0xe513cd11, 0xc45636ae, 0x3a1afd1c, 0x3f176d39, 0x1b5f06a3, 0x0c834f8a, 0x6696f7f5, 0x4e1cba9c, 0xa7cd517e, 0x4b5043c0, 0xa78c3807, 0xc11acff2, 0xec9d12be, 0xf7c2141d, 0x2145fbbf, 0x989b553e, 0x1e529686, 0x6de166ef, 0x74064780, 0x61622965, 0x5ccd6390, 0xc6af781b, 0x4ce5f429, 0x17dc4929, 0xf57a33d1, 0xe990829b, 0x8a4a8c32, 0xbc9257dd, 0x8dff3bdb, 0x1b1e6fda, 0x945973cd, 0xee645c0b, 0xb55de10b, 0xbe6b1968, 0x3f560440, 0x68ad9fb3, 0x78c46173, 0x102897b9, 0xb0111857, 0x4066bba3, 0x9a621b8b, 0x57baf28a, 0x2a7303dc, 0x7f71d69a, 0x7d88982f, 0x714abedc, 0x26b1252f, 0x83853ae4, 0xae02e7a8, 0x642ed039, 0x5e342d25, 0xfcf4ec7e, 0x8f471c17, 0x00000000, 0x5e75445c, 0xfe0da2cb, 0x6da00f96, 0x2d87dd4c, 0x1e13ffff, 0xeb28a557, 0xa281a822, 0xdf485974, 0x19e7216f, 0x813d1d28, 0x63da0ea9, 0xf7837d64, 0x288a4d69, 0x68ecf6ca, 0xa9f63938, 0x710bd7a5, 0x4e5dd3e5, 0x312c057f, 0x57fb9bf3, 0x9d96c51b, 0xb99fc7f8, 0xda45c951, 0x9a2372f2, 0x49a90d75, 0x28cb2410, 0x456b2b86, 0x316d6c06, 0xacbac064, 0xddb117c1, 0x91158a91, 0x76be604c, 0x054cf95c, 0xca6d5ee8, 0xbcd33ea4, 0xae438ed1, 0x1ceab14a, 0x0b77911a, 0xb7e5c6c7, 0x5543bc3f, 0x7f30bfe3, 0x1069fec0, 0x3dee238c, 0x23bcb50a, 0x2f3ffa80, 0x93ecc424, 0x5b39bd00, 0x52f60bd6, 0xbe2a7011, 0x179d2050, 0xc3e38147, 0x8f06756e, 0x1290b075, 0x098edfaf, 0x646fb940, 0xa0398fee, 0x5c8c0ae9, 0xf2cf8438, 0x49e8640c, 0xb2e856e2, 0x83c4539d, 0x47d30c4a, 0x0b36f863, 0x07f4de90, 0xcf60cecd, 0xa078e697, 0x36d8dbef, 0x5b78d479, 0xacfba91d, 0xab0f778d, 0x8a0be54b, 0x339422b3, 0x0cc226f3, 0xc4175fd7, 0x210492c6, 0x3460fc23, 0x4ca49d50, 0x0e7a013f, 0x7a3d2fc6, 0xd1733132, 0xd8bc87e4, 0xe2e71381, 0x639b67d0, 0x94181ab4, 0xddf07eb8, 0xbb66894d, 0x74472ef9, 0x15646ee5, 0x00416979, 0xc8d57924, 0xd6c686db, 0x6a54d106, 0x2f7e93f9, 0x26f04c56, 0x6123401c, 0xfcb58507, 0x09cfb6d6, 0xa5341fcb, 0xa57576b2, 0xf077a3f4, 0xe01e5d34, 0x88f2abfe, 0x6f18285a, 0xd47ea117, 0x47926533, 0xb2a93f9b, 0x23fddc73, 0xda04a028, 0xc894105d, 0xe05f344d, 0x2dc6b435, 0xf9f97c5b, 0x504e2c1a, 0xab4e1ef4, 0xcd998078, 0x8dbe52a2, 0x3daf4af5, 0x9f6f8bae, 0x1cabd833, 0x3421955a, 0x42de9c6f, 0x9154e3e8, 0x2a326aa5, 0x050d9025, 0xe7ea83a4, 0xf9b81522, 0x96a03d78, 0x6f594123, 0xd8fdee9d, 0x38e3b3a9, 0xfb415b97, 0xbb27e034, 0xcf21a7b4, 0x240902e3, 0x98da3c47, 0xd38a7f87, 0x59819acc, 0xb7a4afbe, 0x66d79e8c, 0xeb69cc2e, 0x4027d2da, 0x5502d546, 0x86c9c3b8, 0xb9deae81, 0x84308d0d, 0xd43fc86e, 0x73f29910, 0x500f4563, 0xb050712e, 0x429ff516, 0x96e15401, 0xca2c3791, 0x0e3b6846, 0x52b762af, 0xd687efa2, 0xf53b5aa8, 0xc3a2e83e, 0xe2a67af8, 0xb51c8872, 0xc6ee1162, 0x7885080a, 0xdf09300d, 0x3699b296, 0x02f94eb5, 0x817c7451, 0xfb0032ee, 0x8688aac1, 0xc15ba68b, 0xfe4ccbb2, 0xf036ca8d, 0x33d54bca, 0x8471e474, 0x7a7c46bf, 0xcdd8e901, 0x12d1d90c, 0x9f2ee2d7, 0x38a2dad0, 0xecdc7bc7, 0x73b3f069, 0xe7abeadd, 0xa9b75041, 0x02b827cc, 0x4b112ab9, 0x7dc9f156, 0x24486b9a, 0x76ff0935, 0x93adad5d, 0x19a64816, 0x88b3c287, 0x452a42ff, 0x1525079c, 0xa2c0c15b, 0xd3cb16fe, 0x59c0f3b5, 0x3a5b9465 +}, +{ +0xc6ef1049, 0x84cb4f09, 0x55e3ae25, 0xa0ccb909, 0x9c673305, 0x7d650456, 0x095bb666, 0x39716019, 0x533b9c80, 0xc03722ec, 0xaca5ecd0, 0x0302d8b0, 0x72e68095, 0xb2d1a279, 0x286ea3d9, 0xe4d8dd46, 0x42245f40, 0x6aa2f533, 0x27052eb0, 0xcfb4a62f, 0x743eb230, 0xfaac93ef, 0xf31f2c23, 0x82fb7406, 0xed836b20, 0x1baea4bc, 0x36f2e4da, 0xd4f20b39, 0xe7320c5c, 0x9a57080a, 0x24efffaa, 0xe1023753, 0x65c9785a, 0x7857e7e9, 0xb4e19976, 0xca864590, 0x18ac7c0c, 0x60fb9be5, 0x11f7ca6a, 0xc0df2b46, 0xc5edc8f9, 0xfc74a14a, 0x710c518f, 0x9f65ebb5, 0x7d8d0dfc, 0x2237cd0f, 0x6c92ce3c, 0xb239abd3, 0xaf4f3dca, 0xe2e8e649, 0x14c529d5, 0x4b97e08c, 0x2886aa73, 0x5fbac0f3, 0x2d5c4066, 0xf01df493, 0x2eb6917c, 0x652171f0, 0xc3ddf3f6, 0xee69ba3a, 0xa024b0a3, 0x4b7fe926, 0x121d1b70, 0x05daea15, 0x42cc56ea, 0xff7679fa, 0x0ab1677c, 0x3f415b16, 0x50394430, 0xe1ea3ef9, 0xfc9ca8e0, 0x399969b3, 0xf3f72589, 0x87c997b9, 0x3fa952bc, 0xa6148bac, 0x8ba0c260, 0x87219e13, 0x1d769619, 0x69a02d83, 0xe8b1889f, 0xbeb8f7a0, 0xfa449a45, 0x172ff8cf, 0xb70b486c, 0x21dd1c15, 0xaa95d7df, 0xafa73460, 0xa6fc8206, 0x5a88234c, 0xf6c5c636, 0xc60719e3, 0x17c7f165, 0x5f52c959, 0xde436c45, 0xd7f0d389, 0xe200efe3, 0x930cbe6c, 0x8d90f96f, 0xed6b628a, 0x5cb81843, 0xe7da05f6, 0x63114aff, 0x773c6a80, 0x1e744ea9, 0xcc5e7735, 0x9f8de21f, 0x56e17695, 0x6c7ac796, 0xaa7dde75, 0x6013924f, 0x33280ecf, 0xff9e7050, 0xa97f06c5, 0x53d3952a, 0x361aed70, 0x842346a3, 0xd1c0e886, 0x4895383c, 0x3a73b8a9, 0x0c815c73, 0x900e66dc, 0x9955d0ba, 0x953c8563, 0x8e7a2875, 0x550ba78f, 0x6623a940, 0xf62dcf9c, 0x66cba0ea, 0x44fc6de5, 0xb888ccaf, 0x69482429, 0x2b6c7b69, 0xf0f5fd39, 0x2db449cc, 0x9c8f3aaf, 0x71e45825, 0x78bfee43, 0xdeab65ef, 0x7bbd36f3, 0x7e67dce6, 0xee81b390, 0x1e9c4703, 0x0c6955d9, 0xebb3502f, 0xc505c153, 0xb1d37ac9, 0x7b553f59, 0x213515bf, 0x4d4fd229, 0x50d14d9a, 0xdb718ffa, 0x351835c0, 0x74d6bb9a, 0x0f8384c3, 0x00000000, 0x7e8fd54c, 0x884a137a, 0x3c4383a6, 0x6f90168c, 0xf5c71e86, 0x598afbfc, 0x0f6b8d69, 0xd718da23, 0x3a9bb103, 0x93e4b7c6, 0x56097f3f, 0xc335fa5c, 0xd89b5ee0, 0x0532e3bf, 0x22dfc4a5, 0x8111a51c, 0x111fc3c0, 0x35f03c6a, 0x1d9e9fb3, 0x2e5e98d6, 0x33c00765, 0xac4de57a, 0xb860c505, 0x9abf01a0, 0x99bdd910, 0x412687f0, 0xd22a399c, 0x6a4afc99, 0xf9ae4b5f, 0xa3ce61b9, 0x82137dac, 0xd2c23036, 0x142d207f, 0x00e809aa, 0x06303b0f, 0x81f9acb6, 0x302ad67f, 0xc96c948a, 0x27ed271a, 0x06d832a5, 0x5962f256, 0xa9970f6f, 0x77d4632a, 0xb13b7363, 0xe8598135, 0xbdba2f10, 0xb40990dc, 0x47feb555, 0xf52f172c, 0x5a602ae6, 0xcf5caf85, 0x4e4d0a99, 0xbe50fe0a, 0xdd41b4f5, 0x0a596ed6, 0xc9849d20, 0xa5fe5ab6, 0x2407f600, 0x4414644f, 0xccb67e9f, 0x41ce8e5a, 0xdb998650, 0xd873574a, 0x3cab8a0c, 0xeb5b5985, 0x12f512da, 0x8d78f0c5, 0x8e9221df, 0x95d48cc9, 0x720e893f, 0xbd5226ba, 0x4716bcff, 0x4da7db83, 0x2b8472c3, 0xca6e4c3a, 0xf94642f5, 0x4ea50333, 0x03ead11a, 0xe430d4ec, 0x30c2dfd5, 0xdda9bd5f, 0xa516531c, 0xb7e341c6, 0xd128e12c, 0x963e5dd3, 0x5c5011e9, 0x1b46ad16, 0x96d65479, 0xd41a0293, 0x63f94355, 0x90e66f76, 0x88a21ad0, 0x184475a6, 0xbb621db5, 0xa3266813, 0x6f781f26, 0xbb8a141f, 0x09b3bfcc, 0x487d3196, 0x8b48cbca +}, +{ +0x38279f5f, 0x3e9f9d03, 0xc6f2033d, 0x08b8a2a1, 0x3f5db50f, 0x4ce69e79, 0xce4aa19c, 0x4a5e9c25, 0xa66d53d9, 0x7c79a387, 0x494b3a99, 0x159c79ce, 0x64f0dc08, 0xf86d9e3e, 0xc4258d8d, 0xb48b0047, 0x7eae2d37, 0xc29d8fd1, 0x5cd74357, 0x194b5783, 0xb99e0606, 0xb233021b, 0x716ca5c6, 0x7503292a, 0xdbd6d852, 0x58b8cfbb, 0xeee4414c, 0xfed59c62, 0x9c9d4236, 0x097a8aad, 0x1d24db6f, 0xa4badd69, 0x27d4ca80, 0x36273fa2, 0x42e63e84, 0x55adc9fa, 0xa9afdb28, 0x5bad6907, 0x5d156b5b, 0x85d615b5, 0xcc9d2f2c, 0x4e3110c9, 0xf1171493, 0x9e4acc86, 0x315d15f2, 0x13247b92, 0x6f5dd815, 0xb126a4a7, 0xe0e4e1b1, 0x4ff338c5, 0x2eae402d, 0x74c10126, 0xb3f12a17, 0xc5e7a581, 0xc188296d, 0xd8c37eee, 0x174bf77e, 0xa3c0f739, 0xe85c4310, 0xaaba7d94, 0xdd6eda0e, 0xfb783882, 0x39e5b753, 0xfaba108e, 0x459c14d4, 0xa0d55185, 0xfdc03ade, 0x6d8a56a5, 0xadc057c4, 0x6b3254f9, 0xde7b7cb2, 0x2616e28c, 0x20aee0d0, 0x91884477, 0xf9afb632, 0x2b03e4cd, 0x6af07cf5, 0x338a9b42, 0xd5d678af, 0xe2336f01, 0x1689df72, 0x88c313f4, 0x51c24516, 0x0a6f2c11, 0xac027fc8, 0xe65ce3ed, 0xc8f2a3c0, 0xa202df35, 0xc35fa7dd, 0x2c79ce9d, 0x0cd72e4d, 0x0d150641, 0x638af658, 0xd90156e2, 0xef266940, 0xedf1e7f0, 0x70ae8dca, 0x935fcac7, 0x4031b034, 0x807bb155, 0x9a25406a, 0x50006d1a, 0xf578987f, 0x8fb939a4, 0xf0d53c9f, 0xd36e7af3, 0x3b3239e3, 0xd6c3de13, 0x43241688, 0xcd5f0720, 0x6c487ea9, 0x18897f8f, 0x22796e60, 0xaed5f178, 0x2f6c6821, 0x2ac1ccc1, 0xd41450a3, 0x79d40767, 0x4b9cb429, 0x76168f96, 0xec33cffc, 0x8d6eb714, 0x0bad041d, 0x836e17e9, 0xd2ac52ff, 0x9425e097, 0xd07bdc4f, 0x145e51c2, 0x5e00cde7, 0x3d8a3bbf, 0x89013bf8, 0x41f39838, 0xbb4988b6, 0x8bd6b548, 0xe126c9bd, 0xa578f565, 0xf3c09a23, 0x84143db9, 0xca252d70, 0x69e5da49, 0x86c3b309, 0x1e317dd3, 0x8cac9f18, 0x67e57ab4, 0x96f26e27, 0x37e517ae, 0xe99e6b1c, 0x8e7b11a8, 0xbf26045a, 0xa1177989, 0x445e3cd8, 0x77d4a79a, 0xd1b9f443, 0xbdf18aea, 0x577a474a, 0xe5494551, 0x609f50e4, 0xb79ea6fb, 0x98f2ceda, 0x1ff355df, 0x02d78eb0, 0x95e7c89b, 0x29d46a7d, 0x7f6c053b, 0xa7af7bd5, 0xf66d3ec3, 0x3248b34e, 0x7b0389d7, 0xba8ba0ba, 0xb549284b, 0xcbe7057c, 0x73bb2b76, 0xa86df324, 0xda14f05e, 0x9930e6d6, 0xaf17d974, 0x01c2280c, 0xd701f61f, 0x5315cba6, 0x78162f6b, 0xff17b46e, 0xc04a0161, 0xe3f1470d, 0x474b9a64, 0x4d24b675, 0xab785598, 0xb0e48cab, 0x24c16c3c, 0x00000000, 0xdcacf202, 0x23bb466c, 0x9d5f6a3a, 0x48891295, 0x6827f245, 0x28164271, 0x046f8cec, 0x546fe1f6, 0x2dbbe691, 0xc9308bcc, 0x34f0b112, 0x06b8025c, 0x7dbb8b8b, 0x7279037a, 0xeb49e5ac, 0x4689b268, 0x9be76866, 0x662752b8, 0x3532991e, 0xe79ecbe1, 0xb85c2e0a, 0xf7af16cf, 0x8a149d44, 0x05ada4e0, 0x6e9ff019, 0x3af011ef, 0x52d7e3aa, 0x81b99959, 0xdfb954be, 0x615d78e8, 0xc7302b31, 0x1a5ef13f, 0xcf888990, 0x904a6c7b, 0x5fc2e5eb, 0x9730462b, 0x12e6539e, 0x9f88e48a, 0xb65c8ef7, 0xea8bcda0, 0x929de2cb, 0x597ae7b7, 0x11f3f522, 0x6248de54, 0xe48b6d5d, 0x87019b05, 0xf202b22f, 0x0315a6bc, 0x1b9cd933, 0x7ac1a1db, 0x216cc8dc, 0x82ac3fe5, 0x6532f404, 0xf4bab073, 0x25034430, 0x0e00a0fd, 0x077a2a50, 0xbc33a2e6, 0x1ce6f363, 0x5a6f410b, 0x3c4813b3, 0x0fc288f1, 0x1031dd2e, 0xfc0212d2, 0x309f3dfe, 0x56b86f46, 0xbee42c56 +}, +{ +0xb230fe94, 0xb390a723, 0x2d2f6d5e, 0x1a2e2e51, 0x8e9b08f0, 0x8241b1ea, 0xa39d3f6d, 0x00295ac3, 0x207cd730, 0xa81ed0c5, 0xd402ff63, 0x0d53ba6e, 0x56434e89, 0x6db1ee5f, 0x177d943f, 0x305815bd, 0x661b5b34, 0x3701430f, 0x884b5d36, 0xd5a2a6d4, 0x3d0bafd3, 0x6b61bb99, 0x21f5d444, 0x714f95c8, 0xa3b465ae, 0x886207f5, 0xb569a826, 0x9846c578, 0x0a23b61f, 0xb813488b, 0xbec31d4d, 0x0baab56b, 0x89c25e42, 0x7c357565, 0x93c52ad0, 0xee500602, 0x36a11ab8, 0xc9758780, 0x31f84c0a, 0x46678c04, 0x26ac82f6, 0x60e25431, 0xde0813bf, 0x99cfc60c, 0xb3b9fde0, 0x93ec7013, 0xf92d923d, 0xb9b3113c, 0xe9200a73, 0x3a52f961, 0xbf6344fa, 0x00000000, 0x5dc0a121, 0xefd90576, 0x1cd72154, 0xd35ba9d1, 0x7ae520a3, 0x11adc1f9, 0x2bff3898, 0x8531bd9b, 0xd42ba5a0, 0xfe74c48f, 0x5de9fbe2, 0x4b34366a, 0x07700c71, 0xf904c8fe, 0xc5866459, 0x31d116c9, 0x01a059b7, 0x7d952cd2, 0x0a0aecdc, 0x2ca66e2a, 0x4c443a1b, 0x70c696bc, 0x06f90f05, 0x99e69ccf, 0x95157f16, 0xd8d84679, 0xc5af3e9a, 0x0d7ae0ad, 0x7b6c23d7, 0x270cdb41, 0x5c60f896, 0xb83a1248, 0x4c6d60d8, 0x9e9690be, 0x4de463ac, 0x7dbc7611, 0xb540f2e5, 0x70efcc7f, 0xe90950b0, 0xde21497c, 0x9f36c909, 0x953c25d5, 0xffd49d38, 0x84b8beef, 0x83e1e85d, 0x6d98b49c, 0xf30e2422, 0xf2872756, 0x4b1d6ca9, 0x511a183b, 0x763f99b9, 0x6c11b7e8, 0x5ab0ad50, 0x57ca4dfd, 0x9ebfca7d, 0x4a946fdd, 0xc37f6b5c, 0x50931b4f, 0xa8378a06, 0x409e8301, 0xd372f312, 0x20558df3, 0xd951450d, 0x77b69acd, 0x11849b3a, 0x779fc00e, 0x5c49a255, 0xa54d6aab, 0x949c7c62, 0x6ac1e22e, 0x67925840, 0x3cabf664, 0x16f4974b, 0x67bb0283, 0x0b83efa8, 0x8f3b5147, 0x7acc7a60, 0xbeea478e, 0xe2a3e5db, 0x40b7d9c2, 0xcfa5d246, 0x464ed6c7, 0x413edab6, 0xd2fbf066, 0xb4c9f191, 0x1754cefc, 0x986f9fbb, 0xaece8503, 0x100d984e, 0x075956b2, 0xe5fab369, 0xc95cdd43, 0x6b48e15a, 0xdfa84a08, 0x5b39ae24, 0xa2143c19, 0xce058bf1, 0xdf8110cb, 0x1cfe7b97, 0xd8f11cba, 0x1a077492, 0x8f120b84, 0x566a144a, 0xb4e0ab52, 0x4abd351e, 0x89eb0481, 0x924c29a4, 0xf88dcb8a, 0xa4ed331c, 0xa23d66da, 0xe303bc6c, 0x92657367, 0x1ba72d25, 0xb99a4bff, 0x21dc8e87, 0xaee7dfc0, 0xe8a90907, 0xc2df32eb, 0xee795cc1, 0xa5643068, 0xd2d2aaa5, 0xa4c469df, 0xf5f72b27, 0xaf478677, 0x5b10f4e7, 0x8268eb29, 0x1024c28d, 0xf4577290, 0x57e3173e, 0xf3277ee1, 0x0cdab91a, 0x7616c37a, 0x2a763bec, 0x60cb0ef2, 0xf5de71e4, 0x1d5e2220, 0x513342f8, 0xf47e2853, 0x6ae8b8ed, 0xe32ae6af, 0x5a99f793, 0xe45aeade, 0x2bd6625b, 0x7c1c2fa6, 0x2a5f612f, 0xa997d3b1, 0x6c38ed2b, 0xc8d5de37, 0xe473b01d, 0x06d055c6, 0x372819cc, 0x30714f7e, 0x1b8e77e6, 0x3c82aca7, 0xfe5d9e4c, 0xc356319f, 0x2d06379d, 0x94b526a1, 0x61420d86, 0x27258182, 0xce2cd132, 0x8518e758, 0x4dcd396f, 0xd9781fce, 0x47ee8f70, 0x3bf2a0d6, 0xcf8c8885, 0x7b457914, 0xa9be8972, 0x47c7d5b3, 0x2685d835, 0x3d22f510, 0x01890374, 0x50ba418c, 0xe5d3e9aa, 0xeff05fb5, 0x16ddcd88, 0x3bdbfa15, 0xc8fc84f4, 0xf2ae7d95, 0x41178075, 0x2c8f34e9, 0x0cf3e3d9, 0x8eb25233, 0x3688407b, 0x1d7778e3, 0xd58bfc17, 0xc4263dee, 0x8491e42c, 0x3a7ba3a2, 0xb219a457, 0x83c8b29e, 0xc40f672d, 0xe28abf18, 0xf8a49149, 0x663201f7, 0xe88053c4, 0xfffdc7fb, 0x9f1f93ca, 0xaf6edcb4, 0x616b5745, 0xbf4a1e39, 0xc2f66828, 0x7166cf0b +}, +{ +0x26a7da29, 0xbc23d1c0, 0x802c1c76, 0x3d0e3af8, 0xa8e5b927, 0x48048d19, 0x0101f74e, 0xeee84014, 0xd28086f0, 0x52ac9a86, 0x8bf9ed5b, 0x70d632e6, 0x95eb83df, 0xad393c20, 0xa6eccd0d, 0x3261b2ce, 0xf1fbd9de, 0xc7471959, 0x7b64c899, 0x903706d8, 0x746c4bfd, 0x85979223, 0xd95577dd, 0x8e25685c, 0xb9985f95, 0x6a7e2579, 0x71b0cefa, 0xfa4923a1, 0xfff2adf4, 0x571714d3, 0x9f588eee, 0xccf5e326, 0xd65df4b9, 0x9e5979a0, 0xc84f9a3d, 0x4cd9ff50, 0xb6f7d7a3, 0x49627105, 0x470c0e7d, 0xa882b275, 0x2c14d718, 0x37bd37c9, 0xf19cd28c, 0xc2fc970c, 0xc29b9c5e, 0x804b1724, 0x9ae300bb, 0xf09d25c2, 0x5da419e2, 0xc3fd6042, 0xb8fea389, 0x0ad40663, 0x42d08b7a, 0xd8338bc1, 0xc621e545, 0x0bb2fa7f, 0xcc92e874, 0x05bb8e55, 0xa983453b, 0x00670b52, 0x8a9f1147, 0x460df933, 0x3c0fcdb6, 0x5dc312b0, 0xa68bc65f, 0x05dc8507, 0xd73b08a5, 0x107c11fc, 0x42b78028, 0x4863864b, 0x6fa2a07e, 0x29af594d, 0x60aa231a, 0xad5e3772, 0xd38171be, 0x6b18d965, 0x1f1399ca, 0xea52390f, 0x1ba9e0d1, 0x7b03c3cb, 0xc9296621, 0x33604580, 0x227aa860, 0x5616e39d, 0x958c888d, 0x0166fc1c, 0xe0e1343e, 0xc828916f, 0x740b40af, 0x8af81a15, 0xa3574358, 0x64775153, 0x0f088364, 0xd9327c8f, 0x64105a01, 0x61abd454, 0x3206b99c, 0x8496656d, 0x814ae06a, 0xa330480a, 0x43b67766, 0x2c73dc4a, 0xa9e44e69, 0x1acf1ccd, 0x1bceeb83, 0xa256b416, 0xd63affeb, 0x0e6e7f78, 0xbd22268e, 0x948d7fc3, 0x581f97b7, 0x466af261, 0x101b1aae, 0x8b9ee609, 0xdc89f2da, 0xb7f620ed, 0x8f249f12, 0xac38cb6e, 0xd3e67aec, 0xac5fc03c, 0xf4275cd9, 0xbd452ddc, 0xb7912bbf, 0xc94e6d73, 0xe1e0c370, 0x4cbef402, 0x7fdeb182, 0x237b5f2e, 0x15a094fb, 0x71d7c5a8, 0xd75c03f7, 0x3d6931aa, 0x37da3c9b, 0x7edf46cc, 0xc39a6b10, 0xfef35aba, 0x117de6b2, 0x1f749298, 0xeb34c513, 0x52cb91d4, 0x15c79fa9, 0x28c9a551, 0xee8f4b46, 0x1aa8179f, 0xb24daeb8, 0xa7ed3a43, 0x4dd8081e, 0x111aede0, 0xdceef988, 0x7a653fd7, 0x6511ad4f, 0xb690dcf1, 0xb32b52a4, 0x49057a57, 0xfb48d4ef, 0xea35325d, 0x6b7fd237, 0x9be2f7f5, 0x476b052f, 0x36bcc087, 0x7fb9bad0, 0x2d152056, 0x58789ce5, 0x231c547c, 0x8f439440, 0x5671e8cf, 0xf541a0c5, 0xb9ff54c7, 0x5ca5eeac, 0x7eb84d9e, 0x00000000, 0x04dd7249, 0xf0fa2e90, 0xfe9451e8, 0x6576a61d, 0x750ab7e1, 0x9136f196, 0x6ec45c62, 0x6a192e2b, 0x28aeae03, 0x14c668e7, 0xf440578b, 0xcdf41468, 0xfb2fdfbd, 0xe43c4677, 0xef8ebc08, 0x4dbf034c, 0x53ad6dc8, 0x9e3e72f2, 0xeb53ce41, 0xb899a8db, 0x9f3f85bc, 0x14a163b5, 0x7a023485, 0x6fc5ab2c, 0x39d348b1, 0xddef0ec6, 0xe45b4d25, 0xe53db139, 0x756dbcb3, 0x94ea7491, 0x90500d8a, 0x70b139b4, 0x04ba791b, 0x1e7565d6, 0x812deb38, 0x59796bab, 0x3c68c6e4, 0x53ca669a, 0xc646ee17, 0x2d722b04, 0x8e42630e, 0xe187c822, 0x9a840be9, 0x0ab30d31, 0x6ea35730, 0xbc44da92, 0x33074ed2, 0xd8548093, 0x29c8521f, 0x1e126e84, 0xfa2e28f3, 0x57701f81, 0x39b443e3, 0xefe9b75a, 0x27c12635, 0xd2e78da2, 0xa231bf44, 0xe55aba6b, 0x0bd5f12d, 0x61ccdf06, 0x84f16e3f, 0xe0863f6c, 0x221da332, 0x60cd2848, 0x5cc2e5fe, 0x27a62d67, 0x38d2bfff, 0xff95a6a6, 0x43d17c34, 0xc720120b, 0xcd931f3a, 0x0f6f8836, 0x591e60f9, 0xb34c59f6, 0xa78a3111, 0x36dbcbd5, 0xf526ab97, 0x9b85fca7, 0x9151fac4, 0x38b5b4ad, 0x85f09971, 0x0e09742a, 0xb22aa5ea, 0x26c0d17b, 0xdd880594 +}, +{ +0xdf5c8859, 0x6b48ad8f, 0x1336debf, 0xd778e993, 0x6c6f936f, 0x8fcbfb7a, 0x8f80fc0f, 0x349786f3, 0x31de0d57, 0xe4c85180, 0x88ecc59a, 0xcc6a56e6, 0x086f66bf, 0x3cf8e04c, 0x0a4ad48e, 0xc923dd42, 0x19370d44, 0xf092b6aa, 0x93b57d9a, 0xc14cbbfd, 0xeca7373f, 0xe9a5bbee, 0xbe5ef158, 0x80c8a450, 0x25cfed08, 0x4e874087, 0x662547e1, 0xb932c8cd, 0xdd793a68, 0x41cf18d8, 0x6327cb30, 0xaa041672, 0x7f124aa5, 0x46a3214d, 0x1c7e86e0, 0xaf069aa3, 0x6e4a215e, 0xb116a907, 0x52b2c112, 0x9cfd25c5, 0x43a1ad9c, 0xb63197e7, 0x49eb7912, 0x9492437a, 0xd27a6542, 0xd2316237, 0xc107bc88, 0x9e939081, 0x61027901, 0xf5903a7b, 0x8a8270de, 0x4ce9f5c3, 0x167f551b, 0x78357445, 0x2accb222, 0xe181da24, 0x787e7330, 0x696d1fbe, 0x0f035f2a, 0x58f8159c, 0x2da08bb7, 0x11136c8e, 0x77362b6f, 0xcb066f73, 0xa86aa336, 0x82a61114, 0xff91e980, 0x87ef9ab0, 0x5a96a0d8, 0xbb5c7d89, 0xfdff5cc4, 0x11586bfb, 0xe9eebc9b, 0xfa936551, 0xf7fe8f3f, 0x004b0775, 0x46e82638, 0xf7b5884a, 0x7d37f894, 0xeb8009df, 0xa04ec2fc, 0x93fe7aef, 0xebcb0eaa, 0xb41425d6, 0x5f942c09, 0x3cb3e739, 0xf2b7049b, 0x0225b231, 0xb67a9092, 0x705a12fa, 0x20cd61d9, 0x0d6dea6e, 0x1e5b34d1, 0x87a49dc5, 0x7a5bc101, 0xe1cadd51, 0xa5074958, 0x55def887, 0xa005c589, 0xbc30441c, 0xce4fe4d7, 0xffdaeef5, 0x96fcf63e, 0x94d9440f, 0x4486937c, 0xbb177afc, 0x0f48585f, 0x5595fff2, 0x36b234c2, 0x777d2c1a, 0xd014d006, 0xc6208268, 0xe6a6e4c4, 0x44cd9409, 0x9190cfab, 0x9cb622b0, 0xbe15f62d, 0x8ac977ab, 0x91dbc8de, 0x9bda1b25, 0x2584ea7d, 0x636ccc45, 0xd55d5ba2, 0x7a10c674, 0xcc215193, 0xb3331b36, 0x4b85cc56, 0xe6ede3b1, 0xad682fe7, 0xa54c4e2d, 0x99ffa914, 0x61497e74, 0xdd323d1d, 0xa769fc1c, 0xf8b6d760, 0x666e4094, 0x5fdf2b7c, 0xd05fd773, 0xd733eee6, 0x6400f5d0, 0x8da54e3e, 0x2a87b557, 0x7f594dd0, 0x49a07e67, 0x57b04dc3, 0xecec304a, 0x31950a22, 0xda1503fd, 0x1b12bf75, 0xbc7b4369, 0x5db19e38, 0x85ca2881, 0x43eaaae9, 0x0a01d3fb, 0x05028cd1, 0xd830b1cc, 0x082461ca, 0x1c358195, 0x9ed897f4, 0xb45f22a3, 0x85812ff4, 0x33fbbf66, 0x36f933b7, 0x137dd9ca, 0x05498ba4, 0x0d26ed1b, 0xa26b70cd, 0x22a3d49d, 0xeec9827b, 0x3edd527d, 0x50dc7456, 0xad232892, 0xda5e0488, 0xaf4d9dd6, 0x8dee494b, 0x00000000, 0xc4053059, 0x07273ee0, 0xc36909cc, 0xb15dae72, 0x27a1584c, 0x692618cb, 0x28e90013, 0xaa4f1107, 0x3e965508, 0x197c0a31, 0xce04e3a2, 0x96b7f14b, 0xb3781c43, 0x39fa6c9d, 0xdf178f2c, 0xf2fc03ee, 0x4ecc47f2, 0x3b94d9d9, 0x27ea5f39, 0xee82850e, 0x208666ac, 0x7011158f, 0x026eb544, 0xf0d9b1df, 0xe3ef6f60, 0x5adda7ad, 0x2fce3ef3, 0xf5db3d0e, 0xc968da37, 0x33b0b813, 0xfad86224, 0x7d7cffe1, 0xe3a46815, 0x145ae72a, 0x50977323, 0x5dfa994d, 0x3bdfdeac, 0xa821a443, 0xe48356f5, 0x727fa0cb, 0x1411e05f, 0x2deb8cc2, 0x75589e2b, 0x52f9c667, 0x28a20766, 0x1b59b800, 0x88a7c2ef, 0x1634526e, 0xfdb45bb1, 0x99b4ae61, 0xb979cfb8, 0x57fb4ab6, 0x2f853986, 0xc44e372c, 0x41841fad, 0x4bcecb23, 0xd5165cd7, 0x58b312e9, 0x22e8d3e8, 0x39b16be8, 0x7513995e, 0xc3220eb9, 0xd87bb6b9, 0x8083a325, 0x6c24941a, 0x6b03aafa, 0x644bf2a5, 0x7234a7be, 0xc66b851d, 0x9b911c50, 0x82ed1661, 0x076c3995, 0xcb4d6806, 0xa722fb69, 0x4ca2f2b6, 0xf8fdd015, 0x1e1033a4, 0x34dc8186, 0x6e01262b, 0xa22077b8 +}, +{ +0xf92c605c, 0x17f61a0f, 0xfcb3ba55, 0xd7db475f, 0xe6f578df, 0xa9e42ee6, 0x38458ff8, 0xa454f663, 0x59a3fec2, 0x76106b35, 0xdc9af542, 0xa2a59cfb, 0xb4173400, 0xc169efa4, 0xeb45a05a, 0x036eb091, 0xcb6cef4d, 0x53a6fe2b, 0x9750cb86, 0xecf07836, 0xbd7c8478, 0xf047d024, 0x096bb078, 0x70e101ad, 0x6f38192e, 0x653d19c7, 0xb55386f4, 0x7d51d928, 0xd3002fa2, 0x2cdd2566, 0x3c9ee705, 0xd9052f4b, 0xfa42d0cd, 0x9c11799b, 0x7c156bdc, 0xa67ef406, 0x577d96d6, 0x957ac9e3, 0xaf15447e, 0x0ede6814, 0xbe1234e9, 0x306a8d74, 0x24f227ea, 0xc343edc1, 0xabce2c83, 0x6c56a9bf, 0x22034d72, 0x0a0500e9, 0x0cf46a71, 0x98ca1166, 0x938ba37b, 0x2d999792, 0xca285db9, 0xf10362d0, 0xa5104497, 0x5f52945a, 0x8be76394, 0x92cf118f, 0xfe99b830, 0xb7798491, 0x3eb4e560, 0x39013d0c, 0x943e7b17, 0xaa8a9e77, 0x5b89fca7, 0x4c7fe6a8, 0xf26dd241, 0x2b68fd0a, 0xa08f9e9e, 0xc4f635ad, 0x8e78b99d, 0x9f7fc90a, 0x3dda55f1, 0x408b8cd9, 0x4e55e4cd, 0x42a18ebc, 0x7ae40144, 0xb9a7ec85, 0x04db68fd, 0xe7b1ca2b, 0x4bca3ec4, 0x8d16090c, 0x4f115639, 0x28064d9b, 0x43e53c48, 0xedb4cac2, 0xe140a0b3, 0xe4df7aba, 0x78ce0321, 0x6d121b4b, 0x1a46c28a, 0xccd93721, 0x4a8e8c30, 0x00000000, 0x9ba4a1f7, 0xa73a46f2, 0xe22e1022, 0x1928721b, 0xd12a2dc7, 0x52e24cdf, 0x1e9daa77, 0xcd9d85d5, 0x8889d305, 0xa8a09c12, 0x63cc735f, 0x518cfc4e, 0x7754d9c1, 0xcfb787b0, 0x451456d0, 0x2fb395f7, 0x871309e5, 0xa3e12e0f, 0x6e7cabda, 0x9ae01303, 0xef9ec8a7, 0x688dc142, 0xf49cb8d9, 0xb188ee09, 0x32408f11, 0x20294f17, 0xfdf708a1, 0x7ba0b3b0, 0xd4b5f7ce, 0x54132647, 0x71a5b359, 0x3a6f8d9d, 0xc8025fdc, 0x6aa7c327, 0x6be371d3, 0x8f3c0b69, 0x1fd91883, 0x5c3c24cb, 0xe96fa23f, 0x26d8258f, 0x6288c1ab, 0x61e6713a, 0x37df5518, 0x90e513ea, 0xc6dc37c8, 0xd2449d56, 0x72cb03c8, 0x9d55cb6f, 0x757edba4, 0x8657bb11, 0x89cd61f1, 0x2a2c4ffe, 0xea0112ae, 0x1b02707e, 0xc2075f35, 0x8aa3d160, 0xbf56861d, 0x5d78963f, 0x2ef72703, 0x998ea392, 0xdeb0f727, 0x0144b2f4, 0xd69ff5ab, 0xbac95c14, 0xc946ed28, 0xf6b6babc, 0x798ab1d5, 0xad3f461b, 0x0b41b21d, 0xa1cb2c6a, 0x3b2b3f69, 0x48a48e55, 0x56392422, 0x06f16a98, 0x279c977b, 0x6653a956, 0x67171ba2, 0xddde47b6, 0x1269c006, 0xb63d3665, 0x69c973b6, 0x07b5d86c, 0xdff445d3, 0x85390b80, 0x8c52bbf8, 0x6479ab33, 0x15dc186a, 0xc5b28759, 0x35f5577d, 0x83c86118, 0xda6b9fda, 0x828cd3ec, 0x312e3f80, 0xbc38368c, 0xbb8deee0, 0xfb066239, 0x1498aa9e, 0x58e74c36, 0xe36aa2d6, 0xdb2f2d2e, 0x186cc0ef, 0x1043c263, 0xe82b10cb, 0x34b1e589, 0xeeda7a53, 0xd8419dbf, 0xac7bf4ef, 0xffdd0ac4, 0x5acd4e53, 0x1df31ae6, 0x743a6950, 0x5e1626ae, 0x41cf3e2d, 0x473e54b5, 0x216dfde3, 0x25b6951e, 0xf32960b5, 0x96147972, 0xb2e65e98, 0x0db0d885, 0x369be7ec, 0xcef33544, 0xb8e35e71, 0x082f028c, 0xf5d80a2d, 0xe59bc84e, 0x91a1a11e, 0xc798853c, 0x1cb7a812, 0x9e3b7bfe, 0x2347ff86, 0x132d72f2, 0xc02d5d50, 0x738fb13c, 0xe0041247, 0xae51f68a, 0xd06e9f33, 0xb3a2ec6c, 0x33043de5, 0x49e03ca1, 0x4450e424, 0x11077097, 0x50c84eba, 0x467ae641, 0xb0cc5cfd, 0x3ff05794, 0x0f9adae0, 0x7f7bdb4d, 0xf868d2a8, 0x555794b3, 0x80a6d189, 0x81e2637d, 0x7e3f69b9, 0x022a0265, 0x2942ff6f, 0xf7f20848, 0x60a2c3ce, 0xd5f1453a, 0x4d3b545c, 0x16b2a8fb, 0x059fda09, 0x847db974 +}, +{ +0x95c9e877, 0xd82e1f97, 0x43705e01, 0x38790c7d, 0x8c135fd4, 0xa40b5671, 0x8b3f444e, 0xbe9d27dd, 0xa8490642, 0x2de1ebed, 0x81c8303a, 0x27169f99, 0xbdd1e1d2, 0x6f088a31, 0xd9b7204a, 0x9c725a0c, 0x2b54cfaa, 0xe9eca191, 0x71fe2608, 0x2376420c, 0x6b6857a4, 0xaf651dd8, 0x3b35ca72, 0x1843887e, 0x937ccc30, 0x01993fdd, 0xc1f4a834, 0x403c980e, 0xec1543d9, 0x9b5e4196, 0x91a935e2, 0x35a26393, 0x072c1b9a, 0x672a0797, 0x89eabd9c, 0x29813678, 0x19dab7a3, 0x0b6e4ba9, 0xcc2fc7da, 0x6ddd73e3, 0xfb585d9b, 0xa06b8be4, 0x0f0e963c, 0x80510fe7, 0xadb0e40a, 0x543d4043, 0xa6deafa3, 0x96852e78, 0x1f6f93e4, 0x78459473, 0x281809a5, 0x7ef0b034, 0x08228da6, 0xd5f57079, 0xf8149b94, 0x6e91b5ec, 0x37779a41, 0xeb395843, 0xe437ce7f, 0xf37ad03d, 0x3d80ee35, 0xeec0ba0b, 0xd195adec, 0x22ef7dd1, 0xb6bfaa7b, 0x0c425033, 0x2ead2de2, 0x505d9dd6, 0x106105d8, 0x31c2be06, 0x12b4fc0a, 0x5b33d67f, 0x51c4a20b, 0xdf02040d, 0x85a8edaf, 0x328e7809, 0x0460dd95, 0xc2b86e3b, 0x132dc3d7, 0x4acbec7a, 0x79dcabae, 0xe31bd5e5, 0x706719d5, 0xa9d0399f, 0xdafbe645, 0xcefa3e08, 0x831dc9e8, 0x6466c198, 0xc84f1a4f, 0xb46a53a9, 0x4c7ec83d, 0x971c11a5, 0xb3464833, 0x56e8b991, 0x98128799, 0x69bdae76, 0x5771864c, 0x7dbc763b, 0xe77b0870, 0xbb64c595, 0xc06d97e9, 0x7b09527c, 0x88738241, 0x5eca3437, 0xbc48de0f, 0x587f1070, 0x5aaae9a2, 0x203a8403, 0x49872a75, 0x72b2e007, 0x8d8a6009, 0x1ef6ac39, 0xb5f36c74, 0x7a906da1, 0x331747d4, 0x09bbb27b, 0xef5985d6, 0x9ea7a3de, 0xc59475a1, 0xc9d62592, 0xac29dbd7, 0x8ec6a606, 0x4de7f7e0, 0x52886404, 0x06b52447, 0x305b81db, 0x7f698fe9, 0x4689bc49, 0x0e97a9e1, 0x00000000, 0xb193b1e1, 0x1401d84d, 0x5d86f238, 0xe1ce2c37, 0x11f83a05, 0xa747907e, 0xf1af29ef, 0x1a9671ac, 0x6c444c3e, 0xe5aef1a2, 0x55a47f9e, 0xd6b9b676, 0x877d147d, 0x42e961dc, 0xddd7fddf, 0xd72089ab, 0xd2d96be3, 0x3ecc283a, 0xfea1bfd3, 0x2acdf077, 0xdc4ec202, 0xaa9cff90, 0x1dba6a36, 0x034cc60f, 0x0ddb6fee, 0x634ada02, 0x60061c0d, 0x5c1fcde5, 0x8284f635, 0x998bb844, 0xa2be7236, 0xf71a0da8, 0x759efb9d, 0xe8759e4c, 0x2f34123f, 0x86e42ba0, 0x36eea59c, 0xcdb6f807, 0xd00c9231, 0x732bdfda, 0x53115bd9, 0xe6e237ad, 0x3aacf5af, 0xeaa0679e, 0x9ac77e4b, 0x682491ab, 0xa3274deb, 0x4b52d3a7, 0xf2e3efe0, 0xc6d8b3ae, 0x174d1e42, 0x445c459b, 0xf0361632, 0x7c2549e6, 0xc32151e6, 0xfc744601, 0x5f530bea, 0xb9b13c47, 0xb72695a6, 0xca9ae39d, 0xbf041800, 0x9f3e9c03, 0x3f5517e7, 0x90300a3f, 0xa59269ac, 0x1b0f4e71, 0x619f23d0, 0x45c57a46, 0xa1f2b439, 0xd46c4fa4, 0x05f9e248, 0x02d5f9d2, 0xff38800e, 0xf98da449, 0xaefc2205, 0xc40d4a7c, 0xc7418c73, 0x41a5a7d3, 0xfac16246, 0x8aa67b93, 0x481e15a8, 0xdb62d998, 0xe05713ea, 0xab05c04d, 0x92e5f3ed, 0x9deb65d1, 0x65fffe45, 0xe282ea38, 0x774b024f, 0xcf6301d5, 0xfded79dc, 0x3c19d1e8, 0x7407c440, 0xed8c7c04, 0x25c3664b, 0x2c78d430, 0x1c2355eb, 0x39e033a0, 0x8431d272, 0x4eab31ef, 0xf456cba7, 0x21a3bbde, 0xf5cff47a, 0x59e62fad, 0x9450d7aa, 0xb2df77ee, 0x76d23d92, 0x6af16879, 0x1598e790, 0xcb03dc40, 0x62d3e5df, 0xbafdfa48, 0x66b3384a, 0x245a5996, 0xde9b3bd0, 0xd340543e, 0x343b5c4e, 0x0af77474, 0x16d4219f, 0x47108394, 0xb00a8e3c, 0xf6833275, 0x268fa044, 0xb828039a, 0x8f5f99db, 0x4f320e32 +}, +{ +0x3aadac3c, 0xddaf6813, 0x8f37c958, 0x89c23f1f, 0x4b93f4f1, 0x709f8468, 0xb43bb9c1, 0x158729f1, 0x701b2c96, 0x7db22486, 0xd7524ae1, 0x9c4516ee, 0x2e8b5968, 0x00000000, 0xce591f5b, 0x5e14dd00, 0x96b8341c, 0x9168b600, 0x06715eb9, 0x979d4047, 0xf5d1c73c, 0xed7b4e23, 0xc3f0174b, 0x7bc37a3f, 0x846b370f, 0x55cc8ba9, 0x9b113c0c, 0x5fb501a5, 0x7a62a69a, 0x3cdcf285, 0xb59a6564, 0x0bd856a9, 0x63ed5bde, 0xda7fea0f, 0x7ae60e64, 0xdc0eb4b6, 0xb992b1d1, 0x4de2aa48, 0x5e9075fe, 0xf8fc67d2, 0xdc8a1c48, 0x6e4453ce, 0x416ed603, 0x4c4376ed, 0x1503810f, 0x2fae2d33, 0x29df738a, 0xd6773eba, 0xaa64c699, 0xc90d35b9, 0xe0d24633, 0xf3a09985, 0x62c82f85, 0x8863e3ba, 0x7c13f823, 0x84ef9ff1, 0xb36f9323, 0xedffe6dd, 0xaae06e67, 0x821a69b6, 0xf4701b99, 0x22072523, 0xa6e8bad2, 0xeb8eb864, 0x37800cd2, 0xe7866cd1, 0x0afd22f2, 0x64b9713c, 0x894697e1, 0x0c08d4b5, 0x6518ad99, 0x0125745b, 0x77cbae8a, 0x0c8c7c4b, 0xf878cf2c, 0xd1a7bca6, 0xeaabcc3f, 0x3c585a7b, 0x904dc25b, 0x91ec1efe, 0x6910792c, 0x07d0821c, 0xc8ace91c, 0x5f31a95b, 0x1ffea3fd, 0x90c96aa5, 0x25d7a73f, 0x404ba258, 0x9cc1be10, 0xbec69b33, 0x30508ece, 0xffa84d30, 0xec5e3a78, 0x4cc7de13, 0xcf7c6b00, 0x1e5f7f58, 0xc4a43da9, 0xd0066003, 0xbf674796, 0x287eaf2f, 0x23a6f986, 0x182e21e1, 0x546d570c, 0x23225178, 0x624c877b, 0xab41b2c2, 0xc2d56310, 0xf2014520, 0x9a344857, 0x31f1526b, 0x14a25daa, 0x8e9615fd, 0x774f0674, 0x659c0567, 0xc58149f2, 0x4a322854, 0x521c09b5, 0x0084a8fe, 0x2f2a85cd, 0xceddb7a5, 0x9719e8b9, 0x54e9fff2, 0x4d6602b6, 0x46be541f, 0x9ab0e0a9, 0x6994d1d2, 0xf285edde, 0x7b47d2c1, 0xecda9286, 0x5940f7e2, 0x1257abed, 0x1edbd7a6, 0x53bdd510, 0xd082c8fd, 0xeb0a109a, 0x963c9ce2, 0x28fa07d1, 0x713e58cd, 0xadb44485, 0x01a1dca5, 0xb51ecd9a, 0xf324317b, 0x68b1a589, 0x6fe58f6b, 0xbe4233cd, 0x9b9594f2, 0xdd2bc0ed, 0xac159820, 0xd1231458, 0xe1739a96, 0x6ec0fb30, 0x85caebaa, 0x3175fa95, 0xd6f39644, 0x829ec148, 0x7c9750dd, 0xb4bf113f, 0x3704a42c, 0x41ea7efd, 0xfe099195, 0xdafb42f1, 0xdbde36aa, 0x7d368c78, 0x586583b9, 0x0d2da0ee, 0x190b55ba, 0xcff8c3fe, 0x0a798a0c, 0x9de4ca4b, 0xa7cdce89, 0xad30ec7b, 0x55482357, 0x854e4354, 0x13f67748, 0xa1bc9030, 0xb8b7c58a, 0xe6a3188a, 0xb24ae778, 0x58e12b47, 0x1f7a0b03, 0xa01d4c95, 0x3b0c7099, 0xf4f4b367, 0x479b2044, 0x4ab680aa, 0x30d42630, 0xe056eecd, 0xb8336d74, 0xf9d91389, 0xea2f64c1, 0x59c45f1c, 0x8e12bd03, 0x68350d77, 0x83bbb513, 0xdb5a9e54, 0xc374bfb5, 0x5298a14b, 0x766a722f, 0x833f1ded, 0x295bdb74, 0x3621d077, 0xc4209557, 0x3a2904c2, 0x1426f554, 0x4b175c0f, 0x22838ddd, 0x3df986de, 0xb3eb3bdd, 0xc251cbee, 0xd7d6e21f, 0x76eedad1, 0x3d7d2e20, 0xc505e10c, 0x471f88ba, 0xa7496677, 0xb916192f, 0xff2ce5ce, 0xa13838ce, 0xe702c42f, 0xfe8d396b, 0x0b5cfe57, 0x71baf033, 0xa099e46b, 0xb2ce4f86, 0x2e0ff196, 0xac9130de, 0xc9899d47, 0x18aa891f, 0x0da90810, 0xf95dbb77, 0xf5556fc2, 0x1372dfb6, 0x8fb361a6, 0x07542ae2, 0x40cf0aa6, 0x9d6062b5, 0x36a57889, 0x6369f320, 0x198ffd44, 0x88e74b44, 0x643dd9c2, 0x25530fc1, 0x6f612795, 0xe1f73268, 0x3b88d867, 0x24f2d364, 0x463afce1, 0xbfe3ef68, 0x53397dee, 0x12d30313, 0x06f5f647, 0x24767b9a, 0xa66c122c, 0xe627b074, 0xc82841e2, 0xabc51a3c +}, +{ +0x8b808b93, 0x09b3f4c1, 0x202d6b88, 0x314d1dec, 0xbca04b06, 0x1f8b6361, 0xd7a25338, 0x53fcf113, 0xafa7e2db, 0x2ff34230, 0x35471f2c, 0x88d26897, 0xbd9577bb, 0xda1ba539, 0x4d42aecf, 0xbacd967f, 0x5c22d8ab, 0x856b9e96, 0xcc233299, 0x7805b1e3, 0x9c8d208e, 0x81619c56, 0x57f6f3d3, 0x237f888c, 0x9db81c33, 0xae92de66, 0x27758a4c, 0x591de6d6, 0x156a74a4, 0x9266358b, 0xa32b2867, 0x469685b7, 0x6f081afe, 0x2ec67e8d, 0x40fb58ce, 0xb02c81ba, 0x040a02c0, 0x8ab5b72e, 0x953ed44f, 0xc2c8279c, 0x89e7542a, 0xb8aa49c6, 0x5a4f05d2, 0x7083799f, 0x54a410d7, 0x47a3b90a, 0x332ac255, 0x18d382a5, 0x8ded56ea, 0x5f703baf, 0x2ca1a134, 0x3e933454, 0x321ffee8, 0x170dab1d, 0xd0fab2fc, 0x0bd42b78, 0x28aba3f4, 0xf2b006cd, 0x73d19a9b, 0xb37e62be, 0x053f3e7d, 0xe8045bd1, 0x6a372483, 0xfd6e2f75, 0xa473c9a3, 0x6850fb3a, 0xe488916d, 0xb513bfc7, 0xacf501df, 0x6d6fc547, 0x10554ad9, 0x99b21ef3, 0x3dc1d750, 0xbbf8aac2, 0xdd4344fd, 0x65e90d3b, 0xa9ca3fa2, 0xb99f757b, 0x76eea4e6, 0xee6986a8, 0x74897b5f, 0x6e3d2643, 0xcf71d19d, 0x6965c787, 0x1ab45d1c, 0x845ea22b, 0xe931676c, 0x224ab431, 0x6384d042, 0xc7f719e1, 0xde11a7f9, 0x830643ef, 0x1307a9dd, 0x3fa608e9, 0x6b02183e, 0x1decbcd8, 0xef5cba15, 0xed3b65ac, 0xf5e8e709, 0xc590c658, 0x52c9cdae, 0x3a993694, 0x19e6be18, 0x93530936, 0x9bd5c14a, 0x71b64522, 0xa079cb63, 0x9fdfc38a, 0x4f257176, 0x7a626e5a, 0x7b5752e7, 0xfa36ceb1, 0xea638468, 0x4a1a4f0b, 0x01353cbd, 0x0758e1c4, 0x24276948, 0x1ebe5fdc, 0x966c374b, 0x82337f52, 0xf3853a70, 0x11607664, 0x7d3a8f9e, 0x45c466b3, 0xe2e54c14, 0x7e686c9a, 0x21185735, 0x61e30ffb, 0x55912c6a, 0x56c3cf6e, 0xd3a851f8, 0x9001ea32, 0xa8ff031f, 0x6c5af9fa, 0x41ce6473, 0x62b1ecff, 0x2acc7c4d, 0xf4dddbb4, 0xdf249b44, 0x1cd98065, 0xd949463d, 0x43a9bbca, 0x8f8a8953, 0x9ae0fdf7, 0x4948ac0f, 0xc19ac498, 0xe3d070a9, 0xc4a5fae5, 0x3cf4ebed, 0x60d63346, 0xca4eefe0, 0x0886c87c, 0x4b2f73b6, 0x7c0fb323, 0xa614161a, 0x0352e304, 0x0c8ccabc, 0xe08293ad, 0x2bf940f0, 0x50ae1217, 0xb24b5e03, 0x66bbee3f, 0x38fee92d, 0xeb56b8d5, 0x519b2eaa, 0x299e9f49, 0xc8293059, 0x2640b6f1, 0x487d90b2, 0x86397d92, 0x0267dfb9, 0x0eeb1505, 0xadc03d62, 0x3615fc28, 0xdc767840, 0xa14cf7de, 0x9134d68f, 0x5828da6b, 0xff09f0cc, 0xe1b7af10, 0xe5bdadd0, 0x066ddd79, 0xfc5b13c8, 0xbec794bf, 0x79308d5e, 0x145f4819, 0xcd160e24, 0x34722391, 0x251255f5, 0xa7212aa7, 0xe7da7269, 0x0fde29b8, 0x1b8161a1, 0x97590bf6, 0x7f5d5027, 0x870c412f, 0x4c779272, 0x0ae117c5, 0xb6415cc3, 0xf8511108, 0x2d949d89, 0xb426837a, 0xd4f0b03c, 0xd1cf8e41, 0xb774607e, 0xce44ed20, 0xaa98dca6, 0xd87c7a80, 0xb119bd07, 0x0db9f601, 0xc3fd1b21, 0x8ebfb5ee, 0x75bc47e2, 0x39cbd590, 0x77db985b, 0xd6976f85, 0xdb2e9984, 0x44f15a0e, 0x940be8f2, 0x9eeaff37, 0xf0d7d974, 0x8cd86a57, 0xf9642db5, 0x4e104dcb, 0xec0e5911, 0x429c8777, 0x8054a0eb, 0x72e4a626, 0x12329560, 0xabade01b, 0x3bac0a29, 0xd29d6d45, 0xfe3ccc71, 0xe6ef4ed4, 0xa21e14da, 0xf1e2e5c9, 0xc0aff825, 0xf6ba040d, 0x00000000, 0xfb03f20c, 0xc91c0ce4, 0x64dc3186, 0x678ed282, 0x9887224e, 0xc6c2255c, 0xa546f51e, 0x5e450712, 0xd5c58c81, 0x5b7a396f, 0xcb7bd35d, 0xf78f38b0, 0xbff2a802, 0x3720c095, 0x30782151, 0x163897a0, 0x5d17e416 +}, +{ +0x5259beb3, 0x82ccadc1, 0xdb21913a, 0xf0159f57, 0x1102a067, 0x9c907f8a, 0xbd4d75a5, 0xa8a525a6, 0x67316295, 0xe7f4d13f, 0x7f8e5ed1, 0x4e0c7293, 0x6fd178bc, 0x31822c42, 0x59ed3cfb, 0x015d860a, 0xb8fa03cb, 0x2a698867, 0x4f51f499, 0x2c8a6668, 0x2dd7e062, 0x6c85e0dd, 0x0d576c47, 0x2860960c, 0x4ae682f7, 0xc197b315, 0x12563806, 0x987a8fee, 0x56b34ed7, 0xbe19edc4, 0x03549861, 0x8d92dfed, 0xca23315d, 0xa118b985, 0xf6f67158, 0xc629db10, 0x2fdefe09, 0x952de3a9, 0x16bcc862, 0x3edc5e6e, 0x09bd9c23, 0xd29c0d19, 0xb01a19e2, 0xef14cb16, 0xae46cba9, 0xd522651c, 0x796db0de, 0x8b7131e2, 0xd72b7b77, 0x47b1eeb0, 0x4c056cf8, 0x9a739185, 0xee494d1c, 0x2663622a, 0x02091e6b, 0xc0ca351f, 0x608f0a90, 0x0f5e722c, 0x0bb48248, 0x4d58eaf2, 0x49b21a96, 0x383fb061, 0xf7abf752, 0x992709e4, 0xc977a93c, 0xe5fdcf54, 0xcec9c139, 0x23d41444, 0xf148195d, 0x1ab6222f, 0x54ba50bc, 0x86265da5, 0xf4ff6f33, 0xb1479fe8, 0x0e03f426, 0x07be6805, 0xa4afcfeb, 0x2289924e, 0x8ccf59e7, 0x75675a93, 0x0c0aea4d, 0x2537fa4b, 0x6465faf4, 0xd1c89578, 0x15e85003, 0x293d1006, 0xa0453f8f, 0xe4a0495e, 0x2e837803, 0xcb7eb757, 0x7d8740ba, 0xfafc9b15, 0xe1173f30, 0x7b64aeb5, 0x415200bf, 0x34355a2c, 0x718daaf7, 0x21dd0a2f, 0x7ed3d8db, 0x08e01a29, 0xd9288f51, 0x105f266d, 0xfba11d1f, 0xd47fe316, 0x1d084a2a, 0x04eaf064, 0x91c713cd, 0x70d02cfd, 0x1f015441, 0x510d26d2, 0x9fc4e7eb, 0xb2130789, 0x693296b3, 0x19e2ba4e, 0x686f10b9, 0xad1253c8, 0xbc10f3af, 0x65387cfe, 0xd0951372, 0xc39ead7e, 0x2b340e6d, 0xcd9d5958, 0xfe166b71, 0x776e44f8, 0x8a2cb7e8, 0xe6a95735, 0x9b2e178f, 0x5d07cc9f, 0x8572c5c4, 0x783036d4, 0x06e3ee0f, 0x3d88c60f, 0x5c5a4a95, 0x8f9bc186, 0x666ce49f, 0x6b3b88d8, 0xa5f249e1, 0x5f0ed2f4, 0xec405377, 0x57eec8dd, 0x3b6b2800, 0x92938bac, 0xa9f8a3ac, 0x17e14e68, 0xebfe3b72, 0x947065a3, 0xd3c18b13, 0x4bbb04fd, 0x363c4447, 0x1c55cc20, 0xff4bed7b, 0xe9f72519, 0xda7c1730, 0xc420c57b, 0xfd42f310, 0xb5ad6f8c, 0xb6f9f7ed, 0x6a660ed2, 0x400f86b5, 0xf21c813c, 0xf3410736, 0xa6a6d180, 0xb4f0e986, 0x89782f89, 0xa24c21e4, 0xed1dd57d, 0x3568dc26, 0xb9a785c1, 0x45b8f0db, 0x3962366b, 0x3a36ae0a, 0x5050a0d8, 0xb34e8183, 0xb7a471e7, 0xddc27f35, 0xaaac3bcd, 0xbf446bce, 0xabf1bdc7, 0x1beba425, 0xa7fb578a, 0xc57d4371, 0x8ec6478c, 0xccc0df52, 0x5ab9a49a, 0x130bbe0c, 0xe243a751, 0xe31e215b, 0x819835a0, 0x18bf3c44, 0xc82a2f36, 0x9724fdc2, 0xde96e754, 0x6e8cfeb6, 0x842f43ce, 0xe8aaa313, 0x273ee420, 0xaf1b4da3, 0xac4fd5c2, 0xcf944733, 0x338b3229, 0x63db92f1, 0x3761c24d, 0x6dd866d7, 0x55e7d6b6, 0x7cdac6b0, 0x9e9961e1, 0x3f81d864, 0xdfcb615e, 0xc7745d1a, 0x5be42290, 0xbaf31da0, 0xbbae9baa, 0x246a7c41, 0x8825a983, 0x05b7766e, 0xd875095b, 0x530438b9, 0xc2c32b74, 0x3cd54005, 0x93ce0da6, 0xeaa3bd78, 0x30dfaa48, 0xfc1f751a, 0x628614fb, 0x96797bc8, 0xdc9ff93f, 0xe04ab93a, 0x80c5b3aa, 0x72d93296, 0xd676fd7d, 0x909a95c7, 0x743adc99, 0x7384b49c, 0x0ae90442, 0x9dcdf980, 0x20808c25, 0xf5a2e939, 0x46ec68ba, 0x32d6b423, 0x00000000, 0xa311a7ee, 0x14b5d609, 0xf9a80374, 0x5e5354fe, 0x48ef9c9c, 0x83912bcb, 0xf8f5857e, 0x7a3928bf, 0x44e576d1, 0x420698de, 0x61d28c9a, 0x58b0baf1, 0x7633c2f2, 0x1e5cd24b, 0x877bdbaf, 0x435b1ed4 +}, +{ +0x00000000, 0xf88fd819, 0x4a89a776, 0x1e06d09c, 0x896a4cec, 0x7a2c8347, 0xc125c7d9, 0x237281f4, 0xb2067f6f, 0x2a7dba05, 0x60f41d73, 0xc77333bf, 0x48011db8, 0xfe97baf2, 0xa1d1daaa, 0x5f08f6d5, 0xc8646aa5, 0xd975e323, 0xc5b51ffc, 0xa19f4c27, 0x8f3cb88a, 0x52971501, 0x2c65d8ee, 0x5910943e, 0x15cfc72e, 0x4e57e9de, 0xbf999cbb, 0xed401f37, 0xfa49f45a, 0xaa565b95, 0x0490d825, 0x36f3d057, 0x56495ba9, 0xa8dee15b, 0x8db40244, 0x60ba8bfe, 0xdf6d81c8, 0xe6c79e08, 0x7a6215ca, 0x410e2649, 0x1c8e6a52, 0x3435fc14, 0x753bda5d, 0x82a35b5e, 0x181eb277, 0x2c2b4e63, 0x2eed6220, 0x115f1f0b, 0xa50f9402, 0x28bb9646, 0xeb16eb51, 0x3fb27d2b, 0xdde53b06, 0x5f466058, 0x6464c556, 0xaa18cd18, 0xc73da532, 0x82edcdd3, 0x9abde929, 0xef863374, 0x8633837b, 0x62323130, 0x78a43989, 0xe6890885, 0x004e968d, 0x45d068e1, 0x32630872, 0x548f77ea, 0x5d804c1b, 0x2a332c88, 0xddabad8b, 0xbd112675, 0x95aab033, 0x69fb2682, 0xaec683b0, 0xd2f2621c, 0x7ebc5b62, 0xc5fb8971, 0xb41e1d84, 0x6b739c4c, 0xb248e9e2, 0xbb09449e, 0xa541028f, 0xb0c0532c, 0xac00aff3, 0x090f3bf1, 0xed0e89ba, 0x95e426be, 0x9ca58bc2, 0xc3ad7d17, 0xefc8a5f9, 0xf5103bcd, 0x501fafcf, 0x4758d22f, 0xe44f24c6, 0xe0dffce3, 0xf3085926, 0xf7d6178e, 0x39e4894d, 0xce329ec3, 0xccf4b280, 0x4ac731fb, 0x1e484611, 0x43869c87, 0x93b2d2d8, 0xc3e3eb9a, 0x0bc917b2, 0xe9d0c712, 0xbb47d213, 0x75754cd0, 0x0656f466, 0xcaecd06b, 0x8f722e07, 0x3ffceba6, 0x77b36093, 0xd662ba39, 0x21fa3b3a, 0xccba240d, 0x11118986, 0xd4a4967a, 0xc82afc28, 0xdf231745, 0xd62c2cb4, 0x9e63a781, 0x1ad89e34, 0xe219d0a0, 0x4c91c59d, 0xdbb3cf60, 0xb08ec5a1, 0x69b5b00f, 0xb981fe50, 0x21b4adb7, 0xd4ea00f7, 0xce7c084e, 0x66ec7f98, 0x322d9eff, 0x736d2e3b, 0xb9cf68dd, 0x627ca7bd, 0x233c1779, 0xd2bcf491, 0x7323b8b6, 0x6d6bfea7, 0x30ebb2bc, 0x0dd17559, 0x0f59cf97, 0x8be2f622, 0x8924da61, 0x459efe6c, 0x3b22a50e, 0x27accf5c, 0xac4e397e, 0x8065771d, 0x158151a3, 0x347b6a99, 0x17477de0, 0x913a6816, 0x642a53db, 0x54c1e167, 0x802be190, 0x5607cd24, 0xfc5196b1, 0x9af37fa4, 0xa7872ecc, 0x9174fe9b, 0xa7c9b841, 0x471644a2, 0xfa0762d7, 0x3d745168, 0x3b6c3383, 0xa3596064, 0x78eaaf04, 0x7ef2cdef, 0xd0344e5f, 0x7c7a7721, 0x4140b0c4, 0x8dfa94c9, 0xdbfd59ed, 0xf1ce7565, 0x1a9608b9, 0x5dceda96, 0x84bb39b5, 0x52d9838c, 0x2ea3f4ad, 0x987bc56a, 0xc16b5154, 0xbfd70a36, 0xe0916a6e, 0xf180e3e8, 0xd07ad8d2, 0x0b87813f, 0xb4508b09, 0x6d25682a, 0xe257462d, 0x976c9c70, 0x66a2e915, 0xbd5fb0f8, 0xa317f6e9, 0x061862eb, 0x36bd46da, 0x4cdf5310, 0x1709eb6d, 0xa89077d6, 0xcaa246e6, 0x0288bace, 0xe99e519f, 0x256ae31f, 0xb6d831c7, 0x1cc0fcdf, 0x0d9fe3d4, 0x39aa1fc0, 0x0941ad7c, 0x6fadd2e4, 0x25247592, 0x43c80a0a, 0xb696a74a, 0x77fdf61e, 0x13993348, 0xfc1f003c, 0x595e02b3, 0xeb587ddc, 0x8bac60af, 0xae88153d, 0x84f5af38, 0xe401b24b, 0x6b3d0ac1, 0x0f17591a, 0xf55ead40, 0x983553e7, 0x97220afd, 0x6fe34469, 0x27e259d1, 0x13d7a5c5, 0xf346cfab, 0x9e2d310c, 0x867d15f6, 0x9ceb1d4f, 0x30a52431, 0x5b982ef0, 0x4e197f53, 0x185024fa, 0xf7988103, 0x04de4ea8, 0x28f500cb, 0xf8c14e94, 0x71e594f5, 0x93fc4455, 0xfed92c7f, 0x5bd6b87d, 0x50513942, 0x02c62c43, 0xd93b75ae, 0x3d3ac7e5, 0x7c34e1ac, 0x484f8b35, 0x71ab0278 +}, +{ +0x31e1b374, 0xb6affce9, 0x4af802ad, 0x00b7398d, 0x06219e1e, 0x190260bf, 0x24939596, 0x7f3d1dc2, 0x0ae6e1ce, 0x6c6ea53e, 0xefb37f35, 0x7148699a, 0x836ae386, 0xa74e4f9d, 0x643a4f78, 0xbcfe24aa, 0x941df761, 0xedb64d30, 0x9e4c2f22, 0x2ec24dd5, 0x4c6ea53e, 0x90395b7a, 0xe5559efb, 0xbc491d27, 0x3f23fea1, 0x3d26cca4, 0x15c51f6f, 0x421bd166, 0xf027b819, 0x756cc581, 0xab89304d, 0x908e62f7, 0x87f97610, 0x1b0752ba, 0xfc57fe44, 0x648d76f5, 0xd8c46bd2, 0xf295b391, 0x20b7398d, 0x0854ea46, 0xd0908194, 0x390260bf, 0x3b0752ba, 0x26219e1e, 0xfe52cc41, 0xd873525f, 0x663f7d7d, 0xfa76605a, 0x04939596, 0x874e4f9d, 0xdee5f5cc, 0x9618c564, 0xe17132e0, 0xe7e79573, 0xde52cc41, 0x1353b8fc, 0xad1f97de, 0x98da88b1, 0x401ee363, 0x2ae6e1ce, 0x5148699a, 0x0424ac1b, 0xb8da88b1, 0xd4b42d8f, 0x02b20b88, 0x484a0925, 0x4cd99cb3, 0xc5559efb, 0xc750acfe, 0x5d382fc7, 0x57dece09, 0xe37400e5, 0xc992e12b, 0x177714e7, 0x55dbfc0c, 0x8da8ae53, 0x601ee363, 0x6edcaeb6, 0xc1c60b6d, 0x60a9daee, 0x28e3d3cb, 0x40a9daee, 0xbefb16af, 0xf2228a1c, 0xf6b11f8a, 0x42ace8eb, 0xcfb37f35, 0xa16fd183, 0xa93b3bc5, 0xb0395b7a, 0x556cc581, 0xc37400e5, 0x5b19b1d9, 0xa36ae386, 0x2a51d843, 0xe925d8a6, 0xd4031402, 0x68fd30a8, 0xcb97d32e, 0x0c70465d, 0x443a4f78, 0x7769f784, 0x898c0248, 0x6e6b973b, 0xa1d8e80e, 0x377714e7, 0x2696a793, 0x4e6b973b, 0xa98c0248, 0xcdb64d30, 0x923c697f, 0xba688339, 0x463f7d7d, 0x5769f784, 0x9cfe24aa, 0xbe4c2f22, 0xcb20eaa3, 0x11e1b374, 0x3d91f529, 0x83ddda0b, 0x48fd30a8, 0x7f8a244f, 0x0ec24dd5, 0x9efb16af, 0x6a4f3b20, 0x3bb06b37, 0x73fa6212, 0x1d91f529, 0x468844f0, 0xe750acfe, 0xd2228a1c, 0x3353b8fc, 0xe3c33968, 0xf873525f, 0x5f8a244f, 0xb28b50f2, 0x2c70465d, 0x8f1aa5db, 0x2e757458, 0x4edcaeb6, 0xd6062607, 0xb4aaceec, 0x2854ea46, 0x7b19b1d9, 0xd027b819, 0x7d8f164a, 0xb41df761, 0x35c51f6f, 0x357226e2, 0x8b89304d, 0x13e48171, 0xb618c564, 0x94aaceec, 0x816fd183, 0x986db13c, 0xb08e62f7, 0x9adfbab4, 0xa54b7d98, 0x684a0925, 0xa3ddda0b, 0x5f3d1dc2, 0x5bae8854, 0x893b3bc5, 0x0cc77fd0, 0xf4b42d8f, 0x1bb06b37, 0xc5e2a776, 0x33e48171, 0x22053205, 0x08e3d3cb, 0xef0446b8, 0xcd0174bd, 0x0a51d843, 0x791c83dc, 0x1f94c72c, 0x2424ac1b, 0x621bd166, 0x53fa6212, 0xeb97d32e, 0xf8c46bd2, 0x85fc4415, 0x81d8e80e, 0xc7e79573, 0x39b55932, 0x71ff5017, 0x668844f0, 0x77dece09, 0x62ace8eb, 0xf6062607, 0xdac159d7, 0xe1c60b6d, 0x8d1f97de, 0x591c83dc, 0x0e757458, 0xfac159d7, 0xdc57fe44, 0x37c02d6a, 0x9c491d27, 0xada8ae53, 0x157226e2, 0x8b3e09c0, 0x00000000, 0xab3e09c0, 0x854b7d98, 0x5d8f164a, 0xda76605a, 0xc3c33968, 0xc925d8a6, 0xafad9c56, 0xa7f97610, 0x2cc77fd0, 0x31568af9, 0x96affce9, 0x1d26cca4, 0xeb20eaa3, 0xa5fc4415, 0x51ff5017, 0xdce0c7c9, 0x9a688339, 0x6cd99cb3, 0x928b50f2, 0xe992e12b, 0x11568af9, 0xe5e2a776, 0x7d382fc7, 0xb23c697f, 0xd6b11f8a, 0x7bae8854, 0x6af802ad, 0x17c02d6a, 0x02053205, 0xfce0c7c9, 0x8fad9c56, 0xb86db13c, 0x534d5b9f, 0xf0908194, 0xaf1aa5db, 0xed0174bd, 0x0696a793, 0xd295b391, 0x59abba51, 0x75dbfc0c, 0xbadfbab4, 0xc17132e0, 0x4a4f3b20, 0x734d5b9f, 0x20000000, 0x448d76f5, 0xcf0446b8, 0x3f94c72c, 0xfee5f5cc, 0x1f23fea1, 0x22b20b88, 0xf4031402, 0x19b55932, 0x79abba51 +}, +{ +0x1e4f8d56, 0x941adf86, 0xe58215b3, 0xfa02f208, 0x857bc1d0, 0x90157229, 0x41009d48, 0x51aee9f3, 0x55a1445c, 0xfe18b04f, 0xef6c41f1, 0x0afbbbaa, 0xd4d52823, 0xd115ef61, 0x0f3b7ce8, 0xe042d2f1, 0xa5580dfe, 0x0b213eaf, 0x8a40bd38, 0xa08d2554, 0x547bc159, 0xbad8ea45, 0xbacd05ad, 0x8b9a383d, 0x80aee97a, 0xe45890b6, 0xc5b43675, 0xb5f67945, 0xbec2a802, 0xbf182d07, 0xcb402070, 0x450f30e7, 0xae793351, 0x9b21a36e, 0x3fa32b95, 0x3497fad2, 0x7057a0d8, 0x40cff7a5, 0x3a63ecd7, 0xbed747ea, 0xca9aa575, 0xd0da858c, 0xf4e30be5, 0x44d5b5e2, 0x11611e56, 0xd50fad26, 0x5a8fd75c, 0xda213e26, 0xffc2354a, 0x24398e69, 0xcf4f8ddf, 0x05d528aa, 0xf0eca64a, 0x8e4f1097, 0xc5a1d99d, 0x9afb266b, 0x44c05a0a, 0x4beec90a, 0xaa637116, 0xef79ae19, 0x040fadaf, 0xae6cdcb9, 0xbf0dc2ef, 0xeeb6c4f4, 0xce9508da, 0x5f5afff6, 0x7aac1b72, 0x60f9d463, 0x652cfcc9, 0xe18db81c, 0x041a4247, 0xa54de216, 0x95c05a83, 0xc1bb9bda, 0xfbcd98e5, 0xc46eb370, 0xafa3b654, 0xbb1780a8, 0x856e2e38, 0x7ea3b6dd, 0x81746c7f, 0x21f9492b, 0x411572a0, 0x1a55cf11, 0x01cf6aed, 0xeaac86b3, 0xeb7603b6, 0xe597fa5b, 0x2b02f281, 0x1f950853, 0x4a21a3e7, 0x4e2e0e48, 0xa157a051, 0x546e2eb1, 0xde2e9389, 0xda34d1ce, 0x6fd74763, 0xfe0d5fa7, 0xeab9695b, 0xdbfbbb23, 0x1b9aa5fc, 0x3e6c4178, 0x3558903f, 0xdfe1f964, 0x308db895, 0x0b34d147, 0x70424f30, 0xf5398ee0, 0x65391321, 0x3a76033f, 0xcf5a6237, 0xe44d7f5e, 0x1b8f4a14, 0xd0cf6a64, 0xd4c0c7cb, 0xb42cfc40, 0x7f6cdc30, 0x55b4abb4, 0x2b171d69, 0x5b40bdb1, 0x3bb969d2, 0x8e5aff7f, 0x3bac863a, 0x2023cc2e, 0x0ef41605, 0x4bfb26e2, 0xfbd8770d, 0x2ec235c3, 0x9b344c86, 0xc1ae7432, 0x1a4020f9, 0x84a144d5, 0xf0f949a2, 0x90009dc1, 0x2f18b0c6, 0xb02351ef, 0x14a1d914, 0x1e5a62be, 0x1f80e7bb, 0x40da184d, 0x157b5c11, 0x61235166, 0x25e30b6c, 0x91cff72c, 0xfa171de0, 0x744de29f, 0x2ad87784, 0x6a178021, 0x14b436fc, 0x6136be8e, 0xb43913a8, 0x203623c6, 0x6bd8eacc, 0xc47b5c98, 0xb1ec3b02, 0x6fc2a88b, 0x0ee1f9ed, 0x7b769e77, 0xabac1bfb, 0xd51a42ce, 0xf4f6e40d, 0xffd7daa2, 0x9ef48bc4, 0xa4976713, 0x9ee1642c, 0x8f807a7a, 0xce80e732, 0x60ec3b8b, 0x64f679cc, 0x4ff48b4d, 0x7597679a, 0xf52c6108, 0x25f6e484, 0x6bcd0524, 0xc0611edf, 0xca8f4a9d, 0x31573d90, 0xaa769efe, 0x5e807af3, 0xd1000089, 0x75828872, 0x4a344c0f, 0xa098cabc, 0xcb55cf98, 0x4fe164a5, 0xbb026f40, 0x84b4ab3d, 0x3fb6c47d, 0x0015efe8, 0x6e182d8e, 0x01da8505, 0x64e39624, 0x3482153a, 0xf123cca7, 0x81618397, 0x4e3be1a0, 0x451adf0f, 0xb5e396ad, 0x9f3be129, 0x2ed7da2b, 0x9f2e0ec1, 0x5f4f101e, 0x0aee5442, 0xeb63ec5e, 0x0f2e9300, 0xa48288fb, 0xdbee54cb, 0x91da18c4, 0x7f7933d8, 0x10ae74bb, 0x156eb3f9, 0x354d7fd7, 0x51bb061b, 0xb1f9d4ea, 0x80bb0692, 0x5a9a38b4, 0x00000000, 0x7ab9f49a, 0x05c0c742, 0x6a026fc9, 0xafb659bc, 0x8b8fd7d5, 0x95d5b56b, 0x718d25dd, 0x5e95951b, 0x9aeec983, 0x50746cf6, 0x7198ca35, 0x6e0dc266, 0x2acd986c, 0xdff4168c, 0x10bb9b53, 0x74580d77, 0x2f0d5f2e, 0xeea32b1c, 0x242c6181, 0xc074f137, 0x3142d278, 0x8a5552d0, 0xde3b7c61, 0x3e79ae90, 0x1174f1be, 0x21eca6c3, 0xf136234f, 0xa1424fb9, 0xb036be07, 0x8f959592, 0xabb9f413, 0x5061831e, 0xe19857f4, 0x5b555259, 0x7eb65935, 0x940f306e, 0x7b63719f, 0xe0573d19, 0x3098577d +}, +{ +0x6d56b409, 0xc9649f22, 0x532a34c6, 0xad97a30d, 0xd5be269e, 0x47ac856d, 0xfebd97cb, 0x8cfd799b, 0xb91112a6, 0x4e35243a, 0xff4417fa, 0x922e8a82, 0x79ec2cd3, 0xae5b40e8, 0x3db0632a, 0x1d1f10fc, 0x8d38d0db, 0xd47b8fde, 0x91de4016, 0xf4d4fc08, 0x3f8500fe, 0x78298593, 0xa7c2e1bf, 0x4dc5eeae, 0xa7fec8ce, 0x2afa3164, 0xafa2c0d9, 0x7a1ce647, 0xa4322b2b, 0x1eefda68, 0x7240ee50, 0xdc1baeb8, 0xddde07f8, 0x8f0db30f, 0x20af73d6, 0x0bacc283, 0x3fb9298f, 0x0b90ebf2, 0xe80e45b4, 0x0a696bc3, 0x5ab39591, 0x849d58fd, 0x3c49e31b, 0xfd4d5d5f, 0x64cf155e, 0xe39eae46, 0xe9f7c585, 0x00000000, 0x64f33c2f, 0x216ada96, 0xd5820fef, 0x73b96e61, 0xa5cbab1a, 0x99be6170, 0xb088b3f1, 0x4c3c6e9f, 0x1486b1ab, 0x2156f3e7, 0x4e090d4b, 0x46692c2d, 0xfd71742e, 0xa5f7826b, 0x5b763cd1, 0x445c4ff9, 0xac6e233c, 0xbb247172, 0x35d0424c, 0xcaa87cc7, 0x84a1718c, 0x28f37bc1, 0x1ed3f319, 0xca9455b6, 0x51237e63, 0x16b3d27f, 0x91e26967, 0x6536956f, 0xff783e8b, 0x1f165a59, 0xe06e64d2, 0xb3787965, 0xc1389735, 0x2ac61815, 0xac520a4d, 0x37d908e9, 0x2b3f9824, 0x52ef9d86, 0xe0524da3, 0x362088d8, 0xbaddf143, 0x1f2a7328, 0x174a524e, 0xb281f954, 0x20935aa7, 0xaf9ee9a8, 0xd64eec0a, 0x3415eb0c, 0x511f5712, 0xc331dd90, 0xd78b454a, 0x1d23398d, 0x01f98031, 0xf4e8d579, 0xb92d3bd7, 0x03cce3e5, 0x718c0db5, 0x08602166, 0x9a728295, 0x35ec6b3d, 0x8751bb18, 0x4599e6b9, 0xea070f11, 0x727cc721, 0x361ca1a9, 0x17767b3f, 0x023563d4, 0xa63b618e, 0x7a20cf36, 0x4df9c7df, 0x6caf3438, 0xb17133c0, 0x71b024c4, 0xd7b76c3b, 0xb2bdd025, 0x6ea67e9d, 0x9027c027, 0xae676999, 0xb8d4bbe6, 0x7815ace2, 0xcb6dd587, 0x876d9269, 0x9bb72bd5, 0x6f5ffeac, 0xa60748ff, 0x673fdfca, 0xf724369c, 0x3e7c80cf, 0x01c5a940, 0x7049a4f5, 0x4655055c, 0x50dafe52, 0x3429c27d, 0x0a5542b2, 0xbae1d832, 0x6f63d7dd, 0xb14d1ab1, 0x5a8fbce0, 0xe9cbecf4, 0x5b4a15a0, 0x44606688, 0xebc2a651, 0xf6e19fdc, 0xe2672e77, 0xbb185803, 0x3c75ca6a, 0x1ce690cd, 0x4790ac1c, 0x45a5cfc8, 0x2936d281, 0xb3445014, 0xdc2787c9, 0xadab8a7c, 0x9847e141, 0x8ef4333e, 0x73854710, 0x28cf52b0, 0xe3a28737, 0x229a1002, 0xfc88f41f, 0x37e52198, 0xc2c85da1, 0x8d04f9aa, 0xc8a13662, 0xc0fd3e75, 0x50e6d723, 0xcb51fcf6, 0xe25b0706, 0x3d8c4a5b, 0xf52d7c39, 0x5886f645, 0x22a63973, 0xa40e025a, 0x8cc150ea, 0x3e40a9be, 0x4ff08d7a, 0x1cdab9bc, 0x09a58826, 0x8558f1bd, 0x987bc830, 0x8f319a7e, 0x157f319a, 0x0999a157, 0xe1abcd92, 0xc2f474d0, 0xfcb4dd6e, 0xdfd74d5d, 0xc30df4e1, 0x86a83b29, 0x59435f05, 0xc104be44, 0x8564d8cc, 0x7bd94f07, 0x70758d84, 0xebfe8f20, 0x901be956, 0x085c0817, 0x7be56676, 0x23639033, 0x650abc1e, 0x66c65ffb, 0x79d005a2, 0xf5115548, 0x4c0047ee, 0x290afbf0, 0x9a4eabe4, 0xd447a6af, 0x8ec81a4f, 0x52d3b4f7, 0xb8e89297, 0x14ba98da, 0x9b8b02a4, 0x003c2971, 0x53161db7, 0x9212a3f3, 0xdfeb642c, 0x597f7674, 0x93eb23c2, 0xf6ddb6ad, 0xe8326cc5, 0xde12e41d, 0x4fcca40b, 0xd672c57b, 0x58badf34, 0x168ffb0e, 0xc958b653, 0x154318eb, 0x03f0ca94, 0xb0b49a80, 0x99824801, 0xde2ecd6c, 0xea3b2660, 0x6e9a57ec, 0x86941258, 0x6703f6bb, 0x6c931d49, 0x66fa768a, 0xc89d1f13, 0xf7181fed, 0xdde22e89, 0x2b03b155, 0x235fb942, 0xe197e4e3, 0x02094aa5, 0xc0c11704, 0x6d6a9d78, 0x93d70ab3, 0xfe81beba +}, +{ +0x26729096, 0x7c2f3219, 0x5c90bcc6, 0x0b2d9d95, 0xffdfe159, 0xbdeda0b1, 0x5a5da28f, 0x59e60f40, 0xc70f8ce1, 0x8510b284, 0x38fd1235, 0x7fb9e05b, 0x853dcd09, 0x71e2ce48, 0x0e76519e, 0xda16dc00, 0x20bf8edf, 0x4a890e3f, 0x9d522e6e, 0x08bb4fd7, 0xd4608d9e, 0x909fd23f, 0xe17d1c77, 0x51703f1a, 0xfc49331b, 0xd9ad71cf, 0xbdc0df3c, 0xa0f4f050, 0xd280ec5a, 0x83ddaccd, 0xc979dd7f, 0x0396d242, 0x0e5b2e13, 0xf23f6285, 0x2804c108, 0xad14738c, 0x95e961b9, 0x3da6de3e, 0x9652cc76, 0xc4b4212e, 0x23042310, 0x868660c6, 0x2829be85, 0x5f066e84, 0xb6c03d24, 0x6440d17e, 0xa3622212, 0x6cd6e124, 0xb6ed42a9, 0xc25440ea, 0xec9d9fab, 0xb57b90eb, 0xdf606f86, 0x7959819f, 0xf749d103, 0x98249de8, 0x4fffbdb9, 0x4932a3f0, 0x8b66e31a, 0xf912ff10, 0x628dcf37, 0x6f403366, 0xc1c292a8, 0xf184cf4a, 0xbe560d7e, 0x13427ef2, 0x0de083dc, 0xe9c653a0, 0x41a493aa, 0x2bbf6cc7, 0xef0b4de9, 0xf93f809d, 0x10d4acb0, 0x71cfb1c5, 0x33d08fa0, 0xcf99bcbb, 0x1634cd74, 0x3e300c7c, 0x18429cea, 0x38d06db8, 0xfa842d52, 0x136f017f, 0xa0d98fdd, 0x9309007d, 0x8b4b9c97, 0xcaef0f3d, 0x52e6ed58, 0x1d1950e1, 0xb89b1337, 0x9bb24faa, 0x515d4097, 0x7c024d94, 0xcc0f6ef9, 0xd7f65fdc, 0x2d5f0d03, 0xf4df0341, 0x90b2adb2, 0x8dabfd53, 0x2ec9df41, 0xa6149194, 0x9d7f51e3, 0x9ee983a1, 0xef263264, 0xc954a2f2, 0x52cb92d5, 0x83f0d340, 0x7f949fd6, 0x6f6d4ceb, 0x698d2d2f, 0x055bcc0b, 0x25c93d59, 0xea5081e2, 0x2ee4a0cc, 0xd44df213, 0xe15063fa, 0x421f3e65, 0x93247ff0, 0xb0205ce0, 0xa34f5d9f, 0x6a3680e0, 0x542bf311, 0xe7b0023e, 0x88dd4ed5, 0x186fe367, 0xf2121d08, 0x4744f26e, 0x646daef3, 0x8e3d2f11, 0xaeafde43, 0x9ec4fc2c, 0xfc644c96, 0x06e061c4, 0x9b9f3027, 0x7ae22c50, 0x1d342f6c, 0x67d6033c, 0x265fef1b, 0x4189ec27, 0xc2793f67, 0x86ab1f4b, 0x772fd001, 0xf4f27ccc, 0xbb20bef8, 0x6cfb9ea9, 0x23295c9d, 0x44d2202c, 0x4c441076, 0x7acf53dd, 0xa84fbf87, 0x3530ee64, 0x88f03158, 0xb3b68ea2, 0xf764ae8e, 0xd7db2051, 0x5cbdc34b, 0x2092f152, 0x4fd2c234, 0x2b92134a, 0x59cb70cd, 0xe40baff1, 0x10f9d33d, 0x9809e265, 0x0896305a, 0xe426d07c, 0xea7dfe6f, 0xc4995ea3, 0x4c696ffb, 0x62a0b0ba, 0xfaa952df, 0xdcf6bdc4, 0x967fb3fb, 0x57905ede, 0x5f2b1109, 0x74947dce, 0x611b1d75, 0xb8b66cba, 0xa862c00a, 0x72596387, 0x8d8682de, 0xb556ef66, 0x54068c9c, 0xcc221174, 0x30465de2, 0x7702af8c, 0x69a052a2, 0xe79d7db3, 0x15a21f36, 0x1ea2fd2e, 0x2d72728e, 0x1e8f82a3, 0x44ff5fa1, 0xb39bf12f, 0xc1efed25, 0x36a63c26, 0x1bd44ea8, 0x25e442d4, 0xabd96dc5, 0x491fdc7d, 0x613662f8, 0xecb0e026, 0x3e1d73f1, 0xb00d236d, 0x7974fe12, 0xa639ee19, 0x351d91e9, 0x8e10509c, 0xabf41248, 0x3b6bc077, 0xe2ebce35, 0xd9800e42, 0x0dcdfc51, 0x80660102, 0xda3ba38d, 0xbb0dc175, 0xa58243d6, 0xdf4d100b, 0x306b226f, 0xcfb4c336, 0xd2ad93d7, 0xdcdbc249, 0x158f60bb, 0xd1163e18, 0x0576b386, 0xae82a1ce, 0x804b7e8f, 0xf1a9b0c7, 0x3d8ba1b3, 0x002d7f8d, 0x00000000, 0xcac270b0, 0x74b90243, 0x1619b2f9, 0x57bd2153, 0xe2c6b1b8, 0x3b46bffa, 0x33fdf02d, 0xbe7b72f3, 0x72741c0a, 0x06cd1e49, 0xfff29ed4, 0x423241e8, 0x4aa471b2, 0x5a70dd02, 0x1bf93125, 0xa5af3c5b, 0xe9eb2c2d, 0x368b43ab, 0xd13b4195, 0x03bbadcf, 0x6a1bff6d, 0x0b00e218, 0x47698de3, 0xad390c01, 0x95c41e34, 0xc722f36c, 0x67fb7cb1 +} +}, +{ +{ +0xb44c5f49, 0xd0aea7f7, 0x3842a36c, 0x71b50245, 0xe79f3fed, 0x78911530, 0x5af777d1, 0xf1ac6415, 0xc3ae710f, 0x864e4a53, 0x5fb4d498, 0x80694819, 0x2102c3e2, 0x46f4b416, 0xa45806fb, 0xc5f95d0c, 0x93699ee1, 0x34251750, 0x6db6c182, 0x1370f8b1, 0x61d175be, 0xf78b665f, 0xc6edd246, 0xb17fd249, 0x7bf5b433, 0x6ed26081, 0x7b859a7a, 0xebf88bd1, 0xe1b83da7, 0x34553919, 0x2172edab, 0xfdbbfe60, 0xab5b13c4, 0x74f6a10c, 0x53a34eed, 0xd689a5bd, 0x1a24c18d, 0x9f7e0494, 0x19304ec7, 0xe2dc9ca4, 0xeddf899b, 0x53d360a4, 0x2856fade, 0xfdcbd029, 0xca8a667a, 0xeecb06d1, 0x1527d4b2, 0xf8887360, 0xa74c89b1, 0x106477fb, 0x4cb40260, 0x1f6762c4, 0xccdd4a79, 0x99292897, 0x830de91a, 0xf7fb4816, 0xb26b5d03, 0x1f174c8d, 0xe2acb2ed, 0x78e13b79, 0x5ca05bd2, 0xf4efc75c, 0x43c73916, 0xb728fe4a, 0x3b562c26, 0x8f1a736f, 0x49f7a129, 0x68854c82, 0x80196650, 0x56e0eda4, 0x0f03153f, 0xbe0ce93f, 0x2b325bdd, 0x50b7c1a7, 0x226662e1, 0x3202151a, 0xfb9cfc2a, 0xd3ca06f4, 0xd59d2af7, 0x0c179a75, 0x1a54efc4, 0x9319b0a8, 0xedafa7d2, 0x9f0e2add, 0xc0bafe45, 0x8f6a5d26, 0x71c52c0c, 0xd0de89be, 0x678659bd, 0xda9e3fc8, 0x9c6a8bde, 0x09241775, 0x00000000, 0x3e158f6f, 0xfeaf712a, 0x03148f4a, 0xad7c118e, 0x74868f45, 0x3e65a126, 0x3d010025, 0x3166b419, 0x05338d00, 0x4a93002a, 0xbb4f4a76, 0x9a3da7dd, 0x7eb6177a, 0x38328d25, 0x6ea24ec8, 0x45e03b5c, 0x8a29fe6f, 0xf2b8eb5f, 0x0f733b76, 0xae18b08d, 0xc3de5f46, 0xc69dfc0f, 0xc9eec779, 0xe7ef11a4, 0x6dc6efcb, 0xf1dc4a5c, 0xe48bb0a7, 0x7ec63933, 0xdcb93d82, 0x3b26026f, 0x9c1aa597, 0xf8f85d29, 0x6be1ed81, 0xcfc9c533, 0x907d11ab, 0x1300d6f8, 0x62c5faf4, 0x2755efe1, 0xa83fb2c7, 0xf49fe915, 0xccad6430, 0x77e22e46, 0xd3ba28bd, 0xbb3f643f, 0x45901515, 0x995906de, 0x894d5f6c, 0x06572c03, 0xcfb9eb7a, 0xa27f04b1, 0x67f677f4, 0xe4fb9eee, 0x164375b1, 0xa42828b2, 0x68f562cb, 0xb21b734a, 0x855ac519, 0x8a59d026, 0xfedf5f63, 0x0a40b676, 0xe8ec049b, 0xad0c3fc7, 0x893d7125, 0x5fc4fad1, 0x954e9cab, 0x6492d6f7, 0x3d712e6c, 0xeb88a598, 0x7792000f, 0xfbecd263, 0xb82beb75, 0x3741b653, 0x55f462ee, 0x0543a349, 0x32723b53, 0xdfadb2c8, 0x5993d6d2, 0x2d6577de, 0x72a18d0f, 0x4fa08d2a, 0x1557fafb, 0xa84f9c8e, 0x6b91c3c8, 0x0627024a, 0x24314ee2, 0xd6f98bf4, 0xb758d003, 0x2d155997, 0xbd186675, 0x0364a103, 0x4cc42c29, 0xae689ec4, 0x852aeb50, 0x5a875998, 0x40d3b65c, 0xd9fa9ecb, 0xf2c8c516, 0x2b427594, 0x101459b2, 0x2826d497, 0xd98ab082, 0x1c03c3c7, 0x00702e49, 0xe1c813ee, 0x61a15bf7, 0x8c7ed26c, 0x64e2f8be, 0xd5ed04be, 0x46849a5f, 0xa16b8bfb, 0x22164ca8, 0x2e01d6dd, 0xcafa4833, 0x837dc753, 0x863e641a, 0x50c7efee, 0x5cd0759b, 0xbe7cc776, 0xc5897345, 0xbd68483c, 0x43b7175f, 0x953eb2e2, 0xe89c2ad2, 0x1c73ed8e, 0x5690c3ed, 0xdcc913cb, 0xc0cad00c, 0x244160ab, 0x16335bf8, 0xa20f2af8, 0x0c67b43c, 0xb85bc53c, 0x55844ca7, 0x62b5d4bd, 0x8c0efc25, 0x4fd0a363, 0x7dd2b679, 0xeebb2898, 0x900d3fe2, 0x9a4d8994, 0x49878f60, 0xb10ffc00, 0x2725c1a8, 0x2e71f894, 0x3731981a, 0x59e3f89b, 0x4ae32e63, 0x72d1a346, 0xb43c7100, 0x962a3da8, 0x7da29830, 0x0a30983f, 0xa73ca7f8, 0x0954393c, 0xdfdd9c81, 0xc99ee930, 0x40a39815, 0x31169a50, 0xdaee1181, 0x1940608e, 0x965a13e1, 0xab2b3d8d, 0xa11ba5b2 +}, +{ +0x49c15a0f, 0xb31dc928, 0xe0b1d144, 0x70297221, 0xbf8ffda8, 0x9e867858, 0x210985f0, 0x5adbcefd, 0xc45db6a5, 0x85d4700f, 0xfbe3d913, 0x446c24bb, 0xa3b4f853, 0x5776b049, 0x5c8d8965, 0x74f3da04, 0x77407f8d, 0xae1986e7, 0x4189c6aa, 0xa84fc17f, 0xb8e6f004, 0x3445569a, 0x2af2bcdc, 0x39e8282e, 0x5be484c9, 0x6565a14b, 0xf4c2481a, 0xf96f36ae, 0x97f1aec9, 0x8946448f, 0x11967b4f, 0x0bfb392c, 0xc1b854b4, 0xef90404d, 0xff397136, 0xcb7c27ac, 0x53ac186c, 0xf8507c9a, 0xcc152a00, 0x31a0b48b, 0x795ea4b0, 0x59686b74, 0xe8f94de1, 0xac95695a, 0xf2940f82, 0xa0075dda, 0x87589fb2, 0xc0871e80, 0xf127aa0b, 0xd866b35e, 0x98d03fc0, 0x6fa1d253, 0x22ba2079, 0xc6d15918, 0x75cc9030, 0xdcbc1b7b, 0x3b64c793, 0x71163815, 0x32131102, 0x19dee7ea, 0xeeaf0a79, 0x17c03cd7, 0x6d2d3dee, 0x58572140, 0xb7c7610d, 0xd7472257, 0x8f100317, 0x2036cfc4, 0x2e2814f9, 0xf64ea7a7, 0x1473995e, 0x9c0a97e5, 0x9fb9326c, 0x84eb3a3b, 0x4b4db5b2, 0x36c9b927, 0xdaea5ce3, 0xca436d98, 0x7d840c95, 0x7cbb46a1, 0xdbd516d7, 0x55fa5ff4, 0x04daa825, 0xde30f4c6, 0x1b520857, 0x6c1277da, 0x013f4a34, 0xf771ed93, 0xbeb0b79c, 0x18e1adde, 0xd02e2ffb, 0x9098a365, 0x2660885c, 0xec23e5c4, 0xeb4ae868, 0x275fc268, 0x5649fa7d, 0x932b06ec, 0xe6e796dc, 0x8d9cecaa, 0x82bd7da3, 0xd11165cf, 0x3c0dca3f, 0x00000000, 0x357a1cae, 0x8ca3a69e, 0x88790ebb, 0x2f175ecd, 0x16ff76e3, 0x1f88a072, 0xce99c5bd, 0xed1caff0, 0x810ed82a, 0x7aed0139, 0xe7d8dce8, 0x08489ca5, 0xbd031215, 0xd959f96a, 0x94420b40, 0x3a5b8da7, 0xb222831c, 0x4a72ff86, 0xea75a25c, 0xf3ab45b6, 0xe9c607d5, 0x3fbe6fb6, 0xaac32ec2, 0xd5cbcdea, 0x1c3b05fb, 0x332c5b36, 0x3e812582, 0x1225dec6, 0xdf0fbef2, 0x2ca4fb44, 0x48fe103b, 0x40b68c9e, 0x9b639a49, 0x7f08e328, 0x37f6f313, 0x69f795cb, 0xa13817ee, 0xa6511a42, 0x6b7b7a76, 0x61bf096e, 0xb9d9ba30, 0x45536e8f, 0xb1912695, 0x0dad7eb4, 0x309ffebf, 0x7bd24b0d, 0x10a9317b, 0x07690dac, 0x8031921e, 0x1eb7ea46, 0x52935258, 0xe5543355, 0xa5e2bfcb, 0xcfa68f89, 0x287e5361, 0x4ea857a3, 0x83823797, 0xb474c484, 0x43052917, 0xf018e03f, 0x9a5cd07d, 0x0f219109, 0xc562fc91, 0xfc8ad4bf, 0x96cee4fd, 0xe23d3ef9, 0x92144cd8, 0xfe063b02, 0xf5fd022e, 0x25d32dd5, 0x1a6d4263, 0x54c515c0, 0xa76e5076, 0x7861ee84, 0xd39d8a72, 0x028cefbd, 0xa9708b4b, 0xaf26ccd3, 0xd2a2c046, 0x4d1bf22a, 0x5f3e2cec, 0x91a7e951, 0x423a6323, 0x5db2c351, 0xb0ae6ca1, 0x767f35b9, 0x501fbde5, 0x05e5e211, 0xc20bf13d, 0x03b3a589, 0x38d7621a, 0xbb55558d, 0x0977d691, 0xdd83514f, 0x47df8132, 0xadaa236e, 0x8667d586, 0x6333e6d3, 0x3d32800b, 0x9d35ddd1, 0x29411955, 0x72a59d9c, 0x6080435a, 0xd4f487de, 0xb54b8eb0, 0xd6786863, 0x6e9e9867, 0xfadc9327, 0xc8cf8225, 0x957d4174, 0x6a443042, 0xc7ee132c, 0x68c8dfff, 0x66d604c2, 0x0c923480, 0xa4ddf5ff, 0x0ac47318, 0x0e1edb3d, 0xa28bb267, 0x23856a4d, 0xc9f0c811, 0xabfc64f6, 0x8e2f4923, 0x46e0cb06, 0x99ef75f4, 0x8bcaab32, 0xb6f82b39, 0x131a94f2, 0x06564798, 0xcd2a6034, 0x7e37a91c, 0xc334bb09, 0x67e94ef6, 0xe18e9b70, 0xba6a1fb9, 0x4f971d97, 0x5e0166d8, 0x2d9bb170, 0x5120f7d1, 0xfdb59e8b, 0xbc3c5821, 0x739ad7a8, 0x1d044fcf, 0xe30274cd, 0x24ec67e1, 0x620cace7, 0x645aeb7f, 0x8af5e106, 0x2bcdf6e8, 0x4c24b81e, 0xe46b7961, 0x154cd36a +}, +{ +0x389382db, 0x2dde1e61, 0x00be3560, 0xe2b029c5, 0xd174b7f1, 0xfcaaa990, 0xd195e9ec, 0x99412fe9, 0x8b218c8c, 0xd12bdc8c, 0x9e6c1036, 0x7c83528e, 0x8bc0d291, 0x56ce4650, 0x2145634c, 0xb30c3b37, 0xb8044ca5, 0xb85b27d8, 0x34b6ca96, 0x0b087792, 0x62c6b9a6, 0x3408fff6, 0xb49f3188, 0xdd0e94c1, 0x5a0a5000, 0x92a80666, 0x4f18a7c7, 0xaa64efc0, 0x778b251c, 0x6555b319, 0x5d276fdf, 0x6ee3f1eb, 0x6991a549, 0xc3aa21f4, 0x2af321be, 0x6970fb54, 0x4ff9f9da, 0x1260a365, 0x2d602b01, 0xe59d161a, 0x0c25484d, 0x0bb642f2, 0x436284f7, 0xf71ceb62, 0x5aeb0e1d, 0x515d4cef, 0x7bae6d51, 0x34e9a1eb, 0x776a7b01, 0x1512f7c7, 0xd659882e, 0x4383daea, 0x65b4ed04, 0x7b4f334c, 0x8029fb1e, 0x444fbb28, 0xfb39a32f, 0x2689028e, 0x26d669f3, 0x62788cc6, 0xc8a25666, 0x5d995abf, 0x8ceded4e, 0xbf97461a, 0x4410d055, 0x339bf549, 0x15f3a9da, 0xda7cc063, 0x4fa692a7, 0x2aac4ac3, 0x1ea4b535, 0x70182fa3, 0x433def8a, 0x211a0831, 0xdac2f503, 0x0cc41650, 0xda23ab1e, 0xc4392b4b, 0xda9d9e7e, 0xaa3b84bd, 0xc34b7fe9, 0x00e15e1d, 0x1968d4f7, 0x92163306, 0xc4664036, 0x44aee535, 0xd1ca8291, 0xe9b85e57, 0xe57c4807, 0x8097ce7e, 0x7c620c93, 0xdd51ffbc, 0xb8e512b8, 0xe9e7352a, 0xbf761807, 0xe20e1ca5, 0xfc149cf0, 0x51e3798f, 0x704744de, 0x7cdc39f3, 0x3457948b, 0xa641a78d, 0x486af365, 0x70f971be, 0x3fbebd04, 0x154d9cba, 0xf06ebfc0, 0xa133f32f, 0xbf29737a, 0x7bf1062c, 0xaadadaa0, 0x953b0cd9, 0x650ad864, 0xf7fdb57f, 0xd6b8d633, 0xaa85b1dd, 0x0be9298f, 0x875bafbc, 0xf7a2de02, 0x005f6b7d, 0x382db7bb, 0x44f18e48, 0x21a43d51, 0x2d81751c, 0xc81c6306, 0x56707330, 0x80c8a503, 0x51bc12f2, 0x33c49e34, 0x1281fd78, 0xc8fd3d1b, 0xf031d4bd, 0xb47e6f95, 0x5ab46560, 0xe523237a, 0x7c3d67ee, 0xee956188, 0xfcf5c2ed, 0x3f5fe319, 0x692f9029, 0x3325c029, 0xa6a0f990, 0x95da52c4, 0x92f76d1b, 0xcf315cd9, 0x6ebc9a96, 0x87baf1a1, 0x00000000, 0xad49d01f, 0xb42104e8, 0xee743f95, 0xcfd002c4, 0x07cc61c2, 0x70a61ac3, 0x1e1a8055, 0xe9066b37, 0xf0d08aa0, 0xc4871e2b, 0xc3141494, 0x8cb28633, 0x7735107c, 0x5d7804a2, 0x0b571cef, 0x956467a4, 0x6299d2db, 0xd606e353, 0x07930abf, 0x6e5dc48b, 0xfbd8fd32, 0xe25177d8, 0x9e8d4e2b, 0xf08fe1dd, 0x488bad78, 0x0c7a2330, 0x65eb8679, 0xcf6e37a4, 0x87e59adc, 0x9e337b4b, 0x77d44e61, 0xb4c05af5, 0x3fe1d679, 0x1937bf8a, 0xbfc82d67, 0x8c53d82e, 0x69cece34, 0x19898aea, 0x26685c93, 0x2d3f407c, 0xcf8f69b9, 0xb8ba79c5, 0xadf7e57f, 0x8b9fb9ec, 0xfc4bf78d, 0x6227e7bb, 0x5a553b7d, 0x1e45eb28, 0xe2ef42b8, 0x19d6e197, 0xb353504a, 0x263737ee, 0x9249587b, 0x0c9b7d2d, 0x562f184d, 0xa6ff92ed, 0xfb66c852, 0x5dc631c2, 0x8c0cb353, 0x072d3fdf, 0xa18dc64f, 0x958539b9, 0x6e02aff6, 0xf743801f, 0x1efbde48, 0x991e4494, 0xe959004a, 0x12de9605, 0x99a071f4, 0x337aab54, 0xc3f54a89, 0x15acc2a7, 0x21fb562c, 0xada88e02, 0xe5c27d67, 0x48d4c605, 0x3f008864, 0xfb87964f, 0x80769063, 0x8b7ee7f1, 0x2a4d14de, 0x38cce9a6, 0xa1d2ad32, 0x4f47ccba, 0xb3b20e57, 0xc843087b, 0x7b105831, 0x077254a2, 0xddb0a1a1, 0x2a127fa3, 0xee2b54e8, 0x9ed22556, 0x43dcb197, 0xc4d87556, 0x8704c4c1, 0xd6e7bd4e, 0xddefcadc, 0x3872dcc6, 0x99ff1a89, 0x56912d2d, 0x48359818, 0xa61eccf0, 0xa16c9852, 0x51022792, 0x123fc818, 0xb3ed652a, 0xeeca0af5, 0xad16bb62 +}, +{ +0xf470fbd3, 0x6b1c1fab, 0xe386bdd0, 0x10bd53bc, 0xf227d13d, 0x863833ef, 0xbeb21887, 0x2df19f4e, 0x806f1901, 0x0ea29194, 0xc40f6bc1, 0xbd23d5f3, 0x616456f4, 0x446072c0, 0xe01770a4, 0x8a17505e, 0x00000000, 0x3d4cccf2, 0x11a16ced, 0xd4b2387d, 0x4e183b9f, 0x2789d611, 0x0391cd74, 0xf56cc482, 0x2ceda01f, 0xfd997ff8, 0xec381315, 0xbfae27d6, 0xb29d7b36, 0x7e67ab8d, 0xefa9de61, 0x6edaf831, 0xf0aa2318, 0xa1b1e5fe, 0x011c3f51, 0x7df666f9, 0x8b0b6f0f, 0x91ce75ec, 0x0c2f63b1, 0xbb74ff1d, 0x40baaa0b, 0xe5d1973e, 0x8d5c45e1, 0xe10b4ff5, 0xfad26a47, 0xb0108913, 0x84b5c1ca, 0xe9fef48f, 0x993bce96, 0xe75c651b, 0x511bc6e6, 0x132c9ec8, 0x283778d4, 0x16ea7952, 0xd89d5bcc, 0xba68c04c, 0x778e2fa6, 0xd63fca58, 0x6c570a14, 0x1ac51ae3, 0x97995f02, 0x41a6955a, 0x1d8e0f5c, 0x607869a5, 0xd3f92dc2, 0x24181b65, 0x0fbeaec5, 0x70c53a19, 0xf85f9862, 0x08f5bb7a, 0x4237582e, 0x39961439, 0xce77229e, 0xa0addaaf, 0x1e1fc228, 0xd5ae072c, 0x25042434, 0x06572aee, 0xb5d66e89, 0x55c11e2d, 0xff148ddd, 0xa56b3d35, 0x6a0020fa, 0xc5135490, 0xcde6efea, 0x028df225, 0x741fe2d2, 0x67337c1a, 0xc68299e4, 0xe4cda86f, 0xa4770264, 0xc0d5b30a, 0xc79ea6b5, 0x1c92300d, 0x6fc6c760, 0x47f1bfb4, 0x0d335ce0, 0x82e2eb24, 0xcf6b1dcf, 0x20c2c3ae, 0x5650d359, 0xeb7306aa, 0x9f6ce478, 0x7cea59a8, 0x0b64760e, 0xd723f509, 0xdfd64e73, 0x925fb898, 0xcbb1c504, 0x09e9842b, 0x528a0b92, 0x373485ad, 0x96856053, 0x89869d2a, 0xc1c98c5b, 0x484f1171, 0x14678b77, 0xeeb5e130, 0x2ba6b5a0, 0x1954d797, 0x85a9fe9b, 0x5fb95772, 0x54dd217c, 0x5d34a557, 0xdb0c96b8, 0x934387c9, 0xbc3feaa2, 0x574cec08, 0x17f64603, 0xb4ca51d8, 0xed242c44, 0xb10cb642, 0x5a7fb0e8, 0x9de1165d, 0xea6f39fb, 0x074b15bf, 0x46ed80e5, 0x7f7b94dc, 0x292b4785, 0x23530eda, 0x2695e940, 0xf33bee6c, 0x3a07d94d, 0xb9f90d38, 0x8fd1b7c4, 0x1bd925b2, 0x87240cbe, 0xa9445e84, 0x83fed475, 0xb75b9cac, 0xaf13746a, 0x9514ad27, 0xd068e0b6, 0x78308163, 0x4f0404ce, 0x0a78495f, 0x3fc13ed7, 0x2f7c6d6b, 0x04dad8cb, 0xc93c3721, 0xae0f4b3b, 0xc8200870, 0xcaadfa55, 0x34a548d9, 0x32f26237, 0x59ee7d9c, 0x792cbe32, 0xe29a8281, 0xd174dfe7, 0xfc8540a9, 0x3b1be61c, 0xaad593f0, 0x35b97788, 0x63e9a4d1, 0xabc9aca1, 0x90d24abd, 0x662f434b, 0x224f318b, 0x7248c83c, 0x539634c3, 0xd981649d, 0xac82b91e, 0xf943a733, 0x9e70db29, 0x21defcff, 0x62f59b80, 0x4c95c9ba, 0x7ba14c17, 0x388a2b68, 0x9cfd290c, 0x9bb63cb3, 0x457c4d91, 0x889aa27b, 0xe8e2cbde, 0x3edd0186, 0xf7e136a7, 0x58f242cd, 0x49532e20, 0xe6405a4a, 0xccfad0bb, 0x307f9012, 0x3c50f3a3, 0xdd5bbc56, 0xd2e51293, 0xfe08b28c, 0x1230a199, 0x5b638fb9, 0xa6faf041, 0xfbce5516, 0xf6fd09f6, 0x9aaa03e2, 0x5007f9b7, 0x9827f1c7, 0xb3814467, 0x432b677f, 0x7503dd83, 0xad9e864f, 0xdc478307, 0x1848e8c6, 0xa85861d5, 0xa33c17db, 0xa220288a, 0xb647a3fd, 0x33ee5d66, 0x688dd2df, 0x769210f7, 0x1f03fd79, 0x5ea56823, 0xc258412f, 0x7354f76d, 0x7abd7346, 0x81732650, 0x71d90548, 0xda10a9e9, 0x5c289a06, 0x94089276, 0xdeca7122, 0x64a2b16e, 0x4d89f6eb, 0x8c407ab0, 0x4ac2e354, 0xb8e53269, 0x4bdedc05, 0x2aba8af1, 0x2e60523a, 0x65be8e3f, 0xa7e6cf10, 0x157bb426, 0xc3447e7e, 0x6991ed8e, 0x6d4b3545, 0x05c6e79a, 0x3163af43, 0x3628bafc, 0x8ecd8895, 0xf1b61c49 +}, +{ +0xec633a9e, 0x045858d6, 0x8124188d, 0xf9e8a81a, 0x9270f8b4, 0xfc642374, 0xfdba17dd, 0x7a417ded, 0x2a2bef6f, 0x68cba97d, 0x7d4adce8, 0x84a893e3, 0x87fb6a30, 0xfc6ec465, 0x28acc504, 0x51be413a, 0xfdb0f0cc, 0xadda624e, 0xc09d405d, 0xbdd79cb5, 0x957b59b1, 0x070ba105, 0x9628a062, 0x028dcd7a, 0xe8318559, 0x16d28c46, 0x11d92d43, 0x406d8b68, 0xaadb245a, 0x05866c7f, 0x51b4a62b, 0xfb656560, 0x3a261194, 0x38abdcee, 0x7fc71192, 0xc4cfff9a, 0x12803381, 0x3cf38438, 0x54382d45, 0x80fa2c24, 0x3faa9afa, 0x3e7e4942, 0x6e1e3cd1, 0xedb7e926, 0x40676c79, 0x2a21087e, 0x53338c40, 0xd79b1fa3, 0xd6452b0a, 0x8277e15e, 0xfb6f8271, 0x15817595, 0x1455a62d, 0x433495aa, 0xeeeef7e4, 0xc796e158, 0x927a1fa5, 0x56bf072e, 0xbb08ee08, 0x812eff9c, 0xff37daa7, 0x3fa07deb, 0xc14374f4, 0x16d86b57, 0xd4c20161, 0xe9efb1f0, 0x397f0f56, 0x8576a74a, 0xd791f8b2, 0x6b92b7bf, 0x3d2db091, 0xbadc3db0, 0x862fb988, 0x93aecc1d, 0xf83c7ba2, 0xc79c0649, 0x3a2cf685, 0xc14993e5, 0xaf57af34, 0x84a274f2, 0xd090bea6, 0x17065ffe, 0xbb020919, 0xab0510f3, 0x2bf5dbc6, 0x93a42b0c, 0x52edb8e9, 0xb85b17db, 0xf9e24f0b, 0x0353f9d3, 0xc2108d27, 0x691f7ac5, 0x86255e99, 0x97fc73da, 0x297816bc, 0x2e73b7b9, 0x06d595ac, 0x56b5e03f, 0x7b95ae55, 0xe83b6248, 0x100719ea, 0xd21d73dc, 0x97f694cb, 0x01de34a9, 0x57613387, 0xbddd7ba4, 0xd21794cd, 0x170cb8ef, 0xeee410f5, 0x68c14e6c, 0x476ccd7c, 0x6a466407, 0x47662a6d, 0xac0eb1f6, 0xd3c9a064, 0x69159dd4, 0x07014614, 0x6a4c8316, 0xd516d2d9, 0x38a13bff, 0x94a56d18, 0x90f7d2df, 0x3cf96329, 0xd3c34775, 0x6c93f1ab, 0x4435d3be, 0x827d064f, 0xd1446d1e, 0x2bff3cd7, 0xfee9ee0e, 0x06df72bd, 0xfab1b6d8, 0xec69dd8f, 0x3975e847, 0xeb627c8a, 0x7a4b9afc, 0x55ecfefd, 0xeab6af32, 0xc3ceb98e, 0x6d4dc502, 0x7918632f, 0xbf5a51cf, 0x45ebe717, 0xd64fcc1b, 0x7c9e0f50, 0xaad1c34b, 0x28a62215, 0x100dfefb, 0x2d204e6a, 0xc64232e0, 0xeabc4823, 0xae837c8c, 0xfabb51c9, 0x2d2aa97b, 0x2fa76401, 0x80f0cb35, 0x000ae711, 0xa856e920, 0x83a332e6, 0xc648d5f1, 0xb98fc463, 0x78c65786, 0x7b9f4944, 0xa9823a98, 0x00000000, 0xae899b9d, 0xeb689b9b, 0x2e7950a8, 0xbc09a81c, 0xd51c35c8, 0x7fcdf683, 0xd4c8e670, 0x45e10006, 0xef3a245c, 0x0452bfc7, 0x7e13c22a, 0xbc034f0d, 0xbe846566, 0x94af8a09, 0xaf5d4825, 0x433e72bb, 0x506a9282, 0x576bd496, 0x01d4d3b8, 0x87f18d21, 0x6e14dbc0, 0x2cf49dd2, 0x96224773, 0x41b958d0, 0xb9852372, 0x2fad8310, 0xef30c34d, 0x6fcaef69, 0x9571bea0, 0x50607593, 0xadd0855f, 0xbf50b6de, 0xedbd0e37, 0xab0ff7e2, 0x46b2f9d5, 0x7d403bf9, 0x3bf2c22c, 0x058c8b6e, 0x145f413c, 0xc51b2c22, 0x52e75ff8, 0x6fc00878, 0xc3c45e9f, 0xfee3091f, 0x11d3ca52, 0x1354e039, 0x443f34af, 0xc21a6a36, 0xd09a59b7, 0x128ad490, 0x6d472213, 0x7c94e841, 0xac0456e7, 0x90fd35ce, 0x7912843e, 0x3d275780, 0x55e619ec, 0x135e0728, 0xd14e8a0f, 0x83a9d5f7, 0x91230167, 0x02872a6b, 0x78ccb097, 0x7e19253b, 0xa85c0e31, 0xbad6daa1, 0xc511cb33, 0x5432ca54, 0x2972f1ad, 0x3e74ae53, 0x158b9284, 0xbe8e8277, 0x42eaa103, 0x42e04612, 0x41b3bfc1, 0x6b9850ae, 0x46b81ec4, 0x9129e676, 0xc097a74c, 0x3bf8253d, 0x03591ec2, 0x53396b51, 0x6c9916ba, 0xe9e556e1, 0xff3d3db6, 0xa988dd89, 0x857c405b, 0xf8369cb3, 0x2cfe7ac3, 0xb851f0ca, 0xc4c5188b +}, +{ +0x837128c6, 0xc548f3c8, 0xa7df5c74, 0xaa91db32, 0x58a21a70, 0x31b3cdcd, 0xf522f8cf, 0xb5d3dc86, 0xe2393817, 0x8de010ed, 0x443fa2a9, 0xbd8a1bea, 0x2839353e, 0xca000d29, 0x0a5fbecb, 0x3efb332c, 0xb40a1a4c, 0x4639db0e, 0x709b2f4e, 0x6091d61b, 0x9fec901f, 0xed71c6f6, 0x68c81177, 0xe6f7bef7, 0xf6fd47a2, 0xbf8c624d, 0x4aae9a82, 0x6780ef96, 0xda0af47c, 0x82a8ee0c, 0x6911d7bd, 0xe86686dc, 0xf7248168, 0xea60ff7b, 0xdf1db456, 0xc3800c8f, 0x45e66463, 0xb2c2e50b, 0x2ef1ca79, 0x0711398d, 0xb89d5bc0, 0x81775161, 0x758c6f64, 0x42f75dee, 0xcf174d03, 0x946ae81e, 0xe4f1c750, 0x5fb323fd, 0xe1e6877a, 0x357d4b2d, 0x3f22f5e6, 0xa897a295, 0x5b7da51d, 0xf233c142, 0xa2c81c5e, 0x917da834, 0x26a80d15, 0x198af8f3, 0x377b328a, 0x6ace68d0, 0xf3ea0788, 0x6b17ae1a, 0x634e6976, 0x8fe6694a, 0xfca2f969, 0x8af12960, 0x1e9bc17e, 0x3d248c41, 0xa5d925d3, 0xc9dfb244, 0x39ea0aa1, 0x7455a9ae, 0xc74e8a6f, 0x2a3f4c99, 0x80ae97ab, 0xd2533310, 0x0b867801, 0xdd1bcdf1, 0xf035b8e5, 0xd18c8c7d, 0x326c72a0, 0x100af955, 0x2060f252, 0x53246271, 0x47e01dc4, 0x4b775c48, 0xf9b5b943, 0x5633225b, 0xf4fb3e05, 0x4c6665c5, 0x098001a6, 0x85b9d781, 0x97b55773, 0xeca8003c, 0x0e91382b, 0x778a16c3, 0x6fd928fa, 0x2d2e7514, 0x73449023, 0x36a2f440, 0x4e601c62, 0x1f4207b4, 0xa94e645f, 0xcd1134a4, 0xf86c7f89, 0x95b32ed4, 0xeeae799b, 0xb9449d0a, 0x9afbd035, 0x937bd193, 0x04ce86e0, 0x892e960d, 0xdec4729c, 0x306a0b07, 0xab481df8, 0x4128e283, 0xe528019a, 0x4fb9daa8, 0xb11d5a66, 0x7b1d574f, 0x2be68a53, 0xd69db5f0, 0x8460114b, 0x9e3556d5, 0x6659295c, 0xbe55a487, 0x497125ef, 0x6297afbc, 0x614810d1, 0xae5f5dd2, 0x3cfd4a8b, 0xd9d54b11, 0x6e00ee30, 0x7ac49185, 0xfd7b3fa3, 0x5db55a5a, 0x3bec7306, 0x8e3faf80, 0x7fd3d1af, 0xbb42e4ad, 0xfbb3c0e4, 0x1c9db8d9, 0x1a55479e, 0x597bdcba, 0x4dbfa30f, 0x54355bfc, 0xb31b23c1, 0x6c069797, 0x18533e39, 0x8b28efaa, 0xd80c8ddb, 0x0517402a, 0x21b93498, 0xef77bf51, 0x00000000, 0x92a21759, 0x55ec9d36, 0xd0554ab7, 0x1b8c8154, 0x5aa463d7, 0xb0c49cac, 0xc1867528, 0xc259ca45, 0x5e6ae537, 0xa311da94, 0x7dd5a808, 0xa6069abe, 0x22668bf5, 0xaf869b18, 0x50fbdd1c, 0xe03f41b0, 0x03dfbf6d, 0x23bf4d3f, 0xcbd9cbe3, 0xd5420a9d, 0x1d447e13, 0x7142e984, 0xc806748e, 0x16c20612, 0x151db97f, 0x020679a7, 0x52fda4bb, 0x78c2e822, 0x6ddf515d, 0xe3e0fedd, 0xdbd332b6, 0xa117a333, 0xa400e319, 0xccc8f26e, 0x645f50fb, 0x2cf7b3de, 0xebb939b1, 0x57eae491, 0x40f12449, 0x2771cbdf, 0xac592475, 0x120c80f2, 0x7c0c6ec2, 0xa0ce65f9, 0x65869631, 0x7653d009, 0xdcc20b3b, 0x2577b278, 0x0f48fee1, 0x3833cc6b, 0x0d4e8746, 0x5c6c9c90, 0xbc53dd20, 0x33b5b46a, 0xfea480ce, 0x9b2216ff, 0xf1ec7e2f, 0x24ae74b2, 0x0859c76c, 0x34a48de7, 0xad80e2bf, 0x14c47fb5, 0xcece8bc9, 0x966c91b9, 0x9c332f72, 0x432e9b24, 0x98fda992, 0x729d56e9, 0xfa6a062e, 0x06c8ff47, 0x48a8e325, 0xe9bf4016, 0xba9b2267, 0xb60c63eb, 0xd49bcc57, 0x171bc0d8, 0x13d54638, 0x88f750c7, 0x90a46efe, 0x8c39d627, 0xc6974ca5, 0xc4913502, 0xff7d4604, 0x29e0f3f4, 0x87bfae26, 0xd38af5da, 0xc05fb3e2, 0x0c97418c, 0x3a35b5cc, 0x01d9c6ca, 0x866668ec, 0x99246f58, 0xe72e783d, 0x51221bd6, 0x7e0a1765, 0xd744733a, 0x2f280cb3, 0x791b2ee8, 0x9deae9b8, 0x11d33f9f, 0xb7d5a521 +}, +{ +0x3bda78ae, 0x1aa1962f, 0x4beb6b6f, 0xd6865def, 0xc4b85c45, 0xedc2a253, 0x51d47a52, 0x741bf4f3, 0xb4894f84, 0x03decf95, 0x255109b3, 0xa1436689, 0xd9ede2cd, 0x520ab5c7, 0x84126f3a, 0x1dcb399a, 0x042ae732, 0x7c846376, 0xc3d2f3f0, 0x514afd40, 0x6eba62dc, 0x4c81c4da, 0x83e6479d, 0x25cf8ea1, 0x9d6d3680, 0x309b20be, 0x8378c08f, 0xc893abe0, 0x95f2a105, 0xd1727548, 0x5ebfc570, 0xae28d9ab, 0x21e56993, 0x9df3b192, 0x40aa337f, 0x875227bd, 0xe2a91d71, 0x70af94d3, 0xc7f814c2, 0xccb94cd2, 0x80a60f1a, 0xd618dafd, 0xc092bb77, 0xee1c6dc6, 0x0f6bbf22, 0xdd5982ed, 0x33db6839, 0xadf6163e, 0xa56981bb, 0x8fcdb038, 0x2e8ed6b1, 0xa629c93c, 0x9a991e27, 0x11e0ce3f, 0xe177d2e4, 0x2e1051a3, 0x29e47904, 0xe1e955f6, 0x3f6e188e, 0x614f5aec, 0xd2323dcf, 0xf8088b5e, 0x694e4a7b, 0xf3d7545c, 0x9e2d7e07, 0x962c6e90, 0x389a3029, 0xc426db57, 0x6e24e5ce, 0x66bb724b, 0xea368af4, 0x80388808, 0x5a0ba550, 0xaeb65eb9, 0x2dce9e36, 0x1e8b711d, 0x34b1c78c, 0xcbd3e367, 0x8839989f, 0xd97365df, 0x8be7570a, 0x07f428a7, 0xbc885f13, 0x0cb570b7, 0x6dfa2a5b, 0x6625f559, 0xb3e3e031, 0x223ba606, 0x4c1f43c8, 0xf349d34e, 0x8b79d018, 0xc80d2cf2, 0xd1ecf25a, 0x55601a72, 0xa29da91c, 0x9146c125, 0x88a71f8d, 0x3cb0d71b, 0x6d64ad49, 0xf763347c, 0x0bdfdf02, 0x4b75ec7d, 0x99d956a0, 0x4480d44d, 0xf8960c4c, 0xe55d35d6, 0xa2032e0e, 0x73efdc54, 0x342f409e, 0xaa9cb98b, 0x12a086b8, 0x775bbc74, 0xe2379a63, 0x4374fcea, 0x19e1dea8, 0xf4237cfb, 0x748573e1, 0xb83c3f33, 0x7beeccc3, 0x4fc18c5d, 0xf0971cdb, 0xb0a3a8b6, 0x4835a4fa, 0x376f0819, 0xcc27cbc0, 0x5a952242, 0x4034b46d, 0x3345ef2b, 0x73715b46, 0x2a3ab691, 0x009e8712, 0xda332d58, 0xfffca3f9, 0xe61d7d51, 0xd5c61568, 0x1554ae1f, 0x96b2e982, 0xd2acbadd, 0x77c53b66, 0x920689a2, 0xbbe2f0a6, 0x56bed5e7, 0x620f126b, 0x78ae8444, 0x7f5aace3, 0x61d1ddfe, 0x6a9085ee, 0x197f59ba, 0x1e15f60f, 0xfcbceb7e, 0x08011097, 0xfbd644cb, 0x0ff53830, 0xb7c90703, 0x62919579, 0x37f18f0b, 0x00000000, 0xeaa80de6, 0xf4bdfbe9, 0xad68912c, 0x5dff8df7, 0x91d84637, 0x3c2e5009, 0x47c09cca, 0xe9e84561, 0x4f5f0b4f, 0x7b704bd1, 0x8c8df8bf, 0x562052f5, 0x0b415810, 0x089f9785, 0x3804b73b, 0x78300356, 0x6565bdde, 0x8c137fad, 0x03404887, 0x26114134, 0x65fb3acc, 0xfc226c6c, 0xff6224eb, 0x268fc626, 0x43ea7bf8, 0xf7fdb36e, 0x5d610ae5, 0xddc705ff, 0x55fe9d60, 0xa5f706a9, 0xb417c896, 0xc00c3c65, 0xa1dde19b, 0x1d55be88, 0x1a3f113d, 0x594bedd7, 0x2d501924, 0xde19ca6a, 0xde874d78, 0xf0099bc9, 0xe976c273, 0x9eb3f915, 0x217bee81, 0xb37d6723, 0xcb4d6475, 0x076aafb5, 0x297afe16, 0x0c2bf7a5, 0xd558927a, 0x6a0e02fc, 0x87cca0af, 0xb7578011, 0x703113c1, 0x956c2617, 0x48ab23e8, 0x3b44ffbc, 0xc34c74e2, 0x2aa43183, 0x1614e698, 0x92980eb0, 0xee82ead4, 0x441e535f, 0x5e214262, 0x123e01aa, 0xa6b74e2e, 0xdaadaa4a, 0x59d56ac5, 0xbfc81794, 0x475e1bd8, 0x7fc42bf1, 0xcf678347, 0xa9dcf10c, 0xcff90455, 0x04b46020, 0x69d0cd69, 0xbc16d801, 0xa942761e, 0xed5c2541, 0x8f53372a, 0x848ce828, 0x117e492d, 0x7c1ae464, 0x168a618a, 0xc76693d0, 0xe5c3b2c4, 0x9947d1b2, 0x3005a7ac, 0xb03d2fa4, 0xfb48c3d9, 0x529432d5, 0x15ca290d, 0xbb7c77b4, 0xe683fa43, 0xbf569086, 0x3ff09f9c, 0xaa023e99, 0xb8a2b821, 0x9a079935, 0x22a52114 +}, +{ +0xfb80b07a, 0x732b7fde, 0xf5223a84, 0x5f6f8891, 0xd8d90fdf, 0xe345d2be, 0x15b15099, 0xaa4db215, 0x229554c5, 0x84131699, 0x47d9c321, 0x3481958b, 0xf687ab53, 0xc3b9fccc, 0x497b49df, 0x2359bfa5, 0xd966cdcb, 0x735856aa, 0xa9e823c2, 0x9d69b649, 0x45b0b996, 0xd5ad3d82, 0x51be2b1b, 0x87c5ae3a, 0xef8e22f7, 0xf9e9cacd, 0x1614c14e, 0xf49df890, 0x03a591d7, 0x6bee1d1a, 0x6a22f67a, 0xa824c8a2, 0x7294bdca, 0x66e90633, 0x0d071b29, 0x3a503601, 0x2fe16698, 0xa49c119f, 0xaa3e9b61, 0x17ab035a, 0x46152841, 0x93cb3cb7, 0x64807c84, 0x69f44ed9, 0x85dffdf9, 0x521bbacc, 0x5001e90f, 0x0d74325d, 0x9cd6745d, 0x00732974, 0xfa3f726e, 0x48b7a2bf, 0x708eee09, 0x8b7d7707, 0x18b64bb0, 0x698767ad, 0xc27517ac, 0x0ccbf049, 0xc2063ed8, 0x37572d28, 0x7fe08f97, 0x71312c1d, 0x021a53c3, 0xa99b0ab6, 0x64f355f0, 0x4b611a1c, 0xdb7c9e08, 0xf99ae3b9, 0x6725ed53, 0x208f0706, 0xd608ac55, 0xc01c6d1b, 0x2e2d8df8, 0xbd95983b, 0xf6f48227, 0x4aded808, 0xf85608d9, 0x5ea363f1, 0x53a478d8, 0xf4eed1e4, 0x2dfb355b, 0x36e8ef3c, 0x9ca55d29, 0x0ed1a38a, 0xeffd0b83, 0x70fdc77d, 0x190989a4, 0x0ea28afe, 0x02697ab7, 0x3b9cdd61, 0x5f1ca1e5, 0xe0936a1d, 0xcd1b7632, 0xa523d38b, 0x684b8ccd, 0x440f7b82, 0x5072c07b, 0x45c390e2, 0x4b123368, 0x3beff415, 0x9d1a9f3d, 0x15c279ed, 0x87b6874e, 0xb12d4106, 0xb33712c5, 0xf55113f0, 0xd412ff96, 0x906ead60, 0x01cceb60, 0x6838a5b9, 0x901d8414, 0xbffce28c, 0x8ac2b513, 0xd67b8521, 0xdb0fb77c, 0xcf0125f1, 0x7e2c64f7, 0x654c97e4, 0x22e67db1, 0x5cb93032, 0x9274fea3, 0x6756c427, 0x1adf3107, 0xec589a54, 0x2c37de3b, 0x7c363734, 0xcd685f46, 0xd8aa26ab, 0xbe3009ec, 0x1b60f313, 0xd7c44735, 0xb2fbf9a5, 0x147dbbf9, 0xd7b76e41, 0x1667e83a, 0x34f2bcff, 0xfbf3990e, 0x7e5f4d83, 0x18c562c4, 0x354d7eeb, 0x9ebf0eea, 0x72e794be, 0xb3443bb1, 0x89140db0, 0xbde6b14f, 0x91d16f74, 0xee42c997, 0x01bfc214, 0xc1a3af0f, 0x00000000, 0x9f73e58a, 0x2f924fec, 0xcf720c85, 0x140e928d, 0xd915e4bf, 0x9207d7d7, 0xbc2a5a2f, 0xee31e0e3, 0x8b0e5e73, 0x93b815c3, 0x5d75db52, 0x2130c512, 0x7f93a6e3, 0xa6f56b28, 0x03d6b8a3, 0x232a96d1, 0xcecdce91, 0x39f5a7d6, 0x2c44f74f, 0x490860ab, 0x5ed04a85, 0x867a6c2e, 0xf82521ad, 0x0f6e619e, 0x0cb8d93d, 0xede75840, 0xdab07568, 0x1aac1873, 0x46660135, 0x39868ea2, 0xc06f446f, 0x0f1d48ea, 0x17d82a2e, 0x20fc2e72, 0x369bc648, 0x91a24600, 0x47aaea55, 0x896724c4, 0xa7398048, 0xa4ef38eb, 0x7c451e40, 0xe15f817d, 0x526893b8, 0x71420569, 0x353e579f, 0x3724045c, 0xbc59735b, 0x6a51df0e, 0x51cd026f, 0xa74aa93c, 0xccd79d52, 0x85acd48d, 0xd461d6e2, 0xe12ca809, 0x3a231f75, 0xe336fbca, 0xa686425c, 0x88d8e6d0, 0x384a65c2, 0xe28939de, 0xb288d0d1, 0xa550faff, 0xf74b4033, 0x84603fed, 0xb0e1aa66, 0x2d881c2f, 0xb0928312, 0x88abcfa4, 0xfa4c5b1a, 0xe0e04369, 0xc1d0867b, 0xb15e6872, 0x7d89f520, 0xcebee7e5, 0x669a2f47, 0xd5de14f6, 0xf7386947, 0xc3cad5b8, 0x4aadf17c, 0x9f00ccfe, 0x48c48bcb, 0xdac35c1c, 0x6b9d346e, 0x2e5ea48c, 0xab815975, 0x2143ec66, 0x9ecc279e, 0x53d751ac, 0x5cca1946, 0xcca4b426, 0xabf27001, 0xe2fa10aa, 0x7dfadc54, 0x1b13da67, 0x197aa0d0, 0xa857e1d6, 0x5d06f226, 0x447c52f6, 0x653fbe90, 0x38394cb6, 0xec2bb320, 0x8ab19c67, 0xbe432098, 0xbf8fcbf8, 0x8609455a, 0xed947134 +}, +{ +0x3daa8d14, 0x3eac1bb2, 0x9fa72d6e, 0x26b515b3, 0x3b9519d9, 0x9045d509, 0x5cd9c102, 0x4b223764, 0x5228f90a, 0xe0f2fbb4, 0xc0787aca, 0x7e4616b5, 0x47c659a5, 0xe2e7ad7d, 0x4a31f70b, 0x9998b9a3, 0x8a498dc1, 0xf40f9b74, 0x208a817e, 0xc7542e68, 0x3fbfdbdd, 0x5711fb61, 0x2c6eefbf, 0xcaa380c6, 0xfed46178, 0x28442dbb, 0x7b7f14de, 0x7688ba70, 0x7a6cd4b1, 0x9b8def6a, 0x021556c9, 0x2a517b72, 0x69bde0d3, 0x796a4217, 0xb6f0c0ba, 0x946f170d, 0xc54178a1, 0xd86174cb, 0x9ca1bbc8, 0x2f687919, 0x87be236f, 0xda742202, 0x674cd8db, 0xef1003d3, 0xd7838cac, 0x2957edd4, 0x44c0cf03, 0xea2901b8, 0x8b5a4dae, 0x063f94cd, 0x27a6d5dc, 0x0113c06f, 0xa627627e, 0x356421d1, 0x11c462ab, 0x4f08f560, 0x1c33cc05, 0x73b1b81b, 0xd972b4a4, 0xa521f4d8, 0xf2300fb9, 0xde5ee006, 0xbf2dac10, 0x1f355aa3, 0xe7deaf16, 0x503dafc3, 0x43ec9ba1, 0x5bf595a0, 0xe92f971e, 0xb91238dd, 0xba14ae7b, 0x1e269acc, 0x40ea0d07, 0x6f82741e, 0x030696a6, 0x335bb51c, 0xfdd2f7de, 0xd0afd80e, 0xb4e59673, 0xf8ebf5b5, 0xbc2b3ab6, 0xce8942c2, 0xe4d839b0, 0x3a86d9b6, 0x665f18b4, 0x2d7d2fd0, 0xcbb040a9, 0x6275dab0, 0x2e7bb976, 0x14fd60c0, 0x08ceacc5, 0x305d23ba, 0xa734a211, 0xc9a51660, 0x5fdf57a4, 0xadef581d, 0x56023b0e, 0xcc9c140b, 0x68ae20bc, 0x54176dc7, 0x25b38315, 0x0ef13808, 0x533b3965, 0xdc4bb6cf, 0xd3a94ea8, 0xed05551a, 0x59e0c369, 0x16e83609, 0xe6cd6f79, 0x0bc83a63, 0x957cd762, 0x86ade300, 0x9a9e2f05, 0xfcc137b1, 0x8e634fc5, 0x0539026b, 0x5dca016d, 0xd4851a0a, 0x749decb9, 0x84b8b5c9, 0xd596da65, 0xffc7a117, 0x3477e1be, 0x09dd6caa, 0x63661adf, 0x6d9722d7, 0x6ba8b61a, 0x2b42bb1d, 0x85ab75a6, 0x15eea0af, 0xe3f46d12, 0xc452b8ce, 0x72a27874, 0x70b72ebd, 0xa8d65a76, 0x314ee3d5, 0x644a4e7d, 0xe5cbf9df, 0x758e2cd6, 0x7c53407c, 0x5ae655cf, 0xf9f835da, 0x5504ada8, 0xa43234b7, 0x60608c79, 0xc8b6d60f, 0x0ce46ec1, 0x934343af, 0xfafea37c, 0xaffa0ed4, 0xdb67e26d, 0xc16bbaa5, 0x1a0c58c8, 0xabd0ccd0, 0xb1dc9418, 0x512e6fac, 0x58f30306, 0xa018f6b3, 0xdf4d2069, 0x24a0437a, 0x8f708faa, 0xbe3e6c7f, 0x7d408013, 0xbb076e14, 0x967a41c4, 0x072c54a2, 0xb801f8b2, 0xee03c3bc, 0x78798278, 0x10d7a2c4, 0xb0cf5477, 0x37717718, 0x3cb94d7b, 0x809277cd, 0xf61acdbd, 0x976981ab, 0xf51c5b1b, 0xa9c59a19, 0x45d30f6c, 0x4d1da3a9, 0x0adbfa0c, 0x988b79cc, 0xd2ba8ec7, 0x13d13462, 0x7f55d6da, 0x12c2f40d, 0xf7090dd2, 0x71a4eed2, 0x6e91b471, 0xacfc9872, 0x6c84e2b8, 0x894f1b67, 0xcf9a82ad, 0x65598e12, 0x1b1f98a7, 0xec169575, 0x39804f10, 0xcd8fd464, 0x8d65d963, 0xfbed6313, 0x042ac204, 0x5ecc97cb, 0x238c17d8, 0x61734c16, 0x493761ad, 0x229fd7b7, 0xb7e300d5, 0xdd5876a0, 0x6abb7675, 0xaac30cbf, 0xbd38fad9, 0x9eb4ed01, 0x885cdb08, 0x8c76190c, 0xb2da02be, 0x0fe2f867, 0xc26d2c03, 0x42ff5bce, 0x779b7a1f, 0x41f9cd68, 0x17fbf666, 0xf323cfd6, 0x4824a1c2, 0x925083c0, 0xf136991f, 0x21994111, 0x4e1b350f, 0x190ace6e, 0x8394e16b, 0x91561566, 0x38938f7f, 0xd6904cc3, 0xf0255970, 0xa31e6015, 0x4c0e63c6, 0xb5f6561c, 0x18190e01, 0xc37eec6c, 0xa10b36dc, 0x0df7aeae, 0x9db27ba7, 0xb3c9c2d1, 0x1d200c6a, 0x46d599ca, 0xc647ee07, 0x8181b7a2, 0x3662b777, 0xe1e13bdb, 0xd1bc1861, 0xaee9cebb, 0xe83c5771, 0x00000000, 0xeb3ac1d7, 0x32487573, 0x82872104, 0xa20da07a +}, +{ +0x1972b7a2, 0xbccdfb03, 0x6e7ec9a0, 0xf8509d09, 0x8024b29d, 0xa48e0d28, 0x607176ae, 0xa933eb53, 0x4a92d904, 0xde793a40, 0x8e6da282, 0x7903c10c, 0x4ba3988d, 0x6d8a3fc4, 0x0046af11, 0xf76e638e, 0x95daa2cd, 0x9aa2f35b, 0xe29073de, 0x8f1a4c1a, 0x266f0858, 0x94ebe344, 0x770c7e02, 0xf728cc9f, 0x2ae3afaa, 0x472f3f7f, 0xe3a13257, 0x2860b756, 0xe3e79d46, 0xa84405cb, 0x5f6cc954, 0xd2f59db2, 0x5da97eb9, 0x2bd2ee23, 0xb1701d78, 0xa60d15d4, 0xdf487bc9, 0x8ca8156f, 0x00000000, 0xcb872a10, 0x4658d1e7, 0x3065ee6c, 0x53a6c1b7, 0xc9429dfd, 0x1bf1af5e, 0xe0136b22, 0x14cf51d9, 0xc4b9d497, 0xc67c637a, 0x32a05981, 0x0cca08e3, 0x5125d94b, 0xd382732a, 0xf9277391, 0x0dbde67b, 0x6cbb7e4d, 0x8e2b0d93, 0xc4ff7b86, 0xf8163218, 0x25dd512d, 0x758f66fe, 0x9bd51dc3, 0x505237d3, 0xee1cd42c, 0x33d7b719, 0x3023417d, 0x8396ebe8, 0x6037d9bf, 0x2951f6df, 0xb007f3e0, 0xa802aada, 0x9956053f, 0xbdba159b, 0x81535c05, 0x44dbc91b, 0xf4dc3afb, 0xdcfa22bc, 0x15fe1050, 0x0c8ca7f2, 0x6e3866b1, 0x61069836, 0xb284eb1c, 0xa73c545d, 0x3ce9499e, 0xc74d22f3, 0x8115f314, 0xb3b5aa95, 0x2b944132, 0xdd8dcc24, 0x5f2a6645, 0xbdfcba8a, 0xc90432ec, 0x3e6a5162, 0xd2b332a3, 0xb2c2440d, 0xd1016bd6, 0x5defd1a8, 0xf961dc80, 0xbc8b5412, 0x7bc676e1, 0x4ad47615, 0x53e06ea6, 0xbf7fa276, 0x8d9954e6, 0x160ae634, 0x78742f94, 0x28261847, 0x6cfdd15c, 0xabf65cbe, 0x0f3efe87, 0x0e49101f, 0xf49a95ea, 0x24aabfb5, 0xb136b269, 0x986744b6, 0xef6b3ab4, 0xc873dc74, 0x275e49d1, 0xabb0f3af, 0xfba46b6d, 0x74be2777, 0xfa952ae4, 0xddcb6335, 0x0177ee98, 0x173ba7bd, 0xaac71d37, 0xe1222aab, 0xd147c4c7, 0xbe084cee, 0x4769906e, 0x3f1dbffa, 0x449d660a, 0x5c983f30, 0xfbe2c47c, 0xdf0ed4d8, 0xfad385f5, 0x1bb7004f, 0x03b25975, 0x9759ba31, 0x3cafe68f, 0xcab66b99, 0x959c0ddc, 0xa77afb4c, 0xa5bf4ca1, 0xee5a7b3d, 0xf5ed7b72, 0x03f4f664, 0x6f4f8829, 0x9b93b2d2, 0x028318fc, 0x3f5b10eb, 0xe055c433, 0x638580ca, 0xa9754442, 0x24ec10a4, 0x83d044f9, 0xcaf0c488, 0x45ea8892, 0xd076854e, 0xe2d6dccf, 0x193418b3, 0xf5abd463, 0x0dfb496a, 0x0f785196, 0x774ad113, 0x1843f62b, 0x9821eba7, 0x4be5379c, 0x7ab19879, 0xc63acc6b, 0xb0415cf1, 0x49662f60, 0x971f1520, 0x94ad4c55, 0xf6198d16, 0xc8357365, 0x1a8641c6, 0x2718e6c0, 0x32e6f690, 0x1ac0eed7, 0x3d9ea706, 0x0e0fbf0e, 0xde3f9551, 0x52d12f2f, 0xec9fccd0, 0xe16485ba, 0x80621d8c, 0x2aa500bb, 0x4811c1f8, 0xdcbc8dad, 0x5e1b27cc, 0xef2d95a5, 0xf65f2207, 0xa5f9e3b0, 0x6f092738, 0x82a7aa61, 0xedae8d59, 0x15b8bf41, 0xcbc18501, 0xc70b8de2, 0xbe4ee3ff, 0x5163765a, 0x5e5d88dd, 0x79456e1d, 0x6dcc90d5, 0x5cde9021, 0x5297803e, 0x177d08ac, 0xb3f30584, 0x763d3f8b, 0x74f88866, 0x7af73768, 0x3154afe5, 0x48576ee9, 0x311200f4, 0x2629a749, 0xecd963c1, 0xc588951e, 0x1805593a, 0xa4c8a239, 0x33911808, 0xd3c4dc3b, 0x01314189, 0x62b4c143, 0x02c5b7ed, 0x7b80d9f0, 0x461e7ef6, 0x75c9c9ef, 0x3dd80817, 0xa64bbac5, 0xc5ce3a0f, 0x767b909a, 0x291759ce, 0x259bfe3c, 0x8ceeba7e, 0xaa81b226, 0x164c4925, 0x3e2cfe73, 0x62f26e52, 0x63c32fdb, 0x8f5ce30b, 0x9ae45c4a, 0x49208071, 0x9668fbb8, 0x962e54a9, 0x501498c2, 0xbf390d67, 0x61403727, 0x1489fec8, 0xd0302a5f, 0x9910aa2e, 0x82e10570, 0x45ac2783, 0x8ddffbf7, 0x78328085, 0xede82248 +}, +{ +0x00000000, 0x3dc937ef, 0x61e367e5, 0x8b9c5565, 0xbcf863d7, 0x6959d6f6, 0xf789dfe7, 0xdc6f7fd3, 0x5c2a500a, 0x1e9526c8, 0x7f76412d, 0x7095de53, 0x7b4ca4ef, 0x8ae82e84, 0x88ff9eca, 0x322aa891, 0x054e9e23, 0xfb098b36, 0x5a070586, 0xb8c28615, 0x3be46263, 0x5d5e2beb, 0xa9b43fa3, 0x850bb1fa, 0x63f4d7ab, 0xfc50a55b, 0x335ed370, 0x5e3de044, 0x175bec3a, 0x50aa04db, 0xad8eda61, 0x8fa6b0a7, 0xc0ede955, 0x4a05c7d1, 0x214ba169, 0x4f4b59f2, 0x4c28925d, 0x86687a55, 0x5964ce29, 0xb9b6fdf4, 0x9133966f, 0xa5346b72, 0x1c829686, 0x5490e119, 0x3cbd4c0e, 0x9989277c, 0xb31bfca9, 0xce7a0dca, 0x154c5c74, 0x3407fd1d, 0xd921e1f0, 0x7d61f163, 0x56875157, 0x0217b04e, 0xd2f89b4c, 0x60971c04, 0x40a8c68c, 0x64adf9c6, 0x682dad17, 0x74af3b91, 0xf91e3b78, 0x55e49af8, 0x73f615fc, 0xb655628a, 0x303d18df, 0x24053f4a, 0x22286ac6, 0xea7f3280, 0x28856b9b, 0x2ea83e17, 0x66ba4988, 0x29f1107a, 0x1df6ed67, 0xbd8c1836, 0xfd24deba, 0x235c1127, 0xc4d70c97, 0x6a3a1d59, 0xeb0b4961, 0xa723db3c, 0x6c1748d5, 0x9ed00911, 0x257144ab, 0x76b88bdf, 0xd7b6056f, 0xc2fa591b, 0x6e00f89b, 0x2dcbf5b8, 0xdf0cb47c, 0xed261ced, 0x4492234e, 0x52bdb495, 0x47f1e8e1, 0x3eaafc40, 0x9cc7b95f, 0x3149633e, 0xe59cadfe, 0x782f6f40, 0xfa7df0d7, 0x82529f97, 0xa8c04442, 0x51de7f3a, 0xbba14dba, 0xa3193efe, 0xaad7f40c, 0xdd1b0432, 0xe86882ce, 0xf3b33a25, 0xaeed11ce, 0x2cbf8e59, 0x871c01b4, 0x1fe15d29, 0x0bd97abc, 0x4d5ce9bc, 0x062d558c, 0x8ed2cb46, 0xc6c0bcd9, 0x98fd5c9d, 0xfe471515, 0xa4401093, 0x357386fc, 0x7c158a82, 0xbeefd399, 0xf59e6fa9, 0x162f97db, 0x1bdbb8eb, 0xd6c27e8e, 0xd19b50e3, 0x46859300, 0x8db100e9, 0x847fca1b, 0xf6fda406, 0x947d084c, 0xb26f8748, 0xc8575846, 0x12157219, 0x9b9e9732, 0xb442d2c4, 0x65d98227, 0xec52670c, 0x136109f8, 0xaba38fed, 0x1002c257, 0x3887a9cc, 0x5f499ba5, 0x45e658af, 0xa657a0dd, 0x8cc57b08, 0x14382795, 0xd0ef2b02, 0x41dcbd6d, 0xe78b1db0, 0x7e023acc, 0x53c9cf74, 0x950973ad, 0x795b14a1, 0xb0783706, 0xe2c58393, 0xda422a5f, 0x4e3f2213, 0xf0d0f18a, 0xa07af551, 0x5810b5c8, 0x0fe39f7e, 0x80452fd9, 0x3fde87a1, 0x0e97e49f, 0x2766f4e5, 0x57f32ab6, 0xe0d233dd, 0x92505dc0, 0x43cb0d23, 0xf4ea1448, 0x09cecaf2, 0xee45d742, 0x898be52b, 0x1176b9b6, 0xe1a6483c, 0xcf0e762b, 0x26128f04, 0x18b87344, 0xe3b1f872, 0x6d633334, 0x8326e476, 0x42bf76c2, 0xc7b4c738, 0x0363cbaf, 0x01747be1, 0xff336ef4, 0x39f3d22d, 0xd8559a11, 0xdb3651be, 0x203fda88, 0x2be6a034, 0x376436b2, 0xf86a4099, 0x19cc08a5, 0xa26d451f, 0xb721196b, 0xbf9ba878, 0xe6ff6651, 0x49660c7e, 0x7a38df0e, 0x2fdc45f6, 0x1aafc30a, 0xc38e22fa, 0x6b4e66b8, 0xc19992b4, 0xa10e8eb0, 0x6f74837a, 0xca40e808, 0xf2c741c4, 0x3a901982, 0x5b737e67, 0x93242621, 0xf1a48a6b, 0x36104d53, 0xe4e8d61f, 0x9047ed8e, 0xb536a925, 0xe91cf92f, 0x966ab802, 0xcd19c665, 0xd38ce0ad, 0xacfaa180, 0x971ec3e3, 0x75db4070, 0x6280ac4a, 0x72826e1d, 0x07592e6d, 0x0aad015d, 0x71e1a5b2, 0xd4d5cec0, 0xd5a1b521, 0xc5a37776, 0xc92323a7, 0xef31aca3, 0x08bab113, 0x9fa472f0, 0xcc6dbd84, 0x0c8054d1, 0x4812779f, 0x9db3c2be, 0x043ae5c2, 0x0df42f30, 0x81315438, 0x9aeaecd3, 0xbad5365b, 0xaf996a2f, 0x77ccf03e, 0x2a92dbd5, 0xcb3493e9, 0x67ce3269, 0xde78cf9d, 0x4b71bc30, 0xb10c4ce7 +}, +{ +0x0fc4283c, 0x8acff376, 0x9a057a0f, 0x2bf82a93, 0x8a9cbbb3, 0xda84a372, 0x6a0211af, 0xf23ea00f, 0x535a312f, 0x4c54906a, 0x6b2abb2b, 0x36cf4079, 0xd43b690f, 0xe2a761b3, 0x861aba61, 0x026a836a, 0x2ad08017, 0xc6c82bd9, 0x35de2152, 0xc4f1e076, 0x37e7eafd, 0xcb66808f, 0xf26de8ca, 0x873210e5, 0xe09eaa1c, 0x686892c5, 0x5db6b397, 0x246f4a6a, 0xb2bf7972, 0xdbff4133, 0x3a1a096e, 0xffc3439c, 0x7a9bd013, 0xbd7b514e, 0xa30e124a, 0x67acbaf9, 0xec18abce, 0xc4a2a8b3, 0x78f15379, 0x994753e1, 0x4d2f722b, 0xfdfa8833, 0x850bdb4a, 0xa226b8ce, 0xd651ea65, 0xed63498f, 0x66d758b8, 0x4390b856, 0x94bab072, 0x6684107d, 0x750cb0ea, 0x1e754304, 0xbe3978a0, 0xc58a0237, 0xa35d5a8f, 0x3b32a3ea, 0x0c8601d2, 0xbe6a3065, 0xfeebe918, 0x77663380, 0xee216061, 0x4f45f141, 0xfcd222b7, 0x8470390b, 0xb3c49b33, 0xf3160a8b, 0x11b16b38, 0x65c63993, 0x89de925d, 0xee7228a4, 0x4e3e1300, 0xa01f7361, 0xfc816a72, 0x8bb41137, 0x3a4941ab, 0x96837bdd, 0xbf11d224, 0x4f16b984, 0x97f8999c, 0x43c3f093, 0x272d6384, 0x0311612b, 0xfda9c0f6, 0x358d6997, 0x6b79f3ee, 0x243c02af, 0xbd28198b, 0x8be759f2, 0x2514a82b, 0x40d291b8, 0xbc53fbca, 0x29c1e13c, 0xff900b59, 0x4081d97d, 0xb0d5fa18, 0x5c9e1913, 0x5130b245, 0x034229ee, 0x5f8f7838, 0x504b5004, 0x2605c900, 0x28e94bb8, 0xa275f00b, 0x0f9760f9, 0xf0076ba0, 0x87615820, 0xa04c3ba4, 0xb1ae1859, 0x3b61eb2f, 0xe38fcb37, 0x842371ce, 0x0eec82b8, 0x4d7c3aee, 0xca1d62ce, 0x99141b24, 0x0ebfca7d, 0x747752ab, 0x501818c1, 0xa1649120, 0xaef3f1d9, 0x65957156, 0x78a21bbc, 0xd9c68a9c, 0x2992a9f9, 0x2547e0ee, 0x1d376aea, 0xd513c38b, 0x1e260bc1, 0x52729bab, 0x5221d36e, 0xf17c89e1, 0x77357b45, 0x39582080, 0xca4e2a0b, 0x4c07d8af, 0x798ab138, 0x017be241, 0x1c1fc06e, 0x69137084, 0xc824a961, 0xef09cae5, 0x11e223fd, 0x37b4a238, 0x95c15233, 0xec4be30b, 0xd72a0824, 0x4e6d5bc5, 0x5ea7d2bc, 0xd995c259, 0x69403841, 0xd8bd68dd, 0xef5a8220, 0x5ccd51d6, 0xe0cde2d9, 0x7ac898d6, 0x8558938f, 0x95921af6, 0x986ff965, 0x9a5632ca, 0xdbac09f6, 0xbf429ae1, 0xb1fd509c, 0x88a5701c, 0x277e2b41, 0x683bda00, 0xb2ec31b7, 0xdad7ebb7, 0x1f5de980, 0xadb1d837, 0xf345424e, 0xc90c03e5, 0xa137d9e5, 0x12a00a13, 0x0128aa84, 0xe3dc83f2, 0x1f0ea145, 0x1c4c88ab, 0x0cd54917, 0x5ef49a79, 0xf0542365, 0x530979ea, 0x8649f2a4, 0x3823c2c1, 0x983cb1a0, 0xd8ee2018, 0x7be03252, 0x1388a097, 0x0dfde393, 0x94e9f8b7, 0x2a83c8d2, 0x64ee9317, 0xe2f42976, 0xc69b631c, 0xac9972b3, 0x74241a6e, 0x12f342d6, 0xc877e1a4, 0xf12fc124, 0x67fff23c, 0x00000000, 0x41fa3b3c, 0xd5408b4e, 0xed30014a, 0xc7e0815d, 0x5fdc30fd, 0x79d9f9fd, 0x88f638d9, 0x96d03318, 0xcb35c84a, 0x0239cbaf, 0xb397d3f6, 0xe1b60098, 0xacca3a76, 0x1099c1bc, 0x97abd159, 0x9b7e984e, 0x764e9904, 0xbc00b30f, 0xade290f2, 0x28ba037d, 0xaea0b91c, 0x64bddbd2, 0x34a5c313, 0xc95f4b20, 0x898dda98, 0x0daeab56, 0xd602a2a0, 0x1d64222f, 0x005348c5, 0xd77940e1, 0x9b2dd08b, 0x761dd1c1, 0x755ff82f, 0x34f68bd6, 0x7bb37a97, 0x42b812d2, 0x13dbe852, 0xb086b2dd, 0x390b6845, 0xfeb8a1dd, 0xd46821ca, 0xc5d94af2, 0x38708a04, 0x2bab6256, 0x41a973f9, 0x5de5fb52, 0xc7b3c998, 0x10ca8979, 0xaf881398, 0x42eb5a17, 0x369c08bc, 0xafdb5b5d, 0xe1e5485d, 0x5163fa80, 0x6a51596a, 0x265681c5 +}, +{ +0x7e3c2917, 0xaf83fb8e, 0x60c15899, 0xcf42a317, 0xc52daca8, 0x4602fe04, 0xcdc87ac9, 0x9671e8e0, 0x695249fe, 0x33271faa, 0x27b5619b, 0x9fe2f987, 0xcff8a06c, 0x00ba037b, 0x2679a5e6, 0x1efd718e, 0x535c4448, 0xbb1185bf, 0x0ad50cc4, 0xd95a04f8, 0x8b7087b6, 0x3884d468, 0xc66bb10b, 0xd3350b47, 0x14927e31, 0x0929121c, 0x24f37c38, 0x9537f543, 0xe1ded090, 0xb857981c, 0x607b5be2, 0x253fb845, 0xfda978c0, 0xb0084d06, 0xbadd41c2, 0x8bca84cd, 0xa610eae9, 0xacc5e62d, 0xfeef6563, 0xe981058a, 0xb28294d8, 0xc71d760d, 0x2585bb3e, 0xf54caea1, 0x270f62e0, 0xe8f7c28c, 0xc45b6bae, 0x30db0172, 0xe222ce48, 0x3251d8ac, 0xff99a265, 0x15e4b937, 0x2feab481, 0x2dda6e24, 0x4e5d2b1e, 0x4f2bec18, 0x9f58fafc, 0xce8e676a, 0x443224a1, 0xa5ecf431, 0xa7dc2e94, 0x47ce3a79, 0x9e2e3dfa, 0xb23897a3, 0x81a58b72, 0xfe556618, 0x59334bf7, 0x176e60e9, 0xf4806adc, 0x69e84a85, 0xf6b0b079, 0x61b79f9f, 0xc7a77576, 0x9ca4e424, 0xfd137bbb, 0xaf39f8f5, 0xebb1df2f, 0x77153b0b, 0x7d7a34b4, 0x3bc2c9cb, 0x0230daa5, 0x5b039152, 0x958df638, 0x46b8fd7f, 0x03461da3, 0xac7fe556, 0xc6d1b270, 0xf43a69a7, 0xe298cd33, 0x52908035, 0x448827da, 0xb99b5c61, 0x832f52ac, 0xe0a81796, 0xfcdfbfc6, 0x94413245, 0x00000000, 0xa420304c, 0xbbab86c4, 0x30610209, 0x888c996e, 0x0b19c8b9, 0x39481015, 0x7cb6f0c9, 0x1f8bb688, 0x516c9eed, 0xeac71829, 0x1f31b5f3, 0x4c6df1bb, 0x7ff0ed6a, 0xd38f083c, 0x51d69d96, 0xe93b06f1, 0x2f50b7fa, 0x155eba4c, 0x2e2670fc, 0xaef53c88, 0x501a59eb, 0x8abc43cb, 0x8a0640b0, 0x17d46392, 0x6a14545d, 0x1e4772f5, 0xb3f453de, 0xae4f3ff3, 0x09931167, 0x2c16aa59, 0x96cbeb9b, 0x6387453a, 0xcd7279b2, 0xf60ab302, 0x58458cf1, 0xb34e50a5, 0x4544e3a7, 0x1ccdab2b, 0x50a05a90, 0xcc04beb4, 0x839551d7, 0x689e8d83, 0x7e862a6c, 0x62f1823c, 0xb0b24e7d, 0x7dc037cf, 0x97bd2c9d, 0x1618a7ef, 0x522a834e, 0xd1bfd299, 0xa6aae992, 0x5989488c, 0x2caca922, 0x94fb313e, 0x825995aa, 0x80694f0f, 0x5a755654, 0x0a6f0fbf, 0xd2f9cf3a, 0xb17e8a00, 0xd0c9159f, 0xb1c4897b, 0xd105d1e2, 0x16a2a494, 0x45fee0dc, 0xb8ed9b67, 0xccbebdcf, 0x14287d4a, 0xd9e00783, 0xdbd0dd26, 0x6b62935b, 0x9dd22322, 0x1dbb6c2d, 0x03fc1ed8, 0xe354094e, 0xf7c6777f, 0x624b8147, 0xa7662def, 0xce346411, 0x3a0e0db6, 0x01ccc47d, 0x9d682059, 0xd07316e4, 0xe164d3eb, 0x5acf552f, 0x6bd89020, 0x339d1cd1, 0xf77c7404, 0x31adc674, 0x88369a15, 0x77af3870, 0x68248ef8, 0x82e396d1, 0xd82cc3fe, 0x89405d13, 0x7c0cf3b2, 0x759fe2d5, 0xb9215f1a, 0xf5f6adda, 0x633d4641, 0x085fd51a, 0xba6742b9, 0x53e64733, 0x4cd7f2c0, 0x97072fe6, 0x24497f43, 0x0176c706, 0xdaa61a20, 0xff23a11e, 0x2d606d5f, 0x9c1ee75f, 0xa49a3337, 0xd896c085, 0x745326a8, 0x1c77a850, 0x5bb99229, 0x74e925d3, 0xadb3212b, 0x80d34c74, 0x4ee72865, 0xc4e168d5, 0xe3ee0a35, 0x4f91ef63, 0x89fa5e68, 0x028ad9de, 0xda1c195b, 0x39f2136e, 0xe84dc1f7, 0x3ab40ecd, 0xc597afd3, 0x76d9ff76, 0x2e9c7387, 0x32ebdbd7, 0x3117c50f, 0x47743902, 0xdb6ade5d, 0x383ed713, 0x1d016f56, 0x811f8809, 0x08e5d661, 0x26c3a69d, 0xeb0bdc54, 0x4d1b36bd, 0xfc65bcbd, 0x0ba3cbc2, 0x7f4aee11, 0x7525e1ae, 0x4da135c6, 0x6aae5726, 0xad092250, 0xd243cc41, 0xa556f74a, 0xea7d1b52, 0x610d9ce4, 0xe01214ed, 0x9e943e81, 0x3b78cab0, 0x7663fc0d, 0x58ff8f8a +}, +{ +0x0e91a650, 0xa5f196f5, 0x5d214eb4, 0xee75129e, 0xb05e3c43, 0xcb193d82, 0xd18e94cf, 0x47b6e7f9, 0x492741a9, 0xa078d872, 0x4b84846b, 0x75d6a791, 0xdeb69734, 0x0f3803fb, 0x3a72c8d6, 0x4cae0f2e, 0x9532135f, 0x5533c60a, 0x354acb2d, 0x949bb6f4, 0xc001d555, 0x461f4252, 0x8d067fd0, 0xe7ce3f8b, 0x8514f76e, 0x8b85513e, 0xd5ae7fe3, 0x87b732ac, 0x4fa46f47, 0xe6679a20, 0x3bdb6d7d, 0x01a9a5ab, 0x7dc42f2f, 0xd284f4a6, 0xbdc5fa7a, 0x24c58ab7, 0x2d7ea7a2, 0x888f3157, 0x5e2b2edd, 0x5639a663, 0xe8f63c70, 0xfbdab828, 0x51132d26, 0xb774b706, 0x2cd70209, 0xdb3fd9b3, 0xea55f9b2, 0xc2a21097, 0x132c8458, 0x423fa97e, 0x316a2001, 0xc1a870fe, 0x170c6f74, 0x9f835e23, 0x38d10d14, 0xb6dd12ad, 0x4d07aa85, 0xe0e4b4ce, 0x1a97a94d, 0x3d584393, 0xade31e4b, 0x84bd52c5, 0x79e4c403, 0x2a542ce7, 0x3978a8bf, 0x8fa5ba12, 0x488ee402, 0xa86a50cc, 0x61d0a88c, 0xaee97e22, 0x5a0bc5f1, 0x1c1487a3, 0x2e74c7cb, 0x37e90eef, 0xf7e8dbba, 0xa7525337, 0x50ba888d, 0x8a2cf495, 0x8397d980, 0x9112f873, 0x63736d4e, 0x77756253, 0xab6030a5, 0x747f023a, 0x295e4c8e, 0x28f7e925, 0x43960cd5, 0xd6a41f8a, 0x18346c8f, 0x1f1ee7ca, 0x892694fc, 0x0d9bc639, 0xbf663fb8, 0x67538662, 0xcf39d6ae, 0xa372b81b, 0x6459e60b, 0x06832eee, 0x53b0e8e4, 0x809db9e9, 0x5f828b76, 0x081288be, 0xa6fbf69c, 0xe56dfa49, 0x96387336, 0x3e5223fa, 0x93b13db1, 0xcab09829, 0xddbcf75d, 0x9218981a, 0x072a8b45, 0x6f410edc, 0xc9baf840, 0xfd5996c6, 0xa9c3f567, 0xd70dba21, 0x3640ab44, 0x1026e431, 0x9ba3b50f, 0x20e5619b, 0xf6417e11, 0x7c6d8a84, 0x549a63a1, 0x1eb74261, 0x6ee8ab77, 0xbc6c5fd1, 0x0ab14d7c, 0x030a6069, 0xf16bf554, 0x09bb2d15, 0xb5d772c4, 0xd835b9da, 0xb2fdf981, 0x118f419a, 0x705fe916, 0x6de2cb1e, 0x98a9d566, 0xdf1f329f, 0xc4213e79, 0xaac9950e, 0x4135c917, 0x0420eb2c, 0x409c6cbc, 0x256c2f1c, 0xb1f799e8, 0xd0273164, 0xd407da48, 0x579003c8, 0xa458335e, 0x16a5cadf, 0x0b18e8d7, 0x6b61e5f0, 0xbb46d494, 0x0c326392, 0x9791d69d, 0x861e9707, 0xd32d510d, 0xf8d0d841, 0x5c88eb1f, 0x1dbd2208, 0xe3eed4a7, 0xfcf0336d, 0x199dc924, 0x65f043a0, 0x7ece4f46, 0x71f64cbd, 0xb9e51156, 0x34e36e86, 0x9d209be1, 0xf261953d, 0xfe53f6af, 0xe247710c, 0x4a2d21c0, 0x23ef01f2, 0x00000000, 0xf3c83096, 0xc5889bd2, 0x44bc8790, 0xda967c18, 0x76dcc7f8, 0xbaef713f, 0x3ffb8651, 0xcc33b6c7, 0xf54b1e78, 0xa2db1db0, 0x6ac8405b, 0x128521f3, 0xfffa5304, 0x58a80033, 0x990070cd, 0x214cc430, 0x52194d4f, 0xecd6d75c, 0x72fc2cd4, 0x05894e87, 0xc8135deb, 0xefdcb735, 0xfa731d83, 0x62dac8e5, 0xb47ed76f, 0x5901a598, 0x8cafda7b, 0xe4c45fe2, 0x30c385aa, 0x14060f1d, 0xcd9a136c, 0x66fa23c9, 0xd99c1c71, 0xdc1552f6, 0x7b4701c1, 0x9c893e4a, 0x15afaab6, 0x784d61a8, 0x1b3e0ce6, 0x5ba2605a, 0xbecf9a13, 0x7355897f, 0x2bfd894c, 0xa1d17dd9, 0x9e2afb88, 0xe14d1165, 0x02a3c5c2, 0x686b8599, 0x823e7c2b, 0x2fdd6260, 0xebfc5c19, 0x27cfeade, 0x2246a459, 0xb3545c2a, 0xc72b5e10, 0xf4e2bbd3, 0xb84cb4fd, 0xed7f72f7, 0xe95f99db, 0xaf40db89, 0x4e0dcaec, 0x81341c42, 0x69c22032, 0x7aeea46a, 0x60790d27, 0xf9797dea, 0x3cf1e638, 0xac4abbe0, 0x33c9e5c3, 0x6c4b6eb5, 0xf0c250ff, 0x32604068, 0xce907305, 0x4515223b, 0x8e0c1fb9, 0x9a0a10a4, 0xc682fbbb, 0x26664f75, 0x90bb5dd8, 0xc30bb53c, 0x7f67eaed +}, +{ +0xa81f20db, 0xf7969221, 0xa8f19446, 0xeaf019ef, 0x365ec334, 0x103425a7, 0x0d52ae69, 0x9d57ff7c, 0x8e9b72d5, 0x58e6751d, 0x32c9acdd, 0x175be240, 0xd585afc6, 0x1a094c29, 0x790de0f4, 0x4580fed3, 0x0e44b2fa, 0x2f41938e, 0x5bf0698e, 0xd56b1b5b, 0xf0f955c6, 0xdcaedadb, 0x48d250ba, 0xe0cd7061, 0x3f9b02b4, 0x6ac16d5d, 0x70c82174, 0x6939c553, 0xc5b18a61, 0xbf44c29b, 0x21052174, 0xe4b4ab15, 0x0a3d698e, 0xc80d9095, 0xe3db6cf2, 0x7d743b80, 0x14a34a4e, 0x4696e240, 0x8e75c648, 0x79e35469, 0xab093c48, 0xed716a95, 0x09c5c180, 0x32271840, 0xcb1b8c06, 0x8448afc6, 0x2bd6fc67, 0xa2224955, 0xc1c85115, 0xee89c29b, 0x83276821, 0x5123b49d, 0x2cb93b80, 0xed9fde08, 0xe7a2b786, 0xa6b526bc, 0xb82b057c, 0xfdabfbaf, 0xfa2a88d5, 0x99c09095, 0xa5a33a2f, 0xe45a1f88, 0x56a2c7e7, 0xe023c4fc, 0xcc744be1, 0x555a6fe9, 0x36b077a9, 0xdfb8c648, 0x2faf2713, 0x8a0c1d3c, 0x9db94be1, 0x77a7e693, 0xb66fb786, 0x7d9a8f1d, 0xdc406e46, 0x191f50ba, 0x17b556dd, 0x467856dd, 0x31dfb04e, 0x03161c93, 0x891a01af, 0xbc52de08, 0xf301fdc8, 0xc2de4d86, 0x3548dfa7, 0x22fd897a, 0xcbf5389b, 0xea1ead72, 0xd2ea6821, 0xd204dcbc, 0xdf5672d5, 0x947c8a61, 0x9784226f, 0x1d668bce, 0x63ea1840, 0x51cd0000, 0x381a71ce, 0xf017e15b, 0x7e8c938e, 0x9eaf5772, 0xa13455c6, 0x6daeaaba, 0xd67d07c8, 0x55b4db74, 0x6793c334, 0xfe5353a1, 0x6304acdd, 0x6d401e27, 0xe335d86f, 0xf46e3a2f, 0xd8d701af, 0x25924e9d, 0x8ae2a9a1, 0x745f4e9d, 0x5235a80e, 0x3c8d1e27, 0x5c711af4, 0x6012b04e, 0x6e5602b4, 0x87b007c8, 0x702695e9, 0x2b3848fa, 0xf77826bc, 0xbb3d19ef, 0xbbd3ad72, 0x00000000, 0x8d63dadb, 0xdbc11d3c, 0x4117913a, 0x9e41e3ef, 0x74b1fa00, 0x90055115, 0x2c578f1d, 0x28c0e0f4, 0x076fc7e7, 0x4bc44c29, 0x90ebe588, 0x5f89b2fa, 0x6eb8b629, 0x38f4c553, 0x21eb95e9, 0x5808c180, 0xf3ef4955, 0x7af548fa, 0xabe788d5, 0xa2ccfdc8, 0x456e4a4e, 0xcc9aff7c, 0x5b1edd13, 0x5c9fae69, 0xb1007061, 0xe908b1e1, 0x42018da9, 0xd839b532, 0x69d771ce, 0x1d883f53, 0x677d77a9, 0x992e2408, 0x6a2fd9c0, 0x9a38389b, 0x60fc04d3, 0xe74c031b, 0x1e9e23c0, 0x42ef3934, 0xb8c5b1e1, 0xa1dae15b, 0x875eb355, 0x257cfa00, 0x22133de7, 0xf9d220db, 0xfebde73c, 0x94923efc, 0x35a66b3a, 0xc6a796f2, 0x4f5323c0, 0x00eeb49d, 0xac884f32, 0xaf9e53a1, 0x1ae7f8b4, 0xc649226f, 0x266ae693, 0x0eaa0667, 0xbfaa7606, 0x73de3de7, 0x7749520e, 0x1e70975d, 0x9ad68c06, 0x313104d3, 0x4c453f53, 0x564c737a, 0x52db1c93, 0xa65b9221, 0x483ce427, 0x10da913a, 0xb579ab15, 0x04976fe9, 0x5f670667, 0x3c63aaba, 0x0781737a, 0xb1eec4fc, 0xfac43c48, 0x19f1e427, 0x2684520e, 0x83c9dcbc, 0x4cab8bce, 0xb5971f88, 0x13cc8da9, 0xf4808eb2, 0xac66fbaf, 0x0ad3dd13, 0x3b0c6d5d, 0xa54d8eb2, 0x4b2af8b4, 0x7a1bfc67, 0x3be2d9c0, 0x93134d86, 0x0dbc1af4, 0x976a96f2, 0x144dfed3, 0xee677606, 0xc126e588, 0xf93c9446, 0xe9e6057c, 0x93fdf91b, 0xfd454f32, 0x7330897a, 0x646b6b3a, 0xb2f8d86f, 0x89f4b532, 0x803174b2, 0xc230f91b, 0xd112c02f, 0xaf70e73c, 0x41f925a7, 0x092b751d, 0x8d8d6e46, 0x7e622713, 0xd1fc74b2, 0xcf625772, 0x84a61b5b, 0xdb2fa9a1, 0x03f8a80e, 0x4fbd975d, 0xb2166cf2, 0x80dfc02f, 0x3f75b629, 0x13223934, 0x282e5469, 0xc55f3efc, 0xd693b355, 0x0479db74, 0xb681031b, 0xc8e32408, 0xcf8ce3ef, 0xbcbc6a95, 0x6485dfa7 +}, +{ +0x033b9f12, 0xef1e39b5, 0x86b62f77, 0xc0e18e08, 0xcced9ac5, 0x0e3cbbac, 0xf80b9b08, 0xc9bdd214, 0x18222962, 0xe87ede05, 0x26a3eba1, 0xe579fabb, 0x65a4020f, 0x4a5bb5b2, 0x3cb16da2, 0x84868016, 0xeb454117, 0xac19d01b, 0xd19ffb76, 0x3adaba61, 0xdea870a9, 0xaf224f09, 0x403c76bc, 0x6ec8f172, 0x6b98b9a3, 0x9ca4a974, 0xe64265a9, 0x83e667a6, 0xbe5c3a77, 0x6fc3c101, 0x96c36a7a, 0x5a2ef0bf, 0x0c0c14cd, 0x929812d8, 0x8fea736b, 0x62c4e5bf, 0xfd5bd3d9, 0xfc50e3aa, 0xc68a59cb, 0xa11ef4a5, 0x08576c6f, 0x581e5fde, 0x95f8f568, 0xdfa340da, 0x0760e7b0, 0x94f3c51b, 0x1b19b670, 0x3f8af2b0, 0x1a128603, 0x63cfd5cc, 0xb06081db, 0xdaf3080b, 0x8ddadc0a, 0x4d3b5202, 0x35ed31be, 0x055048d1, 0xae297f7a, 0xa5458c07, 0xa2256bb7, 0x82ed57d5, 0x52799cd0, 0x3dba5dd1, 0xb35b1ec9, 0xc8b6e267, 0x90a8bdb9, 0x010b3073, 0x60f44ade, 0x98ffd1d6, 0x3386e67d, 0x669f9d1d, 0xc5b1c6d9, 0x77e1e863, 0x36d6aeac, 0x2cc428af, 0xbc6c9516, 0x61ff7aad, 0x2dcf18dc, 0x718a3fa0, 0x413746cf, 0x045b78a2, 0xbb0c72a6, 0xcedd35a4, 0x30bd796f, 0x91a38dca, 0x22f89303, 0x7bedfcae, 0x5d4e170f, 0x7ae6ccdd, 0x80ddf8b4, 0x1075450d, 0x55197b60, 0xdd93efbb, 0xb43bf979, 0x34e601cd, 0xaa7207d8, 0xca864d06, 0x420cd9dd, 0x8bb10bc9, 0x259874b3, 0x31b6491c, 0x8981a4a8, 0x8cd1ec79, 0x69a816c2, 0xd7f42cb5, 0xfa3b3469, 0x8ee14318, 0xc2d12169, 0x289f500d, 0xa67e1315, 0x328dd60e, 0xfe604ccb, 0x249344c0, 0x4c306271, 0x00000000, 0x0d0724be, 0xbd67a565, 0x19291911, 0xd6ff1cc6, 0x134eda1f, 0x15250ddc, 0xee1509c6, 0xf157c714, 0x4f0bfd63, 0x5372aca3, 0x75d14702, 0xa015c4d6, 0x504933b1, 0x4657a17f, 0x888a94db, 0x5729d401, 0xf3676875, 0x475c910c, 0x9acf7eb7, 0x2fffb7bd, 0x161e92ce, 0xff6b7cb8, 0xf73c10d7, 0x1715a2bd, 0x21c30c11, 0x7ebdb47f, 0x20c83c62, 0x7d862b6d, 0xf900ab7b, 0xc3da111a, 0xd094cb05, 0x5c45277c, 0xf63720a4, 0xc4baf6aa, 0xb837edb4, 0x7c8d1b1e, 0x37dd9edf, 0x97c85a09, 0xcfd605d7, 0xb700666b, 0x1245ea6c, 0x456c3e6d, 0xa44ebc74, 0x3bd18a12, 0x99f4e1a5, 0x74da7771, 0xd9c89719, 0x73ba90c1, 0x9e940615, 0x59156fad, 0x49602aa0, 0xf4078fc5, 0xd5c483d4, 0x23f3a370, 0xd4cfb3a7, 0xa32e5bc4, 0x0a67c30e, 0x68a326b1, 0xa842a8b9, 0xfb30041a, 0x0f378bdf, 0xe1228219, 0x066bd7c3, 0xe975ee76, 0x095c5c1c, 0xdbf83878, 0x38ea1500, 0x5622e472, 0x9daf9907, 0x39e12573, 0xf05cf767, 0xe74955da, 0xf50cbfb6, 0xd8c3a76a, 0x858db065, 0x1d7261b3, 0xb60b5618, 0x2aafff6c, 0x5f7eb86e, 0xf26c5806, 0x2994607e, 0xd2a46464, 0x6cf85e13, 0x2ef487ce, 0xa94998ca, 0xea4e7164, 0x76ead810, 0x1f42ced2, 0x78d663bc, 0x4b5085c1, 0xbf570a04, 0xb16bb1a8, 0xab7937ab, 0xe029b26a, 0x0b6cf37d, 0xad12e068, 0x1c7951c0, 0x0230af61, 0x7fb6840c, 0xe2191d0b, 0x514203c2, 0x64af327c, 0x27a8dbd2, 0x1e49fea1, 0x6794ad6e, 0x5b25c0cc, 0xdc98dfc8, 0x5e75881d, 0x3e81c2c3, 0x4307e9ae, 0xa7752366, 0xba0742d5, 0xb530c90a, 0xcb8d7d75, 0x44670e1e, 0x79dd53cf, 0x9f9f3666, 0x54124b13, 0xed2e96d4, 0x2ba4cf1f, 0x939322ab, 0xe3122d78, 0x142e3daf, 0x81d6c8c7, 0x486b1ad3, 0xd3af5417, 0xcde6aab6, 0xec25a6a7, 0x6df36e60, 0x117e757e, 0xb2502eba, 0x9bc44ec4, 0xb93cddc7, 0x6a9389d0, 0x72b1a0b2, 0x87bd1f04, 0x70810fd3, 0x4e00cd10, 0xe472cac8, 0xc1eabe7b, 0xc78169b8, 0x8aba3bba +} +}, +{ +{ +0x16a2f28f, 0x1f59d6d0, 0xd3d57010, 0x3332279a, 0x2ebaa8c1, 0xdd254320, 0x7843d1ce, 0x20a1cdcd, 0x4c7ae13b, 0x76b3e2fe, 0x82cc484c, 0x05da4ee4, 0x9654b574, 0xdf1f4c97, 0xa0578a36, 0x47509cef, 0x915fa21b, 0xf6aef339, 0xfa8f9982, 0xcc67f0fc, 0x2e51fefd, 0xa7b7cb65, 0x622b1fc6, 0xb3c46061, 0x80f647fb, 0xfd848eed, 0x070b176f, 0x4c91b707, 0xc0469a47, 0x65cb5e95, 0x0cca3c87, 0xd33e262c, 0x7a928845, 0xceb6a977, 0x9faf912b, 0xaea7b906, 0x3108282d, 0x67f15122, 0xb61e2e85, 0x6ee12341, 0x671a071e, 0xa286d3bd, 0x8bdc3a2f, 0x09fb245f, 0x890d63a4, 0x7f48c6a1, 0x532337eb, 0x7153a3ad, 0xbad41202, 0xc297c3cc, 0xd4353143, 0x1a68ce08, 0x1473ab04, 0xffbe815a, 0xf645a505, 0x652008a9, 0x343930f5, 0x9a75dfcf, 0xba3f443e, 0x29b1bfae, 0x02d1598b, 0x0c216abb, 0xe70716d9, 0x42618437, 0x5d3852e7, 0x8b376c13, 0x3ff81b1d, 0xcb6ce793, 0xc7a6db14, 0x58094a3f, 0xe00c01b6, 0xec2d6b0d, 0xf85ec009, 0x89e63598, 0xa947f855, 0x18b99783, 0xc956e824, 0xdac50273, 0x98a48644, 0x47bbcad3, 0x4eabb8b0, 0x82271e70, 0x07e04153, 0xac9db6b1, 0xcc8ca6c0, 0xce5dff4b, 0x33d971a6, 0xb11539ea, 0xd60f3ef4, 0xe9f725e9, 0xb8054b89, 0x5fe90b6c, 0x1d888f5b, 0xc74d8d28, 0x69ea342e, 0xc59cd4a3, 0x852c091f, 0xd6e468c8, 0x38185a4e, 0x27418c9e, 0x9d7ec8a0, 0xa75c9d59, 0xd4de677f, 0x405b8b80, 0xa9acae69, 0x1393ea57, 0x2b60e625, 0x2b8bb019, 0xb32f365d, 0x3dc214aa, 0x3a2255f9, 0x2c80a776, 0xc0adcc7b, 0x69016212, 0xf1a5e456, 0x7d999f2a, 0xf39febe1, 0xf494fc8e, 0xda2e544f, 0x0ef03330, 0xa56692ee, 0xf47faab2, 0x7382fa26, 0xab96a1de, 0x5119385c, 0x22709446, 0x1fb280ec, 0xfa64cfbe, 0x984fd078, 0x53c861d7, 0x71b8f591, 0xfd6fd8d1, 0x0b2a7dd4, 0x56122f33, 0x801d11c7, 0x87fd5094, 0x7462bb75, 0xeefc3286, 0xab7df7e2, 0x6e0a757d, 0x00eb563c, 0x295ae992, 0x2c6bf14a, 0x6c307aca, 0x91b4f427, 0xac76e08d, 0x023a0fb7, 0x27aadaa2, 0xa58dc4d2, 0x60111071, 0xe2dd583d, 0x456a9358, 0x36033f42, 0xa26d8581, 0xc27c95f0, 0x053118d8, 0x9365adac, 0xe7ec40e5, 0x0bc12be8, 0xf8b59635, 0xe0e7578a, 0x1142b3dc, 0x49a0afdf, 0xb6f578b9, 0xae4cef3a, 0x4b71f654, 0xf14eb26a, 0xe53d196e, 0x96bfe348, 0x5f025d50, 0xc577829f, 0x8e0674cb, 0x257b8329, 0x85c75f23, 0x3ac903c5, 0x78a887f2, 0x51f26e60, 0xbfe50ada, 0xd8145bf8, 0xc9bdbe18, 0x8cd72d40, 0xbd345351, 0x58e21c03, 0xb8ee1db5, 0x204a9bf1, 0x8eed22f7, 0x7489ed49, 0xa0bcdc0a, 0x3d294296, 0x09107263, 0x5dd304db, 0x1a839834, 0x7a79de79, 0x5ad813b4, 0x4e40ee8c, 0x3f134d21, 0x36e8697e, 0x60fa464d, 0x00000000, 0x54282084, 0x31e37e11, 0xf374bddd, 0xb4242132, 0x428ad20b, 0x4b9aa068, 0xecc63d31, 0x62c049fa, 0x7d72c916, 0x6bd03b99, 0xe5d64f52, 0xd8ff0dc4, 0x40b0ddbc, 0xee1764ba, 0xb1fe6fd6, 0xddce151c, 0x8c3c7b7c, 0x946ebac3, 0x9f44c717, 0x56f9790f, 0x9485ecff, 0xd104299b, 0x11a9e5e0, 0x4581c564, 0x229bc27a, 0xbf0e5ce6, 0x938efb90, 0x9a9e89f3, 0xb4cf770e, 0x5a334588, 0xcb87b1af, 0x54c376b8, 0x1649a4b3, 0xe91c73d5, 0xd1ef7fa7, 0x7658b4c2, 0xebcd2a5e, 0x0e1b650c, 0x6b3b6da5, 0xe2360e01, 0x9d959e9c, 0xdff41aab, 0x1498fd38, 0x1852c1bf, 0x7369ac1a, 0x871606a8, 0x38f30c72, 0x2590d515, 0x7fa3909d, 0xbddf056d, 0x34d266c9, 0xff55d766, 0x494bf9e3, 0x1d63d967, 0x1378bc6b, 0x6cdb2cf6, 0xeb267c62 +}, +{ +0xc6ab51fa, 0x065c90fd, 0xb6a3e952, 0x8e1dcbb4, 0x5b9deeef, 0x1176dbb4, 0x0217219b, 0xd62ddb5e, 0x8c4064a1, 0xa189a21b, 0xe975b6db, 0xd470744b, 0x8fa7142a, 0x6535d27a, 0x60c4bc82, 0x05bbe076, 0x00000000, 0x583010ea, 0xed3e07bd, 0x67687d6f, 0xecce56ad, 0x5fd65f89, 0xd66755d0, 0xa5889df3, 0xb50e1757, 0x993780fd, 0x74098740, 0x6134ed92, 0x16da1a59, 0xc310b18c, 0xa26ed290, 0x4d0d7a38, 0xeed97736, 0x4ea0843d, 0x6323cc09, 0x1577e45c, 0x66982c7f, 0x617e631c, 0x14cd3bc2, 0x4946cb5e, 0x4d47f4b6, 0x2b955647, 0xfbae936a, 0x03e7708b, 0x6722f3e1, 0xa39e8380, 0xa432426d, 0x3f586d85, 0x5dc17e12, 0x9ed1cf9e, 0xa079f30b, 0x587a9e64, 0x9d7c319b, 0x132b74a1, 0x73a546ad, 0x2a650757, 0x9c8c608b, 0xd22ce4b6, 0xf849e3e1, 0x07e64f63, 0xfc48dc09, 0x2e6438bf, 0xf9f33c7f, 0xec84d823, 0x997d0e73, 0x89b10a59, 0xc2aa6e12, 0x62991397, 0xd2666a38, 0x3cbf1d0e, 0xf8036d6f, 0x70423626, 0x608e320c, 0x2d834834, 0x2f9469af, 0x044bb166, 0xea92c650, 0x9d36bf15, 0xe8cf6945, 0x880bd5c7, 0x2c731924, 0x66d2a2f1, 0x657f5cf4, 0x8a567ad2, 0xb6e967dc, 0xb54499d9, 0x4aeb355b, 0x1291ab3f, 0x5c312f02, 0x48b69a4e, 0x05f16ef8, 0xc1079017, 0x3f12e30b, 0x9ad0f076, 0x2e2eb631, 0xb35287aa, 0x77eef7cb, 0x3904fd78, 0x03adfe05, 0xa1c32c95, 0x5e6c8017, 0x8a1cf45c, 0xc0f7c107, 0x76542855, 0xead848de, 0xb10f28bf, 0x8db035b1, 0xb71936cc, 0x2bdfd8c9, 0x5f9cd107, 0x761ea6db, 0xd1cb943d, 0x9f6b1000, 0xd3dcb5a6, 0xa2245c1e, 0x71f8e9b8, 0xa66fed78, 0xc14d1e99, 0x4b1b644b, 0xd1811ab3, 0xc7118e64, 0x01f05110, 0xeb2819ce, 0xb4b4c8c9, 0xa5c2137d, 0xd43afac5, 0xb753b842, 0x3d4f4c1e, 0x7008b8a8, 0x8beca54c, 0x172a4b49, 0xc0bd4f89, 0x4aa1bbd5, 0x75b358de, 0xe93f3855, 0xfe15731c, 0xd0714ba3, 0xa0337d85, 0xfe5ffd92, 0x77a47945, 0x3cf59380, 0x38be22e6, 0xa62563f6, 0xfc025287, 0x4eea0ab3, 0x64c5836a, 0x725517bd, 0x721f9933, 0x5a273171, 0x5d8bf09c, 0xef292626, 0x490c45d0, 0x4f1a5ba3, 0x5e260e99, 0x8fed9aa4, 0x89fb84d7, 0xed748933, 0x63694287, 0x287226cc, 0x9e9b4110, 0x8c0aea2f, 0xfdb88d19, 0x48fc14c0, 0x07acc1ed, 0x9a9a7ef8, 0x9cc6ee05, 0x3d05c290, 0xd580255b, 0x2c3997aa, 0xfa144cf4, 0xc506afff, 0xa478cce3, 0x648f0de4, 0x3ae38df3, 0xc75b00ea, 0x025daf15, 0x71b26736, 0x1487b54c, 0xd7dd8a4e, 0x153d6ad2, 0x10868aa4, 0x394e73f6, 0xb145a631, 0xa3d40d0e, 0xc2e0e09c, 0x59c041fa, 0x598acf74, 0x88415b49, 0x1361fa2f, 0x169094d7, 0xe885e7cb, 0x06161e73, 0xb0ff79af, 0x5c7ba18c, 0x8e57453a, 0x10cc042a, 0xffe5220c, 0x12db25b1, 0xfdf20397, 0xd5caabd5, 0x2fdee721, 0x3b13dce3, 0x38f4ac68, 0xfa5ec27a, 0x4f50d52d, 0x3b59526d, 0x298277dc, 0xb0b5f721, 0x04013fe8, 0x73efc823, 0x8ba62bc2, 0xc35a3f02, 0x3ee2b21b, 0x75f9d650, 0x9b20a166, 0x29c8f952, 0x5a6dbfff, 0x5bd76061, 0xb2a2d6ba, 0x113c553a, 0xfbe41de4, 0x98c7d1ed, 0x3ea83c95, 0xf9b9b2f1, 0xd03bc52d, 0xffafac82, 0x4cb7a5a6, 0x62d39d19, 0x744309ce, 0xb4fe4647, 0xeb629740, 0xef63a8a8, 0x01badf9e, 0xc6e1df74, 0xd79704c0, 0x2a2f89d9, 0xee93f9b8, 0xc4f6feef, 0x3aa9037d, 0x988d5f63, 0xc4bc7061, 0x9f219e8e, 0xa79fbc68, 0x2838a842, 0x004a8e8e, 0xa7d532e6, 0xd3963b28, 0xc54c2171, 0x1760c5c7, 0xb3180924, 0x9b6a2fe8, 0x4b51eac5, 0x4cfd2b28, 0xb2e85834, 0x2dc9c6ba, 0x8dfabb3f +}, +{ +0xb715e80d, 0x7a1df68b, 0x381b8985, 0x3d54d300, 0x48a9ef01, 0xf87533f5, 0x676f2e96, 0xf77c5523, 0xb57a2a2d, 0x55329b40, 0xc087162c, 0x6a098a60, 0x62c9d84f, 0x25695198, 0xd2fca8e7, 0x15b28a32, 0x20260b1d, 0xfa1af1d5, 0x42efd352, 0x0aaf900f, 0x18d42ec4, 0x4f8977a4, 0xeae72162, 0x0829fe73, 0xad47a8b5, 0x787234ab, 0x325db5d6, 0xf05ccd86, 0xfdd3c52c, 0x4749258b, 0xadae04e9, 0xf5fa3b5f, 0xd85338e8, 0x575d5960, 0x1f1d1a3d, 0x70b26684, 0x8007075e, 0xb03570a8, 0x05a6f6d9, 0xddf5ce31, 0x4d0f19d8, 0x95b58d6c, 0x9abcebba, 0x1ff4b661, 0xc06eba70, 0x789b98f7, 0xf5139703, 0xb0dcdcf4, 0xf0b561da, 0x68664840, 0xd8ba94b4, 0xef41d7bb, 0x2d40afeb, 0x155b266e, 0x5df2c96f, 0x7af45ad7, 0xb81c8edb, 0xa56e56c6, 0xaa8e9c4c, 0xe888e342, 0x5ad251ca, 0x10147ceb, 0xba734cfb, 0x1abbece4, 0x97da4f4c, 0x927cb995, 0x072098a5, 0xa24ece63, 0x10fdd0b7, 0x62207413, 0xc521e0f5, 0xa587fa9a, 0x8aa89751, 0x40801172, 0xa808f230, 0xfd3a6970, 0x52fbafb9, 0xda3cfac8, 0xe76829c8, 0xc2e8d40c, 0x9f1a1d63, 0x270693b8, 0x604fb633, 0xb2b31ed4, 0xdad55694, 0x45cf4bf7, 0x3a9de7f9, 0xf2daa3fa, 0x4069bd2e, 0x00e9ac5c, 0xdd1c626d, 0xb8f52287, 0x72dda4a4, 0xb7fc4451, 0x955c2130, 0xa8e15e6c, 0xbdba7802, 0x6d2912c5, 0xcac12a7f, 0xc7a78e89, 0xe8614f1e, 0xe5ee47b4, 0xffbc070c, 0x07c934f9, 0x9d9c731f, 0xea0e8d3e, 0xd0936ac7, 0x983a85c6, 0x705bcad8, 0xca288623, 0xa2a7623f, 0x3594812f, 0xcd081e86, 0x60a61a6f, 0xd7b3f262, 0x1d72d81d, 0x3a744ba5, 0x4a2f817d, 0xe227734d, 0x2da903b7, 0xb5938671, 0x85485ddb, 0x6f46d0e5, 0x7dd4c272, 0x42067f0e, 0xf795f97f, 0xa7e838ba, 0x5f74a713, 0x08c0522f, 0x183d8298, 0x6ae0263c, 0x507dc1c5, 0x3f3b1120, 0x0d8f08aa, 0x88c75571, 0xd07ac69b, 0x9733e310, 0x8d880ff4, 0x0f0966d6, 0xc8aee85f, 0x9d75df43, 0x1a5240b8, 0xc8474403, 0xe7818594, 0xd5359c1e, 0x6dc0be99, 0xbf3c167e, 0x4526e7ab, 0x8fe7cdd4, 0x65e940ea, 0x2f2f6dcb, 0x90fad7e9, 0x37fb430f, 0x3dbd7f5c, 0x9ff3b13f, 0xc5c84ca9, 0x75fd3c01, 0xefa87be7, 0x8268c57e, 0x82816922, 0x4ac62d21, 0xcf67dca6, 0x7514905d, 0x85a1f187, 0x90137bb5, 0x723408f8, 0x777b527d, 0x882ef92d, 0x28e65932, 0x7f52ac0e, 0x47a089d7, 0xaf286a95, 0x2249c93d, 0x3fd2bd7c, 0x2fc6c197, 0xe0a11d31, 0x58bd93ea, 0x17dd4812, 0x054f5a85, 0x026fc220, 0x22a06561, 0xafc1c6c9, 0xf89c9fa9, 0x1d9b7441, 0x7d3d6e2e, 0x27ef3fe4, 0x87ce33a7, 0xedc7b9c7, 0xaa673010, 0x7792fe21, 0x0a463c53, 0x57b4f53c, 0xe2cedf11, 0xfaf35d89, 0x00000000, 0x3712ef53, 0x1734e44e, 0x2a60374e, 0x4de6b584, 0x521203e5, 0x58543fb6, 0x357d2d73, 0xd5dc3042, 0xba9ae0a7, 0x4f60dbf8, 0x5a3bfd96, 0x303277f6, 0x7fbb0052, 0x8d61a3a8, 0x2580fdc4, 0xed2e159b, 0xcf8e70fa, 0xf2330fa6, 0x12921297, 0x6faf7cb9, 0x50946d99, 0xdf73a04d, 0xe507ebe8, 0xd21504bb, 0x127bbecb, 0x9a5547e6, 0x929515c9, 0x8f0e6188, 0x0d66a4f6, 0xbd53d45e, 0x32b4198a, 0xa0210c43, 0xdf9a0c11, 0x38f225d9, 0xa0c8a01f, 0x87279ffb, 0xa70194e6, 0x8a413b0d, 0x6500ecb6, 0x280ff56e, 0x2a899b12, 0x20cfa741, 0x4840435d, 0xb25ab288, 0x98d3299a, 0xc74e22d5, 0x688fe41c, 0xbfd5ba22, 0x02866e7c, 0xc2017850, 0x678682ca, 0x55db371c, 0x30dbdbaa, 0xd75a5e3e, 0x5d1b6533, 0x5f9d0b4f, 0x0fe0ca8a, 0x80eeab02, 0xcde1b2da, 0xff55ab50, 0xe048b16d +}, +{ +0xd5319b26, 0x8ba3c640, 0x6deb2190, 0x5e1e1d35, 0x369d8c4a, 0x65eae9ba, 0xa786fe04, 0x2ca97817, 0xf6dc9e01, 0x175d8c98, 0x0fc83d63, 0x12b97c24, 0x49cfd1fe, 0x5432d0ea, 0xa70abe57, 0xcf056f7b, 0x9c720a8b, 0x02a145a6, 0x442ae968, 0x05e4f0bc, 0xc8cc9a32, 0x62231cf3, 0xddbc135f, 0x2c253844, 0xe3ac176c, 0x5cbf5893, 0x23ed0527, 0xc2e057ed, 0x890283e6, 0xaf87362e, 0xad267388, 0x1895b1fb, 0xbf9f0fac, 0xc840da61, 0x3cb14195, 0x77dfd5cd, 0x9996fa37, 0x53fb25a3, 0xe320573f, 0x12353c77, 0x0745b51a, 0x83a20e6a, 0x6fc62465, 0xaf0b767d, 0x0de53896, 0x832e4e39, 0x680fd12c, 0xa04f0b4d, 0x8b2f8613, 0x31d83950, 0xb0db729c, 0xdf9116aa, 0xb856fae5, 0x1ab8b40e, 0x2beccd0d, 0x8ecb76af, 0x5c3318c0, 0x088d8879, 0xa84ec367, 0x70162084, 0x1fd004e1, 0x5693954c, 0xbf134fff, 0x84e7bb70, 0x7fde1de7, 0xf47ddba7, 0x00000000, 0x561fd51f, 0x846bfb23, 0x6d6761c3, 0xd0d56b9a, 0x818f0b9f, 0x3e9c4460, 0x898ec3b5, 0x29c1c8f8, 0x41425987, 0xbaf7bf43, 0xe10d52ca, 0x3955b129, 0x3611cc19, 0xa2ee4eeb, 0xd71c9ed3, 0xc5a5e2f7, 0x7df31812, 0x214c4081, 0x81034bcc, 0xdd30530c, 0xebaddf46, 0x23614574, 0xa527bba2, 0xf3386ebd, 0x34b089bf, 0x2685b5c8, 0xf3b42eee, 0x7d7f5841, 0xd0592bc9, 0x9bbbffc2, 0x537765f0, 0xa0c34b1e, 0x96d28707, 0xec642a0f, 0x1570896d, 0x1dfd0114, 0xcf892f28, 0xcda42add, 0xd790de80, 0xb2f67769, 0xd8d4a3b0, 0x67c7ec4f, 0xd5bddb75, 0x9473c2a1, 0x4ca76111, 0xa8c28334, 0xb27a373a, 0xf1992b1b, 0x6a22d4d9, 0x1819f1a8, 0xbdb20a59, 0x5b76adda, 0x8ce6735a, 0x43e31c21, 0x8e4736fc, 0xe465e225, 0xba7bff10, 0xc704a751, 0xa2620eb8, 0xf1156b48, 0x15fcc93e, 0x24a8b03d, 0x33797cf6, 0x59d7e87c, 0xe90c9ae0, 0x600e1906, 0x9e5f0f7e, 0x0801c82a, 0x9197321d, 0xfb39a697, 0xeec56fa9, 0x723b2571, 0xd858e3e3, 0x0d6978c5, 0x62af5ca0, 0x468bacce, 0xee492ffa, 0xd2742e3c, 0x41ce19d4, 0xdf1d56f9, 0x0aa08d8c, 0x3e100433, 0x0f447d30, 0x1f5c44b2, 0x60825955, 0x709a60d7, 0xece86a5c, 0xe6c4a783, 0xfedd562b, 0x9b37bf91, 0xda75e616, 0xc529a2a4, 0xfbb5e6c4, 0x4c2b2142, 0x31547903, 0xe4e9a276, 0x39d9f17a, 0x72b76522, 0x4be2d40b, 0x0568b0ef, 0x494391ad, 0x6566a9e9, 0x9cfe4ad8, 0x933677bb, 0x515a6005, 0xc788e702, 0x595ba82f, 0x4e0624b7, 0xfe511678, 0x4b6e9458, 0x07c9f549, 0xf998e331, 0x1a34f45d, 0x022d05f5, 0x5bfaed89, 0x3bf4f48f, 0x86cabe85, 0x2b608d5e, 0x10183982, 0xaa63c692, 0xc0cd5218, 0x54be90b9, 0xeb219f15, 0xf4f19bf4, 0xe1811299, 0x436f5c72, 0x4607ec9d, 0x6f4a6436, 0x7f525db4, 0x5e925d66, 0xb8dabab6, 0x7753959e, 0xa5abfbf1, 0x7817e8ae, 0x008c4053, 0xc041124b, 0x2e847de2, 0x343cc9ec, 0x93ba37e8, 0x7ab6ad08, 0xadaa33db, 0x965ec754, 0xbd3e4a0a, 0x674bac1c, 0x21c000d2, 0x2609f59b, 0xb05732cf, 0x33f53ca5, 0x94ff82f2, 0xb53f8220, 0xb5b3c273, 0xfcf053de, 0x9ed34f2d, 0xe648e7d0, 0x911b724e, 0x294d88ab, 0x75f2d038, 0x2e083db1, 0xb71287d5, 0xcd286a8e, 0x1d714147, 0x757e906b, 0x109479d1, 0x44a6a93b, 0xdaf9a645, 0xfc7c138d, 0xaaef86c1, 0x991aba64, 0xf914a362, 0x8c6a3309, 0x789ba8fd, 0xcae19fc7, 0x3c3d01c6, 0x17d1cccb, 0xd2f86e6f, 0xf650de52, 0x3b78b4dc, 0x8646fed6, 0x0a2ccddf, 0xca6ddf94, 0xb79ec786, 0x4e8a64e4, 0xc26c17be, 0x6883917f, 0xe980dab3, 0x6aae948a, 0x2424f06e, 0x7a3aed5b, 0x51d62056 +}, +{ +0x8c01f3e8, 0x46009236, 0xb67662b8, 0xc53460eb, 0x4e1babe0, 0x3c8d9cce, 0x3e9faa53, 0x3496a518, 0x3750a6f8, 0xfee2c866, 0x49359303, 0x715034ce, 0xb5b06158, 0xbb515510, 0x4e6ea740, 0xc07d6235, 0x8da0ca35, 0x767e0c2d, 0xca0161de, 0x75cd036d, 0x8087fd9d, 0x4c099d7d, 0x0c860e75, 0x82e0c7a0, 0xfc85f25b, 0xba85606d, 0x3865a7cd, 0x7296372e, 0x3ba3a42d, 0x8126c440, 0xc3ce6d75, 0x06fa0d9e, 0x03b30f40, 0x893dfd96, 0xf9ccf085, 0x4b27a59e, 0x049d37a3, 0xc6f2630b, 0x0d523b08, 0xb943638d, 0xc1dc5be8, 0xb6036e18, 0x793e01b8, 0x33b89dfb, 0xb08c6f26, 0xb8e25a50, 0xc7265676, 0xf86dc958, 0x00000000, 0xf264c613, 0xfd51c726, 0x3219a426, 0x8153c8e0, 0x80f2f13d, 0x3eeaa6f3, 0xb5c56df8, 0x0f350135, 0x04e83b03, 0xf9b9fc25, 0xbb2459b0, 0x33cd915b, 0xfbdec618, 0xc7535ad6, 0xb0f96386, 0x88e9c8eb, 0x49409fa3, 0xf6f9f1b0, 0x31aaab66, 0x7b593b85, 0x48e1a67e, 0x8a8ef2d6, 0x73420253, 0x8fc7f008, 0x0cf302d5, 0xbdde542e, 0x02673a3d, 0x794b0d18, 0x075b3443, 0xf4ebc72d, 0xcbd554a3, 0x8dd5c695, 0xc6876fab, 0x40fa9fa8, 0x867df003, 0xc4955936, 0x7125386e, 0xbe6d5b6e, 0x4c7c91dd, 0xf818c5f8, 0x7c020fc6, 0xf3c5ffce, 0xf49ecb8d, 0x326ca886, 0xb4115885, 0x85ceff43, 0xcd2f593d, 0x8341fe7d, 0xbe1857ce, 0x00750ca0, 0x4ddda800, 0x3d2ca513, 0xb12d56fb, 0xbfcc62b3, 0x7dd63abb, 0x408f9308, 0xf076f08e, 0xfd24cb86, 0x846fc69e, 0x086e3576, 0x072e38e3, 0x8295cb00, 0x45b39d76, 0x8c74ff48, 0xc9b26e9e, 0x3f4b9f2e, 0xcf486300, 0x7e6535fb, 0x889cc44b, 0xc26f54a8, 0xb7a257c5, 0xf1a2c5f3, 0x4894aade, 0x7fc40c26, 0xf68cfd10, 0x47d4a74b, 0x75b80fcd, 0x068f013e, 0x8608fca3, 0x46759e96, 0x47a1abeb, 0xcf3d6fa0, 0xf53ff250, 0xf211cab3, 0x7b2c3725, 0x4a869c43, 0x4fba923d, 0x0bdd3a36, 0xb29e59bb, 0xf54afef0, 0xc9c7623e, 0x434990e8, 0x3810ab6d, 0x7fb10086, 0x8afbfe76, 0x01d4357d, 0xb9366f2d, 0xc5416c4b, 0x429da595, 0xbaf06ccd, 0xcee95add, 0x8b5ac7ab, 0x3cf8906e, 0x87dcc9de, 0x8e66c9d5, 0x09cf0cab, 0xc21a5808, 0xcba05803, 0xb4645425, 0x053c0e7e, 0x0e9438e8, 0xfa7fffc5, 0x34e3a9b8, 0x4fcf9e9d, 0x0d2737a8, 0x45c691d6, 0x0212369d, 0xfe97c4c6, 0xb1585a5b, 0x307e9e1b, 0x4da8a4a0, 0x36f19f25, 0x0f400d95, 0x36849385, 0xb2eb551b, 0x433c9c48, 0xbc0a6153, 0xc1a95748, 0xc4e05596, 0x708401b3, 0xf72dc4cd, 0xff36fd1b, 0x0a090f4b, 0xf003fc2e, 0xb33f6066, 0xbdab588e, 0xfcf0fefb, 0x3725aa58, 0x39b192b0, 0x7af80258, 0x31dfa7c6, 0x8fb2fca8, 0xf1d7c953, 0xb7d75b65, 0x4af390e3, 0x4b52a93e, 0xca746d7e, 0x7e10395b, 0x73370ef3, 0x746c3ab0, 0x77aa3950, 0xfbabcab8, 0x841aca3e, 0x42e8a935, 0x054902de, 0x0ba83696, 0x8948f136, 0xbfb96e13, 0xff43f1bb, 0x0ee13448, 0x0a7c03eb, 0xb89756f0, 0x081b39d6, 0x87a9c57e, 0x3f3e938e, 0x412eaad5, 0x72e33b8e, 0xc8665be3, 0x01a139dd, 0x8e13c575, 0x39c49e10, 0xccfb6c40, 0x7da3361b, 0x77df35f0, 0x3a779150, 0x70f10d13, 0x760b008d, 0xcc8e60e0, 0x3d59a9b3, 0xcd5a559d, 0x300b92bb, 0xc0086e95, 0xc8135743, 0x7a8d0ef8, 0x4412a4ab, 0x35429065, 0x35379cc5, 0x3a029df0, 0xc3bb61d5, 0xf3b0f36e, 0xf758c86d, 0x03c603e0, 0x8b2fcb0b, 0xb34a6cc6, 0x7c770366, 0x3bd6a88d, 0x85bbf3e3, 0x09ba000b, 0x74193610, 0x789f3865, 0x8334f2dd, 0xfa0af365, 0x415ba675, 0xce9c567d, 0x78ea34c5, 0xbc7f6df3, 0x4467a80b +}, +{ +0xcc3fa03d, 0xd89f2eef, 0xec542549, 0xd498055d, 0xac05367b, 0xbf904153, 0xf33e7e8d, 0x7357e630, 0x1458898c, 0xb89c74b6, 0xc70d7275, 0x2052496b, 0xdf52d04b, 0x4cae3fde, 0xb3aea6fe, 0x7fa8cadc, 0xe092c5ba, 0xdfaad715, 0x1fab9085, 0x78653478, 0xeba017f2, 0xd85ee5ae, 0xd355fbf9, 0xe0530efb, 0x34f2c7b9, 0x13acbb37, 0xabc8c8df, 0x60fb5d07, 0xb45a9445, 0x4ba20a3b, 0xec95ee08, 0x94311131, 0x3f3812af, 0x6b318811, 0x745bd3d5, 0xa0fa1a97, 0xc0388b8f, 0x07cdfea4, 0xe7a73c40, 0xbf518a12, 0x136d7076, 0xb85dbff7, 0x98ce3ddd, 0x6bc98f4f, 0x749a1894, 0x20aa4e35, 0xacfd3125, 0x980ff69c, 0x4764eac8, 0x2093822a, 0x8b9a81b4, 0x98f7f1c2, 0xffc15261, 0x78a4ff39, 0xa0c3d688, 0x94c9166f, 0x60c29118, 0xd86729b1, 0x533c6344, 0xcc066c22, 0x670f6fbc, 0x34330cf8, 0x40a9146c, 0x38f5ec0b, 0x74621fca, 0x340ac0e7, 0xe06ac2e4, 0x40511332, 0xd8a6e2f0, 0x8b5b4af5, 0x6c0471eb, 0xeb99dbed, 0x2767b091, 0xccc7a763, 0x206b8574, 0x543056a1, 0xc0c08cd1, 0x2cad6587, 0xa70e282c, 0x8765ad58, 0xcb0a59c7, 0xb36f6dbf, 0xf83560da, 0xa03bd1d6, 0xf4f38029, 0x54f19de0, 0xab09039e, 0xe75f3b1e, 0x933d24d4, 0x33c73e43, 0x2c94a998, 0x4b9bc624, 0x879daa06, 0xe0ab09a5, 0xff009920, 0x9304e8cb, 0xf8f4ab9b, 0xb3976ae1, 0x5ffa83b7, 0x67f768e2, 0x54c851ff, 0x80a853fc, 0x54099abe, 0x0bf31909, 0xccfe6b7c, 0xd4a1c942, 0xcb3395d8, 0x6736a3a3, 0xd3adfca7, 0xecac2217, 0x80919fe3, 0x18a7a560, 0x5fc34fa8, 0xb356a1a0, 0xd459ce1c, 0x9f03c379, 0x73962d71, 0x1f5397db, 0x98363a83, 0x580eb10c, 0x185fa23e, 0x73afe16e, 0x1354bc69, 0x4c97f3c1, 0x475d26d7, 0xd36c37e6, 0x2b609b23, 0x00c1cb41, 0x603a9646, 0xc7ccb934, 0xab30cf81, 0x53fda805, 0xf4ca4c36, 0xb49b5f04, 0xff39553f, 0xf80cacc5, 0xe766f701, 0xc734be6a, 0x38cc2014, 0x0cc6e0f3, 0x189e697f, 0xbfa98d4c, 0xdf6b1c54, 0x4068df2d, 0xdf931b0a, 0xac3cfa64, 0x6cc5baaa, 0x6b08440e, 0xec6de956, 0xb4a2931b, 0x9408dd2e, 0x479ced96, 0x9ffbc427, 0x5f3b48f6, 0x0cff2cec, 0xf3ffb5cc, 0x4c563880, 0x1f925c9a, 0xa7cfe36d, 0x2ba15062, 0x93c5238a, 0x4c6ff49f, 0xf3c679d3, 0x14614593, 0xf8cd6784, 0x8c577f10, 0x7f69019d, 0x4b5a0d65, 0x275e7c8e, 0xb463585a, 0x53c4641a, 0x6c3dbdf4, 0xd4600203, 0x94f0da70, 0x333f391d, 0x18666e21, 0x3306f502, 0x58377d13, 0xcbf25e99, 0x47a52189, 0x58cf7a4d, 0x279fb7cf, 0x736e2a2f, 0xe79ef05f, 0xbf68460d, 0x27a67bd0, 0x58f6b652, 0x7f50cd82, 0x0b0b1e57, 0x0c072bb2, 0xfff89e7e, 0x2c5562d9, 0xabf104c0, 0x0b32d248, 0xc0014790, 0x4090d873, 0x9f3a0f66, 0x6bf04350, 0x0735f9fa, 0x0bcad516, 0x0c3ee7ad, 0x3f01deb0, 0x2b59573c, 0xa0021dc9, 0xb8a5b8a9, 0x1f6a5bc4, 0x6cfc76b5, 0x4b63c17a, 0x789d3326, 0x806998bd, 0x13957728, 0x5f0284e9, 0x785cf867, 0x07f432bb, 0x3ff9d9ee, 0xa7f62f72, 0x00000000, 0xeb61dcb3, 0x93fcef95, 0x60035a59, 0xcbcb9286, 0xeb5810ac, 0x2c6caec6, 0x3fc015f1, 0xc0f940ce, 0x9fc20838, 0x8caf784e, 0x34cb0ba6, 0x070c35e5, 0x67cea4fd, 0x00f8075e, 0x8b6286ea, 0xa737e433, 0xf4324b68, 0x33fef25c, 0x2b989c7d, 0x3834274a, 0x380deb55, 0x14a08ed2, 0xf40b8777, 0x8ba34dab, 0x7f9106c3, 0xb86473e8, 0x0039cc1f, 0x8c96b451, 0xf307b292, 0x875c6147, 0xacc4fd3a, 0x87a46619, 0x805054a2, 0x5305af5b, 0x8c6eb30f, 0xd39430b8, 0x149942cd, 0x74a3d48b, 0xc7f5752b +}, +{ +0x1ad581b6, 0x1ac65972, 0xc334aee3, 0x45337bac, 0xe8dd5a78, 0x5b0dac2c, 0x70cb4c21, 0xf6e38df8, 0x35ebef49, 0xd9afe7b2, 0xb3ffe2c2, 0xd980f324, 0x00000000, 0xc31bba75, 0x2bc6e00d, 0xdd6ba512, 0x6ec957f3, 0x70aa9050, 0xe8ce82bc, 0xb7756885, 0xf234179c, 0x5fc9ee8c, 0x829e87cc, 0x312fade9, 0x70f78073, 0x2f70a618, 0x82d04f2b, 0x9cee98ab, 0xadb331f7, 0x2b8828ea, 0x5b31607e, 0x5ff522de, 0x04b64615, 0x1e11c316, 0xb3c32e90, 0x1afa9520, 0xec78c4a9, 0x1aa78503, 0x82ff5bbd, 0x1ab45dc7, 0xf255cbed, 0x82b1935a, 0x456e6b8f, 0x9858debe, 0x5b7fa899, 0x41b9f1eb, 0x41e4e1c8, 0xec0ac01c, 0xf27adf7b, 0xdd19a1a7, 0xe8bc8609, 0x1e701f67, 0x6a2201c5, 0x8675d1fa, 0x1e021bd2, 0x9cfd406f, 0xc346aa56, 0xd9f2f791, 0x9805ce9d, 0xec6b1c6d, 0xb73ba062, 0xf6df41aa, 0x7433c2d3, 0xa939bbb0, 0x3161650e, 0xc7f0ec43, 0x3100b97f, 0xc3557292, 0x4552a7dd, 0xf2461329, 0x986412ec, 0x98161659, 0x74201a17, 0xc7cc2011, 0x5f87266b, 0xb38de677, 0x9cc18c3d, 0xec57d03f, 0x5fbbea39, 0xf6ad451f, 0x1e63c7a3, 0xdd44b184, 0xb3a2f2e1, 0x5b6c705d, 0xc7dff8d5, 0x82ec8379, 0x003ccc52, 0xa95867c1, 0x35b6ff6a, 0x828d5f08, 0xadee21d4, 0xd9932be0, 0x741cd645, 0x6a500570, 0x2bfa2c5f, 0x450fb7fe, 0xf691894d, 0x1e3ed780, 0x451c6f3a, 0x9ca0504c, 0x9c8f44da, 0x1e2d0f44, 0x2f5fb28e, 0xd9e12f55, 0x457db34b, 0xb7076c30, 0x41aa292f, 0xa94bbf05, 0x708584c6, 0x048a8a47, 0xec25d48a, 0xe8af5ecd, 0xa964ab93, 0xf6be9ddb, 0xf21b030a, 0x865ac56c, 0x3172bdca, 0x6e9447d0, 0xec1918d8, 0x6a0d1553, 0xe893929f, 0xd9bc3f76, 0x863b191d, 0xdd0a7963, 0xec360c4e, 0x35f8378d, 0xb3ec3a06, 0x70d894e5, 0x04d79a64, 0x5b22b8ba, 0x1a889195, 0x6ea88b82, 0xc7e33487, 0xc782e8f6, 0x41d82d9a, 0x45417f19, 0x41cbf55e, 0x746ed2f0, 0xa916af26, 0xc37a6604, 0xd9ce3bc3, 0x6e879f14, 0x5b4364cb, 0x74521ea2, 0xad9c2561, 0x04c442a0, 0x6a6cc922, 0x2ba73c7c, 0xb766b041, 0x6ef59ba1, 0x8666093e, 0xc3277627, 0x70965c02, 0x41f7390c, 0xad8ffda5, 0xa9777357, 0xf6825189, 0xc7913032, 0x04f88ef2, 0xa92a6374, 0xada0e933, 0x35c4fbdf, 0x9cb38888, 0x04995283, 0x04eb5636, 0xdd36b531, 0xf227cf58, 0x747d0a34, 0x315da95c, 0x1ae94de4, 0x41853db9, 0xf208dbce, 0xc7be24a4, 0xb714b4f4, 0x82c397ef, 0x8628c1d9, 0x4196e57d, 0xa90577e2, 0xb39e3eb3, 0xadc13542, 0xb3d0f654, 0x2f3e6eff, 0x1e5f0bf1, 0xc7adfc60, 0xe8e1962a, 0xc369bec0, 0xb3b12a25, 0x2f02a2ad, 0xdd256df5, 0x1a9b4951, 0xdd576940, 0x35a527ae, 0x311361bb, 0x4520a368, 0x005d1023, 0x9cd254f9, 0x6eda8f37, 0x5fe6fa1a, 0xdd787dd6, 0x0061dc71, 0x2f4c6a4a, 0x6ee64365, 0xd9dde307, 0x2bb4e4b8, 0x86491da8, 0x6a7f11e6, 0xe8804a5b, 0x35d7231b, 0xe8f24eee, 0x983902cf, 0x04a59ed1, 0x5fa832fd, 0x2f2db63b, 0xb72878a6, 0x2bd538c9, 0x002f1496, 0xb75a7c13, 0x9c9c9c1e, 0x358a3338, 0x0013d8c4, 0x70b94894, 0x6a43ddb4, 0x70e458b7, 0x1e4cd335, 0x5b1e74e8, 0xf26907bf, 0xadfdf910, 0xc30862b1, 0x2be9f49b, 0xec4408fb, 0xf6cc996e, 0x6ebb5346, 0x2f117a69, 0x7441c666, 0x2b9bf02e, 0x314e7198, 0x2f637edc, 0x5f94feaf, 0x5b50bc0f, 0x3599ebfc, 0x982ada0b, 0x007204b5, 0x86140d8b, 0x6a31d901, 0x313c752d, 0x82a24b9e, 0xadd2ed86, 0xb749a4d7, 0x5fda3648, 0xf6f0553c, 0x004ec8e7, 0x8607d54f, 0x9877ca28, 0x984b067a, 0x740f0e81, 0x6a1ecd97 +}, +{ +0xc7ecf8c9, 0x6db6ff05, 0x1649da0e, 0xd812ecc4, 0xd292e354, 0xee194316, 0x31f19c35, 0x8c472aa4, 0xe2c61432, 0x21e71e8f, 0x9bab9bf9, 0x6e813e96, 0xc3210abd, 0x9774ccdd, 0x0e4dfde4, 0x625e69b2, 0xb169e1b5, 0x796d8fcb, 0xae97f5b8, 0x6f2455c5, 0x4c51e18a, 0x261d2d68, 0xbdb6b691, 0x412bddfd, 0xaa5a07cc, 0x892fb383, 0xe8461ba2, 0x27b8463b, 0x5c476330, 0x99393139, 0x6a4ccce2, 0x1b33e679, 0xcd6cf759, 0x8de241f7, 0xf375fddb, 0x520a9ed4, 0x408eb6ae, 0x4babd26d, 0xda804604, 0x989c5a6a, 0xb693d252, 0xeb71da31, 0xe7ae8d15, 0x4f662019, 0xca96c4be, 0x34990512, 0xa248a29c, 0x3fbc61d1, 0x444344da, 0xf2d09688, 0x5de20863, 0xb3fb4b75, 0xfb67588b, 0xbc13ddc2, 0x5bbd50d7, 0xdcdf1eb0, 0xa68550e8, 0xf9f5f24b, 0x65a45a55, 0x32c65da6, 0x7720722f, 0xfe0fc1ac, 0x7bff250b, 0xb25e2026, 0xec8be9d6, 0x0337c193, 0x7248eb08, 0x39e33965, 0x7a5a4e58, 0x55f0ad33, 0xe53c27d5, 0xead4b162, 0x29f5bbdf, 0x70da41c8, 0x2375b44f, 0xe3637f61, 0x0b2564c3, 0x87624e67, 0x6736f095, 0x85f0e4a7, 0xe4994c86, 0x84558ff4, 0x47748549, 0x96d1a78e, 0xd1a522c7, 0xe1f1d5a1, 0xa417fa28, 0x9ec302de, 0x2e0f8838, 0x11b3e9e9, 0x3d2ecb11, 0xb0cc8ae6, 0x360bafd2, 0xd3378807, 0x07fa33e7, 0x908eff3a, 0xcb33afed, 0x2ac27a4c, 0xada0342b, 0x8f70eb37, 0x101682ba, 0xe9e370f1, 0xd65f1120, 0x93b93ea9, 0x86c72534, 0x912b9469, 0x3c8ba042, 0x09b7ce03, 0x0812a550, 0x252aecfb, 0x489c13fe, 0x4ec34b4a, 0x717f2a9b, 0xc1b3a07d, 0x813d16d3, 0x157e1b9d, 0xdfe8df23, 0x0d7a3c77, 0xefbc2845, 0x9c51a81e, 0xc649939a, 0x63fb02e1, 0x421c1c6e, 0x37aec481, 0xf7b80faf, 0xc9a1052d, 0x1a968d2a, 0x7da07dbf, 0x065f58b4, 0xb5a413c1, 0xfd38003f, 0x5455c660, 0x75b2d8ef, 0x6169a821, 0x64013106, 0x1cc9d59e, 0xd0004994, 0xe60be646, 0x9a0ef0aa, 0x3e190a82, 0x05689927, 0x46d1ee1a, 0x5a183b84, 0xe054bef2, 0xdb252d57, 0xc016cb2e, 0xbf241c51, 0xaf329eeb, 0x78c8e498, 0x7c0516ec, 0xf48fce3c, 0xbe817702, 0x248f87a8, 0x45e62f89, 0xac055f78, 0x2faae36b, 0x43b9773d, 0xa96dc65f, 0x9f66698d, 0x83afbc13, 0x66939bc6, 0x6c139456, 0x3ad4f8f6, 0x8ed58064, 0x180427ea, 0x576207f3, 0xc28461ee, 0xce5b36ca, 0x336336f5, 0x888ad8d0, 0x3054f766, 0xfc9d6b6c, 0x8a187210, 0x4df48ad9, 0x7685197c, 0x588a9144, 0x2b67111f, 0xb736b901, 0x0292aac0, 0x921c55fa, 0x22d0df1c, 0xdd7a75e3, 0x00000000, 0x3b7193a5, 0x1e5b7f5e, 0x1d6cbecd, 0x60ccc372, 0x4a0eb93e, 0x353c6e41, 0x13214329, 0x19a14cb9, 0x17ecb15d, 0x0cdf5724, 0x14db70ce, 0xf52aa56f, 0xb8de2fb6, 0x01a56b53, 0x1ffe140d, 0x73ed805b, 0x2850d08c, 0x53aff587, 0xc57e5209, 0xa7203bbb, 0xd568d0b3, 0x56c76ca0, 0x7f32d77f, 0x8bbd1943, 0xf61d64fc, 0x94430d4e, 0x820ad740, 0xf1e7571b, 0x6be9a7b1, 0x592ffa17, 0xfac233d8, 0xd9b78797, 0xa3edc9cf, 0x38465236, 0x80987d80, 0xf0423c48, 0x0a800f90, 0xabff6c9f, 0x7e97bc2c, 0xa5b2917b, 0x204275dc, 0x04cdf274, 0x9df4c34d, 0xc4db395a, 0xa0da085c, 0x2d3849ab, 0x1284287a, 0x50983414, 0xb97b44e5, 0xed2e8285, 0xde4db470, 0xccc99c0a, 0xf8509918, 0x0fe896b7, 0xa8c8ad0c, 0x7417b3bc, 0x697b0d71, 0xb4017892, 0xc8046e7e, 0x5f70a2a3, 0x5ed5c9f0, 0xbbe9ee25, 0xffaaaaff, 0x493978ad, 0xba4c8576, 0x68de6622, 0xd7fa7a73, 0xa17f630f, 0x513d5f47, 0xcffe5d99, 0x2c9d22f8, 0xd4cdbbe0, 0x95e6661d +}, +{ +0xb26f4736, 0x18891fcb, 0xcda9373e, 0xe506e678, 0x05e27bbb, 0x3f4bcc3d, 0xf0144d6d, 0x9dd45ba5, 0xe4a0162d, 0x73fb3483, 0x1642ed2e, 0x69849d26, 0x01a6f055, 0xba168853, 0x3c1b8a06, 0x559f1720, 0x8e74cd30, 0xc84b4c85, 0x28afd146, 0x0714cdd5, 0x20d61e23, 0x6f36a0a6, 0x9836201e, 0x0b29895e, 0x9e841d9e, 0x80bf3fd5, 0xbff4f3e8, 0x66e99f96, 0xd3921575, 0x6dc016c8, 0xe7f05016, 0x7a240bb3, 0xdfaf51fe, 0x31803ed8, 0x88c6f0b0, 0x641f29f8, 0x10f0d0ae, 0x479971e0, 0x1512ab15, 0x710d82ed, 0x61fd5243, 0x83ef79ee, 0xbe5203bd, 0xaf042346, 0x8d248b0b, 0x7b82fbe6, 0xb3c9b763, 0x77bfbf6d, 0xe93ba2f3, 0x0350463b, 0xb946ce68, 0x3026ce8d, 0xf86d8208, 0x532d2aa0, 0x2fbb1c93, 0xc476080e, 0x34624563, 0xe2122bad, 0xa58b5a4d, 0xa6db1c76, 0x4d1608eb, 0xd7d69e9b, 0x3694f30d, 0x2d4daafd, 0x5804a3fe, 0xb57b8ae3, 0x06b23d80, 0xdcff17c5, 0x8119cf80, 0x115620fb, 0x65b9d9ad, 0x43ddfa0e, 0x9b666625, 0xbca4b5d3, 0x0ecbf2e5, 0x96fdd2fb, 0xc2c4358e, 0x74eff956, 0x6ad4db1d, 0xb8e03e3d, 0x25346598, 0xb4dd7ab6, 0x463f81b5, 0xa9b61ec6, 0x6e9050f3, 0x975b22ae, 0x824989bb, 0x2a596728, 0xf70080b8, 0xe3b4dbf8, 0x92b95915, 0x3dbd7a53, 0xd8bb9c2b, 0xf3440b56, 0x9ac09670, 0xea6be4c8, 0xe0e49dc3, 0x91e91f2e, 0x1e3b224b, 0x7fc67008, 0x2ceb5aa8, 0xebcd149d, 0xb78d3c8d, 0xc9edbcd0, 0xadf29528, 0xc19473b5, 0xb13f010d, 0x95ad94c0, 0x5f106e2b, 0x49528305, 0xa33967cd, 0x408dbc35, 0x385f01e8, 0xb099f158, 0xf2e2fb03, 0x337688b6, 0x70ab72b8, 0x4cb0f8be, 0xcb1b0abe, 0x79744d88, 0x09df3f30, 0xf5f636d6, 0xd234e520, 0x0c3d448b, 0xd52028f5, 0xd91d6c7e, 0xbd024586, 0x9c72abf0, 0x23865818, 0x5af21590, 0xfb3dc433, 0x8c827b5e, 0xd6706ece, 0xde09a1ab, 0x725dc4d6, 0x7d30c666, 0xf6a670ed, 0x39f9f1bd, 0x4fe0be85, 0x4a02c53e, 0x9f22edcb, 0xfc2909e6, 0xee2f6f26, 0xcc0fc76b, 0x266423a3, 0x17e41d7b, 0x35c4b536, 0x904fef7b, 0x4ba4356b, 0x2170ee76, 0x04448bee, 0xa77dec23, 0xa1cfd1a3, 0x00000000, 0xc362c5db, 0xb62bccd8, 0xc680be60, 0xfedfbf88, 0xc03283e0, 0x37320358, 0x8fd23d65, 0xdd59e790, 0x84fbb43b, 0x4e464ed0, 0xef899f73, 0x1a7fa9a5, 0x62ad1478, 0x51db9cce, 0x59a253ab, 0x32d078e3, 0x7c963633, 0xf9cb725d, 0xecd9d948, 0x8b96b68b, 0x3eed3c68, 0xed7f291d, 0x0d9bb4de, 0x5439e775, 0x674f6fc3, 0xcabdfaeb, 0x249295cd, 0x29092113, 0x27c2d3f6, 0x5b54e5c5, 0x412b4c60, 0x0a8f790b, 0x78d2bddd, 0x6b722b48, 0x8a3046de, 0x1ccd9425, 0xc7264e35, 0x2e1decc6, 0xa06921f6, 0xa42daa18, 0x3aa9b786, 0x6c66e69d, 0xc5d0f85b, 0x0879cf65, 0x605ba216, 0x1d6b6470, 0xf1b2bd38, 0xff794fdd, 0x68226d73, 0xda4d2a45, 0xe656a043, 0xd486d8a0, 0xaae658fd, 0x13a09695, 0x76194f38, 0x427b0a5b, 0x87abf200, 0xab40a8a8, 0xa29f9798, 0xbbb07806, 0xe1426d96, 0xfd8ff9b3, 0x528bdaf5, 0xe89d52a6, 0x75490903, 0x0f6d02b0, 0xcef97105, 0x931fa940, 0x1bd959f0, 0x630be42d, 0xf450c683, 0xd164a31b, 0xdbebda10, 0x120666c0, 0x1f9dd21e, 0x56cf511b, 0x896000e5, 0x5c402810, 0x940b6495, 0x14b45b40, 0xfa9b3466, 0x5de6d845, 0xac54657d, 0x5769a14e, 0x855d446e, 0xcf5f8150, 0x48f47350, 0xa810ee93, 0x860d0255, 0x9990d04b, 0x2220a84d, 0x192fef9e, 0xaea2d313, 0x02f6b66e, 0x456fc78e, 0xd0c2534e, 0x3b0f47d3, 0x7e60805d, 0x5eb69e7e, 0x44c937db, 0x507d6c9b, 0x2bff977d +}, +{ +0xa322db3d, 0x9c2414ce, 0xde857125, 0x4251cc21, 0x78db1a14, 0x276893ad, 0x7b299653, 0xfc915284, 0xde75d8ef, 0x593db5f2, 0xf9ede288, 0x51405984, 0xf7ee9b7f, 0xeafc772d, 0xc5e908f6, 0xbd3212e2, 0x4adc899d, 0x782bb3de, 0x1b9cd019, 0x2a99661d, 0xb84ea2ee, 0x7628ca29, 0x3105b604, 0x44dff06a, 0x087dec76, 0x166d25a9, 0x31f51fce, 0xef706eeb, 0x9459f8b8, 0x63b763c7, 0xaed32e8d, 0x159fa9ee, 0xe183bed6, 0x0302258d, 0xd08608d2, 0x3cf443b4, 0xe70d829d, 0x6eb63fbd, 0xe90efb6a, 0xab5f374b, 0x5a3f907f, 0x4fa03991, 0xcb1ad8cb, 0xa55c4ebc, 0xec82e2ac, 0x169d8c63, 0x8ab998ad, 0xd6f89d53, 0x3a7a7fff, 0x52b2d5c3, 0x6e469677, 0x34790608, 0xd076a118, 0x2c175a56, 0x1ee06015, 0xb5bf575e, 0x844a4890, 0xc36734bd, 0x894b14ea, 0x42a165eb, 0xa020feb0, 0xdd8754a8, 0xcbea7101, 0x52427c09, 0x9a5a814f, 0xd8fbe4a4, 0xb3c1c2df, 0x9fd69889, 0x97ab74ff, 0xd3748495, 0x03f28c47, 0x8fc528a1, 0x5c4105fe, 0x65c9f646, 0xad21a2ca, 0x6d44b3fa, 0x66cbd3cb, 0x6b3a267b, 0x3988f3b8, 0x8cc70d2c, 0x9cd4bd04, 0x3a8ad635, 0x246ab620, 0x7ea58f95, 0x57ce65cf, 0x4c52b5d6, 0x99a80d08, 0xfa1f6ecf, 0xc8e8548c, 0x9aaa2885, 0xa3d272f7, 0x975bdd35, 0x8c37a4e6, 0x156f0024, 0xc61b84b1, 0x54cc4042, 0x7da7aa18, 0x22e48a6b, 0x10e319e2, 0x573ecc05, 0x067e9581, 0x51b0f04e, 0x84bae15a, 0x89bbbd20, 0x4ca21c1c, 0x9f263143, 0x5fb389b9, 0x87486d1d, 0x3489afc2, 0xdd77fd62, 0x81c65156, 0x2f157fdb, 0xbb4c8763, 0x2fe5d611, 0xdb0968e3, 0xf26282b9, 0xc519a13c, 0x73a4d3ef, 0x0ef3d03d, 0x2a69cfd7, 0x492e05da, 0xf4ecbef2, 0x3ff66639, 0xb3316b15, 0xae238747, 0x442f59a0, 0xbec09ea5, 0x8234dd11, 0x683803f6, 0x92d7c4f3, 0x0b7fc9fb, 0xea0cdee7, 0x4a2c2057, 0xfaefc705, 0x5cb1ac34, 0x49deac10, 0x41a34066, 0xff63dec3, 0x8136f89c, 0xa65e6b31, 0x13e13c6f, 0x60b5464a, 0x70565fa8, 0x70a6f662, 0x6bca8fb1, 0x0d015c7a, 0x189ef594, 0x1b6c79d3, 0xcd94e480, 0xadd10b00, 0x21e6afe6, 0x7d5703d2, 0x3c04ea7e, 0x75da466e, 0xb6bd72d3, 0xf91d4b42, 0xc095b8fa, 0xb0c3e752, 0x5f432073, 0xe173171c, 0xc0651130, 0x73547a25, 0x068e3c4b, 0x91d5e17e, 0x912548b4, 0x296bea5a, 0x94a95172, 0x299b4390, 0xb64ddb19, 0x65395f8c, 0x92276d39, 0x4f50905b, 0x00000000, 0x2ce7f39c, 0xbdc2bb28, 0x378b8a4f, 0xb54ffe94, 0x1d12ec52, 0x221423a1, 0x6347ca0d, 0xc818fd46, 0x7bd93f99, 0xd50a1114, 0xe4ff0eda, 0x0df1f5b0, 0xd5fab8de, 0x76d863e3, 0xce6668c7, 0x1013b028, 0x1e10c9df, 0xb0334e98, 0xe2819b5b, 0x131195a5, 0xb8be0b24, 0xbbbc2ea9, 0x6db41a30, 0x47ddd5e7, 0x0b8f6031, 0xff937709, 0xc6eb2d7b, 0x32079389, 0x59cd1c38, 0xd3842d5f, 0xdbf9c129, 0x377b2385, 0xf160a734, 0x5acf39b5, 0xabaf9e81, 0xf1900efe, 0x39785a72, 0xe2713291, 0x87b8c4d7, 0xf41c1738, 0xa5ace776, 0xc3979d77, 0xe7fd2b57, 0x32f73a43, 0xd6083499, 0x0e0379f7, 0xbe30376f, 0xe9fe52a0, 0x057cb00c, 0x2116062c, 0x27983a67, 0x472d7c2d, 0x543ce988, 0xce96c10d, 0x8f35816b, 0x186e5c5e, 0xf2922b73, 0x3f06cff3, 0x058c19c6, 0xec724b66, 0xcd644d4a, 0xd80b4d6e, 0xa8adbb0c, 0xe40fa710, 0x6045ef80, 0x4153e9ac, 0x8a493167, 0xa85d12c6, 0x1de24598, 0x82c474db, 0xa0d0577a, 0x7e55265f, 0xef80c721, 0x9958a4c2, 0x68c8aa3c, 0xa6aec2fb, 0x663b7a01, 0x00f0a9ca, 0xfc61fb4e, 0x752aefa4, 0xf71e32b5, 0x249a1fea, 0x088d45bc +}, +{ +0x49f3206f, 0x86d9fbdd, 0x3ad0c078, 0x98e68acb, 0xeaf48deb, 0xcf2adbb2, 0x25954486, 0xe8e17c23, 0xf514fc70, 0x5592b26e, 0xf630ea8f, 0xeabf9f34, 0x70e91152, 0x713611df, 0x26fa40a6, 0x03caf145, 0x4be6d1a7, 0xa27d586c, 0x4a39d12a, 0x482c20e2, 0xa1594e93, 0xf55feeaf, 0xa1125c4c, 0x848718ca, 0x54a35559, 0xbc42297a, 0xbd73ce4d, 0xcd3f2a7a, 0x032416ff, 0x25de5659, 0x2780b54e, 0xa2364ab3, 0x2614a71c, 0x01df008d, 0xbd9d29f7, 0xa1fcbbf6, 0x84cc0a15, 0x99d76dfc, 0x1e7463c9, 0xbce7dc1f, 0x98437fae, 0xeb8e7803, 0xa3e94a3e, 0x557c55d4, 0x00000000, 0x036f0420, 0x87a30e35, 0x4b4324c2, 0xbf663f85, 0xd081b8f6, 0xa307ad84, 0x7323e017, 0x3be1274f, 0x391a313d, 0xeb609fb9, 0x388e236f, 0x874de98f, 0xce502e5a, 0x9b676951, 0xa34cbf5b, 0x72fce09a, 0xf7a4f8dd, 0x00eee7ba, 0xa023bb7b, 0x55d9a0b1, 0x382bd60a, 0x1f0e9621, 0xd34b49b3, 0x6db96464, 0x1fe0719b, 0x70a2038d, 0x9b898eeb, 0xd1fb4d1e, 0x9a1d9cb9, 0x56fdb64e, 0x4b08361d, 0x6e739521, 0xd0caaa29, 0xbd38dc92, 0x6df276bb, 0xf5fa1bca, 0xeb2b8d66, 0x85130a98, 0x4badc378, 0x6f427216, 0xe8aa6efc, 0x240156d4, 0x1fab6344, 0xf4cbfcfd, 0xcc45df92, 0x85581847, 0x85b6fffd, 0x9af37b03, 0xbf88d83f, 0x8422edaf, 0x39bfc458, 0x4889d587, 0x1d507536, 0x867c0eb8, 0x7368f2c8, 0x6f0960c9, 0xd2df5be1, 0x73861572, 0x9ab869dc, 0x004b12df, 0x8469ff70, 0x491dc7d5, 0x4ad73690, 0x1dbe928c, 0x5406a03c, 0xd0244d93, 0xcce02af7, 0x6fe78773, 0xf5b10915, 0xf4251b47, 0x5722b6c3, 0xa3a258e1, 0x025ee317, 0x99398a46, 0x6cc3918c, 0xcf8f2ed7, 0xccab3828, 0x2530b1e3, 0x72b7f245, 0x99729899, 0x4867323d, 0x1e9a8473, 0x38c531b0, 0x5537470b, 0x26b15279, 0xf480ee22, 0xf7010db8, 0x1e3f7116, 0x1c8f75bb, 0x1c2a80de, 0x578743a6, 0xd1b05fc1, 0xbf2d2d5a, 0xe80f9b99, 0xa2d8ad09, 0x6d5783de, 0xbdd63b28, 0xbcaccec0, 0xa293bfd6, 0xcfc43c08, 0x3b0fc0f5, 0x6d1c9101, 0x9bc29c34, 0x1d1b67e9, 0xbe57d8b2, 0xf6de0d35, 0x4a9c244f, 0x1df58053, 0xea51788e, 0xd3eebcd6, 0x276e52f4, 0x3b44d22a, 0x561351f4, 0xd27aae84, 0xe8448946, 0x8706fb50, 0x2725402b, 0x71d8f665, 0x7193e4ba, 0x3a9bd2a7, 0xf46e0998, 0xbfc3cae0, 0x48c2c758, 0x98086d71, 0x704ce437, 0x1cc46764, 0xcd9adf1f, 0x257ba33c, 0xcf61c96d, 0xe9d09b14, 0xe9756e71, 0xcc0ecd4d, 0xa0cd5cc1, 0xd15eb87b, 0x4956d50a, 0x54e84786, 0x265fb5c3, 0xd294493e, 0x9a568e66, 0x49b832b0, 0x0131e737, 0xebc56adc, 0xd231bc5b, 0x72120720, 0xd3a5ae09, 0x39f4d687, 0x85fded22, 0xbe1cca6d, 0x6c2d7636, 0x02fb1672, 0x24a4a3b1, 0x395123e2, 0x73cd07ad, 0x0215f1c8, 0x5658432b, 0x00a5f565, 0xcebec9e0, 0xd06f5f4c, 0xf67bf850, 0xe99b89cb, 0x6ed66044, 0xce1b3c85, 0x717d0300, 0x0381e39a, 0xe93e7cae, 0x3baa3590, 0x8692e902, 0x1f4584fe, 0x725915ff, 0xbc093ba5, 0xea1a6a51, 0x1ed196ac, 0x9b2c7b8e, 0x7007f6e8, 0x1c619201, 0x544db2e3, 0xcd7438a5, 0xbeb93f08, 0x3860c4d5, 0xa1b7a929, 0x86371c67, 0x57cc5179, 0x3a75351d, 0x98ad9814, 0x87e81cea, 0x6c888353, 0xcef5db3f, 0x5769a41c, 0x01941252, 0x02b004ad, 0x6e9d729b, 0x6c6664e9, 0xf6951fea, 0xd3005b6c, 0x017af5e8, 0x3a3e27c2, 0x244a440b, 0x6e3887fe, 0xf7efea02, 0x999c7f23, 0x24efb16e, 0xa068a9a4, 0xbef22dd7, 0xcdd1cdc0, 0x4a72c3f5, 0x56b6a491, 0x27cba791, 0xf74a1f67, 0x6fac95ac, 0xa0864e1e, 0xd115aaa4 +}, +{ +0x7d9f6a7a, 0xca41fc3d, 0xdb88a349, 0x1698aff7, 0x0ca642fe, 0x997c1c50, 0xdaa58f26, 0xc56a37d1, 0xc7ca92ac, 0xedb4612a, 0xe11223d4, 0x7745f468, 0xf0db7ca0, 0x05f155fe, 0x8fe4b3a7, 0x6ef69073, 0xf52a295e, 0x5d3b07ee, 0x9657d7bc, 0x5c162b81, 0x519d4510, 0x1d6f1d8a, 0xf1f650cf, 0x363cc263, 0x448863f5, 0xa93c02df, 0xbe898147, 0xd2dfb449, 0xa3e69ccd, 0x1369fa09, 0x8ec99fc8, 0xde79f6b7, 0x841301da, 0x189e4874, 0x27f59d17, 0x00000000, 0xfb2ccedd, 0x383a25e0, 0xe03f0fbb, 0xaab18bcd, 0xab9ca7a2, 0x04dc7991, 0x1c4231e5, 0x3f6bd563, 0x88b54324, 0x3ce65c71, 0xcd100cbe, 0xebc8bdc6, 0x45a54f9a, 0x218941fb, 0x2f8fa678, 0xa617c933, 0x6250d28d, 0xf6a7a04c, 0x7668d807, 0x3917098f, 0xce9d85ac, 0xc1b64e40, 0x786e3f84, 0xe96818bb, 0x6b07c58d, 0x19b3641b, 0x28de56fb, 0xade07b4e, 0x35b14b71, 0x668cab1c, 0x533de06d, 0x33cd979d, 0xfff0b74c, 0xfd501231, 0x61dd5b9f, 0xbfa4ad28, 0xd72ee1b7, 0x6d7b1961, 0xb22fc3b9, 0x4e52fde7, 0x55413c81, 0x93a68242, 0x94f772c1, 0xa14639b0, 0x2204c8e9, 0x1ee29498, 0x8c693ab5, 0x40541a64, 0xa8112eb0, 0x89986f4b, 0xc6e7bec3, 0x087a3b6f, 0xc9cc752f, 0x5b47db02, 0xbc29243a, 0xdf54dad8, 0xa59a4021, 0xf27bd9dd, 0xba55f8d6, 0xe4e3762a, 0x9c8d49ae, 0x72b4a196, 0x6c56350e, 0x794313eb, 0x32e0bbf2, 0x4f7fd188, 0x6501220e, 0x7be3b696, 0x3bb7acf2, 0x316d32e0, 0xe3b286a9, 0xa4b76c4e, 0x10e4731b, 0xd58e44ca, 0x58ca5210, 0xf98c6ba0, 0xb57e333a, 0x2555386a, 0xd8052a5b, 0x4628c688, 0xddf47fa5, 0xb7de9647, 0xe76eff38, 0xbb78d4b9, 0xd9280634, 0x3dcb701e, 0xcb6cd052, 0x43d99376, 0x30401e8f, 0x29f37a94, 0x9f00c0bc, 0x853e2db5, 0xaf40de33, 0xd07f1134, 0x4705eae7, 0x6fdbbc1c, 0xd4a368a5, 0xe643d357, 0xd603cdd8, 0xc4471bbe, 0x6a2ae9e2, 0xcfb0a9c3, 0x95da5eae, 0x7f3fcf07, 0x75e55115, 0x73998df9, 0xb1a24aab, 0x80cf784b, 0x9da065c1, 0xb9d871c4, 0xdcd953ca, 0xb302efd6, 0x7cb24615, 0x0f2bcbec, 0x2d2f0305, 0x02a0a57d, 0x49030d64, 0xb8f55dab, 0x4179360b, 0x2329e486, 0xaccd5721, 0x14380a8a, 0xc8e15940, 0xc09b622f, 0x71392884, 0x2b53dfe9, 0x9af19542, 0xcc3d20d1, 0x0bf7b27d, 0xee39e838, 0x4cf2589a, 0xd1523d5b, 0x826fdd36, 0xf78a8c23, 0x5210cc02, 0x7e12e368, 0x81e25424, 0xfa01e2b2, 0x0751f083, 0x42f4bf19, 0xd3f29826, 0x59e77e7f, 0x74c87d7a, 0x879e88c8, 0xc23bc752, 0x9bdcb92d, 0xec994d45, 0x151526e5, 0x1a3eed09, 0x9851303f, 0x902b0b50, 0x4ddf74f5, 0x349c671e, 0xe5ce5a45, 0x642c0e61, 0xbd040855, 0xa06b15df, 0x0d8b6e91, 0x69a760f0, 0x50b0697f, 0xe29faac6, 0x09571700, 0x57e199fc, 0x5a6af76d, 0xa73ae55c, 0xb08f66c4, 0x4a8e8476, 0x038d8912, 0x012d2c6f, 0x9106273f, 0xf8a147cf, 0x3a9a809d, 0xef14c457, 0x60f077f0, 0x2a7ef386, 0x17b58398, 0xb4531f55, 0x3711ee0c, 0x8d4416da, 0x5eb68efc, 0x56ccb593, 0x8a15e659, 0xfc7d3e5e, 0xe84534d4, 0xf4070531, 0x928bae2d, 0x0ada9e12, 0x067cdcec, 0x977afbd3, 0x2ea28a17, 0xc316eb3d, 0x8342f159, 0x1244d666, 0xeae591a9, 0xb6f3ba28, 0x4ba3a819, 0x2c022f6a, 0xa2cbb0a2, 0x637dfee2, 0x8b38ca36, 0x5f9ba293, 0x11c95f74, 0xae6df25c, 0xf356f5b2, 0x9e2decd3, 0x1fcfb8f7, 0xfedd9b23, 0x0e06e783, 0x26d8b178, 0x86b3a4a7, 0x688a4c9f, 0x701404eb, 0x1b13c166, 0x3e46f90c, 0x7ace9af9, 0x67a18773, 0x546c10ee, 0x482e210b, 0x20a46d94, 0x24781405 +}, +{ +0x03856dab, 0xfb2878fd, 0x088c44ac, 0xc00ab674, 0x802ede35, 0xf5bfb7d0, 0x18888256, 0xcb039f73, 0xb8897d17, 0x7883cb63, 0x91cd4304, 0xb47c845a, 0xecd06e4d, 0xfd33f37c, 0x0d12a286, 0x98a65c63, 0x45ba8e6b, 0x9ac46a03, 0xe45c2ae1, 0x463fe3c0, 0x7ae1fd03, 0xe0259700, 0xad135dc7, 0x0cf5f94d, 0xa96ae026, 0xb96e26dc, 0x4d36cac7, 0xf94a4e9d, 0x02623660, 0xf7dd81b0, 0x92482eaf, 0xe1c2cccb, 0x2ac153b8, 0xaaef8d8d, 0x524298db, 0xe3a0faab, 0xe8a9d3ac, 0xbcf0c0f6, 0x563b253a, 0x2634aaf5, 0x147d7b1b, 0xe7d9474a, 0xff51c51c, 0x3940f8e9, 0x638e249e, 0x5cd557f6, 0xf243679a, 0x5b2987bc, 0x34525a6f, 0x1e9309d7, 0xbf75ad5d, 0xd1e92b45, 0x6472f4d4, 0x3f5b7368, 0xd7f2a0c4, 0x2d3d83f2, 0xbaeb4b77, 0x31ccbc45, 0xa38492ea, 0x9d38ba49, 0xed373586, 0xdcfb89c3, 0xbd179b3d, 0xc38fdbdf, 0x196fd99d, 0x3b22ce89, 0x87d20e7f, 0xc2688014, 0x23aa4cdf, 0x9cdfe182, 0x5d320c3d, 0xb00539bb, 0x4f54fca7, 0x161f4d7b, 0xc1ededbf, 0xb3805410, 0x69605652, 0x824ce855, 0xe5bb712a, 0xf3a43c51, 0xc6113df5, 0x8b27f732, 0xc961a913, 0x29443e13, 0x68870d99, 0x5eb76196, 0x40246841, 0x759169e5, 0x7f7f1b29, 0x43a105ea, 0xc4730b95, 0x224d1714, 0xaf716ba7, 0xa61a74c0, 0xdd1cd208, 0x67f7997f, 0xb1e26270, 0xae96306c, 0x81c985fe, 0xa88dbbed, 0x445dd5a0, 0x57dc7ef1, 0x9b2331c8, 0x3ebc28a3, 0xe94e8867, 0x5020aebb, 0xce9d7959, 0x096b1f67, 0x95b4fee5, 0xc886f2d8, 0x4eb3a76c, 0xa47842a0, 0x17f816b0, 0x24569c95, 0x77f35f85, 0x159a20d0, 0x27d3f13e, 0x6610c2b4, 0x845763d4, 0x1004c6fa, 0x6b026032, 0x83abb39e, 0x28a365d8, 0xd477cd6f, 0xf1c60a31, 0xbe92f696, 0xe247a160, 0x37d737c4, 0x5acedc77, 0x9ebdd7e2, 0xab08d646, 0x61ec12fe, 0xfcd4a8b7, 0xb7f9e9f1, 0x3cde1ec3, 0x97d6c885, 0x21c87abf, 0x4cd1910c, 0x1b0deffd, 0x01e75bcb, 0x35b501a4, 0x3d394508, 0x38a7a322, 0xbb0c10bc, 0x53a5c310, 0xcd1814f2, 0xef5503e6, 0x994107a8, 0x8d3c7cb3, 0xb61eb23a, 0x1f74521c, 0xacf4060c, 0x4b2d4146, 0xa59f196b, 0xcae4c4b8, 0x863555b4, 0x902a18cf, 0x62697f55, 0xdf7ee468, 0x85b0381f, 0x2cdad839, 0x9453a52e, 0x41c3338a, 0x07fcd04a, 0x6ae53bf9, 0xc594505e, 0x1aeab436, 0xeb2cbe07, 0x5f503a5d, 0xd59096a4, 0xd26c46ee, 0x00000000, 0x9f5a8c29, 0x51c7f570, 0x88a29a99, 0x0f7094e6, 0xd8823422, 0x2f5fb592, 0x9631934e, 0x0aee72cc, 0x202f2174, 0xf63ada7b, 0x25b1c75e, 0x594bb1dc, 0x700f8fcf, 0xa7fd2f0b, 0x738ae264, 0x3ac59542, 0xa263c921, 0x8945c152, 0x42465e21, 0x726db9af, 0x2eb8ee59, 0x55be4891, 0xdae00242, 0x1381ab51, 0x0479bde1, 0x7d1d2d49, 0x2b260873, 0x6cfeb078, 0x47d8b80b, 0x36306c0f, 0x71e8d404, 0x3249d1ee, 0x0b092907, 0xeacbe5cc, 0x600b4935, 0xccff4f39, 0x8eb91118, 0xd00e708e, 0x0e97cf2d, 0x8f5e4ad3, 0xf8ad1556, 0x1d16647c, 0x7b06a6c8, 0x1cf13fb7, 0x6595af1f, 0xa001ff41, 0xfeb69ed7, 0xc7f6663e, 0xeeb2582d, 0x494f7726, 0x796490a8, 0xa1e6a48a, 0x93af7564, 0xd38b1d25, 0x4aca1a8d, 0xdb075989, 0x7476322e, 0xcf7a2292, 0x1266f09a, 0x7e9840e2, 0x8ac0acf9, 0xd615fb0f, 0x7614044e, 0xb59bdf91, 0x11e39d31, 0x302be78e, 0xf458ec1b, 0x5459135a, 0xfacf2336, 0xe63e1c81, 0x6f7bddd3, 0x059ee62a, 0xf02151fa, 0x061b8b81, 0x48a82ced, 0x7cfa7682, 0x8cdb2778, 0x33ae8a25, 0xd9656fe9, 0xb2670fdb, 0x6e9c8618, 0x6d19ebb3, 0xde99bfa3, 0x58acea17 +}, +{ +0x23e88233, 0xa905fd38, 0xf0f01b9d, 0xceed99a1, 0x3fc16545, 0x2c8feb89, 0xae95539c, 0x209c8a80, 0xe2627228, 0xd488370a, 0x29b7aae7, 0x56928f1f, 0x36ea4522, 0x719eab3b, 0xcc45766b, 0xc61a5ebf, 0x359e4d91, 0xf9db3bfa, 0x8b319872, 0xefadf458, 0x4774ee19, 0x67e86499, 0x7f2525f8, 0x7bc183ef, 0xfe4b955e, 0x6953ea5a, 0xc7c6b9c6, 0x7a1d6496, 0x286b4d9e, 0x99a3f1c7, 0xded71fde, 0x18cd4161, 0x2ac3a254, 0x61a42d44, 0xea95b536, 0x6c6bab34, 0xe686d43f, 0x00000000, 0x21406df9, 0xb93f7b47, 0x134e8ecc, 0xe9e1bd85, 0xd1b07664, 0x26d0c35d, 0xf384132e, 0x5fb9af78, 0x7d8dca32, 0x4abb6869, 0x6db74c4d, 0x70424c42, 0x24782c97, 0x064c49dd, 0x5ccda7cb, 0x915436d9, 0xc2fef8a8, 0xc97d3705, 0x6f1fa387, 0x52762908, 0x821ab815, 0xa5169c31, 0xf807dc83, 0x8ca136d6, 0x6a27e2e9, 0xe3be9551, 0x5d1140b2, 0x3442aae8, 0xa02edd5f, 0xc56e560c, 0xee711321, 0xaf49b4e5, 0x80b257df, 0x6ec344fe, 0x2234654a, 0xa2863295, 0xc18af01b, 0x11e66106, 0xd89b5603, 0x01dce779, 0xcf317ed8, 0xade15b2f, 0xd06c911d, 0xba4b73f4, 0x04e4a617, 0xcd999112, 0x9b0b1e0d, 0x946c77b7, 0xb0145b20, 0x96c4987d, 0x62d025f7, 0x6078ca3d, 0xe83d5afc, 0x4cf721b4, 0x4d2bc6cd, 0x757a0d2c, 0x59f5e6a5, 0x543a60d5, 0x17aa28db, 0x816eb0a6, 0xb3605393, 0x1df5000f, 0xb1c8bc59, 0xe42e3bf5, 0x987f16be, 0x270c2424, 0x2d530cf0, 0x8fd53e65, 0x037408b3, 0xaa71f58b, 0x53aace71, 0xf414bd8a, 0x1502c711, 0xca093fb6, 0x1911a618, 0x7ef9c281, 0x103a867f, 0x8e09d91c, 0x46a80960, 0xbb97948d, 0xeb49524f, 0x83c65f6c, 0xe1167a9b, 0x3d698a8f, 0xd620d8c0, 0x733644f1, 0x3cb56df6, 0xed051b92, 0x5a81ee16, 0x3af9242b, 0xd31899ae, 0xb52c1a4e, 0xb65812fd, 0x0538416e, 0xa7be73fb, 0xc8a1d07c, 0x3736a25b, 0xfce37a94, 0xa1f23a26, 0x6bfb0590, 0x14de2068, 0x3b25c352, 0x3e1d823c, 0xcbd5d8cf, 0x9e335f63, 0x760e059f, 0x398d2c98, 0x65408b53, 0xb2bcb4ea, 0x899977b8, 0x0c136109, 0xc4b2b175, 0x8456f1c8, 0x1bb949d2, 0x45dc01d3, 0xff977227, 0x4e5fce7e, 0x49cf60da, 0x884590c1, 0xac3dbc56, 0x320ee335, 0x0790aea4, 0x649c6c2a, 0xe0ca9de2, 0xc3221fd1, 0xbf73329a, 0xb784f584, 0x0f6769ba, 0x5e654801, 0x1676cfa2, 0x33d2044c, 0xf12cfce4, 0x77d2e2e6, 0xf6bc5240, 0xf258f457, 0xd7fc3fb9, 0x0ebb8ec3, 0x1a65aeab, 0xda33b9c9, 0x55e687ac, 0x9ad7f974, 0xabad12f2, 0x08f7c71e, 0x582901dc, 0x858a16b1, 0x317aeb86, 0x0b83cfad, 0x510221bb, 0x9c9bb0a9, 0x7c512d4b, 0x688f0d23, 0x78b58b5c, 0xdc7ff014, 0xd2c47ed7, 0xa4ca7b48, 0x481387a3, 0x4f832907, 0xa6629482, 0xe75a3346, 0x97187f04, 0xbeafd5e3, 0xecd9fceb, 0x93fcd913, 0x092b2067, 0x1c29e776, 0x74a6ea55, 0x4b678f10, 0x79696c25, 0x8d7dd1af, 0xbddbdd50, 0x8722f97b, 0x02a8efca, 0xf760b539, 0xe5f2dc8c, 0x0a5f28d4, 0x30a60cff, 0xa35ad5ec, 0x4138a7c4, 0xdf0bf8a7, 0x2ffbe33a, 0x630cc28e, 0x0dcf8670, 0xd947b17a, 0x9088d1a0, 0xb8e39c3e, 0xb4f0fd37, 0x92203e6a, 0x574e6866, 0x663483e0, 0xf5c85af3, 0x86fe1e02, 0x129269b5, 0x5b5d096f, 0x40e440bd, 0x2b1f452d, 0x50dec6c2, 0x1e8108bc, 0x1f5defc5, 0x3851cbe1, 0xa8d91a41, 0x25a4cbee, 0xdbef5eb0, 0xfb73d430, 0x424caf77, 0xfaaf3349, 0x4400e6aa, 0xbc073a29, 0x95b090ce, 0xfd3f9ded, 0x8aed7f0b, 0xd554d073, 0x9fefb81a, 0xdda3176d, 0x2e270443, 0x9d4757d0, 0x72eaa388, 0xc0561762, 0x4390480e +}, +{ +0x635822bb, 0xa48f9392, 0xe306afb4, 0x00000000, 0x5b5d18f8, 0x56e6d980, 0x3d8bf210, 0x3ac775ee, 0xfb874004, 0xd3369cdc, 0x77b90f4e, 0x47893c26, 0xcbb7736c, 0x85d0455c, 0xa64ddc3f, 0x840b4661, 0x6dfaaf53, 0x33297ff8, 0x98df62bf, 0x92282439, 0x8efc00e7, 0x32f27cc5, 0x829cc2a2, 0x97a6ec6a, 0x6414a545, 0x0ea28de8, 0x296adfe5, 0x87120af1, 0x3465f806, 0x65cfa678, 0x89b08719, 0x2ba89048, 0x3b1c76d3, 0xb7223999, 0xa93452ea, 0x0f798ed5, 0xa8ef51d7, 0xd5a1181f, 0x68746700, 0xdd941134, 0xde8d5da4, 0x5424962d, 0xfccbc7fa, 0x43dcf748, 0xe2ddac89, 0x1276a936, 0xdad896ca, 0x26135130, 0xf0ab05bf, 0xc9753cc1, 0xbf1730b2, 0x0835092b, 0x619a6d16, 0xb6f93aa4, 0x239d9963, 0xfd10c4c7, 0xacba9ab9, 0xf89e0c94, 0x36a7b7ab, 0x13adaa0b, 0x805e8d0f, 0x1d0f27e3, 0x1b98a320, 0xbb42fbdc, 0xc7d7b129, 0x51aa5e7e, 0x250a1da0, 0xe82aea0f, 0x2e26581b, 0x153a2ec8, 0x9f93e541, 0xeb33a69f, 0x94bfa0fa, 0xec7f2161, 0xffd28b6a, 0x913168a9, 0xdf565e99, 0x02c24fad, 0xdb0395f7, 0x58445468, 0x8f2703da, 0xe01fe324, 0x6b6d2b90, 0xafa3d629, 0x791b82a6, 0x8c3e4f4a, 0x2ce417b6, 0x24d11e9d, 0xaa2d1e7a, 0x449070b6, 0x76620c73, 0xbdd57f1f, 0x2d3f148b, 0x48f0b2f3, 0x058ec853, 0xa2181751, 0x3f49bdbd, 0x5dca9c3b, 0x62832186, 0xef666df1, 0x886b8424, 0x8b72c8b4, 0x4ca5799d, 0xf7e78241, 0x01db033d, 0xe44a284a, 0x9e48e67c, 0xd47a1b22, 0xb2acf1ca, 0xad619984, 0xbc0e7c22, 0x8347c19f, 0xf1700682, 0x74a043de, 0x1881efb0, 0x7f8c0665, 0x39de397e, 0x0af74686, 0x1fcd684e, 0x7bd9cd0b, 0x757b40e3, 0x195aec8d, 0x35befb3b, 0x7a02ce36, 0x50715d43, 0xe1c4e019, 0xe5912b77, 0xeebd6ecc, 0x93f32704, 0x4be9fe63, 0x17f86165, 0x670de9d5, 0xb980b471, 0x967def57, 0xd76357b2, 0xd1f4d371, 0xb377f2f7, 0xf3b2492f, 0xa3c3146c, 0xf9450fa9, 0x712e8b8d, 0x9a1d2d12, 0x116fe5a6, 0x7c954af5, 0xd2ed9fe1, 0x1a43a01d, 0x81858e32, 0xa1015bc1, 0xccfbf492, 0xd6b8548f, 0x9564a3c7, 0xcd20f7af, 0xa796df02, 0x14e12df5, 0x6f38e0fe, 0x16236258, 0xfe098857, 0x2ffd5b26, 0x5ed3d0ab, 0xf4feced1, 0x28b1dcd8, 0x10b4e69b, 0x6ee3e3c3, 0xe75364da, 0xc3827a47, 0xeda4225c, 0xc09b36d7, 0x1cd424de, 0xf525cdec, 0xa55490af, 0x7d4e49c8, 0x38053a43, 0x40c5bbd8, 0x90ea6b94, 0x5c119f06, 0xb06ebe67, 0x069784c3, 0x27c8520d, 0xb85bb74c, 0x5f08d396, 0xfa5c4339, 0x6ab628ad, 0x9bc62e2f, 0x03194c90, 0xc515fe84, 0xe68867e7, 0xbecc338f, 0x30303368, 0xeae8a5a2, 0x0c60c245, 0xb43b7509, 0xcfe2b802, 0x7e570558, 0x599f5755, 0x0dbbc178, 0x7237c71d, 0xdc4f1209, 0x454b738b, 0x4d7e7aa0, 0xc60cb214, 0x5a861bc5, 0x411eb8e5, 0x4fbc350d, 0x09ee0a16, 0xca6c7051, 0x1e166b73, 0xe9f1e932, 0x2084d5f3, 0xc4cefdb9, 0xb5e07634, 0x492bb1ce, 0xabf61d47, 0x22469a5e, 0x60416e2b, 0xf63c817c, 0x52b312ee, 0x66d6eae8, 0x86c909cc, 0x2a739375, 0x9c8aa9d1, 0x73ecc420, 0x0455cb6e, 0xf2694a12, 0x215fd6ce, 0x4207f475, 0x69af643d, 0x377cb496, 0xa0da58fc, 0x3e92be80, 0xba99f8e1, 0xb1b5bd5a, 0xd81ad967, 0x536811d3, 0x9d51aaec, 0x074c87fe, 0xc259797a, 0xc14035ea, 0xae78d514, 0x99046182, 0x55ff9510, 0x573ddabd, 0x8de54c77, 0x8aa9cb89, 0xce39bb3f, 0x4e673630, 0x3c50f12d, 0xd9c1da5a, 0x0b2c45bb, 0x70f588b0, 0xc8ae3ffc, 0x4a32fd5e, 0x46523f1b, 0x31eb3055, 0x6c21ac6e, 0x78c0819b, 0xd02fd04c +}, +{ +0x00000000, 0xf7141c56, 0xefeeb46d, 0xf1c110e7, 0xbc9e3d08, 0x14d61233, 0xe7522e1b, 0x75c47fdc, 0x18faa83b, 0x9ebaebcf, 0x71545fa2, 0x1041e6ed, 0x8cbe21ed, 0xd775e65e, 0x960671b9, 0x9601a519, 0xdb5e88f6, 0xe180f60a, 0xa4634193, 0x41744347, 0x4b8df5fe, 0x3e4e5e82, 0xbedb11c7, 0xb6605f11, 0xae9d238a, 0x7bade91b, 0xb0b553a0, 0x59893fdc, 0x4336bb28, 0x1e28702a, 0x43316f88, 0x0c2b6ea8, 0xaa0d03f4, 0x7d78e5aa, 0x28dd607e, 0xa6266d5c, 0xc1e10c02, 0xd1a73e4f, 0xc3a420cd, 0x67c0b5fe, 0x92918567, 0xb809c9d6, 0xdfc97c28, 0xe3c20e65, 0xd1a0eaef, 0x69a92339, 0xdd8b8447, 0xedac4c02, 0x02452ccf, 0x2a984cb1, 0xae9af72a, 0x3027c845, 0xa2b19982, 0x417397e7, 0x3265302a, 0xc95a42d4, 0xc733d413, 0x34b03c9b, 0x3262e48a, 0xedab98a2, 0xa0f361ed, 0xc576f8dc, 0x778687b3, 0x06d50cb1, 0xd77232fe, 0xf383e888, 0x4f1a0120, 0x1e2fa48a, 0xf5513099, 0x49c8d931, 0x75c3ab7c, 0xd3e5c620, 0xf97d8a91, 0x9a2acbb1, 0x5d191fa2, 0x69aef799, 0x57e77dbb, 0x7311736d, 0x389b5233, 0xf97a5e31, 0xcf889ac5, 0xf3843c28, 0xd5371e31, 0xacd80f45, 0xe93bb8dc, 0xeb7e9413, 0x8efb0d22, 0x2e0fb86f, 0x12031e82, 0x8402bb9b, 0x3ad9aa5c, 0x5f5be7cd, 0x5d1ecb02, 0x90d37d08, 0xb2f7abcf, 0xf1c6c447, 0x7f3a1dc5, 0xeb7940b3, 0xc73400b3, 0x2c4d4000, 0x986fe77e, 0x389c8693, 0x26b32219, 0x0490207e, 0xd91c7099, 0x53708965, 0x5f5c336d, 0x1ab85054, 0x24f60ed6, 0x08bb4ed6, 0xf713c8f6, 0xb80e1d76, 0x9cffc700, 0xe755fabb, 0xbc99e9a8, 0x2a9f9811, 0x1694ea5c, 0x4f1dd580, 0x3ade7efc, 0x9ebd3f6f, 0x0c2cba08, 0x16933efc, 0xfdedaaef, 0xa621b9fc, 0x65824d91, 0x45e46339, 0xcf8f4e65, 0x55a25174, 0x7baa3dbb, 0x4d58f94f, 0x90d4a9a8, 0xc1e6d8a2, 0x49cf0d91, 0xfb3f72fe, 0x5135a5aa, 0x986833de, 0x28dab4de, 0x47a69b56, 0x1204ca22, 0xa2b64d22, 0xbedcc567, 0xffa88620, 0xd91ba439, 0x2c4a94a0, 0x7f3dc965, 0x1c6d5ce5, 0xdfcea888, 0x6bec0ff6, 0x24f1da76, 0x7316a7cd, 0xe18722aa, 0x3e498a22, 0x57e0a91b, 0x79ef1174, 0x6f7bfb28, 0xcdcdb60a, 0xba4ce519, 0xe51702d4, 0xc95d9674, 0x80929be5, 0x7d7f310a, 0x63574120, 0xe510d674, 0x6115b94f, 0x6d3ed7e7, 0xb6678bb1, 0x47a14ff6, 0x944489d6, 0x84056f3b, 0xa4649533, 0xf556e439, 0xa0f4b54d, 0x80954f45, 0xdd8c50e7, 0xe3c5dac5, 0xb0b28700, 0xffaf5280, 0x82d0638a, 0xcb18babb, 0xb2f07f6f, 0x22230267, 0xc3a3f46d, 0xe93c6c7c, 0x0af9b6b9, 0x864043f4, 0x30201ce5, 0x67c7615e, 0x26b4f6b9, 0x1c6a8845, 0x0afe6219, 0x882e0193, 0xefe960cd, 0x0e6996c7, 0x929651c7, 0x4d5f2def, 0x86479754, 0x0497f4de, 0x2224d6c7, 0x2061fa08, 0xdb595c56, 0x18fd7c9b, 0x1abf84f4, 0xaa0ad754, 0x6f7c2f88, 0x63509580, 0xcdca62aa, 0x55a585d4, 0x8cb9f54d, 0x45e3b799, 0xa84ffb9b, 0x1046324d, 0x3c0ca6ed, 0x6d390347, 0x82d7b72a, 0xd3e21280, 0x5bcbc7b3, 0x6bebdb56, 0x598eeb7c, 0xb42573de, 0x61126def, 0x79e8c5d4, 0x08bc9a76, 0x8a6b2d5c, 0x14d1c693, 0x65859931, 0x2e086ccf, 0xcb1f6e1b, 0x8829d533, 0x5132710a, 0x9a2d1f11, 0xba4b31b9, 0x36f51054, 0x8efcd982, 0xa8482f3b, 0x71538b02, 0x77815313, 0xc5712c7c, 0xfb38a65e, 0xd530ca91, 0xacdfdbe5, 0x06d2d811, 0x3c0b724d, 0x94435d76, 0xfdea7e4f, 0x20662ea8, 0x4b8a215e, 0x0e6e4267, 0x0007d4a0, 0x0242f86f, 0x8a6cf9fc, 0xb422a77e, 0x36f2c4f4, 0x53775dc5, 0x34b7e83b, 0x5bcc1313, 0x9cf813a0 +} +}, +{ +{ +0xb5837ec4, 0xfe4ec5c1, 0x493f6365, 0xc209b2fd, 0x7ed0ce4d, 0xec650eb9, 0xfd49d6ea, 0xa65d7ef7, 0x3cfc4fb8, 0xda7f68da, 0x5a5a5bd2, 0xacbb572c, 0x00bb3884, 0x0249e0e4, 0x4bcdbb05, 0x4b768381, 0x5b14a81d, 0xff00360e, 0x412b92de, 0xfef5fd45, 0x1290f3fc, 0xd88db0ba, 0xd9787bf1, 0x257f5ed4, 0x8b36d198, 0x25c46650, 0xe5843449, 0x595d48f9, 0xd836883e, 0x80253308, 0x7436e796, 0x2431ad1b, 0xed90c5f2, 0x13de0033, 0x487190aa, 0x0ba8da14, 0x888afa37, 0x7f250506, 0x278d86b4, 0xf4a8ec1a, 0x839918a7, 0xa7a8b5bc, 0x3c47773c, 0xd26b9961, 0x9853e92f, 0x5149b942, 0x90471894, 0xbc624434, 0x58a883b2, 0xc3fc79b6, 0xcaa67bc2, 0x991d1ae0, 0x2f99770f, 0x48caa82e, 0x9109eb5b, 0x6e09dd55, 0x37efad28, 0x651a3fc5, 0x2e6cbc44, 0xffbb0e8a, 0xaf077c83, 0xc9a168e9, 0x095a0274, 0x03bc2baf, 0x10d91318, 0x6eb2e5d1, 0x0814f1bb, 0x816bc0c7, 0x7e6bf6c9, 0x3d0984f3, 0xb5384640, 0xe4cac786, 0x59e6707d, 0x43d94abe, 0x9aa1314f, 0x112cd853, 0x67e8e7a5, 0x01f5cb4b, 0xee2cee5d, 0x1197e0d7, 0x2ed784c0, 0xe6832762, 0x08afc93f, 0x809e0b8c, 0xe471ff02, 0x7c22162d, 0x3f406417, 0xdb8aa391, 0x361a6663, 0x83222023, 0xf65a347a, 0xecde363d, 0x4362723a, 0x52f592ed, 0x897f317c, 0x6cfb0535, 0x661d2cee, 0xad4e9c67, 0x6753df21, 0x50074a8d, 0xd2d0a1e5, 0x98e8d1ab, 0x2d6baf6f, 0xbf65571f, 0x40656111, 0x136538b7, 0xe53f0ccd, 0xef621d92, 0xf55d2751, 0x00000000, 0xfdf2ee6e, 0x6db5f6fa, 0xa7138d38, 0x64eff48e, 0xefd92516, 0x53bb6122, 0x6f472e9a, 0x5baf9099, 0xaef2b7c8, 0xfcbc1da1, 0x0307132b, 0xd16c8a4a, 0xf413d49e, 0x4190aa5a, 0xd0994101, 0x89c409f8, 0x014ef3cf, 0xbcd97cb0, 0x2dd097eb, 0x1983116c, 0x3e0e97d8, 0x34e8be03, 0x530059a6, 0xc8ef9b26, 0xb7ca9e20, 0x8831c2b3, 0xbfde6f9b, 0x1b71c90c, 0xb6846def, 0x1bcaf188, 0x193829e8, 0xc854a3a2, 0xc0405219, 0xa4afa697, 0xd3256aae, 0x49845be1, 0xb771a6a4, 0xfc072525, 0x92b5c0f4, 0x65a10741, 0x81d0f843, 0x91b2d3df, 0xe6381fe6, 0xa4149e13, 0x375495ac, 0xbd2cb7fb, 0x51f281c6, 0x3ffb5c93, 0x122bcb78, 0x02f2d860, 0xac006fa8, 0xc0fb6a9d, 0x9a1a09cb, 0x767f0772, 0xca1d4346, 0xafbc4407, 0x1876da27, 0x36a15ee7, 0xc1b59952, 0x6d0ece7e, 0xbe909c54, 0x93400bbf, 0x0a5d115f, 0x8a782257, 0x7d6ce5e2, 0xee97d6d9, 0x82d7eb68, 0x3db2bc77, 0x7731f4bd, 0xa5e15558, 0x99a62264, 0x75781459, 0xa55a6ddc, 0xa6e64673, 0x2736be30, 0x4a8348ca, 0xcb53b089, 0x0b13e290, 0x6454cc0a, 0x6c403db1, 0x66a6146a, 0x1a3f3ac3, 0xb63f556b, 0x4297b971, 0xcbe8880d, 0x826cd3ec, 0x8b8de91c, 0x18cde2a3, 0xd1d7b2ce, 0x90fc2010, 0xc3474132, 0x7dd7dd66, 0x35a64dcc, 0x09e13af0, 0xf7afff31, 0x50bc7209, 0x920ef870, 0x8ac31ad3, 0xe776ec29, 0xc2b28a79, 0x5ae16356, 0xf714c7b5, 0xbe2ba4d0, 0x4a38704e, 0x9befc280, 0xadf5a4e3, 0x26784dff, 0xf6e10cfe, 0xd0227985, 0x524eaa69, 0x10622b9c, 0x40de5995, 0xae498f4c, 0x93fb333b, 0x778acc39, 0x76c43ff6, 0x7c992ea9, 0xdb319b15, 0x3eb5af5c, 0x26c3757b, 0xb476b58f, 0x7f9e3d82, 0x1a840247, 0xb4cd8d0b, 0xed2bfd76, 0x2c255ca0, 0xd9c34375, 0x5813bb36, 0x748ddf12, 0x6ffc161e, 0xbd978f7f, 0x2c9e6424, 0x75c32cdd, 0xc10ea1d6, 0x0ae629db, 0x248a959f, 0x9b54fa04, 0x2f224f8b, 0xdac4505e, 0xc91a506d, 0x34538687, 0xe7cdd4ad, 0xf5e61fd5, 0x351d7548, 0x422c81f5, 0xd39e522a +}, +{ +0x44f12f63, 0xdd665c6e, 0xf48ef31e, 0x8584e409, 0x04fc092f, 0x36f22097, 0x945cbb9d, 0x66c8f9d1, 0x48d5476d, 0xd0ad94fe, 0xdb7ced3c, 0xf19d5aaf, 0xa4b42a58, 0xab995ab5, 0x6234f0fe, 0x92460acf, 0xe2a3bd46, 0x4617971e, 0xcd51a364, 0x1c139704, 0x2ae1b793, 0x320e29b8, 0xd1423460, 0xb376c49e, 0xe34c1dd8, 0x56206814, 0xfa4c236d, 0xc46662db, 0xc175cb6a, 0xf072fa31, 0xc3937317, 0x9b71cb70, 0x5a04001a, 0xaf65539a, 0xf6684b63, 0x493ae7f3, 0x8fba3d55, 0xbbaea5bf, 0x87625c74, 0x4dc6eedc, 0xff5f8adc, 0x73ecaf6a, 0x8aa994e4, 0xc589c245, 0x3d235955, 0x5333c1a5, 0x5ef80935, 0x02e6b87d, 0x65c1e132, 0x839e555b, 0x58e2b867, 0xa3413b94, 0xd875f5df, 0x7fc8c764, 0xe972c484, 0x54c6d069, 0xa97fe2c8, 0xfc56923f, 0xe89d641a, 0xe1aaa5a5, 0x868dfcea, 0x96ba03e0, 0xc27cd389, 0x00000000, 0xd5be3d4f, 0x0c24680e, 0xeb947cf9, 0x9755a37e, 0x272a7f03, 0x3ad64899, 0x7adb6ed5, 0xbc5bb473, 0x0f2d70ed, 0x5c1eb148, 0x133ee7e9, 0x9c84dabc, 0x846b4497, 0x07f511cc, 0x1a092656, 0x7b34ce4b, 0x371d8009, 0x242367e0, 0x8cb325b6, 0xaa76fa2b, 0x20df6ecf, 0xcb4b1236, 0x7710a645, 0x76ff06db, 0xd6b725ac, 0x3830f0e4, 0x28070fee, 0xad83ebe7, 0x26c5df9d, 0x80974db8, 0xa6529225, 0xb78acdb1, 0x60d24883, 0xcfb71b19, 0xc76f7a38, 0xbf52ac90, 0x2d14a65f, 0xba410521, 0xc9adaa4b, 0xac6c4b79, 0x52dc613b, 0x3107315b, 0x400d264c, 0xd24b2c83, 0xdf80e413, 0x2cfb06c1, 0x14cbf625, 0xea7bdc67, 0x0a3ed95c, 0xce58bb87, 0xed8ecdab, 0x47f83780, 0x2b0e170d, 0x590d18f9, 0x3fc5e128, 0xec616d35, 0x8e559dcb, 0x4f2056a1, 0x57cfc88a, 0x503ad946, 0x1037ff0a, 0xf5615380, 0xf294424c, 0xbebd0c0e, 0x70e5b789, 0x75f61e38, 0x1ef52f79, 0x8271f5c5, 0xde6f448d, 0x0513a9b1, 0x42eb9e31, 0xbdb414ed, 0xf8aa9b10, 0x341498ea, 0xb07fdc7d, 0xee87d548, 0x29e8af70, 0x3cccf9cb, 0x6b033141, 0x4ecff63f, 0x5df111d6, 0xccbe03fa, 0xa0482377, 0xf9453b8e, 0x63db5060, 0xb6656d2f, 0xb56c75cc, 0x2ff21e22, 0xf787ebfd, 0x79d27636, 0x19003eb5, 0xfdb932a1, 0xa7bd32bb, 0x884f2c99, 0xd3a48c1d, 0x25ccc77e, 0x1f1a8fe7, 0xae8af304, 0x6e1098f0, 0x43043eaf, 0x783dd6a8, 0x6fff386e, 0xf37be2d2, 0xa1a783e9, 0x6cf6208d, 0xb8a7bd5c, 0x0bd179c2, 0x4c294e42, 0x5f17a9ab, 0xd4519dd1, 0x642e41ac, 0x51d579d8, 0xc09a6bf4, 0x90a0b2b2, 0xa8904256, 0x95b31b03, 0x17c2eec6, 0x4a33ff10, 0x9f8dc25f, 0x162d4e58, 0x4bdc5f8e, 0xe556ac8a, 0x9878d393, 0xb1907ce3, 0x2239d6b2, 0x2130ce51, 0x8178ed26, 0x613de81d, 0x9d6b7a22, 0x1dfc379a, 0x72030ff4, 0x914f122c, 0xe045053b, 0x8b46347a, 0x01efa09e, 0x7419bea6, 0xe65fb469, 0xc8420ad5, 0x23d6762c, 0x7cc1df87, 0xdc89fcf0, 0x11d85f94, 0x18ef9e2b, 0xa2ae9b0a, 0x39df507a, 0xcaa4b2a8, 0x7e2767fa, 0x12d14777, 0x3b39e807, 0x9997730d, 0x0937c1bf, 0xd7588532, 0x061ab152, 0xa55b8ac6, 0xd99a5541, 0x030918e3, 0x93a9aa51, 0xda934da2, 0xb483d552, 0x710a1717, 0x0ec2d073, 0xe7b014f7, 0x6aec91df, 0x152456bb, 0x41e286d2, 0x6d198013, 0x69e5893c, 0xb9481dc2, 0xfba383f3, 0x680a29a2, 0x8d5c8528, 0x1be686c8, 0xfeb02a42, 0x3e2a41b6, 0xef6875d6, 0x0dcbc890, 0x451e8ffd, 0x33e18926, 0x9e6262c1, 0x35fb3874, 0x89a08c07, 0x7d2e7f19, 0xc680daa6, 0xb2996400, 0xe4b90c14, 0x9a9e6bee, 0x08d86121, 0x30e891c5, 0x5beba084, 0x6727594f, 0x552970f7, 0x2e1dbebc +}, +{ +0x4db91241, 0xbd7a5831, 0xa5afbe2f, 0xa8d39b51, 0xeeaefce8, 0xf2950692, 0x5706627a, 0x1ca93d1f, 0xaa2bca11, 0x5c6c0a20, 0xa1d3652e, 0xae6bcbd7, 0x4d85c886, 0x4201bcb8, 0x0fb8aef9, 0xe8846b0b, 0xaab90d74, 0xe82a76a9, 0x58821644, 0x1507dec2, 0xf647c031, 0xe7001f35, 0xe73cc5f2, 0x15a9c360, 0xe5c494b2, 0x40c5373f, 0x537ab97b, 0x0b6a685a, 0xa1efbfe9, 0xe3ee0351, 0x0deee21b, 0x46d37a1b, 0x5ea881a7, 0xbde89f54, 0xfd1172ac, 0xf4118cd3, 0x55502e98, 0xb4467c89, 0xb094ba2a, 0x00000000, 0x18e93cd9, 0x132d4921, 0x4baf5f65, 0x0992391a, 0x06b85086, 0xaec5d675, 0x1a83aafc, 0x04d2c6a3, 0xe3d2d996, 0xe1b84fb3, 0x1a2db75e, 0x4f414301, 0x534663bc, 0xfb073f88, 0x53e87e1e, 0xb9a89e92, 0xf207c1f7, 0x46efa0dc, 0xead227e9, 0x4d2bd524, 0x5c50d0e7, 0x06164d24, 0xb2c2f6c8, 0xecc46acd, 0xf06d57d2, 0x153b0405, 0xf42d5614, 0xff473e4e, 0x02f85140, 0x4d170fe3, 0x4fef5ea3, 0x496bd4e2, 0x047cdb01, 0xbb50cfd2, 0x026a9625, 0x0092c765, 0x1abf703b, 0xb9944455, 0x4057f05a, 0xa7c5280a, 0x1147df04, 0xea40e08c, 0xbf2c14d3, 0xe37cc434, 0xecf8b00a, 0xffd5f92b, 0xb62ceaac, 0x0f2a699c, 0xae571110, 0x4f7d99c6, 0xa32b346e, 0x53d4a4d9, 0xe56a8910, 0xac939a97, 0xe8b8b1cc, 0xf9c3b40f, 0xbbc208b7, 0x556cf45f, 0x5ae88061, 0xa53d794a, 0xe1165211, 0xb4e8612b, 0x4b3d9800, 0x406b2a9d, 0x573ab8bd, 0xffe923ec, 0xbb6c1515, 0xbbfed270, 0xaa1710d6, 0xac3d8735, 0xeaeefd2e, 0x5cfecd45, 0x1c95e7d8, 0x1c3bfa7a, 0x442b2b5b, 0x5182e83b, 0xf96da9ad, 0x55c2e9fd, 0x40f9edf8, 0x44b9ec3e, 0x5e945b60, 0x187bfbbc, 0xf6e9dd93, 0xa7f9f2cd, 0xb25031ad, 0xe1849574, 0x003cdac7, 0x18d5e61e, 0x0d40ffb9, 0xb682f70e, 0xe816ac6e, 0x5a7a4704, 0xa87d86f3, 0xa38529cc, 0xb610306b, 0x5cc21782, 0x0dd238dc, 0x4641bd7e, 0x57a87fd8, 0xfb95f8ed, 0x00ae1da2, 0xaef90cb2, 0xf0c34a70, 0x0bf8af3f, 0x1c0720bd, 0x5a469dc3, 0xb6be2dc9, 0xe55653d7, 0x13bf8e44, 0xb4d4bbec, 0xee3c3b8d, 0xb2fe2c0f, 0xbf820971, 0xf9ff6ec8, 0x17c35545, 0xf4bf9171, 0x1eff71fd, 0x467d67b9, 0xfd83b5c9, 0x1e516c5f, 0xf4834bb6, 0x55fe333a, 0x42937bdd, 0x512cf599, 0xa317eea9, 0xfd2da86b, 0xaa85d7b3, 0xb9068330, 0x093c24b8, 0xac015df2, 0xb93a59f7, 0xea7c3a4b, 0x1ec3ab3a, 0x131193e6, 0xbd4682f6, 0xf951736a, 0x11e9c2a6, 0x582c0be6, 0xb0a860ed, 0x0b56b29d, 0xb47aa64e, 0x49c5c940, 0xff7be489, 0x42afa11a, 0xf0518d15, 0xa17d788c, 0xa8415c34, 0x1a116d99, 0x51102f5e, 0x4fd38464, 0xacaf4050, 0xb03aa788, 0x1847217b, 0x11d51861, 0xe12a88d6, 0x5e3a46c2, 0xf23b1b30, 0xbf10ce14, 0x17519220, 0x5810d121, 0xf2a9dc55, 0x5e069c05, 0x49570e25, 0x58becc83, 0x4b0142c7, 0xa501a38d, 0x0900fe7f, 0x17ff8f82, 0x0bc475f8, 0xe7ae0297, 0x448536f9, 0xf0ff90b7, 0xa757ef6f, 0x06848a41, 0x0f84743e, 0xee00e14a, 0x04ee1c64, 0x49f91387, 0x062a97e3, 0x4b9385a2, 0x13835483, 0xfdbf6f0e, 0xe792d850, 0x1e6db698, 0xb26ceb6a, 0xfb3be54f, 0xee92262f, 0xfba9222a, 0x159519a7, 0xa141a24b, 0xe3401ef3, 0xec6a776f, 0x02564ce2, 0xa59364e8, 0x5ad45aa6, 0xbdd44593, 0x4417f19c, 0x176d48e7, 0x117b05c3, 0x0f16b35b, 0x423d667f, 0xb0067d4f, 0xe5f84e75, 0x51be32fc, 0x044001c6, 0x0d7c257e, 0x02c48b87, 0xa8ef4196, 0xf6d50754, 0xec56ada8, 0x09aee3dd, 0xa76b35a8, 0xa3b9f30b, 0xf67b1af6, 0x5794a51f, 0xbfbed3b6 +}, +{ +0x6824478b, 0x190597dc, 0x6e331ada, 0xaa732842, 0xb5951da4, 0xba9725f0, 0xac908a78, 0x60df2e9f, 0xd5becc50, 0x84f763ea, 0x474e0032, 0xfad48be9, 0xe4dcb21e, 0x77c2726d, 0x49a23477, 0x2f9eb8d2, 0x69ca4b9a, 0x4eaf9a5c, 0x67267fdf, 0x6131228e, 0x4956cb1c, 0xdcaba955, 0x40b75172, 0xf4cc40c7, 0x06e3a23a, 0xe532be0f, 0x27912ead, 0x575ef2eb, 0x00000000, 0xd54a333b, 0x9c1cf827, 0x830e32aa, 0x5e4b97ee, 0xfdd925c2, 0x10e40db2, 0x56440191, 0xbc7487ca, 0x78c04a39, 0x289316f9, 0xddb15a2f, 0x19f168b7, 0x2989e583, 0x2e844ba8, 0x51bd50d1, 0x41ada208, 0x61c5dde5, 0xb38240f5, 0x693eb4f1, 0x18eb9bcd, 0x0ff6c73f, 0xb298b38f, 0xdba6077e, 0x76d88117, 0x171d5cf2, 0xf5224cd6, 0x30788d34, 0xec27db0a, 0x1efcc69c, 0xad8a7902, 0xe23f1024, 0xa27cbe3d, 0xecd32461, 0x20687fed, 0x080f967f, 0x7121d057, 0x31627e4e, 0xeb2a7521, 0x85196ffb, 0xb376bf9e, 0xd2479d10, 0x95099d22, 0x308c725f, 0xca58f9b6, 0x8bf55bbe, 0x2867e992, 0x703b232d, 0x01ee0c11, 0xc2a390a2, 0x09156505, 0xf438bfac, 0x8b01a4d5, 0x011af37a, 0xd2b3627b, 0x3e94b971, 0x3883e420, 0xcb420acc, 0x77368d06, 0x09e19a6e, 0x94e79133, 0x94136e58, 0x5149afba, 0x594639c5, 0x48b8c70d, 0xc4b4cdf3, 0xc4403298, 0x1f12ca8d, 0xa585ef7d, 0x38771b4b, 0x07f95140, 0xcaac06dd, 0xac647513, 0xa49f1c07, 0x2f6a47b9, 0x0e18cb2e, 0xa2884156, 0xc2576fc9, 0x931ec073, 0xdabcf404, 0x9d060b5d, 0x218673fc, 0x00f4ff6b, 0x67d280b4, 0x8a1b57af, 0xbd9a8bdb, 0xd35d6e6a, 0x110a01a3, 0xa3664d47, 0x9aff5a1d, 0x369b2f0e, 0x0eec3445, 0x8aefa8c4, 0xd4a43f2a, 0xcbb6f5a7, 0x17e9a399, 0xab69db38, 0x8de206ef, 0xba63da9b, 0x3781dc74, 0x56b0fefa, 0x663c8ca5, 0x57aa0d80, 0xc5ae3e89, 0x8d16f984, 0xfd2ddaa9, 0x5fa59bff, 0x4043ae19, 0x8c0c0afe, 0x070dae2b, 0x71d52f3c, 0x82e03ebb, 0xad7e8669, 0x58a835d4, 0xf3351187, 0x4e5b6537, 0x41595d63, 0x6ec7e5b1, 0xa5711016, 0x31968125, 0x267f22bc, 0x7fcde412, 0xb561e2cf, 0x1fe635e6, 0x92043309, 0x7f391b79, 0xdb52f815, 0x8cf8f595, 0xbc8078a1, 0x83facdc1, 0x3775231f, 0xea30865b, 0x5ebf6885, 0xfc3729d3, 0x7e23e803, 0x9a0ba576, 0x95fd6249, 0x6f29e9a0, 0xe4284d75, 0xcda1a8f6, 0xdc5f563e, 0xab9d2453, 0xcc4fa4e7, 0xfa207482, 0x68d0b8e0, 0x8214c1d0, 0x1607af88, 0xed3d2870, 0xc3b963d8, 0xb48feede, 0x366fd065, 0xaa87d729, 0xd450c041, 0x4fb56926, 0x92f0cc62, 0x585ccabf, 0x1e0839f7, 0xfcc3d6b8, 0x79dab943, 0x209c8086, 0xeac47930, 0xf3c1eeec, 0x602bd1f4, 0xb47b11b5, 0xfb3a87f8, 0xbb8dd68a, 0x3f8e4a0b, 0xe325e35e, 0x484c3866, 0x66c873ce, 0xbb7929e1, 0xb26c4ce4, 0x181f64a6, 0x84039c81, 0x5f516494, 0x2765d1c6, 0x3e60461a, 0xe5c64164, 0xf2db1d96, 0xc34d9cb3, 0xf5d6b3bd, 0x4654f348, 0xccbb5b8c, 0x6fdd16cb, 0x4f41964d, 0x08fb6914, 0xa46be36c, 0x59b2c6ae, 0x11fefec8, 0xda480b6f, 0x9be5a967, 0xe2cbef4f, 0xedc9d71b, 0x70cfdc46, 0x85ed9090, 0x93ea3f18, 0x9ce8074c, 0x7ed71768, 0x21728c97, 0x9b11560c, 0x47baff59, 0x3999175a, 0xbd6e74b0, 0x3f7ab560, 0x9df2f436, 0xd3a99101, 0xebde8a4a, 0x06175d51, 0x50535cc0, 0xc55ac1e2, 0x268bddd7, 0x297d1ae8, 0xfbce7893, 0x792e4628, 0x0f023854, 0xf22fe2fd, 0x2e70b4c3, 0xe3d11c35, 0x46a00c23, 0x16f350e3, 0xdd45a544, 0xcd55579d, 0x50a7a3ab, 0x396de831, 0xa392b22c, 0x762c7e7c, 0x1010f2d9, 0x7834b552 +}, +{ +0xdd2918c5, 0xe890fcbc, 0xd9f7de3e, 0x5a69913d, 0x7b7b04a9, 0x400d9caf, 0x904b6851, 0x3619743d, 0x1cc3e0dc, 0xa89d6013, 0x120c9ca3, 0x1ebacb69, 0x0bc80175, 0xd046f4fe, 0xe65f80c3, 0x00000000, 0x11ac0ce7, 0xb5873b3e, 0xee3711f2, 0x803edf47, 0x077e56bf, 0x0f16c78e, 0x898ff587, 0xe121d67c, 0xe2814638, 0xafe336ac, 0xe426ab76, 0xcd5cafd3, 0x04dec6fb, 0x1d1a5b2d, 0x70b305dc, 0xc85bd2d9, 0x54a6ed42, 0x25cc536f, 0x43ad0ceb, 0x34605f88, 0xf4531c60, 0xa12c4ad3, 0x77cd5363, 0x81e764b6, 0xd6e119b0, 0xfe42a6e4, 0x01d9bbf1, 0x4f1b5b21, 0xac43a6e8, 0x4773ca10, 0x64187431, 0xbdefaa0f, 0xed9781b6, 0x9823f960, 0x266cc32b, 0x41d4275e, 0x611f093b, 0xc03343e8, 0x181d2627, 0x97353eee, 0x02792bb5, 0xf58aa791, 0x31672282, 0xc5343ee2, 0x716abe2d, 0xd4983205, 0xf62a37d5, 0xb159fdc5, 0x46aa71e1, 0x09b12ac0, 0xf154616a, 0xa78ba79d, 0x7614e892, 0x5bb02acc, 0xcc851422, 0x73139598, 0x8539a24d, 0x297a04a5, 0x7c055216, 0x57067d06, 0xdb8ef58b, 0xa42b37d9, 0x8f2818c9, 0xec4e3a47, 0x3e71e50c, 0x8bf6de32, 0x05077d0a, 0x6e09ceb5, 0xdf503370, 0x8d51337c, 0x22b205d0, 0xff9b1d15, 0x9f5dafdf, 0xeb306cf8, 0x8c88888d, 0x3dd17548, 0x50782bb9, 0x5d17c782, 0xba91fcb0, 0xda574e7a, 0x4274b71a, 0xd3e664ba, 0x4d627094, 0x56dfc6f7, 0xb2f96d81, 0xeae9d709, 0xcefc3f97, 0x4cbbcb65, 0x5cce7c73, 0xe7863b32, 0x3c08ceb9, 0x7ddce9e7, 0x1bbdb663, 0xa28cda97, 0xb9316cf4, 0xe0f86d8d, 0x16d25a58, 0xefeeaa03, 0x5810ba88, 0x5201000c, 0x99fa4291, 0x2fdde9eb, 0xa3556166, 0x2415e89e, 0xa5f28c28, 0xb8e8d705, 0x9192d3a0, 0x96ec851f, 0xc393d3ac, 0x2b032f10, 0x9d24846a, 0x21129594, 0x2e04521a, 0x79022f1c, 0x9e84142e, 0x9a5ad2d5, 0xf08dda9b, 0xca22f96c, 0xdcf0a334, 0x72ca2e69, 0x48650d9e, 0x7fa5c252, 0xf7f38c24, 0x49bcb66f, 0x7aa2bf58, 0x30be9973, 0x20cb2e65, 0xbc3611fe, 0x7e7c79a3, 0x37c0cfcc, 0x19c49dd6, 0xc694aea6, 0x6b0eb3bf, 0x9b836924, 0x0d6fec3b, 0x923243e4, 0xd19f4f0f, 0x450ae1a5, 0xc4ed8513, 0x6366228e, 0xf2f4f12e, 0x9495aeaa, 0x5f6eec37, 0xd54189f4, 0x3aaf23f7, 0xc1eaf819, 0x1075b716, 0x4bc59dda, 0x746dc327, 0x62bf997f, 0x28a3bf54, 0x170be1a9, 0x6c70e500, 0xe949474d, 0xd738a241, 0x2ada94e1, 0x3b769806, 0x2c7d79af, 0xbf9681ba, 0x51a19048, 0xe5ff1087, 0x06a7ed4e, 0xfc3b8d51, 0x6ad7084e, 0xd23fdf4b, 0xe358fdc9, 0x44d35a54, 0xa6521c6c, 0xc9826928, 0x08689131, 0xcbfb429d, 0xbb484741, 0xbe4f3a4b, 0x86993209, 0xfa9c601f, 0xab3df057, 0x6fd07544, 0x236bbe21, 0x5eb757c6, 0x8a2f65c3, 0xae3a8d5d, 0x88564e76, 0x874089f8, 0x03a09044, 0xfde236a0, 0x3fa85efd, 0x8ef1a338, 0x6977980a, 0x93ebf815, 0x1572ca1c, 0xb45e80cf, 0x954c155b, 0x27b578da, 0xb7fe108b, 0x78db94ed, 0x38d60842, 0x0ecf7c7f, 0x53d8bbfd, 0x32c7b2c6, 0xc74d1557, 0x839e4f03, 0xb0804634, 0xcf258466, 0x1f637098, 0x60c6b2ca, 0x4ec2e0d0, 0x390fb3b3, 0x6da95ef1, 0x65c1cfc0, 0x68ae23fb, 0xc24a685d, 0x13d52752, 0xad9a1d19, 0x75b478d6, 0x0cb657ca, 0xde898881, 0xa944dbe2, 0xf32d4adf, 0xf93cf05b, 0x4a1c262b, 0x331e0937, 0xb320d670, 0xaae44ba6, 0x67b8e475, 0x14ab71ed, 0xb627ab7a, 0x2da4c25e, 0xfb45dbee, 0x9cfd3f9b, 0x66615f84, 0x8247f4f2, 0x84e019bc, 0x35b9e479, 0xa0f5f122, 0xf8e54baa, 0x0a11ba84, 0x1a640d92, 0x59c90179, 0x557f56b3, 0xd82e65cf +}, +{ +0xa2fa971f, 0x28b417a7, 0x4f66e095, 0xe267e6ca, 0x781fb0d2, 0x2508879f, 0xca1eaf0f, 0xe6d25707, 0x636746ff, 0x880981c0, 0x98f20902, 0x1b78f62d, 0xb2011fdd, 0x25c5d9fd, 0x596fd8e2, 0x838aff2f, 0xbbc5604a, 0xccec1fba, 0x937177ed, 0x8c716e6f, 0xde509600, 0x5d17374d, 0xd51eb68d, 0xd794e997, 0x0dbc9038, 0x5f503635, 0xc1508f82, 0xad01065f, 0x21706830, 0x028a5f1a, 0x7caa011f, 0x6a6e670a, 0x4fabbef7, 0x7e205e05, 0xa0bd9667, 0xa64f26d2, 0xa40827aa, 0x565917c0, 0x9a785618, 0x06f2b0b5, 0xfb954ffd, 0xa237c97d, 0x7351905f, 0xc19dd1e0, 0x00cd5e62, 0x1d8a4698, 0x9c47b8cf, 0xeba3995d, 0x78d2eeb0, 0xb2cc41bf, 0xa68278b0, 0x671fa950, 0xc3178efa, 0x2782d885, 0x85b511f8, 0xceab1ec2, 0x090921f5, 0xffeda052, 0x3a089e1d, 0x7c675f7d, 0xa070c805, 0x67d2f732, 0x77e42192, 0xb6b4ae10, 0x9583c758, 0x0ffb9140, 0x2c01a66a, 0x3ebd2fd0, 0xabf3b6ea, 0x569449a2, 0x02470178, 0xbf70d187, 0xc3dad098, 0x6c5189dd, 0xfb58119f, 0x287949c5, 0x1036d6a0, 0x0b4e208d, 0xe495567f, 0x9c8ae6ad, 0x81cdfe57, 0x4b1e0f3a, 0xc894f015, 0x8e366f17, 0x3146be90, 0x88c4dfa2, 0x37795047, 0xcad3f16d, 0x54d348da, 0xf46edebd, 0x6558a828, 0x6595f64a, 0x1483676d, 0x4decbf8f, 0x3e7071b2, 0x68e43810, 0x541e16b8, 0xe0edb9d0, 0x0478efaf, 0x3301bfe8, 0x3882c107, 0x873f4ee2, 0x87f21080, 0xbdfa8e9d, 0x68296672, 0x2cccf808, 0xcc2141d8, 0x3c3770ca, 0x23376948, 0xb679f072, 0xf91f10e7, 0xb08b40c7, 0x04b5b1cd, 0x71dbcf45, 0x77297ff0, 0x23fa372a, 0xc5e53e4f, 0x12bc89ba, 0x09c47f97, 0xef162890, 0xb0461ea5, 0xf251306a, 0x6aa33968, 0x3ac5c07f, 0xf29c6e08, 0xf9d24e85, 0xc7a23f37, 0x1fcd47e0, 0xdae527cd, 0x5be587f8, 0xed9c778a, 0x954e993a, 0x6c9cd7bf, 0x274f86e7, 0x9e00b9b7, 0x42172ecf, 0xd86f78d7, 0x50aba775, 0x7a95efc8, 0x1271d7d8, 0xefdb76f2, 0xff20fe30, 0x93bc298f, 0xb94f3f50, 0x144e390f, 0xa9b4b792, 0xaf8b5945, 0x8efb3175, 0x71169127, 0x33cce18a, 0x2a3e48bd, 0x4bd35158, 0xbd37d0ff, 0x384f9f65, 0xbfbd8fe5, 0x21bd3652, 0x85784f9a, 0xe9e49825, 0x8100a035, 0x2af316df, 0x8cbc300d, 0xb9826132, 0x97c4c620, 0xd3ec0638, 0x8a4e80b8, 0x5b28d99a, 0xf6e481a7, 0x0d71ce5a, 0x8347a14d, 0xfdaaa12a, 0x19f2a937, 0xd1ab0740, 0x0b837eef, 0x6e1688a5, 0x0f36cf22, 0xed5129e8, 0xe020e7b2, 0xf4a380df, 0x193ff755, 0xdcdac91a, 0x61204787, 0x00000000, 0x1bb5a84f, 0xb4f3af68, 0x42da70ad, 0x46a29f02, 0xb43ef10a, 0x983f5760, 0xf0163112, 0xd5d3e8ef, 0x91fb28f7, 0x44e59e7a, 0xe458081d, 0xeb6ec73f, 0xdc179778, 0xd1665922, 0xf0db6f70, 0xd759b7f5, 0x409d71d5, 0xd8a226b5, 0xab3ee888, 0xa4c579c8, 0x16c46615, 0x97099842, 0xc76f6155, 0x35f30f5d, 0x063feed7, 0x2e46a712, 0xda2879af, 0x8a83deda, 0x5dda692f, 0x756e7e88, 0xc528602d, 0x7a58b1aa, 0x16093877, 0xd321585a, 0x4428c018, 0x5221f86f, 0xa979e9f0, 0x4d21e1ed, 0x40502fb7, 0x5066f917, 0xde9dc862, 0x75a320ea, 0xe929c647, 0xce6640a0, 0x1d4718fa, 0x61ed19e5, 0x3cfa2ea8, 0xbb083e28, 0x49590e42, 0x49945020, 0xe2aab8a8, 0x7eed0067, 0x37b40e25, 0xe61f0965, 0x2e8bf970, 0x9ab5087a, 0x59a28680, 0xfd67ff48, 0x9ecde7d5, 0x466fc160, 0x1f001982, 0x353e513f, 0x10fb88c2, 0x6edbd6c7, 0xaf460727, 0xc859ae77, 0x63aa189d, 0x318be0f2, 0x5f9d6857, 0xf629dfc5, 0xadcc583d, 0x739cce3d, 0x91367695, 0x52eca60d +}, +{ +0xfbb70cb8, 0xc4cecfe5, 0x6519d0f2, 0x561e5cd5, 0x21e1c625, 0xf997b7d0, 0x374b47ac, 0x5840a8c7, 0xef1849c6, 0x0469b414, 0xf1a53321, 0xdc1fc5e1, 0x083284f1, 0x7dc8daf6, 0xc4ebb07a, 0x617064e6, 0x5c291cd3, 0xa3f7a47f, 0xb9061513, 0x98e7d336, 0xe95146ba, 0x73962ee4, 0xf1804cbe, 0xf9b2c84f, 0x2bd68623, 0x4091a2c3, 0x9ac7685e, 0xb111ee7d, 0xa1f26088, 0xaf89eb05, 0xabe05f11, 0x356bfcc4, 0xfb927327, 0x505753a9, 0x1e980578, 0xe70fb2a8, 0xc0a77bf1, 0x5865d758, 0x14af457e, 0xd8530e6a, 0xd42d4110, 0xde3f7e89, 0x4cca9226, 0xe146bdd4, 0xada9506d, 0xeb54824d, 0x5a456c30, 0xd24131f3, 0xe9743925, 0xfdfe03c4, 0x3d597835, 0xde1a0116, 0x0220bb68, 0x71b6958c, 0x7b81d58a, 0x278db6c6, 0x5252975e, 0xa7bb6ff4, 0x94999c4c, 0x8e4d52bf, 0xe52f09c0, 0x3930cc21, 0x8a24e6ab, 0x6942e017, 0x653caf6d, 0x376e3833, 0x40b4dd5c, 0x0e5ef412, 0x7193ea13, 0x0e7b8b8d, 0xed1d8d31, 0x2fbf3237, 0x77dae56f, 0x46fdd220, 0x48a32632, 0x8c489648, 0x0c7e4f7a, 0xcef98fe3, 0xb55d25f6, 0x8821225c, 0x77ff9af0, 0x00257f9f, 0xc287c099, 0x4eea294e, 0xbb26ae7b, 0xccd9348b, 0xc6cb0b12, 0x8e682d20, 0x8013a6ad, 0xa1d71f17, 0xe36606bc, 0x3127374f, 0x4aa6e2c5, 0x5c0c634c, 0x3915b3be, 0x1af1b16c, 0x6d0e2b9c, 0x0a374006, 0x75fa5e07, 0x18d10a04, 0x12e64a02, 0x4a839d5a, 0x42b119ab, 0xccfc4b14, 0x0205c4f7, 0x6375a011, 0x8a019934, 0xa59bd49c, 0xca903bf7, 0xa3d2dbe0, 0xf5cc8735, 0x1c9dc18f, 0x42946634, 0x7984117d, 0x90d557c7, 0x44dd6948, 0x21c4b9ba, 0x94bce3d3, 0xabc5208e, 0x2dbaf6c0, 0x7fcd1e01, 0x00000000, 0x92d09330, 0x06490f7c, 0xbd4ade98, 0x5a6013af, 0xef3d3659, 0x69679f88, 0xffdeb8ac, 0xc082046e, 0xa5beab03, 0x354e835b, 0xe3437923, 0xda56ca9d, 0x8216625a, 0x33078c27, 0x8c6de9d7, 0x6b625b7f, 0xd0618a9b, 0x6b4724e0, 0x25ad0dae, 0xd87671f5, 0x867fd64e, 0x044ccb8b, 0xe72acd37, 0x543ee7bd, 0xa9c0e479, 0xc2a2bf06, 0xbb03d1e4, 0xf7ec3c5d, 0xcab54468, 0x67396b9a, 0xdc3aba7e, 0x7fe8619e, 0xb9236a8c, 0xf3a0f7d6, 0x6f0bef6b, 0x9cab18bd, 0x23c17d4d, 0xb77d9e9e, 0xf3858849, 0x7ba4aa15, 0x5277e8c1, 0xb3315515, 0x6f2e90f4, 0x2bf3f9bc, 0x3b3508d6, 0x79a16ee2, 0x61551b79, 0xa79e106b, 0x0a123f99, 0x16aa8189, 0x168ffe16, 0x10c6f16a, 0xb5785a69, 0x0c5b30e5, 0x3f79c35d, 0xfffbc733, 0x563b234a, 0x27a8c959, 0x1ebd7ae7, 0x92f5ecaf, 0x12c3359d, 0xb13491e2, 0x865aa9d1, 0x82331dc5, 0xbd6fa107, 0xc8b0809f, 0x18f4759b, 0x2d9f895f, 0xe50a765f, 0x5e09a7bb, 0xcedcf07c, 0x3b107749, 0xb3142a8a, 0xbf6a65f0, 0xafac949a, 0xd2644e6c, 0x8036d932, 0x3f5cbcc2, 0x90f02858, 0x969c58bb, 0x5e2cd824, 0x75df2198, 0x9c8e6722, 0x9e8ba3d5, 0x29d342d4, 0x6d2b5403, 0x23e402d2, 0x7deda569, 0x88045dc3, 0xbf4f1a6f, 0x0817fb6e, 0xd60dfa78, 0x9eaedc4a, 0x44f816d7, 0x148a3ae1, 0x066c70e3, 0xd4083e8f, 0xa9e59be6, 0x73b3517b, 0x96b92724, 0xed38f2ae, 0x671c1405, 0xad8c2ff2, 0xf7c943c2, 0x98c2aca9, 0xd044f504, 0x2f9a4da8, 0x310248d0, 0x50722c36, 0x3322f3b8, 0x541b9822, 0xc6ee748d, 0xfddb7c5b, 0xc895ff00, 0x845f6d26, 0xf5e9f8aa, 0x4cefedb9, 0x847a12b9, 0xe163c24b, 0xb758e101, 0x488659ad, 0xd62885e7, 0x10e38ef5, 0x9ae217c1, 0x1cb8be10, 0x25887231, 0x4ecf56d1, 0xeb71fdd2, 0xda73b502, 0x46d8adbf, 0x3d7c07aa, 0x6350df8e, 0x29f63d4b, 0x1ad4cef3 +}, +{ +0x67d3a235, 0x33e2e39f, 0x51b91ea2, 0xc317573d, 0x198739cf, 0x77166699, 0x92ae499f, 0x3407ae3a, 0xe5b82f06, 0x021a75e4, 0x0942fd63, 0x8cbb5abc, 0xa356dfe4, 0x2808c8fd, 0xdd752357, 0x53a36b46, 0x4dc11f2c, 0x604188d9, 0x858ec096, 0xee97c0c8, 0xad86086b, 0xda906ef2, 0x5d04db80, 0x0b2fefce, 0xbf2ede6a, 0x10c5c4ac, 0xb3e47c01, 0xaa6345ce, 0x543141aa, 0x5a96f16c, 0xa6a9e7a5, 0x8ea12f58, 0xf7679e4e, 0x3d323410, 0x8ed64811, 0x05ff3841, 0x4fac0d81, 0xe7d53dab, 0xc4f21a98, 0x7c398957, 0x24b50ddf, 0xdae709bb, 0x469997ab, 0x9b9bd3b5, 0x12dfb148, 0x23272733, 0x5f1eae64, 0x00000000, 0xf0f5b4a2, 0xf710f907, 0xfbad3c25, 0x3d455359, 0xcfddf556, 0x6b6e6717, 0x90b43c7b, 0x90c35b32, 0x26af783b, 0x153afced, 0xe030700e, 0x0ed0d78f, 0x79b1d65f, 0x2df7f0bc, 0x5d73bcc9, 0x7e23fcb3, 0x58fbe3c1, 0x954b043a, 0x339584d6, 0xd8fd7c5f, 0x38cd0c51, 0x821cea7a, 0xb8bcf486, 0x3ad779b5, 0xc3603074, 0x565c5307, 0x67a4c57c, 0x893305b4, 0xeb68f889, 0xc17a4590, 0x2a12bd19, 0x9981a651, 0x3f2841f4, 0xf2efc146, 0xbad1e62b, 0xa14caa00, 0x690375ba, 0x287fafb4, 0xc838b8f3, 0x3aa01efc, 0x0ea7b0c6, 0x2350407a, 0xcdb0e7fb, 0x026d12ad, 0x6cfc4dfb, 0x51ce79eb, 0x10b2a3e5, 0x4a5335c0, 0x214a359e, 0xadf16f22, 0x697412f3, 0xb1896eac, 0x9becb4fc, 0x0cbdc522, 0x07922aec, 0xeb1f9fc0, 0x4db67865, 0xeee0a781, 0x8071f8d7, 0xd1bf813c, 0x31f8967b, 0x07e54da5, 0x562b344e, 0x4483e24f, 0xd88a1b16, 0x2f9ae211, 0x70f32b3c, 0xc6e86f7c, 0x48494024, 0xe905ea24, 0xfc3f16c9, 0x0b588887, 0xaf9c7d8f, 0x8b5e1719, 0xe0471747, 0x6ee6381f, 0x1e62746a, 0xca22cd17, 0x9c7e9e10, 0x38ba6b18, 0xa13bcd49, 0xd3d29391, 0xf9b749c1, 0xf50a8ce3, 0x24c26a96, 0x1bea2b62, 0xe7a25ae2, 0x366abc97, 0x79c6b116, 0x3470c973, 0xecfad265, 0x588c8488, 0xa879302a, 0x9e138cbd, 0xec8db52c, 0x17208909, 0xe9728d6d, 0xc69f0835, 0xbd34ab8e, 0xbf59b923, 0x9c09f959, 0x2fed8558, 0x9e64ebf4, 0xb8cb93cf, 0x776101d0, 0xa4b39241, 0xc84fdfba, 0x953c6373, 0xe5cf484f, 0xfbda5b6c, 0x7baba3bb, 0x6c8b2ab2, 0x213d52d7, 0xf082d3eb, 0xa6de80ec, 0xdf6f56b3, 0x6036ef90, 0xc10d22d9, 0xfe25632d, 0xe25d62a3, 0x4366afea, 0x361ddbde, 0xafeb1ac6, 0x4a245289, 0x46eef0e2, 0xbaa68162, 0x4311c8a3, 0x5ae19625, 0x3f5f26bd, 0x757b7434, 0x544626e3, 0x1c0f66c7, 0xb61b4440, 0xd62dabd0, 0xd440b97d, 0x7bdcc4f2, 0x2a65da50, 0x97261697, 0xa321b8ad, 0x12a8d601, 0xdf1831fa, 0xbd43ccc7, 0x750c137d, 0x53d40c0f, 0xd437de34, 0x00776749, 0x65beb098, 0x4fdb6ac8, 0xaa142287, 0x2d8097f5, 0xdd02441e, 0x410bbd47, 0xd3a5f4d8, 0xd65acc99, 0xcdc780b2, 0xfc487180, 0x0ccaa26b, 0x318ff132, 0x65c9d7d1, 0x6b19005e, 0x80069f9e, 0x417cda0e, 0x975171de, 0x72e95ed8, 0x19f05e86, 0x625bfd3d, 0x826b8d33, 0x44f48506, 0xca55aa5e, 0x7e549bfa, 0xc4857dd1, 0x1b9d4c2b, 0xe22a05ea, 0xb3931b48, 0x6e915f56, 0x8794b572, 0xcfaa921f, 0xf57debaa, 0x7c4eee1e, 0x26d81f72, 0x1c78018e, 0x99f6c118, 0xf298a60f, 0xb66c2309, 0xb47656ed, 0xd1c8e675, 0x5f69c92d, 0x09359a2a, 0x729e3991, 0x894462fd, 0xfe520464, 0xb40131a4, 0x8ccc3df5, 0x483e276d, 0xf9c02e88, 0x1e151323, 0x622c9a74, 0xa80e5763, 0x05885f08, 0x154d9ba4, 0x8b297050, 0x87e3d23b, 0xb1fe09e5, 0x92d92ed6, 0xa4c4f508, 0x85f9a7df, 0x1757ee40, 0x70844c75 +}, +{ +0x8918f03a, 0xc37c3d23, 0x3b2f9557, 0x2bde7e57, 0x19ce7445, 0x834ff29a, 0x390d7c35, 0x6ddd3bda, 0x03689de5, 0x259b1fa1, 0x2e866986, 0xfd0bbfa5, 0x0f0f1571, 0xefd8bdc7, 0xb76f72bc, 0xe2f541d4, 0x1aa6e9a0, 0xfc41cb22, 0x435b525c, 0x2fcc1d01, 0x490c50fc, 0x4f3cdac8, 0x678a397a, 0xa5bc70de, 0xf43420e0, 0x70012cc9, 0x8c40e7eb, 0xee92c940, 0x6bedb1ee, 0xd79fb575, 0xc92b3f83, 0xe3bf3553, 0xa79e99bc, 0xebcade91, 0xc8614b04, 0x2deef463, 0x6aa7c569, 0x22e1e112, 0x4c54472d, 0x6c974f5d, 0x4d1e33aa, 0x10f1eb00, 0x32100a12, 0xdea02a30, 0x055817d1, 0x57b8da0a, 0x9cb10ceb, 0xedfa54a5, 0x23ab9595, 0x50c224b9, 0x014a7487, 0x188400c2, 0x714b584e, 0xbd38701c, 0xea80aa16, 0x61bab34e, 0x5fcd31c8, 0xcd395cd5, 0x37481dc3, 0x8205861d, 0xe0d7a8b6, 0x94c4e729, 0xd1af3f41, 0x356af4a1, 0xa8918ccd, 0x0875ebc2, 0xbf1a997e, 0x139976e5, 0x14e38856, 0x21897cf7, 0x63985a2c, 0xc406c390, 0x4179bb3e, 0x816d1bf8, 0xcb09d6e1, 0xc23649a4, 0x53aab95c, 0xb15ff888, 0x875d91cc, 0xc76e5e75, 0xaab365af, 0x64e2a49f, 0xff2956c7, 0x5defd8aa, 0x9dfb786c, 0x9e93e589, 0xa2c68e6d, 0x7369b12c, 0xd0e54bc6, 0x6eb5a63f, 0xac83ef9b, 0x04126356, 0xd6d5c1f2, 0xecb02022, 0xfa714116, 0x3d1f1f63, 0x0222e962, 0x29fc9735, 0xa9dbf84a, 0xf204aad4, 0x7d2cd0da, 0x1bec9d27, 0x7631a6fd, 0xfb3b3591, 0x1c966394, 0x421126db, 0x1ffefe71, 0x4033cfb9, 0x8d0a936c, 0xb625063b, 0x11bb9f87, 0x27b9f6c3, 0xdbf83de1, 0x3c556be4, 0x97ac7acc, 0x885284bd, 0x99e91b3a, 0xe4c5cbe0, 0x54d047ef, 0xa0e4670f, 0x8617e54b, 0x90d6847f, 0x74134f9f, 0xfe632240, 0x75593b18, 0x4421acef, 0x8a706ddf, 0x52e0cddb, 0x093f9f45, 0xb0158c0f, 0x0d2dfc13, 0x5bdf529e, 0xd2c7a2a4, 0x7874c70b, 0xc15ed441, 0x7e444d3f, 0xce51c130, 0x7c66a45d, 0x2ca480e4, 0xf02643b6, 0xe8a24374, 0xf34ede53, 0x5e87454f, 0x93be199a, 0x8f287a0e, 0x777bd27a, 0x1ddc1713, 0x3a65e1d0, 0xc54cb717, 0x60f0c7c9, 0x2a940ad0, 0xc6242af2, 0x4603458d, 0x7b1c5aee, 0xb86067cd, 0x80276f7f, 0x9fd9910e, 0x958e93ae, 0xcc732852, 0xbe50edf9, 0x0b1d7627, 0x34208026, 0x4a64cd19, 0x919cf0f8, 0x857f78ae, 0x6fffd2b8, 0xb54d9bde, 0xdab24966, 0xb237656d, 0x68852c0b, 0xe9e837f3, 0x3032e370, 0xd38dd623, 0x4749310a, 0xa6d4ed3b, 0xf75cbd05, 0x16c16134, 0xd9dad483, 0xd4f72890, 0x7a562e69, 0x9a8186df, 0x8e620e89, 0xb92a134a, 0xabf91128, 0x7223c5ab, 0x5188503e, 0xddc8b7d5, 0x36026944, 0xe19ddc31, 0x0e4561f6, 0x793eb38c, 0x4e76ae4f, 0xa1ae1388, 0xf616c982, 0x96e60e4b, 0x15a9fcd1, 0x00000000, 0xf16c3731, 0xe6e72282, 0x98a36fbd, 0xe58fbf67, 0xca43a266, 0x12d30262, 0x0a5702a0, 0x178b15b3, 0x62d22eab, 0x84350c29, 0x7f0e39b8, 0x4846247b, 0x456bd868, 0x59fdbbfc, 0x317897f7, 0x335a7e95, 0xe7ad5605, 0xaea106f9, 0xc014a0c6, 0x20c30870, 0x66c04dfd, 0x384708b2, 0xf919dcf3, 0x3e778286, 0x0c678894, 0x58b7cf7b, 0xcf1bb5b7, 0xdc82c352, 0xbb08fa28, 0x24d16b26, 0x92f46d1d, 0xafeb727e, 0x65a8d018, 0x4b2eb99e, 0x56f2ae8d, 0xa38cfaea, 0x8b3a1958, 0x5a952619, 0x06308a34, 0x9bcbf258, 0x28b6e3b2, 0xba428eaf, 0x077afeb3, 0xdfea5eb7, 0xd890a004, 0xbc72049b, 0xb407ef59, 0xf853a874, 0xb37d11ea, 0x26f38244, 0x5ca5ac2d, 0x3f3df601, 0x559a3368, 0xf57e5467, 0x69cf588c, 0xadc99b1c, 0xd5bd5c17, 0xa4f60459, 0x1eb48af6 +}, +{ +0x4703ce77, 0x71b0a5fd, 0x9c33911a, 0xacc4285b, 0xadd374f5, 0xb991459c, 0xfa6ab266, 0x07538e65, 0x453a6983, 0xbba8e268, 0xda2703c3, 0x2609636e, 0xdf4d2a52, 0x03abb7e8, 0x4269e7e6, 0x23e6064d, 0x7022b5e1, 0xb8035580, 0xd81ea437, 0xca184795, 0xdaa24f71, 0xef3fdfa1, 0xebc7e62c, 0x70a7f953, 0xaa05b622, 0x268c2fdc, 0xdb305f6d, 0x9be553cd, 0x8acd4b35, 0xafead301, 0x66dc6fce, 0x6659237c, 0xbc7e20bf, 0x7135e94f, 0xfe17c759, 0xa8b95d64, 0x98cba897, 0x22741651, 0x7666672a, 0xfd393c03, 0x8b5f5b29, 0xec946849, 0x67cb3360, 0x745fc0de, 0xf8531592, 0xfdbc70b1, 0xb8861932, 0x9cb6dda8, 0xddf1c114, 0x54973dc9, 0x324b5207, 0x8f222e16, 0x07d6c2d7, 0x9af20f63, 0xcd4bc9f0, 0xc821e061, 0x729e5ea7, 0x618fe1ab, 0xe8e91d76, 0x64e5c83a, 0x6577d826, 0xb914092e, 0xbabfbec6, 0x335c0ea9, 0xcb8a5789, 0xfaeffed4, 0x64608488, 0xbdec30a3, 0x1206e3a2, 0x1311bf0c, 0x271e3fc0, 0xaf6f9fb3, 0xdbb513df, 0x9e8f7a5c, 0x23634aff, 0x00000000, 0x02bceb46, 0xe9fe41d8, 0x32ce1eb5, 0x6098bd05, 0x89e3b06f, 0xeeadcfbd, 0x8d1b89e2, 0xaa80fa90, 0x8e3572b8, 0x359d90d0, 0x442d352d, 0x348acc7e, 0x3518dc62, 0xdc63d108, 0x103f4456, 0xa92b4d78, 0x167b969d, 0x601df1b7, 0x41471cbc, 0x42ecab54, 0x11ad544a, 0x506f0444, 0x99dcf439, 0xea55f630, 0x9f1d6a40, 0x51fd1458, 0x461492d9, 0xdfc866e0, 0xdce69dba, 0x730c4ebb, 0x75cdd0c2, 0x52d3ef02, 0xc9b3f07d, 0x14c77ddb, 0xdedf3a4e, 0x14423169, 0x9e0a36ee, 0xce6532aa, 0x37a43724, 0xed8334e7, 0xf8d65920, 0x032efb5a, 0xed067855, 0x2430c49a, 0xcee07e18, 0xab97a63e, 0x73890209, 0x00854cb2, 0x62245643, 0xcf726e04, 0x340f80cc, 0x25a2d486, 0xbec2cbf9, 0x53c4b3ac, 0xbd697c11, 0xbcfb6c0d, 0xae78c31d, 0x06c19e79, 0x9a7743d1, 0x31e0e5ef, 0xd89be885, 0xbb2daeda, 0xeb42aa9e, 0x8fa762a4, 0xa83c11d6, 0x047d753f, 0x04f8398d, 0xf944493c, 0x3072f5f3, 0x16feda2f, 0x88f4ecc1, 0x478682c5, 0x33d9421b, 0x57b9c693, 0x77713b84, 0x8d9ec550, 0x40d50ca0, 0xca9d0b27, 0x5341ff1e, 0xcc5c955e, 0x8871a073, 0xde5a76fc, 0x20c8fd17, 0xbe47874b, 0x0239a7f4, 0xfbf8a27a, 0x5256a3b0, 0xaefd8faf, 0xab12ea8c, 0x279b7372, 0xac4164e9, 0xec1124fb, 0x562bd68f, 0x62a11af1, 0x8bda179b, 0xc936bccf, 0x37217b96, 0x984ee425, 0x9d24cdb4, 0xff85d745, 0x36362738, 0x17e98681, 0x56ae9a3d, 0x0192101c, 0x65f29494, 0x8966fcdd, 0x36b36b8a, 0xff009bf7, 0x55806167, 0x1394f3be, 0x41c2500e, 0xf9c1058e, 0x01175cae, 0x8eb03e0a, 0x43fbf7fa, 0x056a2991, 0x24b58828, 0xcb0f1b3b, 0xccd9d9ec, 0x721b1215, 0x8a480787, 0xa9ae01ca, 0x5412717b, 0x610aad19, 0x15556dc7, 0xead0ba82, 0xba3af274, 0x8c0cd54c, 0x9da18106, 0xfe928beb, 0xad563847, 0x437ebb48, 0x9b601f7f, 0xbfd59757, 0x8c8999fe, 0x0644d2cb, 0x204db1a5, 0x63330aed, 0xe97b0d6a, 0x9959b88b, 0x4691de6b, 0x517858ea, 0x44a8799f, 0x75489c70, 0x40504012, 0x112818f8, 0xfb7deec8, 0xfc2e60ad, 0x25279834, 0x22f15ae3, 0xdd748da6, 0xd909f899, 0xefba9313, 0x10ba08e4, 0x50ea48f6, 0x215aed0b, 0x3165a95d, 0xe86c51c4, 0x30f7b941, 0x74da8c6c, 0x1283af10, 0xcdce8542, 0x176cca33, 0xbf50dbe5, 0xfcab2c1f, 0xc8a4acd3, 0xcff722b6, 0xd98cb42b, 0x9f9826f2, 0x573c8a21, 0x76e32b98, 0x45bf2531, 0xee28830f, 0x63b6465f, 0x21dfa1b9, 0x55052dd5, 0x77f47736, 0x674e7fd2, 0x15d02175, 0x05ef6523 +}, +{ +0x201423a4, 0x25392b8c, 0x2083dd10, 0x6fbbb2cf, 0x4f386fdf, 0x9426fcee, 0xa38a4eea, 0x7e2bc296, 0xbf8ed067, 0xd61d8351, 0x7ebc3c22, 0xc1a512f1, 0xf3b35669, 0x581700cb, 0xa31db05e, 0x47167797, 0x318453fd, 0x9c9f1a12, 0x4faf916b, 0x413e966e, 0x5e3fe132, 0x6a014453, 0xaba456a2, 0x192996a5, 0x1c936039, 0x5880fe7f, 0x1a2c7f74, 0x830993fa, 0x8d0f6a4b, 0xb9a6319e, 0xa630b876, 0xae895e8a, 0xd3308b79, 0x12959988, 0x910bf4c6, 0xe99f291d, 0x7605dade, 0xa5a2af13, 0xad1b49ef, 0x6904ad82, 0xb18829d6, 0x99b2123a, 0x94b1025a, 0x7803236f, 0xe126cfe1, 0x0305e9d1, 0x5b12e91a, 0xfd22516c, 0x142a86c5, 0x800c7a2b, 0x39aa4bb5, 0xa83641c7, 0x5dadf657, 0x85b68cb7, 0xec25df81, 0xdb896d85, 0x32164498, 0xcca60291, 0xf50c4924, 0x9a20055f, 0x11907059, 0x3281ba2c, 0x920e1d17, 0xbaa3d84f, 0x4a1567f7, 0xc2a0fb20, 0xa53551a7, 0xb7a0c82f, 0xad8cb75b, 0xae1ea03e, 0x6407bde2, 0x082e1848, 0x9ab7fbeb, 0x809b849f, 0x0e06f9b1, 0x25aed538, 0xf021410c, 0xdd3672c8, 0x03921765, 0xd0a29c1c, 0x3a385cd0, 0xa08fa73b, 0x7500330f, 0xd5186a80, 0xd3a775cd, 0x26ab3ce9, 0x50aee637, 0x34a95bd5, 0x08b9e6fc, 0x0d031060, 0xca191ddc, 0x3c10bd29, 0x05baf69c, 0xe40bc7c9, 0x393db501, 0x1202673c, 0xbc1cc702, 0x551410ab, 0x7b91340a, 0x5d3a08e3, 0xcf3415f4, 0xefb7c8e4, 0x533cf152, 0xea9ac0cc, 0xb4a521fe, 0xd81b7ae0, 0xb11fd762, 0xcc31fc25, 0xfb9d4e21, 0x7b06cabe, 0xd58f9434, 0xd68a7de5, 0x3c87439d, 0xbf192ed3, 0xdea465ad, 0xc91cf40d, 0x839e6d4e, 0x0e910705, 0xc2370594, 0x568607ce, 0xe908d7a9, 0x9299e3a3, 0xbc8b39b6, 0x3113ad49, 0x9f9af3c3, 0xe49c397d, 0x8b278bb2, 0x69935336, 0x7894dddb, 0x0d94eed4, 0xc98b0ab9, 0x88226263, 0x44139e46, 0x448460f2, 0x5ea81f86, 0x0097feb4, 0xca8ee368, 0x1abb81c0, 0x423b7fbf, 0x06bf1f4d, 0x11078eed, 0x61bd4b7e, 0x283a3bec, 0x86b36566, 0x2e12da15, 0x622f5c1b, 0xf609a0f5, 0xd03562a8, 0x8bb07506, 0xef203650, 0xc41fe46d, 0x9723153f, 0x42ac810b, 0x2d1733c4, 0x3f1554f8, 0x70bac593, 0xf69e5e41, 0xea0d3e78, 0x97b4eb8b, 0x6a96bae7, 0xfe27b8bd, 0x88b59cd7, 0x6cbe5b1e, 0xe70e2e18, 0x4caa78ba, 0xf0b6bfb8, 0x19be6811, 0xc71a0dbc, 0x14bd7871, 0x6795aa87, 0x17b891a0, 0x5583ee1f, 0x2ba82c89, 0xa8a1bf73, 0xfb0ab095, 0xf324a8dd, 0x3f82aa4c, 0xe2b4d884, 0xa6a746c2, 0x9c08e4a6, 0x2311ca75, 0x4a829943, 0xde339b19, 0x5b8517ae, 0xba3426fb, 0xfdb5afd8, 0xb737369b, 0x53ab0fe6, 0xb28dc007, 0x8d9894ff, 0x67025433, 0x9f0d0d77, 0x49877092, 0x9925ec8e, 0x7328d2f6, 0x2e8524a1, 0x49108e26, 0x7692246a, 0x7db9d5f3, 0xf898a7f0, 0xb931cf2a, 0x37acb204, 0xb21a3eb3, 0x343ea561, 0x1f01775c, 0x0628e1f9, 0xf59bb790, 0x86249bd2, 0x28adc558, 0x7597cdbb, 0xe799d0ac, 0xe1b13155, 0xecb22135, 0x8e9d7d2e, 0x3aafa264, 0x73bf2c42, 0xc4881ad9, 0x373b4cb0, 0x41a968da, 0xe2232630, 0xb432df4a, 0xab33a816, 0xd88c8454, 0x1f9689e8, 0x0bbc0f2d, 0x62b8a2af, 0x172f6f14, 0x50391883, 0x919c0a72, 0x612ab5ca, 0x00000000, 0x5611f97a, 0x64904356, 0xf80f5944, 0x052d0828, 0x85217203, 0x6f2c4c7b, 0xc132ec45, 0xc78df308, 0xfeb04609, 0x2d80cd70, 0x2b3fd23d, 0xdda18c7c, 0x238634c1, 0x4c3d860e, 0x7d2e2b47, 0x8e0a839a, 0xa018598f, 0x47818923, 0x0b2bf199, 0xdb1e9331, 0x6c29a5aa, 0x1c049e8d, 0x263cc25d, 0x702d3b27, 0xcfa3eb40 +}, +{ +0xabe8be42, 0xfe0230b2, 0x937bc6fe, 0x00df08d2, 0xc2b6d57d, 0x87bc27a6, 0xdfa63260, 0x70691151, 0x061b5dbe, 0x7255d19c, 0x9783535f, 0x8344b207, 0x3a70b0a3, 0x6d79f64c, 0x87632f74, 0x2a90cc88, 0x16242947, 0x9cb79d05, 0xe5098a11, 0xe12e1762, 0x532edb9c, 0x5c3d88b5, 0x5ce28067, 0x76ad443d, 0x4e3e3c81, 0x95609b40, 0x45d5fa09, 0x2398c21f, 0x8c88e9fc, 0xc691480e, 0x2eb751fb, 0xeac5d1ea, 0x47363216, 0xf1ce6b49, 0x450af2db, 0x3aafb871, 0x276057be, 0x1b0bbaa3, 0x19377a6e, 0xa424e5b9, 0x02e3c81f, 0xcd7a8e86, 0x6471f8db, 0x4cddf49e, 0x664d3816, 0x09d70645, 0x19e872bc, 0x5a26d50b, 0x91470633, 0xdd9af2ad, 0x04279d73, 0xa2e0b0d5, 0x47e93ac4, 0x7d4682b5, 0xe312d7af, 0x5ede40aa, 0x10e07c2b, 0x7b82d7d9, 0x626aa565, 0xd6713425, 0xe5d682c3, 0xa6c72da6, 0x384c706e, 0x4311af65, 0x55ea8ef0, 0xd962670c, 0x95bf9392, 0x06c4556c, 0x7f7a4278, 0x28ac0c45, 0x79be1714, 0x839bbad5, 0xb2dfc42c, 0x103f74f9, 0x375f2347, 0x79611fc6, 0xcf994699, 0x412d6fa8, 0x37802b95, 0x3563e38a, 0x6f9a3e53, 0xafcf2331, 0x12dcbce6, 0xeee24c99, 0xf5e9f63a, 0x0b34ce5a, 0xa9d47e8f, 0x0d2f93e4, 0x9a73c869, 0x8e6b21e3, 0xa6182574, 0xb0e304e1, 0xf8c665de, 0x3e572dd0, 0x00000000, 0x51121b51, 0x5af9ddd9, 0x6f453681, 0xb41b9140, 0x31447ef9, 0x605665a8, 0xec018486, 0x25839fa1, 0xcf464e4b, 0xa00378ca, 0x28730497, 0x60896d7a, 0x817872ca, 0xb9eb0a76, 0x749184f0, 0x14c7e158, 0xc9821b27, 0x58c51d14, 0x2c5499e4, 0x81a77a18, 0x9c6895d7, 0x8c57e12e, 0xe1f11fb0, 0xd44df4e8, 0x1dcfefcf, 0x9e54551a, 0x91980ee1, 0x8a93b442, 0x41f2677a, 0xdd45fa7f, 0xdb5ea7c1, 0x023cc0cd, 0xecde8c54, 0x7d998a67, 0x70b61983, 0x975c5b8d, 0x62b5adb7, 0x04f895a1, 0x3e882502, 0x48fa69ed, 0xe8f91127, 0x55358622, 0xfc3ef07f, 0xe7ea420e, 0x1f2c27d0, 0xcb61d338, 0xadf3e3fc, 0xfafaa513, 0xd6ae3cf7, 0x319b762b, 0xd289a184, 0xea1ad938, 0x53f1d34e, 0xc269ddaf, 0xf32da356, 0x698163ed, 0xbd139fd7, 0xbff057c8, 0xf7d536f7, 0xbbd7cabb, 0xab37b690, 0x984f08a4, 0x64aef009, 0x0df09b36, 0x1418e98a, 0x3c6bed1d, 0xd9bd6fde, 0x9e8b5dc8, 0x0f135329, 0xc4ad88c3, 0x1bd4b271, 0xd492fc3a, 0xbdcc9705, 0xcda58654, 0xc0551d62, 0x7fa54aaa, 0xf70a3e25, 0x7b5ddf0b, 0xe7354adc, 0xaf102be3, 0x6da6fe9e, 0xfa25adc1, 0xad2ceb2e, 0xf111639b, 0x4825613f, 0x35bceb58, 0x9aacc0bb, 0xc64e40dc, 0x16fb2195, 0xc95d13f5, 0xdb81af13, 0x8a4cbc90, 0xb6f8595f, 0x3cb4e5cf, 0xa90b765d, 0x855fefb9, 0xb200ccfe, 0xe82619f5, 0x0bebc688, 0x09080e97, 0x8eb42931, 0x3378be34, 0x93a4ce2c, 0x255c9773, 0x570946ef, 0xf536fee8, 0xb93402a4, 0xc4728011, 0x217b0a00, 0x4c02fc4c, 0x88af748f, 0xf8196d0c, 0x1203b434, 0x2347cacd, 0x669230c4, 0x728ad94e, 0x33a7b6e6, 0x1ff32f02, 0xa0dc7018, 0x1d10e71d, 0xee3d444b, 0x4a19a1f2, 0xa23fb807, 0xe3cddf7d, 0x88707c5d, 0xc08a15b0, 0x4ac6a920, 0x43cea7b7, 0x581a15c6, 0x695e6b3f, 0x389378bc, 0xd256a956, 0xb627518d, 0x51cd1383, 0xd0b56149, 0xa4fbed6b, 0xb4c49992, 0x57d64e3d, 0x76724cef, 0x6b62abf2, 0x5e014878, 0xfce1f8ad, 0x6bbda320, 0xf3f2ab84, 0xdf793ab2, 0x21a402d2, 0xbf2f5f1a, 0xcbbedbea, 0x98900076, 0x8580e76b, 0x744e8c22, 0xb03c0c33, 0x0fcc5bfb, 0x2e685929, 0xbb08c269, 0x27bf5f6c, 0xd06a699b, 0x4ee13453, 0xfedd3860, 0x2c8b9136, 0x2a4fc45a +}, +{ +0xc52facfd, 0x6047ba2c, 0xce9cdbff, 0x345ed9fa, 0x34e22702, 0xc781fc67, 0x537a72cf, 0xcb516d13, 0x0212ae62, 0x53c67b58, 0xc52f5b92, 0xfa7efcfd, 0x94fb8ea8, 0x02ae509a, 0xc9ff3d89, 0x62e91dd9, 0xa568e1be, 0x9a85b829, 0x6255e321, 0xabaadea8, 0x3fed5997, 0xab16d73f, 0x51d4d53a, 0x982b1fdc, 0xabaa29c7, 0x3832b676, 0xa7c6464b, 0x3a9ce6ec, 0xcbed6484, 0x9ff40752, 0xaedb61d3, 0x9655de32, 0xa019a9aa, 0x00bcfef8, 0x312f6681, 0x31936f16, 0x0571bf7b, 0x53c68c37, 0x5db84dd9, 0xf3df259d, 0xcb519a7c, 0xfda1131c, 0x3d43fe62, 0xc05e1386, 0x6255144e, 0x65360557, 0x333d3f8c, 0xac753149, 0x541963d6, 0x3a20ef7b, 0x67245c5a, 0x560bcdb4, 0x9a39b1be, 0x5faae3bb, 0xa2b70e5f, 0xcbed93eb, 0x5faa14d4, 0xc2f0431c, 0x07df188e, 0x9de65e5f, 0x0e7ec1ee, 0x00000000, 0xc0e21a11, 0x51d42255, 0xff0fb4e9, 0x9447873f, 0x6c972b58, 0x0bb3806d, 0x5d04444e, 0x0000f76f, 0x9ff4f03d, 0xc0e2ed7e, 0x31939879, 0x6c2bd5a0, 0xab162050, 0x07631119, 0xacc9cfb1, 0x9897e124, 0xa5d41f46, 0xf3dfd2f2, 0xfd1dede4, 0xa77ab8b3, 0x0ec2c879, 0x3f515000, 0x93246149, 0x56b7c423, 0x6c2b22cf, 0x93249626, 0x34e2d06d, 0x54a56a41, 0xcc328b65, 0xa5d4e829, 0xacc938de, 0xf86ca5f0, 0x5a675557, 0xf6ae6d89, 0x9897164b, 0xa0a55752, 0xf1cd8bff, 0xc05ee4e9, 0xf6129371, 0x9136cf2b, 0xa20b07c8, 0x364c80f7, 0x9de6a930, 0x9f48f9aa, 0x69e69423, 0x388ebfe1, 0xc24c4a8b, 0x3a9c1183, 0x5168dcad, 0x6798a2a2, 0xc943c371, 0x6e397bc2, 0x3dfff7f5, 0x05cd4183, 0x560b3adb, 0x0cd0661b, 0x94477050, 0x918ac6bc, 0xff0f4386, 0x0cd09174, 0x982be8b3, 0x36f08960, 0xf363db65, 0x6536f238, 0x91363844, 0x00bc0997, 0xffb3bd7e, 0x939868de, 0x60fbb3bb, 0xf612641e, 0xf8d0ac67, 0xc5935205, 0x94fb79c7, 0x96e9d7a5, 0x0bb37702, 0x69e6634c, 0xce9c2c90, 0xae676844, 0x09a1d960, 0xf3632c0a, 0xf1717507, 0xf6ae9ae6, 0x9a854f46, 0x0b0f89fa, 0xc2f0b473, 0x60fb44d4, 0x9d5aa0a7, 0xc73d029f, 0x51682bc2, 0x3dff009a, 0x0c6c6f8c, 0x5875fb35, 0x658a0cc0, 0xfda1e473, 0x5adb5cc0, 0xfac2f56a, 0x695a9db4, 0xae679f2b, 0x9f480ec5, 0x3d43090d, 0x3a201814, 0xf400ca7c, 0x36f07e0f, 0x5f16ea2c, 0x38324119, 0x5adbabaf, 0xf86c529f, 0x9655295d, 0xfa7e0b92, 0x537a85a0, 0xa2b7f930, 0xc943341e, 0xa7c6b124, 0xa9048e32, 0xc24cbde4, 0xf1718268, 0x6b48c4b9, 0x679855cd, 0xcc8e759d, 0xa77a4fdc, 0x62e9eab6, 0xa0195ec5, 0x3f51a76f, 0xce20d268, 0x658afbaf, 0x918a31d3, 0x333dc8e3, 0x345e2e95, 0x091d2798, 0xa9b887a5, 0x05cdb6ec, 0xa20bf0a7, 0xa9b870ca, 0x5f161d43, 0xc593a56a, 0x3381c174, 0x0763e676, 0x0ec23f16, 0xcc8e82f2, 0x6b4833d6, 0x312f91ee, 0x3381361b, 0xc9ffcae6, 0xffb34a11, 0xf1cd7c90, 0x54a59d2e, 0x0e7e3681, 0xf4003d13, 0x60474d43, 0x56b7334c, 0x9d5a57c8, 0x09a12e0f, 0x05714814, 0xfac20205, 0x6724ab35, 0xa0a5a03d, 0x364c7798, 0x0c6c98e3, 0x58c905cd, 0xa56816d1, 0xc73df5f0, 0xc7810b08, 0xcc327c0a, 0x07dfefe1, 0x6e85853a, 0xf4bc3484, 0x6c97dc37, 0x96e920ca, 0x58750c5a, 0x3fedaef8, 0x388e488e, 0x695a6adb, 0x6e398cad, 0xa904795d, 0xac75c626, 0xce202507, 0xf8d05b08, 0x93989fb1, 0x091dd0f7, 0x6bf4cd2e, 0x0b0f7e95, 0x5db8bab6, 0x5d04b321, 0x6e857255, 0x6bf43a41, 0xaedb96bc, 0x58c9f2a2, 0xfd1d1a8b, 0x541994b9, 0x5a67a238, 0x9a3946d1, 0x02aea7f5, 0xf4bcc3eb, 0x0212590d +}, +{ +0x4ad05a61, 0x19abda8c, 0x2279d6da, 0xbb2c7dca, 0xe9c37f45, 0xc1757fe5, 0x63f2d8a3, 0xeb0bffae, 0x0acfd67a, 0x6ada4ef5, 0xf0d3e76c, 0xf8d4b1fd, 0x40a4cebe, 0x9b26695e, 0x13640cf6, 0xc85de9b3, 0x2bea0229, 0x3afdcc91, 0x22c2947f, 0x280d4205, 0x200a1494, 0x52ef028f, 0xabaf3110, 0xe17f6b71, 0x93213fcf, 0xf2a02522, 0x69864c7c, 0xd2117313, 0x81d1b15b, 0xb204eb9c, 0x1117ceb8, 0x90c67fe3, 0x5a5316bb, 0x8a8ae543, 0xa967b1fb, 0x62dd1864, 0xd865e7cc, 0x80453339, 0x62665ac1, 0x7bcd804d, 0x02c880eb, 0xea243f69, 0x7ae2408a, 0x987a6bd7, 0xc2923fc9, 0x38354c7a, 0x23ed54b8, 0x10834cda, 0xf068a5c9, 0xca956958, 0x01948262, 0x10380e7f, 0x1a4c9aa0, 0x828db3d2, 0xd8dea569, 0x0993d4f3, 0x8ba52584, 0x43f8cc37, 0x12f08e94, 0xf21b6787, 0x418b0e79, 0xf86ff358, 0x41304cdc, 0x89d6e7ca, 0xfb33f1d1, 0x61811aed, 0x816af3fe, 0x1af7d805, 0x5254402a, 0x13df4e53, 0x83a27315, 0x50278264, 0xa04f27ad, 0x0a7494df, 0x3a468e34, 0xd33eb3d4, 0x907d3d46, 0xe8ecbf82, 0xb8cb3de6, 0x4818da8a, 0x5bc794d9, 0xfa1c3116, 0x00bb42a5, 0xb8707f43, 0xa1dba5cf, 0x31a69889, 0xaa3bb372, 0xd385f171, 0x790500a6, 0x11ac8c1d, 0x725e54be, 0xf940339f, 0xd9f165ae, 0xa287a746, 0xe0ebe913, 0x789182c4, 0xc2297d6c, 0x48a3982f, 0x426c4e55, 0xcbbaa99f, 0x589b9650, 0xcb01eb3a, 0x6015988f, 0x09289656, 0x9152fd81, 0x63499a06, 0x884265a8, 0xa3a86781, 0xc1ce3d40, 0x391a8cbd, 0x2356161d, 0x08075691, 0x7b76c2e8, 0x7096d455, 0x5820d4f5, 0xdb39e545, 0x73cad6dc, 0xc05abf22, 0xebb0bd0b, 0x18841a4b, 0x012fc0c7, 0x4b44d803, 0x71025637, 0xc3bdff0e, 0xab1473b5, 0x00000000, 0x2a7e804b, 0x6b4ecc97, 0xd14d719a, 0xa3132524, 0x183f58ee, 0x88f9270d, 0x72e5161b, 0x6bf58e32, 0x39a1ce18, 0xe3b7eb9a, 0xe050abb6, 0x537b80ed, 0x831931b0, 0xaa80f1d7, 0x79be4203, 0x0273c24e, 0x6812ce1e, 0x33d55ac7, 0x6a610c50, 0x782ac061, 0xa0f46508, 0x939a7d6a, 0x4a6b18c4, 0x1b635a67, 0x99eee9b5, 0x9b9d2bfb, 0x9955ab10, 0x4bff9aa6, 0xbab8ffa8, 0xca2e2bfd, 0xf9fb713a, 0x9ab2eb3c, 0x9a09a999, 0xd2aa31b6, 0xa8f33399, 0xb07729d2, 0x8236f177, 0xf1fc27ab, 0xe30ca93f, 0x30321aeb, 0x702d96f0, 0x60aeda2a, 0x590f1432, 0x3241d8a5, 0x0be016bd, 0x91e9bf24, 0xc9722974, 0xc9c96bd1, 0xfaa773b3, 0x68a98cbb, 0x53c0c248, 0x1bd818c2, 0xf38fe5e5, 0xa160e76a, 0x28b600a0, 0x43438e92, 0xdaad6727, 0x219e96f6, 0x388e0edf, 0xea9f7dcc, 0xba03bd0d, 0xd062b15d, 0xb2bfa939, 0x2999c067, 0x3089584e, 0x613a5848, 0xc306bdab, 0xa9dcf35e, 0xe857fd27, 0x19109829, 0x3bd20c56, 0xb39069fe, 0x510842a3, 0xf147650e, 0x7a59022f, 0xbb973f6f, 0x401f8c1b, 0x693d0ed9, 0xda162582, 0x80fe719c, 0xe1c429d4, 0x51b30006, 0x3b694ef3, 0x32fa9a00, 0x8a31a7e6, 0x292282c2, 0x8b1e6721, 0x5b7cd67c, 0xe2982b5d, 0xc0e1fd87, 0x0b5b5418, 0xb158e915, 0xb0cc6b77, 0xa23ce5e3, 0x98c12972, 0x5ae8541e, 0xf334a740, 0xa848713c, 0x2b51408c, 0x49371a4d, 0xb1e3abb0, 0xb95fbf84, 0x336e1862, 0x498c58e8, 0xd0d9f3f8, 0x59b45697, 0x73719479, 0xb9e4fd21, 0x124bcc31, 0x42d70cf0, 0x2ac5c2ee, 0x311dda2c, 0xb32b2b5b, 0x509cc0c1, 0x03e7402c, 0x20b15631, 0x920eff08, 0xd1f6333f, 0x2125d453, 0xfb88b374, 0x896da56f, 0x035c0289, 0xe9783de0, 0x08bc1434, 0x71b91492, 0xc8e6ab16, 0xe22369f8, 0xdb82a7e0, 0x92b5bdad, 0xd94a270b +}, +{ +0x3005d60a, 0x67b84649, 0xb973fe6e, 0x61255d0f, 0x1ee1a772, 0x3dedb223, 0x713f686d, 0x42d03f0e, 0xc3c09e3c, 0x7a4a1702, 0x0b757f6f, 0x156daf4d, 0x71c61f3d, 0xb98a893e, 0x6fdecf1f, 0x5aac833a, 0x6f27b84f, 0x5744e713, 0x0e02e540, 0x898f5f34, 0x2682f82e, 0xf3c54836, 0x92196269, 0x33ef5763, 0xaa7a3d35, 0x57bd9043, 0x23f56201, 0xfed45b4f, 0x2b6a9c07, 0x72d5e904, 0x00f97750, 0xd547b018, 0x7448f242, 0xe3260a04, 0x28796a3e, 0xfe2d2c1f, 0x16872e24, 0x976ef846, 0x2e1d0628, 0x8774cd24, 0xc5a4f22a, 0xb2068101, 0xc8b5e153, 0xa10f425a, 0x99956a56, 0x06646c16, 0x187cbc34, 0xed24ef44, 0xfb5ab630, 0x495c3731, 0x6943d459, 0x77a2732b, 0x3698cd4c, 0x44b45318, 0x67413119, 0x97978f16, 0x7ab36052, 0x33162033, 0x79a0966b, 0x8a9ca90d, 0x9ff10640, 0x358b3b75, 0x6c344e76, 0x51208b05, 0x3b70a965, 0x20e69438, 0xf8494009, 0xeece6e2d, 0xcd3b0c2c, 0x5457112a, 0xc0d36805, 0x9f087110, 0xd0c95d67, 0x7959e13b, 0x7f3d8d2d, 0xfdc7ad76, 0xf0d6be0f, 0x81e9d662, 0xced18d45, 0xb49b9a47, 0xcba6176a, 0x9a7feb3f, 0x74b18512, 0x722c9e54, 0x413abe67, 0x069d1b46, 0xce28fa15, 0x0d111379, 0x84673b1d, 0x9c1b8729, 0x52337d3c, 0x267b8f7e, 0x389a280c, 0xa792591c, 0x9484792f, 0xe5426612, 0x4229485e, 0x0313f639, 0x4a4fc108, 0xb2fff651, 0xfba3c160, 0x8110a132, 0xaff4d04a, 0xe3df7d54, 0x91f3e300, 0xf5a12420, 0xbfeee528, 0x230c1551, 0x1df2514b, 0xba997f07, 0xcdc27b7c, 0x2df78741, 0x878dba74, 0xd5bec748, 0x5a55f46a, 0x10e34232, 0x61dc2a5f, 0x5c31987c, 0xf02fc95f, 0x1b963d5d, 0x6aa95530, 0x62cfdc66, 0xa2e5c333, 0xa969cb0c, 0x3d14c573, 0x201fe368, 0xb1157738, 0x058eed7f, 0x89762864, 0xe035fc3d, 0xc84c9603, 0xa481af25, 0x54ae667a, 0x0b8c083f, 0xe5bb1142, 0x8feb3322, 0xa478d875, 0x03ea8169, 0x1d0b261b, 0x101a3562, 0x775b047b, 0xdb455558, 0x444d2448, 0x92e01539, 0x82fa205b, 0x8203570b, 0x8cf8c51b, 0x0de86429, 0xb462ed17, 0x6a502260, 0x089ffe06, 0x1b6f4a0d, 0x4c2bad1e, 0x1885cb64, 0x996c1d06, 0xb7886c7e, 0x6ccd3926, 0xac1e5123, 0x2ee47178, 0xcb5f603a, 0x35724c25, 0xb1ec0068, 0x4f385b27, 0xc339e96c, 0xf33c3f66, 0x3b89de35, 0xd856a361, 0xbcfd1311, 0xaf0da71a, 0x7cd70c44, 0xa1f6350a, 0x47a7a521, 0xf6b2d219, 0x910a9450, 0xace72673, 0x30fca15a, 0xb7711b2e, 0x475ed271, 0xaa834a65, 0x3e07334a, 0x6236ab36, 0xf8b03759, 0xc64e7343, 0x00000000, 0xe0cc8b6d, 0xdbbc2208, 0x13f0b40b, 0x51d9fc55, 0xba600857, 0x9ce2f079, 0x6452c720, 0x3efe441a, 0x5f226e45, 0x64abb070, 0xe8aa023b, 0x1e18d022, 0xdecbb827, 0x05779a2f, 0x7c2e7b14, 0xebb9f402, 0x59bf7503, 0x2d0ef011, 0xd8afd431, 0x3661ba1c, 0x8f124472, 0xf64ba549, 0x25687947, 0x947d0e7f, 0x2b93eb57, 0x4ab6b658, 0xd0302a37, 0xc02a1f55, 0x41c3c937, 0xa990bc5c, 0xe853756b, 0xbc046441, 0x1594d81d, 0xfd3eda26, 0x849e4c4d, 0xc55d857a, 0x8a65de5d, 0x52ca0a6c, 0xc6b70413, 0x08668956, 0xf5585370, 0xde32cf77, 0xd323dc0e, 0x5cc8ef2c, 0xbf179278, 0xa76b2e4c, 0xeddd9814, 0x167e5974, 0x59460253, 0x25910e17, 0x7fc4fa7d, 0xe651902b, 0x69baa309, 0x5fdb1915, 0xee37197d, 0x0efb9210, 0x38635f5c, 0x8c01b24b, 0x4cd2da4e, 0x49a54061, 0x9a869c6f, 0xd3daab5e, 0xd6ad3171, 0x28801d6e, 0xe6a8e77b, 0xeb408352, 0x1309c35b, 0xd6544621, 0xa21cb463, 0xdd21394e, 0x4fc12c77, 0xddd84e1e +}, +{ +0x4fbda43b, 0x37dbd8b2, 0x676acaa6, 0x34dcfb0f, 0x1a4b62f6, 0x46733bc4, 0x3a736e64, 0x68e4a23d, 0x76c9e9e2, 0xaae81e6a, 0x5d19a4c2, 0xabc9e39a, 0x00000000, 0x664b3756, 0x7c0055a0, 0x96db876a, 0x319b2fd6, 0xb96de363, 0x622d1e7f, 0xe3154d35, 0x2cb147b4, 0x7a40a2c4, 0x95dca4d7, 0x4afa70e2, 0x4334ef1d, 0xbb4b3d2e, 0x17e3d420, 0x654c14eb, 0xd4ce9587, 0xfe3f2557, 0x3f34babd, 0x030723bd, 0xc74b688e, 0x738e3d3b, 0x245e25bb, 0x4e9c59cb, 0xa56676f1, 0xb4c555b5, 0x16c229d0, 0xcca3293c, 0xafafcab3, 0x94fd5927, 0xce85f771, 0xa2077c65, 0xbd0bca4a, 0x8ad012f8, 0x70891e86, 0x5e1e877f, 0xae8e3743, 0x6da376e4, 0x9955eff1, 0xf090b03c, 0x0c894b26, 0xa8cec027, 0x0be841b2, 0x1d2a6862, 0x9c123b28, 0x50b11214, 0x585e701b, 0xdd000a78, 0x612a3dc2, 0x11a32344, 0x7f07761d, 0x6ac27c70, 0xc8c50015, 0x5b5953a6, 0x4bdb8d12, 0xe47447a1, 0xb7c27608, 0xd7c9b63a, 0xdb40fd1c, 0x20380c92, 0x07610a94, 0x221ed2df, 0xf87fd233, 0xa661554c, 0x646de91b, 0xa4478b01, 0x8138534a, 0xeadbd2ca, 0x88f6ccb5, 0x97fa7a9a, 0xa740a8bc, 0xc56db6c3, 0x5a78ae56, 0x6ea45559, 0x79478179, 0xe9dcf177, 0x8c90e59c, 0xedbad85e, 0x2e9799f9, 0xd3af9f13, 0x7e268bed, 0xf7f1baa8, 0x0547d4d9, 0x4d9b7a76, 0x939c53b3, 0x72afc0cb, 0x35fd06ff, 0xe773641c, 0xe65299ec, 0x0ac9bc42, 0xba6ac0de, 0x28d76e9d, 0xb6e38bf8, 0x186dbcbb, 0xf2b66e71, 0x91ba8dfe, 0xb84c1e93, 0xbe0ce9f7, 0x5f3f7a8f, 0xe1339378, 0x909b700e, 0x92bdae43, 0x2d90ba44, 0xa9ef3dd7, 0xb0a37c9c, 0xcbc223a8, 0x2678fbf6, 0x0da8b6d6, 0x98741201, 0xd28e62e3, 0x2af1b0d0, 0x15c50a6d, 0x27590606, 0x0eaf956b, 0x257fd84b, 0x421512ed, 0x4455e589, 0x4752c634, 0xb5e4a845, 0xb285a2d1, 0x233f2f2f, 0xa021a228, 0x09ce9fff, 0xcfa40a81, 0x71a8e376, 0x855e7a63, 0x6be38180, 0xe555ba51, 0x29f6936d, 0xb3a45f21, 0xc44c4b33, 0xfc19fb1a, 0xd5ef6877, 0x3c339900, 0x8eb63bd1, 0xff1ed8a7, 0x9b7331bc, 0x48dcaeaf, 0xd0a8bcae, 0x1f0cb62f, 0xc02a621a, 0x08ef620f, 0xad8914fe, 0xe8fd0c87, 0xebfa2f3a, 0xd847dea1, 0x45741879, 0x12a400f9, 0xaca8e90e, 0x77e81412, 0x9f151895, 0xc66a957e, 0x3d1264f0, 0x6c828b14, 0x54d73b3d, 0xfd3806ea, 0xb182816c, 0x36fa2542, 0xf3979381, 0x55f6c6cd, 0xd9662351, 0x600bc032, 0x6f85a8a9, 0x5297cc59, 0x8bf1ef08, 0x1385fd09, 0xde0729c5, 0x2fb66409, 0x5c385932, 0x39744dd9, 0xf1b14dcc, 0xa1005fd8, 0x630ce38f, 0x9d33c6d8, 0xdf26d435, 0x4033cca0, 0x14e4f79d, 0xcd82d4cc, 0xef9c0613, 0xf4f69915, 0x33bdf19b, 0x4cba8786, 0xfa590c7e, 0x1c0b9592, 0x49fd535f, 0x7b615f34, 0xeebdfbe3, 0x831e8d07, 0xc20cbc57, 0x30bad226, 0x5190efe4, 0x8778a42e, 0xd189415e, 0xf6d04758, 0xe0126e88, 0x0f8e689b, 0x1b6a9f06, 0x2119f162, 0xbf2d1407, 0xf95e2fc3, 0x41123150, 0x194c414b, 0x04662929, 0x0121fdf0, 0xe234b0c5, 0x9e34e565, 0xf5d764e5, 0x78667c89, 0xc10b9fea, 0x8f97c621, 0x3b529394, 0x89d73145, 0x3e15474d, 0xd6e84bca, 0x56f1e570, 0x1e2d4bdf, 0x7d21a850, 0xdc21f788, 0x69c55fcd, 0xcae3de58, 0x3855b029, 0x847f8793, 0x865959de, 0xc9e4fde5, 0xc32d41a7, 0x8019aeba, 0xbc2a37ba, 0x8db1186c, 0x597f8deb, 0xfb78f18e, 0x2bd04d20, 0x74ef37af, 0x329c0c6b, 0xec9b25ae, 0x57d01880, 0x9a52cc4c, 0x0226de4d, 0x1082deb4, 0x823f70f7, 0x53b631a9, 0xa3268195, 0xda6100ec, 0x0640f764, 0x75ceca5f +} +}, +{ +{ +0x0c3cb63b, 0xc2a91b62, 0xeed0f44e, 0x9265e47a, 0xf67cf24f, 0x8b336d67, 0x88f77385, 0x6be1beec, 0x876cfb77, 0x2fded1e5, 0xe28f625e, 0x0063202b, 0x15091f0d, 0x227bc8e9, 0x732e98c6, 0x734db8ed, 0x7f122efd, 0x18ac0601, 0x7cb51034, 0x1b6818e3, 0x52f26ee6, 0x0e0227c5, 0x9d9d4ca3, 0xd65a8b73, 0x93fc4b4d, 0x5f3457c1, 0xd4073aa6, 0x354c461a, 0x2218e8c2, 0xe316cd69, 0x7f710ed6, 0x1490b03a, 0xef2a7b52, 0xab15145b, 0x71732913, 0xd858acb6, 0xecee65b0, 0x72b737f1, 0x1a9297ff, 0xc2ca3b49, 0x2e245ef9, 0xa729a260, 0xc10e25ab, 0x38e95f16, 0x870fdb5c, 0x0199af37, 0x1935a936, 0xccab3ca7, 0x5f5777ea, 0xf81df5a1, 0xda663d48, 0xbe1c0b56, 0xa6b00d57, 0x7d2cbf03, 0x67dd08d7, 0xd59e9591, 0x5d69e614, 0x890dfc99, 0xfbbacb68, 0x03a73ec9, 0xb1e4a38f, 0xc16d0580, 0xb07d0cb8, 0x8ac9e27b, 0xab763470, 0x1754aed8, 0x0e6107ee, 0x17378ef3, 0x4a3d48cc, 0xf9e77abd, 0xcd51b3bb, 0x91c2dab3, 0x6580b902, 0x2c1acf07, 0x2026793c, 0xbdbb359f, 0xdbff927f, 0x34b6c906, 0xf87ed58a, 0xcf6f2245, 0xa48e9ca9, 0x025db1d5, 0x67be28fc, 0x368858f8, 0x1b0b38c8, 0xa8b22a92, 0xb220bd6d, 0x91a1fa98, 0x939f6b66, 0x9c04e394, 0x5eced8dd, 0x662787cb, 0xf44263b1, 0x70ea8624, 0x7089a60f, 0xa74a824b, 0x64191635, 0xa6d32d7c, 0xccc81c8c, 0xe2ec4275, 0x9fc0fd76, 0xb2439d46, 0xfa404474, 0x0da5190c, 0xd5fdb5ba, 0x23e267de, 0xf421439a, 0x45a6c03e, 0xb01e2c93, 0x52914ecd, 0xf5dbcc86, 0x69df2f12, 0x905b7584, 0xe1285c97, 0x65e39929, 0x4601fef7, 0xd7c32444, 0xa4edbc82, 0xe0b1f3a0, 0xec8d459b, 0x3b4e61df, 0x7e8b81ca, 0x3711f7cf, 0xcd329390, 0x2c79ef2c, 0xe14b7cbc, 0x3913d00a, 0x7ee8a1e1, 0xaaef9b47, 0x4662dedc, 0x5eadf8f6, 0x9206c451, 0xd4641a8d, 0xfa23645f, 0x3ad7cee8, 0x0ff8a8d9, 0x8696746b, 0x85526a89, 0x5cf04923, 0xaa8cbb6c, 0x86f55440, 0x45c5e015, 0x443f6f09, 0xfbd9eb43, 0x5c936908, 0xf7867d53, 0x4860f919, 0xb3da3271, 0xbf85a461, 0x47fb71eb, 0xe375ed42, 0x16ae21c4, 0x18cf262a, 0x00000000, 0xcef68d72, 0xef495b79, 0x388a7f3d, 0xa8d10ab9, 0x36eb78d3, 0xa57413b5, 0x6a1b31f0, 0x023e91fe, 0xbc41ba83, 0x49f9562e, 0x51367004, 0x2fbdf1ce, 0xd639ab58, 0x903855af, 0xbe7f2b7d, 0x5308e1fa, 0x1af1b7d4, 0xb3b9125a, 0xa92b85a5, 0x896edcb2, 0x9e3a726a, 0xbc229aa8, 0xd83b8c9d, 0x6644a7e0, 0x20455917, 0xf5b8ecad, 0xb18783a4, 0x69bc0f39, 0x499a7605, 0x536bc1d1, 0x7cd6301f, 0xc353947e, 0xf9845a96, 0xed77ca87, 0x9c67c3bf, 0x21dcf620, 0x2d836030, 0x72d417da, 0x0dc63927, 0xeeb3d465, 0x7d4f9f28, 0xf61fd264, 0xc0978a9c, 0x2e477ed2, 0x3b2d41f4, 0x34d5e92d, 0x9dfe6c88, 0xbdd815b4, 0x156a3f26, 0x1956891d, 0x6a7811db, 0x3970f021, 0xce95ad59, 0x14f39011, 0xd9a223aa, 0x84cbc5be, 0x445c4f22, 0xdb9cb254, 0xe0d2d38b, 0x3772d7e4, 0x71100938, 0x50ccff18, 0x6825a00e, 0x4a5e68e7, 0x21bfd60b, 0x352f6631, 0x16cd01ef, 0x4bc7c7d0, 0x3ab4eec3, 0xc330b455, 0x6b829ec7, 0xcf0c026e, 0x0c5f9610, 0x01fa8f1c, 0xd9c10381, 0x8b504d4c, 0x647a361e, 0x4803d932, 0x50afdf33, 0x0f9b88f2, 0x4ba4e7fb, 0x5d0ac63f, 0xc0f4aab7, 0x9e595241, 0xa948a58e, 0x03c41ee2, 0x479851c0, 0x238147f5, 0x5155502f, 0x889453ae, 0xbfe6844a, 0xd7a0046f, 0x2de0401b, 0xed14eaac, 0x9fa3dd5d, 0xda051d63, 0x68468025, 0xf7e55d78, 0xa517339e, 0x8aaac250, 0x85314aa2, 0x84a8e595 +}, +{ +0x13c0567a, 0xeebf53a7, 0x3c49f5f9, 0xace64037, 0x3f02b366, 0x93e4f351, 0x4b402238, 0xb9e6a57c, 0xf10ef0eb, 0xc4bd058a, 0xedf41538, 0x5ea3f643, 0x54f18174, 0x39c20057, 0x3fe18256, 0x4731d70e, 0x5b2803ed, 0xb357e37b, 0xe7a6620f, 0xaa26f306, 0xb6dc16d5, 0x86e4161a, 0x4ba31308, 0x95244060, 0x41f1643f, 0x361b82ce, 0x00e33130, 0x6761f614, 0x7d5ba0f6, 0xee5c6297, 0xc7f64315, 0x838cd284, 0x52d20375, 0xde875368, 0xa96db599, 0x4e28e6a6, 0xb0ff94d4, 0xceef72bd, 0x99b68466, 0xcd470512, 0x6e9bf68c, 0x58807442, 0xb574617a, 0xc7157225, 0x5412b044, 0x164ba3d4, 0xb905944c, 0x5d0b81ec, 0xbaade3e3, 0x685b45bd, 0x108b10e5, 0x3550c451, 0x2c21d42c, 0xc8ccf0bc, 0xc82fc18c, 0xf4663475, 0xb597504a, 0x7b9b13c7, 0x2050211a, 0x2cc2e51c, 0x2673a31b, 0x33734650, 0xfbbfb6ec, 0x0a527737, 0x5de8b0dc, 0xfd9c34ed, 0x6bf33212, 0xf4850545, 0x1ad967d2, 0x836fe3b4, 0xe185e00e, 0x5e40c773, 0x52313245, 0x9f763757, 0xd77d53f0, 0xc1d5c114, 0x61427415, 0x1a3a56e2, 0xe22d97a1, 0x0c71f536, 0x6782c724, 0x9a1ef3c9, 0xd436156f, 0xe745533f, 0x8a95e32c, 0xfb5c87dc, 0x5bcb32dd, 0x57bac7eb, 0xb3b4d24b, 0xe2cea691, 0x35b3f561, 0xd8a4d169, 0x106821d5, 0x966f06ff, 0xaf4e3798, 0x77eae6f1, 0x058bf5ae, 0x0568c49e, 0xf72d72ea, 0x64c981bb, 0x1f52927c, 0xcb648713, 0x42ba22a0, 0xd847e059, 0x15e3d47b, 0xa097b501, 0xe166d13e, 0x034b469f, 0xd1bde0c1, 0x7709d7c1, 0x25dbd4b4, 0xafad06a8, 0xddcc15f7, 0xcb87b623, 0x303800cf, 0x5759f6db, 0x231b6785, 0x480b64a7, 0x6d338123, 0x3a6a77f8, 0x78d05558, 0x20b3102a, 0x1fb1a34c, 0xfed77272, 0xbf26164d, 0xf245b674, 0x519945ea, 0x9afdc2f9, 0x2a02562d, 0x8024a52b, 0x6e78c7bc, 0x447a9191, 0x95c77150, 0x091931a8, 0x854c61b5, 0x7e10e669, 0xa5ff719f, 0xe40e15a0, 0x2538e584, 0x06c0b331, 0x6dd0b013, 0x03a877af, 0xc45e34ba, 0xbc6d50d2, 0x893d9483, 0x8c55501d, 0xdd2f24c7, 0x0ab14607, 0x78336468, 0x8607272a, 0xba4ed2d3, 0xa3dcf39e, 0xcda43422, 0xa33fc2ae, 0x2f89a383, 0xac057107, 0x23f856b5, 0xa51c40af, 0x16a892e4, 0x29aa2182, 0x39213167, 0x712a55c0, 0xebd79739, 0x33907760, 0x80c7941b, 0x8a76d21c, 0xbfc5277d, 0xdbef97f6, 0x74a1a06e, 0x294910b2, 0x06238201, 0x7b7822f7, 0x68b8748d, 0x6b100322, 0x62ea03ba, 0xde646258, 0x7282226f, 0x6209328a, 0x7442915e, 0x0c92c406, 0x61a14525, 0x1c19d4e3, 0x58634572, 0x8f1e1682, 0xd4d5245f, 0x48e85597, 0x4d63a039, 0xe87fe096, 0x2f6a92b3, 0x30db31ff, 0x4499a0a1, 0x9f950667, 0xb63f27e5, 0x8cb6612d, 0x642ab08b, 0xeb34a609, 0x89dea5b3, 0xbc8e61e2, 0x9307c261, 0xc136f024, 0x8ffd27b2, 0x1971107d, 0x47d2e63e, 0x1cfae5d3, 0x4d809109, 0xc27db6bb, 0xd2f6a65e, 0x2ae1671d, 0x968c37cf, 0x7db891c6, 0xf817c143, 0x42591390, 0xed172408, 0xaac5c236, 0xd15ed1f1, 0xce0c438d, 0x36f8b3fe, 0x0fd98299, 0x9955b556, 0x85af5085, 0x7261135f, 0x9cde40f8, 0xf8f4f073, 0xa6570630, 0xf7ce43da, 0x00000000, 0x0f3ab3a9, 0xe4ed2490, 0xb01ca5e4, 0x4112550f, 0x904c84fe, 0xc29e878b, 0xf1edc1db, 0x1323674a, 0x7ef3d759, 0x1500e54b, 0x3a8946c8, 0xf2a68744, 0x9c3d71c8, 0xd79e62c0, 0x71c964f0, 0xd215976e, 0xa6b43700, 0x1992214d, 0x2690922b, 0xfd7f05dd, 0x517a74da, 0x3caac4c9, 0x4ecbd796, 0x09fa0098, 0xfe344342, 0xa98e84a9, 0xa0748431, 0x90afb5ce, 0xe89cd1a6, 0xdb0ca6c6 +}, +{ +0x9ac9ea59, 0xc82875b0, 0xb74287ce, 0x37eb994d, 0x3541f273, 0xb9e4dc00, 0xdceedaa4, 0x6b64c279, 0x98d920da, 0x820375bd, 0x650a06a4, 0xaffa2684, 0xbb86282d, 0xb52073e3, 0xd2f220d7, 0x71be971e, 0xde368f34, 0x73ae5d9d, 0x46efafee, 0xf3757db0, 0x6b16fcd7, 0x5293a147, 0x393ffc2d, 0x73dc6333, 0xd248816a, 0xa15c7d4a, 0x0e6ec4dd, 0x3b5d0800, 0x5cfd659a, 0xb5e8ecf0, 0xc85a4b1e, 0x0cb6914d, 0xebbfe254, 0xc646b16d, 0x8e7d7be3, 0x5039ca79, 0x9abbd4f7, 0x80a91e83, 0x5c35fa89, 0xc892d40d, 0x375138f0, 0xf307431e, 0xf165b733, 0xe915896a, 0x71cca9b0, 0xa12e43e4, 0xb730b960, 0x7d7a38fd, 0x3b959713, 0x232d3659, 0x6768f289, 0xfdd3267e, 0xaf408739, 0x39855d90, 0x8013bf3e, 0xf1df168e, 0xf117899d, 0xe7c1ec0a, 0x96c5daa9, 0x67d25334, 0x394dc283, 0xd090d4fa, 0x239797e4, 0x3723065e, 0x8ec7da5e, 0x6bac5d6a, 0xd0e2ea54, 0x2f533807, 0x44ff656d, 0xfd1bb96d, 0x8cd710dd, 0xb78a18dd, 0x1a60f4da, 0x671acc27, 0xb92c4313, 0xca4a819d, 0x5eedaf19, 0x525b3e54, 0x0262f42d, 0xad227314, 0xfda118d0, 0x235f08f7, 0x8c1f8fce, 0x65b0a719, 0xebcddcfa, 0x7f18ccd0, 0x52e19fe9, 0x18703e59, 0xbb4eb73e, 0x00000000, 0x967f7b14, 0x9811bfc9, 0xe519b99a, 0xa38428da, 0x462730fd, 0x7dc09940, 0xff0b73ee, 0x2d43f284, 0x96b7e407, 0x98ab1e74, 0x23e5a94a, 0xe9dd1679, 0x2d31cc2a, 0x0210ca83, 0xbbf41683, 0x0ea65bce, 0x960d45ba, 0x213dfcda, 0xf3bde2a3, 0xadeaec07, 0xe5a31827, 0xd23abfc4, 0xca821e8e, 0x7176080d, 0x5e570ea4, 0x0e1cfa73, 0x0c7e0e5e, 0xc6fc10d0, 0xdc2645b7, 0x4a2b000d, 0xa3f61674, 0x483bca8e, 0xc4ecda53, 0xb5524d4d, 0x8c6db160, 0x4ae39f1e, 0xc49ee4fd, 0x4445c4d0, 0x9a734be4, 0x4849f420, 0xa33e8967, 0x0cc4afe3, 0xe5d12689, 0x80618190, 0xaf88182a, 0x522900fa, 0x0c0c30f0, 0xd02a7547, 0x1ada5567, 0xc68e2e7e, 0xb7f82673, 0x2fe999ba, 0x94d5102a, 0x82cbeaae, 0x2df95339, 0x69cea947, 0x214fc274, 0x02aa6b3e, 0xc6348fc3, 0xe7097319, 0x35896d60, 0x16a45b39, 0x3be7a9bd, 0xc8e0eaa3, 0x946fb197, 0x35fb53ce, 0x5e25300a, 0x69063654, 0x2d8b6d97, 0x50836bc4, 0x18b8a14a, 0x4437fa7e, 0xbb3c8990, 0x46550e53, 0xb59ad25e, 0x710436a3, 0xb996e2ae, 0xde44b19a, 0x504bf4d7, 0x67a06d9a, 0x1aa86bc9, 0x16d66597, 0x18ca9fe4, 0x1a12ca74, 0x4a91a1b0, 0x82714b13, 0x469d9140, 0x3b2f36ae, 0x48816b33, 0x2f2106a9, 0x7d080653, 0x697408fa, 0x2f9ba714, 0xe56b8734, 0x98638167, 0xca38bf33, 0x161efa84, 0xeb0543e9, 0x94a72e84, 0x7fa26d6d, 0xf1ad2820, 0x8eb5e4f0, 0xcaf02020, 0x180200f7, 0x8ca52e73, 0x6bde63c4, 0x7366c28e, 0xc4244540, 0xb95e7dbd, 0xaf32b997, 0x4a593ea3, 0xad504dba, 0x02d85590, 0x448d5bc3, 0x21875d67, 0x7314fc20, 0x147c0ea9, 0x50f1556a, 0xde8c2e89, 0xffc3ecfd, 0xe77b4db7, 0x82b9d400, 0x5e9f91b7, 0xe7b3d2a4, 0xdc547b19, 0x69bc97e9, 0x7f6af27e, 0xc4567bee, 0x00723eae, 0x7fd053c3, 0x3799a7e3, 0x166cc42a, 0x9a01754a, 0x3533ccdd, 0xdc9ce40a, 0xdefe1027, 0x7db2a7ee, 0x8e0f454d, 0xa1e6dcf7, 0x00c89f13, 0xd2801e79, 0x5c8f5b34, 0xfd6987c3, 0x140e3007, 0x21f563c9, 0xa194e259, 0x0ed46560, 0x14b491ba, 0xeb777d47, 0xffb1d253, 0x80db202d, 0xd0584be9, 0xa34cb7c9, 0xff794d40, 0x00baa1bd, 0xf3cfdc0d, 0x65c299b7, 0x14c6af14, 0xad98d2a9, 0xe967b7c4, 0xe9af28d7, 0x39f7633e, 0x48f3559d, 0x6578380a, 0x5c47c427, 0x941d8f39 +}, +{ +0x5e263f0f, 0xaea90829, 0x8788cf93, 0x625ed969, 0xe9d02fd4, 0x252637e7, 0xb8bf4209, 0x5d689d80, 0x1ccf96cf, 0xc5616653, 0x1f813440, 0x4da13261, 0x06de2cb2, 0xc3bf4ae1, 0xb1283c69, 0x1a10730e, 0xf08f3726, 0x5221cf52, 0x8156e321, 0xe6997d06, 0x9d9975ee, 0xc62e0daf, 0x6d178bbb, 0x26689568, 0xa2af3107, 0x0ad8159c, 0x7e9086d5, 0xffc7ac87, 0x44378572, 0x6111b295, 0xdf71155d, 0xccf61833, 0x625f101a, 0xe04698c7, 0x4b7ed7a0, 0x23f9d226, 0x477927fd, 0xa73fbf3a, 0xffc665f4, 0xd6e7a24e, 0x13870d6e, 0x5d6954f3, 0x58f9dace, 0xa4711db5, 0x36a0f3fa, 0x44364c01, 0xdae05213, 0xd0398efc, 0x41a6c23c, 0x92d1ee4f, 0x3aa6cad4, 0x5bb6b132, 0xa2aef874, 0x7296bffb, 0x74489349, 0x20b6b9da, 0x2a6f6535, 0x71d9d407, 0x9b46902f, 0xfc88c77b, 0x71d81d74, 0x4830752f, 0xa1e19388, 0xd6e66b3d, 0xe309f33b, 0x10c86692, 0xe698b475, 0xd5a900c1, 0x516ea4ae, 0xdf70dc2e, 0x4eef90ee, 0x4eee599d, 0x7e914fa6, 0xe3083a48, 0xc62fc4dc, 0xf9198035, 0x9ed7d761, 0xf08efe55, 0x919f4cc0, 0x1f80fd33, 0x67cf9e27, 0xbe60a7c8, 0xd5a8c9b2, 0x64813ca8, 0x155921dc, 0x1a11ba7d, 0x9740a901, 0x52200621, 0xea9f4428, 0xb7f610db, 0xbbf1e086, 0x4da0fb12, 0x7707f8b5, 0x61107be6, 0x195f18f2, 0xb2669ee6, 0x81572a52, 0xd9aef09c, 0x16164a20, 0xb129f51a, 0x3f378d9a, 0x57b1416f, 0xf9184946, 0xd038478f, 0xdc3e7ea1, 0xb8be8b7a, 0xb7f7d9a8, 0xca29fdf2, 0xc966960e, 0x84c66d1c, 0xb4b97b27, 0xa876ede8, 0x034ea28f, 0xc9675f7d, 0x0f4952d2, 0x6d1642c8, 0xbd2fcc34, 0x3aa703a7, 0x16178353, 0x10c9afe1, 0x6e592934, 0x940fc2fd, 0x2cb080f4, 0x516f6ddd, 0x4831bc5c, 0x940e0b8e, 0x3c78e666, 0xa877249b, 0x2ffe227b, 0x6bc86e7a, 0x36a13a89, 0x0c06392e, 0xfc890e08, 0x33307dc7, 0x67ce5754, 0xfa56ebc9, 0x4b7f1ed3, 0xf3c05cda, 0x0ad9dcef, 0xbe616ebb, 0x68870586, 0xef0e0366, 0xcfb8babc, 0x7ddfed29, 0x2a6eac46, 0x0001c973, 0x8e1e7880, 0xade7aaa6, 0x09977e60, 0xc0f1e86e, 0x42e860b3, 0xdc3fb7d2, 0x20b770a9, 0x8e1fb1f3, 0x23f81b55, 0x00000000, 0x7b01c19b, 0xc0f0211d, 0x980832a0, 0x97416072, 0xf650d2e7, 0xfa5722ba, 0x307edf48, 0xa1e05afb, 0x034f6bfc, 0xca283481, 0xd9af39ef, 0x88c05432, 0x821841ae, 0xc560af20, 0x57b0881c, 0x784f6314, 0xec40a1e9, 0x3331b4b4, 0x821988dd, 0x39e9a128, 0xbbf029f5, 0x0c07f05d, 0x2527fe94, 0x72977688, 0x3f3644e9, 0xbd2e0547, 0x6480f5db, 0x41a70b4f, 0x8b8f3fce, 0x2fffeb08, 0x35ee5175, 0x770631c6, 0x29200ec9, 0x1386c41d, 0x88c19d41, 0x6bc9a709, 0xe5d7df89, 0x7dde245a, 0x92d0273c, 0x9b47595c, 0xe9d1e6a7, 0xdae19b60, 0xc3be8392, 0x9d98bc9d, 0x74495a3a, 0xf3c195a9, 0x58f813bd, 0x26695c1b, 0xe5d616fa, 0xa470d4c6, 0xf51fb91b, 0x8d50da0f, 0xade663d5, 0x54fe2a93, 0xf51e7068, 0x6e58e047, 0xa73e7649, 0xccf7d140, 0x784eaa67, 0xab384f67, 0xaea8c15a, 0xcfb973cf, 0x919e85b3, 0x8b8ef6bd, 0x39e8685b, 0xb2675795, 0x05908e3d, 0x5bb77841, 0x42e9a9c0, 0x1558e8af, 0xe04751b4, 0x35ef9806, 0xd3772c73, 0xef0fca15, 0x307f163b, 0x9809fbd3, 0x9ed61e12, 0x5e27f67c, 0x0996b713, 0xf6511b94, 0x4778ee8e, 0xb4b8b254, 0x06dfe5c1, 0x2921c7ba, 0x1cce5fbc, 0x2cb14987, 0x195ed181, 0x0f489ba1, 0xec41689a, 0xea9e8d5b, 0x878906e0, 0xd376e500, 0x54ffe3e0, 0x6886ccf5, 0x3c792f15, 0x84c7a46f, 0x7b0008e8, 0xab398614, 0x0591474e, 0x8d51137c +}, +{ +0x7c5c2312, 0xdb01dca8, 0xe9a27860, 0x099e2109, 0x25526d68, 0x6077aca3, 0x208f79f5, 0x0834a9e4, 0xd945bbb0, 0x664457cb, 0x6a07625f, 0x513ae79e, 0x7fb2cce7, 0x782bbf62, 0xf6671824, 0xceb47210, 0xfc17d6d8, 0x41525dbb, 0x6233cbbb, 0x7a6fd87a, 0x7e18440a, 0xc4c4bcec, 0x141f2655, 0xdf7640d8, 0x9454d39f, 0x5e973dff, 0x1fc56044, 0x68430547, 0xb2e85102, 0x48cc7cb2, 0xc72a5319, 0xdedcc835, 0x165b414d, 0x0bda4611, 0xd742e93c, 0xb342d9ef, 0xa280eb27, 0xccf01508, 0x1d81075c, 0x185c13c1, 0x0de9bd79, 0xe03c5969, 0x2ccc4c61, 0x8da248b3, 0x63994356, 0xf1fe6ba1, 0xfff9392d, 0xb106bef7, 0xdc98af2d, 0x5b4a2962, 0x1068ba25, 0x353ad74d, 0x4eff87da, 0xea4c9795, 0x1bb2fc34, 0xaec3deb3, 0x24f8e585, 0xb4dbaa6a, 0x4f550f37, 0x701f1686, 0x07997385, 0x2affb709, 0xf2108454, 0x86780ea2, 0x69e98daa, 0xd5068e24, 0x23619600, 0x3979e2d9, 0x93cda01a, 0x15b5aeb8, 0x67eedf26, 0x71b59e6b, 0xab1eca2e, 0xa95aad36, 0x0e07528c, 0xcb69668d, 0x820f92d2, 0x4cbbe0c2, 0x138655d0, 0xa8f025db, 0xa0c48c3f, 0xcd5a9de5, 0x9817e60b, 0xedd5e410, 0xef918308, 0x36d438b8, 0x75c2021b, 0x87d2864f, 0xe2783e71, 0xd1711254, 0x1a1874d9, 0x73f1f973, 0x58a4c697, 0xa16e04d2, 0xfb8ea55d, 0x537e8086, 0xc92d0195, 0xc0b3209c, 0x7981378f, 0x2e882b79, 0xe808f08d, 0xec7f6cfd, 0xe44bc519, 0xebe61f78, 0x46cb2e3e, 0x725b719e, 0x9f8e958e, 0xbb76700b, 0x0fadda61, 0xe60fa201, 0xf054e34c, 0xaf69565e, 0xee3b0be5, 0x43163aa3, 0xf3ba0cb9, 0x6c349937, 0x9c607a7b, 0x74688af6, 0x28bbd011, 0xbcef038e, 0x03eeeff5, 0x590e4e7a, 0x2d66c48c, 0x887f5c2e, 0x3d0e7ea9, 0xc8878978, 0xa51998a2, 0x926728f7, 0xc56e3401, 0x5cd35ae7, 0xb69fcd72, 0x57091cf6, 0x2b553fe4, 0x8b91b3db, 0x122cdd3d, 0x314d4b3d, 0x6d9e11da, 0xf8604aa8, 0xa32a63ca, 0xe7a52aec, 0xd29ffda1, 0x3ee0915c, 0x34905fa0, 0x804bf5ca, 0xc680dbf4, 0xf4237f3c, 0x56a3941b, 0xf9cac245, 0x61dd244e, 0xbeab6496, 0x19f69b2c, 0xb8989ffe, 0x01aa88ed, 0x52d4086b, 0x89d5d4c3, 0xb9321713, 0x26bc829d, 0x3a970d2c, 0xa4b3104f, 0x33092c25, 0x0c433594, 0x9610b487, 0xa75dffba, 0x4966f45f, 0xdaab5445, 0xc119a871, 0x3f4a19b1, 0xfe53b1c0, 0x95fe5b72, 0x6badeab2, 0xc2f74784, 0xe5e14df4, 0x3b3d85c1, 0x11c232c8, 0x0633fb68, 0x4d11682f, 0x5ae0a18f, 0x27160a70, 0x9189c702, 0x42bcb24e, 0x4525c1cb, 0xd6e861d1, 0x99bd6ee6, 0xb0ac361a, 0x97ba3c6a, 0x4b229347, 0x54e7f303, 0x5f3db512, 0x17f1c9a0, 0x6fda76c2, 0x9bf909fe, 0xd4ac06c9, 0xac87b9ab, 0x5d79d20a, 0xe3d2b69c, 0x83a51a3f, 0x00000000, 0xf7cd90c9, 0xbd458b63, 0x8c08c05e, 0x640030d3, 0x1e6fe8a9, 0x291158fc, 0x1c2b8fb1, 0x4a881baa, 0x77866503, 0xcac3ee60, 0x2125f118, 0x6e70fe2f, 0xd8ef335d, 0x9e241d63, 0xf589f7d1, 0x3ca4f644, 0xad2d3146, 0xd335754c, 0x02446718, 0x05dd149d, 0x04779c70, 0x30e7c3d0, 0x22cb1eed, 0x8a3b3b36, 0xa6f77757, 0x8e4ca746, 0x7df6abff, 0x448f4926, 0x50906f73, 0x762cedee, 0x90234fef, 0xc35dcf69, 0xdd3227c0, 0xb735459f, 0xe196d184, 0x65aab83e, 0xb5712287, 0x4761a6d3, 0xbadcf8e6, 0x554d7bee, 0xd0db9ab9, 0x40f8d556, 0xaab442c3, 0x9dcaf296, 0x377eb055, 0xfa242db0, 0x2f22a394, 0x32a3a4c8, 0x8596e157, 0xbf01ec7b, 0xfdbd5e35, 0x9a538113, 0x38d36a34, 0x843c69ba, 0x7bc55097, 0x0a70cefc, 0x81e17d27, 0xcf1efafd, 0x8fe62fab +}, +{ +0x2fff38fc, 0xadeac1f9, 0x8ce2a173, 0xb2c464f6, 0xb4a38cad, 0x2589d237, 0x00000000, 0x083109a0, 0x171facaf, 0x3c9a5ec1, 0x38ba55f1, 0xb0223e10, 0x38e09453, 0x0c4bc332, 0xbc92850d, 0x8c4318fe, 0x34502f4e, 0x84896971, 0xaf565abd, 0x2939692a, 0x1bf5d610, 0x8cb860d1, 0x95f12d85, 0x29c21105, 0x340aeeec, 0x25d31395, 0x1f8f1c82, 0xbaafacf4, 0xa931b2e6, 0x1baf17b2, 0x139e1e12, 0x1b0eae3f, 0x2963a888, 0x19138cf6, 0x91d126b5, 0xb61f17e9, 0x234f83e1, 0xa347582d, 0x86944bb8, 0x36b675a8, 0xb849f612, 0x2794f0fe, 0x9d9ae587, 0xaff7e330, 0x2b7e8a41, 0xbaf56d56, 0xa9900b6b, 0x326d06b7, 0x0cea7abf, 0x2108608a, 0x1dc8ffe9, 0xa73d92bf, 0x381bec7c, 0x9fdd06ec, 0xb8b28e3d, 0x9bfd0ddc, 0x3eddbdaa, 0x2db8db97, 0x8eff83ba, 0x2f5e8171, 0x276f88d1, 0x0c110290, 0x97ec0f4c, 0x2152a128, 0x866f3397, 0x25286bba, 0xb083879d, 0x17e4d480, 0x11d9fd79, 0x912a5e9a, 0x9ba7cc7e, 0xb6beae64, 0x0481b2bd, 0x95509408, 0x86ce8a1a, 0x80521a6e, 0x8ea54218, 0x8472115e, 0xbed56666, 0x19494d54, 0x8008dbcc, 0x2572aa18, 0x991b573a, 0x21a9d907, 0x23154243, 0xab2c902f, 0x27354973, 0x9d3b5c0a, 0x3a06ceb5, 0x0e0c2059, 0xa520b076, 0x3aa77738, 0x97b6ceee, 0x1d923e4b, 0x9f7cbf61, 0xa3e6e1a0, 0xbe2e1e49, 0x950a55aa, 0xa1fbc369, 0x2f0440d3, 0xbc69fd22, 0xb645d64b, 0xa58109fb, 0x0a2c2b69, 0x23b4fbce, 0x19e8f4d9, 0x069c9074, 0xb0d9463f, 0x3617cc25, 0x2fa5f95e, 0x06c651d6, 0x38412dde, 0xbc333c80, 0xa7c6ea90, 0x21f318a5, 0x3a5c0f17, 0xa767531d, 0xb078ffb2, 0x34f196c3, 0x047aca92, 0x0cb0bb1d, 0x3e7c0427, 0x8a24f0a5, 0x19b2357b, 0x2bdf33cc, 0x88c2aa43, 0x0e56e1fb, 0x0a76eacb, 0x80f3a3e3, 0x8a7e3107, 0x3c6126ee, 0x2de21a35, 0x11228556, 0xba54d4db, 0x308b5c51, 0x82ee812a, 0x2d43a3b8, 0x9dc02425, 0x1fd5dd20, 0x936dbdf1, 0xb4f94d0f, 0x364d0d87, 0x08ca718f, 0x8a854928, 0x0247e36b, 0x02bc9b44, 0x2d19621a, 0xabd7e800, 0x00fb782f, 0x17456d0d, 0x8e04fb95, 0x021d22c9, 0x0a8d92e4, 0x36ecb40a, 0x8adf888a, 0x974db6c1, 0xa9cacac9, 0x9f87c74e, 0xad4b7874, 0x8839d26c, 0xa100bb46, 0x8428d0fc, 0x117844f4, 0xaf0c9b1f, 0xbcc844af, 0x34ab5761, 0x1d3387c6, 0xa79c2b32, 0x91709f38, 0x82b44088, 0x1d694664, 0x93cc047c, 0x9b0675f3, 0xa57a71d4, 0x886313ce, 0x3070247e, 0xb29ea554, 0x23ee3a6c, 0x2b244be3, 0x02e65ae6, 0xb23f1cd9, 0x11833cdb, 0xb8e84f9f, 0xa5dbc859, 0xadb0005b, 0x9f267ec3, 0x2998d0a7, 0x086bc802, 0x32967e98, 0x95abec27, 0x30d19df3, 0xb458f482, 0xb81337b0, 0xbe74dfeb, 0xbe8fa7c4, 0x00a1b98d, 0xa96b7344, 0x1b546f9d, 0xb6e46fc6, 0x8215f905, 0x15f9f649, 0x133fa79f, 0x8c19d95c, 0xb4023520, 0xad11b9d6, 0x824f38a7, 0x97177763, 0x04200b30, 0x0ead99d4, 0x88986be1, 0x3afdb69a, 0x8e5e3a37, 0x27ce315c, 0xba0e1579, 0x3237c715, 0x15a337eb, 0x15028e66, 0x99419698, 0xa3bc2002, 0x9b5cb451, 0x3c3be74c, 0x1f2ea50f, 0x3cc09f63, 0x302ae5dc, 0xa15a7ae4, 0x99e02f15, 0xab76518d, 0x32ccbf3a, 0x99baeeb7, 0x8635f235, 0xa1a102cb, 0x0ef75876, 0x0890b02d, 0x80a96241, 0x04db731f, 0x0667e85b, 0x1365663d, 0x15584fc4, 0xab8d29a2, 0x3e26c585, 0x9d619da8, 0x2b85f26e, 0x9396c5de, 0x84d3a8d3, 0xafad2292, 0x005ac1a2, 0x063d29f9, 0x918be717, 0xa31d998f, 0x1f7464ad, 0x13c4dfb0, 0x0ad75346, 0x17be1522, 0xb265dd7b, 0x93377c53, 0x3e877c08 +}, +{ +0x4864d065, 0x32d60155, 0x48fe8cb7, 0x7c3b9145, 0x2aec1c76, 0xc9f5d82d, 0x3033c0f2, 0xcc9b7c6a, 0x564dd1e1, 0x621290c1, 0x1a458056, 0x79cf69d0, 0x861a6da8, 0xaf1195ec, 0xfe4d7d3f, 0xfed721ed, 0x355d64b5, 0x532375a6, 0xd43b3d9b, 0x667e1113, 0x28938103, 0xe0fe2069, 0xa800acde, 0xabe748ec, 0xd4a16149, 0x2a7640a4, 0xffd50478, 0xcee4e11f, 0x2dfd2544, 0xe166592e, 0xe0647cbb, 0xb347091d, 0xac6c2d0c, 0x505ecd46, 0xcfe6c48a, 0x84ffac0f, 0x98336c2c, 0xd228213c, 0xe7754589, 0x2f82b831, 0x6310b554, 0x9d5dc86b, 0x993149b9, 0xaa7f31ab, 0xd32a04a9, 0x05f4f895, 0x55aa35d3, 0x52bb0ce1, 0x8567d548, 0x8374c9ef, 0x649bd0b4, 0xcd03052d, 0xe677601c, 0xcd9959ff, 0xacf671de, 0xe492a1bb, 0x1c569cf1, 0xe408fd69, 0xb6b3f188, 0x60f75166, 0xe21be1ce, 0xff4f58aa, 0x67e66854, 0x878214ef, 0xd15599dc, 0x18a041f1, 0xc8f7fdb8, 0x7b2aa877, 0x99ab156b, 0xae13b079, 0x82ecb0a8, 0x57d5a8a6, 0xd057bc49, 0x078b65e0, 0x7ca1cd97, 0xb1a2c8ba, 0x2e809da4, 0x2809ddd1, 0x03e7e432, 0xb456302f, 0xb3dd55cf, 0x2bee39e3, 0x78571097, 0x55306901, 0xd5a344dc, 0x7f4629a5, 0x1d54b964, 0x4c920d65, 0xd7dcd9a9, 0xd539180e, 0xd3b0587b, 0xa89af00c, 0x56d78d33, 0x4e77ccc2, 0x056ea447, 0xadf4544b, 0xe319c45b, 0x1e290184, 0x7ede50e2, 0x54324c94, 0xc96f84ff, 0x7a288de2, 0x2c655c03, 0xca123c1f, 0x52215033, 0xfca8bc98, 0x98a930fe, 0x7d39b4d0, 0xd6defc3c, 0x53b92974, 0x9f22551e, 0xca8860cd, 0xcf7c9858, 0x4c0851b7, 0x00000000, 0x64018c66, 0x35c73867, 0xaf8bc93e, 0x01987947, 0xb1389468, 0x4f75e957, 0x183a1d23, 0xab7d143e, 0x8009710f, 0x7ab2d130, 0x334e7812, 0x50c49194, 0x2d677996, 0xb2452c88, 0x1fb178c3, 0x61f574f3, 0x02e5c1a7, 0x9b4ed4cc, 0x49fca922, 0x009a5cd2, 0x6599f521, 0xfb23d978, 0x30a99c20, 0x810b549a, 0x3131e567, 0x345f4120, 0x01022595, 0x8718483d, 0xf85e6198, 0x66e44dc1, 0xf9c618df, 0xb7b1d41d, 0x9bd4881e, 0x2991a496, 0x79553502, 0x4fefb585, 0x290bf844, 0x06894075, 0x677c3486, 0xd1cfc50e, 0xb0a0ed2f, 0xe590842e, 0x19a26464, 0xfdaa990d, 0x7e440c30, 0x51c6b401, 0x4b196885, 0xb72b88cf, 0xf95c440d, 0x8465f0dd, 0x7da3e802, 0x4d0a7422, 0x8276ec7a, 0xb2df705a, 0x1eb35d56, 0x2cff00d1, 0xb55415ba, 0x78cd4c45, 0xf8c43d4a, 0xb5ce4968, 0xfabba03f, 0x4d9028f0, 0x6288cc13, 0xd2b27dee, 0x9a4cf159, 0x4966f5f0, 0x3722f9c0, 0xa902894b, 0x81910848, 0x31abb9b5, 0x85fd899a, 0xe281bd1c, 0x638ae986, 0xe6ed3cce, 0x193838b6, 0x9fb809cc, 0x4eed9010, 0x2f18e4e3, 0x9ad6ad8b, 0xd746857b, 0xcb8a4558, 0xae89ecab, 0x324c5d87, 0xc86da16a, 0x9c5fedfe, 0x36ba8087, 0x616f2821, 0x2b746531, 0x515ce8d3, 0xb03ab1fd, 0x8680317a, 0x4b833457, 0x7bb0f4a5, 0xb4cc6cfd, 0x574ff474, 0x1cccc023, 0xd644a0ee, 0x3620dc55, 0xfbb985aa, 0x04f6dd00, 0x33d424c0, 0xe50ad8fc, 0x4a1b4d10, 0xe3839889, 0xaae56d79, 0x9cc5b12c, 0x1bddf911, 0x037db8e0, 0x1f2b2411, 0x9e20708b, 0x6503a9f3, 0x9dc794b9, 0x027f9d75, 0x1dcee5b6, 0x83ee953d, 0xa998d599, 0xce7ebdcd, 0xcc0120b8, 0x07113932, 0x2e1ac176, 0xfc32e04a, 0xe7ef195b, 0x4a8111c2, 0x606d0db4, 0xfd30c5df, 0x1b47a5c3, 0x54a81046, 0x34c51df2, 0x046c81d2, 0x06131ca7, 0xe1fc05fc, 0xad6e0899, 0x37b8a512, 0xd0cde09b, 0xcb10198a, 0xfa21fced, 0x7fdc7577, 0xb629ad5a, 0x1adfdc84, 0x80932ddd, 0x9eba2c59 +}, +{ +0x1689411a, 0x6f055b97, 0xd18fb10f, 0xdc7cae00, 0x898a48f9, 0xea737fdc, 0xcabf4365, 0x78836930, 0xa40c518b, 0x360fd1dc, 0xc74c5c6a, 0xeb36a01e, 0x4270d45e, 0xeaca4518, 0x930cf3ea, 0xbe33d05c, 0x423a7821, 0xc7bfcad1, 0x847957f6, 0x540a03ff, 0x3700a261, 0x8585b2f0, 0xa5ba18f2, 0x6e408455, 0xa5f0b48d, 0x798c1a8d, 0xdd804b06, 0xf10921c9, 0x63b39b5a, 0x21c34f04, 0xd1368bcb, 0xdc8f38bb, 0xf04cfe0b, 0x9ff09f58, 0x1b30f26a, 0x8876adff, 0x624f7e5c, 0xd17c27b4, 0xc706f015, 0xcb090a1c, 0xa8ba9146, 0x62f64498, 0x20cc3cb9, 0xa90cd83f, 0xe7395a17, 0x9effece5, 0xfd06dbc0, 0xb33359e8, 0x554fdc3d, 0x37b998a5, 0x203faa02, 0xeb7c0c61, 0x0df31f0f, 0xd039f876, 0x00b93ac4, 0xcbb030d8, 0x8433fb89, 0x590a8a4b, 0x59b3b08f, 0xa9467440, 0xfdbfe104, 0xdd3971c2, 0x0d4a25cb, 0x1a86bb13, 0x93465f95, 0x4e358228, 0xe78060d3, 0x16c3ed65, 0x167ad7a1, 0xc6432fd7, 0x4f3af195, 0x4f705dea, 0x4fc9672e, 0x753ada40, 0x6f4ff7e8, 0xcbfa9ca7, 0x2d3f23b6, 0xbe8aea98, 0x1acc176c, 0xbf859925, 0x36b6eb18, 0x63400de1, 0x0c455676, 0x848ac14d, 0xeb8f9ada, 0x4f83cb51, 0x173f0863, 0x3ab91111, 0x59402634, 0xf0bf68b0, 0xfcfa3ec6, 0xddcae779, 0x6eb312ee, 0xbe797c23, 0x9f0309e3, 0x3bfcced3, 0xbec046e7, 0xfdf54d7b, 0xbf3ca3e1, 0x63f93725, 0x55f6e6f9, 0xdcc594c4, 0x0145dfc2, 0x7870ff8b, 0x0d0089b4, 0xdc36027f, 0xdd73ddbd, 0x9f49a59c, 0x92baba93, 0x2dccb50d, 0x1bc364d1, 0xe67c85d5, 0x0cfc6cb2, 0x438c3158, 0x75c94cfb, 0x42c9ee9a, 0x6205d223, 0xfcb092b9, 0xe773f668, 0xbf760f9e, 0x0cb6c0cd, 0x3a4a87aa, 0x1b89c8ae, 0xca4cd5de, 0xb23c2a55, 0xb2851091, 0xfc430402, 0xa5498e49, 0x3b0f5868, 0x7435a9fd, 0x55bc4a86, 0x4e7f2e57, 0x883c0180, 0x88cf973b, 0x3bb662ac, 0x00000000, 0x59f91cf0, 0x55057042, 0x7583e084, 0x43350b9c, 0x437fa7e3, 0x2130d9bf, 0xa9ff4e84, 0xb379f597, 0x17cc9ed8, 0xe7caccac, 0x4ec61493, 0x79352049, 0x2c7afc74, 0xf1fab772, 0xcb43a663, 0x9fba3327, 0xea39d3a3, 0x85cf1e8f, 0x0c0ffa09, 0x8933723d, 0x93ff6551, 0xa446fdf4, 0x747f0582, 0xa84907fd, 0xd1c51d70, 0x2cc3c6b0, 0xcaf5ef1a, 0x8576244b, 0x584f5589, 0xb2cfbcee, 0xc7f566ae, 0xb276862a, 0x2d861972, 0x2c30500b, 0x9eb5409a, 0xc60983a8, 0x6e0a282a, 0x8979de42, 0x58bcc332, 0x43c69d27, 0x7570763f, 0xa4ffc730, 0x208690c6, 0x4e8cb8ec, 0x01b64979, 0xa4b56b4f, 0x1b7a5e15, 0xa9b5e2fb, 0xb38a632c, 0x9e46d621, 0x93b5c92e, 0xebc536a5, 0x217a75c0, 0xa803ab82, 0x1775a41c, 0x3a002bd5, 0x6fbc6153, 0x37f334da, 0xd080c2b2, 0x92038057, 0x00f396bb, 0x6ff6cd2c, 0x2d758fc9, 0x797f8c36, 0x783a53f4, 0xfd4c77bf, 0x88853b44, 0xd0735409, 0x92492c28, 0x89c0e486, 0xb3c0cf53, 0x74c63f46, 0x0db9b370, 0xea80e967, 0x92f016ec, 0x3b45f417, 0x01fce506, 0xd0ca6ecd, 0x2189e37b, 0xca0679a1, 0x84c06d32, 0x010f73bd, 0xe68f136e, 0x853c8834, 0x2c896acf, 0x5805f9f6, 0xbfcf355a, 0xe63629aa, 0x1a3f81d7, 0xf1438db6, 0xf1b01b0d, 0x1a752da8, 0xa8f03d39, 0x36fc4767, 0x9e0c7a5e, 0x62bce8e7, 0x5440af80, 0x374a0e1e, 0xf0065274, 0x58f66f4d, 0x16307bde, 0x2075067d, 0xc6b0b96c, 0x3af3bd6e, 0xa5032236, 0x54f99544, 0x630aa19e, 0xf0f5c4cf, 0x178632a7, 0x428342e5, 0x78c9c54f, 0x004aac7f, 0x79c6b6f2, 0xc6fa1513, 0x36457da3, 0x748c9339, 0x54b3393b, 0x6ef9be91, 0xfc09a87d, 0xe6c5bf11 +}, +{ +0x1ec47521, 0x60772731, 0x3ef23e27, 0xa0edd3bb, 0x06c50e40, 0xb2cc7fbb, 0x80db98bd, 0xb03c5e71, 0x7663a4bb, 0xbac876c3, 0x2cd39227, 0x3ac711ad, 0x98dae3dc, 0xea58973e, 0x8a2fb00f, 0x843a48e4, 0xdcaea061, 0xf8adc4ed, 0x2e23b3ed, 0xdabf51f2, 0xaacd04da, 0x8ceabe4f, 0x48919a9c, 0x4e806b0f, 0xf07d3246, 0x18d584b2, 0x9cefcc56, 0xb8385709, 0x3cd6e03e, 0xe6bd4e1f, 0xb62dafe2, 0x38e3cfb4, 0x0611f193, 0x6a57f050, 0x50441e2e, 0x1e108af2, 0x0c3126f2, 0x1af15aab, 0x8e1a9f85, 0xa6fc2228, 0x447443bd, 0x5c7538dc, 0xd47e56ca, 0xf4481dcc, 0x44a0bc6e, 0x86ca692e, 0xccabd278, 0x9afe3dc5, 0x3217e706, 0xf8793b3e, 0x96cf1b37, 0xca6edc38, 0xbe29a69a, 0xd89b8feb, 0x88df91c5, 0x46846277, 0xc09af48a, 0x5a64c94f, 0xb0e8a1a2, 0x14e4a240, 0x0224de19, 0xa4d8fc31, 0x8ece6056, 0x76b75b68, 0x16c07c59, 0x4265b22e, 0xfa5de527, 0xf66cc3d5, 0x4ca4b516, 0x3a13ee7e, 0x7e67adc3, 0xd4aaa919, 0xd26fa759, 0x28e6bdad, 0x5090e1fd, 0x34061695, 0x728274e2, 0xae2cd483, 0x08d0f6ab, 0x82ff46a4, 0x68a7d19a, 0x900a1577, 0x00000000, 0x78765c50, 0x644208bb, 0xd09f8693, 0x7c4373da, 0xc4afdb00, 0x08040978, 0x6666d6a2, 0x10d18dca, 0x60a3d8e2, 0x6c4601c3, 0x1614838a, 0x3622c88c, 0x547131a4, 0x2ac263b4, 0x3033391f, 0x30e7c6cc, 0x10057219, 0x7a867d9a, 0xacdcf549, 0x84eeb737, 0x38373067, 0x00d4ffd3, 0x58401756, 0x4845654f, 0x92fa34bd, 0x9a2ac216, 0xe87c4927, 0xce5bf3b2, 0x78a2a383, 0x20e2b4d5, 0x2627ba95, 0x880b6e16, 0xdc7a5fb2, 0xea8c68ed, 0x861e96fd, 0xda6bae21, 0xc65ffaca, 0x5894e885, 0xbcd98750, 0xce8f0c61, 0xde8a7e78, 0x1221ac00, 0x2212951f, 0xbc0d7883, 0x628706fb, 0x1c3454eb, 0x9e1fed9c, 0xe0acbf8c, 0xc2be2a93, 0xf6b83c06, 0x6253f928, 0xba1c8910, 0xd2bb588a, 0x0af428b2, 0x14305d93, 0x2832427e, 0x52b43fe4, 0xde5e81ab, 0xbefd5949, 0x04e1d059, 0x0ce5d921, 0xec4966ad, 0x0a20d761, 0xe4999006, 0xb4dd8e28, 0x2c076df4, 0x800f676e, 0xa2c90da2, 0x1ce0ab38, 0xf259ec5f, 0x8afb4fdc, 0x6a830f83, 0x20364b06, 0xfc98eb67, 0x4c704ac5, 0x5e851916, 0x74477aa2, 0x5ca1c70f, 0x3e26c1f4, 0x922ecb6e, 0xe44d6fd5, 0x9ecb124f, 0x7a528249, 0x5655efbd, 0x04352f8a, 0x70a6aafb, 0xd84f7038, 0x4ab54485, 0xa40c03e2, 0x18017b61, 0x2a169c67, 0x6eb62009, 0xe8a8b6f4, 0x9c3b3385, 0x94ebc52e, 0xb6f95031, 0xc89efdf2, 0x943f3afd, 0xa21df271, 0x5e51e6c5, 0xc26ad540, 0x72568b31, 0xe078405f, 0x7c978c09, 0xb8eca8da, 0x6496f768, 0x1a25a578, 0x02f021ca, 0xac080a9a, 0x22c66acc, 0x5260c037, 0xec9d997e, 0xb2188068, 0x8c3e419c, 0xaef82b50, 0xf49ce21f, 0x42b14dfd, 0xf0a9cd95, 0x0e15f8eb, 0xcc7f2dab, 0x7eb35210, 0xd68e7700, 0xe25c9e46, 0xee6db8b4, 0x54a5ce77, 0xfe68caad, 0xa0392c68, 0x4e5494dc, 0x961be4e4, 0x2403648c, 0xf28d138c, 0x34d2e946, 0xd65a88d3, 0x5681106e, 0xfebc357e, 0x5ab0369c, 0xd04b7940, 0xcaba23eb, 0x822bb977, 0x36f6375f, 0x74938571, 0xe669b1cc, 0xe2886195, 0x0ec10738, 0xa8e9dac3, 0xfa891af4, 0x3c021fed, 0x66b22971, 0x90deeaa4, 0xfc4c14b4, 0xc47b24d3, 0x70725528, 0x4a61bb56, 0xeeb94767, 0x12f553d3, 0xc84a0221, 0x46509da4, 0x2ef74c3e, 0x6e62dfda, 0xa628ddfb, 0x24d79b5f, 0xaa19fb09, 0x26f34546, 0xc04e0b59, 0x40416c37, 0x32c318d5, 0xb40971fb, 0x409593e4, 0x6c92fe10, 0xc68b0519, 0xa83d2510, 0x980e1c0f, 0x68732e49 +}, +{ +0xd192327e, 0xaba09ecd, 0x1d0e9ec0, 0xc69117d1, 0xc5c95bf6, 0x9bcca5f2, 0x1250e77c, 0x86c23b32, 0xf947e02b, 0x5bb289ae, 0xb64ab574, 0x64647e54, 0xba4c80ef, 0x35db4c95, 0x91c11e9d, 0x54ecf012, 0x3f324283, 0x5203cb9f, 0x857ec26c, 0x3c6a0ea4, 0xb0413b80, 0xcc7819c7, 0x9dc72b06, 0x12b45205, 0xbf1f423c, 0x9e7bd258, 0xae17e967, 0x4a5e978c, 0x2180251d, 0x51bf32c1, 0x430b60c4, 0x00000000, 0x628b45d9, 0xc3c2d502, 0x49e26ed2, 0x46bc176e, 0x40532ce3, 0x0ae90e16, 0x0553c2d3, 0x580e70f0, 0xf541d5b0, 0x67d8870a, 0xd77d09f3, 0x3a618050, 0x1b051034, 0xebf3b22e, 0x185d5c13, 0x11ec1e22, 0x2d62a5ff, 0x3667b5cb, 0xb3fdc2de, 0xe7f587b5, 0xed1c89a3, 0x4aba22f5, 0x5408456b, 0x4c551978, 0x1eb2679e, 0x4658a217, 0x8ac40ea9, 0x57b4bc35, 0x243752b7, 0x09b14231, 0x70dba2a5, 0xf5a560c9, 0x4cb1ac01, 0xe71132cc, 0x30888e46, 0xdb9f8911, 0xca739733, 0xa81c6793, 0xf3aeee3d, 0xcc9cacbe, 0x060b8ef4, 0x2d861086, 0x22d8693a, 0x33347718, 0x972e2510, 0xf9a35552, 0x306c3b3f, 0xfafb1975, 0x83754c98, 0xd4c1f0ad, 0xdd9407e5, 0x05b777aa, 0xdecc4bc2, 0xb6ae000d, 0xeea070fd, 0xee44c584, 0xf6199997, 0xd22ecb20, 0x75886076, 0x52e77ee6, 0x703f17dc, 0x7a32acb3, 0x5d5db223, 0xe84f4b70, 0x145b6988, 0x97ca9069, 0xc92bdb14, 0x626ff0a0, 0x4906dbab, 0x9d239e7f, 0xbffbf745, 0xbca3bb62, 0xf0f6a21a, 0xc52dee8f, 0x170325af, 0xd2ca7e59, 0x756cd50f, 0x276f1e90, 0xf34a5b44, 0x8c2b3524, 0x3939cc77, 0x2e3ae9d8, 0xa2f56985, 0xd823704f, 0x6e69c53b, 0xa7421e2f, 0x1be1a54d, 0x2831672c, 0x73675bfb, 0xc9cf6e6d, 0xb9f079b1, 0xff4c6edf, 0x7ad619ca, 0x353ff9ec, 0x4fe9e026, 0x0c06359b, 0x80c9b5c6, 0x98705cac, 0x8f97cc7a, 0x45e45b49, 0xeb170757, 0xbc470e1b, 0x6e8d7042, 0x6886feb6, 0xdb7b3c68, 0xfcf09781, 0xb0a58ef9, 0xb512f953, 0xa211dcfc, 0x278babe9, 0x0ce280e2, 0x6137bc87, 0x17e790d6, 0x4500ee30, 0x8ccf805d, 0x368300b2, 0x5750094c, 0xa1ad25a2, 0xb5f64c2a, 0x6480cb2d, 0x927de7c3, 0x0a0dbb6f, 0x929952ba, 0x18b9e96a, 0x3a853529, 0x5db9075a, 0x06ef3b8d, 0x7f616e60, 0x3c8ebbdd, 0x4f0d555f, 0xb31977a7, 0x61d309fe, 0xa4fee771, 0x7383ee82, 0x76349928, 0x8f737903, 0xde28febb, 0x5e05fe04, 0x2b692b0b, 0xbaa83596, 0x8a20bbd0, 0x899c428e, 0xfc1422f8, 0xe1fe0941, 0xf6fd2cee, 0x802d00bf, 0x5b563cd7, 0xedf83cda, 0x2b8d9e72, 0x3fd6f7fa, 0x58eac589, 0x9e9f6721, 0x2ede5ca1, 0xd8c7c536, 0x94766937, 0xadab1039, 0x7c392247, 0xe2a64566, 0x00e4b579, 0x1dea2bb9, 0xc326607b, 0x5ee14b7d, 0xcfc4e099, 0x03bcf95e, 0x1108ab5b, 0xe8abfe09, 0xa8f8d2ea, 0xcf2055e0, 0xb914ccc8, 0x9b28108b, 0x9125abe4, 0xc09a9925, 0xca97224a, 0xdd70b29c, 0x8978f7f7, 0xa41a5208, 0x515b87b8, 0x796ae094, 0x86268e4b, 0x6dd53c65, 0xd1768707, 0x9894e9d5, 0x03584c27, 0x7f85db19, 0x39dd790e, 0xc675a2a8, 0xd799bc8a, 0x1e56d2e7, 0xe242f01f, 0x6bdeb291, 0x21649064, 0xad4fa540, 0xe11abc38, 0xd42545d4, 0x68624bcf, 0x76d02c51, 0x798e55ed, 0x859a7715, 0x33d0c261, 0x7cdd973e, 0x6d31891c, 0xc07e2c5c, 0x0955f748, 0xab442bb4, 0xf0121763, 0x43efd5bd, 0xa7a6ab56, 0x0fbaccc5, 0xfa1fac0c, 0x9492dc4e, 0xffa8dba6, 0x24d3e7ce, 0xaef35c1e, 0xa14990db, 0xe4497eeb, 0x40b7999a, 0x14bfdcf1, 0x28d5d255, 0x8391f9e1, 0x673c3273, 0x223cdc43, 0xe4adcb92, 0x6b3a07e8, 0x0f5e79bc +}, +{ +0xfa82931e, 0x8dd6b5c3, 0x7a8efd44, 0xf5595b12, 0x4181e3e8, 0xa849c183, 0x3025ee52, 0x4347f6ee, 0xd6360435, 0xc861684a, 0x89278d31, 0xa363317d, 0xb41fbe69, 0x71630b29, 0x69c44c31, 0xaeb9eae4, 0xfc72b879, 0x0bedf66d, 0xdf1de75e, 0x134ab175, 0xce5645be, 0x3f3920cd, 0x5f118904, 0x5be0b1f6, 0xefff0f9f, 0x6d3574c3, 0x3ffe265e, 0x2e72822d, 0x95b6f448, 0x6028a9c9, 0xe6d4ecf4, 0xca607bdf, 0x820d7dcf, 0x2a83badf, 0xf7584887, 0x9c9d1723, 0xc77da6d5, 0xe225d406, 0xf36e76e6, 0xa1a5247b, 0x66d882ae, 0xae7eec77, 0x2cb4972b, 0x47b6ce1c, 0x759233db, 0x3224fdc7, 0xeb0e376d, 0xb6d9ab6f, 0x3612c3a6, 0x775426dd, 0x86fc453d, 0x7eb8c325, 0x9c5a11b0, 0x2882a94a, 0x73a51e2f, 0x8b269ea4, 0x520c540e, 0x6bc55fa4, 0xacb8f971, 0xd00129c1, 0xa5541c89, 0xc34b98b4, 0x6df27250, 0xa5931a1a, 0x7793204e, 0x0d1ddd0a, 0x3b0f1eac, 0x5926a4f0, 0xdbecdfac, 0xc7baa046, 0x118ca473, 0x1e906aec, 0xce91432d, 0x486d0610, 0x9346df2f, 0xa16222e8, 0xaa8fd485, 0xbff24804, 0x6f346756, 0x5fd68f97, 0x52cb529d, 0x59e1a263, 0x2c7391b8, 0x177c8f14, 0x216e4cb2, 0xdb2bd93f, 0x8f10a0c5, 0x30e2e8c1, 0x9147ccba, 0x390e0d39, 0x661f843d, 0x18a74718, 0x863b43ae, 0xb228939d, 0x255872d3, 0x3dff35cb, 0x50ca4108, 0xfe73abec, 0x4c5b3871, 0x62eebccf, 0x6ff361c5, 0xe2e2d295, 0x6229ba5c, 0x4aab1316, 0xc5bbb3d3, 0x4e5a2be4, 0xb2ef950e, 0x4c9c3ee2, 0x641e97a8, 0x0ddadb99, 0xbdf35b91, 0x1a61521e, 0xed391a99, 0xe4d5ff61, 0xa88ec710, 0xd92acaaa, 0xb9026363, 0xfcb5beea, 0x986c2fd1, 0x4146e57b, 0xf8448618, 0xb61eadfc, 0x157d9c81, 0x2a44bc4c, 0x89e08ba2, 0xd9edcc39, 0xd4f01133, 0x9e5b0225, 0x1860418b, 0xdddbf258, 0x114ba2e0, 0x8d11b350, 0xebc931fe, 0x3413d033, 0xb0298008, 0x4e9d2d77, 0x64d9913b, 0xd6f102a6, 0xe613ea67, 0xb9c565f0, 0xd2003a54, 0x0f1cce9f, 0xa792098f, 0x800c6e5a, 0x9381d9bc, 0x34d4d6a0, 0xfa45958d, 0x39c90baa, 0xcc9050b8, 0xe0e3c100, 0x7e7fc5b6, 0x788feed1, 0x092be36b, 0x36d5c535, 0x9e9c04b6, 0xcc57562b, 0xe90f24f8, 0xf3a97075, 0x0b2af0fe, 0x4771c88f, 0x4570db1a, 0x736218bc, 0x9770e14e, 0x97b7e7dd, 0xa3a437ee, 0xdfdae1cd, 0xac7fffe2, 0x7848e842, 0x84fd56a8, 0x54fc7f69, 0x7c7ed623, 0xf883808b, 0x236f5f27, 0x02c61506, 0x1c917979, 0xc57cb540, 0x2845afd9, 0xd2c73cc7, 0x4a6c1585, 0xc14a8b21, 0x00c70693, 0xc38c9e27, 0x2eb584be, 0x5b27b765, 0x563a6a6f, 0x1e576c7f, 0x17bb8987, 0xdd1cf4cb, 0xd43717a0, 0x45b7dd89, 0x69034aa2, 0x543b79fa, 0x04f138f2, 0xe024c793, 0x4380f07d, 0xf16f6573, 0xbb0370f6, 0x5dd79c02, 0xa7550f1c, 0xcaa77d4c, 0x15ba9a12, 0x00000000, 0x138db7e6, 0xf59e5d81, 0x32e3fb54, 0xb0ee869b, 0xedfe1c0a, 0x3bc8183f, 0x259f7440, 0x843a503b, 0x9180ca29, 0x0fdbc80c, 0x8be19837, 0x6b025937, 0xbf354e97, 0x06f02b67, 0x500d479b, 0x04363e61, 0x1c567fea, 0x3d383358, 0x48aa0083, 0xc8a66ed9, 0x09ece5f8, 0xaa48d216, 0xc18d8db2, 0xbbc47665, 0x27596146, 0x75553548, 0x7cb9d0b0, 0xbd345d02, 0x82ca7b5c, 0x02011395, 0x23a859b4, 0x98ab2942, 0x279e67d5, 0x60efaf5a, 0xd0c62f52, 0xfeb4ad7f, 0xb4d8b8fa, 0xe412f9f2, 0xf1a863e0, 0x9571f2db, 0xef38090c, 0x9a6d3c44, 0x8fd7a656, 0x21a94a21, 0x06372df4, 0x9aaa3ad7, 0x7a49fbd7, 0x1aa6548d, 0x80cb68c9, 0xe9c8226b, 0x71a40dba, 0x56fd6cfc, 0x5d109a91, 0xf79f4e14 +}, +{ +0xbd70845d, 0x7772fb5a, 0x99379543, 0xf34217dc, 0x9b348c55, 0x71714559, 0xe49826de, 0x8f3e87da, 0x08de51d1, 0x8eeda441, 0xb47df617, 0xef964d82, 0x394068db, 0xa5a47916, 0xaf7931d1, 0xff9ce118, 0xf4928a44, 0x49e20e19, 0x56e66eca, 0x74a2c1d7, 0x6378f0d5, 0x9ce411cd, 0x07d09d98, 0xe7481c53, 0x02031916, 0xa077fd98, 0x11d98f01, 0xa4775a8d, 0xcfd1fb89, 0x6fa60611, 0x583b8118, 0x0f0ecc49, 0x27972b93, 0xc9d2458a, 0x4fe1b01a, 0x2899e7da, 0xca027f07, 0xf541a9df, 0x3a905256, 0x40ef7c53, 0x0cdef6c4, 0x2447111e, 0x9639590a, 0x3e90f543, 0xe69b3fc8, 0xbaa019c5, 0x1b04c7c6, 0xf0922d51, 0xb67eef01, 0xfe4fc283, 0xa97a8fd2, 0x91e9c492, 0x2a9afecc, 0xd4d53c4f, 0x2d4a6354, 0x324e0387, 0x50e5d0c9, 0x25943285, 0xf99f5f1b, 0xc70faa58, 0x0eddefd2, 0xfb9c460d, 0xb1ae7299, 0xfd9ff80e, 0x6a75829f, 0x0add48c7, 0xe348bb46, 0x79af1488, 0x9f342b40, 0xcdd2e29f, 0xd70506c2, 0xb5aed58c, 0xb27e4814, 0x97ea7a91, 0x140a0b8f, 0x66ab745b, 0xeb96ea97, 0x677857c0, 0xde087488, 0x4be1170f, 0x2f497a42, 0x81e36808, 0x319e390a, 0x21949590, 0xa674439b, 0x6da51f07, 0xb7adcc9a, 0x7571e24c, 0x76a1d8c1, 0xed955494, 0xb3ad6b8f, 0x2047b60b, 0x88ee1a42, 0x7facaa8b, 0xda08d39d, 0xd305a1d7, 0x13da9617, 0xe14ba250, 0x903ae709, 0x26440808, 0xdbdbf006, 0x8d3d9ecc, 0x8ceebd57, 0x433f46de, 0xf742b0c9, 0x0603be03, 0x01d3239b, 0x64a86d4d, 0x787c3713, 0xc4df90d5, 0x80304b93, 0x8633f590, 0x5bebbb95, 0xa274e48e, 0x4e329381, 0x9ae7afce, 0x5136f352, 0xab7996c4, 0xe29b98dd, 0x3f43d6d8, 0x7e7f8910, 0xc50cb34e, 0x55365447, 0xf2913447, 0x23978c86, 0x453cf8dd, 0x46ecc250, 0x44efdb46, 0xce02d812, 0xc2dc2ed6, 0xcbd15c9c, 0x5a38980e, 0x5feb1c80, 0x7c7c9006, 0x344dbd84, 0xbca3a7c6, 0x82335285, 0x090d724a, 0x5335ea44, 0x00000000, 0xaaaab55f, 0xbea0bed0, 0x85e3cf1d, 0x15d92814, 0x1209b58c, 0xe995f381, 0xcc01c104, 0x413c5fc8, 0xfc4cdb95, 0xd2d6824c, 0xa8a9ac49, 0xf1410eca, 0x6ba6a104, 0x6c763c9c, 0x4c318a97, 0xc8016611, 0x38934b40, 0xaca90b5c, 0xec46770f, 0x657b4ed6, 0xd6d62559, 0x83e0711e, 0x5e383f1b, 0x379d8709, 0x93eadd84, 0x1907ded0, 0xbb733a5e, 0xe54b0545, 0xd5061fd4, 0xd0d59b5a, 0x1d0779c5, 0x294ac441, 0xddd84e05, 0x9239fe1f, 0xc6dc89c3, 0x2b49dd57, 0xb07d5102, 0x339d201c, 0xc10c145b, 0xd9d8e910, 0xd106b8c1, 0x304d1a91, 0x60a8ca58, 0x0400a715, 0x8aed0354, 0x62abd34e, 0x69a5b812, 0xb9702348, 0xbf739d4b, 0x100aac9a, 0x48312d82, 0x9ee708db, 0x98e4b6d8, 0x7a7f2e05, 0xa3a7c715, 0x359e9e1f, 0x16091299, 0x3d40cfce, 0x7bac0d9e, 0x57354d51, 0x8b3e20cf, 0x2e9a59d9, 0x18d4fd4b, 0x17da3102, 0x5c3b260d, 0x893d39d9, 0xdc0b6d9e, 0xea45c90c, 0xe09881cb, 0xa7a76000, 0x0b0e6b5c, 0x54e577dc, 0xa1a4de03, 0x73725c4f, 0xad7a28c7, 0x59e8a283, 0xf84c7c80, 0xaeaa124a, 0x3b4371cd, 0x4de2a90c, 0x2244af1d, 0x05d3848e, 0x617be9c3, 0xd80bca8b, 0xc0df37c0, 0xc30f0d4d, 0x1cd45a5e, 0x52e6c9df, 0x7dafb39d, 0x70a266c2, 0x943a401c, 0x2c9940cf, 0xb8a300d3, 0xfa4f6596, 0x42ec6545, 0x87e0d60b, 0x68769b89, 0x95e96387, 0x1ed74348, 0x1ad7e45d, 0xf6919352, 0x5de80596, 0x3c93ec55, 0xdfdb5713, 0xee456e19, 0x6e75258a, 0x03d03a8d, 0x473fe1cb, 0x4a323494, 0x364ea492, 0x9d373256, 0x72a17fd4, 0xe846d01a, 0x8430ec86, 0x0d0dd55f, 0x1f0460d3 +}, +{ +0xca5e8b9e, 0x79e758d2, 0xb001d26b, 0x66133445, 0x845066ce, 0xe54e2500, 0x4ca362b4, 0x76795cb5, 0xcd53fc15, 0x14df1e5c, 0x7061a5fd, 0x3451b4a5, 0xa9ed47b4, 0x2f10ae9e, 0x5969f22b, 0xecc8d82f, 0x0986fd2f, 0xaff5befc, 0x0e8b8aa4, 0x57e2788f, 0xa67343d3, 0x0f9e0467, 0xd98ce249, 0x3ada3e01, 0xeddd56ec, 0x17671f7b, 0x9ca97dd2, 0x3877b1e5, 0x2e05205d, 0x31f14cca, 0xc9e68ab9, 0x86fde92a, 0x2dbd217a, 0xe243528b, 0xf817c673, 0xa06bba9b, 0x9e04f236, 0xaee0303f, 0x12c7e714, 0x835d1145, 0xcc4672d6, 0x8545e80d, 0x335cc32e, 0x545a79a8, 0xb4b4a4c7, 0xe7e3aae4, 0x8f7b1405, 0xe6f62427, 0x1ff46c97, 0x600bcd0d, 0x908f7892, 0xd2a79082, 0xf789c214, 0xdf941b01, 0xb892a187, 0x943a0e3e, 0x65ab3562, 0x7b4ad736, 0x0b2b72cb, 0x469d9ebc, 0xbc27d72b, 0x00000000, 0x0c260540, 0x63b3cc2a, 0x106a68f0, 0xf1913b5c, 0xead02167, 0xc0607796, 0x4abb9bfc, 0xba3f2e63, 0x8bce62a9, 0xb6192b23, 0x1a5494f8, 0x089373ec, 0xb5a12a04, 0x53570e23, 0x04b576ac, 0xd8996c8a, 0xebc5afa4, 0x39623f26, 0x6706ba86, 0x7eea2f59, 0xe45babc3, 0xfe0f3f3b, 0x18f91b1c, 0x8adbec6a, 0xb2ac5d8f, 0xa2c6357f, 0x3e6f48ad, 0x4788107f, 0x9f117cf5, 0x51fa81c7, 0xbe8a58cf, 0x433d66d3, 0x19ec95df, 0xa766cd10, 0x62a642e9, 0xcffe73f1, 0x4e0eed50, 0xee6557cb, 0x45259f9b, 0xd5aae709, 0xe0eedd6f, 0x117fe633, 0xfca2b0df, 0xd3b21e41, 0x74d4d351, 0x4f1b6393, 0x2336abde, 0x82489f86, 0x81f09ea1, 0x72cc2a19, 0xbb2aa0a0, 0xc5c08ff9, 0x6b20bfc6, 0x7c47a0bd, 0x6898bee1, 0x290857d6, 0x4bae153f, 0x8dd69be1, 0xaa554693, 0x933779b5, 0x80e51062, 0x49039adb, 0x611e43ce, 0x5ddc8487, 0x6f95c96a, 0x587c7ce8, 0x48161418, 0x408567f4, 0x219b243a, 0xff1ab1f8, 0x1b411a3b, 0x281dd915, 0x13d269d7, 0xde8195c2, 0x7a5f59f5, 0xceebfd32, 0x0a3efc08, 0x919af651, 0xb70ca5e0, 0xdb216dad, 0xac4dbfdb, 0x1d59e373, 0x15ca909f, 0x981c0b7e, 0xc175f955, 0x9ba40a59, 0xa4decc37, 0x070d778b, 0x3bcfb0c2, 0xd11f91a5, 0x71742b3e, 0xd4bf69ca, 0xbf9fd60c, 0x3f7ac66e, 0x4190e937, 0x6c2dc84d, 0x2ca8afb9, 0x2ba5d832, 0x698d3022, 0x8963ed4d, 0xda34e36e, 0x32494ded, 0xf33cb4b8, 0x87e867e9, 0xad583118, 0xfbafc754, 0xf90248b0, 0x3cc2c749, 0x8e6e9ac6, 0xf69c4cd7, 0x02ad8fe4, 0x01158ec3, 0x269653b1, 0x78f2d611, 0x990985bd, 0x167291b8, 0x5bc47dcf, 0xc8f3047a, 0x7d522e7e, 0xc4d5013a, 0x56f7f64c, 0x97820f19, 0x44301158, 0xe87dae83, 0x05a0f86f, 0x37e9b582, 0x35443a66, 0xdc2c1a26, 0x554ff76b, 0x208eaaf9, 0xc6788ede, 0x5ad1f30c, 0x9ab1849a, 0x3dd7498a, 0x9222f776, 0x6d38468e, 0xe9682040, 0x5e6485a0, 0xc76d001d, 0xe1fb53ac, 0x4228e810, 0xd70768ed, 0xe356dc48, 0xf2293a7b, 0xf431c333, 0xfdb73e1c, 0x0618f948, 0x8876638e, 0xc3d876b1, 0x30e4c209, 0x1ee1e254, 0x0d338b83, 0x243bdc55, 0xd612e62e, 0x2ab056f1, 0x75c15d92, 0xab40c850, 0xcb4b055d, 0x36fc3b41, 0xb3b9d34c, 0xbd3259e8, 0x5f710b63, 0x252e5296, 0xb1145ca8, 0x2783dd72, 0xd00a1f66, 0x50ef0f04, 0x64bebba1, 0x6e8047a9, 0x1c4c6db0, 0xf5244df0, 0x969781da, 0x7fffa19a, 0xc2cdf872, 0x5cc90a44, 0x524280e0, 0xa17e3458, 0xfaba4997, 0xef70d908, 0x03b80127, 0x2223251d, 0xa8f8c977, 0xf084b59f, 0x9dbcf311, 0xb9872f44, 0x73d9a4da, 0x8cc31522, 0xdd3994e5, 0xa5cb42f4, 0xa3d3bbbc, 0x4db6ec77, 0x952f80fd, 0x6a353105, 0x776cd276 +}, +{ +0x5e167de2, 0x9759bd8c, 0x3c2f62e4, 0x743807de, 0xd3c51d06, 0x94da48de, 0x870bbaa1, 0x39db4e0d, 0xec698ab0, 0xa8d1ec74, 0x2c59a387, 0x6d15e9aa, 0x9d8167c9, 0xd3e1db48, 0xd046e854, 0x646a00f3, 0xf9eb673a, 0x35744df3, 0x414c4a2d, 0xad25c09d, 0xe9b96017, 0xff9cbe81, 0xdf6a1ef8, 0xe6b150f5, 0x511e4d00, 0x20d26637, 0x9289572b, 0x6b46f65f, 0xa2093631, 0xffb878cf, 0xf9cfa174, 0xe0e24f00, 0x35508bbd, 0x03a7331c, 0x68e1c543, 0xbed0f4ac, 0x92ad9165, 0x644ec6bd, 0xd0622e1a, 0xc3b3dc65, 0xbd77c7b0, 0x7b30373c, 0x0caf03fe, 0x77bbf28c, 0x5861a459, 0xc5c405de, 0xad0106d3, 0x3fac97b6, 0x67cd33ef, 0x473b9396, 0x1076c163, 0x724fde65, 0xf0b0482d, 0x13f53431, 0x62391f06, 0x33039448, 0x0c8bc5b0, 0x0677d9bb, 0xb7af1df5, 0xdf4ed8b6, 0x0f2cf6ac, 0x574d52f5, 0x23519365, 0x44b866c4, 0x5db14efe, 0x7ec41bd5, 0x8ba4b95f, 0x2ffe909b, 0x58456217, 0xa22df07f, 0x84884ff3, 0x471f55d8, 0x3f8851f8, 0x94fe8e90, 0xf6e357d8, 0xc647f08c, 0x78b3c26e, 0x2a2e7a3c, 0x4b949068, 0x68c5030d, 0x67e9f5a1, 0xbd5301fe, 0x726b182b, 0x42eb7931, 0x78970420, 0x097fe959, 0x8158a554, 0xa7d9dc96, 0x25028c90, 0xcf3819d5, 0xe361ba52, 0x6b623011, 0xf6c79196, 0xe69596bb, 0x7d6328c9, 0x095b2f17, 0x5be2510b, 0x30a4a754, 0xbef432e2, 0x41688c63, 0x4de349d3, 0x7ee0dd9b, 0x42cfbf7f, 0x1f5a37cf, 0xb42ce8a7, 0x0f0830e2, 0x619e2c1a, 0xd615f7a1, 0x98518d6e, 0x8e5095b6, 0xbb24d845, 0x88038a43, 0xd63131ef, 0x2c7d65c9, 0xf3177b31, 0xcae8f372, 0xfa689268, 0xea1e530b, 0x192dee74, 0x4e60bc81, 0x6e961cf8, 0x8e7453f8, 0xe0c6894e, 0x98754b20, 0x5d9588b0, 0x912e6437, 0xefceb9ac, 0x6d312fe4, 0xb78bdbbb, 0xdce9ebaa, 0x8dd360e4, 0x15a62bc4, 0xc0302937, 0x3080611a, 0xdabaf45f, 0xe51663e9, 0xa47eef8a, 0xda9e3211, 0x576994bb, 0x7d47ee87, 0x00000000, 0x2a0abc72, 0xea3a9545, 0xefea7fe2, 0x33275206, 0x9da5a187, 0xab521926, 0x82db5006, 0xbb001e0b, 0x05f42ce9, 0x26a5bf8c, 0x910aa279, 0x160118d8, 0xf333bd7f, 0xc66336c2, 0xe3457c1c, 0x5e32bbac, 0x0afc1c0b, 0xfc3b8d9d, 0xc94fc06e, 0x1909283a, 0x82ff9648, 0x9bd2783c, 0x1052072d, 0xb25b311c, 0x9bf6be72, 0x61baea54, 0xf0948e63, 0xfc1f4bd3, 0x817c631a, 0x9e02929b, 0xfa4c5426, 0x1cfd04d3, 0xc014ef79, 0x4bb05626, 0x9e2654d5, 0x5bc69745, 0xc3971a2b, 0x872f7cef, 0xc5e0c390, 0xa18ac363, 0xb4082ee9, 0xe99da659, 0x88274c0d, 0xa1ae052d, 0x513a8b4e, 0x71e8ed79, 0xd939010d, 0x621dd948, 0x29ad8f6e, 0x2375552b, 0x8b807f11, 0x71cc2b37, 0xb8a72d17, 0x36d37eef, 0xcacc353c, 0x52b97e1c, 0x977d7bc2, 0x36f7b8a1, 0x1a8add68, 0x4817653a, 0x741cc190, 0xe532a5a7, 0x7b14f172, 0x449ca08a, 0x1582ed8a, 0x29894920, 0x05d0eaa7, 0xae82f381, 0x4833a374, 0xdccd2de4, 0x779f34c2, 0x1f7ef181, 0x0ad8da45, 0xccbbec87, 0xcc9f2ac9, 0x2fda56d5, 0x4dc78f9d, 0xd59602f3, 0x1625de96, 0x84ac89bd, 0x8df7a6aa, 0x268179c2, 0xd91dc743, 0xc96b0620, 0x25264ade, 0xb27ff752, 0x0383f552, 0xa45a29c4, 0x4e447acf, 0x54ea61e9, 0x3a58bb5f, 0xf560a28a, 0xaea635cf, 0xab76df68, 0xa7fd1ad8, 0x3a7c7d11, 0xd5b2c4bd, 0x39ff8843, 0xec4d4cfe, 0x0024c64e, 0x6eb2dab6, 0x1cd9c29d, 0x13d1f27f, 0x1aae1b26, 0xb883eb59, 0xf54464c4, 0x06531ff5, 0x20f6a079, 0xb1fc0200, 0x54cea7a7, 0xa8f52a3a, 0x529db852, 0xcf1cdf9b, 0x3c0ba4aa, 0xb1d8c44e +}, +{ +0x9ee09671, 0x3536a206, 0x5a012bbf, 0xbb852595, 0x1dfe7d97, 0xabd63477, 0x59783099, 0x18acde57, 0xcbd746af, 0xfa51cb5b, 0xac1f00a3, 0xf2ae04ee, 0x9929a2a5, 0xc1b31e0e, 0xd1e00fec, 0x5dc81f6b, 0x9bb235b1, 0x0ed47753, 0xc328891a, 0xc67a2ada, 0x691c315f, 0x24873fd6, 0x864c4826, 0xdf3478bf, 0x98cb2e97, 0x8067f0c0, 0xe2fd150c, 0xae8497b7, 0x67c8460c, 0xb62849e0, 0x5c2a9359, 0xe1840e2a, 0xebe0568b, 0x589abcab, 0xd8fd4c6b, 0xbc4c1141, 0x306401c6, 0xd91fc059, 0x61e3feea, 0x5537d0de, 0x6ed5058b, 0x9034e122, 0xb91eb281, 0xc051923c, 0x00000000, 0x88983f75, 0xb8fc3eb3, 0x4ee215af, 0xe7afb6cc, 0x92af7636, 0x831eebe6, 0xc4e1bdce, 0x389bce73, 0x07c934d4, 0xaa34b845, 0xb003f106, 0x82fc67d4, 0x261ca8c2, 0x091d4387, 0x6c4e929f, 0x9c7b0165, 0x1bd5c571, 0x3a005967, 0xe4d6adea, 0x1501b222, 0x6553d118, 0xec29625f, 0xcf67695d, 0x9f021a43, 0xd6293b38, 0x7679dbdc, 0x331d1ae0, 0x1f65ea83, 0x84d7df32, 0x72c9f42e, 0xa1b26cd6, 0xc2ca0528, 0x7dff0f4f, 0x0dad6c75, 0x7052633a, 0xf1d71fc8, 0x4564c13c, 0x68febd6d, 0x74e24cc8, 0xa050e0e4, 0xf7fca72e, 0xeeb2f54b, 0x39794241, 0x934dfa04, 0x234e0b02, 0x87aec414, 0xbdae9d73, 0xbed78655, 0xddafefab, 0x0a6458a1, 0xd29914ca, 0x132a0ac4, 0x062bb8e6, 0xe0668218, 0x2bb1c4b7, 0x4f00999d, 0x78adac8f, 0x11b19dd0, 0x5187ff2c, 0xef507979, 0xe53421d8, 0xa4e0cf16, 0xf928d07d, 0x3c2be181, 0x4d9b0e89, 0x47ff5628, 0xf61e2b1c, 0x7500c0fa, 0x1e8766b1, 0xa94da363, 0x2a534885, 0x564ecbf8, 0xea02dab9, 0xe31f993e, 0x12c886f6, 0x7e861469, 0x194e5265, 0x8c281087, 0x732b781c, 0x0c4fe047, 0x292a53a3, 0x5be3a78d, 0x5f53887f, 0x2f01eb45, 0x3eb07695, 0x7c1d837d, 0xce85e56f, 0x8eb38793, 0x5eb1044d, 0x8be12453, 0xff03689b, 0xf03593fa, 0x08ffcfb5, 0x22ac8730, 0xdb84574d, 0xa5024324, 0x37ad3512, 0xba67a9a7, 0x34d42e34, 0x91d66d10, 0x029b9714, 0x4a523a5d, 0xdc4d6399, 0xe97bc19f, 0x85355300, 0x961f59c4, 0x1678a904, 0xd37b98f8, 0xc8ae5d89, 0x1a374943, 0x662aca3e, 0xedcbee6d, 0x48c9ad49, 0xadfd8c91, 0xcdfcfe49, 0x6dac1ead, 0x897ab347, 0xfbb34769, 0x14e33e10, 0xb55152c6, 0x461dda1a, 0x32ff96d2, 0xfc7a73bd, 0x81857cf2, 0x4c7982bb, 0xb1e17d34, 0x7bd4b7a9, 0x637869fe, 0x44864d0e, 0x7a363b9b, 0xaf661b85, 0xcc1e727b, 0xded6f48d, 0xca35ca9d, 0x4bb0b66f, 0x779b57ee, 0x04b02ff2, 0x97fdd5f6, 0x6b87a64b, 0x71b0ef08, 0x629ae5cc, 0x7f64985b, 0x42adf5e8, 0xa67b5802, 0xf567303a, 0x3dc96db3, 0x52fee40a, 0x6a652a79, 0x28c8df91, 0x3f52faa7, 0x3be2d555, 0xe8994dad, 0xfee1e4a9, 0x0552a3c0, 0xa799d430, 0xd550201e, 0x1c1cf1a5, 0xa8af2f51, 0x434f79da, 0x956642e2, 0x179a2536, 0xc94cd1bb, 0x2ee36777, 0xb2986612, 0x403662fc, 0xd7cbb70a, 0xda66db7f, 0x03791b26, 0x492b217b, 0x6f3789b9, 0x27fe24f0, 0xb4b3def4, 0xe64d3afe, 0xa329fbc2, 0x64b15d2a, 0xa2cb77f0, 0x41d4eece, 0xbf350a67, 0x8a03a861, 0x531c6838, 0x0f36fb61, 0x105311e2, 0x8f510ba1, 0x54d55cec, 0x57ac47ca, 0xfd98ff8f, 0xf34c88dc, 0xc50331fc, 0xb7cac5d2, 0xd00283de, 0xf8ca5c4f, 0xc798a6e8, 0x794f20bd, 0x20371024, 0x8dca9cb5, 0x600172d8, 0x01e28c32, 0x2d9a7c51, 0xf485bc08, 0x364fb920, 0xd4b2ac2c, 0x0b86d493, 0x5065731e, 0x9484ced0, 0x2c78f063, 0x9d998d57, 0xb37aea20, 0x21d59c16, 0x9a50b983, 0x31868df4, 0x2565b3e4 +}, +{ +0xd05e307d, 0x1e90abe1, 0x7429e367, 0xe1de16f7, 0x97b77dfc, 0xe6b151d7, 0x2f108d6b, 0x58a0e1c4, 0xfa61725a, 0xc3344233, 0xdda4e9d2, 0x2a3f4227, 0xc174ca5f, 0x2ec98acf, 0x61f5d1ad, 0xbae778fb, 0xbd883fdb, 0x85040816, 0x112afa22, 0x08d516e3, 0x826b4f36, 0xc0adcdfb, 0x5fcfa6e4, 0x1cd0238d, 0x7346a447, 0xde3d661a, 0x1a666309, 0xbe11b013, 0x179cbaa6, 0xa8540d11, 0xabcd82d9, 0x22ea54c4, 0x261c9c2c, 0x0240886c, 0x0a959e8f, 0xca385374, 0x258513e4, 0x3059212e, 0x29a6cdef, 0xb8a7f097, 0xdfe461be, 0x8e48913d, 0x48531c42, 0x7ebc7de8, 0x20aadca8, 0xbfc8b7b7, 0x6ab94886, 0xb072e674, 0x729fa3e3, 0x3b15b805, 0x602cd609, 0x70df2b8f, 0xc878db18, 0xe4f1d9bb, 0x95f7f590, 0x498a1be6, 0x19ffecc1, 0x83b24892, 0x1826eb65, 0xd18737d9, 0x9d22e373, 0xaf3b4a31, 0x03998fc8, 0x33c0aee6, 0x869d87de, 0x8744807a, 0x9a4da453, 0x0e635667, 0x27c59b88, 0xf9f8fd92, 0x245c1440, 0x942ef234, 0x81f2c0fe, 0x7a4ab500, 0x65031945, 0xf642ac51, 0xc9a1dcbc, 0x0b4c992b, 0x79d33ac8, 0xa1581c56, 0x136a724e, 0x9341b514, 0xc7c28adb, 0x3180268a, 0x1645bd02, 0x7cfcf584, 0x06b64084, 0x3da3f881, 0x966e7a58, 0xf5db2399, 0x77b06caf, 0xaee24d95, 0x53ec78ef, 0xf821fa36, 0xd88b269e, 0xe7685673, 0xb3eb69bc, 0xb71da154, 0x4f3c5b62, 0xfe97bab2, 0xdacbaef2, 0x9cfbe4d7, 0x802bc75a, 0x431f8569, 0x45a9c5ed, 0x2d500507, 0xc45b0513, 0x9f626b1f, 0x5ae069a8, 0x555a386b, 0x3219a942, 0x5b396e0c, 0x052fcf4c, 0x1405356e, 0xb2326e18, 0x5979e660, 0xd4a8f895, 0x46304a25, 0x6b604f22, 0x8b675e71, 0x2be64583, 0x6f9687ca, 0x3fe370ed, 0xb1abe1d0, 0xe8d207b0, 0xe0071153, 0x67439129, 0xd3c7bfb5, 0x415f0d05, 0xf402243d, 0xc2ed4597, 0xa5aed4be, 0xe39e9e9b, 0xcc8e13f0, 0x12b375ea, 0xdb12a956, 0x3736660e, 0x4ee55cc6, 0x5c56292c, 0x8abe59d5, 0xea928fdc, 0xedfdc8fc, 0xfbb875fe, 0x15dc32ca, 0x99d42b9b, 0xd952213a, 0xeb4b8878, 0xbc51387f, 0xe90b0014, 0x6e4f806e, 0x980d2c3f, 0xa98d0ab5, 0x8c081951, 0x01d907a4, 0xa6375b76, 0xaa14857d, 0x780a3d6c, 0xaca2c5f9, 0x9b94a3f7, 0x4470c249, 0xa318943a, 0x68f9c0ea, 0xfd0e357a, 0x1f49ac45, 0x3e3a7749, 0x42c682cd, 0x4d7cd30e, 0x40860aa1, 0xec24cf58, 0xee644734, 0xb4842e9c, 0xc61b8d7f, 0x626c5e65, 0x75f0e4c3, 0x5d8f2e88, 0x23335360, 0xa0811bf2, 0xcd571454, 0x8f919699, 0x388c37cd, 0x4bca938a, 0xf36d631d, 0x7d25f220, 0x36ef61aa, 0xf0f4ecd5, 0x8dd11ef5, 0xc58202b7, 0x669a968d, 0x84dd0fb2, 0xa477d31a, 0x1d092429, 0xf12deb71, 0x90d83adc, 0x2c8902a3, 0x0fba51c3, 0xff4ebd16, 0x04f6c8e8, 0x1bbf64ad, 0x63b559c1, 0xe247993f, 0x9298b2b0, 0xdc7dee76, 0x7f657a4c, 0xd6e870f9, 0x76696b0b, 0xa7ee5cd2, 0xcbe154d0, 0x3576ee62, 0xd731775d, 0x4a13942e, 0xb6c4a6f0, 0x34afe9c6, 0x6c0f0802, 0x00000000, 0x56c3b7a3, 0xcece9b9c, 0x64da1ee1, 0x10f3fd86, 0x076f4720, 0x0dfad9af, 0xf79babf5, 0xa2c1939e, 0x52357f4b, 0x39553069, 0x6920c74e, 0xd21eb811, 0xfcd732de, 0xefbd4090, 0x47e94d81, 0xb55d2938, 0x5075f727, 0xad7bc25d, 0x8927d61d, 0x6dd60fa6, 0x3accbfa1, 0x090c1147, 0xd571ff31, 0x3c7aff25, 0x7b93b2a4, 0xe528de1f, 0x54833fcf, 0x0c23de0b, 0x51acf083, 0xb97ef733, 0x4ca5d4aa, 0x287fca4b, 0x571ab007, 0xf2b464b9, 0x91013d78, 0x5e16a140, 0x71062c2b, 0x2173db0c, 0xcf179c38, 0x88fed1b9, 0xbb3e7f5f, 0x9ebb6cbb +} +}, +{ +{ +0x22a6dd54, 0xb06f7ba9, 0xe49d3568, 0xf3bab84b, 0xa393c625, 0xeb6274a1, 0x58be3998, 0xe31b679d, 0xda381479, 0x25208fa1, 0x078652f5, 0x54f24ec1, 0x18d8ccea, 0x661b1889, 0x65467ad3, 0x57af2c9b, 0x92c9a6fd, 0x32e95648, 0x7a18e4cc, 0x2eeaaa0d, 0xaf31e5b6, 0x8a116a17, 0x104f8b1c, 0x3ea52111, 0x53741c34, 0xb3dc4d39, 0x0ca22393, 0xf78fdc2e, 0x32070282, 0xbc230cf0, 0x35815077, 0x2a319aa2, 0x470ef34d, 0x21fbbf0e, 0xe04605c7, 0x1ceda88f, 0x6a576fd0, 0xbf7e6eaa, 0x50297e6e, 0xa748f68a, 0xb45a1fcc, 0x6dd13d25, 0x44539117, 0x0f111503, 0xfff6cf12, 0xac6c87ec, 0x03b33690, 0xa7a6a240, 0x728fa33a, 0x25cedb6b, 0x76549395, 0xc5668a66, 0xac82d326, 0x96fcc298, 0xe72e03f8, 0xfb2dffbd, 0xb7e9295c, 0x2adfce68, 0x00000000, 0xc1bdbac9, 0xde0d701c, 0x9e6b856e, 0xf8709de7, 0xf354ec81, 0xafdfb17c, 0x89a25c87, 0x85007f14, 0xf4d2be74, 0x8d796c28, 0x9e85d1a4, 0x81db4fbb, 0x81351b71, 0xc20e8c59, 0x6e8c5f7f, 0xc2e0d893, 0xe47361a2, 0x4b428414, 0xff189bd8, 0xceacafca, 0xef5710c4, 0xca99cbaf, 0x4bacd0de, 0x79abd25c, 0x4f99b4bb, 0xfbc3ab77, 0x1494bbb3, 0xec0a729e, 0x539a48fe, 0xdee324d6, 0xbf903a60, 0xca779f65, 0x61731eb6, 0xeb8c206b, 0xece42654, 0x2e04fec7, 0x76bac75f, 0x713c95aa, 0xf0e7da11, 0x18369820, 0x8eca5ab8, 0x7af6b006, 0x10a1dfd6, 0xf76188e4, 0x47e0a787, 0xc6d5bcf6, 0xe7c05732, 0xb7077d96, 0x2d599c9d, 0xe0a8510d, 0x8268792b, 0x5c8b5dfd, 0x5b0d0f08, 0xcd1f995a, 0x04db30af, 0x433b9728, 0x2982ac32, 0x4cc4d6e1, 0x79458696, 0x99038351, 0x7509f1cf, 0xd529017a, 0x9d36e734, 0xc153ee03, 0x17278d23, 0xa41594d0, 0x17c9d9e9, 0xc63be83c, 0x04356465, 0x865d1d4e, 0xd1f231d5, 0xb33219f3, 0x1f5e9e1f, 0x0bca25ac, 0x8d9738e2, 0x9ab0b5c1, 0x541c1a0b, 0x5be35bc2, 0x4088a1b8, 0x9227f237, 0x5fd63fa7, 0x66f54c43, 0x6e620bb5, 0x0768063f, 0x0879133c, 0xfc45f982, 0x62c02826, 0xb4b44b06, 0x8e240e72, 0x089747f6, 0x7d70e2f3, 0x58506d52, 0x954ff408, 0xe3f53357, 0x57417851, 0xcdf1cd90, 0x6ab93b1a, 0x86b34984, 0x917a906d, 0xe83f16fb, 0x96129652, 0xefb9440e, 0xb0812f63, 0xa37d92ef, 0x2115ebc4, 0x5c650937, 0x622e7cec, 0x296cf8f8, 0xd98b22e9, 0xa8b7b743, 0x392373e4, 0xf0098edb, 0xa0cea47f, 0x356f04bd, 0x9dd8b3fe, 0xd6746320, 0x4f77e071, 0x2248899e, 0x5f386b6d, 0x690a0d8a, 0xbccd583a, 0x43d5c3e2, 0x85ee2bde, 0xc588deac, 0xa859e389, 0x7d9eb639, 0x0fff41c9, 0x2693b931, 0xe8d14231, 0x481fe64e, 0x147aef79, 0x3e4b75db, 0x7ec3d463, 0x9194c4a7, 0xce42fb00, 0x3df8434b, 0x363266e7, 0x267dedfb, 0xf89ec92d, 0x75e7a505, 0xc9c4a9f5, 0xab0481d3, 0x95a1a0c2, 0xd11c651f, 0xa020f0b5, 0xb8f83c5f, 0x3a7e11be, 0x00ee54ca, 0x39cd272e, 0x48f1b284, 0x99edd79b, 0xdad640b3, 0x0b247166, 0xfcabad48, 0xddbe468c, 0xd9657623, 0x44bdc5dd, 0x619d4a7c, 0x31b43412, 0xbba55e05, 0xb8166895, 0x1312e946, 0xf43ceabe, 0x7261f7f0, 0x13fcbd8c, 0xabead519, 0x6d3f69ef, 0x035d625a, 0x1b85aeb0, 0x0c4c7759, 0xc92afd3f, 0x1b6bfa7a, 0x69e45940, 0x1fb0cad5, 0x9a5ee10b, 0xbb4b0acf, 0x315a60d8, 0x2db7c857, 0x1c03fc45, 0xd2410745, 0x65a82e19, 0x36dc322d, 0xd5c755b0, 0x4c2a822b, 0x71d2c160, 0xa4fbc01a, 0xdd501246, 0x50c72aa4, 0x8aff3edd, 0xd2af538f, 0x894c084d, 0x82862de1, 0x4066f572, 0x3a904574, 0x7e2d80a9, 0xd69a37ea, 0x3d161781 +}, +{ +0x4e99db4b, 0xe44e310d, 0x235f682a, 0x6b74d4de, 0x21a36d2f, 0x40fbb42b, 0xac2f0c33, 0xdc0e8ca3, 0x0c9e6a65, 0x1f51b73e, 0xea2c5e6d, 0xbfaa50a2, 0x4603525e, 0x19a9514b, 0x9e43bc47, 0x06b267bf, 0xd090e6c6, 0xd0da670c, 0x611258ce, 0x0a668c10, 0xb3343ac7, 0x44ff575b, 0x98f1dbf8, 0xdef289a6, 0x55cc8f05, 0x81120b79, 0xe2fc56b2, 0x3840bdae, 0xfb5507f9, 0xe00053b7, 0xd66800b3, 0x34945601, 0x87a06cc6, 0xee623cd7, 0xbbe43218, 0x7cf56b3f, 0x15373b2e, 0xf57de953, 0xc1e9bf52, 0x482bbcf4, 0x424d30e4, 0x1f1b36f4, 0x8f3ae5d3, 0x089a8915, 0xbd5655a7, 0x06f8e675, 0x2f8b8385, 0x78bb0985, 0x5be461af, 0x96d93552, 0x8d8c611c, 0x27110a90, 0x4ad7b9f1, 0xfb1f8633, 0x326cb074, 0xbfe0d168, 0x8b3e06a3, 0xc9733647, 0x44b5d691, 0x5faa0315, 0x7e43eff0, 0x63ee5dcb, 0xf1338be9, 0x30da34bb, 0x13855c91, 0x0404e370, 0x87eaed0c, 0xaad7ea46, 0xd4de847c, 0xc1a33e98, 0x0cd4ebaf, 0x6b3e5514, 0xa24d6353, 0xfdade18c, 0xd49405b6, 0x9021d327, 0x5952e560, 0xb5865d78, 0x69c25011, 0xbbaeb3d2, 0xf3850f26, 0xb918371d, 0x11795994, 0xc35f3b9d, 0x1b1fd584, 0xec9e39d2, 0xee28bd1d, 0x6d8c32ab, 0x380a3c64, 0x5baee065, 0x34ded7cb, 0xe8d05b68, 0x7693e72f, 0x02b684cf, 0x9cf53888, 0x655c3a74, 0xb77a587d, 0x906b52ed, 0x3c445ede, 0xb952b6d7, 0xe6f8b5c2, 0xd26ce3c3, 0x19e3d081, 0xc939b78d, 0x9a0ddefd, 0xcb8f3342, 0x8f706419, 0xf9a902fc, 0x55860ecf, 0xdaf66ad6, 0x78f1884f, 0xd80a6fd3, 0x1781bfe1, 0x25ed0f95, 0xdabceb1c, 0x13cfdd5b, 0x89c203a6, 0xcf8bd032, 0xae9988fc, 0x94253057, 0x8516e809, 0x2315e9e0, 0xb37ebb0d, 0x577a0bca, 0xa207e299, 0x9a475f37, 0x6988d1db, 0xcbc5b288, 0xd840ee19, 0x83a48fb6, 0xf781ec56, 0xff1b6543, 0xa0fbe79c, 0xc5a7dde8, 0x6f3ab664, 0xa4ff04ec, 0x00000000, 0xac658df9, 0x742563e0, 0xe2b6d778, 0x3622d2ce, 0xa6498023, 0x98bb5a32, 0x6516bbbe, 0xdeb8086c, 0xc75bd8ed, 0x83ee0e7c, 0x72dd8595, 0x76d966e5, 0x5d560610, 0xbd1cd46d, 0xb5ccdcb2, 0x706b015a, 0x1dadb23b, 0x25a78e5f, 0x6158d904, 0x5182edbf, 0xff51e489, 0xea66dfa7, 0xcd3d54fd, 0x36685304, 0x6f7037ae, 0x2939e43a, 0x0a2c0dda, 0x8b748769, 0xe404b0c7, 0x3eb85bdb, 0x63a4dc01, 0x4c2f5f84, 0x8988826c, 0x855c69c3, 0xf9e38336, 0x746fe22a, 0x40b135e1, 0xa82bef43, 0x4649d394, 0xf1790a23, 0x044e62ba, 0x81588ab3, 0xa8616e89, 0xb730d9b7, 0x2d3d074a, 0x7297045f, 0x4ed35a81, 0xdc440d69, 0x591864aa, 0x157dbae4, 0x5d1c87da, 0xa0b16656, 0xaa9d6b8c, 0x4a9d383b, 0x53346970, 0x0e28eeaa, 0x1133d85e, 0xe04ad27d, 0x2fc1024f, 0x1b55544e, 0x2bc5e13f, 0xb182be08, 0xc5ed5c22, 0x0e626f60, 0xf5376899, 0x08d008df, 0x9693b498, 0x70218090, 0x8dc6e0d6, 0xaed30936, 0x57308a00, 0xe89adaa2, 0x4c65de4e, 0xa60301e9, 0xf7cb6d9c, 0x2b8f60f5, 0x21e9ece5, 0x946fb19d, 0x297365f0, 0xd6228179, 0x3ef2da11, 0xd2266209, 0x02fc0505, 0x3af63961, 0xe6b23408, 0x7cbfeaf5, 0x004a81ca, 0x67eabebb, 0x4207b12e, 0x3c0edf14, 0xcfc151f8, 0x3090b571, 0x275b8b5a, 0x67a03f71, 0xa4b58526, 0x9e093d8d, 0x2d778680, 0x3abcb8ab, 0x17cb3e2b, 0xcd77d537, 0x7a470c80, 0xecd4b818, 0x929757e8, 0x7e096e3a, 0x7a0d8d4a, 0x9cbfb942, 0x322631be, 0x51c86c75, 0xf3cf8eec, 0x1de733f1, 0xc7115927, 0x5fe082df, 0x537ee8ba, 0xfde76046, 0x92ddd622, 0xb1c83fc2, 0xc315ba57, 0x6dc6b361, 0x48613d3e +}, +{ +0xf35df44a, 0x0240e24a, 0x4480cd89, 0xb7dd39c3, 0x1e313843, 0x37710f2a, 0xb3b2a30c, 0xd89c65ee, 0x4df8b7ba, 0x7a48fc17, 0x7e2766d8, 0x8b94ae90, 0x7ee6225f, 0x3a66efd6, 0xb59ddb89, 0xd70a23df, 0x3531ed60, 0x84c3ac26, 0x1ef07cc4, 0x0d17e0fc, 0x6297f856, 0xb84b7ff2, 0x6d01be67, 0xf7f32a02, 0xb373e78b, 0xc66c192a, 0x73308624, 0x4b168bb8, 0xf5b3c848, 0x7c678492, 0x178806f7, 0xc93b1b9c, 0x64b880d3, 0x55e6f77c, 0xc6ad5dad, 0x69af602f, 0x33dfd162, 0x3ec8319e, 0xed6ccc09, 0x9564d254, 0xd58b8512, 0xf8a428b4, 0xba0b9db8, 0x696e24a8, 0xcf146319, 0xf5728ccf, 0xf39cb0cd, 0x1509a03a, 0x6f8018aa, 0xc20383e5, 0xe414b63a, 0xb71c7d44, 0xf8656c33, 0x1a9fe60b, 0xad42dfc8, 0x8f3a70d8, 0x181e40c6, 0x00c14487, 0x80ac36e9, 0xfccbb27b, 0x42afb50c, 0x6256bcd1, 0x86420aeb, 0x22b9eb97, 0xeb82f00b, 0xb55c9f0e, 0x78081e5d, 0xf7326e85, 0x04aede48, 0xe69510f7, 0x95a596d3, 0x046f9acf, 0xbea543f0, 0xab6da74d, 0x8dbbd615, 0x2b00d523, 0xb13305c1, 0x0f964631, 0xa215dd7e, 0xc2c2c762, 0x15c8e4bd, 0xe2fa8a38, 0x60d71a1c, 0x0dd6a47b, 0x4d39f33d, 0xc0822528, 0x987332a8, 0x8915085d, 0xd85d2169, 0xbce5a1ba, 0xa92d4507, 0x822d9024, 0x5e1f2b82, 0x29403769, 0x51482934, 0x779e586c, 0xdc32bba6, 0x00000000, 0x8d7a9292, 0x4bd7cf3f, 0x51896db3, 0x062f7885, 0x9e5c4a2d, 0x3e097519, 0x6639261e, 0x97e57499, 0xe90356c6, 0x2deee921, 0x5ede6f05, 0x6dc0fae0, 0x18df0441, 0x13e79c38, 0x6479c454, 0x938aee56, 0x46016b44, 0x9af29465, 0x4441890e, 0xd1255b5a, 0x9a33d0e2, 0xe4d5f2bd, 0xbacad93f, 0x06ee3c02, 0xdadc87a4, 0xcb7bf9d6, 0xcd95c5d4, 0xafc37905, 0xcd548153, 0xa4fbe17c, 0xa67a47b1, 0x775f1ceb, 0xd54ac195, 0x7a89b890, 0xdeb31d6b, 0xa43aa5fb, 0x3aa7ab51, 0x576751b1, 0x57a61536, 0x8402e8a1, 0x7ca6c015, 0x26d67158, 0x1a5ea28c, 0x5527b3fb, 0xef2c2e43, 0xbc24e53d, 0xa6bb0336, 0x5a70b14d, 0x402e13c1, 0xf11d1600, 0xda1dc323, 0x89d44cda, 0x0b389879, 0x2fae0b6b, 0x37b04bad, 0xe9c21241, 0x319f3328, 0x73f1c2a3, 0xd365b910, 0x46c02fc3, 0x8ffb345f, 0x38260d9c, 0xa0553f34, 0x24969312, 0xfae4cafe, 0x8b55ea17, 0x60165e9b, 0xb88a3b75, 0x98b2762f, 0x82ecd4a3, 0x751ffea1, 0x9cddece0, 0xe07b2cf5, 0xbe640777, 0x2bc191a4, 0x261735df, 0x66f86299, 0x1cb09e8e, 0x5c9e8d4f, 0xfe8b5031, 0xad839b4f, 0xe23bcebf, 0x495669f2, 0x0281a6cd, 0x331e95e5, 0xe6545470, 0xd1e41fdd, 0x58f11780, 0xcfd5279e, 0x78c95ada, 0x75deba26, 0x58305307, 0x5ab1f5ca, 0x3c88d3d4, 0x2d2fada6, 0xe0ba6872, 0xc4edbfe7, 0xd7cb6758, 0x910b489b, 0x09b93eb4, 0xfa258e79, 0x17494270, 0x91ca0c1c, 0x1326d8bf, 0x2278af10, 0x35f0a9e7, 0xc9fa5f1b, 0xa0947bb3, 0xc04361af, 0x86834e6c, 0x426ef18b, 0xa2d499f9, 0x298173ee, 0x71b120e9, 0x0f5702b6, 0x6b2ec6e2, 0x9724301e, 0x11a77e72, 0x6bef8265, 0xf1dc5287, 0xd3a4fd97, 0x9e9d0eaa, 0x9c1ca867, 0x2457d795, 0x40ef5746, 0xde7259ec, 0x806d726e, 0xb1f24146, 0xedad888e, 0x49972d75, 0x11663af5, 0x38e7491b, 0x3c499753, 0xaf023d82, 0x1c71da09, 0xfc0af6fc, 0xcbbabd51, 0x0bf9dcfe, 0xa9ec0180, 0xefed6ac4, 0x4fb855f0, 0x7170646e, 0x2f6f4fec, 0x09787a33, 0x53c98ff9, 0x20384d5a, 0xc42cfb60, 0x315e77af, 0x4f791177, 0x6f415c2d, 0x5308cb7e, 0xfe4a14b6, 0x20f909dd, 0xeb43b48c, 0xdcf3ff21, 0x5c5fc9c8, 0xabace3ca, 0x934baad1 +}, +{ +0xb240e9bd, 0x398bfc75, 0x2d174ad4, 0xa25e5b39, 0xf6e7bdec, 0x6d321aa0, 0x1edcc1e8, 0x33cb8b3c, 0x794a9479, 0x73eedb48, 0xb26f506b, 0x4a65273d, 0x50f0635e, 0xfca7caa5, 0xd19f39a7, 0x5e321032, 0x91ba69d3, 0xd1b08071, 0x2778844b, 0x101eb284, 0x50145b26, 0x29baf727, 0x8fad2995, 0x5a9fadc1, 0x0aa44f31, 0xecb97821, 0x6df99b0e, 0xfc43f2dd, 0x73255ae6, 0xb8cb1f5a, 0x5e1da9e4, 0xe83b7c04, 0x279cbc33, 0xcb0a7dc4, 0x50dfda88, 0x503be2f0, 0x37adb761, 0x5ef9919c, 0x9195d005, 0x631451b4, 0x1a5ec5cd, 0xc5e7b77e, 0x39407ddb, 0xa271e2ef, 0x81a4db57, 0x95386df6, 0x9f57a369, 0xa617deb2, 0x0ec2736c, 0x6d1da376, 0x5a7b95b9, 0x00e43878, 0xf6038594, 0x4a4a9eeb, 0xdb14cf40, 0xcf6c4199, 0xe8f0fdaa, 0x002fb9d6, 0x29954ef1, 0xdf5d4acb, 0xf28181b1, 0xb8e4a68c, 0xc5c80ea8, 0x545ddead, 0x10fa8afc, 0x0e264b14, 0x9b319f34, 0xe8df447c, 0xd5328454, 0xcb25c412, 0x9bfa1e9a, 0x95f3ec58, 0xd154b809, 0xb6ed544e, 0xdb3b7696, 0x5ab01417, 0x730ae330, 0xd17b01df, 0xac9c2855, 0x33000a92, 0xcf8879e1, 0x6dd622d8, 0xb6c2ed98, 0x67965591, 0x2df372ac, 0x8be4ac1e, 0x5472677b, 0x9f781abf, 0x3dedc028, 0xdf96cb65, 0x816f5af9, 0x2ddccb7a, 0xf6c8043a, 0x77a75ec3, 0x04adbdf3, 0xdbdf4eee, 0x9171e87d, 0x8b009466, 0xa83195a6, 0xcf43f84f, 0xf80a7756, 0x7dc8905c, 0x3d264186, 0xb82f2722, 0x4ee72318, 0x5ed6284a, 0x4a811f45, 0x85ed5edc, 0x40255074, 0x40eed1da, 0x8526df72, 0xa8fa1408, 0x0449858b, 0x14b30f77, 0x7d2ca824, 0x63dfd01a, 0xdfb972b3, 0x633be862, 0x04663c5d, 0xec72f98f, 0x9f9c22c7, 0x396fc40d, 0x332fb344, 0x8140e32f, 0xf2ae3867, 0x63f069cc, 0x400ae9a2, 0xcbee45bc, 0x3d09f850, 0xf825ce80, 0x29717689, 0x233101c0, 0x231eb816, 0x1ef3783e, 0x54965f03, 0xe254b29b, 0x23fa806e, 0x1e38f990, 0xbc829ad1, 0x0a8bf6e7, 0x33e432ea, 0x8f4911ed, 0x1a717c1b, 0xa295da97, 0x0a6fce9f, 0x1457370f, 0x0a407749, 0xbcad2307, 0x95dc558e, 0x818b6281, 0x1abafdb5, 0x10310b52, 0x4e2ca2b6, 0x39a445a3, 0x3dc279fe, 0xc14a0a8d, 0xec5d4059, 0xa6dc5f1c, 0xcfa7c037, 0x1e174046, 0x8f829043, 0xdbf0f738, 0x699fa753, 0xb8009ef4, 0xacb39183, 0xe61d3710, 0x9fb39b11, 0x8f66a83b, 0xf8ee4f2e, 0xac57a9fb, 0xe2b08ae3, 0xbc491b7f, 0xe27b0b4d, 0x9517d420, 0xc5038f06, 0x8bcb15c8, 0x37498f19, 0x850966a4, 0x85c2e70a, 0x798115d7, 0xdf72f31d, 0x7788e715, 0xf8c1f6f8, 0xcbc1fc6a, 0x00000000, 0x37820eb7, 0x00cb81ae, 0xd5d6bc2c, 0xe6f90f68, 0x8b2f2db0, 0x7d0311f2, 0x446cd5ff, 0xbc66a2a9, 0xa8d5adde, 0x69b01e85, 0xf24a001f, 0x0eedcaba, 0x7de7298a, 0x40c1680c, 0x376636cf, 0xa6f3e6ca, 0x4e031b60, 0xd5f905fa, 0x2d38f302, 0x9bd5a74c, 0x23d539b8, 0x54b9e6d5, 0xb6096c36, 0xe814c5d2, 0xe6328ec6, 0x5a542c6f, 0x27b305e5, 0xb2a4d1c5, 0x4ec89ace, 0x04820425, 0x27573d9d, 0x295ecf5f, 0xf265b9c9, 0x0e09f2c2, 0xfc6c4b0b, 0x675dd43f, 0x44436c29, 0x915e51ab, 0xc1ae32f5, 0x697b9f2b, 0xa2ba6341, 0x67b9ec47, 0x695426fd, 0x4aaea693, 0x1a954463, 0x79652daf, 0xe6d6b6be, 0x73c1629e, 0xf62c3c42, 0x67726de9, 0xac78102d, 0xe29f3335, 0xc165b35b, 0xfc887373, 0xec96c1f7, 0xa81e2c70, 0x44a75451, 0x79aeac01, 0xb28b6813, 0x149cb6a1, 0xa6386764, 0x774366bb, 0x9b1e26e2, 0x4488ed87, 0xc52c36d0, 0x10d5332a, 0xd51d3d82, 0x14788ed9, 0xc1818b23, 0x776cdf6d, 0xb626d5e0 +}, +{ +0x6eb83f81, 0x0c93ede9, 0xb3bdcbae, 0x62f0b9ba, 0xa04f9d90, 0x3c873453, 0x6f92b605, 0xf2709642, 0x6e635453, 0x2e5febe9, 0x8f3afffd, 0xd53cfe06, 0x1b1037c5, 0x38f6b841, 0xff1299fd, 0x5f5d046d, 0x444d33a8, 0x7d91026d, 0x9171cdae, 0x6770d7fe, 0x22176dd2, 0xe9bbca55, 0xf6011a50, 0xd067fb90, 0xfb6315ef, 0xca862e03, 0x2bdf85ad, 0x98624e03, 0xf7f0f806, 0xece0cfc3, 0x354fdc2c, 0x055b0596, 0xd19619c6, 0x1203b468, 0x27970396, 0xadf6f9fd, 0x63015bec, 0x6ac9b393, 0xf72b93d4, 0x95db2a6e, 0x3c5c5f81, 0x39075a17, 0xb6e6ce38, 0x01f1e256, 0x57bf6596, 0x1758b1fe, 0x1bcb5c17, 0x48dede41, 0x1f61bbd7, 0x1ae1d593, 0xb7172c6e, 0x8b4b73ef, 0xfa499c6b, 0xd5e795d4, 0xec3ba411, 0x79e08e7f, 0x523f0bd2, 0x4d85dbd7, 0xd4167782, 0xbf2e2647, 0x7cbb8be9, 0xa1be7fc6, 0x6b3851c5, 0xc73f4a6e, 0x63da303e, 0xdcf41679, 0x16a953a8, 0xc34ec67c, 0x382dd393, 0xe84a2803, 0xcfdd2b95, 0x668135a8, 0x53158256, 0x83a91214, 0xfa92f7b9, 0xa5149806, 0x91aaa67c, 0xca5d45d1, 0xd0bc9042, 0x748281c0, 0xd14d7214, 0xc2bf242a, 0x2e84803b, 0xcf064047, 0x67abbc2c, 0xf6da7182, 0xac071bab, 0x40e7d468, 0x793be5ad, 0xbe04afc3, 0xb366a07c, 0xe5f34c6e, 0xa95c1e3d, 0xd8859a6b, 0x30cfb268, 0x75a80844, 0xdd05f42f, 0x9c13c211, 0x78116c29, 0xba7523d1, 0x6f49ddd7, 0x08e261fb, 0x8fe1942f, 0x09c8e87f, 0x2b04ee7f, 0x1e905981, 0x9cc8a9c3, 0x403cbfba, 0x5695ec12, 0x7c60e03b, 0xf2abfd90, 0xc7e421bc, 0x3014d9ba, 0x1a3abe41, 0x13293dec, 0xbb84c187, 0x22cc0600, 0x492f3c17, 0x49f457c5, 0xbaae4803, 0x8b90183d, 0x091383ad, 0xbff54d95, 0xcb77cc55, 0xe89143d1, 0x0db9646d, 0x90802ff8, 0x3d76d605, 0xd85ef1b9, 0x4567ba2c, 0xe960a187, 0xe52827bc, 0x9993ac55, 0x9d394b95, 0x8ecb1dab, 0x564e87c0, 0xad2d922f, 0x3dadbdd7, 0x2f75626d, 0x13f2563e, 0x6a12d841, 0xfee37bab, 0x86f21782, 0x5b2c887f, 0x1783da2c, 0x86297c50, 0x837279c6, 0x4caf5253, 0x04718c12, 0x274c6844, 0x8e107679, 0x00db6bd2, 0x70286600, 0x2666e1c0, 0x6be33a17, 0x52e46000, 0x8258f042, 0x04aae7c0, 0x4116363e, 0x0c48863b, 0x5f866fbf, 0x94f1a3ea, 0xb297422a, 0x57640e44, 0x8aba91b9, 0xa8adfc6b, 0x2a2e67fb, 0x75736396, 0xb63da5ea, 0x5e778de9, 0x98b925d1, 0xe4d9c5ea, 0x00000000, 0x08390a29, 0x82839b90, 0x4496587a, 0xa43e1182, 0x23e68f84, 0x41cd5dec, 0x313e503e, 0xa4e57a50, 0xb24c29f8, 0x8703f5d4, 0xacdc7079, 0x5bf7e3ad, 0x5add6a29, 0x346555a8, 0xcbaca787, 0xa5cff3d4, 0x31e53bec, 0xd974783d, 0xc395adae, 0xb7cc47bc, 0xffc9f22f, 0xedca4647, 0x78ca07fb, 0xc2644ff8, 0x34be3e7a, 0xe073222a, 0xed112d95, 0xe402ae38, 0xf3817414, 0x3594b7fe, 0xcef7a211, 0x9948c787, 0xa98775ef, 0xe182c07c, 0x4805b593, 0x7459ea12, 0x0d620fbf, 0x1e4b3253, 0x9de22047, 0xd4cd1c50, 0xdc2f7dab, 0x905b442a, 0xbedfc411, 0x39dc31c5, 0x950041bc, 0x942ac838, 0x4d5eb005, 0x2af50c29, 0x7d4a69bf, 0x53cee984, 0xe159abae, 0x1fbad005, 0xa87697b9, 0x1672387a, 0xbb5faa55, 0x5eace63b, 0x665a5e7a, 0x622bd268, 0xa094f642, 0x8a61fa6b, 0xd9af13ef, 0x012a8984, 0x5a0601fb, 0x7102ef84, 0x233de456, 0x70f30dd2, 0xc615c3ea, 0x87d89e06, 0xfe381079, 0xe0a849f8, 0xa1651414, 0x12d8dfba, 0x45bcd1fe, 0x71d98456, 0x05806e44, 0xce2cc9c3, 0x4c743981, 0xddde9ffd, 0x2fae09bf, 0xfbb87e3d, 0xc6cea838, 0xf35a1fc6, 0x26bd8a12 +}, +{ +0x110bfbc1, 0xc6e88102, 0xda24a12b, 0xf3cfdeea, 0x7dda245d, 0x8282900e, 0xfbec0b6c, 0x3c543b3f, 0xe2c4252b, 0x1ccc2029, 0x588e02cb, 0x05e40e6e, 0xb7a5cfe6, 0xcee3676a, 0xebb741fc, 0xa68607c9, 0xbb1a96b1, 0xeacfc343, 0x5c128e1a, 0x453aa05d, 0x2d77f310, 0xaa395e9e, 0x4985f90a, 0x65a2bb4b, 0x18789f16, 0x14c7c641, 0x93a15821, 0x9e4eb027, 0x59deb39a, 0xf753523b, 0x714d4ee4, 0x049c8cd1, 0xc30c8f6c, 0x6046b525, 0x05cc3d80, 0xaea5d24f, 0x874ead8e, 0xda0c92c5, 0xfbc43882, 0xe7202b45, 0x93896bcf, 0xee7b7c7c, 0x59f68074, 0x002833ee, 0x9f1e0176, 0xa6ae3427, 0x686560a3, 0x92f1e970, 0x2c0f71af, 0x0defe806, 0xc79003bd, 0xd6b3cb92, 0xc25c3e3d, 0xcecb5484, 0xd7cb492d, 0x48d5485b, 0x446a110c, 0x3193e0d7, 0xa21a8b18, 0xe70818ab, 0x242ca429, 0xca7febbb, 0x75f9f1db, 0x5d6a0ca5, 0xa232b8f6, 0xbf861a60, 0xf2b75c55, 0x9baabe49, 0xdb74107a, 0x1123c82f, 0x658a88a5, 0xeae7f0ad, 0x8bf1f4d9, 0x50add74d, 0xa7d6b698, 0x21e099a9, 0x8e3dc959, 0x35275fe8, 0x86362f31, 0x7df217b3, 0xba62140e, 0x15bf44fe, 0x19001da9, 0x4d314635, 0x5561eacd, 0x30c35186, 0x6cf9ec72, 0x8f6d7808, 0x691de21c, 0x0dc7dbe8, 0x444222e2, 0xb6f57eb7, 0x9645564f, 0x71657d0a, 0x701dffb5, 0x3477eeb9, 0x350f6c06, 0x41a62c8c, 0x5d423f4b, 0xfe2036ec, 0x04b4bf3f, 0x783e2a33, 0xa36209a7, 0x0c976ab9, 0x14eff5af, 0xb31170d9, 0x61160474, 0x418e1f62, 0x15977710, 0x1ce413c7, 0x75d1c235, 0x64da39f4, 0x9b828da7, 0x017882bf, 0x20981b16, 0xe394947a, 0x83d2215f, 0x1073797e, 0x54196872, 0x0823d586, 0xe2ec16c5, 0x7ca2a6e2, 0x30eb6268, 0x684d534d, 0x097364d7, 0xbb32a55f, 0xbfae298e, 0x3c7c08d1, 0x9ad23cf6, 0x7035cc5b, 0x64f20a1a, 0x4c49c48a, 0x6cd1df9c, 0x83fa12b1, 0x39b03551, 0x1db4a296, 0x613e379a, 0xe658a9fa, 0xc2740dd3, 0xca57d855, 0x6d816ecd, 0xcb076904, 0xc7b83053, 0xd69bf87c, 0xdb5c2394, 0x5085e4a3, 0xbefe98df, 0x8aa14588, 0x8a897666, 0x31bbd339, 0x9afa0f18, 0xfabcba3d, 0x54315b9c, 0x6935d1f2, 0xcf9be5d5, 0x58a63125, 0x40deae33, 0xcb2f5aea, 0xf62bd084, 0xb269f266, 0x240497c7, 0xb78dfc08, 0x6da95d23, 0x5c3abdf4, 0xdeb82dfa, 0x74817364, 0x92d9da9e, 0x9715e71e, 0x74a9408a, 0xf603e36a, 0x399806bf, 0x29c34c2f, 0xae8de1a1, 0x38c8b7ee, 0x3d048a6e, 0xd20774ad, 0x8bd9c737, 0xc6c0b2ec, 0xd37ff612, 0x257c1578, 0x19282e47, 0xc324bc82, 0x1d9c9178, 0xaa116d70, 0xb6dd4d59, 0xbed6ab31, 0x0cbf5957, 0x1850acf8, 0x8e15fab7, 0xe6709a14, 0xab69efcf, 0x4d1975db, 0x2893fd7e, 0xb241c188, 0x28bbce90, 0xde901e14, 0x51fd661c, 0x966d65a1, 0xe3bca794, 0x82aaa3e0, 0xee534f92, 0x21c8aa47, 0xba4a27e0, 0x7c8a950c, 0x9e6683c9, 0xa7fe8576, 0x105b4a90, 0xafdd50f0, 0x451293b3, 0x40f69ddd, 0xef03fec3, 0xef2bcd2d, 0x2d5fc0fe, 0x29eb7fc1, 0xd7e37ac3, 0xeb9f7212, 0x3d2cb980, 0xf3e7ed04, 0x38e08400, 0xcfb3d63b, 0x00000000, 0xd357c5fc, 0xfe080502, 0x4c61f764, 0x080be668, 0x2c274241, 0x48fd7bb5, 0x9f363298, 0xab41dc21, 0x606e86cb, 0xff7087bd, 0x796e9b62, 0x8f454be6, 0xaff5631e, 0xff58b453, 0xf29f6fbb, 0x87669e60, 0xd22f4743, 0x51d555f2, 0x781619dd, 0xdfc0af45, 0xfa9489d3, 0x0150b151, 0x7946a88c, 0xf77b61d5, 0x25542696, 0x861e1cdf, 0x20b028f8, 0x345fdd57, 0xdfe89cab, 0xb3394337, 0xa34a3a49, 0x49adcae4, 0x095b5739, 0x5549d923, 0x973dd4f0 +}, +{ +0xef1369d2, 0x1609dbfe, 0x0bcdfb12, 0x459a2d09, 0xbb2ca1ff, 0x11a5e524, 0xc3be3a66, 0x376217cc, 0xf8bde862, 0x1763593e, 0x9781f24b, 0x48916a01, 0xc9d49b3a, 0xb0e15aed, 0x974c2ac5, 0xd9d62450, 0x6f3c1a29, 0x635ddfe1, 0x0cac1d46, 0x3d08b690, 0x1a681e36, 0x31697358, 0x016a82c0, 0x0b00239c, 0x735f608b, 0x0d0b4708, 0xe3bf7494, 0x72f83ac5, 0x80e2ab75, 0xc8be19fa, 0xc41204bc, 0x0761e654, 0x9a476dcd, 0x4f3d54db, 0xaa449c55, 0x3003f198, 0x59f957ab, 0xd3bc850c, 0x55989263, 0x5234acb9, 0x6556bb75, 0xbbe17971, 0xde7a1a8a, 0x6390076f, 0xd3715d82, 0x7935c1d7, 0x7f3ea543, 0xba8bfbb1, 0x9c81d1d7, 0x8624176f, 0x54f210a3, 0xaa8944db, 0xc5b55ef2, 0xd8bca690, 0x2d0a09fa, 0xf2d7493e, 0x5893d56b, 0x06c6bc1a, 0x74f35e51, 0x42fbcb5d, 0xbdea1de5, 0x91474e51, 0x9be03783, 0xe372ac1a, 0x3aa4884a, 0x00000000, 0x443d7747, 0x4ff08c55, 0x7392b805, 0x2aa63720, 0xb74d6437, 0x1caea22c, 0xad257a01, 0x7554041f, 0xa625599d, 0xe2d5f654, 0x9626a805, 0x20014ef2, 0x7e542783, 0xfe7b5478, 0xe2182eda, 0x10cf67e4, 0xe8728f86, 0xdfdd40c4, 0xa74fdb5d, 0x902dcc91, 0xd2d607cc, 0x01a75a4e, 0x9a8ab543, 0x27ad7028, 0x1d09f862, 0xac4ff8c1, 0x8be288e9, 0x435c9113, 0x86e9cfe1, 0xc373e2e8, 0xe4134a4e, 0x7235e24b, 0xf4dc2daa, 0xffdc0e36, 0x689024f3, 0x4e9a0e95, 0x3a6950c4, 0x659b63fb, 0xff11d6b8, 0x2bccb5e0, 0x4936304f, 0xc578867c, 0x17ae81b0, 0xe8bf5708, 0xe4de92c0, 0x6e5698e9, 0xd4dd6358, 0x2b016d6e, 0x8a880a29, 0xa78203d3, 0x685dfc7d, 0x216bcc32, 0x9deb5317, 0x21a614bc, 0x5f3febb1, 0xb02c8263, 0x64f1e13b, 0xa1896747, 0x9b2def0d, 0x8a45d2a7, 0x7e99ff0d, 0x1c637aa2, 0xabe3c61b, 0x2dc7d174, 0x585e0de5, 0x6e9b4067, 0x87834d21, 0xd5b7e198, 0x90e0141f, 0xac82204f, 0x5e556971, 0xf57b77e4, 0x69377ebd, 0xf21a91b0, 0xc873c174, 0x6ff1c2a7, 0xa02e3d09, 0x1bcf4478, 0xd91bfcde, 0x3dc56e1e, 0x0c61c5c8, 0x260a2a66, 0x0dc69f86, 0x423613d3, 0xb627e6f7, 0x4391499d, 0x9d268b99, 0xbc809f25, 0xc4dfdc32, 0xf9d76aa2, 0x535e2e79, 0xb18bd82d, 0xf3bdcbfe, 0x5e98b1ff, 0x8145f13b, 0x11683daa, 0xf5b6af6a, 0xb6ea3e79, 0x78929b99, 0xce78a5e0, 0x743e86df, 0x543fc82d, 0x59348f25, 0x8b2f5067, 0x9c4c0959, 0x62fa85af, 0x3c623450, 0x1b029cf6, 0x8c836ebd, 0xbd27c56b, 0x8c4eb633, 0xfeb68cf6, 0xc2d4b8a6, 0xd57a3916, 0x1002bf6a, 0x2cad53b4, 0x802f73fb, 0xade8a28f, 0xdeb7c204, 0xab2e1e95, 0xf411f524, 0x79f81959, 0xdf10984a, 0xe579c88e, 0x060b6494, 0x3608950c, 0xeeb4339c, 0x1aa5c6b8, 0xceb57d6e, 0x00cdd88e, 0xbc4d47ab, 0x3b03d204, 0x5393f6f7, 0x4e57d61b, 0x16c40370, 0x7ff37dcd, 0xa144bfc9, 0x8d2434f3, 0x69faa633, 0x818829b5, 0x2a6befae, 0x3bce0a8a, 0xa0e3e587, 0xcf122720, 0x3cafecde, 0x4557f587, 0x49fbe8c1, 0xf91ab22c, 0x2760a8a6, 0x62375d21, 0x31a4abd6, 0x30ce2916, 0x485cb28f, 0xe9180d46, 0x37afcf42, 0xd410bbd6, 0x26c7f2e8, 0x1dc420ec, 0xefdeb15c, 0x643c39b5, 0x44f0afc9, 0xb780bcb9, 0x52f97437, 0xc2196028, 0x55554aed, 0x96eb708b, 0x5ff2333f, 0xf3701370, 0x0a6aa15c, 0x918a96df, 0xee79eb12, 0xa6e88113, 0x2c608b3a, 0xc91943b4, 0x8de9ec7d, 0xe9d5d5c8, 0x874e95af, 0x36c54d82, 0xe5b41000, 0x07ac3eda, 0x785f4317, 0xb14600a3, 0x0aa779d2, 0xd8717e1e, 0xd21bdf42, 0xba46233f, 0xf87030ec, 0x20cc967c, 0xcfdfffae, 0x7599dc91 +}, +{ +0xbc83395e, 0xf139673a, 0xb0f1c00e, 0xc4617976, 0xb0204d48, 0x991f8413, 0x7490b978, 0x3b01a88d, 0xed8f3d6b, 0x6b5c5e4a, 0x95bcf005, 0x52a73410, 0xeef58008, 0x766a7baf, 0xbe79fb89, 0xdbad9e44, 0xa1b51cbb, 0x2a94f97e, 0x9b34cb82, 0x4f409cb3, 0xed5eb02d, 0x7441343e, 0x8429a1f6, 0xa2cfa1d8, 0xffb15cbd, 0x259cbd4d, 0x974632d2, 0x27667f9a, 0x4dba5e64, 0x123e61d6, 0x4f9111f5, 0x39fb6a5a, 0xa34fde6c, 0xf292571f, 0x65d465cd, 0xa16491fd, 0x96c64d66, 0xdafc6cb6, 0x0e59b6c1, 0x3bd025cb, 0x42b21a57, 0x286e3ba9, 0x5f55b2f4, 0xbd0346ea, 0x4ec0e307, 0xd4a5da77, 0xef75ffbc, 0x00000000, 0x35581e4c, 0xff60d1fb, 0xcbb8b003, 0xaebd5888, 0xac961719, 0x885b58a6, 0x1fcce732, 0x43e3e8a5, 0x29ee441d, 0x84f82cb0, 0x10c4a301, 0x03ab3025, 0xc69bbba1, 0xd70eea52, 0xd806ae61, 0x508c7b81, 0x254d300b, 0xbea876cf, 0xad1668ad, 0x433265e3, 0x53f6c6e2, 0x0d230ba2, 0x69a69c9d, 0x38aa98a8, 0x984e76e1, 0x7ac90fb9, 0xe0ac36c9, 0xafecaa7a, 0xee240d4e, 0xf31228ab, 0x1d3625e5, 0xd65f18a0, 0x99ce0955, 0x5e044006, 0x5ed5cd40, 0x85a9de42, 0xbf28097b, 0x2a457438, 0x66aed8ae, 0x6485973f, 0x5f843fb2, 0x888ad5e0, 0x9be546c4, 0x377351dd, 0x1e4c9886, 0xecdecf99, 0x79b3b2da, 0x37a2dc9b, 0xe3d68baa, 0xb171bfba, 0xe30706ec, 0xa035630f, 0xe12c497d, 0x34d861f8, 0x9617c020, 0xb20b02d9, 0xfd9a132c, 0x136f9324, 0x3a505a7f, 0xd68e95e6, 0x9a653970, 0xca38cfb7, 0x26e6002e, 0x3409ecbe, 0x1f1d6a74, 0xe07dbb8f, 0x53274ba4, 0x6505e88b, 0x5cfe82d1, 0xd9575c93, 0x5daf7023, 0xfee0ae4f, 0x8602ee67, 0x989ffba7, 0x4cebac96, 0x7510c6cc, 0x7a1882ff, 0x0df286e4, 0x773b895d, 0x0fd9c975, 0xd986d1d5, 0xe1fdc43b, 0xa0e4ee49, 0x943c8fb1, 0x1e9d15c0, 0x87531c95, 0x86d36321, 0x0c72f950, 0x9ab4b436, 0x672ea71a, 0x7833cd6e, 0x79623f9c, 0x4c3a21d0, 0x4048d880, 0x241cc2f9, 0xefa472fa, 0x85785304, 0x392ae71c, 0x94ed02f7, 0xa39e532a, 0x2b1486ca, 0xbc52b418, 0x1c67d717, 0x3589930a, 0xc5308b84, 0x24cd4fbf, 0x3a81d739, 0xe2877958, 0xb1a032fc, 0x9797bf94, 0xadc7e5eb, 0x42639711, 0xbff9843d, 0x697711db, 0x13be1e62, 0xd525a5c3, 0x76bbf6e9, 0xaf3d273c, 0x36f32e69, 0x27b7f2dc, 0xfe312309, 0x505df6c7, 0xda2de1f0, 0x6b8dd30c, 0x037abd63, 0x02fac2d7, 0xa21e2c9e, 0x4e116e41, 0xc5e106c2, 0xae6cd5ce, 0x119551f3, 0x4d6bd322, 0x3622a32f, 0x409955c6, 0x77ea041b, 0xf1e8ea7c, 0x41192a72, 0x89db2712, 0xb2da8f9f, 0x12efec90, 0x890aaa54, 0xc8c20d60, 0xf243da59, 0x878291d3, 0x2bc50b8c, 0x5c2f0f97, 0x8bf06883, 0xcae942f1, 0x7b49700d, 0x8b21e5c5, 0xe256f41e, 0xc94272d4, 0xbdd2cbac, 0x1cb65a51, 0xc7ca4953, 0x01807fb4, 0x68f76e6f, 0xc64a36e7, 0xd7df6714, 0xd4745731, 0x667f55e8, 0x956d7d43, 0xd5f42885, 0x387b15ee, 0xec0f42df, 0x41c8a734, 0x510c0435, 0x6826e329, 0x51dd8973, 0x0ca37416, 0x5276b956, 0xdb7c1302, 0x7b98fd4b, 0xcb693d45, 0x293fc95b, 0xf06895c8, 0xf0b9188e, 0xc8138026, 0x67ff2a5c, 0x75c14b8a, 0x1144dcb5, 0x8a701737, 0x022b4f91, 0x6a0dacb8, 0x0151f2f2, 0x8aa19a71, 0xb35af02b, 0xc993ff92, 0x64541a79, 0xf3c3a5ed, 0x6adc21fe, 0x5d7efd65, 0x0e883b87, 0x00d18d46, 0xfccbe1de, 0x26378d68, 0x1de7a8a3, 0x10152e47, 0xfd4b9e6a, 0xd8d72327, 0xc4b0f430, 0xac479a5f, 0xfc1a6c98, 0x28bfb6ef, 0x78e24028, 0xc71bc415, 0xb38b7d6d, 0x0f084433 +}, +{ +0xf0ddabc5, 0xc9bb0281, 0x216e32e6, 0x7c1ee9a6, 0xdc624afe, 0x22888053, 0xf6c0fe1c, 0x0e376168, 0xb5a5eb27, 0xd999ad92, 0x03e6b2b5, 0xec60806a, 0x85a721b3, 0x9398db79, 0x84e976d2, 0x588b3c2c, 0xdd2c1d9f, 0x48a9933f, 0x314c9df5, 0x8e6ba7b7, 0x555aeff1, 0xcee80039, 0xbf273a42, 0x5b6d8e99, 0x35f92df8, 0x9dafba11, 0x2bece383, 0x0a82d165, 0xfc422f79, 0x79e50eca, 0x5c3e8c21, 0xb70d0ef3, 0x18089ba2, 0xbe696d23, 0xa72fa1e0, 0x13c41da6, 0x3f7bfc9d, 0x41cdf0ef, 0xb93a6f9b, 0xc524863d, 0x67f0c0b1, 0xd0fdce42, 0x96633c15, 0x4365153b, 0x20206587, 0x096463d0, 0xc0df6151, 0x14971f1e, 0x34b77a99, 0xc6c23488, 0xd506292e, 0xb2f6e99f, 0x33e47821, 0xa918c088, 0x3c9d4e28, 0xf9b9c815, 0xd2552b96, 0xa39a11ed, 0xea7dd5b3, 0xe8d53067, 0x4eb4c6e6, 0x9f075fc5, 0x02a8e5d4, 0x5209ed49, 0x7a03bc7f, 0x92d68c18, 0x4a0176eb, 0xe319b663, 0xd6e09b9b, 0x8d8d1502, 0x2aa2b4e2, 0xcd0eb28c, 0xd4487e4f, 0xca5db034, 0x769c38c3, 0x6b6f440d, 0x7434dd17, 0xd8d7faf3, 0x1e15ce7b, 0x7367dfaf, 0x5d70db40, 0xa07ca358, 0x9ce1ed70, 0x6fdaf400, 0xcb13e755, 0xfa5f7aa0, 0x50a1089d, 0x29440657, 0xbcc188f7, 0xeec865be, 0x64167204, 0x422b425a, 0xe7ac066e, 0x23c6d732, 0xae4bc230, 0x757a8a76, 0xd1b39923, 0xbb928a4f, 0xbadcdd2e, 0x5fd83e94, 0xb3b8befe, 0x78ab59ab, 0x469ef257, 0x7eb60c72, 0x6e94a361, 0x77d26fa2, 0xfeeacaad, 0x6c3c46b5, 0x263d305e, 0x0bcc8604, 0x4b4f218a, 0x1771adab, 0xeb3382d2, 0x83ba746a, 0xb87438fa, 0x1cbd2baf, 0x1022af13, 0x57f20a25, 0x128a4ac7, 0x1aa07e76, 0xf78ea97d, 0x3bce4c90, 0xadad7085, 0xdecaaf2a, 0xc8f555e0, 0xcfa65758, 0x722988ce, 0x61ed9568, 0x66be97d0, 0xdb314846, 0x8b9040db, 0x075302b8, 0x49e7c45e, 0xbd8fdf96, 0x4083a78e, 0x634570bc, 0x56bc5d44, 0x2495d58a, 0xdf84f84b, 0xfd0c7818, 0x04b5b00d, 0xc78c63e9, 0x7d50bec7, 0xe99b6706, 0x4c1c2332, 0x3828fe25, 0x8f25f0d6, 0xa5874434, 0xb1105b2a, 0xe257e102, 0x05fbe76c, 0x457840e2, 0x870fc467, 0xe44ab4db, 0x47d0a536, 0x972d6b74, 0x8938a50f, 0xf4681bc8, 0x6a21136c, 0x8cc34263, 0x1df37cce, 0xc339d3e4, 0x2773673f, 0x65582565, 0xf193fca4, 0xa4c91355, 0x6889f6b8, 0x3002ca94, 0xd31b7cf7, 0x5e9669f5, 0x4ffa9187, 0x44361783, 0x00000000, 0x3dd31949, 0xcc40e5ed, 0x98545d7d, 0x6d7211d4, 0x163ffaca, 0x2f59538e, 0xed2ed70b, 0x280a5136, 0x620b27dd, 0x3e35abfc, 0x15d9487f, 0xace327e4, 0xaafe723d, 0x5a23d9f8, 0x9bb2efc8, 0x2e1704ef, 0xa85697e9, 0x60a3c209, 0xa661f681, 0x907e69cc, 0xc1913630, 0x7ff85b13, 0xffa49dcc, 0xe504e3ba, 0x1f5b991a, 0xb05e0c4b, 0x3a801bf1, 0x014e5761, 0x4d527453, 0x1946ccc3, 0x2cbfe13b, 0x0c9f84bc, 0xa2d4468c, 0xf33b1970, 0x51ef5ffc, 0x361f9f4d, 0x8ade17ba, 0x32aa2f40, 0xf8f79f74, 0xaf059551, 0xd7aeccfa, 0x3751c82c, 0xabb0255c, 0x95858ea0, 0x805cc6df, 0x86419306, 0xe6e2510f, 0x2df1b65a, 0x0dd1d3dd, 0x91303ead, 0xb6435992, 0x71cf3a7b, 0xe1b153b7, 0x0f793609, 0x59c56b4d, 0x1bee2917, 0x8876f26e, 0x3966a944, 0x991a0a1c, 0xb4ebbc46, 0x25db82eb, 0x061d55d9, 0xef8632df, 0x811291be, 0x5347ba28, 0xc2778485, 0x5414b890, 0x7b4deb1e, 0x82f4230b, 0xf5264ca9, 0xda7f1f27, 0xfb112dc1, 0x9e4908a4, 0xc46ad15c, 0xf2754e11, 0x69c7a1d9, 0xe0ff04d6, 0x94cbd9c1, 0x9afcb8a9, 0x70816d1a, 0x116cf872, 0x082a34b1, 0xa132f439 +}, +{ +0xc59a7625, 0x15997973, 0xe9967239, 0xbdcf31fc, 0xa982fbe7, 0x0010efb9, 0x4276ab24, 0xffb99ad8, 0xcf0a8549, 0xf4fddadc, 0x9b53c68c, 0x6c188dc2, 0x2758aba1, 0xb75fc290, 0x70a7964f, 0x43b2f7f5, 0xb69b9e41, 0x90178688, 0x27484418, 0x092662fe, 0xbddfde45, 0x331561ba, 0x30b31f91, 0x7301e864, 0x8d7c2e6d, 0xbc0b6d2d, 0xf74b4b4e, 0x7bf339f2, 0x385121be, 0x6fbef3e9, 0x64ea5c54, 0x3a330344, 0x72d55b0c, 0x653eef3c, 0x8ecabfff, 0x1caff434, 0x785547d9, 0xda831383, 0x66887eae, 0x9b432935, 0xfc1fe4f3, 0xaa346a75, 0x5f0dec78, 0x558df0ad, 0x3be7b02c, 0x98f5b8a7, 0x1cbf1b8d, 0x4932eb20, 0x8d6cc1d4, 0x17ebb430, 0x8f1e0c97, 0x7a376523, 0x0b444004, 0x33058e03, 0xd1c75387, 0xd013e0ef, 0x2dd8b774, 0xf52969b4, 0xf539860d, 0x03b69192, 0xbfbdfcbf, 0x2dc858cd, 0x8cb872bc, 0xfdcb579b, 0x91c335e0, 0xd2612dac, 0x1d6ba8e5, 0x7981f4b1, 0x2fba958e, 0x6e6a4081, 0x48e65848, 0x5cbb7dea, 0x17fb5b89, 0xb4f9bcbb, 0xd271c215, 0x09368d47, 0x39957d6f, 0x92654bcb, 0xfc0f0b4a, 0x162fe8e1, 0x0b54afbd, 0xbe694fd7, 0xf75ba4f7, 0xebf450c3, 0x87ecdd01, 0x858efffb, 0x3841ce07, 0xd8f1dec0, 0x1f098a1f, 0x1d7b475c, 0x31774340, 0xcede3621, 0xc63c080e, 0xd0030f56, 0xccbc14db, 0xabe0d91d, 0x40046667, 0xda93fc3a, 0x3a23ecfd, 0x8ca89d05, 0x6c08627b, 0x859e1042, 0x5d6fce82, 0xe3068155, 0x4b402663, 0x0272cd43, 0x268c18c9, 0x545943c5, 0x79911b08, 0x71732527, 0xe8522ee8, 0x158996ca, 0x66989117, 0x57ff3dee, 0x145d25a2, 0x41c03ab6, 0x6fae1c50, 0x2e6e26e6, 0x7be3d64b, 0xea300c12, 0xccacfb62, 0x93a1171a, 0x2c0c041c, 0xf69ff826, 0xe0b010c7, 0xa2c6bbe3, 0x49220499, 0x862881d0, 0xa2d6545a, 0x652e0085, 0x57efd257, 0x70b779f6, 0x1f1965a6, 0x3167acf9, 0x562b8e86, 0x32d13d6b, 0xcd78480a, 0x4b50c9da, 0x4a94950b, 0xd1d7bc3e, 0x9a8775e4, 0x559d1f14, 0xbc1b8294, 0x08f2d196, 0x01c45cd1, 0x00000000, 0x86386e69, 0x41d0d50f, 0xa160c5c8, 0x6dcc3eaa, 0x731107dd, 0x7845a860, 0xea20e3ab, 0x401489de, 0x24ee3a33, 0xabf036a4, 0xd9358211, 0x91d3da59, 0x8eda5046, 0xd3b59ec4, 0xbe79a06e, 0x5f1d03c1, 0xa1702a71, 0x163f0758, 0x0a801cd5, 0xaa2485cc, 0x1edd3977, 0xa302e732, 0x24fed58a, 0xa0b476a0, 0x1ecdd6ce, 0xfe6d29b0, 0xffa97561, 0xa856488f, 0x87fc32b8, 0x7163ca9e, 0x4a847ab2, 0x93b1f8a3, 0x2faa7a37, 0xe164a3af, 0x03a67e2b, 0x7a278a9a, 0x08e23e2f, 0x253a895b, 0xe842c151, 0x563b613f, 0xa0a49919, 0xe0a0ff7e, 0xb68b71f8, 0x5ec9b0a9, 0x43a2184c, 0xe2d2323d, 0xd9256da8, 0xc44ec54d, 0x144dca1b, 0xdb474f52, 0x9931e476, 0xc62ce7b7, 0x3bf75f95, 0xceced998, 0xa846a736, 0x269cf770, 0x90076931, 0x9a979a5d, 0x5449ac7c, 0xcf1a6af0, 0xdb57a0eb, 0xd3a5717d, 0x844aa32a, 0x845a4c93, 0xc7e8bb66, 0xb4e95302, 0x6e7aaf38, 0x5ed95f10, 0x01d4b368, 0x2e7ec95f, 0x32c1d2d2, 0xbfad1306, 0xebe4bf7a, 0x9275a472, 0xf4ed3565, 0xa992145e, 0xe2c2dd84, 0x98e5571e, 0x252a66e2, 0xb53de06a, 0xe3166eec, 0x30a3f028, 0xe9869d80, 0xa312088b, 0xb74f2d29, 0xc7f854df, 0xfe7dc609, 0xe1744c16, 0x72c5b4b5, 0x674c227f, 0x8f0ee32e, 0x0a90f36c, 0xf68f179f, 0x99210bcf, 0xc45e2af4, 0x48f6b7f1, 0x398592d6, 0xfddbb822, 0xc58a999c, 0x6ddcd113, 0xd8e13179, 0x026222fa, 0x2c1ceba5, 0x675ccdc6, 0x4266449d, 0xcd68a7b3, 0x64fab3ed, 0x5d7f213b, 0xb52d0fd3, 0x5cab9253 +}, +{ +0xba7ef19d, 0xdf56aeed, 0xa9ebfb7d, 0x20a4afcf, 0xf441c173, 0x523e71ab, 0xf046498a, 0xfa052c6d, 0x3331a52f, 0x2084acc2, 0x1265af56, 0xf0664a87, 0x91699e03, 0x7d2e96cc, 0xb1ed32c1, 0x4bc81da1, 0x418b7846, 0x41ab7b4b, 0xe223e6dc, 0x447c5509, 0x00000000, 0xdaa183a2, 0x4a38b817, 0x4be81eac, 0x86db1f17, 0x04278bf4, 0xdf76ade0, 0xfe22a799, 0x90993bb5, 0x776df32b, 0x3d554b3c, 0x19d66f07, 0x405bdefd, 0xdb512614, 0x2f30e46a, 0x05f72d4f, 0xe860833b, 0x9efdd5a6, 0xb03d947a, 0xe6046d28, 0x896f57bf, 0xd4c56db1, 0x8d48dc4b, 0x91499d0e, 0x3ca5ee8a, 0xbe797964, 0x0e64ee13, 0xa2583b2c, 0x8cb879fd, 0xb43a1c83, 0x64d8fac6, 0xb5cab935, 0xe8408036, 0xec670bc2, 0x769d569d, 0x1826cab1, 0x956e16fa, 0x8c987af0, 0x65085c7d, 0x830c3155, 0x870bb9ac, 0x19f66c0a, 0xac3cd53f, 0x9b0af8e9, 0xdb712519, 0x3311a622, 0x6ebb9c2c, 0xc680c1ea, 0xb5eaba38, 0xa3889d97, 0xcd1302b6, 0x79091d38, 0x13b509ed, 0x4e3f30ee, 0x78d9bb83, 0x6abc14d5, 0xd0e2e645, 0x2ec041dc, 0x872bbaa1, 0xfbd58ad6, 0x32c10099, 0x521e72a6, 0x65285f70, 0x7d0e95c1, 0x2573818d, 0x82dc97ee, 0xe203e5d1, 0x01d0a6bb, 0x53ced41d, 0xd535c807, 0x4e1f33e3, 0xc2a74a1e, 0xe3f34067, 0x0e44ed1e, 0x32e10394, 0xadcc7089, 0x889ff209, 0xc357efa8, 0xa67fb0d8, 0x5639f952, 0x9f0d7010, 0xc377eca5, 0x60df723f, 0xbfa9dfdf, 0x7cfe3077, 0x832c3258, 0x94beb041, 0xbbae5726, 0xd13240fe, 0xa9cbf870, 0x9ada5e52, 0x3972c0c8, 0xe6246e25, 0x6f4b399a, 0x6e9b9f21, 0x79291e35, 0x25538280, 0x1245ac5b, 0x1df1e4f3, 0x0fb448a8, 0x86fb1c1a, 0x894f54b2, 0xfbf589db, 0x38a26673, 0x3d754831, 0x0bb3c051, 0xda8180af, 0x59adb2f7, 0xa7af1663, 0xf461c27e, 0x736a7bd2, 0xfe02a494, 0x040788f9, 0xc8e42ff9, 0x8d68df46, 0x64f8f9cb, 0xf196ef31, 0x0a4365e7, 0x24a32736, 0x57e95fe9, 0x729ade64, 0xb41a1f8e, 0x3c85ed87, 0x5d8a3903, 0x734a78df, 0x2ac7c925, 0xe3d3436a, 0xc770645c, 0x5c7a9cb5, 0x2b376c93, 0x6f6b3a97, 0xadec7384, 0x88bff104, 0x72badd69, 0x1c214248, 0x2ee042d1, 0x57c95ce4, 0x4a18bb1a, 0xf1b6ec3c, 0x610fd484, 0x17b28114, 0x458cf0bf, 0xfa252f60, 0x407bddf0, 0x53eed710, 0x9eddd6ab, 0xccc3a40d, 0x598db1fa, 0xe9b02580, 0x612fd789, 0xfff20122, 0x6b6cb26e, 0xe7f4c89e, 0xc7506751, 0x949eb34c, 0x4fcf9558, 0xd4e56ebc, 0x01f0a5b6, 0x6b4cb163, 0x164224a2, 0xcd3301bb, 0xedb7ad79, 0x2b176f9e, 0x2483243b, 0x76bd5590, 0x445c5604, 0xba5ef290, 0x90b938b8, 0x0f944ba5, 0xd11243f3, 0x13950ae0, 0xa83b5dc6, 0xf5b164c5, 0xbf89dcd2, 0x5c5a9fb8, 0x82fc94e3, 0xa2783821, 0x21740974, 0x3882657e, 0x166227af, 0x954e15f7, 0xa81b5ecb, 0x17928219, 0x60ff7132, 0x45acf3b2, 0x6a9c17d8, 0xc8c42cf4, 0x05d72e42, 0x587d144c, 0x36e68b6d, 0xde860856, 0xd515cb0a, 0x3952c3c5, 0xa65fb3d5, 0x0a6366ea, 0xc6a0c2e7, 0xcce3a700, 0x7cde337a, 0x9afa5d5f, 0xa78f156e, 0xb1cd31cc, 0x78f9b88e, 0xc9148a4f, 0x1dd1e7fe, 0xffd2022f, 0x9b2afbe4, 0x1806c9bc, 0x21540a79, 0xb01d9777, 0x37362dd6, 0x37162edb, 0xbb8e542b, 0x2ae7ca28, 0x9f2d731d, 0xa3a89e9a, 0xbe597a69, 0xc9348942, 0x36c68860, 0xe990268d, 0x774df026, 0xc2874913, 0x2f10e767, 0xd0c2e548, 0x5619fa5f, 0x5daa3a0e, 0xe7d4cb93, 0xed97ae74, 0xdea60b5b, 0xf59167c8, 0x0b93c35c, 0xec4708cf, 0x585d1741, 0x4fef9655, 0x0020030d, 0x1c014145, 0xac1cd632 +}, +{ +0xa7383561, 0x15b0638d, 0x05bb2b51, 0x6e793837, 0xd96b6857, 0x1c80f194, 0xe65fc463, 0x7b9bfb3c, 0x1948579e, 0x8dbcfad8, 0x4d9fc511, 0x3afc0a3e, 0xc960208b, 0x94d5809b, 0xbb99e928, 0x1cd25112, 0x7be87667, 0x8165e316, 0xe3b64fb4, 0x7e535d36, 0x9de51282, 0xb2fbdbb7, 0xd94a458a, 0xa2831e30, 0x585c2bc7, 0xea86ddad, 0x3add27e3, 0xfadf35f7, 0xf3bd0768, 0x15e2c30b, 0x41147c59, 0xa2f0936b, 0xbe03efa4, 0x0cf83413, 0x982db488, 0x4805c39d, 0x77316fa9, 0x6e2b98b1, 0xdcf16edb, 0xb740f0e6, 0x0962329f, 0x3f47216f, 0xa76a95e7, 0x4167f102, 0xdcd04306, 0x913c0b4c, 0x7e7270eb, 0xa2d1beb6, 0x100b48dc, 0xead47d2b, 0x48764ec6, 0xbe22c279, 0x9d969fd9, 0x15c3eed6, 0xb28856ec, 0x2a84cfb9, 0xabc00172, 0xef3df6fc, 0x2aa5e264, 0x6e0ab56c, 0x19697a43, 0x36043e2d, 0x23e6fd26, 0x987f140e, 0x3677b376, 0xef4e7ba7, 0xab92a1f4, 0xdc82e380, 0x8855710f, 0x2f3fe4e8, 0xb2a97b31, 0x5db5a010, 0xa74bb83a, 0xc5981498, 0x6b90b3e0, 0xfafe182a, 0x62d3aca2, 0xe3e4ef32, 0x00738d5b, 0x728a44f8, 0x676887f3, 0xccdb0bda, 0x8d9dd705, 0x6749aa2e, 0x2ad66f3f, 0x848c68c1, 0xef1cdb21, 0x3f1581e9, 0xd939c8d1, 0x94a60dc0, 0xf39c2ab5, 0x193bdac5, 0x5de70096, 0xe3976269, 0xae5a07fe, 0xbe514f22, 0x62a021f9, 0xc0021214, 0x4dcd6597, 0x5d948dcd, 0xa2a233ed, 0x6bc21366, 0x54853209, 0x7e20d06d, 0x267cfbaa, 0xe62c4938, 0x6e5815ea, 0x3f660cb2, 0x23b45da0, 0x7bbad6e1, 0x05e98bd7, 0xb2daf66a, 0xf6062c39, 0xd07ad793, 0xc050b292, 0xef6f567a, 0x911d2691, 0x72ab6925, 0x1cf37ccf, 0x8826fc54, 0x514d9403, 0x191af718, 0x339e38a1, 0xa71918bc, 0xcca88681, 0x580e8b41, 0x44dcda53, 0x72d8e47e, 0x88745cd2, 0x2395707d, 0x916eabca, 0x260f76f1, 0x9db7b204, 0xeaf550f6, 0x980c9955, 0x84ffe59a, 0xc0233fc9, 0xbe7062ff, 0xccfa2607, 0xc9410d56, 0x09309219, 0x1078c587, 0x1ca1dc49, 0x84dec847, 0xf6548cbf, 0x5dc62d4b, 0xc5cab41e, 0x33edb5fa, 0x94f4ad46, 0x0caa9495, 0x41355184, 0x985e39d3, 0xf3ce8a33, 0xd5c1fcc2, 0x587d061a, 0x54d7928f, 0x448e7ad5, 0x8dcf7783, 0x44fdf78e, 0x582fa69c, 0x54a41fd4, 0xb7337dbd, 0x23c7d0fb, 0x8dee5a5e, 0x4dec484a, 0xff36be20, 0xd5935c44, 0xbbb8c4f5, 0x3a8f8765, 0x00212ddd, 0xff1793fd, 0x84ad451c, 0x9dc43f5f, 0x513e1958, 0xd918e50c, 0xbbea6473, 0xae7b2a23, 0xabb38c29, 0x4857631b, 0xd5e0d11f, 0x33bf157c, 0xc5b93945, 0xe3c5c2ef, 0xae08a778, 0x265dd677, 0x4146dcdf, 0x1059e85a, 0x4824ee40, 0xeaa7f070, 0xd05bfa4e, 0x54f6bf52, 0x6be33ebb, 0xdca3ce5d, 0x33cc9827, 0x4dbee8cc, 0x81374390, 0x44af5708, 0x673a2775, 0xae298aa5, 0xff45337b, 0x0052a086, 0xf3efa7ee, 0xf62701e4, 0x2f6d446e, 0xc913add0, 0x7e01fdb0, 0x8144cecb, 0x2f4c69b3, 0xc932800d, 0x7763cf2f, 0x671b0aa8, 0x102a6501, 0x516cb9de, 0x05c8a60a, 0x0cd919ce, 0xfaacb8ac, 0x0c8bb948, 0x6bb19e3d, 0x059a068c, 0xc5eb99c3, 0xb7125060, 0xcc89ab5c, 0x3f34ac34, 0xc0719f4f, 0x262e5b2c, 0x72f9c9a3, 0x7bc95bba, 0xd5b27199, 0xabe12caf, 0x9487201d, 0xff641ea6, 0x77104274, 0x3aaeaab8, 0x0911bfc4, 0x2f1ec935, 0xd0095ac8, 0x81166e4d, 0xb761dd3b, 0x511f3485, 0x09431f42, 0x914f8617, 0xbbcb49ae, 0x8807d189, 0x2af742e2, 0xd0287715, 0x15914e50, 0x00000000, 0xe67ee9be, 0x7742e2f2, 0x62f2817f, 0xfa8d9571, 0xf675a162, 0xe60d64e5, 0x62810c24, 0x36569eab, 0x362513f0 +}, +{ +0xbdddf10d, 0x910239c8, 0xd12e6c9c, 0x69536603, 0x3a53490f, 0x19db9a3c, 0xe2753fa9, 0x5eaef011, 0x57a6ea2b, 0x36fba8a7, 0x217117d8, 0xfe0e5e07, 0x8a20671f, 0x4bdd8b85, 0x89df9d41, 0xc55b29bd, 0x9daad860, 0x325d6d80, 0xcd550d32, 0x7980e605, 0x065f01cc, 0xf6007a88, 0xc7a2ed56, 0xac084fbe, 0x1a246062, 0x6df5a324, 0xfdf1a459, 0x09081a3a, 0x6cf39d91, 0x2f20329b, 0xe882dfcd, 0xc0fbd22f, 0xf05f7b44, 0x080e248f, 0x7088fc3f, 0x448a9073, 0x8e86a238, 0x2077296d, 0x1d7d5f1b, 0x15737b94, 0xa9a8b42c, 0x0ca8e1a8, 0xe984e178, 0x718ec28a, 0xb72a1169, 0x53002f0c, 0x2388d333, 0x458caec6, 0x868886b7, 0x50ffd552, 0xb97b342a, 0xa5005584, 0x24d1ec4a, 0x4d828a49, 0x10d38006, 0x3d0a7676, 0xaa574e72, 0x49244f6e, 0x0bf1ded1, 0xdf7f49df, 0x9cace6d5, 0x228eed86, 0x51f9ebe7, 0xeeddde01, 0x1b225ed7, 0x0e512543, 0xb5d3d582, 0x1f849bf0, 0xe6d3fa8e, 0x31a297de, 0x07593f79, 0xeb7d2593, 0xde79776a, 0xed22245f, 0x822e4390, 0xd588a9bb, 0xaff7b5e0, 0xe52c00d0, 0x59f7cf68, 0x7ed9d97c, 0x2dd9f670, 0x64fdb91e, 0x8471425c, 0x412a6be1, 0x66047df5, 0x02f9c4eb, 0xf706443d, 0x63a48667, 0xad0e710b, 0x73770661, 0xe42a3e65, 0xb0732e10, 0x3c0c48c3, 0xd7716d50, 0x7886d8b0, 0x04a6c527, 0x3ef58c28, 0x5c5734fa, 0xe18ac5f7, 0x9e55223e, 0x742e3918, 0xa6ffafda, 0xb28aeafb, 0x88d9a3f4, 0x01063eb5, 0x6e0a597a, 0x7b7922ee, 0x62a2b8d2, 0x335b5335, 0xdd868d34, 0xbb82f0c1, 0x18dda489, 0xec241aea, 0x2cdfc8c5, 0xe373011c, 0x7d262322, 0x132c7a58, 0xceaaf76c, 0xe08cfb42, 0xc6a4d3e3, 0x980a23f2, 0x9bf5d9ac, 0x0f571bf6, 0x990c1d47, 0x4f7b4ea2, 0xd48e970e, 0x37fd9612, 0xa0a0ae16, 0x5b0e0b83, 0x6aac9c5d, 0xefdbe0b4, 0x8c7f66d3, 0xd2d196c2, 0x76d7fdf3, 0xcfacc9d9, 0x4adbb530, 0xf2a6bfaf, 0xa35f5448, 0x39acb351, 0xd82676a6, 0xfcf79aec, 0xc3042871, 0xd3d7a877, 0x94a2c25a, 0x93fbfd23, 0x77d1c346, 0xcb0a0cfe, 0x56a0d49e, 0x54591075, 0x555f2ec0, 0x11d5beb3, 0xea7b1b26, 0x7c201d97, 0x1c7b61ae, 0x46735498, 0xc9f3c815, 0x14754521, 0xc8f5f6a0, 0x2a80c909, 0x878eb802, 0x8b2659aa, 0xbe220b53, 0x350452f9, 0x65fb87ab, 0x7a7f1c5b, 0xbcdbcfb8, 0xe7d5c43b, 0xc20216c4, 0x05a0fb92, 0x58f1f1dd, 0xca0c324b, 0xc1fdec9a, 0xdbd98cf8, 0x95a4fcef, 0xcc533387, 0x47756a2d, 0x2e260c2e, 0x85777ce9, 0xa7f9916f, 0xb87d0a9f, 0x67024340, 0x38aa8de4, 0x4e7d7017, 0x975d3804, 0x80d7877b, 0xa2596afd, 0xb38cd44e, 0x92fdc396, 0x6f0c67cf, 0x727138d4, 0x5d510a4f, 0x605b7c39, 0x30a4a96b, 0x6baaa2e8, 0xb17510a5, 0x00000000, 0x520611b9, 0x83287d25, 0x482271db, 0xa1a690a3, 0x168c81ca, 0x28790de2, 0x43d3af0a, 0xdadfb24d, 0x8f809c8d, 0xab5170c7, 0xa8ae8a99, 0xaef18b55, 0x272e1614, 0x5fa8cea4, 0x262828a1, 0x1e82a545, 0x965b06b1, 0x5a083536, 0x42d591bf, 0x34026c4c, 0xd9204813, 0x178abf7f, 0x3b5577ba, 0x685558b6, 0xb62c2fdc, 0xdc80b381, 0x7fdfe7c9, 0xf8515fcb, 0xa4066b31, 0xf15945f1, 0xba84ce74, 0x122a44ed, 0xbf2435e6, 0xc45d1708, 0x0daedf1d, 0x3ff3b29d, 0xf957617e, 0x402c5554, 0xff0860b2, 0xf5ff80d6, 0xb4d5eb37, 0x9f531c8b, 0xd67753e5, 0x297f3357, 0x2b86f7bc, 0x4c84b4fc, 0x0af7e064, 0xfbaea595, 0xf3a0811a, 0xf4f9be63, 0x03fffa5e, 0xfaa89b20, 0x9004077d, 0xd0285229, 0x752807ad, 0x9af3e719, 0x81d1b9ce, 0x8d795866, 0x615d428c, 0x25d7d2ff +}, +{ +0xa5d6b1e8, 0x1f003a20, 0x6d9dbb23, 0xc35f6777, 0x799ac6c3, 0x214a1bb3, 0x3ec5bb4b, 0xb3088b94, 0xe29ae61c, 0xe20656b8, 0x6689d69f, 0xfd9adc3c, 0x9251ba5b, 0x14077de0, 0xb14d7cac, 0x45951068, 0xf4d86cc4, 0xbad68bc8, 0xca81672b, 0xac08b1b4, 0xaed1f628, 0x4c4b1034, 0x215931cf, 0xebd856e4, 0xca924d57, 0x9b130aa3, 0xff439ba0, 0x6d010b87, 0x7057ece3, 0x4c583a48, 0xe0df1124, 0xb1c2e674, 0xc8c49013, 0xe2157cc4, 0x86d95d63, 0xe9011178, 0xa79346d0, 0x47d0e750, 0x0b146dbc, 0x4cd7a090, 0xba4a3b6c, 0x3708916b, 0x0245f738, 0x35d1d6f7, 0x9b8fba07, 0xb81ce628, 0xb3943b30, 0x6f44fcbf, 0x5a1ab090, 0x53d79ab0, 0x0b9bf764, 0x7989ecbf, 0x2808ab4b, 0x230fec8b, 0x92429027, 0xac1b9bc8, 0x585f47a8, 0x584c6dd4, 0x21c5816b, 0x00000000, 0xd7d7804f, 0x70d8763b, 0xd51dedaf, 0x45863a14, 0xc1950a97, 0xf4cb46b8, 0x28873193, 0xac940110, 0x6f57d6c3, 0xebcb7c98, 0x3e4a2193, 0x86ca771f, 0x6d8e915f, 0x4e817dd4, 0x7bdf31fb, 0xf6012b58, 0x009cb0a4, 0x379421cf, 0xeb44e640, 0x23807653, 0x8f147743, 0xb15e56d0, 0x1dca57c0, 0xc34c4d0b, 0xc18620eb, 0x2ac2c6ab, 0x23935c2f, 0x3c804c73, 0x1f13105c, 0xc85820b7, 0xd74b30eb, 0x09de005c, 0x84001aff, 0xc11a904f, 0xc109ba33, 0x720131a7, 0xba591110, 0x3c93660f, 0x848f8027, 0xac872b6c, 0x53580068, 0x1488e738, 0x5a952a48, 0x47c3cd2c, 0x149bcd44, 0x64df0bdb, 0xa5c59b94, 0xe0cc3b58, 0xe98e8ba0, 0x518147f4, 0xdc4c772b, 0x21d6ab17, 0x2a5e760f, 0x4cc48aec, 0x8f9bed9b, 0x70cb5c47, 0x7bcc1b87, 0xca0efdf3, 0xae4d468c, 0x92cd0aff, 0x00132a7c, 0xe043a180, 0xaec2dc54, 0x9945d7e7, 0x16428ad8, 0xdcd0c78f, 0x92de2083, 0xdc5f5d57, 0xca1dd78f, 0x7b50ab23, 0xe99da1dc, 0x72121bdb, 0x534b2a14, 0x281b8137, 0xde098013, 0xfd89f640, 0x1f8fa0f8, 0x64cc21a7, 0xf6120124, 0x0256dd44, 0xd50ec7d3, 0x2ad1ecd7, 0x475f7d88, 0x451a8ab0, 0xb80fcc54, 0xd7581a97, 0x3c0fd6ab, 0x8f88c7e7, 0xe9123b04, 0xffdf2b04, 0x474c57f4, 0x0b88dd18, 0x09cd2a20, 0x8645edc7, 0xff50b1dc, 0xf444dc60, 0xd5927777, 0xc3d0fdaf, 0x9088fdc7, 0xae5e6cf0, 0x1d56e764, 0x53c4b0cc, 0x7044c69f, 0x99ca4d3f, 0x008f9ad8, 0x9956fd9b, 0x8d42aa07, 0x371bbb17, 0xdcc3edf3, 0xb1d1cc08, 0xf68eb180, 0x02d9479c, 0xb8937cf0, 0x0942b0f8, 0xa54a014c, 0x37870bb3, 0x4e9257a8, 0xa7806cac, 0xc8d7ba6f, 0x90144d63, 0x1414579c, 0xc84b0acb, 0x09519a84, 0xb31ba1e8, 0xbac5a1b4, 0x51926d88, 0x16de3a7c, 0x8dde1aa3, 0x79067667, 0xe0508bfc, 0x8656c7bb, 0x99d96743, 0x9b0020df, 0x6d1221fb, 0xde861acb, 0xf69d9bfc, 0xfd066c98, 0x355e4c2f, 0x669afce3, 0x16cd1000, 0xffcc0178, 0xde9530b7, 0x4e0ee70c, 0x729d8103, 0x0b0747c0, 0x5a099aec, 0x6443bb7f, 0xb880568c, 0x2a4d5c73, 0x58d0dd70, 0x909bd7bb, 0x5a860034, 0x1f9c8a84, 0x6fd84c1b, 0x8d51807b, 0x35c2fc8b, 0x231cc6f7, 0x6fcb6667, 0xe289cc60, 0x8dcd30df, 0x9007671f, 0x3c1cfcd7, 0x849caa5b, 0xeb57cc3c, 0x02ca6de0, 0x6615663b, 0xc3c3d7d3, 0xd7c4aa33, 0xde1aaa6f, 0xd5815d0b, 0x28941bef, 0x7b43815f, 0x4509a0cc, 0x511df750, 0x9b9c907b, 0x354d6653, 0x3e590bef, 0x1d45cd18, 0xfd1546e4, 0xa5592b30, 0x58c3f70c, 0x66064c47, 0x84133083, 0x728eab7f, 0xa71cdc08, 0x64509103, 0x1651a0a4, 0xf457f61c, 0x79155c1b, 0x1dd97dbc, 0xa70ff674, 0x510edd2c, 0x3ed69137, 0xb387114c, 0x4e1dcd70, 0x8f075d3f +}, +{ +0xfab86b80, 0xbc4ef5e6, 0x542d8993, 0x2927a2e2, 0x08e2a47f, 0x08616110, 0x1aba76e5, 0x74ab77a1, 0x23feb890, 0x6e110144, 0x2b9fd980, 0x4defb9d4, 0x44cd206b, 0xcb9dc4e5, 0xb5efa936, 0x5fb76b4e, 0x223e8550, 0x131b2a35, 0xd39fc962, 0x037846a2, 0x5755cf31, 0xd0644aaf, 0x97d12c66, 0x46f69e66, 0xaf55dfd3, 0x9752e909, 0x7e726dd3, 0x9e7070b6, 0x6d6947e6, 0x4cac417b, 0x6fd13c84, 0x0083c56f, 0xa4cf3d0e, 0x444ee504, 0xe9a341b5, 0xeb98ffb8, 0x331e1168, 0x850a3b93, 0x8e131c21, 0x94a96ac4, 0x6c2abf49, 0x1b7a4b25, 0xb56c6c59, 0xc37f609a, 0x6dea8289, 0x1258d29a, 0x3a3c88d7, 0x95695704, 0x01c03dc0, 0x961111a6, 0xc8e58247, 0x9c4bcebb, 0x4e143a19, 0x9d083614, 0xc8664728, 0xadeda4b1, 0xeb1b3ad7, 0x556e713c, 0x3bfcb517, 0xafd61abc, 0xda3e95b2, 0x5ccf2dec, 0x7f31957c, 0x2146c3f2, 0xc1c71bf8, 0x3944ce75, 0x9f338819, 0x64c81b36, 0xf3193750, 0xd8052bbf, 0x4c2f8414, 0x28e79f22, 0xa58cc5a1, 0x7fb25013, 0xc084e357, 0x1941f528, 0xe8637c75, 0xa50f00ce, 0xb6142afb, 0x2086fe32, 0x756b4a61, 0xb4ac5199, 0x4f57c2b6, 0x8c28a22c, 0x339dd407, 0x95ea926b, 0xea58c278, 0x11209438, 0x67b05d94, 0x2b1c1cef, 0x5e77568e, 0xfbfb932f, 0x19c23047, 0xc2bf5d5a, 0xd886eed0, 0xe1c220a5, 0xcade3c4a, 0xfa3baeef, 0x8e90d94e, 0x20053b5d, 0x380736da, 0x54ae4cfc, 0x8449c33c, 0xd9c5167f, 0xeadb0717, 0xf1a14c32, 0x00000000, 0x644bde59, 0xf2d90a90, 0x0143f8af, 0xc3fca5f5, 0x5d0f102c, 0x7cca16b1, 0x6f52f9eb, 0x0b1927b2, 0x8cab6743, 0xd31c0c0d, 0xbf36b344, 0xbfb5762b, 0x77d33103, 0x21c5069d, 0x8d6b5a83, 0x66f3a53b, 0x0b9ae2dd, 0x9d8bf37b, 0xe92084da, 0xcb1e018a, 0xa6f48303, 0xa677466c, 0x5f34ae21, 0xb697ef94, 0x9ef3b5d9, 0x87b240f1, 0x39c70b1a, 0x7d89ee1e, 0xb7d4173b, 0x9cc80bd4, 0x237d7dff, 0xfb785640, 0x306657ca, 0x5616379e, 0xd25ff4a2, 0x1bf98e4a, 0x8731859e, 0xdbfea872, 0xbef68e84, 0x32de2ca8, 0x7d0a2b71, 0x3125af65, 0x12db17f5, 0x458ed8c4, 0xe081d80a, 0x66706054, 0x4e97ff76, 0xf943e84d, 0xf883d58d, 0xe141e5ca, 0x6ca97a26, 0xd127b200, 0xa7b77bac, 0xac2d9971, 0xbd0d0d49, 0xe239a368, 0xd0e78fc0, 0xbccd3089, 0xe8e0b91a, 0x6e92c42b, 0x092299bf, 0x325de9c7, 0xc23c9835, 0x8de89fec, 0xf39af23f, 0xbd8ec826, 0x0a5adf1d, 0xa734bec3, 0xe3f99ea8, 0xb757d254, 0x5c4ce883, 0x1a39b38a, 0x03fb83cd, 0x11a35157, 0x31a66a0a, 0xd2dc31cd, 0x18020d87, 0x9692d4c9, 0x942aafab, 0x2a5fe440, 0xf25acfff, 0x7ef1a8bc, 0x5d8cd543, 0xe37a5bc7, 0x09a15cd0, 0x5695f2f1, 0x86f1b85e, 0xf0e2b49d, 0x4d6c7cbb, 0x55edb453, 0x10636c97, 0x3b7f7078, 0x9fb04d76, 0xc0072638, 0x30e592a5, 0x75e88f0e, 0x023bbe0d, 0x1881c8e8, 0x0ad91a72, 0x8fd321e1, 0x8589fefc, 0xc9a67ae8, 0x28645a4d, 0xae95e213, 0x47b566c9, 0x4fd407d9, 0x86727d31, 0x450d1dab, 0x2adc212f, 0xf06171f2, 0x22bd403f, 0x10e0a9f8, 0x650826f6, 0x1398ef5a, 0x46755b09, 0x8f50e48e, 0x84ca0653, 0xa44cf861, 0xb42f94f6, 0xc925bf87, 0x7428b2ce, 0x3884f3b5, 0x02b87b62, 0xf122895d, 0x7c49d3de, 0xc144de97, 0xdabd50dd, 0xe0021d65, 0x5ef493e1, 0x7750f46c, 0xd946d310, 0xf9c02d22, 0xdb7d6d1d, 0xd1a4776f, 0x658be399, 0xe2ba6607, 0xbe754beb, 0xae16277c, 0x57d60a5e, 0x3abf4db8, 0xacae5c1e, 0xad6e61de, 0x7690c9ac, 0x4736a3a6, 0x29a4678d, 0x673398fb, 0xca5df925, 0x76130cc3, 0xf80010e2 +}, +{ +0x26cbfe67, 0x639f79fa, 0x7d287bec, 0x6e740d10, 0xee32cfc1, 0xb2dcd088, 0x79acbc3c, 0x1df4d4a3, 0xbcbef970, 0xa2c370c1, 0x7e6bad59, 0x36d45e2e, 0x9ef1c0c7, 0x931ab42d, 0xf04f4670, 0x4fb269b5, 0x84088ea6, 0x83051464, 0xa14a2dd3, 0x2542a375, 0x07c71165, 0xa5ceea03, 0xc65193f9, 0xdfeb0b2d, 0x2c2d104f, 0xf30c90c5, 0x101fa049, 0x8eee608e, 0x6af0cac0, 0xcbbae713, 0xa647b711, 0x487578d0, 0x8046c2d1, 0x41d0404d, 0x0ea8a25f, 0x5fadc9fc, 0x8a6aa75e, 0x9e3b4b60, 0xbb79e815, 0x17123a8b, 0x67d1358d, 0x7aef6a89, 0x808c4976, 0x1396fd5b, 0xc15c093b, 0x94dda548, 0x9a750717, 0xd684b817, 0x8e24eb29, 0x4bfc25c2, 0xd82c1a48, 0xe050e639, 0x3c32b006, 0x5246bd16, 0x83cf9fc3, 0xf3c61b62, 0xb19f063d, 0xf085cdd7, 0x31d9c4ec, 0x9abf8cb0, 0x2fa44d5d, 0xe41eaa4e, 0xfee7e42f, 0x09a5389d, 0x734a5214, 0x1451ec3e, 0x6d37dba5, 0x149b6799, 0x56c27ac6, 0xb83a3ea0, 0x9db21672, 0x77041e63, 0xa50461a4, 0x2b208a8d, 0x586ad899, 0x7966379b, 0x3f7166b3, 0xa209fb66, 0xd2007fc7, 0xe797f75c, 0x9936d1a2, 0xdca8dd98, 0x700984a1, 0x671bbe2a, 0x99fc5a05, 0xf742dcb2, 0x892971eb, 0xe313308c, 0xa8259ee9, 0xdb6fccfd, 0xeef84466, 0x210cef02, 0x3fbbed14, 0x979e73fd, 0x5608f161, 0x3b3f2ac4, 0xf4cb81a0, 0xe93f5503, 0x58a0533e, 0x6458689f, 0xdba5475a, 0x28635c38, 0x1eb70216, 0x7447c8d6, 0x4b36ae65, 0x1af94e61, 0x5cee1f49, 0xccb77dd1, 0xd64e33b0, 0x429396f8, 0xaca15939, 0x4cf1bf00, 0x46175128, 0x00000000, 0x94172eef, 0x4c3b34a7, 0xa8ef154e, 0x601624e8, 0xfda4329a, 0x28a9d79f, 0x77ce95c4, 0x0a2c658f, 0x60dcaf4f, 0x3bf5a163, 0x459e0c3a, 0x0343d6b5, 0x1d3e5f04, 0x135c76fc, 0xcff4ab64, 0xdc62563f, 0x38b677d6, 0x070d9ac2, 0x260175c0, 0x0deb74ea, 0x0e6229f8, 0xb8f0b507, 0xdf21808a, 0x1a33c5c6, 0xbf37a462, 0x0484c7d0, 0xab66485c, 0x224f39b7, 0x6dfd5002, 0x48bff377, 0xb51bc1ed, 0x9d789dd5, 0xcb706cb4, 0x89e3fa4c, 0xbffd2fc5, 0x361ed589, 0xb1558d9a, 0xb2165b2f, 0xc8f931a6, 0x19701373, 0xe9f5dea4, 0x3597889b, 0xe4d421e9, 0x31134f4b, 0x00ca8ba7, 0x51cfe004, 0xc69b185e, 0x9093e93f, 0xc196829c, 0x6ebe86b7, 0xb5d14a4a, 0xf9ea7eed, 0x46ddda8f, 0x8dadb63b, 0x528c36b1, 0x258828d2, 0x554b27d4, 0x0ae6ee28, 0x6492e338, 0x5f67425b, 0xa68d3cb6, 0xd143a972, 0xd50de505, 0xb6929cff, 0x7380d9b3, 0xf4010a07, 0x17d8b12c, 0xc833ba01, 0xe75d7cfb, 0x03895d12, 0x1e7d89b1, 0x044e4c77, 0xedbb92d3, 0xd2caf460, 0x5be3858b, 0x4f78e212, 0x0d21ff4d, 0xfe2d6f88, 0xbbb363b2, 0x2ce79be8, 0xd8e691ef, 0x8781d3b4, 0xed711974, 0x19ba98d4, 0x70c30f06, 0x90596298, 0x6355f25d, 0x7de2f04b, 0xd18922d5, 0x874b5813, 0x7ea126fe, 0xcc7df676, 0x42591d5f, 0xc512454c, 0x411acbea, 0x9754f85a, 0x5b290e2c, 0x329a1259, 0x10d52bee, 0xf7885715, 0x096fb33a, 0x8aa02cf9, 0x6a3a4167, 0x69b31c75, 0xac6bd29e, 0x5c2494ee, 0x355d033c, 0xafe28f8c, 0xc2d55429, 0xe09a6d9e, 0xc21fdf8e, 0x8d673d9c, 0x2bea012a, 0x2f6ec6fa, 0x21c664a5, 0xc5d8ceeb, 0xd5c76ea2, 0xfaa9a858, 0x51056ba3, 0xea7c83b6, 0x5581ac73, 0xe3d9bb2b, 0x3cf83ba1, 0xbc7472d7, 0xa180a674, 0x93d03f8a, 0xfa6323ff, 0x4554879d, 0xf920f54a, 0xcf3e20c3, 0xeab60811, 0x325099fe, 0xabacc3fb, 0x387cfc71, 0x84c20501, 0x697997d2, 0xb6581758, 0x748d4371, 0x2285b210, 0x7a25e12e, 0xaf28042b, 0xfd6eb93d +} +}, +{ +{ +0xf8225de2, 0x9b4154be, 0xb59e205f, 0xd362e419, 0x91e4895b, 0x2d3dcc79, 0x66fcc446, 0x7c1fdc2f, 0xeab307af, 0x491697fe, 0x4719a058, 0xf3b2a75e, 0x5588fa15, 0xa1720f90, 0xb67c98c7, 0xbb9117f9, 0xb4ab0706, 0x9ede99a4, 0x53f58f97, 0x14ec2fcf, 0x5b87cdb3, 0x7ec843ee, 0xd42ab6c2, 0xb134ca1c, 0x163bb00e, 0x54bddd4c, 0x6081b1c4, 0x0e0f37a6, 0xf2878007, 0x7210eb89, 0xeb8620f6, 0x0ded8f3e, 0xc8b4db29, 0x4bc1083f, 0x43b34a1b, 0x3a335b2e, 0x62562e05, 0x3fac9634, 0xbdec627b, 0x2a759ea2, 0x1bd63f30, 0x0cd8a867, 0x33743e53, 0x45ce3f99, 0xc3242195, 0x15d90896, 0x76ba01ca, 0x02d79fc1, 0x4c895ae4, 0xe016da4a, 0x44fb18c0, 0x28a20163, 0x5dfab831, 0x8a32b66b, 0x7ffd64b7, 0x462c8701, 0xc5595417, 0xaae2f52c, 0x79801135, 0xe66bafc8, 0x39d1e3b6, 0x3d7b09f5, 0x5865752b, 0xc1f3be54, 0x7a62a9ad, 0x0947657d, 0x5ab2eaea, 0x5f2d27f0, 0x88e529aa, 0x37ded410, 0x2798119c, 0x2997263a, 0x9799fcd9, 0xc0c6990d, 0xc981fc70, 0xedfb5574, 0x4af42f66, 0xa5d8e5d3, 0x2c08eb20, 0x70c77448, 0xca6344e8, 0xfe5f2860, 0x04aaea43, 0xac9f80ae, 0xc6bbec8f, 0x183487a8, 0x4823b0a7, 0xf5cfd2dc, 0xbcd94522, 0x8d7ae4b0, 0xaf7d3836, 0xf9177abb, 0xd1b57bd8, 0x1dab4ab2, 0xcd2b1633, 0x80976b8e, 0x3241190a, 0x4e5ec525, 0xf0501fc6, 0x36ebf349, 0x309686cb, 0x1f7cd573, 0x1e49f22a, 0x98a3ec26, 0x9febbefd, 0xdfba4c7e, 0x69c6d4b9, 0xe864986e, 0xcc1e316a, 0xff6a0f39, 0x1ae31869, 0x254f8e5d, 0x651e7cde, 0xee19edec, 0xdc58f4e6, 0x13a47d14, 0xbaa430a0, 0xc21106cc, 0x8b079132, 0x059fcd1a, 0x7b578ef4, 0xa8356aed, 0x6a246c21, 0xcb5663b1, 0x03e2b898, 0x01352759, 0x61b4969d, 0x51221056, 0x78b5366c, 0xe5891750, 0x20d04347, 0xd6fd2903, 0x9a7473e7, 0x8375d316, 0x0b90fabc, 0x42866d42, 0x8e985c28, 0xd7c80e5a, 0xb873af61, 0x0aa5dde5, 0x074852db, 0x6d6c3efa, 0xd0805c81, 0x9333169a, 0xda258164, 0xdb10a63d, 0xb3e355dd, 0xabd7d275, 0x00000000, 0x947b4441, 0x7325ccd0, 0x920631c3, 0xcffc89f2, 0x90d1ae02, 0xe4bc3009, 0xd257c340, 0xe75e8891, 0x247aa904, 0x575f65d4, 0x1173e2d5, 0x3b067c77, 0x746d9e0b, 0xef2ccab5, 0x71f25311, 0xfaf5c223, 0x3e99b16d, 0x31a3a192, 0x2332fbdf, 0xf7184d1d, 0x4dbc7dbd, 0x67c9e31f, 0x067d7582, 0xb749bf9e, 0xe951bf37, 0xd9c739fc, 0x89d00ef3, 0x87df3955, 0xa04728c9, 0x7d2afb76, 0x4051f283, 0xfbc0e57a, 0x6b114b78, 0xc46c734e, 0xf165389f, 0x96acdb80, 0x86ea1e0c, 0x9c090665, 0xbf3bfdba, 0x2edf74e1, 0x1046c58c, 0x5017370f, 0x4f6be27c, 0x7558b952, 0x8fad7b71, 0x35094bd1, 0xf4faf585, 0x4164d5da, 0x68f3f3e0, 0x5ccf9f68, 0xfdbd90f8, 0x59505272, 0xe2c1458b, 0x1c9e6deb, 0xa4edc28a, 0xdd6dd3bf, 0x0f3a10ff, 0x2fea53b8, 0xa3a59051, 0x6e8e8662, 0x8240f44f, 0x9d3c213c, 0x6c5919a3, 0xa63a5d4b, 0x5e1800a9, 0xb2d67284, 0xe123fd13, 0x6363095c, 0xadaaa7f7, 0xe3f462d2, 0x642b5b87, 0x52c0a8ce, 0xd8f21ea5, 0x6fbba13b, 0xb001ed45, 0x170e9757, 0x843d81cd, 0x1901a0f1, 0x12915a4d, 0xde8f6b27, 0x8508a694, 0xecce722d, 0x08724224, 0x8c4fc3e9, 0xbe0edae3, 0x778f2693, 0x9996cb7f, 0x3c4e2eac, 0x21e5641e, 0xae481f6f, 0xc78ecbd6, 0x2207dc86, 0xd51f919b, 0x343c6c88, 0xfc88b7a1, 0xa70f7a12, 0xb9468838, 0x81a24cd7, 0x38e4c4ef, 0xcec9aeab, 0xf62d6a44, 0xa290b708, 0x26ad36c5, 0x566a428d, 0xa9004db4, 0x954e6318, 0x2b40b9fb +}, +{ +0x07f8a8cb, 0xe0c461b3, 0x296806ca, 0x35e52776, 0xf56ee41a, 0xffd3a691, 0x04624e55, 0x8117dc82, 0xdbfe4a1b, 0x37bec28f, 0x48bbbbfb, 0x834c397b, 0x8d9335a5, 0x33dc8cda, 0xcbf78280, 0xb533f893, 0xaf877283, 0xa1587e5d, 0xa0997d3a, 0xc9ac6779, 0x61d3bd31, 0x7c9f9fea, 0x53ce328c, 0x857592d7, 0x1c8d21bc, 0x1009c89b, 0x9e001ba0, 0xb7681d6a, 0x3cc28363, 0xaddc977a, 0xbc145c86, 0x3b3a2ba8, 0x2af2e054, 0xd1430890, 0x3e99669a, 0x31876923, 0x47a5b442, 0xe35e872d, 0x0f1e0fb9, 0x18ef6fe9, 0xa9bed92f, 0xf82b0e5a, 0x5ae99699, 0xc86d641e, 0xb87612d3, 0xefda6e0a, 0xea792338, 0x0c84e927, 0x2ccb4bf8, 0x11c8cbfc, 0x9284f287, 0xd6bba05b, 0x84b491b0, 0xf73501e3, 0x701b76cd, 0x5f4adbab, 0xc7736ba7, 0xbdd55fe1, 0x65b1f364, 0x146b86ce, 0x57ac7cd9, 0xa761d5f1, 0xf9ea0d3d, 0x7d5e9c8d, 0xe6fdca1f, 0x0b7c41ec, 0xfd884368, 0x38a0cd36, 0xac1d941d, 0x8c5236c2, 0x67ea169d, 0x6470f003, 0xde5d0729, 0xf6f40284, 0x68f41924, 0x4f431330, 0xbf8eba18, 0x4d18f6c9, 0x89f17bf0, 0x405d1c89, 0xbe4fb97f, 0x9839b00c, 0x367fc1e8, 0x8fc8d05c, 0x9ba35692, 0x419c1fee, 0x8e09d33b, 0x1d4c22db, 0xb151b6c6, 0xb090b5a1, 0x73819053, 0x7aa63446, 0x6012be56, 0x662b15fa, 0xb4f2fbf4, 0x5e8bd8cc, 0x443f52dc, 0x520f31eb, 0x566d7fbe, 0x1f17c722, 0xda3f497c, 0xe4a62fe6, 0x7ec47a13, 0x911e1419, 0x6aaffcdd, 0xdf9c044e, 0x793cd2d8, 0x192e6c8e, 0x72409334, 0x59737007, 0x0d45ea40, 0x7b673721, 0x8a6b9d6e, 0x0927a415, 0x1ab48a10, 0xe5672c81, 0x4cd9f5ae, 0x54369a47, 0xf4afe77d, 0x86ef7449, 0x872e772e, 0x74793898, 0x1ed6c445, 0x88307897, 0xd52146c5, 0x13932e05, 0xf3574fb6, 0x27b70a14, 0xd4e045a2, 0xf0cda928, 0xcdce292c, 0xba2df72a, 0x3f5865fd, 0x25ecefed, 0xcf95ccd5, 0x957c5a4c, 0xc6b268c0, 0x9a6255f5, 0xb6a91e0d, 0xa4fb336f, 0x638858c8, 0x5195d775, 0xee1b6d6d, 0x0edf0cde, 0x96e6bcd2, 0xd9a5afe2, 0xce54cfb2, 0xd77aa33c, 0x828d3a1c, 0xc5288e5e, 0xed818bf3, 0x90df177e, 0x75b83bff, 0x218ea1b8, 0x23d54441, 0x45fe51bb, 0x00000000, 0xaa243fb1, 0x28a905ad, 0xc14ac00b, 0x4664b725, 0x9345f1e0, 0x9fc118c7, 0x6b6effba, 0x5054d412, 0x4b215d65, 0x3961ce51, 0xebb8205f, 0x9c5bfe59, 0x17f16050, 0x204fa2df, 0x30466a44, 0xc31125f2, 0xbbecf44d, 0x26760973, 0xfa70eba3, 0xb2cb5058, 0x7622dd61, 0x08e6a772, 0xf2964cd1, 0x7f057974, 0xc4e98d39, 0xd2d9ee0e, 0x8baa9e09, 0x22144726, 0xabe53cd6, 0xe10562d4, 0x16306337, 0x9727bfb5, 0x4e821057, 0x78fdd1bf, 0x2d0a489f, 0x242dec8a, 0xa53a3008, 0x15aa85a9, 0xd864ac85, 0x4ae05e02, 0x9d9afd3e, 0x2b33e333, 0xe73cc978, 0x43c7fa17, 0x80d6dfe5, 0x55f79920, 0x0abd428b, 0x4206f970, 0x025be5f9, 0x039ae69e, 0xfc49400f, 0xec408894, 0x2e90ae01, 0xf10caa4f, 0xd318ed69, 0xca3681e7, 0x6d575416, 0x3d038004, 0x6f0cb1ef, 0x69351a43, 0x05a34d32, 0x5cd03d35, 0x71da75aa, 0xc08bc36c, 0x1b758977, 0x77e3de06, 0xe9e3c5a6, 0xcc0f2a4b, 0xa6a0d696, 0x5b2895fe, 0x2f51ad66, 0xa3039ba4, 0xe29f844a, 0x62495baf, 0x34242411, 0xfbb1e8c4, 0x6ecdb288, 0x321d8fbd, 0xdc06e2d0, 0x0639abac, 0x3afb28cf, 0x6c965771, 0xa2c298c3, 0xc2d02695, 0x12522d62, 0xb30a533f, 0xddc7e1b7, 0xb9b711b4, 0x5d113e52, 0xfe12a5f6, 0x58b27360, 0xae4671e4, 0xe822c6c1, 0x01c10367, 0xa87fda48, 0x94bd592b, 0x99f8b36b, 0x497ab89c, 0xd0820bf7 +}, +{ +0xa34eb7c7, 0xbbcffacc, 0xf780227a, 0xb86686a5, 0x003cd3a0, 0xe98bd9a1, 0x7d65b8a8, 0xd89d6a1f, 0xdacef375, 0xa2b452c4, 0x19477ba8, 0x1aee07c1, 0xde17dccf, 0x553470be, 0x2c88e7ac, 0x35cf9c04, 0x51ed5f04, 0x8e0066c8, 0x894ce6bb, 0x4fe6a4df, 0xc53fedad, 0x2a3e82dc, 0x502b69a7, 0x94ee6109, 0x37a0d6ce, 0x4896f70c, 0xf5d3bb10, 0x379c056e, 0xa5f8d2b7, 0xc750a767, 0xea22a5c8, 0x97471d60, 0xb99c63a6, 0x1e37287b, 0x9514840a, 0x5278f0cd, 0x8ad94972, 0xc69691c4, 0xba09cc6f, 0x2f1d4865, 0x0253996a, 0x7c9f5dab, 0xf10a94aa, 0x62a875d0, 0xbf16d576, 0xbbf3296c, 0x66715a6a, 0xeefb8a72, 0x35f34fa4, 0x2ee7ad66, 0xeca81318, 0xebe4936b, 0xf0f071a9, 0xbd454c1c, 0x888ad018, 0xc6aa4264, 0x7eccc4c1, 0x5017ba07, 0xc1e6c217, 0xf4158db3, 0x7bef0e78, 0x8fc6506b, 0xa66d7d7e, 0x30d0851d, 0x32831c77, 0xa0db180e, 0x2bc467df, 0xdc789605, 0x93a2e17a, 0x6294a670, 0x3666e06d, 0xc020f4b4, 0x026f4aca, 0xa11d2ead, 0x2d4ed10f, 0xb9a0b006, 0x538215ce, 0x54f2461d, 0xbed0e3d5, 0x2cb4340c, 0x67b76cc9, 0xc3b55b7d, 0x2d7202af, 0xdfed39cc, 0x787aa1b1, 0x900b9d13, 0x2f219bc5, 0x5767e9d4, 0x2bf8b47f, 0x51d18ca4, 0x60fbecba, 0x91f17810, 0xed6e25bb, 0x977bcec0, 0x1b14e2c2, 0xf4295e13, 0xa40237b4, 0x1e0bfbdb, 0x03a97c69, 0x7f3621c2, 0x4e20927c, 0xf3590dc0, 0x04d92fba, 0x5244236d, 0x610109b9, 0x91cdabb0, 0x18bd9eab, 0x8e3cb568, 0x3379f974, 0x2997feb5, 0x0395afc9, 0x286d1bb6, 0xdb08c5d6, 0x8970351b, 0xd95b5cbc, 0xb85a5505, 0xdaf220d5, 0xef3dbcd1, 0xdfd1ea6c, 0x641e10a0, 0x3116b3be, 0x30ec56bd, 0xd9678f1c, 0x9264d7d9, 0xc24fbe7e, 0x1b283162, 0x2851c816, 0x575b3a74, 0xc01c2714, 0x1fcdcd78, 0xeec759d2, 0x88b603b8, 0x4b0358c5, 0x2edb7ec6, 0x636e4373, 0x8ffa83cb, 0xdc4445a5, 0x04e5fc1a, 0x068ab6d0, 0xef016f71, 0x01fae503, 0x1da287b2, 0xed52f61b, 0xa7ab4bdd, 0x4fda777f, 0xf64614d9, 0xf136470a, 0x0523cab9, 0x7f0af262, 0x53bec66e, 0x94d2b2a9, 0xbcbfa91f, 0x00000000, 0x48aa24ac, 0x077053d3, 0x01c636a3, 0x613dda19, 0xe84def02, 0x65e4f5a3, 0x34357907, 0x7ef01761, 0xdb341676, 0xba351fcf, 0x8b1f7fd1, 0xc38988dd, 0xf29f3b63, 0x90374eb3, 0x496c120f, 0x8c6f2c02, 0xf5ef68b0, 0xe8713ca2, 0x365a33cd, 0x678bbf69, 0xc76c74c7, 0x92580479, 0x5508a31e, 0x79bc9712, 0x8c53ffa2, 0x312a601e, 0xa0e7cbae, 0x1ad2d461, 0x96812bc3, 0x952857aa, 0xa3726467, 0x051f1919, 0x56a1df77, 0x798044b2, 0x8ae59ad2, 0x1ff11ed8, 0x32bfcfd7, 0x939e32da, 0xbd799fbc, 0xa121fd0d, 0x1d9e5412, 0xf0cca209, 0xe9b70a01, 0x65d82603, 0xddbea0a6, 0x4ac56e66, 0x29ab2d15, 0x3409aaa7, 0x8da91aa1, 0xf7bcf1da, 0x4c730b16, 0x4e1c41dc, 0xc2736dde, 0xf365de60, 0x18814d0b, 0x635290d3, 0x33452ad4, 0x4db53db5, 0xbeec3075, 0x8b23ac71, 0x7d596b08, 0x54ce95bd, 0x4b3f8b65, 0x7bd3ddd8, 0xa5c40117, 0xec94c0b8, 0x06b66570, 0xc4c508ae, 0x8d95c901, 0x1c5862b1, 0x96bdf863, 0xa797987d, 0x6422c300, 0xa651aede, 0xa2888164, 0x197ba808, 0x2a02517c, 0x1c64b111, 0x074c8073, 0x7a2938db, 0x4d89ee15, 0x4950c1af, 0xdd827306, 0x4c4fd8b6, 0xc4f9db0e, 0xd8a1b9bf, 0xde2b0f6f, 0x78467211, 0x664d89ca, 0xc1da11b7, 0xebd840cb, 0xf67ac779, 0x4af9bdc6, 0x60c73f1a, 0xa43ee414, 0xf2a3e8c3, 0xea1e7668, 0x569d0cd7, 0xbc837abf, 0xbf2a06d6, 0x7ca38e0b, 0x7a15eb7b, 0xc5033e0d +}, +{ +0x3ab831d5, 0x57662b41, 0x9b801717, 0x17b8056c, 0xe7178c13, 0xb9ba0fce, 0xe40e0640, 0xba3e4054, 0x22a7dd10, 0xc90e32f9, 0x274fd3bf, 0xeb342a20, 0x973e74ed, 0x2d9df170, 0x8a54534e, 0x68abd1f2, 0x797f95ab, 0x1b066696, 0x94ba3b77, 0x369b97e6, 0xabea040d, 0x1725c0a5, 0x11498190, 0x7f13d49e, 0xa4d0286d, 0xc5b05103, 0xf65e0d83, 0x98999d44, 0xa13826c2, 0x70b43d37, 0x61fdbca7, 0xde2bf25c, 0xbccfc4a8, 0xfc11ea85, 0xae020aa2, 0x1eee6839, 0x45362082, 0x43c7a47e, 0x6bb25ba1, 0x97a3b124, 0xc993f730, 0x2e19beea, 0x0575cb66, 0xca8a7d63, 0xbf4b8b32, 0xf0af897f, 0x5ead83dd, 0x7a661ff8, 0xb927ca07, 0xedc5aedc, 0xe8b065ba, 0xe78a49da, 0x91cff011, 0x8677f57d, 0x2123928a, 0x2875ffdf, 0xd4f9d093, 0x547fa112, 0xe17bcd26, 0xcc7bf99f, 0x1df7e26a, 0x3a25f41c, 0x894dd91d, 0xca17b8aa, 0xc0585fac, 0x57fbee88, 0xc6a9db50, 0x12500bc3, 0x3606522f, 0x066c4135, 0xcf6273cc, 0x7c979b04, 0xa8f38e5e, 0xd77d9f09, 0x6b2f9e68, 0x49884378, 0x6279f33d, 0x2b6c758c, 0x755c3398, 0xf9f9e42a, 0x09566d55, 0x5d29cc47, 0xc0c59a65, 0xa86e4b97, 0x24cb9c25, 0x79e25062, 0x73adb764, 0x924bbf8b, 0x1b9ba35f, 0xb3682d01, 0x4fe4024d, 0x7029f8fe, 0x4cfd881e, 0x306a131a, 0x5213e027, 0xd208546f, 0x351fd87c, 0xc3dc1036, 0xf96421e3, 0x6415b208, 0x7c0a5ecd, 0xfae06e79, 0x09cba89c, 0xeedc248f, 0x648877c1, 0xd8da76a0, 0x4f79c784, 0xf6c3c84a, 0x7f8e1157, 0xb599a9fd, 0x915235d8, 0xdd32780f, 0xb3f5e8c8, 0x6dde1a94, 0x80867181, 0xe493c389, 0x3c49b529, 0x89d01cd4, 0x9dec5622, 0x75c1f651, 0xcfffb605, 0xd29591a6, 0x33739949, 0xab77c1c4, 0xff95a51f, 0x2d0034b9, 0xad864538, 0x510a6a74, 0x0cbe63fa, 0x0ad222cf, 0xae9fcf6b, 0x3cd470e0, 0x86ea30b4, 0x05e80eaf, 0xed586b15, 0x491586b1, 0xc52d94ca, 0x4c604dd7, 0xfa7dabb0, 0x03198a53, 0x92d67a42, 0xc341d5ff, 0xe2624775, 0xe1e608ef, 0x2e847b23, 0x6160796e, 0x3f503f7a, 0x462faad1, 0x3fcdfab3, 0x5b458d72, 0x45abe54b, 0x181fecc5, 0x801bb448, 0x0f3a2c60, 0x670c385b, 0x46b26f18, 0xf32bc6e5, 0x223a18d9, 0xc6341e99, 0xddafbdc6, 0xf3b6032c, 0x27d21676, 0xd464155a, 0x39a1bb86, 0x2bf1b045, 0x5e304614, 0x528e25ee, 0xa7c9a23e, 0xb68023ae, 0x11d44459, 0x5bd848bb, 0xbaa3859d, 0x1e73adf0, 0x856e7f2e, 0xf0324cb6, 0x03844f9a, 0x143c4af6, 0xa44deda4, 0x9e6819b8, 0x8c38127b, 0x4043ebe4, 0x9ef5dc71, 0x9b1dd2de, 0xfc8c2f4c, 0x12cdce0a, 0x28e83a16, 0x6d43df5d, 0x4a0c0ce2, 0xbc520161, 0xd7e05ac0, 0xa75467f7, 0x8f219828, 0x62e436f4, 0x6e5a550e, 0x14a18f3f, 0x00000000, 0x9427febe, 0x0fa7e9a9, 0x30f7d6d3, 0x35821db5, 0x8ac99687, 0xbfd64efb, 0xd18c1bf5, 0x7afbda31, 0x21be5743, 0xb071a752, 0xad1b80f1, 0x06f184fc, 0x8ca5d7b2, 0xdeb63795, 0xe82da073, 0x76d87c02, 0x9804588d, 0x6836143b, 0xb5046c34, 0xb0ec629b, 0x6791fd92, 0xee41e146, 0x839ffbd2, 0x733072ad, 0xdbc3fcf3, 0xd111de3c, 0x9d7193eb, 0x40de2e2d, 0x83023e1b, 0xd847b369, 0xf5da4219, 0x58c1c2e8, 0x435a61b7, 0x0c23a633, 0x4a91c92b, 0x5197afbd, 0x245659ec, 0xcce63c56, 0x8fbc5de1, 0x0a4fe706, 0xa221ac91, 0x009dc5c9, 0x54e264db, 0xdb5e393a, 0xa2bc6958, 0xe2ff82bc, 0x85f3bae7, 0x5db4098e, 0xa1a5e30b, 0x6ec790c7, 0x1d6a27a3, 0x393c7e4f, 0x33ee5c80, 0xff0860d6, 0x1882290c, 0xb61de667, 0x7645b9cb, 0x585c0721, 0xeba9efe9, 0xf54787d0 +}, +{ +0x69fb6077, 0xf6d405d0, 0xc5b15024, 0xbf6e4878, 0xc408f872, 0x0c74b2d8, 0x56ea875b, 0xadb12cb3, 0x91ed25eb, 0xfb5babe8, 0x9d999733, 0x6ab68e03, 0x75a4f046, 0xa288701f, 0x21ba313f, 0xf854f12a, 0x4af7a3dc, 0x8184b3b4, 0xd695280f, 0xf9ed597c, 0x3c5c0958, 0xe7043bd9, 0x6b4d92e3, 0x9f2f65a7, 0x7750b664, 0xa331d849, 0x83324120, 0xbc23a60c, 0x02b6f294, 0x79d0429e, 0x20412ddf, 0xc87c4aaa, 0x4ab5176a, 0xbdd8baec, 0xe87fd3c3, 0x02f44622, 0x21f88589, 0x31d3a760, 0xc44a4cc4, 0x92a0cb9f, 0x11d03e09, 0x8df0016c, 0xe9c67b95, 0x6680886d, 0xcacab83e, 0x92e27f29, 0x3eeafbcc, 0x49ba4da8, 0xdb1a8637, 0xb05714d4, 0x5b652963, 0x56a833ed, 0x5b279dd5, 0x45ceff70, 0x931963c9, 0x55a7692f, 0xca880c88, 0xd6d79cb9, 0xe5f07dfb, 0xbf2cfcce, 0x01fb1ce0, 0x01b9a856, 0x90548dbd, 0xb31afaa0, 0x44775726, 0xc707a2b0, 0xaf456a91, 0xd5d8c67b, 0xbe955498, 0xeb708901, 0xb1ac0834, 0x6474ce4f, 0x59d3dbf7, 0x5828c717, 0x57119bbb, 0x677b948d, 0x336555f4, 0x91af915d, 0x102b22e9, 0x68007c97, 0x76abaa84, 0x32dcfda2, 0x48415148, 0x2ec1d925, 0xe984cf23, 0x81c60702, 0xd9eec015, 0x6b0f2655, 0x2c359f07, 0x55e5dd99, 0x234e771d, 0x7a9dacea, 0xaf07de27, 0xbd9a0e5a, 0x230cc3ab, 0xe40b611b, 0xb1eebc82, 0xa1872add, 0x0c36066e, 0xa07c363d, 0xd4616e2d, 0x0dcd1a8e, 0x22b56bfd, 0x306a0f36, 0x11928abf, 0x9c628bd3, 0x00000000, 0x1da48cd1, 0x658fd2af, 0x1366cc9d, 0xaefcc2c7, 0xdaa32e61, 0xa1c59e6b, 0xe83d6775, 0xf599eba4, 0xe6bd938f, 0x1ee962a5, 0x0f395cac, 0xc7451606, 0x545c75cf, 0x7b66b00a, 0x3da715b8, 0x3f53539a, 0x3de5a10e, 0x8db2b5da, 0x20039969, 0x6af43ab5, 0xa03e828b, 0x6842c821, 0x3028bb80, 0xd8576843, 0x745feca6, 0x1324782b, 0x0f7be81a, 0xb2a352f6, 0xcb31a4de, 0x9ed47947, 0x59916f41, 0xb2e1e640, 0xd815dcf5, 0x2f3ac5c5, 0x0d8fae38, 0x458c4bc6, 0xdb583281, 0xdae19ad7, 0xd423da9b, 0xfae203be, 0x7adf185c, 0xcb731068, 0x5a9e3583, 0x66c23cdb, 0xf76dad86, 0xf72f1930, 0x935bd77f, 0x586a73a1, 0x8370f596, 0x2c772bb1, 0xd9ac74a3, 0xf462f744, 0xb3584e16, 0x8ebdef18, 0xe5b2c94d, 0xd59a72cd, 0x2f787173, 0x3ea84f7a, 0xfb191f5e, 0x3327e142, 0x1f127e45, 0x329e4914, 0x75e644f0, 0xf5db5f12, 0x76e91e32, 0x2dce83e7, 0xe6ff2739, 0x7b2404bc, 0x0e80f4fa, 0x034dee74, 0xc9c5e2fc, 0x9e96cdf1, 0x319113d6, 0xa3736cff, 0x030f5ac2, 0xc5f3e492, 0x741d5810, 0x782b5e7e, 0x5adc8135, 0x46831104, 0xadf39805, 0x4b4e0b8a, 0x12df64cb, 0xc6fcbe50, 0xd76e34ef, 0xe7468f6f, 0x0042b4b6, 0x8f04474e, 0xa2cac4a9, 0x1eabd613, 0x7869eac8, 0x2d8c3751, 0x6739203b, 0x9f6dd111, 0x1069965f, 0xbed7e02e, 0xea8b95e1, 0xbc6112ba, 0x2e836d93, 0x1f50caf3, 0xf9afedca, 0x4803e5fe, 0xac0884e5, 0xac4a3053, 0x8c49a93a, 0x803d1be2, 0xc83efe1c, 0xaebe7671, 0x8eff5bae, 0x47780de4, 0x828be976, 0xb015a062, 0x0ec2404c, 0x49f8f91e, 0x57532f0d, 0xd72c8059, 0xeac92157, 0x82c95dc0, 0xfaa0b708, 0x807faf54, 0x65cd6619, 0x1c1d2487, 0x22f7df4b, 0x541ec179, 0x69b9d4c1, 0x8c0b1d8c, 0xc987564a, 0x3f11e72c, 0xeb323db7, 0x9c203f65, 0xf816459c, 0x9016390b, 0x129dd07d, 0x3c1ebdee, 0xc6be0ae6, 0x1de63867, 0x1c5f9031, 0x64367af9, 0xf42043f2, 0xf696b166, 0x46c1a5b2, 0x9ddb2385, 0x473ab952, 0x4435e390, 0x771202d2, 0xe449d5ad, 0x7992f628, 0x8f46f3f8, 0x4b0cbf3c +}, +{ +0x24c4d807, 0xd5bc2316, 0x44695708, 0xa8594922, 0x6729fc87, 0x7b918f36, 0xa6b66161, 0xae47cf5d, 0x4d020cc3, 0xe2b55514, 0x4c98f934, 0x22da5e78, 0xa1587194, 0x5ecfa2c6, 0xba0e12d0, 0x019af5f7, 0x8272b966, 0x98be2fd5, 0x00000000, 0xae2dac20, 0x859ca993, 0x13a7cd78, 0x13cdae05, 0x69c6d4c4, 0x51d01c0f, 0x30e766f7, 0x2c5f1546, 0xd3a2a569, 0xd44cb59c, 0xcf1ad6d8, 0x97a1911c, 0x1aa6f5ce, 0x57ce9a70, 0x9f3a5c5d, 0x74e45282, 0xc7811b99, 0xf0886d9b, 0x006a637d, 0x090138b6, 0xceea4052, 0xebde0edf, 0xf696ebe4, 0x3117f07d, 0xc61bee6e, 0x7c15fcbe, 0x369383f5, 0x66b30970, 0x45f3a2ff, 0xb365491b, 0x50208a85, 0x0eef2843, 0x1449dd8d, 0x6836424e, 0x57a4f90d, 0x1cd210cc, 0x3763157f, 0x1d48e53b, 0xc7eb78e4, 0x8d6d07af, 0x4aec1c36, 0x72fad4fd, 0xedc088a0, 0x2c35763b, 0x66d96a0d, 0x7514c408, 0x387cabb6, 0x2daf83cc, 0xec5a7d57, 0xe345c39e, 0x9ea0a9aa, 0xb4e13a93, 0xc0056811, 0xf7667d6e, 0xcf70b5a5, 0x5f555731, 0x904f81e9, 0x22b03d05, 0x83e84c91, 0xbb94e727, 0xe2df3669, 0xff97d352, 0x1acc96b3, 0x01f0968a, 0xf70c1e13, 0x08f1ae3c, 0x58d124b9, 0xdac9fea2, 0xd25233e3, 0xa0c28463, 0x7d8f0949, 0x9f503f20, 0x91d5741e, 0x98d44ca8, 0x84065c64, 0xc89ea550, 0x25344e8d, 0x089bcd41, 0xdcd778dd, 0xa746f7eb, 0x9ecacad7, 0xec301e2a, 0xc8f4c62d, 0x0674e502, 0xe4c1b016, 0xdd27ee57, 0x4b76e9c1, 0x4599c182, 0x1d228646, 0x36f9e088, 0xbc7af7d2, 0x3816c8cb, 0x97cbf261, 0x2a419339, 0xf112986c, 0x7bfbec4b, 0xdb530b55, 0x994eb95f, 0x4277d177, 0xe531269c, 0x83822fec, 0xd426d6e1, 0x43ed2480, 0x2bdb66ce, 0x91bf1763, 0xb57bcf64, 0x51ba7f72, 0xedaaebdd, 0x1cb873b1, 0x061e867f, 0x123d388f, 0x60ad8f0f, 0x757ea775, 0xb30f2a66, 0xb511ac19, 0xf6fc8899, 0x3e622dc9, 0x4b1c8abc, 0x594bd14e, 0xd3c8c614, 0x4d686fbe, 0x1b3c0039, 0xd238509e, 0x3e084eb4, 0xf178fb11, 0xf989552d, 0x07847388, 0x398c3d3c, 0x9025e294, 0xe55b45e1, 0xfe6745d8, 0xc90450a7, 0xf0e20ee6, 0x44033475, 0x12575bf2, 0xa8332a5f, 0xf879c3a7, 0x308d058a, 0xea44fb28, 0x7c7f9fc3, 0xa9c3bcd5, 0x6fd852bb, 0x39e65e41, 0xb295df91, 0xbd8a6158, 0xafb759d7, 0x730a4277, 0xdb396828, 0x7360210a, 0x4cf29a49, 0x8218da1b, 0xfffdb02f, 0x846c3f19, 0xd5d6406b, 0x9924da22, 0x6e28c431, 0x685c2133, 0xea2e9855, 0x61377af8, 0x0f1fbec9, 0x0e854b3e, 0xe32fa0e3, 0xbbfe845a, 0x3ff8d83e, 0x60c7ec72, 0xc19f9de6, 0x7de56a34, 0x8b19e2ad, 0x3f92bb43, 0xdcbd1ba0, 0x56546f87, 0xc96e33da, 0x69acb7b9, 0x2bb105b3, 0xc1f5fe9b, 0x8c9d9125, 0x615d1985, 0x438747fd, 0x8d0764d2, 0x24aebb7a, 0xa6dc021c, 0x0f75ddb4, 0x7a6119bc, 0x096b5bcb, 0xf9e33650, 0xa13212e9, 0x7290b780, 0x563e0cfa, 0x07ee10f5, 0x8b7381d0, 0xe4abd36b, 0x317d9300, 0x963b64eb, 0xb48b59ee, 0x5f3f344c, 0x5921b233, 0xc06f0b6c, 0x15b94b07, 0x504ae9f8, 0x37097602, 0x58bb47c4, 0xa72c9496, 0x8cf7f258, 0x15d3287a, 0x421db20a, 0xa0a8e71e, 0xc6718d13, 0x2dc5e0b1, 0xdaa39ddf, 0x2a2bf044, 0x1b566344, 0xafdd3aaa, 0xbde00225, 0x1423bef0, 0xa9a9dfa8, 0x6fb231c6, 0xba6471ad, 0x96510796, 0xbc1094af, 0x8ae97427, 0xdd4d8d2a, 0x748e31ff, 0xce80232f, 0x2340ab8f, 0x85f6caee, 0x255e2df0, 0xb2ffbcec, 0xfe0d26a5, 0x8a83175a, 0x4a867f4b, 0x67439ffa, 0xf813a0da, 0x7a0b7ac1, 0x6e42a74c, 0x232ac8f2, 0x5ea5c1bb, 0xebb46da2 +}, +{ +0x19791738, 0xdd2ccf33, 0xee78cd2e, 0x05716355, 0x254ad4fd, 0xe088c66d, 0xee28e54b, 0xaeb99c79, 0x164efe85, 0x05214b30, 0xa4af3ef4, 0x98ccd554, 0xc124bb5e, 0x7252b1b4, 0xaf2e56e2, 0xe5a98d5d, 0x934dbd42, 0x8a34aa7a, 0x7723d2e1, 0xbd8601a9, 0x56df87b7, 0xb3760aea, 0x963cde17, 0x8e822bd1, 0xcb3219d3, 0x2f5c7670, 0xd6fd8f40, 0xd9ca66fd, 0x995b1fcf, 0xb60769bf, 0x5cc9253a, 0x80722092, 0x97ab148c, 0xa4ff1691, 0xb790a324, 0x17d9341e, 0xc455d80b, 0x38d56a0b, 0xa18e75c4, 0x37e283b6, 0xe0d8ee08, 0xf701da16, 0x6e0aedbc, 0x57186549, 0x251afc98, 0x8f45c92f, 0x0b816816, 0x65dbadcf, 0x6f9d2727, 0x4e315a14, 0x928a5fbc, 0xf83633ab, 0xdceb2dcd, 0x92da77d9, 0x4ad7f3da, 0xb7c08b41, 0x4a87dbbf, 0x5c990d5f, 0xd80d8403, 0x8f15e14a, 0x2beaf7db, 0x133f9dd0, 0xf9a1f930, 0x2e9b948e, 0xeb09ae7b, 0xdd7ce756, 0x78143b5c, 0xf6c638e8, 0xd3dcc470, 0x5269061c, 0xf270b943, 0x0f37e9bd, 0x990b37aa, 0xc5923af5, 0x8bf34884, 0x0bd14073, 0x6e5ac5d9, 0xa049973a, 0x4fa6908f, 0x4106b3a9, 0x81e5ea09, 0x85536ba2, 0xd76a45db, 0xaa0f1dd2, 0x12f87f2e, 0x7d35706c, 0xc405f06e, 0x161ed6e0, 0x76b4187a, 0x53fecc87, 0x3293e0e3, 0x0197ca9b, 0x3885426e, 0xcb6231b6, 0xb9308002, 0x04e6a9ce, 0x1dcf9693, 0xb326228f, 0x53aee4e2, 0x3c33c3c5, 0x12a8574b, 0x658b85aa, 0xce1352e3, 0x57484d2c, 0xf3e773d8, 0x3da4095e, 0xab98d749, 0xc0e359a0, 0x5d5eefa1, 0xefbf2fd0, 0x2ecbbceb, 0x136fb5b5, 0x3c63eba0, 0xe46e6fa3, 0x1c08746d, 0x8ed203b4, 0xe11f0cf6, 0x59b8466f, 0xd38cec15, 0xfc80b200, 0x60fae6ff, 0x4427f899, 0x17891c7b, 0xaee9b41c, 0x613d0401, 0x6aec4472, 0x0a468ae8, 0xc174933b, 0x32c3c886, 0xd21b268e, 0x6fcd0f42, 0x97fb3ce9, 0xcaf5fb2d, 0xabc8ff2c, 0x8a64821f, 0xb2e1c071, 0xe5f9a538, 0xbdd629cc, 0x2a2d1525, 0x00000000, 0xf2209126, 0x79d3d9a2, 0x73c57b2f, 0x206b9fcd, 0xb65741da, 0xa568dc0a, 0xf9f1d155, 0x9c7a54ff, 0x850343c7, 0xaf7e7e87, 0x391288f5, 0xce437a86, 0x40917932, 0xd6ada725, 0xd73a6dbe, 0x0f67c1d8, 0x6abc6c17, 0xcf849878, 0xf8661bce, 0x6b7b8ee9, 0x59e86e0a, 0x4e617271, 0x616d2c64, 0xeace4c85, 0x33042a78, 0xc0b371c5, 0x24dd1e66, 0x45b03202, 0x3942a090, 0x644c6754, 0x36256148, 0xbc41e357, 0x2f0c5e15, 0x989cfd31, 0x248d3603, 0x7773fa84, 0x52392e79, 0x1c585c08, 0xb2b1e814, 0xd99a4e98, 0xcfd4b01d, 0x7cf29292, 0x3675492d, 0xf696108d, 0xf3b75bbd, 0xfd4750fe, 0x8ba360e1, 0xefef07b5, 0xd24b0eeb, 0x7d655809, 0x21ac7d33, 0x78441339, 0x45e01a67, 0x966cf672, 0x4ff6b8ea, 0x21fc5556, 0x40c15157, 0x37b2abd3, 0x3df4213b, 0xdcbb05a8, 0x582f8cf4, 0x2a7d3d40, 0x6b2ba68c, 0xeb59861e, 0xaa5f35b7, 0x931d9527, 0x8494895c, 0xc5c21290, 0x18bef5c6, 0xb960a867, 0x76e4301f, 0xbc11cb32, 0x84c4a139, 0x2bbadfbe, 0x641c4f31, 0xf751f273, 0x7395534a, 0x04b681ab, 0x0a16a28d, 0x7ca2baf7, 0xcaa5d348, 0x5d0ec7c4, 0x9ded9e64, 0x720299d1, 0x19293f5d, 0x7983f1c7, 0x9dbdb601, 0x81b5c26c, 0x00502865, 0x4b101124, 0xa538f46f, 0xe14f2493, 0x4477d0fc, 0xb8a74a99, 0xfcd09a65, 0xb8f762fc, 0x203bb7a8, 0x0ea02326, 0x568fafd2, 0xa019bf5f, 0x587fa491, 0x01c7e2fe, 0x9c2a7c9a, 0xe43e47c6, 0x3354021d, 0x1d9fbef6, 0x60aace9a, 0xa1de5da1, 0xea9e64e0, 0x41569bcc, 0x18eedda3, 0x802208f7, 0x0ef00b43, 0xd85dac66, 0x4b403941, 0xfd17789b +}, +{ +0x8004d846, 0xdeba5fe4, 0xae249c02, 0xa341209f, 0x2fcdc5e1, 0xfd7ad0ca, 0x0625cc97, 0x557b805f, 0xd57f5819, 0xa39b2744, 0x7dfb7f7b, 0x52b3cd6d, 0x0c0d4acf, 0x0a288658, 0xd84594a8, 0xa85e20b9, 0x71f635b4, 0x71a94598, 0xd26d12f0, 0xfbda6baa, 0x005f702c, 0xdf57de41, 0x222d0e8b, 0xf6e0a71b, 0xfda0d711, 0x7da40f57, 0xf128ea29, 0x5524f073, 0x8af659c5, 0x7cccf905, 0x5269cab6, 0x8a2c5e1e, 0x8d3e14f7, 0x248db5eb, 0x8d6164db, 0xd417ae4b, 0x81b629cf, 0x5f0c762b, 0x8c8ce57e, 0x53013ce4, 0xfcc82143, 0x5236ba9a, 0x86a46326, 0xfa689a23, 0x0b9a77d1, 0x712c326f, 0x544c0621, 0xa8db574e, 0xaefe9bd9, 0x285af8ff, 0x2560344e, 0x8a732e32, 0x59f3bd67, 0x06ffcb4c, 0x70c1b3ca, 0x7044c43d, 0x22727ea7, 0x2345f8d9, 0xfb5f1c5d, 0x0de0cb6a, 0x0137867e, 0x778c890f, 0x7a333249, 0x5413760d, 0xfaededd4, 0x8aa929e9, 0x5f530607, 0x7c16fede, 0x29e80976, 0x239fff02, 0x7b81c3c0, 0xa4d61d81, 0xa31e50b3, 0x7ae93592, 0x7ab645be, 0x763e7886, 0x0c883d38, 0xf7885149, 0xa229d6cd, 0x86fb130a, 0x816c2e14, 0xfa37ea0f, 0x5ebe87a2, 0xd89f9373, 0x76bb0f71, 0xfc97516f, 0xa276a6e1, 0xd3809355, 0x53db3b3f, 0x867e64fd, 0xd5202835, 0xa2aca13a, 0x25e543b9, 0x766108aa, 0x0a77f674, 0x81335e38, 0x54c971d6, 0x5f8901dc, 0x2e204444, 0x8081afb1, 0x06a0bb60, 0xdf8dd99a, 0xfc122698, 0x5e648079, 0x535e4cc8, 0x2f48b216, 0x2e7f3468, 0x77568ed4, 0x2ea533b3, 0xa4536a76, 0xd5a55fc2, 0xa9ecd130, 0x55fef7a8, 0x0dbfbb46, 0xf63aa0c0, 0x59accd4b, 0xf0c56b8c, 0x8c56e2a5, 0xf1f2edf2, 0x231a88f5, 0xf09a1ba0, 0x07124ae9, 0xfb851b86, 0x0c523ae3, 0x23c08f2e, 0x074d3ac5, 0x7709fef8, 0x22a8797c, 0x253f4462, 0x55a18784, 0x52ecbd41, 0x53844b13, 0x8749e283, 0x067abcbb, 0x2f92b5cd, 0x0168f652, 0xd35a948e, 0x862114d1, 0xf7525692, 0xd492d9bc, 0x0af28183, 0xf70d26be, 0x80dedf9d, 0x5e3bf055, 0xa5e19bff, 0x8c099289, 0x7b04b437, 0xd92d62fa, 0x549601fa, 0xd3dfe379, 0xfd25a0e6, 0x5ee1f78e, 0xd2e86507, 0x2880ff24, 0xd97212d6, 0xdf08ae6d, 0xaea1ebf5, 0x709ec3e6, 0x2408c21c, 0x2efa439f, 0x01ed81a5, 0x8793e558, 0xd9f76521, 0xdee52fc8, 0xaf966d8b, 0xa5beebd3, 0x7a6c4265, 0x58414cee, 0xae7bec2e, 0x07973d1e, 0x2f17c23a, 0x8bc1dfbb, 0xf7d72165, 0x01b2f189, 0x00000000, 0x8dbb6300, 0x7d7e088c, 0x77d3f923, 0xfb006c71, 0x701bb411, 0x58c43b19, 0xa564ec08, 0x28df8f08, 0xd23262dc, 0x0b1f0026, 0xd4cda990, 0x24d2c5c7, 0xa53b9c24, 0xd305e4a2, 0x5976ca90, 0xa936d6eb, 0xa40c1a5a, 0x0bc507fd, 0x871692af, 0x7d2178a0, 0xdfd2a9b6, 0x296d7e81, 0xd81ae484, 0x0b40700a, 0xd8c0e35f, 0x5929babc, 0xa8015095, 0xd448de67, 0xaf4c6a50, 0x7b5bc41b, 0xa2f3d116, 0xfc4d56b4, 0xd9a8150d, 0xa4896dad, 0xd2b7152b, 0x2457b230, 0xf1779a05, 0xf01f6c57, 0x71734243, 0xf1ad9dde, 0xafc91da7, 0x0d3accb1, 0xde3f2813, 0x29b7795a, 0x8cd39552, 0xa969a6c7, 0xa8842762, 0x7c498ef2, 0x280588d3, 0x29320ead, 0xde60583f, 0xf6bfd737, 0x8b9eaf97, 0x0d65bc9d, 0xd5fa2fee, 0x581e3cc2, 0xf0401c7b, 0x81e959e3, 0x76e47f5d, 0xa9b3a11c, 0x00da07db, 0x0aadf1af, 0xf665d0ec, 0x589b4b35, 0xa3c45768, 0xfab29df8, 0x87cc9574, 0x8b1bd860, 0x8de4132c, 0x8b44a84c, 0xaf131a7c, 0x07c84d32, 0x805ba86a, 0xfdffa73d, 0x008577f7, 0x7bdeb3ec, 0x5fd671f0, 0x7c938929, 0x0cd74d14, 0x22f70950, 0x25ba3395 +}, +{ +0xadd93554, 0x49bce2a7, 0x2441f55d, 0x53b7b103, 0x26d8d4a3, 0x249dd669, 0x77f6445e, 0x148cc81b, 0x5635202d, 0xa4993d0f, 0xe6fcf60d, 0x7c2f6dfb, 0x1d10e374, 0x055eb21a, 0x6d2134ce, 0x66243e5f, 0x9ad39bf6, 0xda2f710a, 0xc7e3b14a, 0x211f4747, 0x5f752876, 0xe37e6723, 0x37d68d96, 0x0940085b, 0xd6ede87f, 0xa3828ddf, 0xad051660, 0x4265cb02, 0xc2bd0350, 0x56e90319, 0xe8a74e86, 0x0b050a91, 0x8e5f53ed, 0x536b9237, 0xcbfd0b0b, 0x4ce250bd, 0x5af7b958, 0xdf71c310, 0xbcd76c61, 0x40fceafc, 0xdde8e2ee, 0xb597643a, 0x6ae6a72a, 0x110e5935, 0x5fa90b42, 0x9f8d29ec, 0x7be8fe1f, 0xf7f2af38, 0x370aaea2, 0x39511629, 0xaf9c379e, 0xb70e45c4, 0x85867a48, 0xfb30364d, 0x5dec0988, 0x586e98a6, 0x855a597c, 0xd4a8eab5, 0x871f5bb6, 0xe3a24417, 0x0582912e, 0x28836c28, 0x1615e9e5, 0xa85ba47a, 0xce7f9a25, 0x2604f797, 0xe1e746dd, 0x7274d570, 0x0cc29975, 0x47e75a2c, 0x4bf9e06d, 0x099c2b6f, 0xfc2b869d, 0x16c9cad1, 0x30cd3d46, 0x32541cb8, 0xedf9fc9c, 0x285f4f1c, 0x9a0fb8c2, 0xa11bac21, 0x79adfcd5, 0x772a676a, 0x2d01fd06, 0x0e5bb88b, 0xcc3a98ef, 0x9488237d, 0x1a0b53a4, 0xa6dc3fc5, 0x024502ca, 0x9f510ad8, 0x473b7918, 0x134b5bff, 0xa4451e3b, 0x071bb0d0, 0x1dccc040, 0x94540049, 0xd474c981, 0xc0f8019a, 0x354fac68, 0xf9753487, 0x238666b9, 0xf0e91fe8, 0x4e7b7143, 0x00dc2334, 0x64bd1fa1, 0xe620d539, 0x8b01e1f7, 0xa1c78f15, 0xa35eaeeb, 0xc9b809c1, 0x637a8c45, 0xbc0b4f55, 0x3e9685cd, 0x7b34dd2b, 0xaf4014aa, 0x457e7bd2, 0xd8b650f4, 0xe13b65e9, 0x45a258e6, 0x939393ad, 0x70edf48e, 0x235a458d, 0xc2612064, 0xc73f927e, 0x4960c193, 0xbe926eab, 0x139778cb, 0x30111e72, 0x398d351d, 0xaac28584, 0x2f98dcf8, 0xc02422ae, 0xf72e8c0c, 0xdd34c1da, 0xd1f658af, 0x756f65a0, 0xd631cb4b, 0x7eb64c05, 0x2f44ffcc, 0x6f643604, 0x64613c95, 0xa6001cf1, 0x1ad77090, 0xd12a7b9b, 0x75b34694, 0xcb21283f, 0xfeb2a763, 0x6a3a841e, 0x00000000, 0xb54b470e, 0xe87b6db2, 0x6fb81530, 0xea3e6f78, 0x984aba08, 0x1450eb2f, 0xed25dfa8, 0x5d302abc, 0x029921fe, 0xeae24c4c, 0xb28cd4ea, 0xf2703e16, 0x8c1a5127, 0xc5a6b380, 0x1f89c28a, 0x5a2b9a6c, 0x61e3adbb, 0x9d140812, 0x66f81d6b, 0x512e90fd, 0x8998c009, 0xc9642af5, 0xdaf3523e, 0xd3b35a65, 0x1f55e1be, 0x3cd38707, 0xb250f7de, 0xf0353cdc, 0xbbccdcb1, 0xaa1ea6b0, 0x829dca98, 0xe4b9f4c7, 0x7cf34ecf, 0x3bc837d7, 0x8bddc2c3, 0x42b9e836, 0x4ea75277, 0x2dddde32, 0x4b25c359, 0x6dfd17fa, 0x0c1eba41, 0x8e8370d9, 0x7e6a6f31, 0x32883f8c, 0x68a3a5e0, 0xb015f514, 0x184e516e, 0x3c0fa433, 0x35938f5c, 0x3b1414e3, 0x3e4aa6f9, 0xa887874e, 0xcea3b911, 0xb989de7b, 0x96cd21b7, 0x11d27a01, 0xfcf7a5a9, 0xd36f7951, 0xf2ac1d22, 0xef60dd62, 0x63a6af71, 0x934fb099, 0x1892725a, 0x613f8e8f, 0xcce6bbdb, 0x4020c9c8, 0x87c37882, 0xe465d7f3, 0xb0c9d620, 0x7031d7ba, 0x8004eb66, 0x7971dfe1, 0x8241e9ac, 0x51f2b3c9, 0xb7d266f0, 0x687f86d4, 0xb955fd4f, 0x2a1a4dd6, 0xfbec1579, 0x58b2bb92, 0x07c793e4, 0x8cc67213, 0x9896993c, 0x21c36473, 0xf5b7adf2, 0xc57a90b4, 0xbe4e4d9f, 0x96110283, 0x910ab253, 0xf9a917b3, 0x72a8f644, 0xd86a73c0, 0x8944e33d, 0x0e879bbf, 0x80d8c852, 0xdfade024, 0x91d69167, 0x2ac66ee2, 0xbb10ff85, 0x54ac01d3, 0xefbcfe56, 0x4c3e7389, 0xf56b8ec6, 0x547022e7, 0x9dc82b26, 0x0bd929a5, 0xfe6e8457 +}, +{ +0x070a74ce, 0x770145a4, 0x598711da, 0x19919ab5, 0x72ced1b8, 0x558ebf9d, 0xff15d5db, 0x7ec77fff, 0x1b8fe981, 0x605c9184, 0x2091890d, 0xd855bbfe, 0xa45724d3, 0x9d57376b, 0xc8d988f6, 0xd699f56b, 0xd88e2818, 0x225469df, 0x1057a0ee, 0xd3566177, 0xd19381a5, 0xd1481243, 0x69413839, 0x3509bdff, 0x595c823c, 0x0e17dd73, 0xb11483c7, 0xe3904894, 0xf6d3ef80, 0x77dad642, 0xe34bdb72, 0x6e90df11, 0xea5672cf, 0x35d22e19, 0x699aabdf, 0x5e8d6514, 0x55552c7b, 0x86d8deea, 0xb3d16315, 0x91850aca, 0x6548967e, 0x574b5f4f, 0xaa9b6a46, 0x6b84d8eb, 0x4e01561c, 0x5b42f108, 0x490b22d2, 0x4cc4b6ce, 0x175dd420, 0xf1d99b4e, 0x81d2aa24, 0x70d0a28c, 0xcf086fde, 0xbfd8cd52, 0x194a0953, 0x49d0b134, 0xb4db17db, 0x07d1e728, 0xbf035eb4, 0x8ad170ad, 0x5c4885c6, 0xe155a846, 0x65930598, 0x4b1551e6, 0x6c8eac25, 0x1b547a67, 0xd38df291, 0xb8092a7a, 0x6e4b4cf7, 0x5790cca9, 0xbd1d2d80, 0x051407fa, 0x2e86547e, 0x8a0ae34b, 0x45028c95, 0x02c5e0d2, 0x678d76ac, 0xfa01d221, 0x9654ede2, 0x279bfdc3, 0x60870262, 0xca1c6824, 0x301dba05, 0x8fc57757, 0xef99e6d3, 0xb1cf1021, 0x2b925384, 0x0c09ae47, 0x939b79fe, 0x228ffa39, 0x47c76c47, 0x4edac5fa, 0x3ed1f490, 0x9898a377, 0x40168b6f, 0x3e0a6776, 0xc11fb2ad, 0x8d009785, 0x5e56f6f2, 0xc301c199, 0xd487865f, 0x6242e2b0, 0x40cd1889, 0x1292403c, 0x9f49445f, 0xa386c3fb, 0xb30af0f3, 0xa692c401, 0xf31c7b9c, 0xdf5fcf30, 0x94910d30, 0x3203c931, 0xc40bb557, 0x4c1f2528, 0x9340ea18, 0xd45c15b9, 0x8f1ee4b1, 0xe65fdc88, 0xed5c0601, 0x204a1aeb, 0x7215425e, 0x471cffa1, 0x108c3308, 0xcdcd8f0c, 0xef427535, 0x25858ef7, 0x091da9bd, 0x525f58b5, 0xf81fa115, 0xa198b0cf, 0xd642668d, 0xf8c432f3, 0x45d91f73, 0xa1432329, 0xa48cb735, 0xb400843d, 0xf4cd9cb4, 0xfd0ba6ef, 0x9d8ca48d, 0xdf845cd6, 0x3c141442, 0x791698d7, 0xaf54fe5a, 0xed8795e7, 0x4bcec200, 0x1c5e0ea9, 0x3bc5f36a, 0x37cc5d2d, 0x021e7334, 0x7e1cec19, 0xcd161cea, 0xe84801fb, 0x7cd90ccb, 0xb8d2b99c, 0x84c6adde, 0xcac7fbc2, 0xdd9a2fe2, 0x39db805e, 0x0b03da89, 0x88cf0399, 0x30c629e3, 0xfada41c7, 0xc615c663, 0x7c029f2d, 0x841d3e38, 0x2c43b4ac, 0xad911e88, 0x6c553fc3, 0x9f92d7b9, 0xc6ce5585, 0x968f7e04, 0xda4bc8ca, 0xc4d026b1, 0x4208f85b, 0xdd41bc04, 0x1249d3da, 0xf6087c66, 0xa8851972, 0xf3c7e87a, 0x05cf941c, 0x3b1e608c, 0x98433091, 0x62997156, 0x00db93e6, 0xe893921d, 0x8ddb0463, 0xea8de129, 0x2e5dc798, 0x178647c6, 0xe441afbc, 0xad4a8d6e, 0x2957b356, 0xb6c564ef, 0xda905b2c, 0xa64957e7, 0xc1c4214b, 0x0ecc4e95, 0xe6844f6e, 0x3ccf87a4, 0x2b49c062, 0x79cd0b31, 0x32d85ad7, 0xa85e8a94, 0xbacccaa8, 0x8814907f, 0xf10208a8, 0x751f3690, 0x42d36bbd, 0x9a86d043, 0x00000000, 0x1c859d4f, 0x27406e25, 0x7b08ebe3, 0xcfd3fc38, 0x5b9962ee, 0x83174af6, 0x1e407d9d, 0xbdc6be66, 0xaa40f9a0, 0x390013b8, 0xaf8f6dbc, 0x509ab867, 0x09c63a5b, 0xba17594e, 0x75c4a576, 0xe49a3c5a, 0x2c98274a, 0x810939c2, 0x159834f2, 0xf4160f52, 0x944a9ed6, 0x7bd37805, 0xfdd03509, 0xb61ef709, 0xc3da527f, 0xc8021b10, 0x5284cb53, 0xa35d501d, 0x86034d0c, 0x0cd23da1, 0xffce463d, 0x50412b81, 0x255e1d11, 0x915e992c, 0x9a5d43a5, 0x83ccd910, 0x1543a714, 0x6756e54a, 0x1e9bee7b, 0x6b5f4b0d, 0xe18e3ba0, 0x0bd8496f, 0x3717cecb, 0x298c20b0, 0x700b316a, 0x5c931620 +}, +{ +0x6e8ee46d, 0x168d18f6, 0x8b6ee681, 0xaa84a2fe, 0x5e5e856c, 0x48d39d9a, 0xccc8a953, 0xb36e31f9, 0x76fac2a5, 0x47a64fd2, 0x0ef93e3e, 0xbd85567e, 0xe46cee9a, 0x9df1a7ce, 0xa3d8f8f1, 0x931ac049, 0x10b6c908, 0x094e03b6, 0x50b5e2eb, 0x83ac0941, 0x462aa3a4, 0xdbdb046a, 0xa5e3290f, 0x799d4954, 0x315c8d77, 0xa2541487, 0x50a7bb52, 0xd5223a54, 0x3e295f3f, 0x70d34ae2, 0x8ccb82b0, 0x7811a522, 0xdc7e605b, 0x10a490b1, 0xab1a1731, 0x4ee84c64, 0xc231976d, 0xc594f35c, 0x9de3fe77, 0x1713ad39, 0x3e3b0686, 0x08c2efc0, 0x7764776a, 0x4011725a, 0xa3caa148, 0xab084e88, 0x001259b9, 0x494d2855, 0xacbf7300, 0x61fb3625, 0xe3c98aab, 0xe5f25b55, 0xe24566dd, 0x92847586, 0xf556cbe4, 0xcaf378ad, 0x7e2a74dc, 0x8cd9db09, 0x952111b7, 0xcd444525, 0x930899f0, 0x07a56431, 0x59fbe15d, 0x264f204e, 0xd30bb213, 0xed22ed2c, 0xf36d1a1a, 0xddf28c2d, 0xdbc95dd3, 0xb2e2dd8f, 0x6939d9e5, 0x08d0b679, 0x6e9cbdd4, 0xba20324f, 0x569c6aac, 0xacad2ab9, 0xc40a4693, 0x265d79f7, 0x4f64a012, 0xccdaf0ea, 0x8232bc8e, 0x92962c3f, 0x4638fa1d, 0x293af206, 0x3fa5b349, 0x58655492, 0xd53063ed, 0x2928abbf, 0x85858106, 0x7e382d65, 0x2f137a41, 0x606583ea, 0x8220e537, 0x30d06101, 0xb4d90c71, 0x21ea447f, 0xc3bd7b1b, 0x2066a809, 0x11287cc7, 0xa47d9cc0, 0xc223ced4, 0xeb193cd2, 0xf4c87e2b, 0x9a469a46, 0xd319ebaa, 0x7803fc9b, 0xe47eb723, 0x4f76f9ab, 0xad21c6cf, 0x19ea9307, 0x5e4cdcd5, 0x94adfdc1, 0x692b805c, 0xd2875e65, 0x715fa694, 0x47b4166b, 0x113a257e, 0x51390e9d, 0xcb7f94db, 0x19f8cabe, 0xe5e002ec, 0x419d9e2c, 0x314ed4ce, 0x0f75d248, 0x18667f71, 0x169f414f, 0x67c0e7db, 0x399e62b7, 0xf4da2792, 0x5702df63, 0x8af0534e, 0xfd867d9d, 0x37750530, 0xba326bf6, 0x9c7d4bb8, 0x36ebb0ff, 0x94bfa478, 0x512b5724, 0x418fc795, 0x571086da, 0x664c0bad, 0x798f10ed, 0x063bd1fe, 0xbbacde39, 0xa5f170b6, 0x61e96f9c, 0xc3af22a2, 0x00000000, 0x68b53593, 0x2e8dcf8e, 0x06298847, 0x37675c89, 0x2f0123f8, 0x83be50f8, 0xe2573f64, 0xa2464d3e, 0x6f1051a2, 0xad339f76, 0x9bca7630, 0x40032be3, 0xb547b9be, 0x9533480e, 0x9a54c3ff, 0x8d55377f, 0x5fd2691a, 0xfa314015, 0x36f9e946, 0xf37f43a3, 0xecbc58e3, 0x38128ec1, 0x9c6f1201, 0x76e89b1c, 0x665e5214, 0x27c3cc38, 0xfbbdac63, 0xbc09ba08, 0xda57e81c, 0x1701f480, 0x27d19581, 0xbc1be3b1, 0xcae12114, 0x5fc030a3, 0x3fb7eaf0, 0xd29507dc, 0xc586aae5, 0xd4aed622, 0x1e4ff736, 0x841b34c9, 0x2e9f9637, 0x9bd82f89, 0xe3dbd312, 0xfd942424, 0xda45b1a5, 0xd4bc8f9b, 0x28a447c9, 0xfbaff5da, 0xb37c6840, 0xcd561c9c, 0x8ae20af7, 0x07b73d88, 0x30c238b8, 0xb555e007, 0x0f678bf1, 0x6077da53, 0x67d2be62, 0x1e5dae8f, 0xcb6dcd62, 0xbd970fc7, 0xc4181f2a, 0x1fc31b40, 0xea87891d, 0x59e9b8e4, 0x70c1135b, 0xaa96fb47, 0xbbbe8780, 0x4efa15dd, 0x21f81dc6, 0x7fb4c113, 0x095c5a0f, 0xea95d0a4, 0x28b61e70, 0xfa2319ac, 0x0eeb6787, 0x7fa698aa, 0x58770d2b, 0xf544925d, 0xecae015a, 0x6f02081b, 0x2074f1b0, 0x77762ed3, 0xdde0d594, 0x495f71ec, 0x187426c8, 0x019eb5cf, 0x8b7cbf38, 0xa46fc579, 0xf2f3afd5, 0x398c3b0e, 0x1fd142f9, 0x8597d8bf, 0xfc0a91eb, 0xb4cb55c8, 0x48c1c423, 0x68a76c2a, 0xeb0b656b, 0xfc18c852, 0x3800d778, 0x84096d70, 0xed30b495, 0xf2e1f66c, 0x568e3315, 0xb2f08436, 0xdc6c39e2, 0x018cec76, 0x8d476ec6, 0x714dff2d +}, +{ +0x919ae77e, 0x18cc5dba, 0x904af99f, 0x12505b1e, 0x3a7311fe, 0x9ad6ff3b, 0x45a6c455, 0x2e75a510, 0x83cabc60, 0x242cf4cd, 0x00000000, 0x138045ff, 0xabe9f680, 0xe90c94bd, 0x609f7900, 0xc0ffc0bc, 0x908faee6, 0x844c4d71, 0x97cc088e, 0xf6836f6f, 0xfb9998da, 0xf010d7e6, 0x5b3c761f, 0x0743a668, 0x50706e5a, 0xb4a35a2b, 0xde6572f6, 0x3ce0a977, 0x2fa5bbf1, 0xa7231fd4, 0xd3bad23a, 0x9a13a842, 0x0656eff0, 0xd37f8543, 0xe2408cf8, 0xb8ace406, 0xe9c9c3c4, 0x6c559054, 0x19d91422, 0xa175f024, 0x15d6aa0f, 0x1f4aacab, 0xef5a7b4d, 0xc12fde5d, 0x4e2f8b69, 0xbefa0bf6, 0x01154998, 0xb97cfae7, 0xcaa69161, 0xccf07e91, 0x961c166f, 0x5dafce96, 0x0693b889, 0x37acb132, 0x28e61d99, 0xd926d49e, 0x3769e64b, 0x859c5390, 0x4f3ac2f1, 0x5aec68fe, 0x6a037fa4, 0x8993edbd, 0xc77931ad, 0x1406b4ee, 0xfcda3eb2, 0x01d01ee1, 0x0c0fbe2d, 0x6ac628dd, 0xadbf1970, 0xacaa50e8, 0x3b665866, 0xdea0258f, 0x0b894f3c, 0xa7e648ad, 0x8ed04bd5, 0xcbb3d8f9, 0x49a97a78, 0x56e3d6d3, 0x5cba870e, 0x9c8010cb, 0x42203544, 0x13451286, 0xf753718e, 0x6d858eb5, 0x7f1082d2, 0x84891a08, 0x5c7fd077, 0x0ddfa0cc, 0xc1ea8924, 0xd8f6ca7f, 0x1e9ab24a, 0x6b16363c, 0x0a9c06a4, 0x82dff5f8, 0xb4660d52, 0xfb5ccfa3, 0xb3e0fc43, 0x7fd5d5ab, 0x31fa5ec2, 0xe355c560, 0xb325ab3a, 0x18090ac3, 0xe5c67de9, 0x8886a425, 0x36b9f8aa, 0x6d40d9cc, 0x2eb0f269, 0x5bf92166, 0xaafcbf18, 0x789673c3, 0x25fcea2c, 0x0d1af7b5, 0x7499cdee, 0xbfef426e, 0x50b53923, 0x8fc5024d, 0xbe3f5c8f, 0x745c9a97, 0x516527c2, 0xcc3529e8, 0xc03a97c5, 0xfa49863b, 0x5d6a99ef, 0x0b4c1845, 0xe285db81, 0xb2f5b5db, 0x2f60ec88, 0xab2ca1f9, 0x57f69f4b, 0x67dcdf68, 0xb57344ca, 0x23aa05dc, 0x915fb007, 0xcde53709, 0x8f005534, 0x3ba30f1f, 0xad7a4e09, 0xa1b0a75d, 0x562681aa, 0xe4166308, 0xac6f0791, 0x855904e9, 0x3c25fe0e, 0xe3909219, 0x367cafd3, 0x51a070bb, 0x9bc3b6a3, 0x191c435b, 0x29360378, 0x1513fd76, 0xf79626f7, 0xe4d33471, 0xa6f30135, 0xee4f32d5, 0x8e151cac, 0x48796499, 0x9c4547b2, 0x3ab64687, 0x4563932c, 0x7e05cb4a, 0xfc1f69cb, 0x8843f35c, 0xcd206070, 0xf0d5809f, 0x73da6b86, 0x302a4023, 0xb5b613b3, 0x496c2d01, 0x4476dab4, 0x8956bac4, 0x618a3098, 0x66c996f0, 0x830feb19, 0xd5ec3dca, 0x79466d22, 0x0786f111, 0x1e5fe533, 0x0a5951dd, 0x821aa281, 0x2539bd55, 0x3d30b796, 0x236f52a5, 0xe8dc8a5c, 0xc7bc66d4, 0x660cc189, 0xdfb56c17, 0x9b06e1da, 0xfa8cd142, 0x14c3e397, 0x67198811, 0xd26accdb, 0xee8a65ac, 0x4fff9588, 0x96d94116, 0x30ef175a, 0xdf703b6e, 0xd4f97452, 0xe5032a90, 0xc66c7835, 0xf1059e7e, 0x44b38dcd, 0x22bf4c44, 0x1f8ffbd2, 0x42e5623d, 0x3df5e0ef, 0x7ec09c33, 0xd8339d06, 0x72cf221e, 0xe819dd25, 0x29f35401, 0x4eeadc10, 0x24e9a3b4, 0x720a7567, 0x605a2e79, 0xb9b9ad9e, 0x28234ae0, 0xb869b37f, 0x758c8476, 0x6c90c72d, 0x00c55779, 0xf6463816, 0x6bd36145, 0xd9e383e7, 0x5a293f87, 0x313f09bb, 0xa636564c, 0xaa39e861, 0xa060b9bc, 0x614f67e1, 0x785324ba, 0x79833a5b, 0x43357cdc, 0xc6a92f4c, 0x9d955953, 0xf1c0c907, 0x227a1b3d, 0x5733c832, 0x12950c67, 0x0ccae954, 0xca63c618, 0x48bc33e0, 0xb230e2a2, 0xef9f2c34, 0xd2af9ba2, 0xcb768f80, 0xfdcf772a, 0x43f02ba5, 0xfd0a2053, 0x7549d30f, 0xd43c232b, 0x97095ff7, 0xd5296ab3, 0xbf2a1517, 0xa0a5eec5, 0x9d500e2a, 0x731f3cff +}, +{ +0x319ff16a, 0x4ec1e4df, 0x0527436f, 0xa752cff5, 0x4c3de052, 0x00000000, 0x4122c620, 0x3c367a61, 0x36f21bf1, 0xa6327a97, 0x01d6181b, 0x78855257, 0xe3e1e7c3, 0x700b9a33, 0x923c65eb, 0xdfd79da2, 0x07db47e2, 0x7baf4ec1, 0x7b19e3b8, 0x992e1c60, 0xd31ea3cb, 0x0e353ae4, 0x372403ea, 0x479934a0, 0x0447f60d, 0x9998b119, 0x38c72115, 0xe0cbfb55, 0x935cd089, 0x724133c7, 0x3e7cd395, 0x7606c5ca, 0x42be77cf, 0xa9d15868, 0x40f4de3b, 0x7e3ea0d7, 0x9e43f6fb, 0xa8b1ed0a, 0x9076cc1f, 0xe1ab4e37, 0xd68f4ddd, 0x3bed3d83, 0x928ac892, 0x032a1c96, 0xed62705e, 0xdb26c6d6, 0x7da21138, 0xad96ae65, 0x4e7749a6, 0x33d5589e, 0x4be6a7b0, 0x3f1c66f7, 0x3644b688, 0xd7eff8bf, 0x91a0d404, 0x0b12798b, 0x0a72cce9, 0x9d69ea6d, 0x0d1f2672, 0xab9bf19c, 0x32034085, 0xdd9d3456, 0xebd982de, 0x464f2cbb, 0xac40b67e, 0x9bd218ed, 0xec02c53c, 0x7c740923, 0xef9e74d3, 0x4fa151bd, 0x7d14bc41, 0xd80cda40, 0x0838651d, 0xd1540a3f, 0xa31539f8, 0x0ac46190, 0x3911390e, 0xda4673b4, 0xafdc0791, 0xe48c0d58, 0xe6c6a4ac, 0x31295c13, 0x95e72209, 0x71dd8228, 0x96cd3e9f, 0x3faacb8e, 0xa5aecb78, 0x984ea902, 0x759a7425, 0x9ddf4714, 0x38718c6c, 0xd8ba7739, 0x3d56cf03, 0x3c80d718, 0x4a30bfab, 0xa478d363, 0x73972bdc, 0xeefec1b1, 0xdaf0decd, 0x0e83979d, 0x9f95eee0, 0x30ff4408, 0x3b5b90fa, 0xa4ce7e1a, 0xe237ffd8, 0xd96c6f22, 0x94313a12, 0x356eaa1e, 0x72f79ebe, 0xa0898817, 0xdeb728c0, 0x3363f5e7, 0xa15f900c, 0x9f234399, 0x9ab2ad8f, 0xdd2b992f, 0xde0185b9, 0x340e1f7c, 0x4f17fcc4, 0x3792ae93, 0xedd4dd27, 0xee486cc8, 0x06bbf280, 0x46f981c2, 0xe67009d5, 0x41946b59, 0xe9258653, 0x00b6ad79, 0x74fac147, 0xd513fc32, 0x97ad8bfd, 0xa5186601, 0x76b068b3, 0xea0f9ac5, 0xd0821224, 0x0cc93e69, 0xd75955c6, 0xe07d562c, 0x4208dab6, 0xd9dac25b, 0x43686fd4, 0x98f8047b, 0x4a8612d2, 0x45d39d54, 0x716b2f51, 0xa03f256e, 0x7e880dae, 0xaa4de987, 0xd3a80eb2, 0x49ac0e44, 0x0160b562, 0xd4c5e429, 0x70bd374a, 0x3a8d88e1, 0xe7a611ce, 0x32b5edfc, 0x3de0627a, 0xa8074073, 0xe8453331, 0xa2c321e3, 0x024aa9f4, 0x752cd95c, 0xd639e0a4, 0x3a3b2598, 0xe3574aba, 0xe710bcb7, 0x4debf849, 0x09ee7d06, 0x7a7956da, 0x9ef55b82, 0x0f558f86, 0x04f15b74, 0x3eca7eec, 0x4405854f, 0xe43aa021, 0xe28152a1, 0x076dea9b, 0xd4734950, 0x4c8b4d2b, 0x487a165f, 0x491aa33d, 0xae0a1f8a, 0xa1e93d75, 0xe55a1543, 0x35d80767, 0xaafb44fe, 0x4565302d, 0x7cc2a45a, 0xe8f39e48, 0x93ea7df0, 0x77d0ddd1, 0x39a79477, 0xad20031c, 0xa3a39481, 0x776670a8, 0x7acffba3, 0xa2758c9a, 0x967b93e6, 0xeab937bc, 0x0fe322ff, 0x9116797d, 0x9a0400f6, 0xdf6130db, 0x7fe8b8cc, 0xa7e4628c, 0x0958d07f, 0xdb906baf, 0xd1e2a746, 0x3049e971, 0x0c7f9310, 0x90c06166, 0x95518f70, 0x060d5ff9, 0x9487976b, 0xa967f511, 0xeb6f2fa7, 0x9b64b594, 0x44b32836, 0x48ccbb26, 0xab2d5ce5, 0x472f99d9, 0x7833ff2e, 0x34b8b205, 0xacf61b07, 0x40427342, 0xdc4b2c4d, 0xe5ecb83a, 0x43dec2ad, 0xecb46845, 0x971b2684, 0x0591ee16, 0x9c095f0f, 0x0da98b0b, 0x732186a5, 0xdcfd8134, 0xe11de34e, 0x7f5e15b5, 0x088ec864, 0xd2c8bbd0, 0xa684d7ee, 0x02fc048d, 0x039cb1ef, 0x79534a4c, 0xef28d9aa, 0xd034bf5d, 0x744c6c3e, 0x79e5e735, 0xaf6aaae8, 0x4b500ac9, 0x0ba4d4f2, 0x4d5d5530, 0xe9932b2a, 0xd27e16a9, 0xaebcb2f3, 0x9cbff276, 0xd5a5514b +}, +{ +0x010d42e5, 0x58553af8, 0x2ac125b8, 0xf49d6cb6, 0x99f11d29, 0x1c738ae9, 0x699a63a2, 0x47ad5427, 0x6ee795a9, 0x224b51ab, 0xe8eee65f, 0x6c61337a, 0x27b00173, 0xeb650269, 0x88f3b30b, 0x0670b4ee, 0xd55dd92b, 0xe169d0a9, 0x6a118794, 0x36b2af51, 0x35394b67, 0x96069f31, 0xb23d7a74, 0xed15b687, 0x8a7515d8, 0x1b0e7ce2, 0x8d08e3d3, 0x6396b162, 0x98fc5fcc, 0xd1abcb16, 0xbe411c5a, 0xb0bbdca7, 0xd82cfde0, 0x9b77bbfa, 0x5ad39c2b, 0xc45f7709, 0x8b78573d, 0x17721acc, 0x64eb4769, 0x9c0a4df1, 0xdcdaefdd, 0xef931054, 0x848fd525, 0x93fdcfe9, 0x7b1329b6, 0x2dbcd3b3, 0x3db33f74, 0xd921bf05, 0x3244bd6c, 0x37bfedb4, 0x8f8e4500, 0x3349ff89, 0xde5c490e, 0x7a1e6b53, 0xc1a427d1, 0x3e38db42, 0x188598d4, 0xb44dce9a, 0x495794da, 0x56affa05, 0x138408f1, 0xf3e09abd, 0xa23296b3, 0x2536a7a0, 0x948039e2, 0xabb5a045, 0x74e4abae, 0x79958f65, 0xadc514ab, 0xb1b69e42, 0x00000000, 0x76620d7d, 0xa442225d, 0x0efac0fd, 0x89fef1ee, 0xc3228102, 0x30c21bbf, 0x485ad63f, 0xdba719d6, 0x9d070f14, 0x2847836b, 0xbbba4c82, 0xa83e4473, 0xa9330696, 0x05fb50d8, 0xcdd841ff, 0xcba8f511, 0xf9ec487d, 0x917b693a, 0x088a7413, 0x3bc38b9a, 0xb6cb6849, 0x7c6edfbd, 0xbcc7ba89, 0xcaa5b7f4, 0x55241e33, 0x100fecc7, 0xbf4c5ebf, 0x4cacc402, 0xae4ef09d, 0x8c05a136, 0x5958781d, 0x51d20c0e, 0x92f08d0c, 0x0c7c662e, 0x5bdedece, 0x04f6123d, 0x41dde0c9, 0xfa67ac4b, 0x0ff78218, 0x958d7b07, 0x452bf2f4, 0xa1b97285, 0xdf510beb, 0x68972147, 0x6760a35f, 0x601d5554, 0x57a2b8e0, 0x5ca328c5, 0xd0a689f3, 0x5dae6a20, 0xc7d4933f, 0x9e8ceb22, 0x7d639d58, 0x0b019025, 0xf1663c6e, 0x21c0b59d, 0x666de1ba, 0xb5408c7f, 0x611017b1, 0x31cf595a, 0xe9e3a4ba, 0xc55235ec, 0xec18f462, 0xfe91be76, 0x3f3599a7, 0x1ef52c3a, 0x2346134e, 0x243be545, 0x4426b011, 0xfb6aeeae, 0x860973f6, 0x711ffb76, 0x87043113, 0xf2edd858, 0x4adc70ec, 0xdaaa5b33, 0x776f4f98, 0xe2e2349f, 0x5f28ccf3, 0xfc1718a5, 0xa7c9c66b, 0x4e2a62d1, 0xd32d6dc5, 0x098736f6, 0x39452d49, 0xe7196447, 0xd2202f20, 0xb7c62aac, 0x167f5829, 0xb3303891, 0x3acec97f, 0x2f3a7560, 0xacc8564e, 0x83f2232e, 0xb831a8b4, 0xe3ef767a, 0x4bd13209, 0x9f81a9c7, 0x3cbe7d91, 0xd7db7ff8, 0xd4509bce, 0x9a7af91f, 0xf7168880, 0x7fe53b8b, 0x0d7124cb, 0x54295cd6, 0xaab8e2a0, 0x1ff86edf, 0x0286a6d3, 0xf8e10a98, 0xb93cea51, 0x6d6c719f, 0xf5902e53, 0xe064924c, 0x6b1cc571, 0x73995da5, 0xccd5031a, 0x4da186e7, 0x90762bdf, 0xf61bca65, 0xe4928071, 0x858297c0, 0xf06b7e8b, 0x5e258e16, 0x7ee8796e, 0xc92e53c2, 0xe61426a2, 0xff9cfc93, 0x6fead74c, 0x970bddd4, 0xbdcaf86c, 0x82ff61cb, 0x4f272034, 0x14f9fefa, 0xc22fc3e7, 0x26bd4396, 0xa0b43060, 0x5354aadd, 0x038be436, 0x2e373785, 0xc6d9d1da, 0x50df4eeb, 0x1d7ec80c, 0xce53a5c9, 0xea68408c, 0x75e9e94b, 0x2bcc675d, 0x1988da31, 0xc8231127, 0x2cb19156, 0xee9e52b1, 0x425604ff, 0xa33fd456, 0x0a0cd2c0, 0x5259e838, 0x7012b993, 0x1102ae22, 0x629bf387, 0x7898cd80, 0x38486fac, 0x8e8307e5, 0xa54f60b8, 0xd6d63d1d, 0x817485fd, 0xa6c4848e, 0x8079c718, 0x34340982, 0x1a033e07, 0xaf43b278, 0xc0a96534, 0x65e6058c, 0x435b461a, 0xbab70e67, 0x294ac18e, 0x20cdf778, 0xe59fc294, 0xddd7ad38, 0x12894a14, 0x077df60b, 0x40d0a22c, 0xcf5ee72c, 0x15f4bc1f, 0x72941f40, 0x46a016c2, 0xfd1a5a40 +}, +{ +0x96893a61, 0x2591358f, 0x077c88d8, 0x196ea214, 0xedfcd49c, 0xe9a5746a, 0x15887d12, 0x889b10ad, 0x478a7966, 0x5ee4db72, 0x76572d12, 0x94680ea6, 0x7572053c, 0xeed9fcb2, 0x5abd7b84, 0xf874a98e, 0xa95385d4, 0xe7a29fab, 0x720e8de4, 0x3fdabfb5, 0x4132ed57, 0xa69072fc, 0x08bf7ff0, 0xd3e277c0, 0xdc2180e8, 0xced57522, 0xae2f0d0c, 0x3a4703aa, 0x1fd63625, 0xf673424f, 0xe0de1773, 0x2fcf7eb8, 0xa7546e15, 0x4aa8ba89, 0xf9b0b567, 0x3019489d, 0xa1ecfa24, 0x9314867e, 0x2d2e4a7f, 0x74b619d5, 0xc66a0ad2, 0xe487b785, 0xf10fca97, 0x2329a1be, 0xdde59c01, 0x3584f482, 0xabb2b113, 0x779331fb, 0x7994da3a, 0xdec0b42f, 0x059dbc1f, 0x82c55b9a, 0x9ff25978, 0xe8616883, 0x498d92a7, 0xe543ab6c, 0x585c4f43, 0x24552966, 0xc48b3e15, 0xa5b55ad2, 0xfc2d0978, 0xd878201e, 0x1a4b8a3a, 0x8fe79875, 0x9cd77156, 0x3cff979b, 0xafeb11e5, 0x06b89431, 0x2977ea89, 0x2cea5696, 0xbcdbf8c6, 0x40f6f1be, 0xb1f93b29, 0xd9bc3cf7, 0x9031ae50, 0xd67fcbdf, 0xc54f22fc, 0xf22ae2b9, 0xfb5181a0, 0x22edbd57, 0xd2266b29, 0x7c096625, 0x974d2688, 0x31dd5474, 0x4c102eb8, 0x2a52c2a7, 0xf4927688, 0x0459a0f6, 0x1cf31e0b, 0x621b4ce9, 0xcdf05d0c, 0xa028e6cd, 0x176949d5, 0x994acd49, 0x51272c5a, 0x097b6319, 0xc9a9fdfa, 0x9e364591, 0x64a3d8d8, 0x557e8cac, 0x200c8990, 0xa471463b, 0x6efd93ef, 0x613e64c7, 0x28b3f660, 0xe6668342, 0xd55ae3f1, 0x8e23849c, 0xa2c9d20a, 0x1e122acc, 0x38a6376d, 0x869cfb6c, 0x50e330b3, 0x6b602ff0, 0x1b8f96d3, 0x4f350696, 0xfde91591, 0x80246f5d, 0x39622b84, 0x12f4f5ca, 0xda9914d9, 0x7b75eefd, 0xb8825830, 0xdf04a8c6, 0x3d3b8b72, 0x8cc2b05b, 0xb94644d9, 0xef1de05b, 0xfecc3dbf, 0x333c60b3, 0xc3f7b6cd, 0xc233aa24, 0x6786f0f6, 0x02e134c7, 0x7ee852e2, 0xbd1fe42f, 0x36a1dcac, 0x27700148, 0x83014773, 0x895f0c44, 0xf0cbd67e, 0xf7b75ea6, 0xaa76adfa, 0xd1034307, 0x70efb923, 0x43d3d990, 0xe3fb3f5d, 0x712ba5ca, 0xb741af18, 0x8bbe3883, 0x579fb86b, 0x81e073b4, 0x6567c431, 0x0fc3f728, 0x01c41ce9, 0x26b41da1, 0xff082156, 0x54ba9045, 0x4ef11a7f, 0xb03d27c0, 0x6c1ca728, 0x2b96de4e, 0x7dcd7acc, 0x4217c579, 0x53c6189d, 0x44af5148, 0x0a5e4b37, 0x3765c045, 0xa30dcee3, 0x565ba482, 0x144c61fb, 0x00000000, 0xba636cf7, 0x6f398f06, 0xea805c44, 0x456b4da1, 0x0ce6df06, 0xfa959d49, 0x3440e86b, 0x18aabefd, 0xbffed0e8, 0x7f2c4e0b, 0xe23f23b4, 0x684507de, 0x599853aa, 0x1015c10d, 0xcf1169cb, 0xb5a09bdf, 0x4dd43251, 0x63df5000, 0xeb4440ad, 0x464e658f, 0x73ca910d, 0xbba7701e, 0x1330e923, 0x847dcfab, 0xd49eff18, 0x0325282e, 0x2e0b6251, 0x988ed1a0, 0xb685b3f1, 0x6642ec1f, 0xd0c75fee, 0xb2dc1307, 0x91f5b2b9, 0xbe3acc01, 0x4b6ca660, 0xca8cd5d4, 0x21c89579, 0x0b9a57de, 0xcc3441e5, 0xa897993d, 0xb3180fee, 0x48498e4e, 0xc86de113, 0xc116820a, 0x16ad553c, 0x52020474, 0x7850c6d3, 0x5b79676d, 0x6aa43319, 0x7ab1f214, 0xd7bbd736, 0xdb5d0830, 0x69811b37, 0x9d136dbf, 0xec38c875, 0x9a6fe567, 0x8d06acb2, 0x5c05efb5, 0x0d22c3ef, 0x95ac124f, 0xf5566a61, 0xc0d29ee3, 0x92d09a97, 0x1d3702e2, 0x9babf98e, 0xad0a2522, 0x60fa782e, 0x32f87c5a, 0xacce39cb, 0x6dd8bbc1, 0x0e07ebc1, 0x5dc1f35c, 0xb4648736, 0xcb48c93d, 0xf3eefe50, 0x8a7a246a, 0x3e1ea35c, 0x3b831f43, 0x85b9d342, 0x5f20c79b, 0x8758e785, 0x11d1dde4, 0xc7ae163b, 0xe11a0b9a +}, +{ +0x3da21ebd, 0x398a3cbf, 0x1e9997e8, 0x45a70da7, 0x3ed88303, 0x037a9dbe, 0xa8478854, 0x445eb3a7, 0x6037854e, 0x9ebae690, 0xd99ec889, 0xf5d213a7, 0xf379121b, 0x51985436, 0x7805131a, 0xa0626593, 0x10177b93, 0x5c6c25f3, 0x584407f1, 0x1de30a56, 0xad961456, 0x246936e9, 0xfdf7fe60, 0xdae45537, 0x04282202, 0xf1fa31a5, 0xec193bf3, 0x62b4a6f0, 0x3b091f01, 0x259088e9, 0x1ab1b5ea, 0xede085f3, 0x7eae12a6, 0x19cb2854, 0x52e2c988, 0xd71024f2, 0xfe8d63de, 0xddb6ea8b, 0x3587f37a, 0xc5847cdf, 0xb0751e00, 0x00000000, 0x4d82e060, 0xa9be3654, 0xaeec89e8, 0xc1ac5edd, 0xdb1deb37, 0x1294582d, 0x9dc07b2e, 0x92b72955, 0x22c23755, 0x868870c4, 0x143f5991, 0xcaf32ea4, 0x47242e19, 0x3af0a101, 0x1f6029e8, 0xb9a94dc7, 0xcb0a90a4, 0x2864f92c, 0xaac4abea, 0x81dacf78, 0x7b7f8ea4, 0x30566f78, 0x68126889, 0xb850f3c7, 0x18329654, 0xdf35c935, 0x4b29e1dc, 0xb2f63dbe, 0xcda19118, 0x407691a5, 0x55b07634, 0x61ce3b4e, 0xf9dfdc62, 0xac6faa56, 0xa730da2f, 0x8359ecc6, 0x0c0dcfc5, 0x430c0c1b, 0x5f16b84d, 0xb727a1bc, 0x299d472c, 0xfaa541dc, 0xc7075f61, 0x79fcad1a, 0x65e6194c, 0xe7464b8a, 0xe297d788, 0x8f542303, 0xf42bada7, 0x31afd178, 0x8dd700bd, 0xaf1537e8, 0x8ead9d03, 0xa6c9642f, 0x72a3dd63, 0xf6a88e19, 0xcedb0ca6, 0x2ecff890, 0x26ea1557, 0x941c28e9, 0x06ab01bc, 0x5733558a, 0x4c7b5e60, 0x0e8eec7b, 0xe43cd634, 0x7dd48f18, 0x7020fedd, 0x418f2fa5, 0xf280ac1b, 0x2b1e6492, 0x669c84f2, 0x531b7788, 0x2f364690, 0x56caeb8a, 0x387382bf, 0xdecc7735, 0xbd816fc5, 0x8771cec4, 0xbc78d1c5, 0x1745c42f, 0x634d18f0, 0xff74ddde, 0xa5b3f991, 0x5449c834, 0xf8266262, 0x2c4cdb2e, 0xd8677689, 0x969f0b57, 0xd46ab94c, 0xb18ca000, 0xb45d3c02, 0x9a92c492, 0x768bff61, 0xee9a184d, 0x840b537a, 0x90340aeb, 0x85f2ed7a, 0x136de62d, 0x8b7c0101, 0xc2d6c363, 0xc47dc2df, 0x36fd6ec4, 0x1c1ab456, 0x67653af2, 0xb30f83be, 0x88069cbf, 0xbad3d079, 0x15c6e791, 0x59bdb9f1, 0xd1bb254e, 0x6b68f537, 0xfb5cffdc, 0x77724161, 0x1b480bea, 0x5061ea36, 0x4f01c3de, 0x4ad05fdc, 0xa44a4791, 0xc6fee161, 0x05d19c02, 0xd593074c, 0xa318f82d, 0x0b5f7079, 0xc055e0dd, 0x09dc53c7, 0x48537c62, 0x7c2d3118, 0x6dc3f48b, 0xa19bdb93, 0xc8700d1a, 0xf7513019, 0x80237178, 0x735a6363, 0x99e8592c, 0x9c39c52e, 0x641fa74c, 0xe6bff58a, 0x332cf2c6, 0xe36e6988, 0xcc582f18, 0x6a914b37, 0xeab23a4f, 0xe5c56834, 0x91cdb4eb, 0xcf22b2a6, 0xb5a48202, 0xd6e99af2, 0x42f5b21b, 0x5ac7244f, 0xef63a64d, 0x6f40d735, 0xdc4f548b, 0x2ae7da92, 0x2713ab57, 0x0752bfbc, 0x5d959bf3, 0x934e9755, 0x0f77527b, 0x0825edc7, 0x89ff22bf, 0x21b8aaeb, 0xeb4b844f, 0x82a052c6, 0x69ebd689, 0xe1ed4a36, 0x3c5ba0bd, 0xd0429b4e, 0x01f9be00, 0x11eec593, 0x7a8630a4, 0xe014f436, 0x9811e72c, 0x7f57aca6, 0xd33806f0, 0x5b3e9a4f, 0x0df471c5, 0x0aa6ce79, 0x347e4d7a, 0x71d940dd, 0xbefbf27b, 0xf0038fa5, 0xb6de1fbc, 0xe83119f1, 0xe9c8a7f1, 0xc32f7d63, 0x6eb96935, 0x16bc7a2f, 0x7408dcdf, 0x2db5652e, 0x95e596e9, 0xc989b31a, 0x46dd9019, 0x9766b557, 0x8c2ebebd, 0xbf024c7b, 0xfc0e4060, 0x49aac262, 0x4ef87dde, 0xd2c1b8f0, 0x3f213d03, 0x75f162df, 0x8a85bf01, 0xbb2a6e79, 0x6c3a4a8b, 0x5eef064d, 0x204114eb, 0x9f435890, 0x3704d0c4, 0xab3d15ea, 0xa2e1462d, 0x9b6b7a92, 0x32d54cc6, 0x233b8955, 0x028323be +} +} +}; +unsigned int mixBijOut[10][16][256] = +{ +{ +{ +0x00000000, 0x8f5a6cca, 0xd56917f9, 0x5a337b33, 0x31628b1f, 0xbe38e7d5, 0xe40b9ce6, 0x6b51f02c, 0x471f5922, 0xc84535e8, 0x92764edb, 0x1d2c2211, 0x767dd23d, 0xf927bef7, 0xa314c5c4, 0x2c4ea90e, 0xe3d2d8fe, 0x6c88b434, 0x36bbcf07, 0xb9e1a3cd, 0xd2b053e1, 0x5dea3f2b, 0x07d94418, 0x888328d2, 0xa4cd81dc, 0x2b97ed16, 0x71a49625, 0xfefefaef, 0x95af0ac3, 0x1af56609, 0x40c61d3a, 0xcf9c71f0, 0x75afa14f, 0xfaf5cd85, 0xa0c6b6b6, 0x2f9cda7c, 0x44cd2a50, 0xcb97469a, 0x91a43da9, 0x1efe5163, 0x32b0f86d, 0xbdea94a7, 0xe7d9ef94, 0x6883835e, 0x03d27372, 0x8c881fb8, 0xd6bb648b, 0x59e10841, 0x967d79b1, 0x1927157b, 0x43146e48, 0xcc4e0282, 0xa71ff2ae, 0x28459e64, 0x7276e557, 0xfd2c899d, 0xd1622093, 0x5e384c59, 0x040b376a, 0x8b515ba0, 0xe000ab8c, 0x6f5ac746, 0x3569bc75, 0xba33d0bf, 0x180eeab2, 0x97548678, 0xcd67fd4b, 0x423d9181, 0x296c61ad, 0xa6360d67, 0xfc057654, 0x735f1a9e, 0x5f11b390, 0xd04bdf5a, 0x8a78a469, 0x0522c8a3, 0x6e73388f, 0xe1295445, 0xbb1a2f76, 0x344043bc, 0xfbdc324c, 0x74865e86, 0x2eb525b5, 0xa1ef497f, 0xcabeb953, 0x45e4d599, 0x1fd7aeaa, 0x908dc260, 0xbcc36b6e, 0x339907a4, 0x69aa7c97, 0xe6f0105d, 0x8da1e071, 0x02fb8cbb, 0x58c8f788, 0xd7929b42, 0x6da14bfd, 0xe2fb2737, 0xb8c85c04, 0x379230ce, 0x5cc3c0e2, 0xd399ac28, 0x89aad71b, 0x06f0bbd1, 0x2abe12df, 0xa5e47e15, 0xffd70526, 0x708d69ec, 0x1bdc99c0, 0x9486f50a, 0xceb58e39, 0x41efe2f3, 0x8e739303, 0x0129ffc9, 0x5b1a84fa, 0xd440e830, 0xbf11181c, 0x304b74d6, 0x6a780fe5, 0xe522632f, 0xc96cca21, 0x4636a6eb, 0x1c05ddd8, 0x935fb112, 0xf80e413e, 0x77542df4, 0x2d6756c7, 0xa23d3a0d, 0x547134d1, 0xdb2b581b, 0x81182328, 0x0e424fe2, 0x6513bfce, 0xea49d304, 0xb07aa837, 0x3f20c4fd, 0x136e6df3, 0x9c340139, 0xc6077a0a, 0x495d16c0, 0x220ce6ec, 0xad568a26, 0xf765f115, 0x783f9ddf, 0xb7a3ec2f, 0x38f980e5, 0x62cafbd6, 0xed90971c, 0x86c16730, 0x099b0bfa, 0x53a870c9, 0xdcf21c03, 0xf0bcb50d, 0x7fe6d9c7, 0x25d5a2f4, 0xaa8fce3e, 0xc1de3e12, 0x4e8452d8, 0x14b729eb, 0x9bed4521, 0x21de959e, 0xae84f954, 0xf4b78267, 0x7bedeead, 0x10bc1e81, 0x9fe6724b, 0xc5d50978, 0x4a8f65b2, 0x66c1ccbc, 0xe99ba076, 0xb3a8db45, 0x3cf2b78f, 0x57a347a3, 0xd8f92b69, 0x82ca505a, 0x0d903c90, 0xc20c4d60, 0x4d5621aa, 0x17655a99, 0x983f3653, 0xf36ec67f, 0x7c34aab5, 0x2607d186, 0xa95dbd4c, 0x85131442, 0x0a497888, 0x507a03bb, 0xdf206f71, 0xb4719f5d, 0x3b2bf397, 0x611888a4, 0xee42e46e, 0x4c7fde63, 0xc325b2a9, 0x9916c99a, 0x164ca550, 0x7d1d557c, 0xf24739b6, 0xa8744285, 0x272e2e4f, 0x0b608741, 0x843aeb8b, 0xde0990b8, 0x5153fc72, 0x3a020c5e, 0xb5586094, 0xef6b1ba7, 0x6031776d, 0xafad069d, 0x20f76a57, 0x7ac41164, 0xf59e7dae, 0x9ecf8d82, 0x1195e148, 0x4ba69a7b, 0xc4fcf6b1, 0xe8b25fbf, 0x67e83375, 0x3ddb4846, 0xb281248c, 0xd9d0d4a0, 0x568ab86a, 0x0cb9c359, 0x83e3af93, 0x39d07f2c, 0xb68a13e6, 0xecb968d5, 0x63e3041f, 0x08b2f433, 0x87e898f9, 0xdddbe3ca, 0x52818f00, 0x7ecf260e, 0xf1954ac4, 0xaba631f7, 0x24fc5d3d, 0x4fadad11, 0xc0f7c1db, 0x9ac4bae8, 0x159ed622, 0xda02a7d2, 0x5558cb18, 0x0f6bb02b, 0x8031dce1, 0xeb602ccd, 0x643a4007, 0x3e093b34, 0xb15357fe, 0x9d1dfef0, 0x1247923a, 0x4874e909, 0xc72e85c3, 0xac7f75ef, 0x23251925, 0x79166216, 0xf64c0edc +}, +{ +0x00000000, 0xd6917328, 0xca6fd408, 0x1cfea720, 0xdf0f02e7, 0x099e71cf, 0x1560d6ef, 0xc3f1a5c7, 0x241ef2bd, 0xf28f8195, 0xee7126b5, 0x38e0559d, 0xfb11f05a, 0x2d808372, 0x317e2452, 0xe7ef577a, 0xaf45e2f1, 0x79d491d9, 0x652a36f9, 0xb3bb45d1, 0x704ae016, 0xa6db933e, 0xba25341e, 0x6cb44736, 0x8b5b104c, 0x5dca6364, 0x4134c444, 0x97a5b76c, 0x545412ab, 0x82c56183, 0x9e3bc6a3, 0x48aab58b, 0x425c568e, 0x94cd25a6, 0x88338286, 0x5ea2f1ae, 0x9d535469, 0x4bc22741, 0x573c8061, 0x81adf349, 0x6642a433, 0xb0d3d71b, 0xac2d703b, 0x7abc0313, 0xb94da6d4, 0x6fdcd5fc, 0x732272dc, 0xa5b301f4, 0xed19b47f, 0x3b88c757, 0x27766077, 0xf1e7135f, 0x3216b698, 0xe487c5b0, 0xf8796290, 0x2ee811b8, 0xc90746c2, 0x1f9635ea, 0x036892ca, 0xd5f9e1e2, 0x16084425, 0xc099370d, 0xdc67902d, 0x0af6e305, 0x9c49b8ca, 0x4ad8cbe2, 0x56266cc2, 0x80b71fea, 0x4346ba2d, 0x95d7c905, 0x89296e25, 0x5fb81d0d, 0xb8574a77, 0x6ec6395f, 0x72389e7f, 0xa4a9ed57, 0x67584890, 0xb1c93bb8, 0xad379c98, 0x7ba6efb0, 0x330c5a3b, 0xe59d2913, 0xf9638e33, 0x2ff2fd1b, 0xec0358dc, 0x3a922bf4, 0x266c8cd4, 0xf0fdfffc, 0x1712a886, 0xc183dbae, 0xdd7d7c8e, 0x0bec0fa6, 0xc81daa61, 0x1e8cd949, 0x02727e69, 0xd4e30d41, 0xde15ee44, 0x08849d6c, 0x147a3a4c, 0xc2eb4964, 0x011aeca3, 0xd78b9f8b, 0xcb7538ab, 0x1de44b83, 0xfa0b1cf9, 0x2c9a6fd1, 0x3064c8f1, 0xe6f5bbd9, 0x25041e1e, 0xf3956d36, 0xef6bca16, 0x39fab93e, 0x71500cb5, 0xa7c17f9d, 0xbb3fd8bd, 0x6daeab95, 0xae5f0e52, 0x78ce7d7a, 0x6430da5a, 0xb2a1a972, 0x554efe08, 0x83df8d20, 0x9f212a00, 0x49b05928, 0x8a41fcef, 0x5cd08fc7, 0x402e28e7, 0x96bf5bcf, 0x7bd49a39, 0xad45e911, 0xb1bb4e31, 0x672a3d19, 0xa4db98de, 0x724aebf6, 0x6eb44cd6, 0xb8253ffe, 0x5fca6884, 0x895b1bac, 0x95a5bc8c, 0x4334cfa4, 0x80c56a63, 0x5654194b, 0x4aaabe6b, 0x9c3bcd43, 0xd49178c8, 0x02000be0, 0x1efeacc0, 0xc86fdfe8, 0x0b9e7a2f, 0xdd0f0907, 0xc1f1ae27, 0x1760dd0f, 0xf08f8a75, 0x261ef95d, 0x3ae05e7d, 0xec712d55, 0x2f808892, 0xf911fbba, 0xe5ef5c9a, 0x337e2fb2, 0x3988ccb7, 0xef19bf9f, 0xf3e718bf, 0x25766b97, 0xe687ce50, 0x3016bd78, 0x2ce81a58, 0xfa796970, 0x1d963e0a, 0xcb074d22, 0xd7f9ea02, 0x0168992a, 0xc2993ced, 0x14084fc5, 0x08f6e8e5, 0xde679bcd, 0x96cd2e46, 0x405c5d6e, 0x5ca2fa4e, 0x8a338966, 0x49c22ca1, 0x9f535f89, 0x83adf8a9, 0x553c8b81, 0xb2d3dcfb, 0x6442afd3, 0x78bc08f3, 0xae2d7bdb, 0x6ddcde1c, 0xbb4dad34, 0xa7b30a14, 0x7122793c, 0xe79d22f3, 0x310c51db, 0x2df2f6fb, 0xfb6385d3, 0x38922014, 0xee03533c, 0xf2fdf41c, 0x246c8734, 0xc383d04e, 0x1512a366, 0x09ec0446, 0xdf7d776e, 0x1c8cd2a9, 0xca1da181, 0xd6e306a1, 0x00727589, 0x48d8c002, 0x9e49b32a, 0x82b7140a, 0x54266722, 0x97d7c2e5, 0x4146b1cd, 0x5db816ed, 0x8b2965c5, 0x6cc632bf, 0xba574197, 0xa6a9e6b7, 0x7038959f, 0xb3c93058, 0x65584370, 0x79a6e450, 0xaf379778, 0xa5c1747d, 0x73500755, 0x6faea075, 0xb93fd35d, 0x7ace769a, 0xac5f05b2, 0xb0a1a292, 0x6630d1ba, 0x81df86c0, 0x574ef5e8, 0x4bb052c8, 0x9d2121e0, 0x5ed08427, 0x8841f70f, 0x94bf502f, 0x422e2307, 0x0a84968c, 0xdc15e5a4, 0xc0eb4284, 0x167a31ac, 0xd58b946b, 0x031ae743, 0x1fe44063, 0xc975334b, 0x2e9a6431, 0xf80b1719, 0xe4f5b039, 0x3264c311, 0xf19566d6, 0x270415fe, 0x3bfab2de, 0xed6bc1f6 +}, +{ +0x00000000, 0x08871a42, 0x30faf06c, 0x387dea2e, 0x59bf2925, 0x51383367, 0x6945d949, 0x61c2c30b, 0x1c30b6fd, 0x14b7acbf, 0x2cca4691, 0x244d5cd3, 0x458f9fd8, 0x4d08859a, 0x75756fb4, 0x7df275f6, 0xa0a09e0b, 0xa8278449, 0x905a6e67, 0x98dd7425, 0xf91fb72e, 0xf198ad6c, 0xc9e54742, 0xc1625d00, 0xbc9028f6, 0xb41732b4, 0x8c6ad89a, 0x84edc2d8, 0xe52f01d3, 0xeda81b91, 0xd5d5f1bf, 0xdd52ebfd, 0x22fdf4d8, 0x2a7aee9a, 0x120704b4, 0x1a801ef6, 0x7b42ddfd, 0x73c5c7bf, 0x4bb82d91, 0x433f37d3, 0x3ecd4225, 0x364a5867, 0x0e37b249, 0x06b0a80b, 0x67726b00, 0x6ff57142, 0x57889b6c, 0x5f0f812e, 0x825d6ad3, 0x8ada7091, 0xb2a79abf, 0xba2080fd, 0xdbe243f6, 0xd36559b4, 0xeb18b39a, 0xe39fa9d8, 0x9e6ddc2e, 0x96eac66c, 0xae972c42, 0xa6103600, 0xc7d2f50b, 0xcf55ef49, 0xf7280567, 0xffaf1f25, 0x6b7f79be, 0x63f863fc, 0x5b8589d2, 0x53029390, 0x32c0509b, 0x3a474ad9, 0x023aa0f7, 0x0abdbab5, 0x774fcf43, 0x7fc8d501, 0x47b53f2f, 0x4f32256d, 0x2ef0e666, 0x2677fc24, 0x1e0a160a, 0x168d0c48, 0xcbdfe7b5, 0xc358fdf7, 0xfb2517d9, 0xf3a20d9b, 0x9260ce90, 0x9ae7d4d2, 0xa29a3efc, 0xaa1d24be, 0xd7ef5148, 0xdf684b0a, 0xe715a124, 0xef92bb66, 0x8e50786d, 0x86d7622f, 0xbeaa8801, 0xb62d9243, 0x49828d66, 0x41059724, 0x79787d0a, 0x71ff6748, 0x103da443, 0x18babe01, 0x20c7542f, 0x28404e6d, 0x55b23b9b, 0x5d3521d9, 0x6548cbf7, 0x6dcfd1b5, 0x0c0d12be, 0x048a08fc, 0x3cf7e2d2, 0x3470f890, 0xe922136d, 0xe1a5092f, 0xd9d8e301, 0xd15ff943, 0xb09d3a48, 0xb81a200a, 0x8067ca24, 0x88e0d066, 0xf512a590, 0xfd95bfd2, 0xc5e855fc, 0xcd6f4fbe, 0xacad8cb5, 0xa42a96f7, 0x9c577cd9, 0x94d0669b, 0xf6262765, 0xfea13d27, 0xc6dcd709, 0xce5bcd4b, 0xaf990e40, 0xa71e1402, 0x9f63fe2c, 0x97e4e46e, 0xea169198, 0xe2918bda, 0xdaec61f4, 0xd26b7bb6, 0xb3a9b8bd, 0xbb2ea2ff, 0x835348d1, 0x8bd45293, 0x5686b96e, 0x5e01a32c, 0x667c4902, 0x6efb5340, 0x0f39904b, 0x07be8a09, 0x3fc36027, 0x37447a65, 0x4ab60f93, 0x423115d1, 0x7a4cffff, 0x72cbe5bd, 0x130926b6, 0x1b8e3cf4, 0x23f3d6da, 0x2b74cc98, 0xd4dbd3bd, 0xdc5cc9ff, 0xe42123d1, 0xeca63993, 0x8d64fa98, 0x85e3e0da, 0xbd9e0af4, 0xb51910b6, 0xc8eb6540, 0xc06c7f02, 0xf811952c, 0xf0968f6e, 0x91544c65, 0x99d35627, 0xa1aebc09, 0xa929a64b, 0x747b4db6, 0x7cfc57f4, 0x4481bdda, 0x4c06a798, 0x2dc46493, 0x25437ed1, 0x1d3e94ff, 0x15b98ebd, 0x684bfb4b, 0x60cce109, 0x58b10b27, 0x50361165, 0x31f4d26e, 0x3973c82c, 0x010e2202, 0x09893840, 0x9d595edb, 0x95de4499, 0xada3aeb7, 0xa524b4f5, 0xc4e677fe, 0xcc616dbc, 0xf41c8792, 0xfc9b9dd0, 0x8169e826, 0x89eef264, 0xb193184a, 0xb9140208, 0xd8d6c103, 0xd051db41, 0xe82c316f, 0xe0ab2b2d, 0x3df9c0d0, 0x357eda92, 0x0d0330bc, 0x05842afe, 0x6446e9f5, 0x6cc1f3b7, 0x54bc1999, 0x5c3b03db, 0x21c9762d, 0x294e6c6f, 0x11338641, 0x19b49c03, 0x78765f08, 0x70f1454a, 0x488caf64, 0x400bb526, 0xbfa4aa03, 0xb723b041, 0x8f5e5a6f, 0x87d9402d, 0xe61b8326, 0xee9c9964, 0xd6e1734a, 0xde666908, 0xa3941cfe, 0xab1306bc, 0x936eec92, 0x9be9f6d0, 0xfa2b35db, 0xf2ac2f99, 0xcad1c5b7, 0xc256dff5, 0x1f043408, 0x17832e4a, 0x2ffec464, 0x2779de26, 0x46bb1d2d, 0x4e3c076f, 0x7641ed41, 0x7ec6f703, 0x033482f5, 0x0bb398b7, 0x33ce7299, 0x3b4968db, 0x5a8babd0, 0x520cb192, 0x6a715bbc, 0x62f641fe +}, +{ +0x00000000, 0xe53cfb62, 0x4a2ab0e9, 0xaf164b8b, 0x66a922d7, 0x8395d9b5, 0x2c83923e, 0xc9bf695c, 0x79c1dffe, 0x9cfd249c, 0x33eb6f17, 0xd6d79475, 0x1f68fd29, 0xfa54064b, 0x55424dc0, 0xb07eb6a2, 0x21c08ff8, 0xc4fc749a, 0x6bea3f11, 0x8ed6c473, 0x4769ad2f, 0xa255564d, 0x0d431dc6, 0xe87fe6a4, 0x58015006, 0xbd3dab64, 0x122be0ef, 0xf7171b8d, 0x3ea872d1, 0xdb9489b3, 0x7482c238, 0x91be395a, 0x39628b0e, 0xdc5e706c, 0x73483be7, 0x9674c085, 0x5fcba9d9, 0xbaf752bb, 0x15e11930, 0xf0dde252, 0x40a354f0, 0xa59faf92, 0x0a89e419, 0xefb51f7b, 0x260a7627, 0xc3368d45, 0x6c20c6ce, 0x891c3dac, 0x18a204f6, 0xfd9eff94, 0x5288b41f, 0xb7b44f7d, 0x7e0b2621, 0x9b37dd43, 0x342196c8, 0xd11d6daa, 0x6163db08, 0x845f206a, 0x2b496be1, 0xce759083, 0x07caf9df, 0xe2f602bd, 0x4de04936, 0xa8dcb254, 0x58ef8e88, 0xbdd375ea, 0x12c53e61, 0xf7f9c503, 0x3e46ac5f, 0xdb7a573d, 0x746c1cb6, 0x9150e7d4, 0x212e5176, 0xc412aa14, 0x6b04e19f, 0x8e381afd, 0x478773a1, 0xa2bb88c3, 0x0dadc348, 0xe891382a, 0x792f0170, 0x9c13fa12, 0x3305b199, 0xd6394afb, 0x1f8623a7, 0xfabad8c5, 0x55ac934e, 0xb090682c, 0x00eede8e, 0xe5d225ec, 0x4ac46e67, 0xaff89505, 0x6647fc59, 0x837b073b, 0x2c6d4cb0, 0xc951b7d2, 0x618d0586, 0x84b1fee4, 0x2ba7b56f, 0xce9b4e0d, 0x07242751, 0xe218dc33, 0x4d0e97b8, 0xa8326cda, 0x184cda78, 0xfd70211a, 0x52666a91, 0xb75a91f3, 0x7ee5f8af, 0x9bd903cd, 0x34cf4846, 0xd1f3b324, 0x404d8a7e, 0xa571711c, 0x0a673a97, 0xef5bc1f5, 0x26e4a8a9, 0xc3d853cb, 0x6cce1840, 0x89f2e322, 0x398c5580, 0xdcb0aee2, 0x73a6e569, 0x969a1e0b, 0x5f257757, 0xba198c35, 0x150fc7be, 0xf0333cdc, 0xe1803dc4, 0x04bcc6a6, 0xabaa8d2d, 0x4e96764f, 0x87291f13, 0x6215e471, 0xcd03affa, 0x283f5498, 0x9841e23a, 0x7d7d1958, 0xd26b52d3, 0x3757a9b1, 0xfee8c0ed, 0x1bd43b8f, 0xb4c27004, 0x51fe8b66, 0xc040b23c, 0x257c495e, 0x8a6a02d5, 0x6f56f9b7, 0xa6e990eb, 0x43d56b89, 0xecc32002, 0x09ffdb60, 0xb9816dc2, 0x5cbd96a0, 0xf3abdd2b, 0x16972649, 0xdf284f15, 0x3a14b477, 0x9502fffc, 0x703e049e, 0xd8e2b6ca, 0x3dde4da8, 0x92c80623, 0x77f4fd41, 0xbe4b941d, 0x5b776f7f, 0xf46124f4, 0x115ddf96, 0xa1236934, 0x441f9256, 0xeb09d9dd, 0x0e3522bf, 0xc78a4be3, 0x22b6b081, 0x8da0fb0a, 0x689c0068, 0xf9223932, 0x1c1ec250, 0xb30889db, 0x563472b9, 0x9f8b1be5, 0x7ab7e087, 0xd5a1ab0c, 0x309d506e, 0x80e3e6cc, 0x65df1dae, 0xcac95625, 0x2ff5ad47, 0xe64ac41b, 0x03763f79, 0xac6074f2, 0x495c8f90, 0xb96fb34c, 0x5c53482e, 0xf34503a5, 0x1679f8c7, 0xdfc6919b, 0x3afa6af9, 0x95ec2172, 0x70d0da10, 0xc0ae6cb2, 0x259297d0, 0x8a84dc5b, 0x6fb82739, 0xa6074e65, 0x433bb507, 0xec2dfe8c, 0x091105ee, 0x98af3cb4, 0x7d93c7d6, 0xd2858c5d, 0x37b9773f, 0xfe061e63, 0x1b3ae501, 0xb42cae8a, 0x511055e8, 0xe16ee34a, 0x04521828, 0xab4453a3, 0x4e78a8c1, 0x87c7c19d, 0x62fb3aff, 0xcded7174, 0x28d18a16, 0x800d3842, 0x6531c320, 0xca2788ab, 0x2f1b73c9, 0xe6a41a95, 0x0398e1f7, 0xac8eaa7c, 0x49b2511e, 0xf9cce7bc, 0x1cf01cde, 0xb3e65755, 0x56daac37, 0x9f65c56b, 0x7a593e09, 0xd54f7582, 0x30738ee0, 0xa1cdb7ba, 0x44f14cd8, 0xebe70753, 0x0edbfc31, 0xc764956d, 0x22586e0f, 0x8d4e2584, 0x6872dee6, 0xd80c6844, 0x3d309326, 0x9226d8ad, 0x771a23cf, 0xbea54a93, 0x5b99b1f1, 0xf48ffa7a, 0x11b30118 +}, +{ +0x00000000, 0x6708bd0c, 0x6519cbce, 0x021176c2, 0xa9932f4f, 0xce9b9243, 0xcc8ae481, 0xab82598d, 0xcc859e61, 0xab8d236d, 0xa99c55af, 0xce94e8a3, 0x6516b12e, 0x021e0c22, 0x000f7ae0, 0x6707c7ec, 0x2e0bacef, 0x490311e3, 0x4b126721, 0x2c1ada2d, 0x879883a0, 0xe0903eac, 0xe281486e, 0x8589f562, 0xe28e328e, 0x85868f82, 0x8797f940, 0xe09f444c, 0x4b1d1dc1, 0x2c15a0cd, 0x2e04d60f, 0x490c6b03, 0x2b9090b3, 0x4c982dbf, 0x4e895b7d, 0x2981e671, 0x8203bffc, 0xe50b02f0, 0xe71a7432, 0x8012c93e, 0xe7150ed2, 0x801db3de, 0x820cc51c, 0xe5047810, 0x4e86219d, 0x298e9c91, 0x2b9fea53, 0x4c97575f, 0x059b3c5c, 0x62938150, 0x6082f792, 0x078a4a9e, 0xac081313, 0xcb00ae1f, 0xc911d8dd, 0xae1965d1, 0xc91ea23d, 0xae161f31, 0xac0769f3, 0xcb0fd4ff, 0x608d8d72, 0x0785307e, 0x059446bc, 0x629cfbb0, 0xb63824f4, 0xd13099f8, 0xd321ef3a, 0xb4295236, 0x1fab0bbb, 0x78a3b6b7, 0x7ab2c075, 0x1dba7d79, 0x7abdba95, 0x1db50799, 0x1fa4715b, 0x78accc57, 0xd32e95da, 0xb42628d6, 0xb6375e14, 0xd13fe318, 0x9833881b, 0xff3b3517, 0xfd2a43d5, 0x9a22fed9, 0x31a0a754, 0x56a81a58, 0x54b96c9a, 0x33b1d196, 0x54b6167a, 0x33beab76, 0x31afddb4, 0x56a760b8, 0xfd253935, 0x9a2d8439, 0x983cf2fb, 0xff344ff7, 0x9da8b447, 0xfaa0094b, 0xf8b17f89, 0x9fb9c285, 0x343b9b08, 0x53332604, 0x512250c6, 0x362aedca, 0x512d2a26, 0x3625972a, 0x3434e1e8, 0x533c5ce4, 0xf8be0569, 0x9fb6b865, 0x9da7cea7, 0xfaaf73ab, 0xb3a318a8, 0xd4aba5a4, 0xd6bad366, 0xb1b26e6a, 0x1a3037e7, 0x7d388aeb, 0x7f29fc29, 0x18214125, 0x7f2686c9, 0x182e3bc5, 0x1a3f4d07, 0x7d37f00b, 0xd6b5a986, 0xb1bd148a, 0xb3ac6248, 0xd4a4df44, 0xe167cb45, 0x866f7649, 0x847e008b, 0xe376bd87, 0x48f4e40a, 0x2ffc5906, 0x2ded2fc4, 0x4ae592c8, 0x2de25524, 0x4aeae828, 0x48fb9eea, 0x2ff323e6, 0x84717a6b, 0xe379c767, 0xe168b1a5, 0x86600ca9, 0xcf6c67aa, 0xa864daa6, 0xaa75ac64, 0xcd7d1168, 0x66ff48e5, 0x01f7f5e9, 0x03e6832b, 0x64ee3e27, 0x03e9f9cb, 0x64e144c7, 0x66f03205, 0x01f88f09, 0xaa7ad684, 0xcd726b88, 0xcf631d4a, 0xa86ba046, 0xcaf75bf6, 0xadffe6fa, 0xafee9038, 0xc8e62d34, 0x636474b9, 0x046cc9b5, 0x067dbf77, 0x6175027b, 0x0672c597, 0x617a789b, 0x636b0e59, 0x0463b355, 0xafe1ead8, 0xc8e957d4, 0xcaf82116, 0xadf09c1a, 0xe4fcf719, 0x83f44a15, 0x81e53cd7, 0xe6ed81db, 0x4d6fd856, 0x2a67655a, 0x28761398, 0x4f7eae94, 0x28796978, 0x4f71d474, 0x4d60a2b6, 0x2a681fba, 0x81ea4637, 0xe6e2fb3b, 0xe4f38df9, 0x83fb30f5, 0x575fefb1, 0x305752bd, 0x3246247f, 0x554e9973, 0xfeccc0fe, 0x99c47df2, 0x9bd50b30, 0xfcddb63c, 0x9bda71d0, 0xfcd2ccdc, 0xfec3ba1e, 0x99cb0712, 0x32495e9f, 0x5541e393, 0x57509551, 0x3058285d, 0x7954435e, 0x1e5cfe52, 0x1c4d8890, 0x7b45359c, 0xd0c76c11, 0xb7cfd11d, 0xb5dea7df, 0xd2d61ad3, 0xb5d1dd3f, 0xd2d96033, 0xd0c816f1, 0xb7c0abfd, 0x1c42f270, 0x7b4a4f7c, 0x795b39be, 0x1e5384b2, 0x7ccf7f02, 0x1bc7c20e, 0x19d6b4cc, 0x7ede09c0, 0xd55c504d, 0xb254ed41, 0xb0459b83, 0xd74d268f, 0xb04ae163, 0xd7425c6f, 0xd5532aad, 0xb25b97a1, 0x19d9ce2c, 0x7ed17320, 0x7cc005e2, 0x1bc8b8ee, 0x52c4d3ed, 0x35cc6ee1, 0x37dd1823, 0x50d5a52f, 0xfb57fca2, 0x9c5f41ae, 0x9e4e376c, 0xf9468a60, 0x9e414d8c, 0xf949f080, 0xfb588642, 0x9c503b4e, 0x37d262c3, 0x50dadfcf, 0x52cba90d, 0x35c31401 +}, +{ +0x00000000, 0x4322b012, 0x496cb9dd, 0x0a4e09cf, 0x939d8046, 0xd0bf3054, 0xdaf1399b, 0x99d38989, 0x4e1ba08f, 0x0d39109d, 0x07771952, 0x4455a940, 0xdd8620c9, 0x9ea490db, 0x94ea9914, 0xd7c82906, 0x7cd0b3e8, 0x3ff203fa, 0x35bc0a35, 0x769eba27, 0xef4d33ae, 0xac6f83bc, 0xa6218a73, 0xe5033a61, 0x32cb1367, 0x71e9a375, 0x7ba7aaba, 0x38851aa8, 0xa1569321, 0xe2742333, 0xe83a2afc, 0xab189aee, 0xd97f6135, 0x9a5dd127, 0x9013d8e8, 0xd33168fa, 0x4ae2e173, 0x09c05161, 0x038e58ae, 0x40ace8bc, 0x9764c1ba, 0xd44671a8, 0xde087867, 0x9d2ac875, 0x04f941fc, 0x47dbf1ee, 0x4d95f821, 0x0eb74833, 0xa5afd2dd, 0xe68d62cf, 0xecc36b00, 0xafe1db12, 0x3632529b, 0x7510e289, 0x7f5eeb46, 0x3c7c5b54, 0xebb47252, 0xa896c240, 0xa2d8cb8f, 0xe1fa7b9d, 0x7829f214, 0x3b0b4206, 0x31454bc9, 0x7267fbdb, 0x3557d81a, 0x76756808, 0x7c3b61c7, 0x3f19d1d5, 0xa6ca585c, 0xe5e8e84e, 0xefa6e181, 0xac845193, 0x7b4c7895, 0x386ec887, 0x3220c148, 0x7102715a, 0xe8d1f8d3, 0xabf348c1, 0xa1bd410e, 0xe29ff11c, 0x49876bf2, 0x0aa5dbe0, 0x00ebd22f, 0x43c9623d, 0xda1aebb4, 0x99385ba6, 0x93765269, 0xd054e27b, 0x079ccb7d, 0x44be7b6f, 0x4ef072a0, 0x0dd2c2b2, 0x94014b3b, 0xd723fb29, 0xdd6df2e6, 0x9e4f42f4, 0xec28b92f, 0xaf0a093d, 0xa54400f2, 0xe666b0e0, 0x7fb53969, 0x3c97897b, 0x36d980b4, 0x75fb30a6, 0xa23319a0, 0xe111a9b2, 0xeb5fa07d, 0xa87d106f, 0x31ae99e6, 0x728c29f4, 0x78c2203b, 0x3be09029, 0x90f80ac7, 0xd3dabad5, 0xd994b31a, 0x9ab60308, 0x03658a81, 0x40473a93, 0x4a09335c, 0x092b834e, 0xdee3aa48, 0x9dc11a5a, 0x978f1395, 0xd4ada387, 0x4d7e2a0e, 0x0e5c9a1c, 0x041293d3, 0x473023c1, 0x0c161dbb, 0x4f34ada9, 0x457aa466, 0x06581474, 0x9f8b9dfd, 0xdca92def, 0xd6e72420, 0x95c59432, 0x420dbd34, 0x012f0d26, 0x0b6104e9, 0x4843b4fb, 0xd1903d72, 0x92b28d60, 0x98fc84af, 0xdbde34bd, 0x70c6ae53, 0x33e41e41, 0x39aa178e, 0x7a88a79c, 0xe35b2e15, 0xa0799e07, 0xaa3797c8, 0xe91527da, 0x3edd0edc, 0x7dffbece, 0x77b1b701, 0x34930713, 0xad408e9a, 0xee623e88, 0xe42c3747, 0xa70e8755, 0xd5697c8e, 0x964bcc9c, 0x9c05c553, 0xdf277541, 0x46f4fcc8, 0x05d64cda, 0x0f984515, 0x4cbaf507, 0x9b72dc01, 0xd8506c13, 0xd21e65dc, 0x913cd5ce, 0x08ef5c47, 0x4bcdec55, 0x4183e59a, 0x02a15588, 0xa9b9cf66, 0xea9b7f74, 0xe0d576bb, 0xa3f7c6a9, 0x3a244f20, 0x7906ff32, 0x7348f6fd, 0x306a46ef, 0xe7a26fe9, 0xa480dffb, 0xaeced634, 0xedec6626, 0x743fefaf, 0x371d5fbd, 0x3d535672, 0x7e71e660, 0x3941c5a1, 0x7a6375b3, 0x702d7c7c, 0x330fcc6e, 0xaadc45e7, 0xe9fef5f5, 0xe3b0fc3a, 0xa0924c28, 0x775a652e, 0x3478d53c, 0x3e36dcf3, 0x7d146ce1, 0xe4c7e568, 0xa7e5557a, 0xadab5cb5, 0xee89eca7, 0x45917649, 0x06b3c65b, 0x0cfdcf94, 0x4fdf7f86, 0xd60cf60f, 0x952e461d, 0x9f604fd2, 0xdc42ffc0, 0x0b8ad6c6, 0x48a866d4, 0x42e66f1b, 0x01c4df09, 0x98175680, 0xdb35e692, 0xd17bef5d, 0x92595f4f, 0xe03ea494, 0xa31c1486, 0xa9521d49, 0xea70ad5b, 0x73a324d2, 0x308194c0, 0x3acf9d0f, 0x79ed2d1d, 0xae25041b, 0xed07b409, 0xe749bdc6, 0xa46b0dd4, 0x3db8845d, 0x7e9a344f, 0x74d43d80, 0x37f68d92, 0x9cee177c, 0xdfcca76e, 0xd582aea1, 0x96a01eb3, 0x0f73973a, 0x4c512728, 0x461f2ee7, 0x053d9ef5, 0xd2f5b7f3, 0x91d707e1, 0x9b990e2e, 0xd8bbbe3c, 0x416837b5, 0x024a87a7, 0x08048e68, 0x4b263e7a +}, +{ +0x00000000, 0x06ea2602, 0xadbd90fa, 0xab57b6f8, 0xf7a6f731, 0xf14cd133, 0x5a1b67cb, 0x5cf141c9, 0x84ac0a25, 0x82462c27, 0x29119adf, 0x2ffbbcdd, 0x730afd14, 0x75e0db16, 0xdeb76dee, 0xd85d4bec, 0x5f961108, 0x597c370a, 0xf22b81f2, 0xf4c1a7f0, 0xa830e639, 0xaedac03b, 0x058d76c3, 0x036750c1, 0xdb3a1b2d, 0xddd03d2f, 0x76878bd7, 0x706dadd5, 0x2c9cec1c, 0x2a76ca1e, 0x81217ce6, 0x87cb5ae4, 0x27c9a08d, 0x2123868f, 0x8a743077, 0x8c9e1675, 0xd06f57bc, 0xd68571be, 0x7dd2c746, 0x7b38e144, 0xa365aaa8, 0xa58f8caa, 0x0ed83a52, 0x08321c50, 0x54c35d99, 0x52297b9b, 0xf97ecd63, 0xff94eb61, 0x785fb185, 0x7eb59787, 0xd5e2217f, 0xd308077d, 0x8ff946b4, 0x891360b6, 0x2244d64e, 0x24aef04c, 0xfcf3bba0, 0xfa199da2, 0x514e2b5a, 0x57a40d58, 0x0b554c91, 0x0dbf6a93, 0xa6e8dc6b, 0xa002fa69, 0xa7e4c960, 0xa10eef62, 0x0a59599a, 0x0cb37f98, 0x50423e51, 0x56a81853, 0xfdffaeab, 0xfb1588a9, 0x2348c345, 0x25a2e547, 0x8ef553bf, 0x881f75bd, 0xd4ee3474, 0xd2041276, 0x7953a48e, 0x7fb9828c, 0xf872d868, 0xfe98fe6a, 0x55cf4892, 0x53256e90, 0x0fd42f59, 0x093e095b, 0xa269bfa3, 0xa48399a1, 0x7cded24d, 0x7a34f44f, 0xd16342b7, 0xd78964b5, 0x8b78257c, 0x8d92037e, 0x26c5b586, 0x202f9384, 0x802d69ed, 0x86c74fef, 0x2d90f917, 0x2b7adf15, 0x778b9edc, 0x7161b8de, 0xda360e26, 0xdcdc2824, 0x048163c8, 0x026b45ca, 0xa93cf332, 0xafd6d530, 0xf32794f9, 0xf5cdb2fb, 0x5e9a0403, 0x58702201, 0xdfbb78e5, 0xd9515ee7, 0x7206e81f, 0x74ecce1d, 0x281d8fd4, 0x2ef7a9d6, 0x85a01f2e, 0x834a392c, 0x5b1772c0, 0x5dfd54c2, 0xf6aae23a, 0xf040c438, 0xacb185f1, 0xaa5ba3f3, 0x010c150b, 0x07e63309, 0xb198f24b, 0xb772d449, 0x1c2562b1, 0x1acf44b3, 0x463e057a, 0x40d42378, 0xeb839580, 0xed69b382, 0x3534f86e, 0x33dede6c, 0x98896894, 0x9e634e96, 0xc2920f5f, 0xc478295d, 0x6f2f9fa5, 0x69c5b9a7, 0xee0ee343, 0xe8e4c541, 0x43b373b9, 0x455955bb, 0x19a81472, 0x1f423270, 0xb4158488, 0xb2ffa28a, 0x6aa2e966, 0x6c48cf64, 0xc71f799c, 0xc1f55f9e, 0x9d041e57, 0x9bee3855, 0x30b98ead, 0x3653a8af, 0x965152c6, 0x90bb74c4, 0x3becc23c, 0x3d06e43e, 0x61f7a5f7, 0x671d83f5, 0xcc4a350d, 0xcaa0130f, 0x12fd58e3, 0x14177ee1, 0xbf40c819, 0xb9aaee1b, 0xe55bafd2, 0xe3b189d0, 0x48e63f28, 0x4e0c192a, 0xc9c743ce, 0xcf2d65cc, 0x647ad334, 0x6290f536, 0x3e61b4ff, 0x388b92fd, 0x93dc2405, 0x95360207, 0x4d6b49eb, 0x4b816fe9, 0xe0d6d911, 0xe63cff13, 0xbacdbeda, 0xbc2798d8, 0x17702e20, 0x119a0822, 0x167c3b2b, 0x10961d29, 0xbbc1abd1, 0xbd2b8dd3, 0xe1dacc1a, 0xe730ea18, 0x4c675ce0, 0x4a8d7ae2, 0x92d0310e, 0x943a170c, 0x3f6da1f4, 0x398787f6, 0x6576c63f, 0x639ce03d, 0xc8cb56c5, 0xce2170c7, 0x49ea2a23, 0x4f000c21, 0xe457bad9, 0xe2bd9cdb, 0xbe4cdd12, 0xb8a6fb10, 0x13f14de8, 0x151b6bea, 0xcd462006, 0xcbac0604, 0x60fbb0fc, 0x661196fe, 0x3ae0d737, 0x3c0af135, 0x975d47cd, 0x91b761cf, 0x31b59ba6, 0x375fbda4, 0x9c080b5c, 0x9ae22d5e, 0xc6136c97, 0xc0f94a95, 0x6baefc6d, 0x6d44da6f, 0xb5199183, 0xb3f3b781, 0x18a40179, 0x1e4e277b, 0x42bf66b2, 0x445540b0, 0xef02f648, 0xe9e8d04a, 0x6e238aae, 0x68c9acac, 0xc39e1a54, 0xc5743c56, 0x99857d9f, 0x9f6f5b9d, 0x3438ed65, 0x32d2cb67, 0xea8f808b, 0xec65a689, 0x47321071, 0x41d83673, 0x1d2977ba, 0x1bc351b8, 0xb094e740, 0xb67ec142 +}, +{ +0x00000000, 0xf2c4a9aa, 0x14f26478, 0xe636cdd2, 0x7340460d, 0x8184efa7, 0x67b22275, 0x95768bdf, 0x27d200d0, 0xd516a97a, 0x332064a8, 0xc1e4cd02, 0x549246dd, 0xa656ef77, 0x406022a5, 0xb2a48b0f, 0xf1792404, 0x03bd8dae, 0xe58b407c, 0x174fe9d6, 0x82396209, 0x70fdcba3, 0x96cb0671, 0x640fafdb, 0xd6ab24d4, 0x246f8d7e, 0xc25940ac, 0x309de906, 0xa5eb62d9, 0x572fcb73, 0xb11906a1, 0x43ddaf0b, 0xe56602d4, 0x17a2ab7e, 0xf19466ac, 0x0350cf06, 0x962644d9, 0x64e2ed73, 0x82d420a1, 0x7010890b, 0xc2b40204, 0x3070abae, 0xd646667c, 0x2482cfd6, 0xb1f44409, 0x4330eda3, 0xa5062071, 0x57c289db, 0x141f26d0, 0xe6db8f7a, 0x00ed42a8, 0xf229eb02, 0x675f60dd, 0x959bc977, 0x73ad04a5, 0x8169ad0f, 0x33cd2600, 0xc1098faa, 0x273f4278, 0xd5fbebd2, 0x408d600d, 0xb249c9a7, 0x547f0475, 0xa6bbaddf, 0xc7573237, 0x35939b9d, 0xd3a5564f, 0x2161ffe5, 0xb417743a, 0x46d3dd90, 0xa0e51042, 0x5221b9e8, 0xe08532e7, 0x12419b4d, 0xf477569f, 0x06b3ff35, 0x93c574ea, 0x6101dd40, 0x87371092, 0x75f3b938, 0x362e1633, 0xc4eabf99, 0x22dc724b, 0xd018dbe1, 0x456e503e, 0xb7aaf994, 0x519c3446, 0xa3589dec, 0x11fc16e3, 0xe338bf49, 0x050e729b, 0xf7cadb31, 0x62bc50ee, 0x9078f944, 0x764e3496, 0x848a9d3c, 0x223130e3, 0xd0f59949, 0x36c3549b, 0xc407fd31, 0x517176ee, 0xa3b5df44, 0x45831296, 0xb747bb3c, 0x05e33033, 0xf7279999, 0x1111544b, 0xe3d5fde1, 0x76a3763e, 0x8467df94, 0x62511246, 0x9095bbec, 0xd34814e7, 0x218cbd4d, 0xc7ba709f, 0x357ed935, 0xa00852ea, 0x52ccfb40, 0xb4fa3692, 0x463e9f38, 0xf49a1437, 0x065ebd9d, 0xe068704f, 0x12acd9e5, 0x87da523a, 0x751efb90, 0x93283642, 0x61ec9fe8, 0xb2fb5e47, 0x403ff7ed, 0xa6093a3f, 0x54cd9395, 0xc1bb184a, 0x337fb1e0, 0xd5497c32, 0x278dd598, 0x95295e97, 0x67edf73d, 0x81db3aef, 0x731f9345, 0xe669189a, 0x14adb130, 0xf29b7ce2, 0x005fd548, 0x43827a43, 0xb146d3e9, 0x57701e3b, 0xa5b4b791, 0x30c23c4e, 0xc20695e4, 0x24305836, 0xd6f4f19c, 0x64507a93, 0x9694d339, 0x70a21eeb, 0x8266b741, 0x17103c9e, 0xe5d49534, 0x03e258e6, 0xf126f14c, 0x579d5c93, 0xa559f539, 0x436f38eb, 0xb1ab9141, 0x24dd1a9e, 0xd619b334, 0x302f7ee6, 0xc2ebd74c, 0x704f5c43, 0x828bf5e9, 0x64bd383b, 0x96799191, 0x030f1a4e, 0xf1cbb3e4, 0x17fd7e36, 0xe539d79c, 0xa6e47897, 0x5420d13d, 0xb2161cef, 0x40d2b545, 0xd5a43e9a, 0x27609730, 0xc1565ae2, 0x3392f348, 0x81367847, 0x73f2d1ed, 0x95c41c3f, 0x6700b595, 0xf2763e4a, 0x00b297e0, 0xe6845a32, 0x1440f398, 0x75ac6c70, 0x8768c5da, 0x615e0808, 0x939aa1a2, 0x06ec2a7d, 0xf42883d7, 0x121e4e05, 0xe0dae7af, 0x527e6ca0, 0xa0bac50a, 0x468c08d8, 0xb448a172, 0x213e2aad, 0xd3fa8307, 0x35cc4ed5, 0xc708e77f, 0x84d54874, 0x7611e1de, 0x90272c0c, 0x62e385a6, 0xf7950e79, 0x0551a7d3, 0xe3676a01, 0x11a3c3ab, 0xa30748a4, 0x51c3e10e, 0xb7f52cdc, 0x45318576, 0xd0470ea9, 0x2283a703, 0xc4b56ad1, 0x3671c37b, 0x90ca6ea4, 0x620ec70e, 0x84380adc, 0x76fca376, 0xe38a28a9, 0x114e8103, 0xf7784cd1, 0x05bce57b, 0xb7186e74, 0x45dcc7de, 0xa3ea0a0c, 0x512ea3a6, 0xc4582879, 0x369c81d3, 0xd0aa4c01, 0x226ee5ab, 0x61b34aa0, 0x9377e30a, 0x75412ed8, 0x87858772, 0x12f30cad, 0xe037a507, 0x060168d5, 0xf4c5c17f, 0x46614a70, 0xb4a5e3da, 0x52932e08, 0xa05787a2, 0x35210c7d, 0xc7e5a5d7, 0x21d36805, 0xd317c1af +}, +{ +0x00000000, 0xafab07f8, 0x471561a0, 0xe8be6658, 0x99c81b78, 0x36631c80, 0xdedd7ad8, 0x71767d20, 0xb82b3b72, 0x17803c8a, 0xff3e5ad2, 0x50955d2a, 0x21e3200a, 0x8e4827f2, 0x66f641aa, 0xc95d4652, 0x15fdae45, 0xba56a9bd, 0x52e8cfe5, 0xfd43c81d, 0x8c35b53d, 0x239eb2c5, 0xcb20d49d, 0x648bd365, 0xadd69537, 0x027d92cf, 0xeac3f497, 0x4568f36f, 0x341e8e4f, 0x9bb589b7, 0x730befef, 0xdca0e817, 0x8c889660, 0x23239198, 0xcb9df7c0, 0x6436f038, 0x15408d18, 0xbaeb8ae0, 0x5255ecb8, 0xfdfeeb40, 0x34a3ad12, 0x9b08aaea, 0x73b6ccb2, 0xdc1dcb4a, 0xad6bb66a, 0x02c0b192, 0xea7ed7ca, 0x45d5d032, 0x99753825, 0x36de3fdd, 0xde605985, 0x71cb5e7d, 0x00bd235d, 0xaf1624a5, 0x47a842fd, 0xe8034505, 0x215e0357, 0x8ef504af, 0x664b62f7, 0xc9e0650f, 0xb896182f, 0x173d1fd7, 0xff83798f, 0x50287e77, 0x7ae16c9c, 0xd54a6b64, 0x3df40d3c, 0x925f0ac4, 0xe32977e4, 0x4c82701c, 0xa43c1644, 0x0b9711bc, 0xc2ca57ee, 0x6d615016, 0x85df364e, 0x2a7431b6, 0x5b024c96, 0xf4a94b6e, 0x1c172d36, 0xb3bc2ace, 0x6f1cc2d9, 0xc0b7c521, 0x2809a379, 0x87a2a481, 0xf6d4d9a1, 0x597fde59, 0xb1c1b801, 0x1e6abff9, 0xd737f9ab, 0x789cfe53, 0x9022980b, 0x3f899ff3, 0x4effe2d3, 0xe154e52b, 0x09ea8373, 0xa641848b, 0xf669fafc, 0x59c2fd04, 0xb17c9b5c, 0x1ed79ca4, 0x6fa1e184, 0xc00ae67c, 0x28b48024, 0x871f87dc, 0x4e42c18e, 0xe1e9c676, 0x0957a02e, 0xa6fca7d6, 0xd78adaf6, 0x7821dd0e, 0x909fbb56, 0x3f34bcae, 0xe39454b9, 0x4c3f5341, 0xa4813519, 0x0b2a32e1, 0x7a5c4fc1, 0xd5f74839, 0x3d492e61, 0x92e22999, 0x5bbf6fcb, 0xf4146833, 0x1caa0e6b, 0xb3010993, 0xc27774b3, 0x6ddc734b, 0x85621513, 0x2ac912eb, 0xb11f752a, 0x1eb472d2, 0xf60a148a, 0x59a11372, 0x28d76e52, 0x877c69aa, 0x6fc20ff2, 0xc069080a, 0x09344e58, 0xa69f49a0, 0x4e212ff8, 0xe18a2800, 0x90fc5520, 0x3f5752d8, 0xd7e93480, 0x78423378, 0xa4e2db6f, 0x0b49dc97, 0xe3f7bacf, 0x4c5cbd37, 0x3d2ac017, 0x9281c7ef, 0x7a3fa1b7, 0xd594a64f, 0x1cc9e01d, 0xb362e7e5, 0x5bdc81bd, 0xf4778645, 0x8501fb65, 0x2aaafc9d, 0xc2149ac5, 0x6dbf9d3d, 0x3d97e34a, 0x923ce4b2, 0x7a8282ea, 0xd5298512, 0xa45ff832, 0x0bf4ffca, 0xe34a9992, 0x4ce19e6a, 0x85bcd838, 0x2a17dfc0, 0xc2a9b998, 0x6d02be60, 0x1c74c340, 0xb3dfc4b8, 0x5b61a2e0, 0xf4caa518, 0x286a4d0f, 0x87c14af7, 0x6f7f2caf, 0xc0d42b57, 0xb1a25677, 0x1e09518f, 0xf6b737d7, 0x591c302f, 0x9041767d, 0x3fea7185, 0xd75417dd, 0x78ff1025, 0x09896d05, 0xa6226afd, 0x4e9c0ca5, 0xe1370b5d, 0xcbfe19b6, 0x64551e4e, 0x8ceb7816, 0x23407fee, 0x523602ce, 0xfd9d0536, 0x1523636e, 0xba886496, 0x73d522c4, 0xdc7e253c, 0x34c04364, 0x9b6b449c, 0xea1d39bc, 0x45b63e44, 0xad08581c, 0x02a35fe4, 0xde03b7f3, 0x71a8b00b, 0x9916d653, 0x36bdd1ab, 0x47cbac8b, 0xe860ab73, 0x00decd2b, 0xaf75cad3, 0x66288c81, 0xc9838b79, 0x213ded21, 0x8e96ead9, 0xffe097f9, 0x504b9001, 0xb8f5f659, 0x175ef1a1, 0x47768fd6, 0xe8dd882e, 0x0063ee76, 0xafc8e98e, 0xdebe94ae, 0x71159356, 0x99abf50e, 0x3600f2f6, 0xff5db4a4, 0x50f6b35c, 0xb848d504, 0x17e3d2fc, 0x6695afdc, 0xc93ea824, 0x2180ce7c, 0x8e2bc984, 0x528b2193, 0xfd20266b, 0x159e4033, 0xba3547cb, 0xcb433aeb, 0x64e83d13, 0x8c565b4b, 0x23fd5cb3, 0xeaa01ae1, 0x450b1d19, 0xadb57b41, 0x021e7cb9, 0x73680199, 0xdcc30661, 0x347d6039, 0x9bd667c1 +}, +{ +0x00000000, 0x1fd3b0ed, 0xa2203a1e, 0xbdf38af3, 0xf72a13a6, 0xe8f9a34b, 0x550a29b8, 0x4ad99955, 0x2c10dfe3, 0x33c36f0e, 0x8e30e5fd, 0x91e35510, 0xdb3acc45, 0xc4e97ca8, 0x791af65b, 0x66c946b6, 0x2fe25b06, 0x3031ebeb, 0x8dc26118, 0x9211d1f5, 0xd8c848a0, 0xc71bf84d, 0x7ae872be, 0x653bc253, 0x03f284e5, 0x1c213408, 0xa1d2befb, 0xbe010e16, 0xf4d89743, 0xeb0b27ae, 0x56f8ad5d, 0x492b1db0, 0x8721dd8c, 0x98f26d61, 0x2501e792, 0x3ad2577f, 0x700bce2a, 0x6fd87ec7, 0xd22bf434, 0xcdf844d9, 0xab31026f, 0xb4e2b282, 0x09113871, 0x16c2889c, 0x5c1b11c9, 0x43c8a124, 0xfe3b2bd7, 0xe1e89b3a, 0xa8c3868a, 0xb7103667, 0x0ae3bc94, 0x15300c79, 0x5fe9952c, 0x403a25c1, 0xfdc9af32, 0xe21a1fdf, 0x84d35969, 0x9b00e984, 0x26f36377, 0x3920d39a, 0x73f94acf, 0x6c2afa22, 0xd1d970d1, 0xce0ac03c, 0x937a871b, 0x8ca937f6, 0x315abd05, 0x2e890de8, 0x645094bd, 0x7b832450, 0xc670aea3, 0xd9a31e4e, 0xbf6a58f8, 0xa0b9e815, 0x1d4a62e6, 0x0299d20b, 0x48404b5e, 0x5793fbb3, 0xea607140, 0xf5b3c1ad, 0xbc98dc1d, 0xa34b6cf0, 0x1eb8e603, 0x016b56ee, 0x4bb2cfbb, 0x54617f56, 0xe992f5a5, 0xf6414548, 0x908803fe, 0x8f5bb313, 0x32a839e0, 0x2d7b890d, 0x67a21058, 0x7871a0b5, 0xc5822a46, 0xda519aab, 0x145b5a97, 0x0b88ea7a, 0xb67b6089, 0xa9a8d064, 0xe3714931, 0xfca2f9dc, 0x4151732f, 0x5e82c3c2, 0x384b8574, 0x27983599, 0x9a6bbf6a, 0x85b80f87, 0xcf6196d2, 0xd0b2263f, 0x6d41accc, 0x72921c21, 0x3bb90191, 0x246ab17c, 0x99993b8f, 0x864a8b62, 0xcc931237, 0xd340a2da, 0x6eb32829, 0x716098c4, 0x17a9de72, 0x087a6e9f, 0xb589e46c, 0xaa5a5481, 0xe083cdd4, 0xff507d39, 0x42a3f7ca, 0x5d704727, 0xfbb524ef, 0xe4669402, 0x59951ef1, 0x4646ae1c, 0x0c9f3749, 0x134c87a4, 0xaebf0d57, 0xb16cbdba, 0xd7a5fb0c, 0xc8764be1, 0x7585c112, 0x6a5671ff, 0x208fe8aa, 0x3f5c5847, 0x82afd2b4, 0x9d7c6259, 0xd4577fe9, 0xcb84cf04, 0x767745f7, 0x69a4f51a, 0x237d6c4f, 0x3caedca2, 0x815d5651, 0x9e8ee6bc, 0xf847a00a, 0xe79410e7, 0x5a679a14, 0x45b42af9, 0x0f6db3ac, 0x10be0341, 0xad4d89b2, 0xb29e395f, 0x7c94f963, 0x6347498e, 0xdeb4c37d, 0xc1677390, 0x8bbeeac5, 0x946d5a28, 0x299ed0db, 0x364d6036, 0x50842680, 0x4f57966d, 0xf2a41c9e, 0xed77ac73, 0xa7ae3526, 0xb87d85cb, 0x058e0f38, 0x1a5dbfd5, 0x5376a265, 0x4ca51288, 0xf156987b, 0xee852896, 0xa45cb1c3, 0xbb8f012e, 0x067c8bdd, 0x19af3b30, 0x7f667d86, 0x60b5cd6b, 0xdd464798, 0xc295f775, 0x884c6e20, 0x979fdecd, 0x2a6c543e, 0x35bfe4d3, 0x68cfa3f4, 0x771c1319, 0xcaef99ea, 0xd53c2907, 0x9fe5b052, 0x803600bf, 0x3dc58a4c, 0x22163aa1, 0x44df7c17, 0x5b0cccfa, 0xe6ff4609, 0xf92cf6e4, 0xb3f56fb1, 0xac26df5c, 0x11d555af, 0x0e06e542, 0x472df8f2, 0x58fe481f, 0xe50dc2ec, 0xfade7201, 0xb007eb54, 0xafd45bb9, 0x1227d14a, 0x0df461a7, 0x6b3d2711, 0x74ee97fc, 0xc91d1d0f, 0xd6ceade2, 0x9c1734b7, 0x83c4845a, 0x3e370ea9, 0x21e4be44, 0xefee7e78, 0xf03dce95, 0x4dce4466, 0x521df48b, 0x18c46dde, 0x0717dd33, 0xbae457c0, 0xa537e72d, 0xc3fea19b, 0xdc2d1176, 0x61de9b85, 0x7e0d2b68, 0x34d4b23d, 0x2b0702d0, 0x96f48823, 0x892738ce, 0xc00c257e, 0xdfdf9593, 0x622c1f60, 0x7dffaf8d, 0x372636d8, 0x28f58635, 0x95060cc6, 0x8ad5bc2b, 0xec1cfa9d, 0xf3cf4a70, 0x4e3cc083, 0x51ef706e, 0x1b36e93b, 0x04e559d6, 0xb916d325, 0xa6c563c8 +}, +{ +0x00000000, 0x73372e3c, 0x68b43501, 0x1b831b3d, 0x5af0638f, 0x29c74db3, 0x3244568e, 0x417378b2, 0x44979401, 0x37a0ba3d, 0x2c23a100, 0x5f148f3c, 0x1e67f78e, 0x6d50d9b2, 0x76d3c28f, 0x05e4ecb3, 0x34f82370, 0x47cf0d4c, 0x5c4c1671, 0x2f7b384d, 0x6e0840ff, 0x1d3f6ec3, 0x06bc75fe, 0x758b5bc2, 0x706fb771, 0x0358994d, 0x18db8270, 0x6becac4c, 0x2a9fd4fe, 0x59a8fac2, 0x422be1ff, 0x311ccfc3, 0xacd07f4c, 0xdfe75170, 0xc4644a4d, 0xb7536471, 0xf6201cc3, 0x851732ff, 0x9e9429c2, 0xeda307fe, 0xe847eb4d, 0x9b70c571, 0x80f3de4c, 0xf3c4f070, 0xb2b788c2, 0xc180a6fe, 0xda03bdc3, 0xa93493ff, 0x98285c3c, 0xeb1f7200, 0xf09c693d, 0x83ab4701, 0xc2d83fb3, 0xb1ef118f, 0xaa6c0ab2, 0xd95b248e, 0xdcbfc83d, 0xaf88e601, 0xb40bfd3c, 0xc73cd300, 0x864fabb2, 0xf578858e, 0xeefb9eb3, 0x9dccb08f, 0x692fcde9, 0x1a18e3d5, 0x019bf8e8, 0x72acd6d4, 0x33dfae66, 0x40e8805a, 0x5b6b9b67, 0x285cb55b, 0x2db859e8, 0x5e8f77d4, 0x450c6ce9, 0x363b42d5, 0x77483a67, 0x047f145b, 0x1ffc0f66, 0x6ccb215a, 0x5dd7ee99, 0x2ee0c0a5, 0x3563db98, 0x4654f5a4, 0x07278d16, 0x7410a32a, 0x6f93b817, 0x1ca4962b, 0x19407a98, 0x6a7754a4, 0x71f44f99, 0x02c361a5, 0x43b01917, 0x3087372b, 0x2b042c16, 0x5833022a, 0xc5ffb2a5, 0xb6c89c99, 0xad4b87a4, 0xde7ca998, 0x9f0fd12a, 0xec38ff16, 0xf7bbe42b, 0x848cca17, 0x816826a4, 0xf25f0898, 0xe9dc13a5, 0x9aeb3d99, 0xdb98452b, 0xa8af6b17, 0xb32c702a, 0xc01b5e16, 0xf10791d5, 0x8230bfe9, 0x99b3a4d4, 0xea848ae8, 0xabf7f25a, 0xd8c0dc66, 0xc343c75b, 0xb074e967, 0xb59005d4, 0xc6a72be8, 0xdd2430d5, 0xae131ee9, 0xef60665b, 0x9c574867, 0x87d4535a, 0xf4e37d66, 0x8fecf9a7, 0xfcdbd79b, 0xe758cca6, 0x946fe29a, 0xd51c9a28, 0xa62bb414, 0xbda8af29, 0xce9f8115, 0xcb7b6da6, 0xb84c439a, 0xa3cf58a7, 0xd0f8769b, 0x918b0e29, 0xe2bc2015, 0xf93f3b28, 0x8a081514, 0xbb14dad7, 0xc823f4eb, 0xd3a0efd6, 0xa097c1ea, 0xe1e4b958, 0x92d39764, 0x89508c59, 0xfa67a265, 0xff834ed6, 0x8cb460ea, 0x97377bd7, 0xe40055eb, 0xa5732d59, 0xd6440365, 0xcdc71858, 0xbef03664, 0x233c86eb, 0x500ba8d7, 0x4b88b3ea, 0x38bf9dd6, 0x79cce564, 0x0afbcb58, 0x1178d065, 0x624ffe59, 0x67ab12ea, 0x149c3cd6, 0x0f1f27eb, 0x7c2809d7, 0x3d5b7165, 0x4e6c5f59, 0x55ef4464, 0x26d86a58, 0x17c4a59b, 0x64f38ba7, 0x7f70909a, 0x0c47bea6, 0x4d34c614, 0x3e03e828, 0x2580f315, 0x56b7dd29, 0x5353319a, 0x20641fa6, 0x3be7049b, 0x48d02aa7, 0x09a35215, 0x7a947c29, 0x61176714, 0x12204928, 0xe6c3344e, 0x95f41a72, 0x8e77014f, 0xfd402f73, 0xbc3357c1, 0xcf0479fd, 0xd48762c0, 0xa7b04cfc, 0xa254a04f, 0xd1638e73, 0xcae0954e, 0xb9d7bb72, 0xf8a4c3c0, 0x8b93edfc, 0x9010f6c1, 0xe327d8fd, 0xd23b173e, 0xa10c3902, 0xba8f223f, 0xc9b80c03, 0x88cb74b1, 0xfbfc5a8d, 0xe07f41b0, 0x93486f8c, 0x96ac833f, 0xe59bad03, 0xfe18b63e, 0x8d2f9802, 0xcc5ce0b0, 0xbf6bce8c, 0xa4e8d5b1, 0xd7dffb8d, 0x4a134b02, 0x3924653e, 0x22a77e03, 0x5190503f, 0x10e3288d, 0x63d406b1, 0x78571d8c, 0x0b6033b0, 0x0e84df03, 0x7db3f13f, 0x6630ea02, 0x1507c43e, 0x5474bc8c, 0x274392b0, 0x3cc0898d, 0x4ff7a7b1, 0x7eeb6872, 0x0ddc464e, 0x165f5d73, 0x6568734f, 0x241b0bfd, 0x572c25c1, 0x4caf3efc, 0x3f9810c0, 0x3a7cfc73, 0x494bd24f, 0x52c8c972, 0x21ffe74e, 0x608c9ffc, 0x13bbb1c0, 0x0838aafd, 0x7b0f84c1 +}, +{ +0x00000000, 0x2be652f1, 0x02c14cc5, 0x29271e34, 0x5cf558aa, 0x77130a5b, 0x5e34146f, 0x75d2469e, 0x4e3ce25e, 0x65dab0af, 0x4cfdae9b, 0x671bfc6a, 0x12c9baf4, 0x392fe805, 0x1008f631, 0x3beea4c0, 0x148c4b57, 0x3f6a19a6, 0x164d0792, 0x3dab5563, 0x487913fd, 0x639f410c, 0x4ab85f38, 0x615e0dc9, 0x5ab0a909, 0x7156fbf8, 0x5871e5cc, 0x7397b73d, 0x0645f1a3, 0x2da3a352, 0x0484bd66, 0x2f62ef97, 0x1b742d07, 0x30927ff6, 0x19b561c2, 0x32533333, 0x478175ad, 0x6c67275c, 0x45403968, 0x6ea66b99, 0x5548cf59, 0x7eae9da8, 0x5789839c, 0x7c6fd16d, 0x09bd97f3, 0x225bc502, 0x0b7cdb36, 0x209a89c7, 0x0ff86650, 0x241e34a1, 0x0d392a95, 0x26df7864, 0x530d3efa, 0x78eb6c0b, 0x51cc723f, 0x7a2a20ce, 0x41c4840e, 0x6a22d6ff, 0x4305c8cb, 0x68e39a3a, 0x1d31dca4, 0x36d78e55, 0x1ff09061, 0x3416c290, 0x50e20d61, 0x7b045f90, 0x522341a4, 0x79c51355, 0x0c1755cb, 0x27f1073a, 0x0ed6190e, 0x25304bff, 0x1edeef3f, 0x3538bdce, 0x1c1fa3fa, 0x37f9f10b, 0x422bb795, 0x69cde564, 0x40eafb50, 0x6b0ca9a1, 0x446e4636, 0x6f8814c7, 0x46af0af3, 0x6d495802, 0x189b1e9c, 0x337d4c6d, 0x1a5a5259, 0x31bc00a8, 0x0a52a468, 0x21b4f699, 0x0893e8ad, 0x2375ba5c, 0x56a7fcc2, 0x7d41ae33, 0x5466b007, 0x7f80e2f6, 0x4b962066, 0x60707297, 0x49576ca3, 0x62b13e52, 0x176378cc, 0x3c852a3d, 0x15a23409, 0x3e4466f8, 0x05aac238, 0x2e4c90c9, 0x076b8efd, 0x2c8ddc0c, 0x595f9a92, 0x72b9c863, 0x5b9ed657, 0x707884a6, 0x5f1a6b31, 0x74fc39c0, 0x5ddb27f4, 0x763d7505, 0x03ef339b, 0x2809616a, 0x012e7f5e, 0x2ac82daf, 0x1126896f, 0x3ac0db9e, 0x13e7c5aa, 0x3801975b, 0x4dd3d1c5, 0x66358334, 0x4f129d00, 0x64f4cff1, 0xced280bd, 0xe534d24c, 0xcc13cc78, 0xe7f59e89, 0x9227d817, 0xb9c18ae6, 0x90e694d2, 0xbb00c623, 0x80ee62e3, 0xab083012, 0x822f2e26, 0xa9c97cd7, 0xdc1b3a49, 0xf7fd68b8, 0xdeda768c, 0xf53c247d, 0xda5ecbea, 0xf1b8991b, 0xd89f872f, 0xf379d5de, 0x86ab9340, 0xad4dc1b1, 0x846adf85, 0xaf8c8d74, 0x946229b4, 0xbf847b45, 0x96a36571, 0xbd453780, 0xc897711e, 0xe37123ef, 0xca563ddb, 0xe1b06f2a, 0xd5a6adba, 0xfe40ff4b, 0xd767e17f, 0xfc81b38e, 0x8953f510, 0xa2b5a7e1, 0x8b92b9d5, 0xa074eb24, 0x9b9a4fe4, 0xb07c1d15, 0x995b0321, 0xb2bd51d0, 0xc76f174e, 0xec8945bf, 0xc5ae5b8b, 0xee48097a, 0xc12ae6ed, 0xeaccb41c, 0xc3ebaa28, 0xe80df8d9, 0x9ddfbe47, 0xb639ecb6, 0x9f1ef282, 0xb4f8a073, 0x8f1604b3, 0xa4f05642, 0x8dd74876, 0xa6311a87, 0xd3e35c19, 0xf8050ee8, 0xd12210dc, 0xfac4422d, 0x9e308ddc, 0xb5d6df2d, 0x9cf1c119, 0xb71793e8, 0xc2c5d576, 0xe9238787, 0xc00499b3, 0xebe2cb42, 0xd00c6f82, 0xfbea3d73, 0xd2cd2347, 0xf92b71b6, 0x8cf93728, 0xa71f65d9, 0x8e387bed, 0xa5de291c, 0x8abcc68b, 0xa15a947a, 0x887d8a4e, 0xa39bd8bf, 0xd6499e21, 0xfdafccd0, 0xd488d2e4, 0xff6e8015, 0xc48024d5, 0xef667624, 0xc6416810, 0xeda73ae1, 0x98757c7f, 0xb3932e8e, 0x9ab430ba, 0xb152624b, 0x8544a0db, 0xaea2f22a, 0x8785ec1e, 0xac63beef, 0xd9b1f871, 0xf257aa80, 0xdb70b4b4, 0xf096e645, 0xcb784285, 0xe09e1074, 0xc9b90e40, 0xe25f5cb1, 0x978d1a2f, 0xbc6b48de, 0x954c56ea, 0xbeaa041b, 0x91c8eb8c, 0xba2eb97d, 0x9309a749, 0xb8eff5b8, 0xcd3db326, 0xe6dbe1d7, 0xcffcffe3, 0xe41aad12, 0xdff409d2, 0xf4125b23, 0xdd354517, 0xf6d317e6, 0x83015178, 0xa8e70389, 0x81c01dbd, 0xaa264f4c +}, +{ +0x00000000, 0xe69f25d3, 0xc9848e73, 0x2f1baba0, 0x5101fb9f, 0xb79ede4c, 0x988575ec, 0x7e1a503f, 0x1bf93ffc, 0xfd661a2f, 0xd27db18f, 0x34e2945c, 0x4af8c463, 0xac67e1b0, 0x837c4a10, 0x65e36fc3, 0x255e2632, 0xc3c103e1, 0xecdaa841, 0x0a458d92, 0x745fddad, 0x92c0f87e, 0xbddb53de, 0x5b44760d, 0x3ea719ce, 0xd8383c1d, 0xf72397bd, 0x11bcb26e, 0x6fa6e251, 0x8939c782, 0xa6226c22, 0x40bd49f1, 0xe1854500, 0x071a60d3, 0x2801cb73, 0xce9eeea0, 0xb084be9f, 0x561b9b4c, 0x790030ec, 0x9f9f153f, 0xfa7c7afc, 0x1ce35f2f, 0x33f8f48f, 0xd567d15c, 0xab7d8163, 0x4de2a4b0, 0x62f90f10, 0x84662ac3, 0xc4db6332, 0x224446e1, 0x0d5fed41, 0xebc0c892, 0x95da98ad, 0x7345bd7e, 0x5c5e16de, 0xbac1330d, 0xdf225cce, 0x39bd791d, 0x16a6d2bd, 0xf039f76e, 0x8e23a751, 0x68bc8282, 0x47a72922, 0xa1380cf1, 0x20a83286, 0xc6371755, 0xe92cbcf5, 0x0fb39926, 0x71a9c919, 0x9736ecca, 0xb82d476a, 0x5eb262b9, 0x3b510d7a, 0xddce28a9, 0xf2d58309, 0x144aa6da, 0x6a50f6e5, 0x8ccfd336, 0xa3d47896, 0x454b5d45, 0x05f614b4, 0xe3693167, 0xcc729ac7, 0x2aedbf14, 0x54f7ef2b, 0xb268caf8, 0x9d736158, 0x7bec448b, 0x1e0f2b48, 0xf8900e9b, 0xd78ba53b, 0x311480e8, 0x4f0ed0d7, 0xa991f504, 0x868a5ea4, 0x60157b77, 0xc12d7786, 0x27b25255, 0x08a9f9f5, 0xee36dc26, 0x902c8c19, 0x76b3a9ca, 0x59a8026a, 0xbf3727b9, 0xdad4487a, 0x3c4b6da9, 0x1350c609, 0xf5cfe3da, 0x8bd5b3e5, 0x6d4a9636, 0x42513d96, 0xa4ce1845, 0xe47351b4, 0x02ec7467, 0x2df7dfc7, 0xcb68fa14, 0xb572aa2b, 0x53ed8ff8, 0x7cf62458, 0x9a69018b, 0xff8a6e48, 0x19154b9b, 0x360ee03b, 0xd091c5e8, 0xae8b95d7, 0x4814b004, 0x670f1ba4, 0x81903e77, 0x4a60756d, 0xacff50be, 0x83e4fb1e, 0x657bdecd, 0x1b618ef2, 0xfdfeab21, 0xd2e50081, 0x347a2552, 0x51994a91, 0xb7066f42, 0x981dc4e2, 0x7e82e131, 0x0098b10e, 0xe60794dd, 0xc91c3f7d, 0x2f831aae, 0x6f3e535f, 0x89a1768c, 0xa6badd2c, 0x4025f8ff, 0x3e3fa8c0, 0xd8a08d13, 0xf7bb26b3, 0x11240360, 0x74c76ca3, 0x92584970, 0xbd43e2d0, 0x5bdcc703, 0x25c6973c, 0xc359b2ef, 0xec42194f, 0x0add3c9c, 0xabe5306d, 0x4d7a15be, 0x6261be1e, 0x84fe9bcd, 0xfae4cbf2, 0x1c7bee21, 0x33604581, 0xd5ff6052, 0xb01c0f91, 0x56832a42, 0x799881e2, 0x9f07a431, 0xe11df40e, 0x0782d1dd, 0x28997a7d, 0xce065fae, 0x8ebb165f, 0x6824338c, 0x473f982c, 0xa1a0bdff, 0xdfbaedc0, 0x3925c813, 0x163e63b3, 0xf0a14660, 0x954229a3, 0x73dd0c70, 0x5cc6a7d0, 0xba598203, 0xc443d23c, 0x22dcf7ef, 0x0dc75c4f, 0xeb58799c, 0x6ac847eb, 0x8c576238, 0xa34cc998, 0x45d3ec4b, 0x3bc9bc74, 0xdd5699a7, 0xf24d3207, 0x14d217d4, 0x71317817, 0x97ae5dc4, 0xb8b5f664, 0x5e2ad3b7, 0x20308388, 0xc6afa65b, 0xe9b40dfb, 0x0f2b2828, 0x4f9661d9, 0xa909440a, 0x8612efaa, 0x608dca79, 0x1e979a46, 0xf808bf95, 0xd7131435, 0x318c31e6, 0x546f5e25, 0xb2f07bf6, 0x9debd056, 0x7b74f585, 0x056ea5ba, 0xe3f18069, 0xccea2bc9, 0x2a750e1a, 0x8b4d02eb, 0x6dd22738, 0x42c98c98, 0xa456a94b, 0xda4cf974, 0x3cd3dca7, 0x13c87707, 0xf55752d4, 0x90b43d17, 0x762b18c4, 0x5930b364, 0xbfaf96b7, 0xc1b5c688, 0x272ae35b, 0x083148fb, 0xeeae6d28, 0xae1324d9, 0x488c010a, 0x6797aaaa, 0x81088f79, 0xff12df46, 0x198dfa95, 0x36965135, 0xd00974e6, 0xb5ea1b25, 0x53753ef6, 0x7c6e9556, 0x9af1b085, 0xe4ebe0ba, 0x0274c569, 0x2d6f6ec9, 0xcbf04b1a +}, +{ +0x00000000, 0xc6b891d3, 0x7fe2a8a7, 0xb95a3974, 0xa0a4d763, 0x661c46b0, 0xdf467fc4, 0x19feee17, 0xe3c9e7e9, 0x2571763a, 0x9c2b4f4e, 0x5a93de9d, 0x436d308a, 0x85d5a159, 0x3c8f982d, 0xfa3709fe, 0x454da6f8, 0x83f5372b, 0x3aaf0e5f, 0xfc179f8c, 0xe5e9719b, 0x2351e048, 0x9a0bd93c, 0x5cb348ef, 0xa6844111, 0x603cd0c2, 0xd966e9b6, 0x1fde7865, 0x06209672, 0xc09807a1, 0x79c23ed5, 0xbf7aaf06, 0x339afd70, 0xf5226ca3, 0x4c7855d7, 0x8ac0c404, 0x933e2a13, 0x5586bbc0, 0xecdc82b4, 0x2a641367, 0xd0531a99, 0x16eb8b4a, 0xafb1b23e, 0x690923ed, 0x70f7cdfa, 0xb64f5c29, 0x0f15655d, 0xc9adf48e, 0x76d75b88, 0xb06fca5b, 0x0935f32f, 0xcf8d62fc, 0xd6738ceb, 0x10cb1d38, 0xa991244c, 0x6f29b59f, 0x951ebc61, 0x53a62db2, 0xeafc14c6, 0x2c448515, 0x35ba6b02, 0xf302fad1, 0x4a58c3a5, 0x8ce05276, 0x9fde1e73, 0x59668fa0, 0xe03cb6d4, 0x26842707, 0x3f7ac910, 0xf9c258c3, 0x409861b7, 0x8620f064, 0x7c17f99a, 0xbaaf6849, 0x03f5513d, 0xc54dc0ee, 0xdcb32ef9, 0x1a0bbf2a, 0xa351865e, 0x65e9178d, 0xda93b88b, 0x1c2b2958, 0xa571102c, 0x63c981ff, 0x7a376fe8, 0xbc8ffe3b, 0x05d5c74f, 0xc36d569c, 0x395a5f62, 0xffe2ceb1, 0x46b8f7c5, 0x80006616, 0x99fe8801, 0x5f4619d2, 0xe61c20a6, 0x20a4b175, 0xac44e303, 0x6afc72d0, 0xd3a64ba4, 0x151eda77, 0x0ce03460, 0xca58a5b3, 0x73029cc7, 0xb5ba0d14, 0x4f8d04ea, 0x89359539, 0x306fac4d, 0xf6d73d9e, 0xef29d389, 0x2991425a, 0x90cb7b2e, 0x5673eafd, 0xe90945fb, 0x2fb1d428, 0x96ebed5c, 0x50537c8f, 0x49ad9298, 0x8f15034b, 0x364f3a3f, 0xf0f7abec, 0x0ac0a212, 0xcc7833c1, 0x75220ab5, 0xb39a9b66, 0xaa647571, 0x6cdce4a2, 0xd586ddd6, 0x133e4c05, 0xc891be76, 0x0e292fa5, 0xb77316d1, 0x71cb8702, 0x68356915, 0xae8df8c6, 0x17d7c1b2, 0xd16f5061, 0x2b58599f, 0xede0c84c, 0x54baf138, 0x920260eb, 0x8bfc8efc, 0x4d441f2f, 0xf41e265b, 0x32a6b788, 0x8ddc188e, 0x4b64895d, 0xf23eb029, 0x348621fa, 0x2d78cfed, 0xebc05e3e, 0x529a674a, 0x9422f699, 0x6e15ff67, 0xa8ad6eb4, 0x11f757c0, 0xd74fc613, 0xceb12804, 0x0809b9d7, 0xb15380a3, 0x77eb1170, 0xfb0b4306, 0x3db3d2d5, 0x84e9eba1, 0x42517a72, 0x5baf9465, 0x9d1705b6, 0x244d3cc2, 0xe2f5ad11, 0x18c2a4ef, 0xde7a353c, 0x67200c48, 0xa1989d9b, 0xb866738c, 0x7edee25f, 0xc784db2b, 0x013c4af8, 0xbe46e5fe, 0x78fe742d, 0xc1a44d59, 0x071cdc8a, 0x1ee2329d, 0xd85aa34e, 0x61009a3a, 0xa7b80be9, 0x5d8f0217, 0x9b3793c4, 0x226daab0, 0xe4d53b63, 0xfd2bd574, 0x3b9344a7, 0x82c97dd3, 0x4471ec00, 0x574fa005, 0x91f731d6, 0x28ad08a2, 0xee159971, 0xf7eb7766, 0x3153e6b5, 0x8809dfc1, 0x4eb14e12, 0xb48647ec, 0x723ed63f, 0xcb64ef4b, 0x0ddc7e98, 0x1422908f, 0xd29a015c, 0x6bc03828, 0xad78a9fb, 0x120206fd, 0xd4ba972e, 0x6de0ae5a, 0xab583f89, 0xb2a6d19e, 0x741e404d, 0xcd447939, 0x0bfce8ea, 0xf1cbe114, 0x377370c7, 0x8e2949b3, 0x4891d860, 0x516f3677, 0x97d7a7a4, 0x2e8d9ed0, 0xe8350f03, 0x64d55d75, 0xa26dcca6, 0x1b37f5d2, 0xdd8f6401, 0xc4718a16, 0x02c91bc5, 0xbb9322b1, 0x7d2bb362, 0x871cba9c, 0x41a42b4f, 0xf8fe123b, 0x3e4683e8, 0x27b86dff, 0xe100fc2c, 0x585ac558, 0x9ee2548b, 0x2198fb8d, 0xe7206a5e, 0x5e7a532a, 0x98c2c2f9, 0x813c2cee, 0x4784bd3d, 0xfede8449, 0x3866159a, 0xc2511c64, 0x04e98db7, 0xbdb3b4c3, 0x7b0b2510, 0x62f5cb07, 0xa44d5ad4, 0x1d1763a0, 0xdbaff273 +}, +{ +0x00000000, 0x570cf5b0, 0x8f99d2bc, 0xd895270c, 0xcae762a3, 0x9deb9713, 0x457eb01f, 0x127245af, 0x1fd8936f, 0x48d466df, 0x904141d3, 0xc74db463, 0xd53ff1cc, 0x8233047c, 0x5aa62370, 0x0daad6c0, 0xf8b8e276, 0xafb417c6, 0x772130ca, 0x202dc57a, 0x325f80d5, 0x65537565, 0xbdc65269, 0xeacaa7d9, 0xe7607119, 0xb06c84a9, 0x68f9a3a5, 0x3ff55615, 0x2d8713ba, 0x7a8be60a, 0xa21ec106, 0xf51234b6, 0xe3a09718, 0xb4ac62a8, 0x6c3945a4, 0x3b35b014, 0x2947f5bb, 0x7e4b000b, 0xa6de2707, 0xf1d2d2b7, 0xfc780477, 0xab74f1c7, 0x73e1d6cb, 0x24ed237b, 0x369f66d4, 0x61939364, 0xb906b468, 0xee0a41d8, 0x1b18756e, 0x4c1480de, 0x9481a7d2, 0xc38d5262, 0xd1ff17cd, 0x86f3e27d, 0x5e66c571, 0x096a30c1, 0x04c0e601, 0x53cc13b1, 0x8b5934bd, 0xdc55c10d, 0xce2784a2, 0x992b7112, 0x41be561e, 0x16b2a3ae, 0x328adfd9, 0x65862a69, 0xbd130d65, 0xea1ff8d5, 0xf86dbd7a, 0xaf6148ca, 0x77f46fc6, 0x20f89a76, 0x2d524cb6, 0x7a5eb906, 0xa2cb9e0a, 0xf5c76bba, 0xe7b52e15, 0xb0b9dba5, 0x682cfca9, 0x3f200919, 0xca323daf, 0x9d3ec81f, 0x45abef13, 0x12a71aa3, 0x00d55f0c, 0x57d9aabc, 0x8f4c8db0, 0xd8407800, 0xd5eaaec0, 0x82e65b70, 0x5a737c7c, 0x0d7f89cc, 0x1f0dcc63, 0x480139d3, 0x90941edf, 0xc798eb6f, 0xd12a48c1, 0x8626bd71, 0x5eb39a7d, 0x09bf6fcd, 0x1bcd2a62, 0x4cc1dfd2, 0x9454f8de, 0xc3580d6e, 0xcef2dbae, 0x99fe2e1e, 0x416b0912, 0x1667fca2, 0x0415b90d, 0x53194cbd, 0x8b8c6bb1, 0xdc809e01, 0x2992aab7, 0x7e9e5f07, 0xa60b780b, 0xf1078dbb, 0xe375c814, 0xb4793da4, 0x6cec1aa8, 0x3be0ef18, 0x364a39d8, 0x6146cc68, 0xb9d3eb64, 0xeedf1ed4, 0xfcad5b7b, 0xaba1aecb, 0x733489c7, 0x24387c77, 0xb7a7fa4d, 0xe0ab0ffd, 0x383e28f1, 0x6f32dd41, 0x7d4098ee, 0x2a4c6d5e, 0xf2d94a52, 0xa5d5bfe2, 0xa87f6922, 0xff739c92, 0x27e6bb9e, 0x70ea4e2e, 0x62980b81, 0x3594fe31, 0xed01d93d, 0xba0d2c8d, 0x4f1f183b, 0x1813ed8b, 0xc086ca87, 0x978a3f37, 0x85f87a98, 0xd2f48f28, 0x0a61a824, 0x5d6d5d94, 0x50c78b54, 0x07cb7ee4, 0xdf5e59e8, 0x8852ac58, 0x9a20e9f7, 0xcd2c1c47, 0x15b93b4b, 0x42b5cefb, 0x54076d55, 0x030b98e5, 0xdb9ebfe9, 0x8c924a59, 0x9ee00ff6, 0xc9ecfa46, 0x1179dd4a, 0x467528fa, 0x4bdffe3a, 0x1cd30b8a, 0xc4462c86, 0x934ad936, 0x81389c99, 0xd6346929, 0x0ea14e25, 0x59adbb95, 0xacbf8f23, 0xfbb37a93, 0x23265d9f, 0x742aa82f, 0x6658ed80, 0x31541830, 0xe9c13f3c, 0xbecdca8c, 0xb3671c4c, 0xe46be9fc, 0x3cfecef0, 0x6bf23b40, 0x79807eef, 0x2e8c8b5f, 0xf619ac53, 0xa11559e3, 0x852d2594, 0xd221d024, 0x0ab4f728, 0x5db80298, 0x4fca4737, 0x18c6b287, 0xc053958b, 0x975f603b, 0x9af5b6fb, 0xcdf9434b, 0x156c6447, 0x426091f7, 0x5012d458, 0x071e21e8, 0xdf8b06e4, 0x8887f354, 0x7d95c7e2, 0x2a993252, 0xf20c155e, 0xa500e0ee, 0xb772a541, 0xe07e50f1, 0x38eb77fd, 0x6fe7824d, 0x624d548d, 0x3541a13d, 0xedd48631, 0xbad87381, 0xa8aa362e, 0xffa6c39e, 0x2733e492, 0x703f1122, 0x668db28c, 0x3181473c, 0xe9146030, 0xbe189580, 0xac6ad02f, 0xfb66259f, 0x23f30293, 0x74fff723, 0x795521e3, 0x2e59d453, 0xf6ccf35f, 0xa1c006ef, 0xb3b24340, 0xe4beb6f0, 0x3c2b91fc, 0x6b27644c, 0x9e3550fa, 0xc939a54a, 0x11ac8246, 0x46a077f6, 0x54d23259, 0x03dec7e9, 0xdb4be0e5, 0x8c471555, 0x81edc395, 0xd6e13625, 0x0e741129, 0x5978e499, 0x4b0aa136, 0x1c065486, 0xc493738a, 0x939f863a +}, +{ +0x00000000, 0xf615ece0, 0xacc78444, 0x5ad268a4, 0x10245110, 0xe631bdf0, 0xbce3d554, 0x4af639b4, 0xb3d9cc77, 0x45cc2097, 0x1f1e4833, 0xe90ba4d3, 0xa3fd9d67, 0x55e87187, 0x0f3a1923, 0xf92ff5c3, 0xa0dd64bf, 0x56c8885f, 0x0c1ae0fb, 0xfa0f0c1b, 0xb0f935af, 0x46ecd94f, 0x1c3eb1eb, 0xea2b5d0b, 0x1304a8c8, 0xe5114428, 0xbfc32c8c, 0x49d6c06c, 0x0320f9d8, 0xf5351538, 0xafe77d9c, 0x59f2917c, 0x6e6993b7, 0x987c7f57, 0xc2ae17f3, 0x34bbfb13, 0x7e4dc2a7, 0x88582e47, 0xd28a46e3, 0x249faa03, 0xddb05fc0, 0x2ba5b320, 0x7177db84, 0x87623764, 0xcd940ed0, 0x3b81e230, 0x61538a94, 0x97466674, 0xceb4f708, 0x38a11be8, 0x6273734c, 0x94669fac, 0xde90a618, 0x28854af8, 0x7257225c, 0x8442cebc, 0x7d6d3b7f, 0x8b78d79f, 0xd1aabf3b, 0x27bf53db, 0x6d496a6f, 0x9b5c868f, 0xc18eee2b, 0x379b02cb, 0x5498bf2b, 0xa28d53cb, 0xf85f3b6f, 0x0e4ad78f, 0x44bcee3b, 0xb2a902db, 0xe87b6a7f, 0x1e6e869f, 0xe741735c, 0x11549fbc, 0x4b86f718, 0xbd931bf8, 0xf765224c, 0x0170ceac, 0x5ba2a608, 0xadb74ae8, 0xf445db94, 0x02503774, 0x58825fd0, 0xae97b330, 0xe4618a84, 0x12746664, 0x48a60ec0, 0xbeb3e220, 0x479c17e3, 0xb189fb03, 0xeb5b93a7, 0x1d4e7f47, 0x57b846f3, 0xa1adaa13, 0xfb7fc2b7, 0x0d6a2e57, 0x3af12c9c, 0xcce4c07c, 0x9636a8d8, 0x60234438, 0x2ad57d8c, 0xdcc0916c, 0x8612f9c8, 0x70071528, 0x8928e0eb, 0x7f3d0c0b, 0x25ef64af, 0xd3fa884f, 0x990cb1fb, 0x6f195d1b, 0x35cb35bf, 0xc3ded95f, 0x9a2c4823, 0x6c39a4c3, 0x36ebcc67, 0xc0fe2087, 0x8a081933, 0x7c1df5d3, 0x26cf9d77, 0xd0da7197, 0x29f58454, 0xdfe068b4, 0x85320010, 0x7327ecf0, 0x39d1d544, 0xcfc439a4, 0x95165100, 0x6303bde0, 0x53df2926, 0xa5cac5c6, 0xff18ad62, 0x090d4182, 0x43fb7836, 0xb5ee94d6, 0xef3cfc72, 0x19291092, 0xe006e551, 0x161309b1, 0x4cc16115, 0xbad48df5, 0xf022b441, 0x063758a1, 0x5ce53005, 0xaaf0dce5, 0xf3024d99, 0x0517a179, 0x5fc5c9dd, 0xa9d0253d, 0xe3261c89, 0x1533f069, 0x4fe198cd, 0xb9f4742d, 0x40db81ee, 0xb6ce6d0e, 0xec1c05aa, 0x1a09e94a, 0x50ffd0fe, 0xa6ea3c1e, 0xfc3854ba, 0x0a2db85a, 0x3db6ba91, 0xcba35671, 0x91713ed5, 0x6764d235, 0x2d92eb81, 0xdb870761, 0x81556fc5, 0x77408325, 0x8e6f76e6, 0x787a9a06, 0x22a8f2a2, 0xd4bd1e42, 0x9e4b27f6, 0x685ecb16, 0x328ca3b2, 0xc4994f52, 0x9d6bde2e, 0x6b7e32ce, 0x31ac5a6a, 0xc7b9b68a, 0x8d4f8f3e, 0x7b5a63de, 0x21880b7a, 0xd79de79a, 0x2eb21259, 0xd8a7feb9, 0x8275961d, 0x74607afd, 0x3e964349, 0xc883afa9, 0x9251c70d, 0x64442bed, 0x0747960d, 0xf1527aed, 0xab801249, 0x5d95fea9, 0x1763c71d, 0xe1762bfd, 0xbba44359, 0x4db1afb9, 0xb49e5a7a, 0x428bb69a, 0x1859de3e, 0xee4c32de, 0xa4ba0b6a, 0x52afe78a, 0x087d8f2e, 0xfe6863ce, 0xa79af2b2, 0x518f1e52, 0x0b5d76f6, 0xfd489a16, 0xb7bea3a2, 0x41ab4f42, 0x1b7927e6, 0xed6ccb06, 0x14433ec5, 0xe256d225, 0xb884ba81, 0x4e915661, 0x04676fd5, 0xf2728335, 0xa8a0eb91, 0x5eb50771, 0x692e05ba, 0x9f3be95a, 0xc5e981fe, 0x33fc6d1e, 0x790a54aa, 0x8f1fb84a, 0xd5cdd0ee, 0x23d83c0e, 0xdaf7c9cd, 0x2ce2252d, 0x76304d89, 0x8025a169, 0xcad398dd, 0x3cc6743d, 0x66141c99, 0x9001f079, 0xc9f36105, 0x3fe68de5, 0x6534e541, 0x932109a1, 0xd9d73015, 0x2fc2dcf5, 0x7510b451, 0x830558b1, 0x7a2aad72, 0x8c3f4192, 0xd6ed2936, 0x20f8c5d6, 0x6a0efc62, 0x9c1b1082, 0xc6c97826, 0x30dc94c6 +} +}, +{ +{ +0x00000000, 0x0c3727f7, 0x2e3d3c36, 0x220a1bc1, 0xb926d1d5, 0xb511f622, 0x971bede3, 0x9b2cca14, 0xdd742a56, 0xd1430da1, 0xf3491660, 0xff7e3197, 0x6452fb83, 0x6865dc74, 0x4a6fc7b5, 0x4658e042, 0x01cdfb33, 0x0dfadcc4, 0x2ff0c705, 0x23c7e0f2, 0xb8eb2ae6, 0xb4dc0d11, 0x96d616d0, 0x9ae13127, 0xdcb9d165, 0xd08ef692, 0xf284ed53, 0xfeb3caa4, 0x659f00b0, 0x69a82747, 0x4ba23c86, 0x47951b71, 0xd0f80e9b, 0xdccf296c, 0xfec532ad, 0xf2f2155a, 0x69dedf4e, 0x65e9f8b9, 0x47e3e378, 0x4bd4c48f, 0x0d8c24cd, 0x01bb033a, 0x23b118fb, 0x2f863f0c, 0xb4aaf518, 0xb89dd2ef, 0x9a97c92e, 0x96a0eed9, 0xd135f5a8, 0xdd02d25f, 0xff08c99e, 0xf33fee69, 0x6813247d, 0x6424038a, 0x462e184b, 0x4a193fbc, 0x0c41dffe, 0x0076f809, 0x227ce3c8, 0x2e4bc43f, 0xb5670e2b, 0xb95029dc, 0x9b5a321d, 0x976d15ea, 0xeacb7cc2, 0xe6fc5b35, 0xc4f640f4, 0xc8c16703, 0x53edad17, 0x5fda8ae0, 0x7dd09121, 0x71e7b6d6, 0x37bf5694, 0x3b887163, 0x19826aa2, 0x15b54d55, 0x8e998741, 0x82aea0b6, 0xa0a4bb77, 0xac939c80, 0xeb0687f1, 0xe731a006, 0xc53bbbc7, 0xc90c9c30, 0x52205624, 0x5e1771d3, 0x7c1d6a12, 0x702a4de5, 0x3672ada7, 0x3a458a50, 0x184f9191, 0x1478b666, 0x8f547c72, 0x83635b85, 0xa1694044, 0xad5e67b3, 0x3a337259, 0x360455ae, 0x140e4e6f, 0x18396998, 0x8315a38c, 0x8f22847b, 0xad289fba, 0xa11fb84d, 0xe747580f, 0xeb707ff8, 0xc97a6439, 0xc54d43ce, 0x5e6189da, 0x5256ae2d, 0x705cb5ec, 0x7c6b921b, 0x3bfe896a, 0x37c9ae9d, 0x15c3b55c, 0x19f492ab, 0x82d858bf, 0x8eef7f48, 0xace56489, 0xa0d2437e, 0xe68aa33c, 0xeabd84cb, 0xc8b79f0a, 0xc480b8fd, 0x5fac72e9, 0x539b551e, 0x71914edf, 0x7da66928, 0x5a963081, 0x56a11776, 0x74ab0cb7, 0x789c2b40, 0xe3b0e154, 0xef87c6a3, 0xcd8ddd62, 0xc1bafa95, 0x87e21ad7, 0x8bd53d20, 0xa9df26e1, 0xa5e80116, 0x3ec4cb02, 0x32f3ecf5, 0x10f9f734, 0x1cced0c3, 0x5b5bcbb2, 0x576cec45, 0x7566f784, 0x7951d073, 0xe27d1a67, 0xee4a3d90, 0xcc402651, 0xc07701a6, 0x862fe1e4, 0x8a18c613, 0xa812ddd2, 0xa425fa25, 0x3f093031, 0x333e17c6, 0x11340c07, 0x1d032bf0, 0x8a6e3e1a, 0x865919ed, 0xa453022c, 0xa86425db, 0x3348efcf, 0x3f7fc838, 0x1d75d3f9, 0x1142f40e, 0x571a144c, 0x5b2d33bb, 0x7927287a, 0x75100f8d, 0xee3cc599, 0xe20be26e, 0xc001f9af, 0xcc36de58, 0x8ba3c529, 0x8794e2de, 0xa59ef91f, 0xa9a9dee8, 0x328514fc, 0x3eb2330b, 0x1cb828ca, 0x108f0f3d, 0x56d7ef7f, 0x5ae0c888, 0x78ead349, 0x74ddf4be, 0xeff13eaa, 0xe3c6195d, 0xc1cc029c, 0xcdfb256b, 0xb05d4c43, 0xbc6a6bb4, 0x9e607075, 0x92575782, 0x097b9d96, 0x054cba61, 0x2746a1a0, 0x2b718657, 0x6d296615, 0x611e41e2, 0x43145a23, 0x4f237dd4, 0xd40fb7c0, 0xd8389037, 0xfa328bf6, 0xf605ac01, 0xb190b770, 0xbda79087, 0x9fad8b46, 0x939aacb1, 0x08b666a5, 0x04814152, 0x268b5a93, 0x2abc7d64, 0x6ce49d26, 0x60d3bad1, 0x42d9a110, 0x4eee86e7, 0xd5c24cf3, 0xd9f56b04, 0xfbff70c5, 0xf7c85732, 0x60a542d8, 0x6c92652f, 0x4e987eee, 0x42af5919, 0xd983930d, 0xd5b4b4fa, 0xf7beaf3b, 0xfb8988cc, 0xbdd1688e, 0xb1e64f79, 0x93ec54b8, 0x9fdb734f, 0x04f7b95b, 0x08c09eac, 0x2aca856d, 0x26fda29a, 0x6168b9eb, 0x6d5f9e1c, 0x4f5585dd, 0x4362a22a, 0xd84e683e, 0xd4794fc9, 0xf6735408, 0xfa4473ff, 0xbc1c93bd, 0xb02bb44a, 0x9221af8b, 0x9e16887c, 0x053a4268, 0x090d659f, 0x2b077e5e, 0x273059a9 +}, +{ +0x00000000, 0xa6732e61, 0xe0d5637e, 0x46a64d1f, 0xa5b6687a, 0x03c5461b, 0x45630b04, 0xe3102565, 0xc3aca485, 0x65df8ae4, 0x2379c7fb, 0x850ae99a, 0x661accff, 0xc069e29e, 0x86cfaf81, 0x20bc81e0, 0x053e257e, 0xa34d0b1f, 0xe5eb4600, 0x43986861, 0xa0884d04, 0x06fb6365, 0x405d2e7a, 0xe62e001b, 0xc69281fb, 0x60e1af9a, 0x2647e285, 0x8034cce4, 0x6324e981, 0xc557c7e0, 0x83f18aff, 0x2582a49e, 0xa1d77136, 0x07a45f57, 0x41021248, 0xe7713c29, 0x0461194c, 0xa212372d, 0xe4b47a32, 0x42c75453, 0x627bd5b3, 0xc408fbd2, 0x82aeb6cd, 0x24dd98ac, 0xc7cdbdc9, 0x61be93a8, 0x2718deb7, 0x816bf0d6, 0xa4e95448, 0x029a7a29, 0x443c3736, 0xe24f1957, 0x015f3c32, 0xa72c1253, 0xe18a5f4c, 0x47f9712d, 0x6745f0cd, 0xc136deac, 0x879093b3, 0x21e3bdd2, 0xc2f398b7, 0x6480b6d6, 0x2226fbc9, 0x8455d5a8, 0xc18076a3, 0x67f358c2, 0x215515dd, 0x87263bbc, 0x64361ed9, 0xc24530b8, 0x84e37da7, 0x229053c6, 0x022cd226, 0xa45ffc47, 0xe2f9b158, 0x448a9f39, 0xa79aba5c, 0x01e9943d, 0x474fd922, 0xe13cf743, 0xc4be53dd, 0x62cd7dbc, 0x246b30a3, 0x82181ec2, 0x61083ba7, 0xc77b15c6, 0x81dd58d9, 0x27ae76b8, 0x0712f758, 0xa161d939, 0xe7c79426, 0x41b4ba47, 0xa2a49f22, 0x04d7b143, 0x4271fc5c, 0xe402d23d, 0x60570795, 0xc62429f4, 0x808264eb, 0x26f14a8a, 0xc5e16fef, 0x6392418e, 0x25340c91, 0x834722f0, 0xa3fba310, 0x05888d71, 0x432ec06e, 0xe55dee0f, 0x064dcb6a, 0xa03ee50b, 0xe698a814, 0x40eb8675, 0x656922eb, 0xc31a0c8a, 0x85bc4195, 0x23cf6ff4, 0xc0df4a91, 0x66ac64f0, 0x200a29ef, 0x8679078e, 0xa6c5866e, 0x00b6a80f, 0x4610e510, 0xe063cb71, 0x0373ee14, 0xa500c075, 0xe3a68d6a, 0x45d5a30b, 0x73be9b58, 0xd5cdb539, 0x936bf826, 0x3518d647, 0xd608f322, 0x707bdd43, 0x36dd905c, 0x90aebe3d, 0xb0123fdd, 0x166111bc, 0x50c75ca3, 0xf6b472c2, 0x15a457a7, 0xb3d779c6, 0xf57134d9, 0x53021ab8, 0x7680be26, 0xd0f39047, 0x9655dd58, 0x3026f339, 0xd336d65c, 0x7545f83d, 0x33e3b522, 0x95909b43, 0xb52c1aa3, 0x135f34c2, 0x55f979dd, 0xf38a57bc, 0x109a72d9, 0xb6e95cb8, 0xf04f11a7, 0x563c3fc6, 0xd269ea6e, 0x741ac40f, 0x32bc8910, 0x94cfa771, 0x77df8214, 0xd1acac75, 0x970ae16a, 0x3179cf0b, 0x11c54eeb, 0xb7b6608a, 0xf1102d95, 0x576303f4, 0xb4732691, 0x120008f0, 0x54a645ef, 0xf2d56b8e, 0xd757cf10, 0x7124e171, 0x3782ac6e, 0x91f1820f, 0x72e1a76a, 0xd492890b, 0x9234c414, 0x3447ea75, 0x14fb6b95, 0xb28845f4, 0xf42e08eb, 0x525d268a, 0xb14d03ef, 0x173e2d8e, 0x51986091, 0xf7eb4ef0, 0xb23eedfb, 0x144dc39a, 0x52eb8e85, 0xf498a0e4, 0x17888581, 0xb1fbabe0, 0xf75de6ff, 0x512ec89e, 0x7192497e, 0xd7e1671f, 0x91472a00, 0x37340461, 0xd4242104, 0x72570f65, 0x34f1427a, 0x92826c1b, 0xb700c885, 0x1173e6e4, 0x57d5abfb, 0xf1a6859a, 0x12b6a0ff, 0xb4c58e9e, 0xf263c381, 0x5410ede0, 0x74ac6c00, 0xd2df4261, 0x94790f7e, 0x320a211f, 0xd11a047a, 0x77692a1b, 0x31cf6704, 0x97bc4965, 0x13e99ccd, 0xb59ab2ac, 0xf33cffb3, 0x554fd1d2, 0xb65ff4b7, 0x102cdad6, 0x568a97c9, 0xf0f9b9a8, 0xd0453848, 0x76361629, 0x30905b36, 0x96e37557, 0x75f35032, 0xd3807e53, 0x9526334c, 0x33551d2d, 0x16d7b9b3, 0xb0a497d2, 0xf602dacd, 0x5071f4ac, 0xb361d1c9, 0x1512ffa8, 0x53b4b2b7, 0xf5c79cd6, 0xd57b1d36, 0x73083357, 0x35ae7e48, 0x93dd5029, 0x70cd754c, 0xd6be5b2d, 0x90181632, 0x366b3853 +}, +{ +0x00000000, 0x53ff1f4e, 0x0e683d2f, 0x5d972261, 0xdae44416, 0x891b5b58, 0xd48c7939, 0x87736677, 0x7a46a8f0, 0x29b9b7be, 0x742e95df, 0x27d18a91, 0xa0a2ece6, 0xf35df3a8, 0xaecad1c9, 0xfd35ce87, 0x8f78713e, 0xdc876e70, 0x81104c11, 0xd2ef535f, 0x559c3528, 0x06632a66, 0x5bf40807, 0x080b1749, 0xf53ed9ce, 0xa6c1c680, 0xfb56e4e1, 0xa8a9fbaf, 0x2fda9dd8, 0x7c258296, 0x21b2a0f7, 0x724dbfb9, 0xbf78f0cb, 0xec87ef85, 0xb110cde4, 0xe2efd2aa, 0x659cb4dd, 0x3663ab93, 0x6bf489f2, 0x380b96bc, 0xc53e583b, 0x96c14775, 0xcb566514, 0x98a97a5a, 0x1fda1c2d, 0x4c250363, 0x11b22102, 0x424d3e4c, 0x300081f5, 0x63ff9ebb, 0x3e68bcda, 0x6d97a394, 0xeae4c5e3, 0xb91bdaad, 0xe48cf8cc, 0xb773e782, 0x4a462905, 0x19b9364b, 0x442e142a, 0x17d10b64, 0x90a26d13, 0xc35d725d, 0x9eca503c, 0xcd354f72, 0x33ec101d, 0x60130f53, 0x3d842d32, 0x6e7b327c, 0xe908540b, 0xbaf74b45, 0xe7606924, 0xb49f766a, 0x49aab8ed, 0x1a55a7a3, 0x47c285c2, 0x143d9a8c, 0x934efcfb, 0xc0b1e3b5, 0x9d26c1d4, 0xced9de9a, 0xbc946123, 0xef6b7e6d, 0xb2fc5c0c, 0xe1034342, 0x66702535, 0x358f3a7b, 0x6818181a, 0x3be70754, 0xc6d2c9d3, 0x952dd69d, 0xc8baf4fc, 0x9b45ebb2, 0x1c368dc5, 0x4fc9928b, 0x125eb0ea, 0x41a1afa4, 0x8c94e0d6, 0xdf6bff98, 0x82fcddf9, 0xd103c2b7, 0x5670a4c0, 0x058fbb8e, 0x581899ef, 0x0be786a1, 0xf6d24826, 0xa52d5768, 0xf8ba7509, 0xab456a47, 0x2c360c30, 0x7fc9137e, 0x225e311f, 0x71a12e51, 0x03ec91e8, 0x50138ea6, 0x0d84acc7, 0x5e7bb389, 0xd908d5fe, 0x8af7cab0, 0xd760e8d1, 0x849ff79f, 0x79aa3918, 0x2a552656, 0x77c20437, 0x243d1b79, 0xa34e7d0e, 0xf0b16240, 0xad264021, 0xfed95f6f, 0xc8fba103, 0x9b04be4d, 0xc6939c2c, 0x956c8362, 0x121fe515, 0x41e0fa5b, 0x1c77d83a, 0x4f88c774, 0xb2bd09f3, 0xe14216bd, 0xbcd534dc, 0xef2a2b92, 0x68594de5, 0x3ba652ab, 0x663170ca, 0x35ce6f84, 0x4783d03d, 0x147ccf73, 0x49ebed12, 0x1a14f25c, 0x9d67942b, 0xce988b65, 0x930fa904, 0xc0f0b64a, 0x3dc578cd, 0x6e3a6783, 0x33ad45e2, 0x60525aac, 0xe7213cdb, 0xb4de2395, 0xe94901f4, 0xbab61eba, 0x778351c8, 0x247c4e86, 0x79eb6ce7, 0x2a1473a9, 0xad6715de, 0xfe980a90, 0xa30f28f1, 0xf0f037bf, 0x0dc5f938, 0x5e3ae676, 0x03adc417, 0x5052db59, 0xd721bd2e, 0x84dea260, 0xd9498001, 0x8ab69f4f, 0xf8fb20f6, 0xab043fb8, 0xf6931dd9, 0xa56c0297, 0x221f64e0, 0x71e07bae, 0x2c7759cf, 0x7f884681, 0x82bd8806, 0xd1429748, 0x8cd5b529, 0xdf2aaa67, 0x5859cc10, 0x0ba6d35e, 0x5631f13f, 0x05ceee71, 0xfb17b11e, 0xa8e8ae50, 0xf57f8c31, 0xa680937f, 0x21f3f508, 0x720cea46, 0x2f9bc827, 0x7c64d769, 0x815119ee, 0xd2ae06a0, 0x8f3924c1, 0xdcc63b8f, 0x5bb55df8, 0x084a42b6, 0x55dd60d7, 0x06227f99, 0x746fc020, 0x2790df6e, 0x7a07fd0f, 0x29f8e241, 0xae8b8436, 0xfd749b78, 0xa0e3b919, 0xf31ca657, 0x0e2968d0, 0x5dd6779e, 0x004155ff, 0x53be4ab1, 0xd4cd2cc6, 0x87323388, 0xdaa511e9, 0x895a0ea7, 0x446f41d5, 0x17905e9b, 0x4a077cfa, 0x19f863b4, 0x9e8b05c3, 0xcd741a8d, 0x90e338ec, 0xc31c27a2, 0x3e29e925, 0x6dd6f66b, 0x3041d40a, 0x63becb44, 0xe4cdad33, 0xb732b27d, 0xeaa5901c, 0xb95a8f52, 0xcb1730eb, 0x98e82fa5, 0xc57f0dc4, 0x9680128a, 0x11f374fd, 0x420c6bb3, 0x1f9b49d2, 0x4c64569c, 0xb151981b, 0xe2ae8755, 0xbf39a534, 0xecc6ba7a, 0x6bb5dc0d, 0x384ac343, 0x65dde122, 0x3622fe6c +}, +{ +0x00000000, 0xf177016c, 0x208547e2, 0xd1f2468e, 0x4e1c5614, 0xbf6b5778, 0x6e9911f6, 0x9fee109a, 0x5ebc316d, 0xafcb3001, 0x7e39768f, 0x8f4e77e3, 0x10a06779, 0xe1d76615, 0x3025209b, 0xc15221f7, 0xa7d5a548, 0x56a2a424, 0x8750e2aa, 0x7627e3c6, 0xe9c9f35c, 0x18bef230, 0xc94cb4be, 0x383bb5d2, 0xf9699425, 0x081e9549, 0xd9ecd3c7, 0x289bd2ab, 0xb775c231, 0x4602c35d, 0x97f085d3, 0x668784bf, 0x0ad7d12d, 0xfba0d041, 0x2a5296cf, 0xdb2597a3, 0x44cb8739, 0xb5bc8655, 0x644ec0db, 0x9539c1b7, 0x546be040, 0xa51ce12c, 0x74eea7a2, 0x8599a6ce, 0x1a77b654, 0xeb00b738, 0x3af2f1b6, 0xcb85f0da, 0xad027465, 0x5c757509, 0x8d873387, 0x7cf032eb, 0xe31e2271, 0x1269231d, 0xc39b6593, 0x32ec64ff, 0xf3be4508, 0x02c94464, 0xd33b02ea, 0x224c0386, 0xbda2131c, 0x4cd51270, 0x9d2754fe, 0x6c505592, 0xf17ec0ad, 0x0009c1c1, 0xd1fb874f, 0x208c8623, 0xbf6296b9, 0x4e1597d5, 0x9fe7d15b, 0x6e90d037, 0xafc2f1c0, 0x5eb5f0ac, 0x8f47b622, 0x7e30b74e, 0xe1dea7d4, 0x10a9a6b8, 0xc15be036, 0x302ce15a, 0x56ab65e5, 0xa7dc6489, 0x762e2207, 0x8759236b, 0x18b733f1, 0xe9c0329d, 0x38327413, 0xc945757f, 0x08175488, 0xf96055e4, 0x2892136a, 0xd9e51206, 0x460b029c, 0xb77c03f0, 0x668e457e, 0x97f94412, 0xfba91180, 0x0ade10ec, 0xdb2c5662, 0x2a5b570e, 0xb5b54794, 0x44c246f8, 0x95300076, 0x6447011a, 0xa51520ed, 0x54622181, 0x8590670f, 0x74e76663, 0xeb0976f9, 0x1a7e7795, 0xcb8c311b, 0x3afb3077, 0x5c7cb4c8, 0xad0bb5a4, 0x7cf9f32a, 0x8d8ef246, 0x1260e2dc, 0xe317e3b0, 0x32e5a53e, 0xc392a452, 0x02c085a5, 0xf3b784c9, 0x2245c247, 0xd332c32b, 0x4cdcd3b1, 0xbdabd2dd, 0x6c599453, 0x9d2e953f, 0xce6500fe, 0x3f120192, 0xeee0471c, 0x1f974670, 0x807956ea, 0x710e5786, 0xa0fc1108, 0x518b1064, 0x90d93193, 0x61ae30ff, 0xb05c7671, 0x412b771d, 0xdec56787, 0x2fb266eb, 0xfe402065, 0x0f372109, 0x69b0a5b6, 0x98c7a4da, 0x4935e254, 0xb842e338, 0x27acf3a2, 0xd6dbf2ce, 0x0729b440, 0xf65eb52c, 0x370c94db, 0xc67b95b7, 0x1789d339, 0xe6fed255, 0x7910c2cf, 0x8867c3a3, 0x5995852d, 0xa8e28441, 0xc4b2d1d3, 0x35c5d0bf, 0xe4379631, 0x1540975d, 0x8aae87c7, 0x7bd986ab, 0xaa2bc025, 0x5b5cc149, 0x9a0ee0be, 0x6b79e1d2, 0xba8ba75c, 0x4bfca630, 0xd412b6aa, 0x2565b7c6, 0xf497f148, 0x05e0f024, 0x6367749b, 0x921075f7, 0x43e23379, 0xb2953215, 0x2d7b228f, 0xdc0c23e3, 0x0dfe656d, 0xfc896401, 0x3ddb45f6, 0xccac449a, 0x1d5e0214, 0xec290378, 0x73c713e2, 0x82b0128e, 0x53425400, 0xa235556c, 0x3f1bc053, 0xce6cc13f, 0x1f9e87b1, 0xeee986dd, 0x71079647, 0x8070972b, 0x5182d1a5, 0xa0f5d0c9, 0x61a7f13e, 0x90d0f052, 0x4122b6dc, 0xb055b7b0, 0x2fbba72a, 0xdecca646, 0x0f3ee0c8, 0xfe49e1a4, 0x98ce651b, 0x69b96477, 0xb84b22f9, 0x493c2395, 0xd6d2330f, 0x27a53263, 0xf65774ed, 0x07207581, 0xc6725476, 0x3705551a, 0xe6f71394, 0x178012f8, 0x886e0262, 0x7919030e, 0xa8eb4580, 0x599c44ec, 0x35cc117e, 0xc4bb1012, 0x1549569c, 0xe43e57f0, 0x7bd0476a, 0x8aa74606, 0x5b550088, 0xaa2201e4, 0x6b702013, 0x9a07217f, 0x4bf567f1, 0xba82669d, 0x256c7607, 0xd41b776b, 0x05e931e5, 0xf49e3089, 0x9219b436, 0x636eb55a, 0xb29cf3d4, 0x43ebf2b8, 0xdc05e222, 0x2d72e34e, 0xfc80a5c0, 0x0df7a4ac, 0xcca5855b, 0x3dd28437, 0xec20c2b9, 0x1d57c3d5, 0x82b9d34f, 0x73ced223, 0xa23c94ad, 0x534b95c1 +}, +{ +0x00000000, 0x84eb300e, 0xd0cd22fd, 0x542612f3, 0xadf93b43, 0x29120b4d, 0x7d3419be, 0xf9df29b0, 0x6a0271f8, 0xeee941f6, 0xbacf5305, 0x3e24630b, 0xc7fb4abb, 0x43107ab5, 0x17366846, 0x93dd5848, 0x4ff1b991, 0xcb1a899f, 0x9f3c9b6c, 0x1bd7ab62, 0xe20882d2, 0x66e3b2dc, 0x32c5a02f, 0xb62e9021, 0x25f3c869, 0xa118f867, 0xf53eea94, 0x71d5da9a, 0x880af32a, 0x0ce1c324, 0x58c7d1d7, 0xdc2ce1d9, 0x2c52f28c, 0xa8b9c282, 0xfc9fd071, 0x7874e07f, 0x81abc9cf, 0x0540f9c1, 0x5166eb32, 0xd58ddb3c, 0x46508374, 0xc2bbb37a, 0x969da189, 0x12769187, 0xeba9b837, 0x6f428839, 0x3b649aca, 0xbf8faac4, 0x63a34b1d, 0xe7487b13, 0xb36e69e0, 0x378559ee, 0xce5a705e, 0x4ab14050, 0x1e9752a3, 0x9a7c62ad, 0x09a13ae5, 0x8d4a0aeb, 0xd96c1818, 0x5d872816, 0xa45801a6, 0x20b331a8, 0x7495235b, 0xf07e1355, 0x01016234, 0x85ea523a, 0xd1cc40c9, 0x552770c7, 0xacf85977, 0x28136979, 0x7c357b8a, 0xf8de4b84, 0x6b0313cc, 0xefe823c2, 0xbbce3131, 0x3f25013f, 0xc6fa288f, 0x42111881, 0x16370a72, 0x92dc3a7c, 0x4ef0dba5, 0xca1bebab, 0x9e3df958, 0x1ad6c956, 0xe309e0e6, 0x67e2d0e8, 0x33c4c21b, 0xb72ff215, 0x24f2aa5d, 0xa0199a53, 0xf43f88a0, 0x70d4b8ae, 0x890b911e, 0x0de0a110, 0x59c6b3e3, 0xdd2d83ed, 0x2d5390b8, 0xa9b8a0b6, 0xfd9eb245, 0x7975824b, 0x80aaabfb, 0x04419bf5, 0x50678906, 0xd48cb908, 0x4751e140, 0xc3bad14e, 0x979cc3bd, 0x1377f3b3, 0xeaa8da03, 0x6e43ea0d, 0x3a65f8fe, 0xbe8ec8f0, 0x62a22929, 0xe6491927, 0xb26f0bd4, 0x36843bda, 0xcf5b126a, 0x4bb02264, 0x1f963097, 0x9b7d0099, 0x08a058d1, 0x8c4b68df, 0xd86d7a2c, 0x5c864a22, 0xa5596392, 0x21b2539c, 0x7594416f, 0xf17f7161, 0x51c290d3, 0xd529a0dd, 0x810fb22e, 0x05e48220, 0xfc3bab90, 0x78d09b9e, 0x2cf6896d, 0xa81db963, 0x3bc0e12b, 0xbf2bd125, 0xeb0dc3d6, 0x6fe6f3d8, 0x9639da68, 0x12d2ea66, 0x46f4f895, 0xc21fc89b, 0x1e332942, 0x9ad8194c, 0xcefe0bbf, 0x4a153bb1, 0xb3ca1201, 0x3721220f, 0x630730fc, 0xe7ec00f2, 0x743158ba, 0xf0da68b4, 0xa4fc7a47, 0x20174a49, 0xd9c863f9, 0x5d2353f7, 0x09054104, 0x8dee710a, 0x7d90625f, 0xf97b5251, 0xad5d40a2, 0x29b670ac, 0xd069591c, 0x54826912, 0x00a47be1, 0x844f4bef, 0x179213a7, 0x937923a9, 0xc75f315a, 0x43b40154, 0xba6b28e4, 0x3e8018ea, 0x6aa60a19, 0xee4d3a17, 0x3261dbce, 0xb68aebc0, 0xe2acf933, 0x6647c93d, 0x9f98e08d, 0x1b73d083, 0x4f55c270, 0xcbbef27e, 0x5863aa36, 0xdc889a38, 0x88ae88cb, 0x0c45b8c5, 0xf59a9175, 0x7171a17b, 0x2557b388, 0xa1bc8386, 0x50c3f2e7, 0xd428c2e9, 0x800ed01a, 0x04e5e014, 0xfd3ac9a4, 0x79d1f9aa, 0x2df7eb59, 0xa91cdb57, 0x3ac1831f, 0xbe2ab311, 0xea0ca1e2, 0x6ee791ec, 0x9738b85c, 0x13d38852, 0x47f59aa1, 0xc31eaaaf, 0x1f324b76, 0x9bd97b78, 0xcfff698b, 0x4b145985, 0xb2cb7035, 0x3620403b, 0x620652c8, 0xe6ed62c6, 0x75303a8e, 0xf1db0a80, 0xa5fd1873, 0x2116287d, 0xd8c901cd, 0x5c2231c3, 0x08042330, 0x8cef133e, 0x7c91006b, 0xf87a3065, 0xac5c2296, 0x28b71298, 0xd1683b28, 0x55830b26, 0x01a519d5, 0x854e29db, 0x16937193, 0x9278419d, 0xc65e536e, 0x42b56360, 0xbb6a4ad0, 0x3f817ade, 0x6ba7682d, 0xef4c5823, 0x3360b9fa, 0xb78b89f4, 0xe3ad9b07, 0x6746ab09, 0x9e9982b9, 0x1a72b2b7, 0x4e54a044, 0xcabf904a, 0x5962c802, 0xdd89f80c, 0x89afeaff, 0x0d44daf1, 0xf49bf341, 0x7070c34f, 0x2456d1bc, 0xa0bde1b2 +}, +{ +0x00000000, 0xa3d4c67e, 0xd50f8353, 0x76db452d, 0xd485c496, 0x775102e8, 0x018a47c5, 0xa25e81bb, 0x5f071537, 0xfcd3d349, 0x8a089664, 0x29dc501a, 0x8b82d1a1, 0x285617df, 0x5e8d52f2, 0xfd59948c, 0x6aefc8bc, 0xc93b0ec2, 0xbfe04bef, 0x1c348d91, 0xbe6a0c2a, 0x1dbeca54, 0x6b658f79, 0xc8b14907, 0x35e8dd8b, 0x963c1bf5, 0xe0e75ed8, 0x433398a6, 0xe16d191d, 0x42b9df63, 0x34629a4e, 0x97b65c30, 0x73c4c835, 0xd0100e4b, 0xa6cb4b66, 0x051f8d18, 0xa7410ca3, 0x0495cadd, 0x724e8ff0, 0xd19a498e, 0x2cc3dd02, 0x8f171b7c, 0xf9cc5e51, 0x5a18982f, 0xf8461994, 0x5b92dfea, 0x2d499ac7, 0x8e9d5cb9, 0x192b0089, 0xbaffc6f7, 0xcc2483da, 0x6ff045a4, 0xcdaec41f, 0x6e7a0261, 0x18a1474c, 0xbb758132, 0x462c15be, 0xe5f8d3c0, 0x932396ed, 0x30f75093, 0x92a9d128, 0x317d1756, 0x47a6527b, 0xe4729405, 0x2b19340f, 0x88cdf271, 0xfe16b75c, 0x5dc27122, 0xff9cf099, 0x5c4836e7, 0x2a9373ca, 0x8947b5b4, 0x741e2138, 0xd7cae746, 0xa111a26b, 0x02c56415, 0xa09be5ae, 0x034f23d0, 0x759466fd, 0xd640a083, 0x41f6fcb3, 0xe2223acd, 0x94f97fe0, 0x372db99e, 0x95733825, 0x36a7fe5b, 0x407cbb76, 0xe3a87d08, 0x1ef1e984, 0xbd252ffa, 0xcbfe6ad7, 0x682aaca9, 0xca742d12, 0x69a0eb6c, 0x1f7bae41, 0xbcaf683f, 0x58ddfc3a, 0xfb093a44, 0x8dd27f69, 0x2e06b917, 0x8c5838ac, 0x2f8cfed2, 0x5957bbff, 0xfa837d81, 0x07dae90d, 0xa40e2f73, 0xd2d56a5e, 0x7101ac20, 0xd35f2d9b, 0x708bebe5, 0x0650aec8, 0xa58468b6, 0x32323486, 0x91e6f2f8, 0xe73db7d5, 0x44e971ab, 0xe6b7f010, 0x4563366e, 0x33b87343, 0x906cb53d, 0x6d3521b1, 0xcee1e7cf, 0xb83aa2e2, 0x1bee649c, 0xb9b0e527, 0x1a642359, 0x6cbf6674, 0xcf6ba00a, 0x396b508a, 0x9abf96f4, 0xec64d3d9, 0x4fb015a7, 0xedee941c, 0x4e3a5262, 0x38e1174f, 0x9b35d131, 0x666c45bd, 0xc5b883c3, 0xb363c6ee, 0x10b70090, 0xb2e9812b, 0x113d4755, 0x67e60278, 0xc432c406, 0x53849836, 0xf0505e48, 0x868b1b65, 0x255fdd1b, 0x87015ca0, 0x24d59ade, 0x520edff3, 0xf1da198d, 0x0c838d01, 0xaf574b7f, 0xd98c0e52, 0x7a58c82c, 0xd8064997, 0x7bd28fe9, 0x0d09cac4, 0xaedd0cba, 0x4aaf98bf, 0xe97b5ec1, 0x9fa01bec, 0x3c74dd92, 0x9e2a5c29, 0x3dfe9a57, 0x4b25df7a, 0xe8f11904, 0x15a88d88, 0xb67c4bf6, 0xc0a70edb, 0x6373c8a5, 0xc12d491e, 0x62f98f60, 0x1422ca4d, 0xb7f60c33, 0x20405003, 0x8394967d, 0xf54fd350, 0x569b152e, 0xf4c59495, 0x571152eb, 0x21ca17c6, 0x821ed1b8, 0x7f474534, 0xdc93834a, 0xaa48c667, 0x099c0019, 0xabc281a2, 0x081647dc, 0x7ecd02f1, 0xdd19c48f, 0x12726485, 0xb1a6a2fb, 0xc77de7d6, 0x64a921a8, 0xc6f7a013, 0x6523666d, 0x13f82340, 0xb02ce53e, 0x4d7571b2, 0xeea1b7cc, 0x987af2e1, 0x3bae349f, 0x99f0b524, 0x3a24735a, 0x4cff3677, 0xef2bf009, 0x789dac39, 0xdb496a47, 0xad922f6a, 0x0e46e914, 0xac1868af, 0x0fccaed1, 0x7917ebfc, 0xdac32d82, 0x279ab90e, 0x844e7f70, 0xf2953a5d, 0x5141fc23, 0xf31f7d98, 0x50cbbbe6, 0x2610fecb, 0x85c438b5, 0x61b6acb0, 0xc2626ace, 0xb4b92fe3, 0x176de99d, 0xb5336826, 0x16e7ae58, 0x603ceb75, 0xc3e82d0b, 0x3eb1b987, 0x9d657ff9, 0xebbe3ad4, 0x486afcaa, 0xea347d11, 0x49e0bb6f, 0x3f3bfe42, 0x9cef383c, 0x0b59640c, 0xa88da272, 0xde56e75f, 0x7d822121, 0xdfdca09a, 0x7c0866e4, 0x0ad323c9, 0xa907e5b7, 0x545e713b, 0xf78ab745, 0x8151f268, 0x22853416, 0x80dbb5ad, 0x230f73d3, 0x55d436fe, 0xf600f080 +}, +{ +0x00000000, 0xbcfefe30, 0x2c72f9f4, 0x908c07c4, 0x279ab03a, 0x9b644e0a, 0x0be849ce, 0xb716b7fe, 0xc0e0e0e4, 0x7c1e1ed4, 0xec921910, 0x506ce720, 0xe77a50de, 0x5b84aeee, 0xcb08a92a, 0x77f6571a, 0x31059d38, 0x8dfb6308, 0x1d7764cc, 0xa1899afc, 0x169f2d02, 0xaa61d332, 0x3aedd4f6, 0x86132ac6, 0xf1e57ddc, 0x4d1b83ec, 0xdd978428, 0x61697a18, 0xd67fcde6, 0x6a8133d6, 0xfa0d3412, 0x46f3ca22, 0xffb18bd7, 0x434f75e7, 0xd3c37223, 0x6f3d8c13, 0xd82b3bed, 0x64d5c5dd, 0xf459c219, 0x48a73c29, 0x3f516b33, 0x83af9503, 0x132392c7, 0xafdd6cf7, 0x18cbdb09, 0xa4352539, 0x34b922fd, 0x8847dccd, 0xceb416ef, 0x724ae8df, 0xe2c6ef1b, 0x5e38112b, 0xe92ea6d5, 0x55d058e5, 0xc55c5f21, 0x79a2a111, 0x0e54f60b, 0xb2aa083b, 0x22260fff, 0x9ed8f1cf, 0x29ce4631, 0x9530b801, 0x05bcbfc5, 0xb94241f5, 0x5e2ac47e, 0xe2d43a4e, 0x72583d8a, 0xcea6c3ba, 0x79b07444, 0xc54e8a74, 0x55c28db0, 0xe93c7380, 0x9eca249a, 0x2234daaa, 0xb2b8dd6e, 0x0e46235e, 0xb95094a0, 0x05ae6a90, 0x95226d54, 0x29dc9364, 0x6f2f5946, 0xd3d1a776, 0x435da0b2, 0xffa35e82, 0x48b5e97c, 0xf44b174c, 0x64c71088, 0xd839eeb8, 0xafcfb9a2, 0x13314792, 0x83bd4056, 0x3f43be66, 0x88550998, 0x34abf7a8, 0xa427f06c, 0x18d90e5c, 0xa19b4fa9, 0x1d65b199, 0x8de9b65d, 0x3117486d, 0x8601ff93, 0x3aff01a3, 0xaa730667, 0x168df857, 0x617baf4d, 0xdd85517d, 0x4d0956b9, 0xf1f7a889, 0x46e11f77, 0xfa1fe147, 0x6a93e683, 0xd66d18b3, 0x909ed291, 0x2c602ca1, 0xbcec2b65, 0x0012d555, 0xb70462ab, 0x0bfa9c9b, 0x9b769b5f, 0x2788656f, 0x507e3275, 0xec80cc45, 0x7c0ccb81, 0xc0f235b1, 0x77e4824f, 0xcb1a7c7f, 0x5b967bbb, 0xe768858b, 0x3816c052, 0x84e83e62, 0x146439a6, 0xa89ac796, 0x1f8c7068, 0xa3728e58, 0x33fe899c, 0x8f0077ac, 0xf8f620b6, 0x4408de86, 0xd484d942, 0x687a2772, 0xdf6c908c, 0x63926ebc, 0xf31e6978, 0x4fe09748, 0x09135d6a, 0xb5eda35a, 0x2561a49e, 0x999f5aae, 0x2e89ed50, 0x92771360, 0x02fb14a4, 0xbe05ea94, 0xc9f3bd8e, 0x750d43be, 0xe581447a, 0x597fba4a, 0xee690db4, 0x5297f384, 0xc21bf440, 0x7ee50a70, 0xc7a74b85, 0x7b59b5b5, 0xebd5b271, 0x572b4c41, 0xe03dfbbf, 0x5cc3058f, 0xcc4f024b, 0x70b1fc7b, 0x0747ab61, 0xbbb95551, 0x2b355295, 0x97cbaca5, 0x20dd1b5b, 0x9c23e56b, 0x0cafe2af, 0xb0511c9f, 0xf6a2d6bd, 0x4a5c288d, 0xdad02f49, 0x662ed179, 0xd1386687, 0x6dc698b7, 0xfd4a9f73, 0x41b46143, 0x36423659, 0x8abcc869, 0x1a30cfad, 0xa6ce319d, 0x11d88663, 0xad267853, 0x3daa7f97, 0x815481a7, 0x663c042c, 0xdac2fa1c, 0x4a4efdd8, 0xf6b003e8, 0x41a6b416, 0xfd584a26, 0x6dd44de2, 0xd12ab3d2, 0xa6dce4c8, 0x1a221af8, 0x8aae1d3c, 0x3650e30c, 0x814654f2, 0x3db8aac2, 0xad34ad06, 0x11ca5336, 0x57399914, 0xebc76724, 0x7b4b60e0, 0xc7b59ed0, 0x70a3292e, 0xcc5dd71e, 0x5cd1d0da, 0xe02f2eea, 0x97d979f0, 0x2b2787c0, 0xbbab8004, 0x07557e34, 0xb043c9ca, 0x0cbd37fa, 0x9c31303e, 0x20cfce0e, 0x998d8ffb, 0x257371cb, 0xb5ff760f, 0x0901883f, 0xbe173fc1, 0x02e9c1f1, 0x9265c635, 0x2e9b3805, 0x596d6f1f, 0xe593912f, 0x751f96eb, 0xc9e168db, 0x7ef7df25, 0xc2092115, 0x528526d1, 0xee7bd8e1, 0xa88812c3, 0x1476ecf3, 0x84faeb37, 0x38041507, 0x8f12a2f9, 0x33ec5cc9, 0xa3605b0d, 0x1f9ea53d, 0x6868f227, 0xd4960c17, 0x441a0bd3, 0xf8e4f5e3, 0x4ff2421d, 0xf30cbc2d, 0x6380bbe9, 0xdf7e45d9 +}, +{ +0x00000000, 0x5de8ef3b, 0x13399e92, 0x4ed171a9, 0x35abf931, 0x6843160a, 0x269267a3, 0x7b7a8898, 0x93c50fd8, 0xce2de0e3, 0x80fc914a, 0xdd147e71, 0xa66ef6e9, 0xfb8619d2, 0xb557687b, 0xe8bf8740, 0x9e32fbfd, 0xc3da14c6, 0x8d0b656f, 0xd0e38a54, 0xab9902cc, 0xf671edf7, 0xb8a09c5e, 0xe5487365, 0x0df7f425, 0x501f1b1e, 0x1ece6ab7, 0x4326858c, 0x385c0d14, 0x65b4e22f, 0x2b659386, 0x768d7cbd, 0x551c61fa, 0x08f48ec1, 0x4625ff68, 0x1bcd1053, 0x60b798cb, 0x3d5f77f0, 0x738e0659, 0x2e66e962, 0xc6d96e22, 0x9b318119, 0xd5e0f0b0, 0x88081f8b, 0xf3729713, 0xae9a7828, 0xe04b0981, 0xbda3e6ba, 0xcb2e9a07, 0x96c6753c, 0xd8170495, 0x85ffebae, 0xfe856336, 0xa36d8c0d, 0xedbcfda4, 0xb054129f, 0x58eb95df, 0x05037ae4, 0x4bd20b4d, 0x163ae476, 0x6d406cee, 0x30a883d5, 0x7e79f27c, 0x23911d47, 0xd8635442, 0x858bbb79, 0xcb5acad0, 0x96b225eb, 0xedc8ad73, 0xb0204248, 0xfef133e1, 0xa319dcda, 0x4ba65b9a, 0x164eb4a1, 0x589fc508, 0x05772a33, 0x7e0da2ab, 0x23e54d90, 0x6d343c39, 0x30dcd302, 0x4651afbf, 0x1bb94084, 0x5568312d, 0x0880de16, 0x73fa568e, 0x2e12b9b5, 0x60c3c81c, 0x3d2b2727, 0xd594a067, 0x887c4f5c, 0xc6ad3ef5, 0x9b45d1ce, 0xe03f5956, 0xbdd7b66d, 0xf306c7c4, 0xaeee28ff, 0x8d7f35b8, 0xd097da83, 0x9e46ab2a, 0xc3ae4411, 0xb8d4cc89, 0xe53c23b2, 0xabed521b, 0xf605bd20, 0x1eba3a60, 0x4352d55b, 0x0d83a4f2, 0x506b4bc9, 0x2b11c351, 0x76f92c6a, 0x38285dc3, 0x65c0b2f8, 0x134dce45, 0x4ea5217e, 0x007450d7, 0x5d9cbfec, 0x26e63774, 0x7b0ed84f, 0x35dfa9e6, 0x683746dd, 0x8088c19d, 0xdd602ea6, 0x93b15f0f, 0xce59b034, 0xb52338ac, 0xe8cbd797, 0xa61aa63e, 0xfbf24905, 0x1074a404, 0x4d9c4b3f, 0x034d3a96, 0x5ea5d5ad, 0x25df5d35, 0x7837b20e, 0x36e6c3a7, 0x6b0e2c9c, 0x83b1abdc, 0xde5944e7, 0x9088354e, 0xcd60da75, 0xb61a52ed, 0xebf2bdd6, 0xa523cc7f, 0xf8cb2344, 0x8e465ff9, 0xd3aeb0c2, 0x9d7fc16b, 0xc0972e50, 0xbbeda6c8, 0xe60549f3, 0xa8d4385a, 0xf53cd761, 0x1d835021, 0x406bbf1a, 0x0ebaceb3, 0x53522188, 0x2828a910, 0x75c0462b, 0x3b113782, 0x66f9d8b9, 0x4568c5fe, 0x18802ac5, 0x56515b6c, 0x0bb9b457, 0x70c33ccf, 0x2d2bd3f4, 0x63faa25d, 0x3e124d66, 0xd6adca26, 0x8b45251d, 0xc59454b4, 0x987cbb8f, 0xe3063317, 0xbeeedc2c, 0xf03fad85, 0xadd742be, 0xdb5a3e03, 0x86b2d138, 0xc863a091, 0x958b4faa, 0xeef1c732, 0xb3192809, 0xfdc859a0, 0xa020b69b, 0x489f31db, 0x1577dee0, 0x5ba6af49, 0x064e4072, 0x7d34c8ea, 0x20dc27d1, 0x6e0d5678, 0x33e5b943, 0xc817f046, 0x95ff1f7d, 0xdb2e6ed4, 0x86c681ef, 0xfdbc0977, 0xa054e64c, 0xee8597e5, 0xb36d78de, 0x5bd2ff9e, 0x063a10a5, 0x48eb610c, 0x15038e37, 0x6e7906af, 0x3391e994, 0x7d40983d, 0x20a87706, 0x56250bbb, 0x0bcde480, 0x451c9529, 0x18f47a12, 0x638ef28a, 0x3e661db1, 0x70b76c18, 0x2d5f8323, 0xc5e00463, 0x9808eb58, 0xd6d99af1, 0x8b3175ca, 0xf04bfd52, 0xada31269, 0xe37263c0, 0xbe9a8cfb, 0x9d0b91bc, 0xc0e37e87, 0x8e320f2e, 0xd3dae015, 0xa8a0688d, 0xf54887b6, 0xbb99f61f, 0xe6711924, 0x0ece9e64, 0x5326715f, 0x1df700f6, 0x401fefcd, 0x3b656755, 0x668d886e, 0x285cf9c7, 0x75b416fc, 0x03396a41, 0x5ed1857a, 0x1000f4d3, 0x4de81be8, 0x36929370, 0x6b7a7c4b, 0x25ab0de2, 0x7843e2d9, 0x90fc6599, 0xcd148aa2, 0x83c5fb0b, 0xde2d1430, 0xa5579ca8, 0xf8bf7393, 0xb66e023a, 0xeb86ed01 +}, +{ +0x00000000, 0xd610dc94, 0x5116beb1, 0x87066225, 0xd338010a, 0x0528dd9e, 0x822ebfbb, 0x543e632f, 0x128ed4c4, 0xc49e0850, 0x43986a75, 0x9588b6e1, 0xc1b6d5ce, 0x17a6095a, 0x90a06b7f, 0x46b0b7eb, 0x7dc413d8, 0xabd4cf4c, 0x2cd2ad69, 0xfac271fd, 0xaefc12d2, 0x78ecce46, 0xffeaac63, 0x29fa70f7, 0x6f4ac71c, 0xb95a1b88, 0x3e5c79ad, 0xe84ca539, 0xbc72c616, 0x6a621a82, 0xed6478a7, 0x3b74a433, 0x4f1ce06f, 0x990c3cfb, 0x1e0a5ede, 0xc81a824a, 0x9c24e165, 0x4a343df1, 0xcd325fd4, 0x1b228340, 0x5d9234ab, 0x8b82e83f, 0x0c848a1a, 0xda94568e, 0x8eaa35a1, 0x58bae935, 0xdfbc8b10, 0x09ac5784, 0x32d8f3b7, 0xe4c82f23, 0x63ce4d06, 0xb5de9192, 0xe1e0f2bd, 0x37f02e29, 0xb0f64c0c, 0x66e69098, 0x20562773, 0xf646fbe7, 0x714099c2, 0xa7504556, 0xf36e2679, 0x257efaed, 0xa27898c8, 0x7468445c, 0xd1787888, 0x0768a41c, 0x806ec639, 0x567e1aad, 0x02407982, 0xd450a516, 0x5356c733, 0x85461ba7, 0xc3f6ac4c, 0x15e670d8, 0x92e012fd, 0x44f0ce69, 0x10cead46, 0xc6de71d2, 0x41d813f7, 0x97c8cf63, 0xacbc6b50, 0x7aacb7c4, 0xfdaad5e1, 0x2bba0975, 0x7f846a5a, 0xa994b6ce, 0x2e92d4eb, 0xf882087f, 0xbe32bf94, 0x68226300, 0xef240125, 0x3934ddb1, 0x6d0abe9e, 0xbb1a620a, 0x3c1c002f, 0xea0cdcbb, 0x9e6498e7, 0x48744473, 0xcf722656, 0x1962fac2, 0x4d5c99ed, 0x9b4c4579, 0x1c4a275c, 0xca5afbc8, 0x8cea4c23, 0x5afa90b7, 0xddfcf292, 0x0bec2e06, 0x5fd24d29, 0x89c291bd, 0x0ec4f398, 0xd8d42f0c, 0xe3a08b3f, 0x35b057ab, 0xb2b6358e, 0x64a6e91a, 0x30988a35, 0xe68856a1, 0x618e3484, 0xb79ee810, 0xf12e5ffb, 0x273e836f, 0xa038e14a, 0x76283dde, 0x22165ef1, 0xf4068265, 0x7300e040, 0xa5103cd4, 0x29ea94b0, 0xfffa4824, 0x78fc2a01, 0xaeecf695, 0xfad295ba, 0x2cc2492e, 0xabc42b0b, 0x7dd4f79f, 0x3b644074, 0xed749ce0, 0x6a72fec5, 0xbc622251, 0xe85c417e, 0x3e4c9dea, 0xb94affcf, 0x6f5a235b, 0x542e8768, 0x823e5bfc, 0x053839d9, 0xd328e54d, 0x87168662, 0x51065af6, 0xd60038d3, 0x0010e447, 0x46a053ac, 0x90b08f38, 0x17b6ed1d, 0xc1a63189, 0x959852a6, 0x43888e32, 0xc48eec17, 0x129e3083, 0x66f674df, 0xb0e6a84b, 0x37e0ca6e, 0xe1f016fa, 0xb5ce75d5, 0x63dea941, 0xe4d8cb64, 0x32c817f0, 0x7478a01b, 0xa2687c8f, 0x256e1eaa, 0xf37ec23e, 0xa740a111, 0x71507d85, 0xf6561fa0, 0x2046c334, 0x1b326707, 0xcd22bb93, 0x4a24d9b6, 0x9c340522, 0xc80a660d, 0x1e1aba99, 0x991cd8bc, 0x4f0c0428, 0x09bcb3c3, 0xdfac6f57, 0x58aa0d72, 0x8ebad1e6, 0xda84b2c9, 0x0c946e5d, 0x8b920c78, 0x5d82d0ec, 0xf892ec38, 0x2e8230ac, 0xa9845289, 0x7f948e1d, 0x2baaed32, 0xfdba31a6, 0x7abc5383, 0xacac8f17, 0xea1c38fc, 0x3c0ce468, 0xbb0a864d, 0x6d1a5ad9, 0x392439f6, 0xef34e562, 0x68328747, 0xbe225bd3, 0x8556ffe0, 0x53462374, 0xd4404151, 0x02509dc5, 0x566efeea, 0x807e227e, 0x0778405b, 0xd1689ccf, 0x97d82b24, 0x41c8f7b0, 0xc6ce9595, 0x10de4901, 0x44e02a2e, 0x92f0f6ba, 0x15f6949f, 0xc3e6480b, 0xb78e0c57, 0x619ed0c3, 0xe698b2e6, 0x30886e72, 0x64b60d5d, 0xb2a6d1c9, 0x35a0b3ec, 0xe3b06f78, 0xa500d893, 0x73100407, 0xf4166622, 0x2206bab6, 0x7638d999, 0xa028050d, 0x272e6728, 0xf13ebbbc, 0xca4a1f8f, 0x1c5ac31b, 0x9b5ca13e, 0x4d4c7daa, 0x19721e85, 0xcf62c211, 0x4864a034, 0x9e747ca0, 0xd8c4cb4b, 0x0ed417df, 0x89d275fa, 0x5fc2a96e, 0x0bfcca41, 0xddec16d5, 0x5aea74f0, 0x8cfaa864 +}, +{ +0x00000000, 0x95bca644, 0xdd636f8e, 0x48dfc9ca, 0x12aa7483, 0x8716d2c7, 0xcfc91b0d, 0x5a75bd49, 0x894ed71b, 0x1cf2715f, 0x542db895, 0xc1911ed1, 0x9be4a398, 0x0e5805dc, 0x4687cc16, 0xd33b6a52, 0xbc325c56, 0x298efa12, 0x615133d8, 0xf4ed959c, 0xae9828d5, 0x3b248e91, 0x73fb475b, 0xe647e11f, 0x357c8b4d, 0xa0c02d09, 0xe81fe4c3, 0x7da34287, 0x27d6ffce, 0xb26a598a, 0xfab59040, 0x6f093604, 0xdb3b49ad, 0x4e87efe9, 0x06582623, 0x93e48067, 0xc9913d2e, 0x5c2d9b6a, 0x14f252a0, 0x814ef4e4, 0x52759eb6, 0xc7c938f2, 0x8f16f138, 0x1aaa577c, 0x40dfea35, 0xd5634c71, 0x9dbc85bb, 0x080023ff, 0x670915fb, 0xf2b5b3bf, 0xba6a7a75, 0x2fd6dc31, 0x75a36178, 0xe01fc73c, 0xa8c00ef6, 0x3d7ca8b2, 0xee47c2e0, 0x7bfb64a4, 0x3324ad6e, 0xa6980b2a, 0xfcedb663, 0x69511027, 0x218ed9ed, 0xb4327fa9, 0x31b1274e, 0xa40d810a, 0xecd248c0, 0x796eee84, 0x231b53cd, 0xb6a7f589, 0xfe783c43, 0x6bc49a07, 0xb8fff055, 0x2d435611, 0x659c9fdb, 0xf020399f, 0xaa5584d6, 0x3fe92292, 0x7736eb58, 0xe28a4d1c, 0x8d837b18, 0x183fdd5c, 0x50e01496, 0xc55cb2d2, 0x9f290f9b, 0x0a95a9df, 0x424a6015, 0xd7f6c651, 0x04cdac03, 0x91710a47, 0xd9aec38d, 0x4c1265c9, 0x1667d880, 0x83db7ec4, 0xcb04b70e, 0x5eb8114a, 0xea8a6ee3, 0x7f36c8a7, 0x37e9016d, 0xa255a729, 0xf8201a60, 0x6d9cbc24, 0x254375ee, 0xb0ffd3aa, 0x63c4b9f8, 0xf6781fbc, 0xbea7d676, 0x2b1b7032, 0x716ecd7b, 0xe4d26b3f, 0xac0da2f5, 0x39b104b1, 0x56b832b5, 0xc30494f1, 0x8bdb5d3b, 0x1e67fb7f, 0x44124636, 0xd1aee072, 0x997129b8, 0x0ccd8ffc, 0xdff6e5ae, 0x4a4a43ea, 0x02958a20, 0x97292c64, 0xcd5c912d, 0x58e03769, 0x103ffea3, 0x858358e7, 0x88d13c70, 0x1d6d9a34, 0x55b253fe, 0xc00ef5ba, 0x9a7b48f3, 0x0fc7eeb7, 0x4718277d, 0xd2a48139, 0x019feb6b, 0x94234d2f, 0xdcfc84e5, 0x494022a1, 0x13359fe8, 0x868939ac, 0xce56f066, 0x5bea5622, 0x34e36026, 0xa15fc662, 0xe9800fa8, 0x7c3ca9ec, 0x264914a5, 0xb3f5b2e1, 0xfb2a7b2b, 0x6e96dd6f, 0xbdadb73d, 0x28111179, 0x60ced8b3, 0xf5727ef7, 0xaf07c3be, 0x3abb65fa, 0x7264ac30, 0xe7d80a74, 0x53ea75dd, 0xc656d399, 0x8e891a53, 0x1b35bc17, 0x4140015e, 0xd4fca71a, 0x9c236ed0, 0x099fc894, 0xdaa4a2c6, 0x4f180482, 0x07c7cd48, 0x927b6b0c, 0xc80ed645, 0x5db27001, 0x156db9cb, 0x80d11f8f, 0xefd8298b, 0x7a648fcf, 0x32bb4605, 0xa707e041, 0xfd725d08, 0x68cefb4c, 0x20113286, 0xb5ad94c2, 0x6696fe90, 0xf32a58d4, 0xbbf5911e, 0x2e49375a, 0x743c8a13, 0xe1802c57, 0xa95fe59d, 0x3ce343d9, 0xb9601b3e, 0x2cdcbd7a, 0x640374b0, 0xf1bfd2f4, 0xabca6fbd, 0x3e76c9f9, 0x76a90033, 0xe315a677, 0x302ecc25, 0xa5926a61, 0xed4da3ab, 0x78f105ef, 0x2284b8a6, 0xb7381ee2, 0xffe7d728, 0x6a5b716c, 0x05524768, 0x90eee12c, 0xd83128e6, 0x4d8d8ea2, 0x17f833eb, 0x824495af, 0xca9b5c65, 0x5f27fa21, 0x8c1c9073, 0x19a03637, 0x517ffffd, 0xc4c359b9, 0x9eb6e4f0, 0x0b0a42b4, 0x43d58b7e, 0xd6692d3a, 0x625b5293, 0xf7e7f4d7, 0xbf383d1d, 0x2a849b59, 0x70f12610, 0xe54d8054, 0xad92499e, 0x382eefda, 0xeb158588, 0x7ea923cc, 0x3676ea06, 0xa3ca4c42, 0xf9bff10b, 0x6c03574f, 0x24dc9e85, 0xb16038c1, 0xde690ec5, 0x4bd5a881, 0x030a614b, 0x96b6c70f, 0xccc37a46, 0x597fdc02, 0x11a015c8, 0x841cb38c, 0x5727d9de, 0xc29b7f9a, 0x8a44b650, 0x1ff81014, 0x458dad5d, 0xd0310b19, 0x98eec2d3, 0x0d526497 +}, +{ +0x00000000, 0x4b3f6445, 0x3c37ff77, 0x77089b32, 0x72b65dfd, 0x398939b8, 0x4e81a28a, 0x05bec6cf, 0xaec18132, 0xe5fee577, 0x92f67e45, 0xd9c91a00, 0xdc77dccf, 0x9748b88a, 0xe04023b8, 0xab7f47fd, 0xd82c407e, 0x9313243b, 0xe41bbf09, 0xaf24db4c, 0xaa9a1d83, 0xe1a579c6, 0x96ade2f4, 0xdd9286b1, 0x76edc14c, 0x3dd2a509, 0x4ada3e3b, 0x01e55a7e, 0x045b9cb1, 0x4f64f8f4, 0x386c63c6, 0x73530783, 0x69abfd8b, 0x229499ce, 0x559c02fc, 0x1ea366b9, 0x1b1da076, 0x5022c433, 0x272a5f01, 0x6c153b44, 0xc76a7cb9, 0x8c5518fc, 0xfb5d83ce, 0xb062e78b, 0xb5dc2144, 0xfee34501, 0x89ebde33, 0xc2d4ba76, 0xb187bdf5, 0xfab8d9b0, 0x8db04282, 0xc68f26c7, 0xc331e008, 0x880e844d, 0xff061f7f, 0xb4397b3a, 0x1f463cc7, 0x54795882, 0x2371c3b0, 0x684ea7f5, 0x6df0613a, 0x26cf057f, 0x51c79e4d, 0x1af8fa08, 0x0568062b, 0x4e57626e, 0x395ff95c, 0x72609d19, 0x77de5bd6, 0x3ce13f93, 0x4be9a4a1, 0x00d6c0e4, 0xaba98719, 0xe096e35c, 0x979e786e, 0xdca11c2b, 0xd91fdae4, 0x9220bea1, 0xe5282593, 0xae1741d6, 0xdd444655, 0x967b2210, 0xe173b922, 0xaa4cdd67, 0xaff21ba8, 0xe4cd7fed, 0x93c5e4df, 0xd8fa809a, 0x7385c767, 0x38baa322, 0x4fb23810, 0x048d5c55, 0x01339a9a, 0x4a0cfedf, 0x3d0465ed, 0x763b01a8, 0x6cc3fba0, 0x27fc9fe5, 0x50f404d7, 0x1bcb6092, 0x1e75a65d, 0x554ac218, 0x2242592a, 0x697d3d6f, 0xc2027a92, 0x893d1ed7, 0xfe3585e5, 0xb50ae1a0, 0xb0b4276f, 0xfb8b432a, 0x8c83d818, 0xc7bcbc5d, 0xb4efbbde, 0xffd0df9b, 0x88d844a9, 0xc3e720ec, 0xc659e623, 0x8d668266, 0xfa6e1954, 0xb1517d11, 0x1a2e3aec, 0x51115ea9, 0x2619c59b, 0x6d26a1de, 0x68986711, 0x23a70354, 0x54af9866, 0x1f90fc23, 0x25b7186a, 0x6e887c2f, 0x1980e71d, 0x52bf8358, 0x57014597, 0x1c3e21d2, 0x6b36bae0, 0x2009dea5, 0x8b769958, 0xc049fd1d, 0xb741662f, 0xfc7e026a, 0xf9c0c4a5, 0xb2ffa0e0, 0xc5f73bd2, 0x8ec85f97, 0xfd9b5814, 0xb6a43c51, 0xc1aca763, 0x8a93c326, 0x8f2d05e9, 0xc41261ac, 0xb31afa9e, 0xf8259edb, 0x535ad926, 0x1865bd63, 0x6f6d2651, 0x24524214, 0x21ec84db, 0x6ad3e09e, 0x1ddb7bac, 0x56e41fe9, 0x4c1ce5e1, 0x072381a4, 0x702b1a96, 0x3b147ed3, 0x3eaab81c, 0x7595dc59, 0x029d476b, 0x49a2232e, 0xe2dd64d3, 0xa9e20096, 0xdeea9ba4, 0x95d5ffe1, 0x906b392e, 0xdb545d6b, 0xac5cc659, 0xe763a21c, 0x9430a59f, 0xdf0fc1da, 0xa8075ae8, 0xe3383ead, 0xe686f862, 0xadb99c27, 0xdab10715, 0x918e6350, 0x3af124ad, 0x71ce40e8, 0x06c6dbda, 0x4df9bf9f, 0x48477950, 0x03781d15, 0x74708627, 0x3f4fe262, 0x20df1e41, 0x6be07a04, 0x1ce8e136, 0x57d78573, 0x526943bc, 0x195627f9, 0x6e5ebccb, 0x2561d88e, 0x8e1e9f73, 0xc521fb36, 0xb2296004, 0xf9160441, 0xfca8c28e, 0xb797a6cb, 0xc09f3df9, 0x8ba059bc, 0xf8f35e3f, 0xb3cc3a7a, 0xc4c4a148, 0x8ffbc50d, 0x8a4503c2, 0xc17a6787, 0xb672fcb5, 0xfd4d98f0, 0x5632df0d, 0x1d0dbb48, 0x6a05207a, 0x213a443f, 0x248482f0, 0x6fbbe6b5, 0x18b37d87, 0x538c19c2, 0x4974e3ca, 0x024b878f, 0x75431cbd, 0x3e7c78f8, 0x3bc2be37, 0x70fdda72, 0x07f54140, 0x4cca2505, 0xe7b562f8, 0xac8a06bd, 0xdb829d8f, 0x90bdf9ca, 0x95033f05, 0xde3c5b40, 0xa934c072, 0xe20ba437, 0x9158a3b4, 0xda67c7f1, 0xad6f5cc3, 0xe6503886, 0xe3eefe49, 0xa8d19a0c, 0xdfd9013e, 0x94e6657b, 0x3f992286, 0x74a646c3, 0x03aeddf1, 0x4891b9b4, 0x4d2f7f7b, 0x06101b3e, 0x7118800c, 0x3a27e449 +}, +{ +0x00000000, 0xfe431425, 0x2ff27448, 0xd1b1606d, 0x7c577ee0, 0x82146ac5, 0x53a50aa8, 0xade61e8d, 0x7e5de3d3, 0x801ef7f6, 0x51af979b, 0xafec83be, 0x020a9d33, 0xfc498916, 0x2df8e97b, 0xd3bbfd5e, 0xdfe6c59b, 0x21a5d1be, 0xf014b1d3, 0x0e57a5f6, 0xa3b1bb7b, 0x5df2af5e, 0x8c43cf33, 0x7200db16, 0xa1bb2648, 0x5ff8326d, 0x8e495200, 0x700a4625, 0xddec58a8, 0x23af4c8d, 0xf21e2ce0, 0x0c5d38c5, 0xd4ff57df, 0x2abc43fa, 0xfb0d2397, 0x054e37b2, 0xa8a8293f, 0x56eb3d1a, 0x875a5d77, 0x79194952, 0xaaa2b40c, 0x54e1a029, 0x8550c044, 0x7b13d461, 0xd6f5caec, 0x28b6dec9, 0xf907bea4, 0x0744aa81, 0x0b199244, 0xf55a8661, 0x24ebe60c, 0xdaa8f229, 0x774eeca4, 0x890df881, 0x58bc98ec, 0xa6ff8cc9, 0x75447197, 0x8b0765b2, 0x5ab605df, 0xa4f511fa, 0x09130f77, 0xf7501b52, 0x26e17b3f, 0xd8a26f1a, 0x4a79e2ff, 0xb43af6da, 0x658b96b7, 0x9bc88292, 0x362e9c1f, 0xc86d883a, 0x19dce857, 0xe79ffc72, 0x3424012c, 0xca671509, 0x1bd67564, 0xe5956141, 0x48737fcc, 0xb6306be9, 0x67810b84, 0x99c21fa1, 0x959f2764, 0x6bdc3341, 0xba6d532c, 0x442e4709, 0xe9c85984, 0x178b4da1, 0xc63a2dcc, 0x387939e9, 0xebc2c4b7, 0x1581d092, 0xc430b0ff, 0x3a73a4da, 0x9795ba57, 0x69d6ae72, 0xb867ce1f, 0x4624da3a, 0x9e86b520, 0x60c5a105, 0xb174c168, 0x4f37d54d, 0xe2d1cbc0, 0x1c92dfe5, 0xcd23bf88, 0x3360abad, 0xe0db56f3, 0x1e9842d6, 0xcf2922bb, 0x316a369e, 0x9c8c2813, 0x62cf3c36, 0xb37e5c5b, 0x4d3d487e, 0x416070bb, 0xbf23649e, 0x6e9204f3, 0x90d110d6, 0x3d370e5b, 0xc3741a7e, 0x12c57a13, 0xec866e36, 0x3f3d9368, 0xc17e874d, 0x10cfe720, 0xee8cf305, 0x436aed88, 0xbd29f9ad, 0x6c9899c0, 0x92db8de5, 0x29935963, 0xd7d04d46, 0x06612d2b, 0xf822390e, 0x55c42783, 0xab8733a6, 0x7a3653cb, 0x847547ee, 0x57cebab0, 0xa98dae95, 0x783ccef8, 0x867fdadd, 0x2b99c450, 0xd5dad075, 0x046bb018, 0xfa28a43d, 0xf6759cf8, 0x083688dd, 0xd987e8b0, 0x27c4fc95, 0x8a22e218, 0x7461f63d, 0xa5d09650, 0x5b938275, 0x88287f2b, 0x766b6b0e, 0xa7da0b63, 0x59991f46, 0xf47f01cb, 0x0a3c15ee, 0xdb8d7583, 0x25ce61a6, 0xfd6c0ebc, 0x032f1a99, 0xd29e7af4, 0x2cdd6ed1, 0x813b705c, 0x7f786479, 0xaec90414, 0x508a1031, 0x8331ed6f, 0x7d72f94a, 0xacc39927, 0x52808d02, 0xff66938f, 0x012587aa, 0xd094e7c7, 0x2ed7f3e2, 0x228acb27, 0xdcc9df02, 0x0d78bf6f, 0xf33bab4a, 0x5eddb5c7, 0xa09ea1e2, 0x712fc18f, 0x8f6cd5aa, 0x5cd728f4, 0xa2943cd1, 0x73255cbc, 0x8d664899, 0x20805614, 0xdec34231, 0x0f72225c, 0xf1313679, 0x63eabb9c, 0x9da9afb9, 0x4c18cfd4, 0xb25bdbf1, 0x1fbdc57c, 0xe1fed159, 0x304fb134, 0xce0ca511, 0x1db7584f, 0xe3f44c6a, 0x32452c07, 0xcc063822, 0x61e026af, 0x9fa3328a, 0x4e1252e7, 0xb05146c2, 0xbc0c7e07, 0x424f6a22, 0x93fe0a4f, 0x6dbd1e6a, 0xc05b00e7, 0x3e1814c2, 0xefa974af, 0x11ea608a, 0xc2519dd4, 0x3c1289f1, 0xeda3e99c, 0x13e0fdb9, 0xbe06e334, 0x4045f711, 0x91f4977c, 0x6fb78359, 0xb715ec43, 0x4956f866, 0x98e7980b, 0x66a48c2e, 0xcb4292a3, 0x35018686, 0xe4b0e6eb, 0x1af3f2ce, 0xc9480f90, 0x370b1bb5, 0xe6ba7bd8, 0x18f96ffd, 0xb51f7170, 0x4b5c6555, 0x9aed0538, 0x64ae111d, 0x68f329d8, 0x96b03dfd, 0x47015d90, 0xb94249b5, 0x14a45738, 0xeae7431d, 0x3b562370, 0xc5153755, 0x16aeca0b, 0xe8edde2e, 0x395cbe43, 0xc71faa66, 0x6af9b4eb, 0x94baa0ce, 0x450bc0a3, 0xbb48d486 +}, +{ +0x00000000, 0x6e901d7c, 0x671e2382, 0x098e3efe, 0xe0f9b519, 0x8e69a865, 0x87e7969b, 0xe9778be7, 0xee72e201, 0x80e2ff7d, 0x896cc183, 0xe7fcdcff, 0x0e8b5718, 0x601b4a64, 0x6995749a, 0x070569e6, 0x42c7219b, 0x2c573ce7, 0x25d90219, 0x4b491f65, 0xa23e9482, 0xccae89fe, 0xc520b700, 0xabb0aa7c, 0xacb5c39a, 0xc225dee6, 0xcbabe018, 0xa53bfd64, 0x4c4c7683, 0x22dc6bff, 0x2b525501, 0x45c2487d, 0x1efcf239, 0x706cef45, 0x79e2d1bb, 0x1772ccc7, 0xfe054720, 0x90955a5c, 0x991b64a2, 0xf78b79de, 0xf08e1038, 0x9e1e0d44, 0x979033ba, 0xf9002ec6, 0x1077a521, 0x7ee7b85d, 0x776986a3, 0x19f99bdf, 0x5c3bd3a2, 0x32abcede, 0x3b25f020, 0x55b5ed5c, 0xbcc266bb, 0xd2527bc7, 0xdbdc4539, 0xb54c5845, 0xb24931a3, 0xdcd92cdf, 0xd5571221, 0xbbc70f5d, 0x52b084ba, 0x3c2099c6, 0x35aea738, 0x5b3eba44, 0x98cdb898, 0xf65da5e4, 0xffd39b1a, 0x91438666, 0x78340d81, 0x16a410fd, 0x1f2a2e03, 0x71ba337f, 0x76bf5a99, 0x182f47e5, 0x11a1791b, 0x7f316467, 0x9646ef80, 0xf8d6f2fc, 0xf158cc02, 0x9fc8d17e, 0xda0a9903, 0xb49a847f, 0xbd14ba81, 0xd384a7fd, 0x3af32c1a, 0x54633166, 0x5ded0f98, 0x337d12e4, 0x34787b02, 0x5ae8667e, 0x53665880, 0x3df645fc, 0xd481ce1b, 0xba11d367, 0xb39fed99, 0xdd0ff0e5, 0x86314aa1, 0xe8a157dd, 0xe12f6923, 0x8fbf745f, 0x66c8ffb8, 0x0858e2c4, 0x01d6dc3a, 0x6f46c146, 0x6843a8a0, 0x06d3b5dc, 0x0f5d8b22, 0x61cd965e, 0x88ba1db9, 0xe62a00c5, 0xefa43e3b, 0x81342347, 0xc4f66b3a, 0xaa667646, 0xa3e848b8, 0xcd7855c4, 0x240fde23, 0x4a9fc35f, 0x4311fda1, 0x2d81e0dd, 0x2a84893b, 0x44149447, 0x4d9aaab9, 0x230ab7c5, 0xca7d3c22, 0xa4ed215e, 0xad631fa0, 0xc3f302dc, 0xf270f470, 0x9ce0e90c, 0x956ed7f2, 0xfbfeca8e, 0x12894169, 0x7c195c15, 0x759762eb, 0x1b077f97, 0x1c021671, 0x72920b0d, 0x7b1c35f3, 0x158c288f, 0xfcfba368, 0x926bbe14, 0x9be580ea, 0xf5759d96, 0xb0b7d5eb, 0xde27c897, 0xd7a9f669, 0xb939eb15, 0x504e60f2, 0x3ede7d8e, 0x37504370, 0x59c05e0c, 0x5ec537ea, 0x30552a96, 0x39db1468, 0x574b0914, 0xbe3c82f3, 0xd0ac9f8f, 0xd922a171, 0xb7b2bc0d, 0xec8c0649, 0x821c1b35, 0x8b9225cb, 0xe50238b7, 0x0c75b350, 0x62e5ae2c, 0x6b6b90d2, 0x05fb8dae, 0x02fee448, 0x6c6ef934, 0x65e0c7ca, 0x0b70dab6, 0xe2075151, 0x8c974c2d, 0x851972d3, 0xeb896faf, 0xae4b27d2, 0xc0db3aae, 0xc9550450, 0xa7c5192c, 0x4eb292cb, 0x20228fb7, 0x29acb149, 0x473cac35, 0x4039c5d3, 0x2ea9d8af, 0x2727e651, 0x49b7fb2d, 0xa0c070ca, 0xce506db6, 0xc7de5348, 0xa94e4e34, 0x6abd4ce8, 0x042d5194, 0x0da36f6a, 0x63337216, 0x8a44f9f1, 0xe4d4e48d, 0xed5ada73, 0x83cac70f, 0x84cfaee9, 0xea5fb395, 0xe3d18d6b, 0x8d419017, 0x64361bf0, 0x0aa6068c, 0x03283872, 0x6db8250e, 0x287a6d73, 0x46ea700f, 0x4f644ef1, 0x21f4538d, 0xc883d86a, 0xa613c516, 0xaf9dfbe8, 0xc10de694, 0xc6088f72, 0xa898920e, 0xa116acf0, 0xcf86b18c, 0x26f13a6b, 0x48612717, 0x41ef19e9, 0x2f7f0495, 0x7441bed1, 0x1ad1a3ad, 0x135f9d53, 0x7dcf802f, 0x94b80bc8, 0xfa2816b4, 0xf3a6284a, 0x9d363536, 0x9a335cd0, 0xf4a341ac, 0xfd2d7f52, 0x93bd622e, 0x7acae9c9, 0x145af4b5, 0x1dd4ca4b, 0x7344d737, 0x36869f4a, 0x58168236, 0x5198bcc8, 0x3f08a1b4, 0xd67f2a53, 0xb8ef372f, 0xb16109d1, 0xdff114ad, 0xd8f47d4b, 0xb6646037, 0xbfea5ec9, 0xd17a43b5, 0x380dc852, 0x569dd52e, 0x5f13ebd0, 0x3183f6ac +}, +{ +0x00000000, 0x40f0f08a, 0x45175106, 0x05e7a18c, 0x1c0059a6, 0x5cf0a92c, 0x591708a0, 0x19e7f82a, 0x6f291605, 0x2fd9e68f, 0x2a3e4703, 0x6aceb789, 0x73294fa3, 0x33d9bf29, 0x363e1ea5, 0x76ceee2f, 0x783c4244, 0x38ccb2ce, 0x3d2b1342, 0x7ddbe3c8, 0x643c1be2, 0x24cceb68, 0x212b4ae4, 0x61dbba6e, 0x17155441, 0x57e5a4cb, 0x52020547, 0x12f2f5cd, 0x0b150de7, 0x4be5fd6d, 0x4e025ce1, 0x0ef2ac6b, 0xacdfb4c3, 0xec2f4449, 0xe9c8e5c5, 0xa938154f, 0xb0dfed65, 0xf02f1def, 0xf5c8bc63, 0xb5384ce9, 0xc3f6a2c6, 0x8306524c, 0x86e1f3c0, 0xc611034a, 0xdff6fb60, 0x9f060bea, 0x9ae1aa66, 0xda115aec, 0xd4e3f687, 0x9413060d, 0x91f4a781, 0xd104570b, 0xc8e3af21, 0x88135fab, 0x8df4fe27, 0xcd040ead, 0xbbcae082, 0xfb3a1008, 0xfeddb184, 0xbe2d410e, 0xa7cab924, 0xe73a49ae, 0xe2dde822, 0xa22d18a8, 0x13a5a46e, 0x535554e4, 0x56b2f568, 0x164205e2, 0x0fa5fdc8, 0x4f550d42, 0x4ab2acce, 0x0a425c44, 0x7c8cb26b, 0x3c7c42e1, 0x399be36d, 0x796b13e7, 0x608cebcd, 0x207c1b47, 0x259bbacb, 0x656b4a41, 0x6b99e62a, 0x2b6916a0, 0x2e8eb72c, 0x6e7e47a6, 0x7799bf8c, 0x37694f06, 0x328eee8a, 0x727e1e00, 0x04b0f02f, 0x444000a5, 0x41a7a129, 0x015751a3, 0x18b0a989, 0x58405903, 0x5da7f88f, 0x1d570805, 0xbf7a10ad, 0xff8ae027, 0xfa6d41ab, 0xba9db121, 0xa37a490b, 0xe38ab981, 0xe66d180d, 0xa69de887, 0xd05306a8, 0x90a3f622, 0x954457ae, 0xd5b4a724, 0xcc535f0e, 0x8ca3af84, 0x89440e08, 0xc9b4fe82, 0xc74652e9, 0x87b6a263, 0x825103ef, 0xc2a1f365, 0xdb460b4f, 0x9bb6fbc5, 0x9e515a49, 0xdea1aac3, 0xa86f44ec, 0xe89fb466, 0xed7815ea, 0xad88e560, 0xb46f1d4a, 0xf49fedc0, 0xf1784c4c, 0xb188bcc6, 0xfccf4d59, 0xbc3fbdd3, 0xb9d81c5f, 0xf928ecd5, 0xe0cf14ff, 0xa03fe475, 0xa5d845f9, 0xe528b573, 0x93e65b5c, 0xd316abd6, 0xd6f10a5a, 0x9601fad0, 0x8fe602fa, 0xcf16f270, 0xcaf153fc, 0x8a01a376, 0x84f30f1d, 0xc403ff97, 0xc1e45e1b, 0x8114ae91, 0x98f356bb, 0xd803a631, 0xdde407bd, 0x9d14f737, 0xebda1918, 0xab2ae992, 0xaecd481e, 0xee3db894, 0xf7da40be, 0xb72ab034, 0xb2cd11b8, 0xf23de132, 0x5010f99a, 0x10e00910, 0x1507a89c, 0x55f75816, 0x4c10a03c, 0x0ce050b6, 0x0907f13a, 0x49f701b0, 0x3f39ef9f, 0x7fc91f15, 0x7a2ebe99, 0x3ade4e13, 0x2339b639, 0x63c946b3, 0x662ee73f, 0x26de17b5, 0x282cbbde, 0x68dc4b54, 0x6d3bead8, 0x2dcb1a52, 0x342ce278, 0x74dc12f2, 0x713bb37e, 0x31cb43f4, 0x4705addb, 0x07f55d51, 0x0212fcdd, 0x42e20c57, 0x5b05f47d, 0x1bf504f7, 0x1e12a57b, 0x5ee255f1, 0xef6ae937, 0xaf9a19bd, 0xaa7db831, 0xea8d48bb, 0xf36ab091, 0xb39a401b, 0xb67de197, 0xf68d111d, 0x8043ff32, 0xc0b30fb8, 0xc554ae34, 0x85a45ebe, 0x9c43a694, 0xdcb3561e, 0xd954f792, 0x99a40718, 0x9756ab73, 0xd7a65bf9, 0xd241fa75, 0x92b10aff, 0x8b56f2d5, 0xcba6025f, 0xce41a3d3, 0x8eb15359, 0xf87fbd76, 0xb88f4dfc, 0xbd68ec70, 0xfd981cfa, 0xe47fe4d0, 0xa48f145a, 0xa168b5d6, 0xe198455c, 0x43b55df4, 0x0345ad7e, 0x06a20cf2, 0x4652fc78, 0x5fb50452, 0x1f45f4d8, 0x1aa25554, 0x5a52a5de, 0x2c9c4bf1, 0x6c6cbb7b, 0x698b1af7, 0x297bea7d, 0x309c1257, 0x706ce2dd, 0x758b4351, 0x357bb3db, 0x3b891fb0, 0x7b79ef3a, 0x7e9e4eb6, 0x3e6ebe3c, 0x27894616, 0x6779b69c, 0x629e1710, 0x226ee79a, 0x54a009b5, 0x1450f93f, 0x11b758b3, 0x5147a839, 0x48a05013, 0x0850a099, 0x0db70115, 0x4d47f19f +}, +{ +0x00000000, 0x479142f4, 0x77a59cf2, 0x3034de06, 0x194e446e, 0x5edf069a, 0x6eebd89c, 0x297a9a68, 0xcfb16fee, 0x88202d1a, 0xb814f31c, 0xff85b1e8, 0xd6ff2b80, 0x916e6974, 0xa15ab772, 0xe6cbf586, 0xf8af3612, 0xbf3e74e6, 0x8f0aaae0, 0xc89be814, 0xe1e1727c, 0xa6703088, 0x9644ee8e, 0xd1d5ac7a, 0x371e59fc, 0x708f1b08, 0x40bbc50e, 0x072a87fa, 0x2e501d92, 0x69c15f66, 0x59f58160, 0x1e64c394, 0x81a4554f, 0xc63517bb, 0xf601c9bd, 0xb1908b49, 0x98ea1121, 0xdf7b53d5, 0xef4f8dd3, 0xa8decf27, 0x4e153aa1, 0x09847855, 0x39b0a653, 0x7e21e4a7, 0x575b7ecf, 0x10ca3c3b, 0x20fee23d, 0x676fa0c9, 0x790b635d, 0x3e9a21a9, 0x0eaeffaf, 0x493fbd5b, 0x60452733, 0x27d465c7, 0x17e0bbc1, 0x5071f935, 0xb6ba0cb3, 0xf12b4e47, 0xc11f9041, 0x868ed2b5, 0xaff448dd, 0xe8650a29, 0xd851d42f, 0x9fc096db, 0x865b1a49, 0xc1ca58bd, 0xf1fe86bb, 0xb66fc44f, 0x9f155e27, 0xd8841cd3, 0xe8b0c2d5, 0xaf218021, 0x49ea75a7, 0x0e7b3753, 0x3e4fe955, 0x79deaba1, 0x50a431c9, 0x1735733d, 0x2701ad3b, 0x6090efcf, 0x7ef42c5b, 0x39656eaf, 0x0951b0a9, 0x4ec0f25d, 0x67ba6835, 0x202b2ac1, 0x101ff4c7, 0x578eb633, 0xb14543b5, 0xf6d40141, 0xc6e0df47, 0x81719db3, 0xa80b07db, 0xef9a452f, 0xdfae9b29, 0x983fd9dd, 0x07ff4f06, 0x406e0df2, 0x705ad3f4, 0x37cb9100, 0x1eb10b68, 0x5920499c, 0x6914979a, 0x2e85d56e, 0xc84e20e8, 0x8fdf621c, 0xbfebbc1a, 0xf87afeee, 0xd1006486, 0x96912672, 0xa6a5f874, 0xe134ba80, 0xff507914, 0xb8c13be0, 0x88f5e5e6, 0xcf64a712, 0xe61e3d7a, 0xa18f7f8e, 0x91bba188, 0xd62ae37c, 0x30e116fa, 0x7770540e, 0x47448a08, 0x00d5c8fc, 0x29af5294, 0x6e3e1060, 0x5e0ace66, 0x199b8c92, 0x8ba0675f, 0xcc3125ab, 0xfc05fbad, 0xbb94b959, 0x92ee2331, 0xd57f61c5, 0xe54bbfc3, 0xa2dafd37, 0x441108b1, 0x03804a45, 0x33b49443, 0x7425d6b7, 0x5d5f4cdf, 0x1ace0e2b, 0x2afad02d, 0x6d6b92d9, 0x730f514d, 0x349e13b9, 0x04aacdbf, 0x433b8f4b, 0x6a411523, 0x2dd057d7, 0x1de489d1, 0x5a75cb25, 0xbcbe3ea3, 0xfb2f7c57, 0xcb1ba251, 0x8c8ae0a5, 0xa5f07acd, 0xe2613839, 0xd255e63f, 0x95c4a4cb, 0x0a043210, 0x4d9570e4, 0x7da1aee2, 0x3a30ec16, 0x134a767e, 0x54db348a, 0x64efea8c, 0x237ea878, 0xc5b55dfe, 0x82241f0a, 0xb210c10c, 0xf58183f8, 0xdcfb1990, 0x9b6a5b64, 0xab5e8562, 0xeccfc796, 0xf2ab0402, 0xb53a46f6, 0x850e98f0, 0xc29fda04, 0xebe5406c, 0xac740298, 0x9c40dc9e, 0xdbd19e6a, 0x3d1a6bec, 0x7a8b2918, 0x4abff71e, 0x0d2eb5ea, 0x24542f82, 0x63c56d76, 0x53f1b370, 0x1460f184, 0x0dfb7d16, 0x4a6a3fe2, 0x7a5ee1e4, 0x3dcfa310, 0x14b53978, 0x53247b8c, 0x6310a58a, 0x2481e77e, 0xc24a12f8, 0x85db500c, 0xb5ef8e0a, 0xf27eccfe, 0xdb045696, 0x9c951462, 0xaca1ca64, 0xeb308890, 0xf5544b04, 0xb2c509f0, 0x82f1d7f6, 0xc5609502, 0xec1a0f6a, 0xab8b4d9e, 0x9bbf9398, 0xdc2ed16c, 0x3ae524ea, 0x7d74661e, 0x4d40b818, 0x0ad1faec, 0x23ab6084, 0x643a2270, 0x540efc76, 0x139fbe82, 0x8c5f2859, 0xcbce6aad, 0xfbfab4ab, 0xbc6bf65f, 0x95116c37, 0xd2802ec3, 0xe2b4f0c5, 0xa525b231, 0x43ee47b7, 0x047f0543, 0x344bdb45, 0x73da99b1, 0x5aa003d9, 0x1d31412d, 0x2d059f2b, 0x6a94dddf, 0x74f01e4b, 0x33615cbf, 0x035582b9, 0x44c4c04d, 0x6dbe5a25, 0x2a2f18d1, 0x1a1bc6d7, 0x5d8a8423, 0xbb4171a5, 0xfcd03351, 0xcce4ed57, 0x8b75afa3, 0xa20f35cb, 0xe59e773f, 0xd5aaa939, 0x923bebcd +}, +{ +0x00000000, 0x22a10580, 0x13a5e5e0, 0x3104e060, 0x6b9b40d8, 0x493a4558, 0x783ea538, 0x5a9fa0b8, 0xb299d0d4, 0x9038d554, 0xa13c3534, 0x839d30b4, 0xd902900c, 0xfba3958c, 0xcaa775ec, 0xe806706c, 0x99d7c4a2, 0xbb76c122, 0x8a722142, 0xa8d324c2, 0xf24c847a, 0xd0ed81fa, 0xe1e9619a, 0xc348641a, 0x2b4e1476, 0x09ef11f6, 0x38ebf196, 0x1a4af416, 0x40d554ae, 0x6274512e, 0x5370b14e, 0x71d1b4ce, 0x3f33870d, 0x1d92828d, 0x2c9662ed, 0x0e37676d, 0x54a8c7d5, 0x7609c255, 0x470d2235, 0x65ac27b5, 0x8daa57d9, 0xaf0b5259, 0x9e0fb239, 0xbcaeb7b9, 0xe6311701, 0xc4901281, 0xf594f2e1, 0xd735f761, 0xa6e443af, 0x8445462f, 0xb541a64f, 0x97e0a3cf, 0xcd7f0377, 0xefde06f7, 0xdedae697, 0xfc7be317, 0x147d937b, 0x36dc96fb, 0x07d8769b, 0x2579731b, 0x7fe6d3a3, 0x5d47d623, 0x6c433643, 0x4ee233c3, 0x0ebdf60e, 0x2c1cf38e, 0x1d1813ee, 0x3fb9166e, 0x6526b6d6, 0x4787b356, 0x76835336, 0x542256b6, 0xbc2426da, 0x9e85235a, 0xaf81c33a, 0x8d20c6ba, 0xd7bf6602, 0xf51e6382, 0xc41a83e2, 0xe6bb8662, 0x976a32ac, 0xb5cb372c, 0x84cfd74c, 0xa66ed2cc, 0xfcf17274, 0xde5077f4, 0xef549794, 0xcdf59214, 0x25f3e278, 0x0752e7f8, 0x36560798, 0x14f70218, 0x4e68a2a0, 0x6cc9a720, 0x5dcd4740, 0x7f6c42c0, 0x318e7103, 0x132f7483, 0x222b94e3, 0x008a9163, 0x5a1531db, 0x78b4345b, 0x49b0d43b, 0x6b11d1bb, 0x8317a1d7, 0xa1b6a457, 0x90b24437, 0xb21341b7, 0xe88ce10f, 0xca2de48f, 0xfb2904ef, 0xd988016f, 0xa859b5a1, 0x8af8b021, 0xbbfc5041, 0x995d55c1, 0xc3c2f579, 0xe163f0f9, 0xd0671099, 0xf2c61519, 0x1ac06575, 0x386160f5, 0x09658095, 0x2bc48515, 0x715b25ad, 0x53fa202d, 0x62fec04d, 0x405fc5cd, 0x2300462d, 0x01a143ad, 0x30a5a3cd, 0x1204a64d, 0x489b06f5, 0x6a3a0375, 0x5b3ee315, 0x799fe695, 0x919996f9, 0xb3389379, 0x823c7319, 0xa09d7699, 0xfa02d621, 0xd8a3d3a1, 0xe9a733c1, 0xcb063641, 0xbad7828f, 0x9876870f, 0xa972676f, 0x8bd362ef, 0xd14cc257, 0xf3edc7d7, 0xc2e927b7, 0xe0482237, 0x084e525b, 0x2aef57db, 0x1bebb7bb, 0x394ab23b, 0x63d51283, 0x41741703, 0x7070f763, 0x52d1f2e3, 0x1c33c120, 0x3e92c4a0, 0x0f9624c0, 0x2d372140, 0x77a881f8, 0x55098478, 0x640d6418, 0x46ac6198, 0xaeaa11f4, 0x8c0b1474, 0xbd0ff414, 0x9faef194, 0xc531512c, 0xe79054ac, 0xd694b4cc, 0xf435b14c, 0x85e40582, 0xa7450002, 0x9641e062, 0xb4e0e5e2, 0xee7f455a, 0xccde40da, 0xfddaa0ba, 0xdf7ba53a, 0x377dd556, 0x15dcd0d6, 0x24d830b6, 0x06793536, 0x5ce6958e, 0x7e47900e, 0x4f43706e, 0x6de275ee, 0x2dbdb023, 0x0f1cb5a3, 0x3e1855c3, 0x1cb95043, 0x4626f0fb, 0x6487f57b, 0x5583151b, 0x7722109b, 0x9f2460f7, 0xbd856577, 0x8c818517, 0xae208097, 0xf4bf202f, 0xd61e25af, 0xe71ac5cf, 0xc5bbc04f, 0xb46a7481, 0x96cb7101, 0xa7cf9161, 0x856e94e1, 0xdff13459, 0xfd5031d9, 0xcc54d1b9, 0xeef5d439, 0x06f3a455, 0x2452a1d5, 0x155641b5, 0x37f74435, 0x6d68e48d, 0x4fc9e10d, 0x7ecd016d, 0x5c6c04ed, 0x128e372e, 0x302f32ae, 0x012bd2ce, 0x238ad74e, 0x791577f6, 0x5bb47276, 0x6ab09216, 0x48119796, 0xa017e7fa, 0x82b6e27a, 0xb3b2021a, 0x9113079a, 0xcb8ca722, 0xe92da2a2, 0xd82942c2, 0xfa884742, 0x8b59f38c, 0xa9f8f60c, 0x98fc166c, 0xba5d13ec, 0xe0c2b354, 0xc263b6d4, 0xf36756b4, 0xd1c65334, 0x39c02358, 0x1b6126d8, 0x2a65c6b8, 0x08c4c338, 0x525b6380, 0x70fa6600, 0x41fe8660, 0x635f83e0 +} +}, +{ +{ +0x00000000, 0xef95fdf9, 0xdf4727cf, 0x30d2da36, 0xe3a1e221, 0x0c341fd8, 0x3ce6c5ee, 0xd3733817, 0x2bcb7f0c, 0xc45e82f5, 0xf48c58c3, 0x1b19a53a, 0xc86a9d2d, 0x27ff60d4, 0x172dbae2, 0xf8b8471b, 0x2ca7cb39, 0xc33236c0, 0xf3e0ecf6, 0x1c75110f, 0xcf062918, 0x2093d4e1, 0x10410ed7, 0xffd4f32e, 0x076cb435, 0xe8f949cc, 0xd82b93fa, 0x37be6e03, 0xe4cd5614, 0x0b58abed, 0x3b8a71db, 0xd41f8c22, 0xd3627c44, 0x3cf781bd, 0x0c255b8b, 0xe3b0a672, 0x30c39e65, 0xdf56639c, 0xef84b9aa, 0x00114453, 0xf8a90348, 0x173cfeb1, 0x27ee2487, 0xc87bd97e, 0x1b08e169, 0xf49d1c90, 0xc44fc6a6, 0x2bda3b5f, 0xffc5b77d, 0x10504a84, 0x208290b2, 0xcf176d4b, 0x1c64555c, 0xf3f1a8a5, 0xc3237293, 0x2cb68f6a, 0xd40ec871, 0x3b9b3588, 0x0b49efbe, 0xe4dc1247, 0x37af2a50, 0xd83ad7a9, 0xe8e80d9f, 0x077df066, 0x29994a18, 0xc60cb7e1, 0xf6de6dd7, 0x194b902e, 0xca38a839, 0x25ad55c0, 0x157f8ff6, 0xfaea720f, 0x02523514, 0xedc7c8ed, 0xdd1512db, 0x3280ef22, 0xe1f3d735, 0x0e662acc, 0x3eb4f0fa, 0xd1210d03, 0x053e8121, 0xeaab7cd8, 0xda79a6ee, 0x35ec5b17, 0xe69f6300, 0x090a9ef9, 0x39d844cf, 0xd64db936, 0x2ef5fe2d, 0xc16003d4, 0xf1b2d9e2, 0x1e27241b, 0xcd541c0c, 0x22c1e1f5, 0x12133bc3, 0xfd86c63a, 0xfafb365c, 0x156ecba5, 0x25bc1193, 0xca29ec6a, 0x195ad47d, 0xf6cf2984, 0xc61df3b2, 0x29880e4b, 0xd1304950, 0x3ea5b4a9, 0x0e776e9f, 0xe1e29366, 0x3291ab71, 0xdd045688, 0xedd68cbe, 0x02437147, 0xd65cfd65, 0x39c9009c, 0x091bdaaa, 0xe68e2753, 0x35fd1f44, 0xda68e2bd, 0xeaba388b, 0x052fc572, 0xfd978269, 0x12027f90, 0x22d0a5a6, 0xcd45585f, 0x1e366048, 0xf1a39db1, 0xc1714787, 0x2ee4ba7e, 0xa886f2a0, 0x47130f59, 0x77c1d56f, 0x98542896, 0x4b271081, 0xa4b2ed78, 0x9460374e, 0x7bf5cab7, 0x834d8dac, 0x6cd87055, 0x5c0aaa63, 0xb39f579a, 0x60ec6f8d, 0x8f799274, 0xbfab4842, 0x503eb5bb, 0x84213999, 0x6bb4c460, 0x5b661e56, 0xb4f3e3af, 0x6780dbb8, 0x88152641, 0xb8c7fc77, 0x5752018e, 0xafea4695, 0x407fbb6c, 0x70ad615a, 0x9f389ca3, 0x4c4ba4b4, 0xa3de594d, 0x930c837b, 0x7c997e82, 0x7be48ee4, 0x9471731d, 0xa4a3a92b, 0x4b3654d2, 0x98456cc5, 0x77d0913c, 0x47024b0a, 0xa897b6f3, 0x502ff1e8, 0xbfba0c11, 0x8f68d627, 0x60fd2bde, 0xb38e13c9, 0x5c1bee30, 0x6cc93406, 0x835cc9ff, 0x574345dd, 0xb8d6b824, 0x88046212, 0x67919feb, 0xb4e2a7fc, 0x5b775a05, 0x6ba58033, 0x84307dca, 0x7c883ad1, 0x931dc728, 0xa3cf1d1e, 0x4c5ae0e7, 0x9f29d8f0, 0x70bc2509, 0x406eff3f, 0xaffb02c6, 0x811fb8b8, 0x6e8a4541, 0x5e589f77, 0xb1cd628e, 0x62be5a99, 0x8d2ba760, 0xbdf97d56, 0x526c80af, 0xaad4c7b4, 0x45413a4d, 0x7593e07b, 0x9a061d82, 0x49752595, 0xa6e0d86c, 0x9632025a, 0x79a7ffa3, 0xadb87381, 0x422d8e78, 0x72ff544e, 0x9d6aa9b7, 0x4e1991a0, 0xa18c6c59, 0x915eb66f, 0x7ecb4b96, 0x86730c8d, 0x69e6f174, 0x59342b42, 0xb6a1d6bb, 0x65d2eeac, 0x8a471355, 0xba95c963, 0x5500349a, 0x527dc4fc, 0xbde83905, 0x8d3ae333, 0x62af1eca, 0xb1dc26dd, 0x5e49db24, 0x6e9b0112, 0x810efceb, 0x79b6bbf0, 0x96234609, 0xa6f19c3f, 0x496461c6, 0x9a1759d1, 0x7582a428, 0x45507e1e, 0xaac583e7, 0x7eda0fc5, 0x914ff23c, 0xa19d280a, 0x4e08d5f3, 0x9d7bede4, 0x72ee101d, 0x423cca2b, 0xada937d2, 0x551170c9, 0xba848d30, 0x8a565706, 0x65c3aaff, 0xb6b092e8, 0x59256f11, 0x69f7b527, 0x866248de +}, +{ +0x00000000, 0xd51dc966, 0x4224643e, 0x9739ad58, 0x02912127, 0xd78ce841, 0x40b54519, 0x95a88c7f, 0x345a5937, 0xe1479051, 0x767e3d09, 0xa363f46f, 0x36cb7810, 0xe3d6b176, 0x74ef1c2e, 0xa1f2d548, 0x5ffc6273, 0x8ae1ab15, 0x1dd8064d, 0xc8c5cf2b, 0x5d6d4354, 0x88708a32, 0x1f49276a, 0xca54ee0c, 0x6ba63b44, 0xbebbf222, 0x29825f7a, 0xfc9f961c, 0x69371a63, 0xbc2ad305, 0x2b137e5d, 0xfe0eb73b, 0xb0a7b33e, 0x65ba7a58, 0xf283d700, 0x279e1e66, 0xb2369219, 0x672b5b7f, 0xf012f627, 0x250f3f41, 0x84fdea09, 0x51e0236f, 0xc6d98e37, 0x13c44751, 0x866ccb2e, 0x53710248, 0xc448af10, 0x11556676, 0xef5bd14d, 0x3a46182b, 0xad7fb573, 0x78627c15, 0xedcaf06a, 0x38d7390c, 0xafee9454, 0x7af35d32, 0xdb01887a, 0x0e1c411c, 0x9925ec44, 0x4c382522, 0xd990a95d, 0x0c8d603b, 0x9bb4cd63, 0x4ea90405, 0x8e770dcc, 0x5b6ac4aa, 0xcc5369f2, 0x194ea094, 0x8ce62ceb, 0x59fbe58d, 0xcec248d5, 0x1bdf81b3, 0xba2d54fb, 0x6f309d9d, 0xf80930c5, 0x2d14f9a3, 0xb8bc75dc, 0x6da1bcba, 0xfa9811e2, 0x2f85d884, 0xd18b6fbf, 0x0496a6d9, 0x93af0b81, 0x46b2c2e7, 0xd31a4e98, 0x060787fe, 0x913e2aa6, 0x4423e3c0, 0xe5d13688, 0x30ccffee, 0xa7f552b6, 0x72e89bd0, 0xe74017af, 0x325ddec9, 0xa5647391, 0x7079baf7, 0x3ed0bef2, 0xebcd7794, 0x7cf4dacc, 0xa9e913aa, 0x3c419fd5, 0xe95c56b3, 0x7e65fbeb, 0xab78328d, 0x0a8ae7c5, 0xdf972ea3, 0x48ae83fb, 0x9db34a9d, 0x081bc6e2, 0xdd060f84, 0x4a3fa2dc, 0x9f226bba, 0x612cdc81, 0xb43115e7, 0x2308b8bf, 0xf61571d9, 0x63bdfda6, 0xb6a034c0, 0x21999998, 0xf48450fe, 0x557685b6, 0x806b4cd0, 0x1752e188, 0xc24f28ee, 0x57e7a491, 0x82fa6df7, 0x15c3c0af, 0xc0de09c9, 0xa83297a3, 0x7d2f5ec5, 0xea16f39d, 0x3f0b3afb, 0xaaa3b684, 0x7fbe7fe2, 0xe887d2ba, 0x3d9a1bdc, 0x9c68ce94, 0x497507f2, 0xde4caaaa, 0x0b5163cc, 0x9ef9efb3, 0x4be426d5, 0xdcdd8b8d, 0x09c042eb, 0xf7cef5d0, 0x22d33cb6, 0xb5ea91ee, 0x60f75888, 0xf55fd4f7, 0x20421d91, 0xb77bb0c9, 0x626679af, 0xc394ace7, 0x16896581, 0x81b0c8d9, 0x54ad01bf, 0xc1058dc0, 0x141844a6, 0x8321e9fe, 0x563c2098, 0x1895249d, 0xcd88edfb, 0x5ab140a3, 0x8fac89c5, 0x1a0405ba, 0xcf19ccdc, 0x58206184, 0x8d3da8e2, 0x2ccf7daa, 0xf9d2b4cc, 0x6eeb1994, 0xbbf6d0f2, 0x2e5e5c8d, 0xfb4395eb, 0x6c7a38b3, 0xb967f1d5, 0x476946ee, 0x92748f88, 0x054d22d0, 0xd050ebb6, 0x45f867c9, 0x90e5aeaf, 0x07dc03f7, 0xd2c1ca91, 0x73331fd9, 0xa62ed6bf, 0x31177be7, 0xe40ab281, 0x71a23efe, 0xa4bff798, 0x33865ac0, 0xe69b93a6, 0x26459a6f, 0xf3585309, 0x6461fe51, 0xb17c3737, 0x24d4bb48, 0xf1c9722e, 0x66f0df76, 0xb3ed1610, 0x121fc358, 0xc7020a3e, 0x503ba766, 0x85266e00, 0x108ee27f, 0xc5932b19, 0x52aa8641, 0x87b74f27, 0x79b9f81c, 0xaca4317a, 0x3b9d9c22, 0xee805544, 0x7b28d93b, 0xae35105d, 0x390cbd05, 0xec117463, 0x4de3a12b, 0x98fe684d, 0x0fc7c515, 0xdada0c73, 0x4f72800c, 0x9a6f496a, 0x0d56e432, 0xd84b2d54, 0x96e22951, 0x43ffe037, 0xd4c64d6f, 0x01db8409, 0x94730876, 0x416ec110, 0xd6576c48, 0x034aa52e, 0xa2b87066, 0x77a5b900, 0xe09c1458, 0x3581dd3e, 0xa0295141, 0x75349827, 0xe20d357f, 0x3710fc19, 0xc91e4b22, 0x1c038244, 0x8b3a2f1c, 0x5e27e67a, 0xcb8f6a05, 0x1e92a363, 0x89ab0e3b, 0x5cb6c75d, 0xfd441215, 0x2859db73, 0xbf60762b, 0x6a7dbf4d, 0xffd53332, 0x2ac8fa54, 0xbdf1570c, 0x68ec9e6a +}, +{ +0x00000000, 0xc58b15cf, 0x041f98b3, 0xc1948d7c, 0xe9db3267, 0x2c5027a8, 0xedc4aad4, 0x284fbf1b, 0x7c64cf8f, 0xb9efda40, 0x787b573c, 0xbdf042f3, 0x95bffde8, 0x5034e827, 0x91a0655b, 0x542b7094, 0xa42e6705, 0x61a572ca, 0xa031ffb6, 0x65baea79, 0x4df55562, 0x887e40ad, 0x49eacdd1, 0x8c61d81e, 0xd84aa88a, 0x1dc1bd45, 0xdc553039, 0x19de25f6, 0x31919aed, 0xf41a8f22, 0x358e025e, 0xf0051791, 0xef8da70d, 0x2a06b2c2, 0xeb923fbe, 0x2e192a71, 0x0656956a, 0xc3dd80a5, 0x02490dd9, 0xc7c21816, 0x93e96882, 0x56627d4d, 0x97f6f031, 0x527de5fe, 0x7a325ae5, 0xbfb94f2a, 0x7e2dc256, 0xbba6d799, 0x4ba3c008, 0x8e28d5c7, 0x4fbc58bb, 0x8a374d74, 0xa278f26f, 0x67f3e7a0, 0xa6676adc, 0x63ec7f13, 0x37c70f87, 0xf24c1a48, 0x33d89734, 0xf65382fb, 0xde1c3de0, 0x1b97282f, 0xda03a553, 0x1f88b09c, 0x48715b7f, 0x8dfa4eb0, 0x4c6ec3cc, 0x89e5d603, 0xa1aa6918, 0x64217cd7, 0xa5b5f1ab, 0x603ee464, 0x341594f0, 0xf19e813f, 0x300a0c43, 0xf581198c, 0xddcea697, 0x1845b358, 0xd9d13e24, 0x1c5a2beb, 0xec5f3c7a, 0x29d429b5, 0xe840a4c9, 0x2dcbb106, 0x05840e1d, 0xc00f1bd2, 0x019b96ae, 0xc4108361, 0x903bf3f5, 0x55b0e63a, 0x94246b46, 0x51af7e89, 0x79e0c192, 0xbc6bd45d, 0x7dff5921, 0xb8744cee, 0xa7fcfc72, 0x6277e9bd, 0xa3e364c1, 0x6668710e, 0x4e27ce15, 0x8bacdbda, 0x4a3856a6, 0x8fb34369, 0xdb9833fd, 0x1e132632, 0xdf87ab4e, 0x1a0cbe81, 0x3243019a, 0xf7c81455, 0x365c9929, 0xf3d78ce6, 0x03d29b77, 0xc6598eb8, 0x07cd03c4, 0xc246160b, 0xea09a910, 0x2f82bcdf, 0xee1631a3, 0x2b9d246c, 0x7fb654f8, 0xba3d4137, 0x7ba9cc4b, 0xbe22d984, 0x966d669f, 0x53e67350, 0x9272fe2c, 0x57f9ebe3, 0xf45ebf25, 0x31d5aaea, 0xf0412796, 0x35ca3259, 0x1d858d42, 0xd80e988d, 0x199a15f1, 0xdc11003e, 0x883a70aa, 0x4db16565, 0x8c25e819, 0x49aefdd6, 0x61e142cd, 0xa46a5702, 0x65feda7e, 0xa075cfb1, 0x5070d820, 0x95fbcdef, 0x546f4093, 0x91e4555c, 0xb9abea47, 0x7c20ff88, 0xbdb472f4, 0x783f673b, 0x2c1417af, 0xe99f0260, 0x280b8f1c, 0xed809ad3, 0xc5cf25c8, 0x00443007, 0xc1d0bd7b, 0x045ba8b4, 0x1bd31828, 0xde580de7, 0x1fcc809b, 0xda479554, 0xf2082a4f, 0x37833f80, 0xf617b2fc, 0x339ca733, 0x67b7d7a7, 0xa23cc268, 0x63a84f14, 0xa6235adb, 0x8e6ce5c0, 0x4be7f00f, 0x8a737d73, 0x4ff868bc, 0xbffd7f2d, 0x7a766ae2, 0xbbe2e79e, 0x7e69f251, 0x56264d4a, 0x93ad5885, 0x5239d5f9, 0x97b2c036, 0xc399b0a2, 0x0612a56d, 0xc7862811, 0x020d3dde, 0x2a4282c5, 0xefc9970a, 0x2e5d1a76, 0xebd60fb9, 0xbc2fe45a, 0x79a4f195, 0xb8307ce9, 0x7dbb6926, 0x55f4d63d, 0x907fc3f2, 0x51eb4e8e, 0x94605b41, 0xc04b2bd5, 0x05c03e1a, 0xc454b366, 0x01dfa6a9, 0x299019b2, 0xec1b0c7d, 0x2d8f8101, 0xe80494ce, 0x1801835f, 0xdd8a9690, 0x1c1e1bec, 0xd9950e23, 0xf1dab138, 0x3451a4f7, 0xf5c5298b, 0x304e3c44, 0x64654cd0, 0xa1ee591f, 0x607ad463, 0xa5f1c1ac, 0x8dbe7eb7, 0x48356b78, 0x89a1e604, 0x4c2af3cb, 0x53a24357, 0x96295698, 0x57bddbe4, 0x9236ce2b, 0xba797130, 0x7ff264ff, 0xbe66e983, 0x7bedfc4c, 0x2fc68cd8, 0xea4d9917, 0x2bd9146b, 0xee5201a4, 0xc61dbebf, 0x0396ab70, 0xc202260c, 0x078933c3, 0xf78c2452, 0x3207319d, 0xf393bce1, 0x3618a92e, 0x1e571635, 0xdbdc03fa, 0x1a488e86, 0xdfc39b49, 0x8be8ebdd, 0x4e63fe12, 0x8ff7736e, 0x4a7c66a1, 0x6233d9ba, 0xa7b8cc75, 0x662c4109, 0xa3a754c6 +}, +{ +0x00000000, 0x34d977f2, 0x5533cf2d, 0x61eab8df, 0x85bc1102, 0xb16566f0, 0xd08fde2f, 0xe456a9dd, 0xc549ca70, 0xf190bd82, 0x907a055d, 0xa4a372af, 0x40f5db72, 0x742cac80, 0x15c6145f, 0x211f63ad, 0x5fcbea14, 0x6b129de6, 0x0af82539, 0x3e2152cb, 0xda77fb16, 0xeeae8ce4, 0x8f44343b, 0xbb9d43c9, 0x9a822064, 0xae5b5796, 0xcfb1ef49, 0xfb6898bb, 0x1f3e3166, 0x2be74694, 0x4a0dfe4b, 0x7ed489b9, 0x12f91e6c, 0x2620699e, 0x47cad141, 0x7313a6b3, 0x97450f6e, 0xa39c789c, 0xc276c043, 0xf6afb7b1, 0xd7b0d41c, 0xe369a3ee, 0x82831b31, 0xb65a6cc3, 0x520cc51e, 0x66d5b2ec, 0x073f0a33, 0x33e67dc1, 0x4d32f478, 0x79eb838a, 0x18013b55, 0x2cd84ca7, 0xc88ee57a, 0xfc579288, 0x9dbd2a57, 0xa9645da5, 0x887b3e08, 0xbca249fa, 0xdd48f125, 0xe99186d7, 0x0dc72f0a, 0x391e58f8, 0x58f4e027, 0x6c2d97d5, 0xa3f68615, 0x972ff1e7, 0xf6c54938, 0xc21c3eca, 0x264a9717, 0x1293e0e5, 0x7379583a, 0x47a02fc8, 0x66bf4c65, 0x52663b97, 0x338c8348, 0x0755f4ba, 0xe3035d67, 0xd7da2a95, 0xb630924a, 0x82e9e5b8, 0xfc3d6c01, 0xc8e41bf3, 0xa90ea32c, 0x9dd7d4de, 0x79817d03, 0x4d580af1, 0x2cb2b22e, 0x186bc5dc, 0x3974a671, 0x0dadd183, 0x6c47695c, 0x589e1eae, 0xbcc8b773, 0x8811c081, 0xe9fb785e, 0xdd220fac, 0xb10f9879, 0x85d6ef8b, 0xe43c5754, 0xd0e520a6, 0x34b3897b, 0x006afe89, 0x61804656, 0x555931a4, 0x74465209, 0x409f25fb, 0x21759d24, 0x15acead6, 0xf1fa430b, 0xc52334f9, 0xa4c98c26, 0x9010fbd4, 0xeec4726d, 0xda1d059f, 0xbbf7bd40, 0x8f2ecab2, 0x6b78636f, 0x5fa1149d, 0x3e4bac42, 0x0a92dbb0, 0x2b8db81d, 0x1f54cfef, 0x7ebe7730, 0x4a6700c2, 0xae31a91f, 0x9ae8deed, 0xfb026632, 0xcfdb11c0, 0x34eb2385, 0x00325477, 0x61d8eca8, 0x55019b5a, 0xb1573287, 0x858e4575, 0xe464fdaa, 0xd0bd8a58, 0xf1a2e9f5, 0xc57b9e07, 0xa49126d8, 0x9048512a, 0x741ef8f7, 0x40c78f05, 0x212d37da, 0x15f44028, 0x6b20c991, 0x5ff9be63, 0x3e1306bc, 0x0aca714e, 0xee9cd893, 0xda45af61, 0xbbaf17be, 0x8f76604c, 0xae6903e1, 0x9ab07413, 0xfb5acccc, 0xcf83bb3e, 0x2bd512e3, 0x1f0c6511, 0x7ee6ddce, 0x4a3faa3c, 0x26123de9, 0x12cb4a1b, 0x7321f2c4, 0x47f88536, 0xa3ae2ceb, 0x97775b19, 0xf69de3c6, 0xc2449434, 0xe35bf799, 0xd782806b, 0xb66838b4, 0x82b14f46, 0x66e7e69b, 0x523e9169, 0x33d429b6, 0x070d5e44, 0x79d9d7fd, 0x4d00a00f, 0x2cea18d0, 0x18336f22, 0xfc65c6ff, 0xc8bcb10d, 0xa95609d2, 0x9d8f7e20, 0xbc901d8d, 0x88496a7f, 0xe9a3d2a0, 0xdd7aa552, 0x392c0c8f, 0x0df57b7d, 0x6c1fc3a2, 0x58c6b450, 0x971da590, 0xa3c4d262, 0xc22e6abd, 0xf6f71d4f, 0x12a1b492, 0x2678c360, 0x47927bbf, 0x734b0c4d, 0x52546fe0, 0x668d1812, 0x0767a0cd, 0x33bed73f, 0xd7e87ee2, 0xe3310910, 0x82dbb1cf, 0xb602c63d, 0xc8d64f84, 0xfc0f3876, 0x9de580a9, 0xa93cf75b, 0x4d6a5e86, 0x79b32974, 0x185991ab, 0x2c80e659, 0x0d9f85f4, 0x3946f206, 0x58ac4ad9, 0x6c753d2b, 0x882394f6, 0xbcfae304, 0xdd105bdb, 0xe9c92c29, 0x85e4bbfc, 0xb13dcc0e, 0xd0d774d1, 0xe40e0323, 0x0058aafe, 0x3481dd0c, 0x556b65d3, 0x61b21221, 0x40ad718c, 0x7474067e, 0x159ebea1, 0x2147c953, 0xc511608e, 0xf1c8177c, 0x9022afa3, 0xa4fbd851, 0xda2f51e8, 0xeef6261a, 0x8f1c9ec5, 0xbbc5e937, 0x5f9340ea, 0x6b4a3718, 0x0aa08fc7, 0x3e79f835, 0x1f669b98, 0x2bbfec6a, 0x4a5554b5, 0x7e8c2347, 0x9ada8a9a, 0xae03fd68, 0xcfe945b7, 0xfb303245 +}, +{ +0x00000000, 0xb0f6c5de, 0x998835da, 0x297ef004, 0x8858e53a, 0x38ae20e4, 0x11d0d0e0, 0xa126153e, 0xa527b568, 0x15d170b6, 0x3caf80b2, 0x8c59456c, 0x2d7f5052, 0x9d89958c, 0xb4f76588, 0x0401a056, 0xafff0495, 0x1f09c14b, 0x3677314f, 0x8681f491, 0x27a7e1af, 0x97512471, 0xbe2fd475, 0x0ed911ab, 0x0ad8b1fd, 0xba2e7423, 0x93508427, 0x23a641f9, 0x828054c7, 0x32769119, 0x1b08611d, 0xabfea4c3, 0xdb4921fc, 0x6bbfe422, 0x42c11426, 0xf237d1f8, 0x5311c4c6, 0xe3e70118, 0xca99f11c, 0x7a6f34c2, 0x7e6e9494, 0xce98514a, 0xe7e6a14e, 0x57106490, 0xf63671ae, 0x46c0b470, 0x6fbe4474, 0xdf4881aa, 0x74b62569, 0xc440e0b7, 0xed3e10b3, 0x5dc8d56d, 0xfceec053, 0x4c18058d, 0x6566f589, 0xd5903057, 0xd1919001, 0x616755df, 0x4819a5db, 0xf8ef6005, 0x59c9753b, 0xe93fb0e5, 0xc04140e1, 0x70b7853f, 0xf5fec26b, 0x450807b5, 0x6c76f7b1, 0xdc80326f, 0x7da62751, 0xcd50e28f, 0xe42e128b, 0x54d8d755, 0x50d97703, 0xe02fb2dd, 0xc95142d9, 0x79a78707, 0xd8819239, 0x687757e7, 0x4109a7e3, 0xf1ff623d, 0x5a01c6fe, 0xeaf70320, 0xc389f324, 0x737f36fa, 0xd25923c4, 0x62afe61a, 0x4bd1161e, 0xfb27d3c0, 0xff267396, 0x4fd0b648, 0x66ae464c, 0xd6588392, 0x777e96ac, 0xc7885372, 0xeef6a376, 0x5e0066a8, 0x2eb7e397, 0x9e412649, 0xb73fd64d, 0x07c91393, 0xa6ef06ad, 0x1619c373, 0x3f673377, 0x8f91f6a9, 0x8b9056ff, 0x3b669321, 0x12186325, 0xa2eea6fb, 0x03c8b3c5, 0xb33e761b, 0x9a40861f, 0x2ab643c1, 0x8148e702, 0x31be22dc, 0x18c0d2d8, 0xa8361706, 0x09100238, 0xb9e6c7e6, 0x909837e2, 0x206ef23c, 0x246f526a, 0x949997b4, 0xbde767b0, 0x0d11a26e, 0xac37b750, 0x1cc1728e, 0x35bf828a, 0x85494754, 0xb053eb9e, 0x00a52e40, 0x29dbde44, 0x992d1b9a, 0x380b0ea4, 0x88fdcb7a, 0xa1833b7e, 0x1175fea0, 0x15745ef6, 0xa5829b28, 0x8cfc6b2c, 0x3c0aaef2, 0x9d2cbbcc, 0x2dda7e12, 0x04a48e16, 0xb4524bc8, 0x1facef0b, 0xaf5a2ad5, 0x8624dad1, 0x36d21f0f, 0x97f40a31, 0x2702cfef, 0x0e7c3feb, 0xbe8afa35, 0xba8b5a63, 0x0a7d9fbd, 0x23036fb9, 0x93f5aa67, 0x32d3bf59, 0x82257a87, 0xab5b8a83, 0x1bad4f5d, 0x6b1aca62, 0xdbec0fbc, 0xf292ffb8, 0x42643a66, 0xe3422f58, 0x53b4ea86, 0x7aca1a82, 0xca3cdf5c, 0xce3d7f0a, 0x7ecbbad4, 0x57b54ad0, 0xe7438f0e, 0x46659a30, 0xf6935fee, 0xdfedafea, 0x6f1b6a34, 0xc4e5cef7, 0x74130b29, 0x5d6dfb2d, 0xed9b3ef3, 0x4cbd2bcd, 0xfc4bee13, 0xd5351e17, 0x65c3dbc9, 0x61c27b9f, 0xd134be41, 0xf84a4e45, 0x48bc8b9b, 0xe99a9ea5, 0x596c5b7b, 0x7012ab7f, 0xc0e46ea1, 0x45ad29f5, 0xf55bec2b, 0xdc251c2f, 0x6cd3d9f1, 0xcdf5cccf, 0x7d030911, 0x547df915, 0xe48b3ccb, 0xe08a9c9d, 0x507c5943, 0x7902a947, 0xc9f46c99, 0x68d279a7, 0xd824bc79, 0xf15a4c7d, 0x41ac89a3, 0xea522d60, 0x5aa4e8be, 0x73da18ba, 0xc32cdd64, 0x620ac85a, 0xd2fc0d84, 0xfb82fd80, 0x4b74385e, 0x4f759808, 0xff835dd6, 0xd6fdadd2, 0x660b680c, 0xc72d7d32, 0x77dbb8ec, 0x5ea548e8, 0xee538d36, 0x9ee40809, 0x2e12cdd7, 0x076c3dd3, 0xb79af80d, 0x16bced33, 0xa64a28ed, 0x8f34d8e9, 0x3fc21d37, 0x3bc3bd61, 0x8b3578bf, 0xa24b88bb, 0x12bd4d65, 0xb39b585b, 0x036d9d85, 0x2a136d81, 0x9ae5a85f, 0x311b0c9c, 0x81edc942, 0xa8933946, 0x1865fc98, 0xb943e9a6, 0x09b52c78, 0x20cbdc7c, 0x903d19a2, 0x943cb9f4, 0x24ca7c2a, 0x0db48c2e, 0xbd4249f0, 0x1c645cce, 0xac929910, 0x85ec6914, 0x351aacca +}, +{ +0x00000000, 0xe18fd649, 0x72eabc07, 0x93656a4e, 0x1a0b833d, 0xfb845574, 0x68e13f3a, 0x896ee973, 0x1d52dae9, 0xfcdd0ca0, 0x6fb866ee, 0x8e37b0a7, 0x075959d4, 0xe6d68f9d, 0x75b3e5d3, 0x943c339a, 0xa0dc5f59, 0x41538910, 0xd236e35e, 0x33b93517, 0xbad7dc64, 0x5b580a2d, 0xc83d6063, 0x29b2b62a, 0xbd8e85b0, 0x5c0153f9, 0xcf6439b7, 0x2eebeffe, 0xa785068d, 0x460ad0c4, 0xd56fba8a, 0x34e06cc3, 0xbc00e687, 0x5d8f30ce, 0xceea5a80, 0x2f658cc9, 0xa60b65ba, 0x4784b3f3, 0xd4e1d9bd, 0x356e0ff4, 0xa1523c6e, 0x40ddea27, 0xd3b88069, 0x32375620, 0xbb59bf53, 0x5ad6691a, 0xc9b30354, 0x283cd51d, 0x1cdcb9de, 0xfd536f97, 0x6e3605d9, 0x8fb9d390, 0x06d73ae3, 0xe758ecaa, 0x743d86e4, 0x95b250ad, 0x018e6337, 0xe001b57e, 0x7364df30, 0x92eb0979, 0x1b85e00a, 0xfa0a3643, 0x696f5c0d, 0x88e08a44, 0xbab786ce, 0x5b385087, 0xc85d3ac9, 0x29d2ec80, 0xa0bc05f3, 0x4133d3ba, 0xd256b9f4, 0x33d96fbd, 0xa7e55c27, 0x466a8a6e, 0xd50fe020, 0x34803669, 0xbdeedf1a, 0x5c610953, 0xcf04631d, 0x2e8bb554, 0x1a6bd997, 0xfbe40fde, 0x68816590, 0x890eb3d9, 0x00605aaa, 0xe1ef8ce3, 0x728ae6ad, 0x930530e4, 0x0739037e, 0xe6b6d537, 0x75d3bf79, 0x945c6930, 0x1d328043, 0xfcbd560a, 0x6fd83c44, 0x8e57ea0d, 0x06b76049, 0xe738b600, 0x745ddc4e, 0x95d20a07, 0x1cbce374, 0xfd33353d, 0x6e565f73, 0x8fd9893a, 0x1be5baa0, 0xfa6a6ce9, 0x690f06a7, 0x8880d0ee, 0x01ee399d, 0xe061efd4, 0x7304859a, 0x928b53d3, 0xa66b3f10, 0x47e4e959, 0xd4818317, 0x350e555e, 0xbc60bc2d, 0x5def6a64, 0xce8a002a, 0x2f05d663, 0xbb39e5f9, 0x5ab633b0, 0xc9d359fe, 0x285c8fb7, 0xa13266c4, 0x40bdb08d, 0xd3d8dac3, 0x32570c8a, 0x6e773e0e, 0x8ff8e847, 0x1c9d8209, 0xfd125440, 0x747cbd33, 0x95f36b7a, 0x06960134, 0xe719d77d, 0x7325e4e7, 0x92aa32ae, 0x01cf58e0, 0xe0408ea9, 0x692e67da, 0x88a1b193, 0x1bc4dbdd, 0xfa4b0d94, 0xceab6157, 0x2f24b71e, 0xbc41dd50, 0x5dce0b19, 0xd4a0e26a, 0x352f3423, 0xa64a5e6d, 0x47c58824, 0xd3f9bbbe, 0x32766df7, 0xa11307b9, 0x409cd1f0, 0xc9f23883, 0x287deeca, 0xbb188484, 0x5a9752cd, 0xd277d889, 0x33f80ec0, 0xa09d648e, 0x4112b2c7, 0xc87c5bb4, 0x29f38dfd, 0xba96e7b3, 0x5b1931fa, 0xcf250260, 0x2eaad429, 0xbdcfbe67, 0x5c40682e, 0xd52e815d, 0x34a15714, 0xa7c43d5a, 0x464beb13, 0x72ab87d0, 0x93245199, 0x00413bd7, 0xe1ceed9e, 0x68a004ed, 0x892fd2a4, 0x1a4ab8ea, 0xfbc56ea3, 0x6ff95d39, 0x8e768b70, 0x1d13e13e, 0xfc9c3777, 0x75f2de04, 0x947d084d, 0x07186203, 0xe697b44a, 0xd4c0b8c0, 0x354f6e89, 0xa62a04c7, 0x47a5d28e, 0xcecb3bfd, 0x2f44edb4, 0xbc2187fa, 0x5dae51b3, 0xc9926229, 0x281db460, 0xbb78de2e, 0x5af70867, 0xd399e114, 0x3216375d, 0xa1735d13, 0x40fc8b5a, 0x741ce799, 0x959331d0, 0x06f65b9e, 0xe7798dd7, 0x6e1764a4, 0x8f98b2ed, 0x1cfdd8a3, 0xfd720eea, 0x694e3d70, 0x88c1eb39, 0x1ba48177, 0xfa2b573e, 0x7345be4d, 0x92ca6804, 0x01af024a, 0xe020d403, 0x68c05e47, 0x894f880e, 0x1a2ae240, 0xfba53409, 0x72cbdd7a, 0x93440b33, 0x0021617d, 0xe1aeb734, 0x759284ae, 0x941d52e7, 0x077838a9, 0xe6f7eee0, 0x6f990793, 0x8e16d1da, 0x1d73bb94, 0xfcfc6ddd, 0xc81c011e, 0x2993d757, 0xbaf6bd19, 0x5b796b50, 0xd2178223, 0x3398546a, 0xa0fd3e24, 0x4172e86d, 0xd54edbf7, 0x34c10dbe, 0xa7a467f0, 0x462bb1b9, 0xcf4558ca, 0x2eca8e83, 0xbdafe4cd, 0x5c203284 +}, +{ +0x00000000, 0x1173c7ef, 0x92cba0f7, 0x83b86718, 0x0ac2329b, 0x1bb1f574, 0x9809926c, 0x897a5583, 0x0ff6cd90, 0x1e850a7f, 0x9d3d6d67, 0x8c4eaa88, 0x0534ff0b, 0x144738e4, 0x97ff5ffc, 0x868c9813, 0xe9256474, 0xf856a39b, 0x7beec483, 0x6a9d036c, 0xe3e756ef, 0xf2949100, 0x712cf618, 0x605f31f7, 0xe6d3a9e4, 0xf7a06e0b, 0x74180913, 0x656bcefc, 0xec119b7f, 0xfd625c90, 0x7eda3b88, 0x6fa9fc67, 0xfd653d73, 0xec16fa9c, 0x6fae9d84, 0x7edd5a6b, 0xf7a70fe8, 0xe6d4c807, 0x656caf1f, 0x741f68f0, 0xf293f0e3, 0xe3e0370c, 0x60585014, 0x712b97fb, 0xf851c278, 0xe9220597, 0x6a9a628f, 0x7be9a560, 0x14405907, 0x05339ee8, 0x868bf9f0, 0x97f83e1f, 0x1e826b9c, 0x0ff1ac73, 0x8c49cb6b, 0x9d3a0c84, 0x1bb69497, 0x0ac55378, 0x897d3460, 0x980ef38f, 0x1174a60c, 0x000761e3, 0x83bf06fb, 0x92ccc114, 0xb746001c, 0xa635c7f3, 0x258da0eb, 0x34fe6704, 0xbd843287, 0xacf7f568, 0x2f4f9270, 0x3e3c559f, 0xb8b0cd8c, 0xa9c30a63, 0x2a7b6d7b, 0x3b08aa94, 0xb272ff17, 0xa30138f8, 0x20b95fe0, 0x31ca980f, 0x5e636468, 0x4f10a387, 0xcca8c49f, 0xdddb0370, 0x54a156f3, 0x45d2911c, 0xc66af604, 0xd71931eb, 0x5195a9f8, 0x40e66e17, 0xc35e090f, 0xd22dcee0, 0x5b579b63, 0x4a245c8c, 0xc99c3b94, 0xd8effc7b, 0x4a233d6f, 0x5b50fa80, 0xd8e89d98, 0xc99b5a77, 0x40e10ff4, 0x5192c81b, 0xd22aaf03, 0xc35968ec, 0x45d5f0ff, 0x54a63710, 0xd71e5008, 0xc66d97e7, 0x4f17c264, 0x5e64058b, 0xdddc6293, 0xccafa57c, 0xa306591b, 0xb2759ef4, 0x31cdf9ec, 0x20be3e03, 0xa9c46b80, 0xb8b7ac6f, 0x3b0fcb77, 0x2a7c0c98, 0xacf0948b, 0xbd835364, 0x3e3b347c, 0x2f48f393, 0xa632a610, 0xb74161ff, 0x34f906e7, 0x258ac108, 0x1cd3b7ee, 0x0da07001, 0x8e181719, 0x9f6bd0f6, 0x16118575, 0x0762429a, 0x84da2582, 0x95a9e26d, 0x13257a7e, 0x0256bd91, 0x81eeda89, 0x909d1d66, 0x19e748e5, 0x08948f0a, 0x8b2ce812, 0x9a5f2ffd, 0xf5f6d39a, 0xe4851475, 0x673d736d, 0x764eb482, 0xff34e101, 0xee4726ee, 0x6dff41f6, 0x7c8c8619, 0xfa001e0a, 0xeb73d9e5, 0x68cbbefd, 0x79b87912, 0xf0c22c91, 0xe1b1eb7e, 0x62098c66, 0x737a4b89, 0xe1b68a9d, 0xf0c54d72, 0x737d2a6a, 0x620eed85, 0xeb74b806, 0xfa077fe9, 0x79bf18f1, 0x68ccdf1e, 0xee40470d, 0xff3380e2, 0x7c8be7fa, 0x6df82015, 0xe4827596, 0xf5f1b279, 0x7649d561, 0x673a128e, 0x0893eee9, 0x19e02906, 0x9a584e1e, 0x8b2b89f1, 0x0251dc72, 0x13221b9d, 0x909a7c85, 0x81e9bb6a, 0x07652379, 0x1616e496, 0x95ae838e, 0x84dd4461, 0x0da711e2, 0x1cd4d60d, 0x9f6cb115, 0x8e1f76fa, 0xab95b7f2, 0xbae6701d, 0x395e1705, 0x282dd0ea, 0xa1578569, 0xb0244286, 0x339c259e, 0x22efe271, 0xa4637a62, 0xb510bd8d, 0x36a8da95, 0x27db1d7a, 0xaea148f9, 0xbfd28f16, 0x3c6ae80e, 0x2d192fe1, 0x42b0d386, 0x53c31469, 0xd07b7371, 0xc108b49e, 0x4872e11d, 0x590126f2, 0xdab941ea, 0xcbca8605, 0x4d461e16, 0x5c35d9f9, 0xdf8dbee1, 0xcefe790e, 0x47842c8d, 0x56f7eb62, 0xd54f8c7a, 0xc43c4b95, 0x56f08a81, 0x47834d6e, 0xc43b2a76, 0xd548ed99, 0x5c32b81a, 0x4d417ff5, 0xcef918ed, 0xdf8adf02, 0x59064711, 0x487580fe, 0xcbcde7e6, 0xdabe2009, 0x53c4758a, 0x42b7b265, 0xc10fd57d, 0xd07c1292, 0xbfd5eef5, 0xaea6291a, 0x2d1e4e02, 0x3c6d89ed, 0xb517dc6e, 0xa4641b81, 0x27dc7c99, 0x36afbb76, 0xb0232365, 0xa150e48a, 0x22e88392, 0x339b447d, 0xbae111fe, 0xab92d611, 0x282ab109, 0x395976e6 +}, +{ +0x00000000, 0x8d497497, 0x5f19bbf6, 0xd250cf61, 0x328f45a8, 0xbfc6313f, 0x6d96fe5e, 0xe0df8ac9, 0x9105e1fe, 0x1c4c9569, 0xce1c5a08, 0x43552e9f, 0xa38aa456, 0x2ec3d0c1, 0xfc931fa0, 0x71da6b37, 0xf65ebaa1, 0x7b17ce36, 0xa9470157, 0x240e75c0, 0xc4d1ff09, 0x49988b9e, 0x9bc844ff, 0x16813068, 0x675b5b5f, 0xea122fc8, 0x3842e0a9, 0xb50b943e, 0x55d41ef7, 0xd89d6a60, 0x0acda501, 0x8784d196, 0xd000aaad, 0x5d49de3a, 0x8f19115b, 0x025065cc, 0xe28fef05, 0x6fc69b92, 0xbd9654f3, 0x30df2064, 0x41054b53, 0xcc4c3fc4, 0x1e1cf0a5, 0x93558432, 0x738a0efb, 0xfec37a6c, 0x2c93b50d, 0xa1dac19a, 0x265e100c, 0xab17649b, 0x7947abfa, 0xf40edf6d, 0x14d155a4, 0x99982133, 0x4bc8ee52, 0xc6819ac5, 0xb75bf1f2, 0x3a128565, 0xe8424a04, 0x650b3e93, 0x85d4b45a, 0x089dc0cd, 0xdacd0fac, 0x57847b3b, 0xf6fe0c97, 0x7bb77800, 0xa9e7b761, 0x24aec3f6, 0xc471493f, 0x49383da8, 0x9b68f2c9, 0x1621865e, 0x67fbed69, 0xeab299fe, 0x38e2569f, 0xb5ab2208, 0x5574a8c1, 0xd83ddc56, 0x0a6d1337, 0x872467a0, 0x00a0b636, 0x8de9c2a1, 0x5fb90dc0, 0xd2f07957, 0x322ff39e, 0xbf668709, 0x6d364868, 0xe07f3cff, 0x91a557c8, 0x1cec235f, 0xcebcec3e, 0x43f598a9, 0xa32a1260, 0x2e6366f7, 0xfc33a996, 0x717add01, 0x26fea63a, 0xabb7d2ad, 0x79e71dcc, 0xf4ae695b, 0x1471e392, 0x99389705, 0x4b685864, 0xc6212cf3, 0xb7fb47c4, 0x3ab23353, 0xe8e2fc32, 0x65ab88a5, 0x8574026c, 0x083d76fb, 0xda6db99a, 0x5724cd0d, 0xd0a01c9b, 0x5de9680c, 0x8fb9a76d, 0x02f0d3fa, 0xe22f5933, 0x6f662da4, 0xbd36e2c5, 0x307f9652, 0x41a5fd65, 0xccec89f2, 0x1ebc4693, 0x93f53204, 0x732ab8cd, 0xfe63cc5a, 0x2c33033b, 0xa17a77ac, 0x4a5b9322, 0xc712e7b5, 0x154228d4, 0x980b5c43, 0x78d4d68a, 0xf59da21d, 0x27cd6d7c, 0xaa8419eb, 0xdb5e72dc, 0x5617064b, 0x8447c92a, 0x090ebdbd, 0xe9d13774, 0x649843e3, 0xb6c88c82, 0x3b81f815, 0xbc052983, 0x314c5d14, 0xe31c9275, 0x6e55e6e2, 0x8e8a6c2b, 0x03c318bc, 0xd193d7dd, 0x5cdaa34a, 0x2d00c87d, 0xa049bcea, 0x7219738b, 0xff50071c, 0x1f8f8dd5, 0x92c6f942, 0x40963623, 0xcddf42b4, 0x9a5b398f, 0x17124d18, 0xc5428279, 0x480bf6ee, 0xa8d47c27, 0x259d08b0, 0xf7cdc7d1, 0x7a84b346, 0x0b5ed871, 0x8617ace6, 0x54476387, 0xd90e1710, 0x39d19dd9, 0xb498e94e, 0x66c8262f, 0xeb8152b8, 0x6c05832e, 0xe14cf7b9, 0x331c38d8, 0xbe554c4f, 0x5e8ac686, 0xd3c3b211, 0x01937d70, 0x8cda09e7, 0xfd0062d0, 0x70491647, 0xa219d926, 0x2f50adb1, 0xcf8f2778, 0x42c653ef, 0x90969c8e, 0x1ddfe819, 0xbca59fb5, 0x31eceb22, 0xe3bc2443, 0x6ef550d4, 0x8e2ada1d, 0x0363ae8a, 0xd13361eb, 0x5c7a157c, 0x2da07e4b, 0xa0e90adc, 0x72b9c5bd, 0xfff0b12a, 0x1f2f3be3, 0x92664f74, 0x40368015, 0xcd7ff482, 0x4afb2514, 0xc7b25183, 0x15e29ee2, 0x98abea75, 0x787460bc, 0xf53d142b, 0x276ddb4a, 0xaa24afdd, 0xdbfec4ea, 0x56b7b07d, 0x84e77f1c, 0x09ae0b8b, 0xe9718142, 0x6438f5d5, 0xb6683ab4, 0x3b214e23, 0x6ca53518, 0xe1ec418f, 0x33bc8eee, 0xbef5fa79, 0x5e2a70b0, 0xd3630427, 0x0133cb46, 0x8c7abfd1, 0xfda0d4e6, 0x70e9a071, 0xa2b96f10, 0x2ff01b87, 0xcf2f914e, 0x4266e5d9, 0x90362ab8, 0x1d7f5e2f, 0x9afb8fb9, 0x17b2fb2e, 0xc5e2344f, 0x48ab40d8, 0xa874ca11, 0x253dbe86, 0xf76d71e7, 0x7a240570, 0x0bfe6e47, 0x86b71ad0, 0x54e7d5b1, 0xd9aea126, 0x39712bef, 0xb4385f78, 0x66689019, 0xeb21e48e +}, +{ +0x00000000, 0x6ab7161e, 0x266cca95, 0x4cdbdc8b, 0xf875dd07, 0x92c2cb19, 0xde191792, 0xb4ae018c, 0x19b7e8f8, 0x7300fee6, 0x3fdb226d, 0x556c3473, 0xe1c235ff, 0x8b7523e1, 0xc7aeff6a, 0xad19e974, 0x9fc16ec1, 0xf57678df, 0xb9ada454, 0xd31ab24a, 0x67b4b3c6, 0x0d03a5d8, 0x41d87953, 0x2b6f6f4d, 0x86768639, 0xecc19027, 0xa01a4cac, 0xcaad5ab2, 0x7e035b3e, 0x14b44d20, 0x586f91ab, 0x32d887b5, 0xdb0af858, 0xb1bdee46, 0xfd6632cd, 0x97d124d3, 0x237f255f, 0x49c83341, 0x0513efca, 0x6fa4f9d4, 0xc2bd10a0, 0xa80a06be, 0xe4d1da35, 0x8e66cc2b, 0x3ac8cda7, 0x507fdbb9, 0x1ca40732, 0x7613112c, 0x44cb9699, 0x2e7c8087, 0x62a75c0c, 0x08104a12, 0xbcbe4b9e, 0xd6095d80, 0x9ad2810b, 0xf0659715, 0x5d7c7e61, 0x37cb687f, 0x7b10b4f4, 0x11a7a2ea, 0xa509a366, 0xcfbeb578, 0x836569f3, 0xe9d27fed, 0x4694ec2d, 0x2c23fa33, 0x60f826b8, 0x0a4f30a6, 0xbee1312a, 0xd4562734, 0x988dfbbf, 0xf23aeda1, 0x5f2304d5, 0x359412cb, 0x794fce40, 0x13f8d85e, 0xa756d9d2, 0xcde1cfcc, 0x813a1347, 0xeb8d0559, 0xd95582ec, 0xb3e294f2, 0xff394879, 0x958e5e67, 0x21205feb, 0x4b9749f5, 0x074c957e, 0x6dfb8360, 0xc0e26a14, 0xaa557c0a, 0xe68ea081, 0x8c39b69f, 0x3897b713, 0x5220a10d, 0x1efb7d86, 0x744c6b98, 0x9d9e1475, 0xf729026b, 0xbbf2dee0, 0xd145c8fe, 0x65ebc972, 0x0f5cdf6c, 0x438703e7, 0x293015f9, 0x8429fc8d, 0xee9eea93, 0xa2453618, 0xc8f22006, 0x7c5c218a, 0x16eb3794, 0x5a30eb1f, 0x3087fd01, 0x025f7ab4, 0x68e86caa, 0x2433b021, 0x4e84a63f, 0xfa2aa7b3, 0x909db1ad, 0xdc466d26, 0xb6f17b38, 0x1be8924c, 0x715f8452, 0x3d8458d9, 0x57334ec7, 0xe39d4f4b, 0x892a5955, 0xc5f185de, 0xaf4693c0, 0x54627905, 0x3ed56f1b, 0x720eb390, 0x18b9a58e, 0xac17a402, 0xc6a0b21c, 0x8a7b6e97, 0xe0cc7889, 0x4dd591fd, 0x276287e3, 0x6bb95b68, 0x010e4d76, 0xb5a04cfa, 0xdf175ae4, 0x93cc866f, 0xf97b9071, 0xcba317c4, 0xa11401da, 0xedcfdd51, 0x8778cb4f, 0x33d6cac3, 0x5961dcdd, 0x15ba0056, 0x7f0d1648, 0xd214ff3c, 0xb8a3e922, 0xf47835a9, 0x9ecf23b7, 0x2a61223b, 0x40d63425, 0x0c0de8ae, 0x66bafeb0, 0x8f68815d, 0xe5df9743, 0xa9044bc8, 0xc3b35dd6, 0x771d5c5a, 0x1daa4a44, 0x517196cf, 0x3bc680d1, 0x96df69a5, 0xfc687fbb, 0xb0b3a330, 0xda04b52e, 0x6eaab4a2, 0x041da2bc, 0x48c67e37, 0x22716829, 0x10a9ef9c, 0x7a1ef982, 0x36c52509, 0x5c723317, 0xe8dc329b, 0x826b2485, 0xceb0f80e, 0xa407ee10, 0x091e0764, 0x63a9117a, 0x2f72cdf1, 0x45c5dbef, 0xf16bda63, 0x9bdccc7d, 0xd70710f6, 0xbdb006e8, 0x12f69528, 0x78418336, 0x349a5fbd, 0x5e2d49a3, 0xea83482f, 0x80345e31, 0xccef82ba, 0xa65894a4, 0x0b417dd0, 0x61f66bce, 0x2d2db745, 0x479aa15b, 0xf334a0d7, 0x9983b6c9, 0xd5586a42, 0xbfef7c5c, 0x8d37fbe9, 0xe780edf7, 0xab5b317c, 0xc1ec2762, 0x754226ee, 0x1ff530f0, 0x532eec7b, 0x3999fa65, 0x94801311, 0xfe37050f, 0xb2ecd984, 0xd85bcf9a, 0x6cf5ce16, 0x0642d808, 0x4a990483, 0x202e129d, 0xc9fc6d70, 0xa34b7b6e, 0xef90a7e5, 0x8527b1fb, 0x3189b077, 0x5b3ea669, 0x17e57ae2, 0x7d526cfc, 0xd04b8588, 0xbafc9396, 0xf6274f1d, 0x9c905903, 0x283e588f, 0x42894e91, 0x0e52921a, 0x64e58404, 0x563d03b1, 0x3c8a15af, 0x7051c924, 0x1ae6df3a, 0xae48deb6, 0xc4ffc8a8, 0x88241423, 0xe293023d, 0x4f8aeb49, 0x253dfd57, 0x69e621dc, 0x035137c2, 0xb7ff364e, 0xdd482050, 0x9193fcdb, 0xfb24eac5 +}, +{ +0x00000000, 0x65d95217, 0x1ff27278, 0x7a2b206f, 0xe27874a2, 0x87a126b5, 0xfd8a06da, 0x985354cd, 0x486b19dd, 0x2db24bca, 0x57996ba5, 0x324039b2, 0xaa136d7f, 0xcfca3f68, 0xb5e11f07, 0xd0384d10, 0xfb7dcaa1, 0x9ea498b6, 0xe48fb8d9, 0x8156eace, 0x1905be03, 0x7cdcec14, 0x06f7cc7b, 0x632e9e6c, 0xb316d37c, 0xd6cf816b, 0xace4a104, 0xc93df313, 0x516ea7de, 0x34b7f5c9, 0x4e9cd5a6, 0x2b4587b1, 0xc22ccd39, 0xa7f59f2e, 0xdddebf41, 0xb807ed56, 0x2054b99b, 0x458deb8c, 0x3fa6cbe3, 0x5a7f99f4, 0x8a47d4e4, 0xef9e86f3, 0x95b5a69c, 0xf06cf48b, 0x683fa046, 0x0de6f251, 0x77cdd23e, 0x12148029, 0x39510798, 0x5c88558f, 0x26a375e0, 0x437a27f7, 0xdb29733a, 0xbef0212d, 0xc4db0142, 0xa1025355, 0x713a1e45, 0x14e34c52, 0x6ec86c3d, 0x0b113e2a, 0x93426ae7, 0xf69b38f0, 0x8cb0189f, 0xe9694a88, 0xf25d2168, 0x9784737f, 0xedaf5310, 0x88760107, 0x102555ca, 0x75fc07dd, 0x0fd727b2, 0x6a0e75a5, 0xba3638b5, 0xdfef6aa2, 0xa5c44acd, 0xc01d18da, 0x584e4c17, 0x3d971e00, 0x47bc3e6f, 0x22656c78, 0x0920ebc9, 0x6cf9b9de, 0x16d299b1, 0x730bcba6, 0xeb589f6b, 0x8e81cd7c, 0xf4aaed13, 0x9173bf04, 0x414bf214, 0x2492a003, 0x5eb9806c, 0x3b60d27b, 0xa33386b6, 0xc6ead4a1, 0xbcc1f4ce, 0xd918a6d9, 0x3071ec51, 0x55a8be46, 0x2f839e29, 0x4a5acc3e, 0xd20998f3, 0xb7d0cae4, 0xcdfbea8b, 0xa822b89c, 0x781af58c, 0x1dc3a79b, 0x67e887f4, 0x0231d5e3, 0x9a62812e, 0xffbbd339, 0x8590f356, 0xe049a141, 0xcb0c26f0, 0xaed574e7, 0xd4fe5488, 0xb127069f, 0x29745252, 0x4cad0045, 0x3686202a, 0x535f723d, 0x83673f2d, 0xe6be6d3a, 0x9c954d55, 0xf94c1f42, 0x611f4b8f, 0x04c61998, 0x7eed39f7, 0x1b346be0, 0x2f4f8bb4, 0x4a96d9a3, 0x30bdf9cc, 0x5564abdb, 0xcd37ff16, 0xa8eead01, 0xd2c58d6e, 0xb71cdf79, 0x67249269, 0x02fdc07e, 0x78d6e011, 0x1d0fb206, 0x855ce6cb, 0xe085b4dc, 0x9aae94b3, 0xff77c6a4, 0xd4324115, 0xb1eb1302, 0xcbc0336d, 0xae19617a, 0x364a35b7, 0x539367a0, 0x29b847cf, 0x4c6115d8, 0x9c5958c8, 0xf9800adf, 0x83ab2ab0, 0xe67278a7, 0x7e212c6a, 0x1bf87e7d, 0x61d35e12, 0x040a0c05, 0xed63468d, 0x88ba149a, 0xf29134f5, 0x974866e2, 0x0f1b322f, 0x6ac26038, 0x10e94057, 0x75301240, 0xa5085f50, 0xc0d10d47, 0xbafa2d28, 0xdf237f3f, 0x47702bf2, 0x22a979e5, 0x5882598a, 0x3d5b0b9d, 0x161e8c2c, 0x73c7de3b, 0x09ecfe54, 0x6c35ac43, 0xf466f88e, 0x91bfaa99, 0xeb948af6, 0x8e4dd8e1, 0x5e7595f1, 0x3bacc7e6, 0x4187e789, 0x245eb59e, 0xbc0de153, 0xd9d4b344, 0xa3ff932b, 0xc626c13c, 0xdd12aadc, 0xb8cbf8cb, 0xc2e0d8a4, 0xa7398ab3, 0x3f6ade7e, 0x5ab38c69, 0x2098ac06, 0x4541fe11, 0x9579b301, 0xf0a0e116, 0x8a8bc179, 0xef52936e, 0x7701c7a3, 0x12d895b4, 0x68f3b5db, 0x0d2ae7cc, 0x266f607d, 0x43b6326a, 0x399d1205, 0x5c444012, 0xc41714df, 0xa1ce46c8, 0xdbe566a7, 0xbe3c34b0, 0x6e0479a0, 0x0bdd2bb7, 0x71f60bd8, 0x142f59cf, 0x8c7c0d02, 0xe9a55f15, 0x938e7f7a, 0xf6572d6d, 0x1f3e67e5, 0x7ae735f2, 0x00cc159d, 0x6515478a, 0xfd461347, 0x989f4150, 0xe2b4613f, 0x876d3328, 0x57557e38, 0x328c2c2f, 0x48a70c40, 0x2d7e5e57, 0xb52d0a9a, 0xd0f4588d, 0xaadf78e2, 0xcf062af5, 0xe443ad44, 0x819aff53, 0xfbb1df3c, 0x9e688d2b, 0x063bd9e6, 0x63e28bf1, 0x19c9ab9e, 0x7c10f989, 0xac28b499, 0xc9f1e68e, 0xb3dac6e1, 0xd60394f6, 0x4e50c03b, 0x2b89922c, 0x51a2b243, 0x347be054 +}, +{ +0x00000000, 0x209b48fb, 0x9c9675de, 0xbc0d3d25, 0x9ab8fb07, 0xba23b3fc, 0x062e8ed9, 0x26b5c622, 0x0ba1c868, 0x2b3a8093, 0x9737bdb6, 0xb7acf54d, 0x9119336f, 0xb1827b94, 0x0d8f46b1, 0x2d140e4a, 0x941e82a6, 0xb485ca5d, 0x0888f778, 0x2813bf83, 0x0ea679a1, 0x2e3d315a, 0x92300c7f, 0xb2ab4484, 0x9fbf4ace, 0xbf240235, 0x03293f10, 0x23b277eb, 0x0507b1c9, 0x259cf932, 0x9991c417, 0xb90a8cec, 0xdf652aa6, 0xfffe625d, 0x43f35f78, 0x63681783, 0x45ddd1a1, 0x6546995a, 0xd94ba47f, 0xf9d0ec84, 0xd4c4e2ce, 0xf45faa35, 0x48529710, 0x68c9dfeb, 0x4e7c19c9, 0x6ee75132, 0xd2ea6c17, 0xf27124ec, 0x4b7ba800, 0x6be0e0fb, 0xd7edddde, 0xf7769525, 0xd1c35307, 0xf1581bfc, 0x4d5526d9, 0x6dce6e22, 0x40da6068, 0x60412893, 0xdc4c15b6, 0xfcd75d4d, 0xda629b6f, 0xfaf9d394, 0x46f4eeb1, 0x666fa64a, 0x4e4594bc, 0x6ededc47, 0xd2d3e162, 0xf248a999, 0xd4fd6fbb, 0xf4662740, 0x486b1a65, 0x68f0529e, 0x45e45cd4, 0x657f142f, 0xd972290a, 0xf9e961f1, 0xdf5ca7d3, 0xffc7ef28, 0x43cad20d, 0x63519af6, 0xda5b161a, 0xfac05ee1, 0x46cd63c4, 0x66562b3f, 0x40e3ed1d, 0x6078a5e6, 0xdc7598c3, 0xfceed038, 0xd1fade72, 0xf1619689, 0x4d6cabac, 0x6df7e357, 0x4b422575, 0x6bd96d8e, 0xd7d450ab, 0xf74f1850, 0x9120be1a, 0xb1bbf6e1, 0x0db6cbc4, 0x2d2d833f, 0x0b98451d, 0x2b030de6, 0x970e30c3, 0xb7957838, 0x9a817672, 0xba1a3e89, 0x061703ac, 0x268c4b57, 0x00398d75, 0x20a2c58e, 0x9caff8ab, 0xbc34b050, 0x053e3cbc, 0x25a57447, 0x99a84962, 0xb9330199, 0x9f86c7bb, 0xbf1d8f40, 0x0310b265, 0x238bfa9e, 0x0e9ff4d4, 0x2e04bc2f, 0x9209810a, 0xb292c9f1, 0x94270fd3, 0xb4bc4728, 0x08b17a0d, 0x282a32f6, 0xca74fdfe, 0xeaefb505, 0x56e28820, 0x7679c0db, 0x50cc06f9, 0x70574e02, 0xcc5a7327, 0xecc13bdc, 0xc1d53596, 0xe14e7d6d, 0x5d434048, 0x7dd808b3, 0x5b6dce91, 0x7bf6866a, 0xc7fbbb4f, 0xe760f3b4, 0x5e6a7f58, 0x7ef137a3, 0xc2fc0a86, 0xe267427d, 0xc4d2845f, 0xe449cca4, 0x5844f181, 0x78dfb97a, 0x55cbb730, 0x7550ffcb, 0xc95dc2ee, 0xe9c68a15, 0xcf734c37, 0xefe804cc, 0x53e539e9, 0x737e7112, 0x1511d758, 0x358a9fa3, 0x8987a286, 0xa91cea7d, 0x8fa92c5f, 0xaf3264a4, 0x133f5981, 0x33a4117a, 0x1eb01f30, 0x3e2b57cb, 0x82266aee, 0xa2bd2215, 0x8408e437, 0xa493accc, 0x189e91e9, 0x3805d912, 0x810f55fe, 0xa1941d05, 0x1d992020, 0x3d0268db, 0x1bb7aef9, 0x3b2ce602, 0x8721db27, 0xa7ba93dc, 0x8aae9d96, 0xaa35d56d, 0x1638e848, 0x36a3a0b3, 0x10166691, 0x308d2e6a, 0x8c80134f, 0xac1b5bb4, 0x84316942, 0xa4aa21b9, 0x18a71c9c, 0x383c5467, 0x1e899245, 0x3e12dabe, 0x821fe79b, 0xa284af60, 0x8f90a12a, 0xaf0be9d1, 0x1306d4f4, 0x339d9c0f, 0x15285a2d, 0x35b312d6, 0x89be2ff3, 0xa9256708, 0x102febe4, 0x30b4a31f, 0x8cb99e3a, 0xac22d6c1, 0x8a9710e3, 0xaa0c5818, 0x1601653d, 0x369a2dc6, 0x1b8e238c, 0x3b156b77, 0x87185652, 0xa7831ea9, 0x8136d88b, 0xa1ad9070, 0x1da0ad55, 0x3d3be5ae, 0x5b5443e4, 0x7bcf0b1f, 0xc7c2363a, 0xe7597ec1, 0xc1ecb8e3, 0xe177f018, 0x5d7acd3d, 0x7de185c6, 0x50f58b8c, 0x706ec377, 0xcc63fe52, 0xecf8b6a9, 0xca4d708b, 0xead63870, 0x56db0555, 0x76404dae, 0xcf4ac142, 0xefd189b9, 0x53dcb49c, 0x7347fc67, 0x55f23a45, 0x756972be, 0xc9644f9b, 0xe9ff0760, 0xc4eb092a, 0xe47041d1, 0x587d7cf4, 0x78e6340f, 0x5e53f22d, 0x7ec8bad6, 0xc2c587f3, 0xe25ecf08 +}, +{ +0x00000000, 0x3dc597a0, 0xa3ea6644, 0x9e2ff1e4, 0xf2d3f737, 0xcf166097, 0x51399173, 0x6cfc06d3, 0xf4b4b9eb, 0xc9712e4b, 0x575edfaf, 0x6a9b480f, 0x06674edc, 0x3ba2d97c, 0xa58d2898, 0x9848bf38, 0x8fef0ceb, 0xb22a9b4b, 0x2c056aaf, 0x11c0fd0f, 0x7d3cfbdc, 0x40f96c7c, 0xded69d98, 0xe3130a38, 0x7b5bb500, 0x469e22a0, 0xd8b1d344, 0xe57444e4, 0x89884237, 0xb44dd597, 0x2a622473, 0x17a7b3d3, 0xd1f6a45b, 0xec3333fb, 0x721cc21f, 0x4fd955bf, 0x2325536c, 0x1ee0c4cc, 0x80cf3528, 0xbd0aa288, 0x25421db0, 0x18878a10, 0x86a87bf4, 0xbb6dec54, 0xd791ea87, 0xea547d27, 0x747b8cc3, 0x49be1b63, 0x5e19a8b0, 0x63dc3f10, 0xfdf3cef4, 0xc0365954, 0xacca5f87, 0x910fc827, 0x0f2039c3, 0x32e5ae63, 0xaaad115b, 0x976886fb, 0x0947771f, 0x3482e0bf, 0x587ee66c, 0x65bb71cc, 0xfb948028, 0xc6511788, 0x1465d321, 0x29a04481, 0xb78fb565, 0x8a4a22c5, 0xe6b62416, 0xdb73b3b6, 0x455c4252, 0x7899d5f2, 0xe0d16aca, 0xdd14fd6a, 0x433b0c8e, 0x7efe9b2e, 0x12029dfd, 0x2fc70a5d, 0xb1e8fbb9, 0x8c2d6c19, 0x9b8adfca, 0xa64f486a, 0x3860b98e, 0x05a52e2e, 0x695928fd, 0x549cbf5d, 0xcab34eb9, 0xf776d919, 0x6f3e6621, 0x52fbf181, 0xccd40065, 0xf11197c5, 0x9ded9116, 0xa02806b6, 0x3e07f752, 0x03c260f2, 0xc593777a, 0xf856e0da, 0x6679113e, 0x5bbc869e, 0x3740804d, 0x0a8517ed, 0x94aae609, 0xa96f71a9, 0x3127ce91, 0x0ce25931, 0x92cda8d5, 0xaf083f75, 0xc3f439a6, 0xfe31ae06, 0x601e5fe2, 0x5ddbc842, 0x4a7c7b91, 0x77b9ec31, 0xe9961dd5, 0xd4538a75, 0xb8af8ca6, 0x856a1b06, 0x1b45eae2, 0x26807d42, 0xbec8c27a, 0x830d55da, 0x1d22a43e, 0x20e7339e, 0x4c1b354d, 0x71dea2ed, 0xeff15309, 0xd234c4a9, 0xed93561b, 0xd056c1bb, 0x4e79305f, 0x73bca7ff, 0x1f40a12c, 0x2285368c, 0xbcaac768, 0x816f50c8, 0x1927eff0, 0x24e27850, 0xbacd89b4, 0x87081e14, 0xebf418c7, 0xd6318f67, 0x481e7e83, 0x75dbe923, 0x627c5af0, 0x5fb9cd50, 0xc1963cb4, 0xfc53ab14, 0x90afadc7, 0xad6a3a67, 0x3345cb83, 0x0e805c23, 0x96c8e31b, 0xab0d74bb, 0x3522855f, 0x08e712ff, 0x641b142c, 0x59de838c, 0xc7f17268, 0xfa34e5c8, 0x3c65f240, 0x01a065e0, 0x9f8f9404, 0xa24a03a4, 0xceb60577, 0xf37392d7, 0x6d5c6333, 0x5099f493, 0xc8d14bab, 0xf514dc0b, 0x6b3b2def, 0x56feba4f, 0x3a02bc9c, 0x07c72b3c, 0x99e8dad8, 0xa42d4d78, 0xb38afeab, 0x8e4f690b, 0x106098ef, 0x2da50f4f, 0x4159099c, 0x7c9c9e3c, 0xe2b36fd8, 0xdf76f878, 0x473e4740, 0x7afbd0e0, 0xe4d42104, 0xd911b6a4, 0xb5edb077, 0x882827d7, 0x1607d633, 0x2bc24193, 0xf9f6853a, 0xc433129a, 0x5a1ce37e, 0x67d974de, 0x0b25720d, 0x36e0e5ad, 0xa8cf1449, 0x950a83e9, 0x0d423cd1, 0x3087ab71, 0xaea85a95, 0x936dcd35, 0xff91cbe6, 0xc2545c46, 0x5c7bada2, 0x61be3a02, 0x761989d1, 0x4bdc1e71, 0xd5f3ef95, 0xe8367835, 0x84ca7ee6, 0xb90fe946, 0x272018a2, 0x1ae58f02, 0x82ad303a, 0xbf68a79a, 0x2147567e, 0x1c82c1de, 0x707ec70d, 0x4dbb50ad, 0xd394a149, 0xee5136e9, 0x28002161, 0x15c5b6c1, 0x8bea4725, 0xb62fd085, 0xdad3d656, 0xe71641f6, 0x7939b012, 0x44fc27b2, 0xdcb4988a, 0xe1710f2a, 0x7f5efece, 0x429b696e, 0x2e676fbd, 0x13a2f81d, 0x8d8d09f9, 0xb0489e59, 0xa7ef2d8a, 0x9a2aba2a, 0x04054bce, 0x39c0dc6e, 0x553cdabd, 0x68f94d1d, 0xf6d6bcf9, 0xcb132b59, 0x535b9461, 0x6e9e03c1, 0xf0b1f225, 0xcd746585, 0xa1886356, 0x9c4df4f6, 0x02620512, 0x3fa792b2 +}, +{ +0x00000000, 0xc2a7c31a, 0xb7798caa, 0x75de4fb0, 0xba7233f3, 0x78d5f0e9, 0x0d0bbf59, 0xcfac7c43, 0x40b08ecc, 0x82174dd6, 0xf7c90266, 0x356ec17c, 0xfac2bd3f, 0x38657e25, 0x4dbb3195, 0x8f1cf28f, 0xea2022c5, 0x2887e1df, 0x5d59ae6f, 0x9ffe6d75, 0x50521136, 0x92f5d22c, 0xe72b9d9c, 0x258c5e86, 0xaa90ac09, 0x68376f13, 0x1de920a3, 0xdf4ee3b9, 0x10e29ffa, 0xd2455ce0, 0xa79b1350, 0x653cd04a, 0x783c3c44, 0xba9bff5e, 0xcf45b0ee, 0x0de273f4, 0xc24e0fb7, 0x00e9ccad, 0x7537831d, 0xb7904007, 0x388cb288, 0xfa2b7192, 0x8ff53e22, 0x4d52fd38, 0x82fe817b, 0x40594261, 0x35870dd1, 0xf720cecb, 0x921c1e81, 0x50bbdd9b, 0x2565922b, 0xe7c25131, 0x286e2d72, 0xeac9ee68, 0x9f17a1d8, 0x5db062c2, 0xd2ac904d, 0x100b5357, 0x65d51ce7, 0xa772dffd, 0x68dea3be, 0xaa7960a4, 0xdfa72f14, 0x1d00ec0e, 0x85d9c064, 0x477e037e, 0x32a04cce, 0xf0078fd4, 0x3fabf397, 0xfd0c308d, 0x88d27f3d, 0x4a75bc27, 0xc5694ea8, 0x07ce8db2, 0x7210c202, 0xb0b70118, 0x7f1b7d5b, 0xbdbcbe41, 0xc862f1f1, 0x0ac532eb, 0x6ff9e2a1, 0xad5e21bb, 0xd8806e0b, 0x1a27ad11, 0xd58bd152, 0x172c1248, 0x62f25df8, 0xa0559ee2, 0x2f496c6d, 0xedeeaf77, 0x9830e0c7, 0x5a9723dd, 0x953b5f9e, 0x579c9c84, 0x2242d334, 0xe0e5102e, 0xfde5fc20, 0x3f423f3a, 0x4a9c708a, 0x883bb390, 0x4797cfd3, 0x85300cc9, 0xf0ee4379, 0x32498063, 0xbd5572ec, 0x7ff2b1f6, 0x0a2cfe46, 0xc88b3d5c, 0x0727411f, 0xc5808205, 0xb05ecdb5, 0x72f90eaf, 0x17c5dee5, 0xd5621dff, 0xa0bc524f, 0x621b9155, 0xadb7ed16, 0x6f102e0c, 0x1ace61bc, 0xd869a2a6, 0x57755029, 0x95d29333, 0xe00cdc83, 0x22ab1f99, 0xed0763da, 0x2fa0a0c0, 0x5a7eef70, 0x98d92c6a, 0x82795e7f, 0x40de9d65, 0x3500d2d5, 0xf7a711cf, 0x380b6d8c, 0xfaacae96, 0x8f72e126, 0x4dd5223c, 0xc2c9d0b3, 0x006e13a9, 0x75b05c19, 0xb7179f03, 0x78bbe340, 0xba1c205a, 0xcfc26fea, 0x0d65acf0, 0x68597cba, 0xaafebfa0, 0xdf20f010, 0x1d87330a, 0xd22b4f49, 0x108c8c53, 0x6552c3e3, 0xa7f500f9, 0x28e9f276, 0xea4e316c, 0x9f907edc, 0x5d37bdc6, 0x929bc185, 0x503c029f, 0x25e24d2f, 0xe7458e35, 0xfa45623b, 0x38e2a121, 0x4d3cee91, 0x8f9b2d8b, 0x403751c8, 0x829092d2, 0xf74edd62, 0x35e91e78, 0xbaf5ecf7, 0x78522fed, 0x0d8c605d, 0xcf2ba347, 0x0087df04, 0xc2201c1e, 0xb7fe53ae, 0x755990b4, 0x106540fe, 0xd2c283e4, 0xa71ccc54, 0x65bb0f4e, 0xaa17730d, 0x68b0b017, 0x1d6effa7, 0xdfc93cbd, 0x50d5ce32, 0x92720d28, 0xe7ac4298, 0x250b8182, 0xeaa7fdc1, 0x28003edb, 0x5dde716b, 0x9f79b271, 0x07a09e1b, 0xc5075d01, 0xb0d912b1, 0x727ed1ab, 0xbdd2ade8, 0x7f756ef2, 0x0aab2142, 0xc80ce258, 0x471010d7, 0x85b7d3cd, 0xf0699c7d, 0x32ce5f67, 0xfd622324, 0x3fc5e03e, 0x4a1baf8e, 0x88bc6c94, 0xed80bcde, 0x2f277fc4, 0x5af93074, 0x985ef36e, 0x57f28f2d, 0x95554c37, 0xe08b0387, 0x222cc09d, 0xad303212, 0x6f97f108, 0x1a49beb8, 0xd8ee7da2, 0x174201e1, 0xd5e5c2fb, 0xa03b8d4b, 0x629c4e51, 0x7f9ca25f, 0xbd3b6145, 0xc8e52ef5, 0x0a42edef, 0xc5ee91ac, 0x074952b6, 0x72971d06, 0xb030de1c, 0x3f2c2c93, 0xfd8bef89, 0x8855a039, 0x4af26323, 0x855e1f60, 0x47f9dc7a, 0x322793ca, 0xf08050d0, 0x95bc809a, 0x571b4380, 0x22c50c30, 0xe062cf2a, 0x2fceb369, 0xed697073, 0x98b73fc3, 0x5a10fcd9, 0xd50c0e56, 0x17abcd4c, 0x627582fc, 0xa0d241e6, 0x6f7e3da5, 0xadd9febf, 0xd807b10f, 0x1aa07215 +}, +{ +0x00000000, 0x1527bd2d, 0xa346ac11, 0xb661113c, 0x5bafef84, 0x4e8852a9, 0xf8e94395, 0xedcefeb8, 0x8d14ea64, 0x98335749, 0x2e524675, 0x3b75fb58, 0xd6bb05e0, 0xc39cb8cd, 0x75fda9f1, 0x60da14dc, 0xe1d1b717, 0xf4f60a3a, 0x42971b06, 0x57b0a62b, 0xba7e5893, 0xaf59e5be, 0x1938f482, 0x0c1f49af, 0x6cc55d73, 0x79e2e05e, 0xcf83f162, 0xdaa44c4f, 0x376ab2f7, 0x224d0fda, 0x942c1ee6, 0x810ba3cb, 0xfa072d45, 0xef209068, 0x59418154, 0x4c663c79, 0xa1a8c2c1, 0xb48f7fec, 0x02ee6ed0, 0x17c9d3fd, 0x7713c721, 0x62347a0c, 0xd4556b30, 0xc172d61d, 0x2cbc28a5, 0x399b9588, 0x8ffa84b4, 0x9add3999, 0x1bd69a52, 0x0ef1277f, 0xb8903643, 0xadb78b6e, 0x407975d6, 0x555ec8fb, 0xe33fd9c7, 0xf61864ea, 0x96c27036, 0x83e5cd1b, 0x3584dc27, 0x20a3610a, 0xcd6d9fb2, 0xd84a229f, 0x6e2b33a3, 0x7b0c8e8e, 0x438b0b05, 0x56acb628, 0xe0cda714, 0xf5ea1a39, 0x1824e481, 0x0d0359ac, 0xbb624890, 0xae45f5bd, 0xce9fe161, 0xdbb85c4c, 0x6dd94d70, 0x78fef05d, 0x95300ee5, 0x8017b3c8, 0x3676a2f4, 0x23511fd9, 0xa25abc12, 0xb77d013f, 0x011c1003, 0x143bad2e, 0xf9f55396, 0xecd2eebb, 0x5ab3ff87, 0x4f9442aa, 0x2f4e5676, 0x3a69eb5b, 0x8c08fa67, 0x992f474a, 0x74e1b9f2, 0x61c604df, 0xd7a715e3, 0xc280a8ce, 0xb98c2640, 0xacab9b6d, 0x1aca8a51, 0x0fed377c, 0xe223c9c4, 0xf70474e9, 0x416565d5, 0x5442d8f8, 0x3498cc24, 0x21bf7109, 0x97de6035, 0x82f9dd18, 0x6f3723a0, 0x7a109e8d, 0xcc718fb1, 0xd956329c, 0x585d9157, 0x4d7a2c7a, 0xfb1b3d46, 0xee3c806b, 0x03f27ed3, 0x16d5c3fe, 0xa0b4d2c2, 0xb5936fef, 0xd5497b33, 0xc06ec61e, 0x760fd722, 0x63286a0f, 0x8ee694b7, 0x9bc1299a, 0x2da038a6, 0x3887858b, 0x96eba6cb, 0x83cc1be6, 0x35ad0ada, 0x208ab7f7, 0xcd44494f, 0xd863f462, 0x6e02e55e, 0x7b255873, 0x1bff4caf, 0x0ed8f182, 0xb8b9e0be, 0xad9e5d93, 0x4050a32b, 0x55771e06, 0xe3160f3a, 0xf631b217, 0x773a11dc, 0x621dacf1, 0xd47cbdcd, 0xc15b00e0, 0x2c95fe58, 0x39b24375, 0x8fd35249, 0x9af4ef64, 0xfa2efbb8, 0xef094695, 0x596857a9, 0x4c4fea84, 0xa181143c, 0xb4a6a911, 0x02c7b82d, 0x17e00500, 0x6cec8b8e, 0x79cb36a3, 0xcfaa279f, 0xda8d9ab2, 0x3743640a, 0x2264d927, 0x9405c81b, 0x81227536, 0xe1f861ea, 0xf4dfdcc7, 0x42becdfb, 0x579970d6, 0xba578e6e, 0xaf703343, 0x1911227f, 0x0c369f52, 0x8d3d3c99, 0x981a81b4, 0x2e7b9088, 0x3b5c2da5, 0xd692d31d, 0xc3b56e30, 0x75d47f0c, 0x60f3c221, 0x0029d6fd, 0x150e6bd0, 0xa36f7aec, 0xb648c7c1, 0x5b863979, 0x4ea18454, 0xf8c09568, 0xede72845, 0xd560adce, 0xc04710e3, 0x762601df, 0x6301bcf2, 0x8ecf424a, 0x9be8ff67, 0x2d89ee5b, 0x38ae5376, 0x587447aa, 0x4d53fa87, 0xfb32ebbb, 0xee155696, 0x03dba82e, 0x16fc1503, 0xa09d043f, 0xb5bab912, 0x34b11ad9, 0x2196a7f4, 0x97f7b6c8, 0x82d00be5, 0x6f1ef55d, 0x7a394870, 0xcc58594c, 0xd97fe461, 0xb9a5f0bd, 0xac824d90, 0x1ae35cac, 0x0fc4e181, 0xe20a1f39, 0xf72da214, 0x414cb328, 0x546b0e05, 0x2f67808b, 0x3a403da6, 0x8c212c9a, 0x990691b7, 0x74c86f0f, 0x61efd222, 0xd78ec31e, 0xc2a97e33, 0xa2736aef, 0xb754d7c2, 0x0135c6fe, 0x14127bd3, 0xf9dc856b, 0xecfb3846, 0x5a9a297a, 0x4fbd9457, 0xceb6379c, 0xdb918ab1, 0x6df09b8d, 0x78d726a0, 0x9519d818, 0x803e6535, 0x365f7409, 0x2378c924, 0x43a2ddf8, 0x568560d5, 0xe0e471e9, 0xf5c3ccc4, 0x180d327c, 0x0d2a8f51, 0xbb4b9e6d, 0xae6c2340 +}, +{ +0x00000000, 0xaf48228c, 0x018245e4, 0xaeca6768, 0xd0611ffe, 0x7f293d72, 0xd1e35a1a, 0x7eab7896, 0x3defb0fb, 0x92a79277, 0x3c6df51f, 0x9325d793, 0xed8eaf05, 0x42c68d89, 0xec0ceae1, 0x4344c86d, 0x0ee44042, 0xa1ac62ce, 0x0f6605a6, 0xa02e272a, 0xde855fbc, 0x71cd7d30, 0xdf071a58, 0x704f38d4, 0x330bf0b9, 0x9c43d235, 0x3289b55d, 0x9dc197d1, 0xe36aef47, 0x4c22cdcb, 0xe2e8aaa3, 0x4da0882f, 0xd2499528, 0x7d01b7a4, 0xd3cbd0cc, 0x7c83f240, 0x02288ad6, 0xad60a85a, 0x03aacf32, 0xace2edbe, 0xefa625d3, 0x40ee075f, 0xee246037, 0x416c42bb, 0x3fc73a2d, 0x908f18a1, 0x3e457fc9, 0x910d5d45, 0xdcadd56a, 0x73e5f7e6, 0xdd2f908e, 0x7267b202, 0x0cccca94, 0xa384e818, 0x0d4e8f70, 0xa206adfc, 0xe1426591, 0x4e0a471d, 0xe0c02075, 0x4f8802f9, 0x31237a6f, 0x9e6b58e3, 0x30a13f8b, 0x9fe91d07, 0xf831549a, 0x57797616, 0xf9b3117e, 0x56fb33f2, 0x28504b64, 0x871869e8, 0x29d20e80, 0x869a2c0c, 0xc5dee461, 0x6a96c6ed, 0xc45ca185, 0x6b148309, 0x15bffb9f, 0xbaf7d913, 0x143dbe7b, 0xbb759cf7, 0xf6d514d8, 0x599d3654, 0xf757513c, 0x581f73b0, 0x26b40b26, 0x89fc29aa, 0x27364ec2, 0x887e6c4e, 0xcb3aa423, 0x647286af, 0xcab8e1c7, 0x65f0c34b, 0x1b5bbbdd, 0xb4139951, 0x1ad9fe39, 0xb591dcb5, 0x2a78c1b2, 0x8530e33e, 0x2bfa8456, 0x84b2a6da, 0xfa19de4c, 0x5551fcc0, 0xfb9b9ba8, 0x54d3b924, 0x17977149, 0xb8df53c5, 0x161534ad, 0xb95d1621, 0xc7f66eb7, 0x68be4c3b, 0xc6742b53, 0x693c09df, 0x249c81f0, 0x8bd4a37c, 0x251ec414, 0x8a56e698, 0xf4fd9e0e, 0x5bb5bc82, 0xf57fdbea, 0x5a37f966, 0x1973310b, 0xb63b1387, 0x18f174ef, 0xb7b95663, 0xc9122ef5, 0x665a0c79, 0xc8906b11, 0x67d8499d, 0x4e7c0b4b, 0xe13429c7, 0x4ffe4eaf, 0xe0b66c23, 0x9e1d14b5, 0x31553639, 0x9f9f5151, 0x30d773dd, 0x7393bbb0, 0xdcdb993c, 0x7211fe54, 0xdd59dcd8, 0xa3f2a44e, 0x0cba86c2, 0xa270e1aa, 0x0d38c326, 0x40984b09, 0xefd06985, 0x411a0eed, 0xee522c61, 0x90f954f7, 0x3fb1767b, 0x917b1113, 0x3e33339f, 0x7d77fbf2, 0xd23fd97e, 0x7cf5be16, 0xd3bd9c9a, 0xad16e40c, 0x025ec680, 0xac94a1e8, 0x03dc8364, 0x9c359e63, 0x337dbcef, 0x9db7db87, 0x32fff90b, 0x4c54819d, 0xe31ca311, 0x4dd6c479, 0xe29ee6f5, 0xa1da2e98, 0x0e920c14, 0xa0586b7c, 0x0f1049f0, 0x71bb3166, 0xdef313ea, 0x70397482, 0xdf71560e, 0x92d1de21, 0x3d99fcad, 0x93539bc5, 0x3c1bb949, 0x42b0c1df, 0xedf8e353, 0x4332843b, 0xec7aa6b7, 0xaf3e6eda, 0x00764c56, 0xaebc2b3e, 0x01f409b2, 0x7f5f7124, 0xd01753a8, 0x7edd34c0, 0xd195164c, 0xb64d5fd1, 0x19057d5d, 0xb7cf1a35, 0x188738b9, 0x662c402f, 0xc96462a3, 0x67ae05cb, 0xc8e62747, 0x8ba2ef2a, 0x24eacda6, 0x8a20aace, 0x25688842, 0x5bc3f0d4, 0xf48bd258, 0x5a41b530, 0xf50997bc, 0xb8a91f93, 0x17e13d1f, 0xb92b5a77, 0x166378fb, 0x68c8006d, 0xc78022e1, 0x694a4589, 0xc6026705, 0x8546af68, 0x2a0e8de4, 0x84c4ea8c, 0x2b8cc800, 0x5527b096, 0xfa6f921a, 0x54a5f572, 0xfbedd7fe, 0x6404caf9, 0xcb4ce875, 0x65868f1d, 0xcacead91, 0xb465d507, 0x1b2df78b, 0xb5e790e3, 0x1aafb26f, 0x59eb7a02, 0xf6a3588e, 0x58693fe6, 0xf7211d6a, 0x898a65fc, 0x26c24770, 0x88082018, 0x27400294, 0x6ae08abb, 0xc5a8a837, 0x6b62cf5f, 0xc42aedd3, 0xba819545, 0x15c9b7c9, 0xbb03d0a1, 0x144bf22d, 0x570f3a40, 0xf84718cc, 0x568d7fa4, 0xf9c55d28, 0x876e25be, 0x28260732, 0x86ec605a, 0x29a442d6 +}, +{ +0x00000000, 0x7a9d1fb7, 0x2119cebc, 0x5b84d10b, 0xbbbcae20, 0xc121b197, 0x9aa5609c, 0xe0387f2b, 0x58044615, 0x229959a2, 0x791d88a9, 0x0380971e, 0xe3b8e835, 0x9925f782, 0xc2a12689, 0xb83c393e, 0x21c57326, 0x5b586c91, 0x00dcbd9a, 0x7a41a22d, 0x9a79dd06, 0xe0e4c2b1, 0xbb6013ba, 0xc1fd0c0d, 0x79c13533, 0x035c2a84, 0x58d8fb8f, 0x2245e438, 0xc27d9b13, 0xb8e084a4, 0xe36455af, 0x99f94a18, 0x556177c1, 0x2ffc6876, 0x7478b97d, 0x0ee5a6ca, 0xeeddd9e1, 0x9440c656, 0xcfc4175d, 0xb55908ea, 0x0d6531d4, 0x77f82e63, 0x2c7cff68, 0x56e1e0df, 0xb6d99ff4, 0xcc448043, 0x97c05148, 0xed5d4eff, 0x74a404e7, 0x0e391b50, 0x55bdca5b, 0x2f20d5ec, 0xcf18aac7, 0xb585b570, 0xee01647b, 0x949c7bcc, 0x2ca042f2, 0x563d5d45, 0x0db98c4e, 0x772493f9, 0x971cecd2, 0xed81f365, 0xb605226e, 0xcc983dd9, 0xb1ece78f, 0xcb71f838, 0x90f52933, 0xea683684, 0x0a5049af, 0x70cd5618, 0x2b498713, 0x51d498a4, 0xe9e8a19a, 0x9375be2d, 0xc8f16f26, 0xb26c7091, 0x52540fba, 0x28c9100d, 0x734dc106, 0x09d0deb1, 0x902994a9, 0xeab48b1e, 0xb1305a15, 0xcbad45a2, 0x2b953a89, 0x5108253e, 0x0a8cf435, 0x7011eb82, 0xc82dd2bc, 0xb2b0cd0b, 0xe9341c00, 0x93a903b7, 0x73917c9c, 0x090c632b, 0x5288b220, 0x2815ad97, 0xe48d904e, 0x9e108ff9, 0xc5945ef2, 0xbf094145, 0x5f313e6e, 0x25ac21d9, 0x7e28f0d2, 0x04b5ef65, 0xbc89d65b, 0xc614c9ec, 0x9d9018e7, 0xe70d0750, 0x0735787b, 0x7da867cc, 0x262cb6c7, 0x5cb1a970, 0xc548e368, 0xbfd5fcdf, 0xe4512dd4, 0x9ecc3263, 0x7ef44d48, 0x046952ff, 0x5fed83f4, 0x25709c43, 0x9d4ca57d, 0xe7d1baca, 0xbc556bc1, 0xc6c87476, 0x26f00b5d, 0x5c6d14ea, 0x07e9c5e1, 0x7d74da56, 0x3b9a3474, 0x41072bc3, 0x1a83fac8, 0x601ee57f, 0x80269a54, 0xfabb85e3, 0xa13f54e8, 0xdba24b5f, 0x639e7261, 0x19036dd6, 0x4287bcdd, 0x381aa36a, 0xd822dc41, 0xa2bfc3f6, 0xf93b12fd, 0x83a60d4a, 0x1a5f4752, 0x60c258e5, 0x3b4689ee, 0x41db9659, 0xa1e3e972, 0xdb7ef6c5, 0x80fa27ce, 0xfa673879, 0x425b0147, 0x38c61ef0, 0x6342cffb, 0x19dfd04c, 0xf9e7af67, 0x837ab0d0, 0xd8fe61db, 0xa2637e6c, 0x6efb43b5, 0x14665c02, 0x4fe28d09, 0x357f92be, 0xd547ed95, 0xafdaf222, 0xf45e2329, 0x8ec33c9e, 0x36ff05a0, 0x4c621a17, 0x17e6cb1c, 0x6d7bd4ab, 0x8d43ab80, 0xf7deb437, 0xac5a653c, 0xd6c77a8b, 0x4f3e3093, 0x35a32f24, 0x6e27fe2f, 0x14bae198, 0xf4829eb3, 0x8e1f8104, 0xd59b500f, 0xaf064fb8, 0x173a7686, 0x6da76931, 0x3623b83a, 0x4cbea78d, 0xac86d8a6, 0xd61bc711, 0x8d9f161a, 0xf70209ad, 0x8a76d3fb, 0xf0ebcc4c, 0xab6f1d47, 0xd1f202f0, 0x31ca7ddb, 0x4b57626c, 0x10d3b367, 0x6a4eacd0, 0xd27295ee, 0xa8ef8a59, 0xf36b5b52, 0x89f644e5, 0x69ce3bce, 0x13532479, 0x48d7f572, 0x324aeac5, 0xabb3a0dd, 0xd12ebf6a, 0x8aaa6e61, 0xf03771d6, 0x100f0efd, 0x6a92114a, 0x3116c041, 0x4b8bdff6, 0xf3b7e6c8, 0x892af97f, 0xd2ae2874, 0xa83337c3, 0x480b48e8, 0x3296575f, 0x69128654, 0x138f99e3, 0xdf17a43a, 0xa58abb8d, 0xfe0e6a86, 0x84937531, 0x64ab0a1a, 0x1e3615ad, 0x45b2c4a6, 0x3f2fdb11, 0x8713e22f, 0xfd8efd98, 0xa60a2c93, 0xdc973324, 0x3caf4c0f, 0x463253b8, 0x1db682b3, 0x672b9d04, 0xfed2d71c, 0x844fc8ab, 0xdfcb19a0, 0xa5560617, 0x456e793c, 0x3ff3668b, 0x6477b780, 0x1eeaa837, 0xa6d69109, 0xdc4b8ebe, 0x87cf5fb5, 0xfd524002, 0x1d6a3f29, 0x67f7209e, 0x3c73f195, 0x46eeee22 +} +}, +{ +{ +0x00000000, 0x559ca332, 0x0d8c5f80, 0x5810fcb2, 0x868524b5, 0xd3198787, 0x8b097b35, 0xde95d807, 0x4f752b95, 0x1ae988a7, 0x42f97415, 0x1765d727, 0xc9f00f20, 0x9c6cac12, 0xc47c50a0, 0x91e0f392, 0xbb45fade, 0xeed959ec, 0xb6c9a55e, 0xe355066c, 0x3dc0de6b, 0x685c7d59, 0x304c81eb, 0x65d022d9, 0xf430d14b, 0xa1ac7279, 0xf9bc8ecb, 0xac202df9, 0x72b5f5fe, 0x272956cc, 0x7f39aa7e, 0x2aa5094c, 0xaa5b8b0e, 0xffc7283c, 0xa7d7d48e, 0xf24b77bc, 0x2cdeafbb, 0x79420c89, 0x2152f03b, 0x74ce5309, 0xe52ea09b, 0xb0b203a9, 0xe8a2ff1b, 0xbd3e5c29, 0x63ab842e, 0x3637271c, 0x6e27dbae, 0x3bbb789c, 0x111e71d0, 0x4482d2e2, 0x1c922e50, 0x490e8d62, 0x979b5565, 0xc207f657, 0x9a170ae5, 0xcf8ba9d7, 0x5e6b5a45, 0x0bf7f977, 0x53e705c5, 0x067ba6f7, 0xd8ee7ef0, 0x8d72ddc2, 0xd5622170, 0x80fe8242, 0xf3b29fec, 0xa62e3cde, 0xfe3ec06c, 0xaba2635e, 0x7537bb59, 0x20ab186b, 0x78bbe4d9, 0x2d2747eb, 0xbcc7b479, 0xe95b174b, 0xb14bebf9, 0xe4d748cb, 0x3a4290cc, 0x6fde33fe, 0x37cecf4c, 0x62526c7e, 0x48f76532, 0x1d6bc600, 0x457b3ab2, 0x10e79980, 0xce724187, 0x9beee2b5, 0xc3fe1e07, 0x9662bd35, 0x07824ea7, 0x521eed95, 0x0a0e1127, 0x5f92b215, 0x81076a12, 0xd49bc920, 0x8c8b3592, 0xd91796a0, 0x59e914e2, 0x0c75b7d0, 0x54654b62, 0x01f9e850, 0xdf6c3057, 0x8af09365, 0xd2e06fd7, 0x877ccce5, 0x169c3f77, 0x43009c45, 0x1b1060f7, 0x4e8cc3c5, 0x90191bc2, 0xc585b8f0, 0x9d954442, 0xc809e770, 0xe2acee3c, 0xb7304d0e, 0xef20b1bc, 0xbabc128e, 0x6429ca89, 0x31b569bb, 0x69a59509, 0x3c39363b, 0xadd9c5a9, 0xf845669b, 0xa0559a29, 0xf5c9391b, 0x2b5ce11c, 0x7ec0422e, 0x26d0be9c, 0x734c1dae, 0x8fea116c, 0xda76b25e, 0x82664eec, 0xd7faedde, 0x096f35d9, 0x5cf396eb, 0x04e36a59, 0x517fc96b, 0xc09f3af9, 0x950399cb, 0xcd136579, 0x988fc64b, 0x461a1e4c, 0x1386bd7e, 0x4b9641cc, 0x1e0ae2fe, 0x34afebb2, 0x61334880, 0x3923b432, 0x6cbf1700, 0xb22acf07, 0xe7b66c35, 0xbfa69087, 0xea3a33b5, 0x7bdac027, 0x2e466315, 0x76569fa7, 0x23ca3c95, 0xfd5fe492, 0xa8c347a0, 0xf0d3bb12, 0xa54f1820, 0x25b19a62, 0x702d3950, 0x283dc5e2, 0x7da166d0, 0xa334bed7, 0xf6a81de5, 0xaeb8e157, 0xfb244265, 0x6ac4b1f7, 0x3f5812c5, 0x6748ee77, 0x32d44d45, 0xec419542, 0xb9dd3670, 0xe1cdcac2, 0xb45169f0, 0x9ef460bc, 0xcb68c38e, 0x93783f3c, 0xc6e49c0e, 0x18714409, 0x4dede73b, 0x15fd1b89, 0x4061b8bb, 0xd1814b29, 0x841de81b, 0xdc0d14a9, 0x8991b79b, 0x57046f9c, 0x0298ccae, 0x5a88301c, 0x0f14932e, 0x7c588e80, 0x29c42db2, 0x71d4d100, 0x24487232, 0xfaddaa35, 0xaf410907, 0xf751f5b5, 0xa2cd5687, 0x332da515, 0x66b10627, 0x3ea1fa95, 0x6b3d59a7, 0xb5a881a0, 0xe0342292, 0xb824de20, 0xedb87d12, 0xc71d745e, 0x9281d76c, 0xca912bde, 0x9f0d88ec, 0x419850eb, 0x1404f3d9, 0x4c140f6b, 0x1988ac59, 0x88685fcb, 0xddf4fcf9, 0x85e4004b, 0xd078a379, 0x0eed7b7e, 0x5b71d84c, 0x036124fe, 0x56fd87cc, 0xd603058e, 0x839fa6bc, 0xdb8f5a0e, 0x8e13f93c, 0x5086213b, 0x051a8209, 0x5d0a7ebb, 0x0896dd89, 0x99762e1b, 0xccea8d29, 0x94fa719b, 0xc166d2a9, 0x1ff30aae, 0x4a6fa99c, 0x127f552e, 0x47e3f61c, 0x6d46ff50, 0x38da5c62, 0x60caa0d0, 0x355603e2, 0xebc3dbe5, 0xbe5f78d7, 0xe64f8465, 0xb3d32757, 0x2233d4c5, 0x77af77f7, 0x2fbf8b45, 0x7a232877, 0xa4b6f070, 0xf12a5342, 0xa93aaff0, 0xfca60cc2 +}, +{ +0x00000000, 0xbd3ca6fd, 0x26489324, 0x9b7435d9, 0x69c43b26, 0xd4f89ddb, 0x4f8ca802, 0xf2b00eff, 0x4ae989bc, 0xf7d52f41, 0x6ca11a98, 0xd19dbc65, 0x232db29a, 0x9e111467, 0x056521be, 0xb8598743, 0x11f0a3f7, 0xaccc050a, 0x37b830d3, 0x8a84962e, 0x783498d1, 0xc5083e2c, 0x5e7c0bf5, 0xe340ad08, 0x5b192a4b, 0xe6258cb6, 0x7d51b96f, 0xc06d1f92, 0x32dd116d, 0x8fe1b790, 0x14958249, 0xa9a924b4, 0x25850d09, 0x98b9abf4, 0x03cd9e2d, 0xbef138d0, 0x4c41362f, 0xf17d90d2, 0x6a09a50b, 0xd73503f6, 0x6f6c84b5, 0xd2502248, 0x49241791, 0xf418b16c, 0x06a8bf93, 0xbb94196e, 0x20e02cb7, 0x9ddc8a4a, 0x3475aefe, 0x89490803, 0x123d3dda, 0xaf019b27, 0x5db195d8, 0xe08d3325, 0x7bf906fc, 0xc6c5a001, 0x7e9c2742, 0xc3a081bf, 0x58d4b466, 0xe5e8129b, 0x17581c64, 0xaa64ba99, 0x31108f40, 0x8c2c29bd, 0xd4393d29, 0x69059bd4, 0xf271ae0d, 0x4f4d08f0, 0xbdfd060f, 0x00c1a0f2, 0x9bb5952b, 0x268933d6, 0x9ed0b495, 0x23ec1268, 0xb89827b1, 0x05a4814c, 0xf7148fb3, 0x4a28294e, 0xd15c1c97, 0x6c60ba6a, 0xc5c99ede, 0x78f53823, 0xe3810dfa, 0x5ebdab07, 0xac0da5f8, 0x11310305, 0x8a4536dc, 0x37799021, 0x8f201762, 0x321cb19f, 0xa9688446, 0x145422bb, 0xe6e42c44, 0x5bd88ab9, 0xc0acbf60, 0x7d90199d, 0xf1bc3020, 0x4c8096dd, 0xd7f4a304, 0x6ac805f9, 0x98780b06, 0x2544adfb, 0xbe309822, 0x030c3edf, 0xbb55b99c, 0x06691f61, 0x9d1d2ab8, 0x20218c45, 0xd29182ba, 0x6fad2447, 0xf4d9119e, 0x49e5b763, 0xe04c93d7, 0x5d70352a, 0xc60400f3, 0x7b38a60e, 0x8988a8f1, 0x34b40e0c, 0xafc03bd5, 0x12fc9d28, 0xaaa51a6b, 0x1799bc96, 0x8ced894f, 0x31d12fb2, 0xc361214d, 0x7e5d87b0, 0xe529b269, 0x58151494, 0xfb5d1971, 0x4661bf8c, 0xdd158a55, 0x60292ca8, 0x92992257, 0x2fa584aa, 0xb4d1b173, 0x09ed178e, 0xb1b490cd, 0x0c883630, 0x97fc03e9, 0x2ac0a514, 0xd870abeb, 0x654c0d16, 0xfe3838cf, 0x43049e32, 0xeaadba86, 0x57911c7b, 0xcce529a2, 0x71d98f5f, 0x836981a0, 0x3e55275d, 0xa5211284, 0x181db479, 0xa044333a, 0x1d7895c7, 0x860ca01e, 0x3b3006e3, 0xc980081c, 0x74bcaee1, 0xefc89b38, 0x52f43dc5, 0xded81478, 0x63e4b285, 0xf890875c, 0x45ac21a1, 0xb71c2f5e, 0x0a2089a3, 0x9154bc7a, 0x2c681a87, 0x94319dc4, 0x290d3b39, 0xb2790ee0, 0x0f45a81d, 0xfdf5a6e2, 0x40c9001f, 0xdbbd35c6, 0x6681933b, 0xcf28b78f, 0x72141172, 0xe96024ab, 0x545c8256, 0xa6ec8ca9, 0x1bd02a54, 0x80a41f8d, 0x3d98b970, 0x85c13e33, 0x38fd98ce, 0xa389ad17, 0x1eb50bea, 0xec050515, 0x5139a3e8, 0xca4d9631, 0x777130cc, 0x2f642458, 0x925882a5, 0x092cb77c, 0xb4101181, 0x46a01f7e, 0xfb9cb983, 0x60e88c5a, 0xddd42aa7, 0x658dade4, 0xd8b10b19, 0x43c53ec0, 0xfef9983d, 0x0c4996c2, 0xb175303f, 0x2a0105e6, 0x973da31b, 0x3e9487af, 0x83a82152, 0x18dc148b, 0xa5e0b276, 0x5750bc89, 0xea6c1a74, 0x71182fad, 0xcc248950, 0x747d0e13, 0xc941a8ee, 0x52359d37, 0xef093bca, 0x1db93535, 0xa08593c8, 0x3bf1a611, 0x86cd00ec, 0x0ae12951, 0xb7dd8fac, 0x2ca9ba75, 0x91951c88, 0x63251277, 0xde19b48a, 0x456d8153, 0xf85127ae, 0x4008a0ed, 0xfd340610, 0x664033c9, 0xdb7c9534, 0x29cc9bcb, 0x94f03d36, 0x0f8408ef, 0xb2b8ae12, 0x1b118aa6, 0xa62d2c5b, 0x3d591982, 0x8065bf7f, 0x72d5b180, 0xcfe9177d, 0x549d22a4, 0xe9a18459, 0x51f8031a, 0xecc4a5e7, 0x77b0903e, 0xca8c36c3, 0x383c383c, 0x85009ec1, 0x1e74ab18, 0xa3480de5 +}, +{ +0x00000000, 0x0cf4e9cc, 0x156f116c, 0x199bf8a0, 0xfa7b3780, 0xf68fde4c, 0xef1426ec, 0xe3e0cf20, 0x9e0e158c, 0x92fafc40, 0x8b6104e0, 0x8795ed2c, 0x6475220c, 0x6881cbc0, 0x711a3360, 0x7deedaac, 0x2aa1346d, 0x2655dda1, 0x3fce2501, 0x333acccd, 0xd0da03ed, 0xdc2eea21, 0xc5b51281, 0xc941fb4d, 0xb4af21e1, 0xb85bc82d, 0xa1c0308d, 0xad34d941, 0x4ed41661, 0x4220ffad, 0x5bbb070d, 0x574feec1, 0x7c3bc611, 0x70cf2fdd, 0x6954d77d, 0x65a03eb1, 0x8640f191, 0x8ab4185d, 0x932fe0fd, 0x9fdb0931, 0xe235d39d, 0xeec13a51, 0xf75ac2f1, 0xfbae2b3d, 0x184ee41d, 0x14ba0dd1, 0x0d21f571, 0x01d51cbd, 0x569af27c, 0x5a6e1bb0, 0x43f5e310, 0x4f010adc, 0xace1c5fc, 0xa0152c30, 0xb98ed490, 0xb57a3d5c, 0xc894e7f0, 0xc4600e3c, 0xddfbf69c, 0xd10f1f50, 0x32efd070, 0x3e1b39bc, 0x2780c11c, 0x2b7428d0, 0x795155e7, 0x75a5bc2b, 0x6c3e448b, 0x60caad47, 0x832a6267, 0x8fde8bab, 0x9645730b, 0x9ab19ac7, 0xe75f406b, 0xebaba9a7, 0xf2305107, 0xfec4b8cb, 0x1d2477eb, 0x11d09e27, 0x084b6687, 0x04bf8f4b, 0x53f0618a, 0x5f048846, 0x469f70e6, 0x4a6b992a, 0xa98b560a, 0xa57fbfc6, 0xbce44766, 0xb010aeaa, 0xcdfe7406, 0xc10a9dca, 0xd891656a, 0xd4658ca6, 0x37854386, 0x3b71aa4a, 0x22ea52ea, 0x2e1ebb26, 0x056a93f6, 0x099e7a3a, 0x1005829a, 0x1cf16b56, 0xff11a476, 0xf3e54dba, 0xea7eb51a, 0xe68a5cd6, 0x9b64867a, 0x97906fb6, 0x8e0b9716, 0x82ff7eda, 0x611fb1fa, 0x6deb5836, 0x7470a096, 0x7884495a, 0x2fcba79b, 0x233f4e57, 0x3aa4b6f7, 0x36505f3b, 0xd5b0901b, 0xd94479d7, 0xc0df8177, 0xcc2b68bb, 0xb1c5b217, 0xbd315bdb, 0xa4aaa37b, 0xa85e4ab7, 0x4bbe8597, 0x474a6c5b, 0x5ed194fb, 0x52257d37, 0xeae6a8e1, 0xe612412d, 0xff89b98d, 0xf37d5041, 0x109d9f61, 0x1c6976ad, 0x05f28e0d, 0x090667c1, 0x74e8bd6d, 0x781c54a1, 0x6187ac01, 0x6d7345cd, 0x8e938aed, 0x82676321, 0x9bfc9b81, 0x9708724d, 0xc0479c8c, 0xccb37540, 0xd5288de0, 0xd9dc642c, 0x3a3cab0c, 0x36c842c0, 0x2f53ba60, 0x23a753ac, 0x5e498900, 0x52bd60cc, 0x4b26986c, 0x47d271a0, 0xa432be80, 0xa8c6574c, 0xb15dafec, 0xbda94620, 0x96dd6ef0, 0x9a29873c, 0x83b27f9c, 0x8f469650, 0x6ca65970, 0x6052b0bc, 0x79c9481c, 0x753da1d0, 0x08d37b7c, 0x042792b0, 0x1dbc6a10, 0x114883dc, 0xf2a84cfc, 0xfe5ca530, 0xe7c75d90, 0xeb33b45c, 0xbc7c5a9d, 0xb088b351, 0xa9134bf1, 0xa5e7a23d, 0x46076d1d, 0x4af384d1, 0x53687c71, 0x5f9c95bd, 0x22724f11, 0x2e86a6dd, 0x371d5e7d, 0x3be9b7b1, 0xd8097891, 0xd4fd915d, 0xcd6669fd, 0xc1928031, 0x93b7fd06, 0x9f4314ca, 0x86d8ec6a, 0x8a2c05a6, 0x69ccca86, 0x6538234a, 0x7ca3dbea, 0x70573226, 0x0db9e88a, 0x014d0146, 0x18d6f9e6, 0x1422102a, 0xf7c2df0a, 0xfb3636c6, 0xe2adce66, 0xee5927aa, 0xb916c96b, 0xb5e220a7, 0xac79d807, 0xa08d31cb, 0x436dfeeb, 0x4f991727, 0x5602ef87, 0x5af6064b, 0x2718dce7, 0x2bec352b, 0x3277cd8b, 0x3e832447, 0xdd63eb67, 0xd19702ab, 0xc80cfa0b, 0xc4f813c7, 0xef8c3b17, 0xe378d2db, 0xfae32a7b, 0xf617c3b7, 0x15f70c97, 0x1903e55b, 0x00981dfb, 0x0c6cf437, 0x71822e9b, 0x7d76c757, 0x64ed3ff7, 0x6819d63b, 0x8bf9191b, 0x870df0d7, 0x9e960877, 0x9262e1bb, 0xc52d0f7a, 0xc9d9e6b6, 0xd0421e16, 0xdcb6f7da, 0x3f5638fa, 0x33a2d136, 0x2a392996, 0x26cdc05a, 0x5b231af6, 0x57d7f33a, 0x4e4c0b9a, 0x42b8e256, 0xa1582d76, 0xadacc4ba, 0xb4373c1a, 0xb8c3d5d6 +}, +{ +0x00000000, 0xa8820f95, 0x2aaf13a9, 0x822d1c3c, 0x4d2038fd, 0xe5a23768, 0x678f2b54, 0xcf0d24c1, 0xcda842d3, 0x652a4d46, 0xe707517a, 0x4f855eef, 0x80887a2e, 0x280a75bb, 0xaa276987, 0x02a56612, 0xdd9d689d, 0x751f6708, 0xf7327b34, 0x5fb074a1, 0x90bd5060, 0x383f5ff5, 0xba1243c9, 0x12904c5c, 0x10352a4e, 0xb8b725db, 0x3a9a39e7, 0x92183672, 0x5d1512b3, 0xf5971d26, 0x77ba011a, 0xdf380e8f, 0xadd07013, 0x05527f86, 0x877f63ba, 0x2ffd6c2f, 0xe0f048ee, 0x4872477b, 0xca5f5b47, 0x62dd54d2, 0x607832c0, 0xc8fa3d55, 0x4ad72169, 0xe2552efc, 0x2d580a3d, 0x85da05a8, 0x07f71994, 0xaf751601, 0x704d188e, 0xd8cf171b, 0x5ae20b27, 0xf26004b2, 0x3d6d2073, 0x95ef2fe6, 0x17c233da, 0xbf403c4f, 0xbde55a5d, 0x156755c8, 0x974a49f4, 0x3fc84661, 0xf0c562a0, 0x58476d35, 0xda6a7109, 0x72e87e9c, 0xe9fa963c, 0x417899a9, 0xc3558595, 0x6bd78a00, 0xa4daaec1, 0x0c58a154, 0x8e75bd68, 0x26f7b2fd, 0x2452d4ef, 0x8cd0db7a, 0x0efdc746, 0xa67fc8d3, 0x6972ec12, 0xc1f0e387, 0x43ddffbb, 0xeb5ff02e, 0x3467fea1, 0x9ce5f134, 0x1ec8ed08, 0xb64ae29d, 0x7947c65c, 0xd1c5c9c9, 0x53e8d5f5, 0xfb6ada60, 0xf9cfbc72, 0x514db3e7, 0xd360afdb, 0x7be2a04e, 0xb4ef848f, 0x1c6d8b1a, 0x9e409726, 0x36c298b3, 0x442ae62f, 0xeca8e9ba, 0x6e85f586, 0xc607fa13, 0x090aded2, 0xa188d147, 0x23a5cd7b, 0x8b27c2ee, 0x8982a4fc, 0x2100ab69, 0xa32db755, 0x0bafb8c0, 0xc4a29c01, 0x6c209394, 0xee0d8fa8, 0x468f803d, 0x99b78eb2, 0x31358127, 0xb3189d1b, 0x1b9a928e, 0xd497b64f, 0x7c15b9da, 0xfe38a5e6, 0x56baaa73, 0x541fcc61, 0xfc9dc3f4, 0x7eb0dfc8, 0xd632d05d, 0x193ff49c, 0xb1bdfb09, 0x3390e735, 0x9b12e8a0, 0xd3513ca1, 0x7bd33334, 0xf9fe2f08, 0x517c209d, 0x9e71045c, 0x36f30bc9, 0xb4de17f5, 0x1c5c1860, 0x1ef97e72, 0xb67b71e7, 0x34566ddb, 0x9cd4624e, 0x53d9468f, 0xfb5b491a, 0x79765526, 0xd1f45ab3, 0x0ecc543c, 0xa64e5ba9, 0x24634795, 0x8ce14800, 0x43ec6cc1, 0xeb6e6354, 0x69437f68, 0xc1c170fd, 0xc36416ef, 0x6be6197a, 0xe9cb0546, 0x41490ad3, 0x8e442e12, 0x26c62187, 0xa4eb3dbb, 0x0c69322e, 0x7e814cb2, 0xd6034327, 0x542e5f1b, 0xfcac508e, 0x33a1744f, 0x9b237bda, 0x190e67e6, 0xb18c6873, 0xb3290e61, 0x1bab01f4, 0x99861dc8, 0x3104125d, 0xfe09369c, 0x568b3909, 0xd4a62535, 0x7c242aa0, 0xa31c242f, 0x0b9e2bba, 0x89b33786, 0x21313813, 0xee3c1cd2, 0x46be1347, 0xc4930f7b, 0x6c1100ee, 0x6eb466fc, 0xc6366969, 0x441b7555, 0xec997ac0, 0x23945e01, 0x8b165194, 0x093b4da8, 0xa1b9423d, 0x3aabaa9d, 0x9229a508, 0x1004b934, 0xb886b6a1, 0x778b9260, 0xdf099df5, 0x5d2481c9, 0xf5a68e5c, 0xf703e84e, 0x5f81e7db, 0xddacfbe7, 0x752ef472, 0xba23d0b3, 0x12a1df26, 0x908cc31a, 0x380ecc8f, 0xe736c200, 0x4fb4cd95, 0xcd99d1a9, 0x651bde3c, 0xaa16fafd, 0x0294f568, 0x80b9e954, 0x283be6c1, 0x2a9e80d3, 0x821c8f46, 0x0031937a, 0xa8b39cef, 0x67beb82e, 0xcf3cb7bb, 0x4d11ab87, 0xe593a412, 0x977bda8e, 0x3ff9d51b, 0xbdd4c927, 0x1556c6b2, 0xda5be273, 0x72d9ede6, 0xf0f4f1da, 0x5876fe4f, 0x5ad3985d, 0xf25197c8, 0x707c8bf4, 0xd8fe8461, 0x17f3a0a0, 0xbf71af35, 0x3d5cb309, 0x95debc9c, 0x4ae6b213, 0xe264bd86, 0x6049a1ba, 0xc8cbae2f, 0x07c68aee, 0xaf44857b, 0x2d699947, 0x85eb96d2, 0x874ef0c0, 0x2fccff55, 0xade1e369, 0x0563ecfc, 0xca6ec83d, 0x62ecc7a8, 0xe0c1db94, 0x4843d401 +}, +{ +0x00000000, 0x806fe68a, 0x708adfd3, 0xf0e53959, 0xb77bdb92, 0x37143d18, 0xc7f10441, 0x479ee2cb, 0xf2973da9, 0x72f8db23, 0x821de27a, 0x027204f0, 0x45ece63b, 0xc58300b1, 0x356639e8, 0xb509df62, 0x305e6389, 0xb0318503, 0x40d4bc5a, 0xc0bb5ad0, 0x8725b81b, 0x074a5e91, 0xf7af67c8, 0x77c08142, 0xc2c95e20, 0x42a6b8aa, 0xb24381f3, 0x322c6779, 0x75b285b2, 0xf5dd6338, 0x05385a61, 0x8557bceb, 0xc2a20659, 0x42cde0d3, 0xb228d98a, 0x32473f00, 0x75d9ddcb, 0xf5b63b41, 0x05530218, 0x853ce492, 0x30353bf0, 0xb05add7a, 0x40bfe423, 0xc0d002a9, 0x874ee062, 0x072106e8, 0xf7c43fb1, 0x77abd93b, 0xf2fc65d0, 0x7293835a, 0x8276ba03, 0x02195c89, 0x4587be42, 0xc5e858c8, 0x350d6191, 0xb562871b, 0x006b5879, 0x8004bef3, 0x70e187aa, 0xf08e6120, 0xb71083eb, 0x377f6561, 0xc79a5c38, 0x47f5bab2, 0xf4b67792, 0x74d99118, 0x843ca841, 0x04534ecb, 0x43cdac00, 0xc3a24a8a, 0x334773d3, 0xb3289559, 0x06214a3b, 0x864eacb1, 0x76ab95e8, 0xf6c47362, 0xb15a91a9, 0x31357723, 0xc1d04e7a, 0x41bfa8f0, 0xc4e8141b, 0x4487f291, 0xb462cbc8, 0x340d2d42, 0x7393cf89, 0xf3fc2903, 0x0319105a, 0x8376f6d0, 0x367f29b2, 0xb610cf38, 0x46f5f661, 0xc69a10eb, 0x8104f220, 0x016b14aa, 0xf18e2df3, 0x71e1cb79, 0x361471cb, 0xb67b9741, 0x469eae18, 0xc6f14892, 0x816faa59, 0x01004cd3, 0xf1e5758a, 0x718a9300, 0xc4834c62, 0x44ecaae8, 0xb40993b1, 0x3466753b, 0x73f897f0, 0xf397717a, 0x03724823, 0x831daea9, 0x064a1242, 0x8625f4c8, 0x76c0cd91, 0xf6af2b1b, 0xb131c9d0, 0x315e2f5a, 0xc1bb1603, 0x41d4f089, 0xf4dd2feb, 0x74b2c961, 0x8457f038, 0x043816b2, 0x43a6f479, 0xc3c912f3, 0x332c2baa, 0xb343cd20, 0x074f7a10, 0x87209c9a, 0x77c5a5c3, 0xf7aa4349, 0xb034a182, 0x305b4708, 0xc0be7e51, 0x40d198db, 0xf5d847b9, 0x75b7a133, 0x8552986a, 0x053d7ee0, 0x42a39c2b, 0xc2cc7aa1, 0x322943f8, 0xb246a572, 0x37111999, 0xb77eff13, 0x479bc64a, 0xc7f420c0, 0x806ac20b, 0x00052481, 0xf0e01dd8, 0x708ffb52, 0xc5862430, 0x45e9c2ba, 0xb50cfbe3, 0x35631d69, 0x72fdffa2, 0xf2921928, 0x02772071, 0x8218c6fb, 0xc5ed7c49, 0x45829ac3, 0xb567a39a, 0x35084510, 0x7296a7db, 0xf2f94151, 0x021c7808, 0x82739e82, 0x377a41e0, 0xb715a76a, 0x47f09e33, 0xc79f78b9, 0x80019a72, 0x006e7cf8, 0xf08b45a1, 0x70e4a32b, 0xf5b31fc0, 0x75dcf94a, 0x8539c013, 0x05562699, 0x42c8c452, 0xc2a722d8, 0x32421b81, 0xb22dfd0b, 0x07242269, 0x874bc4e3, 0x77aefdba, 0xf7c11b30, 0xb05ff9fb, 0x30301f71, 0xc0d52628, 0x40bac0a2, 0xf3f90d82, 0x7396eb08, 0x8373d251, 0x031c34db, 0x4482d610, 0xc4ed309a, 0x340809c3, 0xb467ef49, 0x016e302b, 0x8101d6a1, 0x71e4eff8, 0xf18b0972, 0xb615ebb9, 0x367a0d33, 0xc69f346a, 0x46f0d2e0, 0xc3a76e0b, 0x43c88881, 0xb32db1d8, 0x33425752, 0x74dcb599, 0xf4b35313, 0x04566a4a, 0x84398cc0, 0x313053a2, 0xb15fb528, 0x41ba8c71, 0xc1d56afb, 0x864b8830, 0x06246eba, 0xf6c157e3, 0x76aeb169, 0x315b0bdb, 0xb134ed51, 0x41d1d408, 0xc1be3282, 0x8620d049, 0x064f36c3, 0xf6aa0f9a, 0x76c5e910, 0xc3cc3672, 0x43a3d0f8, 0xb346e9a1, 0x33290f2b, 0x74b7ede0, 0xf4d80b6a, 0x043d3233, 0x8452d4b9, 0x01056852, 0x816a8ed8, 0x718fb781, 0xf1e0510b, 0xb67eb3c0, 0x3611554a, 0xc6f46c13, 0x469b8a99, 0xf39255fb, 0x73fdb371, 0x83188a28, 0x03776ca2, 0x44e98e69, 0xc48668e3, 0x346351ba, 0xb40cb730 +}, +{ +0x00000000, 0xf3694224, 0x3ba6fcd1, 0xc8cfbef5, 0xf2ae817c, 0x01c7c358, 0xc9087dad, 0x3a613f89, 0x7d1f3c73, 0x8e767e57, 0x46b9c0a2, 0xb5d08286, 0x8fb1bd0f, 0x7cd8ff2b, 0xb41741de, 0x477e03fa, 0xa43d5781, 0x575415a5, 0x9f9bab50, 0x6cf2e974, 0x5693d6fd, 0xa5fa94d9, 0x6d352a2c, 0x9e5c6808, 0xd9226bf2, 0x2a4b29d6, 0xe2849723, 0x11edd507, 0x2b8cea8e, 0xd8e5a8aa, 0x102a165f, 0xe343547b, 0xe32cbb7d, 0x1045f959, 0xd88a47ac, 0x2be30588, 0x11823a01, 0xe2eb7825, 0x2a24c6d0, 0xd94d84f4, 0x9e33870e, 0x6d5ac52a, 0xa5957bdf, 0x56fc39fb, 0x6c9d0672, 0x9ff44456, 0x573bfaa3, 0xa452b887, 0x4711ecfc, 0xb478aed8, 0x7cb7102d, 0x8fde5209, 0xb5bf6d80, 0x46d62fa4, 0x8e199151, 0x7d70d375, 0x3a0ed08f, 0xc96792ab, 0x01a82c5e, 0xf2c16e7a, 0xc8a051f3, 0x3bc913d7, 0xf306ad22, 0x006fef06, 0xa2d960ca, 0x51b022ee, 0x997f9c1b, 0x6a16de3f, 0x5077e1b6, 0xa31ea392, 0x6bd11d67, 0x98b85f43, 0xdfc65cb9, 0x2caf1e9d, 0xe460a068, 0x1709e24c, 0x2d68ddc5, 0xde019fe1, 0x16ce2114, 0xe5a76330, 0x06e4374b, 0xf58d756f, 0x3d42cb9a, 0xce2b89be, 0xf44ab637, 0x0723f413, 0xcfec4ae6, 0x3c8508c2, 0x7bfb0b38, 0x8892491c, 0x405df7e9, 0xb334b5cd, 0x89558a44, 0x7a3cc860, 0xb2f37695, 0x419a34b1, 0x41f5dbb7, 0xb29c9993, 0x7a532766, 0x893a6542, 0xb35b5acb, 0x403218ef, 0x88fda61a, 0x7b94e43e, 0x3ceae7c4, 0xcf83a5e0, 0x074c1b15, 0xf4255931, 0xce4466b8, 0x3d2d249c, 0xf5e29a69, 0x068bd84d, 0xe5c88c36, 0x16a1ce12, 0xde6e70e7, 0x2d0732c3, 0x17660d4a, 0xe40f4f6e, 0x2cc0f19b, 0xdfa9b3bf, 0x98d7b045, 0x6bbef261, 0xa3714c94, 0x50180eb0, 0x6a793139, 0x9910731d, 0x51dfcde8, 0xa2b68fcc, 0xbbf054ad, 0x48991689, 0x8056a87c, 0x733fea58, 0x495ed5d1, 0xba3797f5, 0x72f82900, 0x81916b24, 0xc6ef68de, 0x35862afa, 0xfd49940f, 0x0e20d62b, 0x3441e9a2, 0xc728ab86, 0x0fe71573, 0xfc8e5757, 0x1fcd032c, 0xeca44108, 0x246bfffd, 0xd702bdd9, 0xed638250, 0x1e0ac074, 0xd6c57e81, 0x25ac3ca5, 0x62d23f5f, 0x91bb7d7b, 0x5974c38e, 0xaa1d81aa, 0x907cbe23, 0x6315fc07, 0xabda42f2, 0x58b300d6, 0x58dcefd0, 0xabb5adf4, 0x637a1301, 0x90135125, 0xaa726eac, 0x591b2c88, 0x91d4927d, 0x62bdd059, 0x25c3d3a3, 0xd6aa9187, 0x1e652f72, 0xed0c6d56, 0xd76d52df, 0x240410fb, 0xeccbae0e, 0x1fa2ec2a, 0xfce1b851, 0x0f88fa75, 0xc7474480, 0x342e06a4, 0x0e4f392d, 0xfd267b09, 0x35e9c5fc, 0xc68087d8, 0x81fe8422, 0x7297c606, 0xba5878f3, 0x49313ad7, 0x7350055e, 0x8039477a, 0x48f6f98f, 0xbb9fbbab, 0x19293467, 0xea407643, 0x228fc8b6, 0xd1e68a92, 0xeb87b51b, 0x18eef73f, 0xd02149ca, 0x23480bee, 0x64360814, 0x975f4a30, 0x5f90f4c5, 0xacf9b6e1, 0x96988968, 0x65f1cb4c, 0xad3e75b9, 0x5e57379d, 0xbd1463e6, 0x4e7d21c2, 0x86b29f37, 0x75dbdd13, 0x4fbae29a, 0xbcd3a0be, 0x741c1e4b, 0x87755c6f, 0xc00b5f95, 0x33621db1, 0xfbada344, 0x08c4e160, 0x32a5dee9, 0xc1cc9ccd, 0x09032238, 0xfa6a601c, 0xfa058f1a, 0x096ccd3e, 0xc1a373cb, 0x32ca31ef, 0x08ab0e66, 0xfbc24c42, 0x330df2b7, 0xc064b093, 0x871ab369, 0x7473f14d, 0xbcbc4fb8, 0x4fd50d9c, 0x75b43215, 0x86dd7031, 0x4e12cec4, 0xbd7b8ce0, 0x5e38d89b, 0xad519abf, 0x659e244a, 0x96f7666e, 0xac9659e7, 0x5fff1bc3, 0x9730a536, 0x6459e712, 0x2327e4e8, 0xd04ea6cc, 0x18811839, 0xebe85a1d, 0xd1896594, 0x22e027b0, 0xea2f9945, 0x1946db61 +}, +{ +0x00000000, 0x38a340b9, 0x2b55b681, 0x13f6f638, 0x93b9ab7d, 0xab1aebc4, 0xb8ec1dfc, 0x804f5d45, 0xa9af9b73, 0x910cdbca, 0x82fa2df2, 0xba596d4b, 0x3a16300e, 0x02b570b7, 0x1143868f, 0x29e0c636, 0x1e641b33, 0x26c75b8a, 0x3531adb2, 0x0d92ed0b, 0x8dddb04e, 0xb57ef0f7, 0xa68806cf, 0x9e2b4676, 0xb7cb8040, 0x8f68c0f9, 0x9c9e36c1, 0xa43d7678, 0x24722b3d, 0x1cd16b84, 0x0f279dbc, 0x3784dd05, 0xa1d17149, 0x997231f0, 0x8a84c7c8, 0xb2278771, 0x3268da34, 0x0acb9a8d, 0x193d6cb5, 0x219e2c0c, 0x087eea3a, 0x30ddaa83, 0x232b5cbb, 0x1b881c02, 0x9bc74147, 0xa36401fe, 0xb092f7c6, 0x8831b77f, 0xbfb56a7a, 0x87162ac3, 0x94e0dcfb, 0xac439c42, 0x2c0cc107, 0x14af81be, 0x07597786, 0x3ffa373f, 0x161af109, 0x2eb9b1b0, 0x3d4f4788, 0x05ec0731, 0x85a35a74, 0xbd001acd, 0xaef6ecf5, 0x9655ac4c, 0x9f1bff13, 0xa7b8bfaa, 0xb44e4992, 0x8ced092b, 0x0ca2546e, 0x340114d7, 0x27f7e2ef, 0x1f54a256, 0x36b46460, 0x0e1724d9, 0x1de1d2e1, 0x25429258, 0xa50dcf1d, 0x9dae8fa4, 0x8e58799c, 0xb6fb3925, 0x817fe420, 0xb9dca499, 0xaa2a52a1, 0x92891218, 0x12c64f5d, 0x2a650fe4, 0x3993f9dc, 0x0130b965, 0x28d07f53, 0x10733fea, 0x0385c9d2, 0x3b26896b, 0xbb69d42e, 0x83ca9497, 0x903c62af, 0xa89f2216, 0x3eca8e5a, 0x0669cee3, 0x159f38db, 0x2d3c7862, 0xad732527, 0x95d0659e, 0x862693a6, 0xbe85d31f, 0x97651529, 0xafc65590, 0xbc30a3a8, 0x8493e311, 0x04dcbe54, 0x3c7ffeed, 0x2f8908d5, 0x172a486c, 0x20ae9569, 0x180dd5d0, 0x0bfb23e8, 0x33586351, 0xb3173e14, 0x8bb47ead, 0x98428895, 0xa0e1c82c, 0x89010e1a, 0xb1a24ea3, 0xa254b89b, 0x9af7f822, 0x1ab8a567, 0x221be5de, 0x31ed13e6, 0x094e535f, 0x1a8d25c6, 0x222e657f, 0x31d89347, 0x097bd3fe, 0x89348ebb, 0xb197ce02, 0xa261383a, 0x9ac27883, 0xb322beb5, 0x8b81fe0c, 0x98770834, 0xa0d4488d, 0x209b15c8, 0x18385571, 0x0bcea349, 0x336de3f0, 0x04e93ef5, 0x3c4a7e4c, 0x2fbc8874, 0x171fc8cd, 0x97509588, 0xaff3d531, 0xbc052309, 0x84a663b0, 0xad46a586, 0x95e5e53f, 0x86131307, 0xbeb053be, 0x3eff0efb, 0x065c4e42, 0x15aab87a, 0x2d09f8c3, 0xbb5c548f, 0x83ff1436, 0x9009e20e, 0xa8aaa2b7, 0x28e5fff2, 0x1046bf4b, 0x03b04973, 0x3b1309ca, 0x12f3cffc, 0x2a508f45, 0x39a6797d, 0x010539c4, 0x814a6481, 0xb9e92438, 0xaa1fd200, 0x92bc92b9, 0xa5384fbc, 0x9d9b0f05, 0x8e6df93d, 0xb6ceb984, 0x3681e4c1, 0x0e22a478, 0x1dd45240, 0x257712f9, 0x0c97d4cf, 0x34349476, 0x27c2624e, 0x1f6122f7, 0x9f2e7fb2, 0xa78d3f0b, 0xb47bc933, 0x8cd8898a, 0x8596dad5, 0xbd359a6c, 0xaec36c54, 0x96602ced, 0x162f71a8, 0x2e8c3111, 0x3d7ac729, 0x05d98790, 0x2c3941a6, 0x149a011f, 0x076cf727, 0x3fcfb79e, 0xbf80eadb, 0x8723aa62, 0x94d55c5a, 0xac761ce3, 0x9bf2c1e6, 0xa351815f, 0xb0a77767, 0x880437de, 0x084b6a9b, 0x30e82a22, 0x231edc1a, 0x1bbd9ca3, 0x325d5a95, 0x0afe1a2c, 0x1908ec14, 0x21abacad, 0xa1e4f1e8, 0x9947b151, 0x8ab14769, 0xb21207d0, 0x2447ab9c, 0x1ce4eb25, 0x0f121d1d, 0x37b15da4, 0xb7fe00e1, 0x8f5d4058, 0x9cabb660, 0xa408f6d9, 0x8de830ef, 0xb54b7056, 0xa6bd866e, 0x9e1ec6d7, 0x1e519b92, 0x26f2db2b, 0x35042d13, 0x0da76daa, 0x3a23b0af, 0x0280f016, 0x1176062e, 0x29d54697, 0xa99a1bd2, 0x91395b6b, 0x82cfad53, 0xba6cedea, 0x938c2bdc, 0xab2f6b65, 0xb8d99d5d, 0x807adde4, 0x003580a1, 0x3896c018, 0x2b603620, 0x13c37699 +}, +{ +0x00000000, 0x18357cb5, 0xe6e52090, 0xfed05c25, 0x4b9519fd, 0x53a06548, 0xad70396d, 0xb54545d8, 0x2991418d, 0x31a43d38, 0xcf74611d, 0xd7411da8, 0x62045870, 0x7a3124c5, 0x84e178e0, 0x9cd40455, 0xfe8648c8, 0xe6b3347d, 0x18636858, 0x005614ed, 0xb5135135, 0xad262d80, 0x53f671a5, 0x4bc30d10, 0xd7170945, 0xcf2275f0, 0x31f229d5, 0x29c75560, 0x9c8210b8, 0x84b76c0d, 0x7a673028, 0x62524c9d, 0xb3a204d1, 0xab977864, 0x55472441, 0x4d7258f4, 0xf8371d2c, 0xe0026199, 0x1ed23dbc, 0x06e74109, 0x9a33455c, 0x820639e9, 0x7cd665cc, 0x64e31979, 0xd1a65ca1, 0xc9932014, 0x37437c31, 0x2f760084, 0x4d244c19, 0x551130ac, 0xabc16c89, 0xb3f4103c, 0x06b155e4, 0x1e842951, 0xe0547574, 0xf86109c1, 0x64b50d94, 0x7c807121, 0x82502d04, 0x9a6551b1, 0x2f201469, 0x371568dc, 0xc9c534f9, 0xd1f0484c, 0x59290b20, 0x411c7795, 0xbfcc2bb0, 0xa7f95705, 0x12bc12dd, 0x0a896e68, 0xf459324d, 0xec6c4ef8, 0x70b84aad, 0x688d3618, 0x965d6a3d, 0x8e681688, 0x3b2d5350, 0x23182fe5, 0xddc873c0, 0xc5fd0f75, 0xa7af43e8, 0xbf9a3f5d, 0x414a6378, 0x597f1fcd, 0xec3a5a15, 0xf40f26a0, 0x0adf7a85, 0x12ea0630, 0x8e3e0265, 0x960b7ed0, 0x68db22f5, 0x70ee5e40, 0xc5ab1b98, 0xdd9e672d, 0x234e3b08, 0x3b7b47bd, 0xea8b0ff1, 0xf2be7344, 0x0c6e2f61, 0x145b53d4, 0xa11e160c, 0xb92b6ab9, 0x47fb369c, 0x5fce4a29, 0xc31a4e7c, 0xdb2f32c9, 0x25ff6eec, 0x3dca1259, 0x888f5781, 0x90ba2b34, 0x6e6a7711, 0x765f0ba4, 0x140d4739, 0x0c383b8c, 0xf2e867a9, 0xeadd1b1c, 0x5f985ec4, 0x47ad2271, 0xb97d7e54, 0xa14802e1, 0x3d9c06b4, 0x25a97a01, 0xdb792624, 0xc34c5a91, 0x76091f49, 0x6e3c63fc, 0x90ec3fd9, 0x88d9436c, 0x3ee7bdc4, 0x26d2c171, 0xd8029d54, 0xc037e1e1, 0x7572a439, 0x6d47d88c, 0x939784a9, 0x8ba2f81c, 0x1776fc49, 0x0f4380fc, 0xf193dcd9, 0xe9a6a06c, 0x5ce3e5b4, 0x44d69901, 0xba06c524, 0xa233b991, 0xc061f50c, 0xd85489b9, 0x2684d59c, 0x3eb1a929, 0x8bf4ecf1, 0x93c19044, 0x6d11cc61, 0x7524b0d4, 0xe9f0b481, 0xf1c5c834, 0x0f159411, 0x1720e8a4, 0xa265ad7c, 0xba50d1c9, 0x44808dec, 0x5cb5f159, 0x8d45b915, 0x9570c5a0, 0x6ba09985, 0x7395e530, 0xc6d0a0e8, 0xdee5dc5d, 0x20358078, 0x3800fccd, 0xa4d4f898, 0xbce1842d, 0x4231d808, 0x5a04a4bd, 0xef41e165, 0xf7749dd0, 0x09a4c1f5, 0x1191bd40, 0x73c3f1dd, 0x6bf68d68, 0x9526d14d, 0x8d13adf8, 0x3856e820, 0x20639495, 0xdeb3c8b0, 0xc686b405, 0x5a52b050, 0x4267cce5, 0xbcb790c0, 0xa482ec75, 0x11c7a9ad, 0x09f2d518, 0xf722893d, 0xef17f588, 0x67ceb6e4, 0x7ffbca51, 0x812b9674, 0x991eeac1, 0x2c5baf19, 0x346ed3ac, 0xcabe8f89, 0xd28bf33c, 0x4e5ff769, 0x566a8bdc, 0xa8bad7f9, 0xb08fab4c, 0x05caee94, 0x1dff9221, 0xe32fce04, 0xfb1ab2b1, 0x9948fe2c, 0x817d8299, 0x7faddebc, 0x6798a209, 0xd2dde7d1, 0xcae89b64, 0x3438c741, 0x2c0dbbf4, 0xb0d9bfa1, 0xa8ecc314, 0x563c9f31, 0x4e09e384, 0xfb4ca65c, 0xe379dae9, 0x1da986cc, 0x059cfa79, 0xd46cb235, 0xcc59ce80, 0x328992a5, 0x2abcee10, 0x9ff9abc8, 0x87ccd77d, 0x791c8b58, 0x6129f7ed, 0xfdfdf3b8, 0xe5c88f0d, 0x1b18d328, 0x032daf9d, 0xb668ea45, 0xae5d96f0, 0x508dcad5, 0x48b8b660, 0x2aeafafd, 0x32df8648, 0xcc0fda6d, 0xd43aa6d8, 0x617fe300, 0x794a9fb5, 0x879ac390, 0x9fafbf25, 0x037bbb70, 0x1b4ec7c5, 0xe59e9be0, 0xfdabe755, 0x48eea28d, 0x50dbde38, 0xae0b821d, 0xb63efea8 +}, +{ +0x00000000, 0x675afb43, 0xf4f87eed, 0x93a285ae, 0x8bbff1bf, 0xece50afc, 0x7f478f52, 0x181d7411, 0xb952a580, 0xde085ec3, 0x4daadb6d, 0x2af0202e, 0x32ed543f, 0x55b7af7c, 0xc6152ad2, 0xa14fd191, 0x3b3ad58f, 0x5c602ecc, 0xcfc2ab62, 0xa8985021, 0xb0852430, 0xd7dfdf73, 0x447d5add, 0x2327a19e, 0x8268700f, 0xe5328b4c, 0x76900ee2, 0x11caf5a1, 0x09d781b0, 0x6e8d7af3, 0xfd2fff5d, 0x9a75041e, 0x6ee8f92b, 0x09b20268, 0x9a1087c6, 0xfd4a7c85, 0xe5570894, 0x820df3d7, 0x11af7679, 0x76f58d3a, 0xd7ba5cab, 0xb0e0a7e8, 0x23422246, 0x4418d905, 0x5c05ad14, 0x3b5f5657, 0xa8fdd3f9, 0xcfa728ba, 0x55d22ca4, 0x3288d7e7, 0xa12a5249, 0xc670a90a, 0xde6ddd1b, 0xb9372658, 0x2a95a3f6, 0x4dcf58b5, 0xec808924, 0x8bda7267, 0x1878f7c9, 0x7f220c8a, 0x673f789b, 0x006583d8, 0x93c70676, 0xf49dfd35, 0xeae342a7, 0x8db9b9e4, 0x1e1b3c4a, 0x7941c709, 0x615cb318, 0x0606485b, 0x95a4cdf5, 0xf2fe36b6, 0x53b1e727, 0x34eb1c64, 0xa74999ca, 0xc0136289, 0xd80e1698, 0xbf54eddb, 0x2cf66875, 0x4bac9336, 0xd1d99728, 0xb6836c6b, 0x2521e9c5, 0x427b1286, 0x5a666697, 0x3d3c9dd4, 0xae9e187a, 0xc9c4e339, 0x688b32a8, 0x0fd1c9eb, 0x9c734c45, 0xfb29b706, 0xe334c317, 0x846e3854, 0x17ccbdfa, 0x709646b9, 0x840bbb8c, 0xe35140cf, 0x70f3c561, 0x17a93e22, 0x0fb44a33, 0x68eeb170, 0xfb4c34de, 0x9c16cf9d, 0x3d591e0c, 0x5a03e54f, 0xc9a160e1, 0xaefb9ba2, 0xb6e6efb3, 0xd1bc14f0, 0x421e915e, 0x25446a1d, 0xbf316e03, 0xd86b9540, 0x4bc910ee, 0x2c93ebad, 0x348e9fbc, 0x53d464ff, 0xc076e151, 0xa72c1a12, 0x0663cb83, 0x613930c0, 0xf29bb56e, 0x95c14e2d, 0x8ddc3a3c, 0xea86c17f, 0x792444d1, 0x1e7ebf92, 0xa946f0d1, 0xce1c0b92, 0x5dbe8e3c, 0x3ae4757f, 0x22f9016e, 0x45a3fa2d, 0xd6017f83, 0xb15b84c0, 0x10145551, 0x774eae12, 0xe4ec2bbc, 0x83b6d0ff, 0x9baba4ee, 0xfcf15fad, 0x6f53da03, 0x08092140, 0x927c255e, 0xf526de1d, 0x66845bb3, 0x01dea0f0, 0x19c3d4e1, 0x7e992fa2, 0xed3baa0c, 0x8a61514f, 0x2b2e80de, 0x4c747b9d, 0xdfd6fe33, 0xb88c0570, 0xa0917161, 0xc7cb8a22, 0x54690f8c, 0x3333f4cf, 0xc7ae09fa, 0xa0f4f2b9, 0x33567717, 0x540c8c54, 0x4c11f845, 0x2b4b0306, 0xb8e986a8, 0xdfb37deb, 0x7efcac7a, 0x19a65739, 0x8a04d297, 0xed5e29d4, 0xf5435dc5, 0x9219a686, 0x01bb2328, 0x66e1d86b, 0xfc94dc75, 0x9bce2736, 0x086ca298, 0x6f3659db, 0x772b2dca, 0x1071d689, 0x83d35327, 0xe489a864, 0x45c679f5, 0x229c82b6, 0xb13e0718, 0xd664fc5b, 0xce79884a, 0xa9237309, 0x3a81f6a7, 0x5ddb0de4, 0x43a5b276, 0x24ff4935, 0xb75dcc9b, 0xd00737d8, 0xc81a43c9, 0xaf40b88a, 0x3ce23d24, 0x5bb8c667, 0xfaf717f6, 0x9dadecb5, 0x0e0f691b, 0x69559258, 0x7148e649, 0x16121d0a, 0x85b098a4, 0xe2ea63e7, 0x789f67f9, 0x1fc59cba, 0x8c671914, 0xeb3de257, 0xf3209646, 0x947a6d05, 0x07d8e8ab, 0x608213e8, 0xc1cdc279, 0xa697393a, 0x3535bc94, 0x526f47d7, 0x4a7233c6, 0x2d28c885, 0xbe8a4d2b, 0xd9d0b668, 0x2d4d4b5d, 0x4a17b01e, 0xd9b535b0, 0xbeefcef3, 0xa6f2bae2, 0xc1a841a1, 0x520ac40f, 0x35503f4c, 0x941feedd, 0xf345159e, 0x60e79030, 0x07bd6b73, 0x1fa01f62, 0x78fae421, 0xeb58618f, 0x8c029acc, 0x16779ed2, 0x712d6591, 0xe28fe03f, 0x85d51b7c, 0x9dc86f6d, 0xfa92942e, 0x69301180, 0x0e6aeac3, 0xaf253b52, 0xc87fc011, 0x5bdd45bf, 0x3c87befc, 0x249acaed, 0x43c031ae, 0xd062b400, 0xb7384f43 +}, +{ +0x00000000, 0x8340a43e, 0x5de75eb4, 0xdea7fa8a, 0x382d7662, 0xbb6dd25c, 0x65ca28d6, 0xe68a8ce8, 0x2b88214e, 0xa8c88570, 0x766f7ffa, 0xf52fdbc4, 0x13a5572c, 0x90e5f312, 0x4e420998, 0xcd02ada6, 0x7bf65043, 0xf8b6f47d, 0x26110ef7, 0xa551aac9, 0x43db2621, 0xc09b821f, 0x1e3c7895, 0x9d7cdcab, 0x507e710d, 0xd33ed533, 0x0d992fb9, 0x8ed98b87, 0x6853076f, 0xeb13a351, 0x35b459db, 0xb6f4fde5, 0x2db2cadb, 0xaef26ee5, 0x7055946f, 0xf3153051, 0x159fbcb9, 0x96df1887, 0x4878e20d, 0xcb384633, 0x063aeb95, 0x857a4fab, 0x5bddb521, 0xd89d111f, 0x3e179df7, 0xbd5739c9, 0x63f0c343, 0xe0b0677d, 0x56449a98, 0xd5043ea6, 0x0ba3c42c, 0x88e36012, 0x6e69ecfa, 0xed2948c4, 0x338eb24e, 0xb0ce1670, 0x7dccbbd6, 0xfe8c1fe8, 0x202be562, 0xa36b415c, 0x45e1cdb4, 0xc6a1698a, 0x18069300, 0x9b46373e, 0xea6ed457, 0x692e7069, 0xb7898ae3, 0x34c92edd, 0xd243a235, 0x5103060b, 0x8fa4fc81, 0x0ce458bf, 0xc1e6f519, 0x42a65127, 0x9c01abad, 0x1f410f93, 0xf9cb837b, 0x7a8b2745, 0xa42cddcf, 0x276c79f1, 0x91988414, 0x12d8202a, 0xcc7fdaa0, 0x4f3f7e9e, 0xa9b5f276, 0x2af55648, 0xf452acc2, 0x771208fc, 0xba10a55a, 0x39500164, 0xe7f7fbee, 0x64b75fd0, 0x823dd338, 0x017d7706, 0xdfda8d8c, 0x5c9a29b2, 0xc7dc1e8c, 0x449cbab2, 0x9a3b4038, 0x197be406, 0xfff168ee, 0x7cb1ccd0, 0xa216365a, 0x21569264, 0xec543fc2, 0x6f149bfc, 0xb1b36176, 0x32f3c548, 0xd47949a0, 0x5739ed9e, 0x899e1714, 0x0adeb32a, 0xbc2a4ecf, 0x3f6aeaf1, 0xe1cd107b, 0x628db445, 0x840738ad, 0x07479c93, 0xd9e06619, 0x5aa0c227, 0x97a26f81, 0x14e2cbbf, 0xca453135, 0x4905950b, 0xaf8f19e3, 0x2ccfbddd, 0xf2684757, 0x7128e369, 0x70d6ecd7, 0xf39648e9, 0x2d31b263, 0xae71165d, 0x48fb9ab5, 0xcbbb3e8b, 0x151cc401, 0x965c603f, 0x5b5ecd99, 0xd81e69a7, 0x06b9932d, 0x85f93713, 0x6373bbfb, 0xe0331fc5, 0x3e94e54f, 0xbdd44171, 0x0b20bc94, 0x886018aa, 0x56c7e220, 0xd587461e, 0x330dcaf6, 0xb04d6ec8, 0x6eea9442, 0xedaa307c, 0x20a89dda, 0xa3e839e4, 0x7d4fc36e, 0xfe0f6750, 0x1885ebb8, 0x9bc54f86, 0x4562b50c, 0xc6221132, 0x5d64260c, 0xde248232, 0x008378b8, 0x83c3dc86, 0x6549506e, 0xe609f450, 0x38ae0eda, 0xbbeeaae4, 0x76ec0742, 0xf5aca37c, 0x2b0b59f6, 0xa84bfdc8, 0x4ec17120, 0xcd81d51e, 0x13262f94, 0x90668baa, 0x2692764f, 0xa5d2d271, 0x7b7528fb, 0xf8358cc5, 0x1ebf002d, 0x9dffa413, 0x43585e99, 0xc018faa7, 0x0d1a5701, 0x8e5af33f, 0x50fd09b5, 0xd3bdad8b, 0x35372163, 0xb677855d, 0x68d07fd7, 0xeb90dbe9, 0x9ab83880, 0x19f89cbe, 0xc75f6634, 0x441fc20a, 0xa2954ee2, 0x21d5eadc, 0xff721056, 0x7c32b468, 0xb13019ce, 0x3270bdf0, 0xecd7477a, 0x6f97e344, 0x891d6fac, 0x0a5dcb92, 0xd4fa3118, 0x57ba9526, 0xe14e68c3, 0x620eccfd, 0xbca93677, 0x3fe99249, 0xd9631ea1, 0x5a23ba9f, 0x84844015, 0x07c4e42b, 0xcac6498d, 0x4986edb3, 0x97211739, 0x1461b307, 0xf2eb3fef, 0x71ab9bd1, 0xaf0c615b, 0x2c4cc565, 0xb70af25b, 0x344a5665, 0xeaedacef, 0x69ad08d1, 0x8f278439, 0x0c672007, 0xd2c0da8d, 0x51807eb3, 0x9c82d315, 0x1fc2772b, 0xc1658da1, 0x4225299f, 0xa4afa577, 0x27ef0149, 0xf948fbc3, 0x7a085ffd, 0xccfca218, 0x4fbc0626, 0x911bfcac, 0x125b5892, 0xf4d1d47a, 0x77917044, 0xa9368ace, 0x2a762ef0, 0xe7748356, 0x64342768, 0xba93dde2, 0x39d379dc, 0xdf59f534, 0x5c19510a, 0x82beab80, 0x01fe0fbe +}, +{ +0x00000000, 0x728c7740, 0xe98fc79a, 0x9b03b0da, 0x680eb7cc, 0x1a82c08c, 0x81817056, 0xf30d0716, 0x86b591f7, 0xf439e6b7, 0x6f3a566d, 0x1db6212d, 0xeebb263b, 0x9c37517b, 0x0734e1a1, 0x75b896e1, 0xc995e163, 0xbb199623, 0x201a26f9, 0x529651b9, 0xa19b56af, 0xd31721ef, 0x48149135, 0x3a98e675, 0x4f207094, 0x3dac07d4, 0xa6afb70e, 0xd423c04e, 0x272ec758, 0x55a2b018, 0xcea100c2, 0xbc2d7782, 0x0c6d144b, 0x7ee1630b, 0xe5e2d3d1, 0x976ea491, 0x6463a387, 0x16efd4c7, 0x8dec641d, 0xff60135d, 0x8ad885bc, 0xf854f2fc, 0x63574226, 0x11db3566, 0xe2d63270, 0x905a4530, 0x0b59f5ea, 0x79d582aa, 0xc5f8f528, 0xb7748268, 0x2c7732b2, 0x5efb45f2, 0xadf642e4, 0xdf7a35a4, 0x4479857e, 0x36f5f23e, 0x434d64df, 0x31c1139f, 0xaac2a345, 0xd84ed405, 0x2b43d313, 0x59cfa453, 0xc2cc1489, 0xb04063c9, 0x461769b9, 0x349b1ef9, 0xaf98ae23, 0xdd14d963, 0x2e19de75, 0x5c95a935, 0xc79619ef, 0xb51a6eaf, 0xc0a2f84e, 0xb22e8f0e, 0x292d3fd4, 0x5ba14894, 0xa8ac4f82, 0xda2038c2, 0x41238818, 0x33afff58, 0x8f8288da, 0xfd0eff9a, 0x660d4f40, 0x14813800, 0xe78c3f16, 0x95004856, 0x0e03f88c, 0x7c8f8fcc, 0x0937192d, 0x7bbb6e6d, 0xe0b8deb7, 0x9234a9f7, 0x6139aee1, 0x13b5d9a1, 0x88b6697b, 0xfa3a1e3b, 0x4a7a7df2, 0x38f60ab2, 0xa3f5ba68, 0xd179cd28, 0x2274ca3e, 0x50f8bd7e, 0xcbfb0da4, 0xb9777ae4, 0xcccfec05, 0xbe439b45, 0x25402b9f, 0x57cc5cdf, 0xa4c15bc9, 0xd64d2c89, 0x4d4e9c53, 0x3fc2eb13, 0x83ef9c91, 0xf163ebd1, 0x6a605b0b, 0x18ec2c4b, 0xebe12b5d, 0x996d5c1d, 0x026eecc7, 0x70e29b87, 0x055a0d66, 0x77d67a26, 0xecd5cafc, 0x9e59bdbc, 0x6d54baaa, 0x1fd8cdea, 0x84db7d30, 0xf6570a70, 0xb94dd372, 0xcbc1a432, 0x50c214e8, 0x224e63a8, 0xd14364be, 0xa3cf13fe, 0x38cca324, 0x4a40d464, 0x3ff84285, 0x4d7435c5, 0xd677851f, 0xa4fbf25f, 0x57f6f549, 0x257a8209, 0xbe7932d3, 0xccf54593, 0x70d83211, 0x02544551, 0x9957f58b, 0xebdb82cb, 0x18d685dd, 0x6a5af29d, 0xf1594247, 0x83d53507, 0xf66da3e6, 0x84e1d4a6, 0x1fe2647c, 0x6d6e133c, 0x9e63142a, 0xecef636a, 0x77ecd3b0, 0x0560a4f0, 0xb520c739, 0xc7acb079, 0x5caf00a3, 0x2e2377e3, 0xdd2e70f5, 0xafa207b5, 0x34a1b76f, 0x462dc02f, 0x339556ce, 0x4119218e, 0xda1a9154, 0xa896e614, 0x5b9be102, 0x29179642, 0xb2142698, 0xc09851d8, 0x7cb5265a, 0x0e39511a, 0x953ae1c0, 0xe7b69680, 0x14bb9196, 0x6637e6d6, 0xfd34560c, 0x8fb8214c, 0xfa00b7ad, 0x888cc0ed, 0x138f7037, 0x61030777, 0x920e0061, 0xe0827721, 0x7b81c7fb, 0x090db0bb, 0xff5abacb, 0x8dd6cd8b, 0x16d57d51, 0x64590a11, 0x97540d07, 0xe5d87a47, 0x7edbca9d, 0x0c57bddd, 0x79ef2b3c, 0x0b635c7c, 0x9060eca6, 0xe2ec9be6, 0x11e19cf0, 0x636debb0, 0xf86e5b6a, 0x8ae22c2a, 0x36cf5ba8, 0x44432ce8, 0xdf409c32, 0xadcceb72, 0x5ec1ec64, 0x2c4d9b24, 0xb74e2bfe, 0xc5c25cbe, 0xb07aca5f, 0xc2f6bd1f, 0x59f50dc5, 0x2b797a85, 0xd8747d93, 0xaaf80ad3, 0x31fbba09, 0x4377cd49, 0xf337ae80, 0x81bbd9c0, 0x1ab8691a, 0x68341e5a, 0x9b39194c, 0xe9b56e0c, 0x72b6ded6, 0x003aa996, 0x75823f77, 0x070e4837, 0x9c0df8ed, 0xee818fad, 0x1d8c88bb, 0x6f00fffb, 0xf4034f21, 0x868f3861, 0x3aa24fe3, 0x482e38a3, 0xd32d8879, 0xa1a1ff39, 0x52acf82f, 0x20208f6f, 0xbb233fb5, 0xc9af48f5, 0xbc17de14, 0xce9ba954, 0x5598198e, 0x27146ece, 0xd41969d8, 0xa6951e98, 0x3d96ae42, 0x4f1ad902 +}, +{ +0x00000000, 0x8a0c2a2f, 0xd51d9aa4, 0x5f11b08b, 0x0358d6e5, 0x8954fcca, 0xd6454c41, 0x5c49666e, 0x5caf03f6, 0xd6a329d9, 0x89b29952, 0x03beb37d, 0x5ff7d513, 0xd5fbff3c, 0x8aea4fb7, 0x00e66598, 0xb09f5dac, 0x3a937783, 0x6582c708, 0xef8eed27, 0xb3c78b49, 0x39cba166, 0x66da11ed, 0xecd63bc2, 0xec305e5a, 0x663c7475, 0x392dc4fe, 0xb321eed1, 0xef6888bf, 0x6564a290, 0x3a75121b, 0xb0793834, 0x4c40ec24, 0xc64cc60b, 0x995d7680, 0x13515caf, 0x4f183ac1, 0xc51410ee, 0x9a05a065, 0x10098a4a, 0x10efefd2, 0x9ae3c5fd, 0xc5f27576, 0x4ffe5f59, 0x13b73937, 0x99bb1318, 0xc6aaa393, 0x4ca689bc, 0xfcdfb188, 0x76d39ba7, 0x29c22b2c, 0xa3ce0103, 0xff87676d, 0x758b4d42, 0x2a9afdc9, 0xa096d7e6, 0xa070b27e, 0x2a7c9851, 0x756d28da, 0xff6102f5, 0xa328649b, 0x29244eb4, 0x7635fe3f, 0xfc39d410, 0x1a4fda2e, 0x9043f001, 0xcf52408a, 0x455e6aa5, 0x19170ccb, 0x931b26e4, 0xcc0a966f, 0x4606bc40, 0x46e0d9d8, 0xccecf3f7, 0x93fd437c, 0x19f16953, 0x45b80f3d, 0xcfb42512, 0x90a59599, 0x1aa9bfb6, 0xaad08782, 0x20dcadad, 0x7fcd1d26, 0xf5c13709, 0xa9885167, 0x23847b48, 0x7c95cbc3, 0xf699e1ec, 0xf67f8474, 0x7c73ae5b, 0x23621ed0, 0xa96e34ff, 0xf5275291, 0x7f2b78be, 0x203ac835, 0xaa36e21a, 0x560f360a, 0xdc031c25, 0x8312acae, 0x091e8681, 0x5557e0ef, 0xdf5bcac0, 0x804a7a4b, 0x0a465064, 0x0aa035fc, 0x80ac1fd3, 0xdfbdaf58, 0x55b18577, 0x09f8e319, 0x83f4c936, 0xdce579bd, 0x56e95392, 0xe6906ba6, 0x6c9c4189, 0x338df102, 0xb981db2d, 0xe5c8bd43, 0x6fc4976c, 0x30d527e7, 0xbad90dc8, 0xba3f6850, 0x3033427f, 0x6f22f2f4, 0xe52ed8db, 0xb967beb5, 0x336b949a, 0x6c7a2411, 0xe6760e3e, 0xbf255e69, 0x35297446, 0x6a38c4cd, 0xe034eee2, 0xbc7d888c, 0x3671a2a3, 0x69601228, 0xe36c3807, 0xe38a5d9f, 0x698677b0, 0x3697c73b, 0xbc9bed14, 0xe0d28b7a, 0x6adea155, 0x35cf11de, 0xbfc33bf1, 0x0fba03c5, 0x85b629ea, 0xdaa79961, 0x50abb34e, 0x0ce2d520, 0x86eeff0f, 0xd9ff4f84, 0x53f365ab, 0x53150033, 0xd9192a1c, 0x86089a97, 0x0c04b0b8, 0x504dd6d6, 0xda41fcf9, 0x85504c72, 0x0f5c665d, 0xf365b24d, 0x79699862, 0x267828e9, 0xac7402c6, 0xf03d64a8, 0x7a314e87, 0x2520fe0c, 0xaf2cd423, 0xafcab1bb, 0x25c69b94, 0x7ad72b1f, 0xf0db0130, 0xac92675e, 0x269e4d71, 0x798ffdfa, 0xf383d7d5, 0x43faefe1, 0xc9f6c5ce, 0x96e77545, 0x1ceb5f6a, 0x40a23904, 0xcaae132b, 0x95bfa3a0, 0x1fb3898f, 0x1f55ec17, 0x9559c638, 0xca4876b3, 0x40445c9c, 0x1c0d3af2, 0x960110dd, 0xc910a056, 0x431c8a79, 0xa56a8447, 0x2f66ae68, 0x70771ee3, 0xfa7b34cc, 0xa63252a2, 0x2c3e788d, 0x732fc806, 0xf923e229, 0xf9c587b1, 0x73c9ad9e, 0x2cd81d15, 0xa6d4373a, 0xfa9d5154, 0x70917b7b, 0x2f80cbf0, 0xa58ce1df, 0x15f5d9eb, 0x9ff9f3c4, 0xc0e8434f, 0x4ae46960, 0x16ad0f0e, 0x9ca12521, 0xc3b095aa, 0x49bcbf85, 0x495ada1d, 0xc356f032, 0x9c4740b9, 0x164b6a96, 0x4a020cf8, 0xc00e26d7, 0x9f1f965c, 0x1513bc73, 0xe92a6863, 0x6326424c, 0x3c37f2c7, 0xb63bd8e8, 0xea72be86, 0x607e94a9, 0x3f6f2422, 0xb5630e0d, 0xb5856b95, 0x3f8941ba, 0x6098f131, 0xea94db1e, 0xb6ddbd70, 0x3cd1975f, 0x63c027d4, 0xe9cc0dfb, 0x59b535cf, 0xd3b91fe0, 0x8ca8af6b, 0x06a48544, 0x5aede32a, 0xd0e1c905, 0x8ff0798e, 0x05fc53a1, 0x051a3639, 0x8f161c16, 0xd007ac9d, 0x5a0b86b2, 0x0642e0dc, 0x8c4ecaf3, 0xd35f7a78, 0x59535057 +}, +{ +0x00000000, 0x6f5303bc, 0xd2812c3b, 0xbdd22f87, 0x30a13391, 0x5ff2302d, 0xe2201faa, 0x8d731c16, 0xa4d636cc, 0xcb853570, 0x76571af7, 0x1904194b, 0x9477055d, 0xfb2406e1, 0x46f62966, 0x29a52ada, 0x28332b1e, 0x476028a2, 0xfab20725, 0x95e10499, 0x1892188f, 0x77c11b33, 0xca1334b4, 0xa5403708, 0x8ce51dd2, 0xe3b61e6e, 0x5e6431e9, 0x31373255, 0xbc442e43, 0xd3172dff, 0x6ec50278, 0x019601c4, 0xfeb7cc76, 0x91e4cfca, 0x2c36e04d, 0x4365e3f1, 0xce16ffe7, 0xa145fc5b, 0x1c97d3dc, 0x73c4d060, 0x5a61faba, 0x3532f906, 0x88e0d681, 0xe7b3d53d, 0x6ac0c92b, 0x0593ca97, 0xb841e510, 0xd712e6ac, 0xd684e768, 0xb9d7e4d4, 0x0405cb53, 0x6b56c8ef, 0xe625d4f9, 0x8976d745, 0x34a4f8c2, 0x5bf7fb7e, 0x7252d1a4, 0x1d01d218, 0xa0d3fd9f, 0xcf80fe23, 0x42f3e235, 0x2da0e189, 0x9072ce0e, 0xff21cdb2, 0xba984974, 0xd5cb4ac8, 0x6819654f, 0x074a66f3, 0x8a397ae5, 0xe56a7959, 0x58b856de, 0x37eb5562, 0x1e4e7fb8, 0x711d7c04, 0xcccf5383, 0xa39c503f, 0x2eef4c29, 0x41bc4f95, 0xfc6e6012, 0x933d63ae, 0x92ab626a, 0xfdf861d6, 0x402a4e51, 0x2f794ded, 0xa20a51fb, 0xcd595247, 0x708b7dc0, 0x1fd87e7c, 0x367d54a6, 0x592e571a, 0xe4fc789d, 0x8baf7b21, 0x06dc6737, 0x698f648b, 0xd45d4b0c, 0xbb0e48b0, 0x442f8502, 0x2b7c86be, 0x96aea939, 0xf9fdaa85, 0x748eb693, 0x1bddb52f, 0xa60f9aa8, 0xc95c9914, 0xe0f9b3ce, 0x8faab072, 0x32789ff5, 0x5d2b9c49, 0xd058805f, 0xbf0b83e3, 0x02d9ac64, 0x6d8aafd8, 0x6c1cae1c, 0x034fada0, 0xbe9d8227, 0xd1ce819b, 0x5cbd9d8d, 0x33ee9e31, 0x8e3cb1b6, 0xe16fb20a, 0xc8ca98d0, 0xa7999b6c, 0x1a4bb4eb, 0x7518b757, 0xf86bab41, 0x9738a8fd, 0x2aea877a, 0x45b984c6, 0xea7524e8, 0x85262754, 0x38f408d3, 0x57a70b6f, 0xdad41779, 0xb58714c5, 0x08553b42, 0x670638fe, 0x4ea31224, 0x21f01198, 0x9c223e1f, 0xf3713da3, 0x7e0221b5, 0x11512209, 0xac830d8e, 0xc3d00e32, 0xc2460ff6, 0xad150c4a, 0x10c723cd, 0x7f942071, 0xf2e73c67, 0x9db43fdb, 0x2066105c, 0x4f3513e0, 0x6690393a, 0x09c33a86, 0xb4111501, 0xdb4216bd, 0x56310aab, 0x39620917, 0x84b02690, 0xebe3252c, 0x14c2e89e, 0x7b91eb22, 0xc643c4a5, 0xa910c719, 0x2463db0f, 0x4b30d8b3, 0xf6e2f734, 0x99b1f488, 0xb014de52, 0xdf47ddee, 0x6295f269, 0x0dc6f1d5, 0x80b5edc3, 0xefe6ee7f, 0x5234c1f8, 0x3d67c244, 0x3cf1c380, 0x53a2c03c, 0xee70efbb, 0x8123ec07, 0x0c50f011, 0x6303f3ad, 0xded1dc2a, 0xb182df96, 0x9827f54c, 0xf774f6f0, 0x4aa6d977, 0x25f5dacb, 0xa886c6dd, 0xc7d5c561, 0x7a07eae6, 0x1554e95a, 0x50ed6d9c, 0x3fbe6e20, 0x826c41a7, 0xed3f421b, 0x604c5e0d, 0x0f1f5db1, 0xb2cd7236, 0xdd9e718a, 0xf43b5b50, 0x9b6858ec, 0x26ba776b, 0x49e974d7, 0xc49a68c1, 0xabc96b7d, 0x161b44fa, 0x79484746, 0x78de4682, 0x178d453e, 0xaa5f6ab9, 0xc50c6905, 0x487f7513, 0x272c76af, 0x9afe5928, 0xf5ad5a94, 0xdc08704e, 0xb35b73f2, 0x0e895c75, 0x61da5fc9, 0xeca943df, 0x83fa4063, 0x3e286fe4, 0x517b6c58, 0xae5aa1ea, 0xc109a256, 0x7cdb8dd1, 0x13888e6d, 0x9efb927b, 0xf1a891c7, 0x4c7abe40, 0x2329bdfc, 0x0a8c9726, 0x65df949a, 0xd80dbb1d, 0xb75eb8a1, 0x3a2da4b7, 0x557ea70b, 0xe8ac888c, 0x87ff8b30, 0x86698af4, 0xe93a8948, 0x54e8a6cf, 0x3bbba573, 0xb6c8b965, 0xd99bbad9, 0x6449955e, 0x0b1a96e2, 0x22bfbc38, 0x4decbf84, 0xf03e9003, 0x9f6d93bf, 0x121e8fa9, 0x7d4d8c15, 0xc09fa392, 0xafcca02e +}, +{ +0x00000000, 0x94e51b5c, 0xae81bc0a, 0x3a64a756, 0xab570776, 0x3fb21c2a, 0x05d6bb7c, 0x9133a020, 0x77e84956, 0xe30d520a, 0xd969f55c, 0x4d8cee00, 0xdcbf4e20, 0x485a557c, 0x723ef22a, 0xe6dbe976, 0xa247bbbf, 0x36a2a0e3, 0x0cc607b5, 0x98231ce9, 0x0910bcc9, 0x9df5a795, 0xa79100c3, 0x33741b9f, 0xd5aff2e9, 0x414ae9b5, 0x7b2e4ee3, 0xefcb55bf, 0x7ef8f59f, 0xea1deec3, 0xd0794995, 0x449c52c9, 0xb0fc84fe, 0x24199fa2, 0x1e7d38f4, 0x8a9823a8, 0x1bab8388, 0x8f4e98d4, 0xb52a3f82, 0x21cf24de, 0xc714cda8, 0x53f1d6f4, 0x699571a2, 0xfd706afe, 0x6c43cade, 0xf8a6d182, 0xc2c276d4, 0x56276d88, 0x12bb3f41, 0x865e241d, 0xbc3a834b, 0x28df9817, 0xb9ec3837, 0x2d09236b, 0x176d843d, 0x83889f61, 0x65537617, 0xf1b66d4b, 0xcbd2ca1d, 0x5f37d141, 0xce047161, 0x5ae16a3d, 0x6085cd6b, 0xf460d637, 0x66499d9d, 0xf2ac86c1, 0xc8c82197, 0x5c2d3acb, 0xcd1e9aeb, 0x59fb81b7, 0x639f26e1, 0xf77a3dbd, 0x11a1d4cb, 0x8544cf97, 0xbf2068c1, 0x2bc5739d, 0xbaf6d3bd, 0x2e13c8e1, 0x14776fb7, 0x809274eb, 0xc40e2622, 0x50eb3d7e, 0x6a8f9a28, 0xfe6a8174, 0x6f592154, 0xfbbc3a08, 0xc1d89d5e, 0x553d8602, 0xb3e66f74, 0x27037428, 0x1d67d37e, 0x8982c822, 0x18b16802, 0x8c54735e, 0xb630d408, 0x22d5cf54, 0xd6b51963, 0x4250023f, 0x7834a569, 0xecd1be35, 0x7de21e15, 0xe9070549, 0xd363a21f, 0x4786b943, 0xa15d5035, 0x35b84b69, 0x0fdcec3f, 0x9b39f763, 0x0a0a5743, 0x9eef4c1f, 0xa48beb49, 0x306ef015, 0x74f2a2dc, 0xe017b980, 0xda731ed6, 0x4e96058a, 0xdfa5a5aa, 0x4b40bef6, 0x712419a0, 0xe5c102fc, 0x031aeb8a, 0x97fff0d6, 0xad9b5780, 0x397e4cdc, 0xa84decfc, 0x3ca8f7a0, 0x06cc50f6, 0x92294baa, 0x82180b66, 0x16fd103a, 0x2c99b76c, 0xb87cac30, 0x294f0c10, 0xbdaa174c, 0x87ceb01a, 0x132bab46, 0xf5f04230, 0x6115596c, 0x5b71fe3a, 0xcf94e566, 0x5ea74546, 0xca425e1a, 0xf026f94c, 0x64c3e210, 0x205fb0d9, 0xb4baab85, 0x8ede0cd3, 0x1a3b178f, 0x8b08b7af, 0x1fedacf3, 0x25890ba5, 0xb16c10f9, 0x57b7f98f, 0xc352e2d3, 0xf9364585, 0x6dd35ed9, 0xfce0fef9, 0x6805e5a5, 0x526142f3, 0xc68459af, 0x32e48f98, 0xa60194c4, 0x9c653392, 0x088028ce, 0x99b388ee, 0x0d5693b2, 0x373234e4, 0xa3d72fb8, 0x450cc6ce, 0xd1e9dd92, 0xeb8d7ac4, 0x7f686198, 0xee5bc1b8, 0x7abedae4, 0x40da7db2, 0xd43f66ee, 0x90a33427, 0x04462f7b, 0x3e22882d, 0xaac79371, 0x3bf43351, 0xaf11280d, 0x95758f5b, 0x01909407, 0xe74b7d71, 0x73ae662d, 0x49cac17b, 0xdd2fda27, 0x4c1c7a07, 0xd8f9615b, 0xe29dc60d, 0x7678dd51, 0xe45196fb, 0x70b48da7, 0x4ad02af1, 0xde3531ad, 0x4f06918d, 0xdbe38ad1, 0xe1872d87, 0x756236db, 0x93b9dfad, 0x075cc4f1, 0x3d3863a7, 0xa9dd78fb, 0x38eed8db, 0xac0bc387, 0x966f64d1, 0x028a7f8d, 0x46162d44, 0xd2f33618, 0xe897914e, 0x7c728a12, 0xed412a32, 0x79a4316e, 0x43c09638, 0xd7258d64, 0x31fe6412, 0xa51b7f4e, 0x9f7fd818, 0x0b9ac344, 0x9aa96364, 0x0e4c7838, 0x3428df6e, 0xa0cdc432, 0x54ad1205, 0xc0480959, 0xfa2cae0f, 0x6ec9b553, 0xfffa1573, 0x6b1f0e2f, 0x517ba979, 0xc59eb225, 0x23455b53, 0xb7a0400f, 0x8dc4e759, 0x1921fc05, 0x88125c25, 0x1cf74779, 0x2693e02f, 0xb276fb73, 0xf6eaa9ba, 0x620fb2e6, 0x586b15b0, 0xcc8e0eec, 0x5dbdaecc, 0xc958b590, 0xf33c12c6, 0x67d9099a, 0x8102e0ec, 0x15e7fbb0, 0x2f835ce6, 0xbb6647ba, 0x2a55e79a, 0xbeb0fcc6, 0x84d45b90, 0x103140cc +}, +{ +0x00000000, 0x98a63de6, 0xa08c2b84, 0x382a1662, 0x41d7bebe, 0xd9718358, 0xe15b953a, 0x79fda8dc, 0x6a1173c5, 0xf2b74e23, 0xca9d5841, 0x523b65a7, 0x2bc6cd7b, 0xb360f09d, 0x8b4ae6ff, 0x13ecdb19, 0xae6f36ae, 0x36c90b48, 0x0ee31d2a, 0x964520cc, 0xefb88810, 0x771eb5f6, 0x4f34a394, 0xd7929e72, 0xc47e456b, 0x5cd8788d, 0x64f26eef, 0xfc545309, 0x85a9fbd5, 0x1d0fc633, 0x2525d051, 0xbd83edb7, 0x5dc0f028, 0xc566cdce, 0xfd4cdbac, 0x65eae64a, 0x1c174e96, 0x84b17370, 0xbc9b6512, 0x243d58f4, 0x37d183ed, 0xaf77be0b, 0x975da869, 0x0ffb958f, 0x76063d53, 0xeea000b5, 0xd68a16d7, 0x4e2c2b31, 0xf3afc686, 0x6b09fb60, 0x5323ed02, 0xcb85d0e4, 0xb2787838, 0x2ade45de, 0x12f453bc, 0x8a526e5a, 0x99beb543, 0x011888a5, 0x39329ec7, 0xa194a321, 0xd8690bfd, 0x40cf361b, 0x78e52079, 0xe0431d9f, 0xb87a3118, 0x20dc0cfe, 0x18f61a9c, 0x8050277a, 0xf9ad8fa6, 0x610bb240, 0x5921a422, 0xc18799c4, 0xd26b42dd, 0x4acd7f3b, 0x72e76959, 0xea4154bf, 0x93bcfc63, 0x0b1ac185, 0x3330d7e7, 0xab96ea01, 0x161507b6, 0x8eb33a50, 0xb6992c32, 0x2e3f11d4, 0x57c2b908, 0xcf6484ee, 0xf74e928c, 0x6fe8af6a, 0x7c047473, 0xe4a24995, 0xdc885ff7, 0x442e6211, 0x3dd3cacd, 0xa575f72b, 0x9d5fe149, 0x05f9dcaf, 0xe5bac130, 0x7d1cfcd6, 0x4536eab4, 0xdd90d752, 0xa46d7f8e, 0x3ccb4268, 0x04e1540a, 0x9c4769ec, 0x8fabb2f5, 0x170d8f13, 0x2f279971, 0xb781a497, 0xce7c0c4b, 0x56da31ad, 0x6ef027cf, 0xf6561a29, 0x4bd5f79e, 0xd373ca78, 0xeb59dc1a, 0x73ffe1fc, 0x0a024920, 0x92a474c6, 0xaa8e62a4, 0x32285f42, 0x21c4845b, 0xb962b9bd, 0x8148afdf, 0x19ee9239, 0x60133ae5, 0xf8b50703, 0xc09f1161, 0x58392c87, 0x4c172cbc, 0xd4b1115a, 0xec9b0738, 0x743d3ade, 0x0dc09202, 0x9566afe4, 0xad4cb986, 0x35ea8460, 0x26065f79, 0xbea0629f, 0x868a74fd, 0x1e2c491b, 0x67d1e1c7, 0xff77dc21, 0xc75dca43, 0x5ffbf7a5, 0xe2781a12, 0x7ade27f4, 0x42f43196, 0xda520c70, 0xa3afa4ac, 0x3b09994a, 0x03238f28, 0x9b85b2ce, 0x886969d7, 0x10cf5431, 0x28e54253, 0xb0437fb5, 0xc9bed769, 0x5118ea8f, 0x6932fced, 0xf194c10b, 0x11d7dc94, 0x8971e172, 0xb15bf710, 0x29fdcaf6, 0x5000622a, 0xc8a65fcc, 0xf08c49ae, 0x682a7448, 0x7bc6af51, 0xe36092b7, 0xdb4a84d5, 0x43ecb933, 0x3a1111ef, 0xa2b72c09, 0x9a9d3a6b, 0x023b078d, 0xbfb8ea3a, 0x271ed7dc, 0x1f34c1be, 0x8792fc58, 0xfe6f5484, 0x66c96962, 0x5ee37f00, 0xc64542e6, 0xd5a999ff, 0x4d0fa419, 0x7525b27b, 0xed838f9d, 0x947e2741, 0x0cd81aa7, 0x34f20cc5, 0xac543123, 0xf46d1da4, 0x6ccb2042, 0x54e13620, 0xcc470bc6, 0xb5baa31a, 0x2d1c9efc, 0x1536889e, 0x8d90b578, 0x9e7c6e61, 0x06da5387, 0x3ef045e5, 0xa6567803, 0xdfabd0df, 0x470ded39, 0x7f27fb5b, 0xe781c6bd, 0x5a022b0a, 0xc2a416ec, 0xfa8e008e, 0x62283d68, 0x1bd595b4, 0x8373a852, 0xbb59be30, 0x23ff83d6, 0x301358cf, 0xa8b56529, 0x909f734b, 0x08394ead, 0x71c4e671, 0xe962db97, 0xd148cdf5, 0x49eef013, 0xa9aded8c, 0x310bd06a, 0x0921c608, 0x9187fbee, 0xe87a5332, 0x70dc6ed4, 0x48f678b6, 0xd0504550, 0xc3bc9e49, 0x5b1aa3af, 0x6330b5cd, 0xfb96882b, 0x826b20f7, 0x1acd1d11, 0x22e70b73, 0xba413695, 0x07c2db22, 0x9f64e6c4, 0xa74ef0a6, 0x3fe8cd40, 0x4615659c, 0xdeb3587a, 0xe6994e18, 0x7e3f73fe, 0x6dd3a8e7, 0xf5759501, 0xcd5f8363, 0x55f9be85, 0x2c041659, 0xb4a22bbf, 0x8c883ddd, 0x142e003b +}, +{ +0x00000000, 0x6dc67348, 0xef557b68, 0x82930820, 0x552b4dbc, 0x38ed3ef4, 0xba7e36d4, 0xd7b8459c, 0xe04f6cf3, 0x8d891fbb, 0x0f1a179b, 0x62dc64d3, 0xb564214f, 0xd8a25207, 0x5a315a27, 0x37f7296f, 0xda022ee9, 0xb7c45da1, 0x35575581, 0x589126c9, 0x8f296355, 0xe2ef101d, 0x607c183d, 0x0dba6b75, 0x3a4d421a, 0x578b3152, 0xd5183972, 0xb8de4a3a, 0x6f660fa6, 0x02a07cee, 0x803374ce, 0xedf50786, 0x30f2bda8, 0x5d34cee0, 0xdfa7c6c0, 0xb261b588, 0x65d9f014, 0x081f835c, 0x8a8c8b7c, 0xe74af834, 0xd0bdd15b, 0xbd7ba213, 0x3fe8aa33, 0x522ed97b, 0x85969ce7, 0xe850efaf, 0x6ac3e78f, 0x070594c7, 0xeaf09341, 0x8736e009, 0x05a5e829, 0x68639b61, 0xbfdbdefd, 0xd21dadb5, 0x508ea595, 0x3d48d6dd, 0x0abfffb2, 0x67798cfa, 0xe5ea84da, 0x882cf792, 0x5f94b20e, 0x3252c146, 0xb0c1c966, 0xdd07ba2e, 0x13b95514, 0x7e7f265c, 0xfcec2e7c, 0x912a5d34, 0x469218a8, 0x2b546be0, 0xa9c763c0, 0xc4011088, 0xf3f639e7, 0x9e304aaf, 0x1ca3428f, 0x716531c7, 0xa6dd745b, 0xcb1b0713, 0x49880f33, 0x244e7c7b, 0xc9bb7bfd, 0xa47d08b5, 0x26ee0095, 0x4b2873dd, 0x9c903641, 0xf1564509, 0x73c54d29, 0x1e033e61, 0x29f4170e, 0x44326446, 0xc6a16c66, 0xab671f2e, 0x7cdf5ab2, 0x111929fa, 0x938a21da, 0xfe4c5292, 0x234be8bc, 0x4e8d9bf4, 0xcc1e93d4, 0xa1d8e09c, 0x7660a500, 0x1ba6d648, 0x9935de68, 0xf4f3ad20, 0xc304844f, 0xaec2f707, 0x2c51ff27, 0x41978c6f, 0x962fc9f3, 0xfbe9babb, 0x797ab29b, 0x14bcc1d3, 0xf949c655, 0x948fb51d, 0x161cbd3d, 0x7bdace75, 0xac628be9, 0xc1a4f8a1, 0x4337f081, 0x2ef183c9, 0x1906aaa6, 0x74c0d9ee, 0xf653d1ce, 0x9b95a286, 0x4c2de71a, 0x21eb9452, 0xa3789c72, 0xcebeef3a, 0x17104988, 0x7ad63ac0, 0xf84532e0, 0x958341a8, 0x423b0434, 0x2ffd777c, 0xad6e7f5c, 0xc0a80c14, 0xf75f257b, 0x9a995633, 0x180a5e13, 0x75cc2d5b, 0xa27468c7, 0xcfb21b8f, 0x4d2113af, 0x20e760e7, 0xcd126761, 0xa0d41429, 0x22471c09, 0x4f816f41, 0x98392add, 0xf5ff5995, 0x776c51b5, 0x1aaa22fd, 0x2d5d0b92, 0x409b78da, 0xc20870fa, 0xafce03b2, 0x7876462e, 0x15b03566, 0x97233d46, 0xfae54e0e, 0x27e2f420, 0x4a248768, 0xc8b78f48, 0xa571fc00, 0x72c9b99c, 0x1f0fcad4, 0x9d9cc2f4, 0xf05ab1bc, 0xc7ad98d3, 0xaa6beb9b, 0x28f8e3bb, 0x453e90f3, 0x9286d56f, 0xff40a627, 0x7dd3ae07, 0x1015dd4f, 0xfde0dac9, 0x9026a981, 0x12b5a1a1, 0x7f73d2e9, 0xa8cb9775, 0xc50de43d, 0x479eec1d, 0x2a589f55, 0x1dafb63a, 0x7069c572, 0xf2facd52, 0x9f3cbe1a, 0x4884fb86, 0x254288ce, 0xa7d180ee, 0xca17f3a6, 0x04a91c9c, 0x696f6fd4, 0xebfc67f4, 0x863a14bc, 0x51825120, 0x3c442268, 0xbed72a48, 0xd3115900, 0xe4e6706f, 0x89200327, 0x0bb30b07, 0x6675784f, 0xb1cd3dd3, 0xdc0b4e9b, 0x5e9846bb, 0x335e35f3, 0xdeab3275, 0xb36d413d, 0x31fe491d, 0x5c383a55, 0x8b807fc9, 0xe6460c81, 0x64d504a1, 0x091377e9, 0x3ee45e86, 0x53222dce, 0xd1b125ee, 0xbc7756a6, 0x6bcf133a, 0x06096072, 0x849a6852, 0xe95c1b1a, 0x345ba134, 0x599dd27c, 0xdb0eda5c, 0xb6c8a914, 0x6170ec88, 0x0cb69fc0, 0x8e2597e0, 0xe3e3e4a8, 0xd414cdc7, 0xb9d2be8f, 0x3b41b6af, 0x5687c5e7, 0x813f807b, 0xecf9f333, 0x6e6afb13, 0x03ac885b, 0xee598fdd, 0x839ffc95, 0x010cf4b5, 0x6cca87fd, 0xbb72c261, 0xd6b4b129, 0x5427b909, 0x39e1ca41, 0x0e16e32e, 0x63d09066, 0xe1439846, 0x8c85eb0e, 0x5b3dae92, 0x36fbddda, 0xb468d5fa, 0xd9aea6b2 +} +}, +{ +{ +0x00000000, 0x4cca8095, 0xdc043abf, 0x90ceba2a, 0x6f46b9dc, 0x238c3949, 0xb3428363, 0xff8803f6, 0x19c94260, 0x5503c2f5, 0xc5cd78df, 0x8907f84a, 0x768ffbbc, 0x3a457b29, 0xaa8bc103, 0xe6414196, 0xc9501c85, 0x859a9c10, 0x1554263a, 0x599ea6af, 0xa616a559, 0xeadc25cc, 0x7a129fe6, 0x36d81f73, 0xd0995ee5, 0x9c53de70, 0x0c9d645a, 0x4057e4cf, 0xbfdfe739, 0xf31567ac, 0x63dbdd86, 0x2f115d13, 0xfb33894d, 0xb7f909d8, 0x2737b3f2, 0x6bfd3367, 0x94753091, 0xd8bfb004, 0x48710a2e, 0x04bb8abb, 0xe2facb2d, 0xae304bb8, 0x3efef192, 0x72347107, 0x8dbc72f1, 0xc176f264, 0x51b8484e, 0x1d72c8db, 0x326395c8, 0x7ea9155d, 0xee67af77, 0xa2ad2fe2, 0x5d252c14, 0x11efac81, 0x812116ab, 0xcdeb963e, 0x2baad7a8, 0x6760573d, 0xf7aeed17, 0xbb646d82, 0x44ec6e74, 0x0826eee1, 0x98e854cb, 0xd422d45e, 0x69fc08fd, 0x25368868, 0xb5f83242, 0xf932b2d7, 0x06bab121, 0x4a7031b4, 0xdabe8b9e, 0x96740b0b, 0x70354a9d, 0x3cffca08, 0xac317022, 0xe0fbf0b7, 0x1f73f341, 0x53b973d4, 0xc377c9fe, 0x8fbd496b, 0xa0ac1478, 0xec6694ed, 0x7ca82ec7, 0x3062ae52, 0xcfeaada4, 0x83202d31, 0x13ee971b, 0x5f24178e, 0xb9655618, 0xf5afd68d, 0x65616ca7, 0x29abec32, 0xd623efc4, 0x9ae96f51, 0x0a27d57b, 0x46ed55ee, 0x92cf81b0, 0xde050125, 0x4ecbbb0f, 0x02013b9a, 0xfd89386c, 0xb143b8f9, 0x218d02d3, 0x6d478246, 0x8b06c3d0, 0xc7cc4345, 0x5702f96f, 0x1bc879fa, 0xe4407a0c, 0xa88afa99, 0x384440b3, 0x748ec026, 0x5b9f9d35, 0x17551da0, 0x879ba78a, 0xcb51271f, 0x34d924e9, 0x7813a47c, 0xe8dd1e56, 0xa4179ec3, 0x4256df55, 0x0e9c5fc0, 0x9e52e5ea, 0xd298657f, 0x2d106689, 0x61dae61c, 0xf1145c36, 0xbddedca3, 0x4192864d, 0x0d5806d8, 0x9d96bcf2, 0xd15c3c67, 0x2ed43f91, 0x621ebf04, 0xf2d0052e, 0xbe1a85bb, 0x585bc42d, 0x149144b8, 0x845ffe92, 0xc8957e07, 0x371d7df1, 0x7bd7fd64, 0xeb19474e, 0xa7d3c7db, 0x88c29ac8, 0xc4081a5d, 0x54c6a077, 0x180c20e2, 0xe7842314, 0xab4ea381, 0x3b8019ab, 0x774a993e, 0x910bd8a8, 0xddc1583d, 0x4d0fe217, 0x01c56282, 0xfe4d6174, 0xb287e1e1, 0x22495bcb, 0x6e83db5e, 0xbaa10f00, 0xf66b8f95, 0x66a535bf, 0x2a6fb52a, 0xd5e7b6dc, 0x992d3649, 0x09e38c63, 0x45290cf6, 0xa3684d60, 0xefa2cdf5, 0x7f6c77df, 0x33a6f74a, 0xcc2ef4bc, 0x80e47429, 0x102ace03, 0x5ce04e96, 0x73f11385, 0x3f3b9310, 0xaff5293a, 0xe33fa9af, 0x1cb7aa59, 0x507d2acc, 0xc0b390e6, 0x8c791073, 0x6a3851e5, 0x26f2d170, 0xb63c6b5a, 0xfaf6ebcf, 0x057ee839, 0x49b468ac, 0xd97ad286, 0x95b05213, 0x286e8eb0, 0x64a40e25, 0xf46ab40f, 0xb8a0349a, 0x4728376c, 0x0be2b7f9, 0x9b2c0dd3, 0xd7e68d46, 0x31a7ccd0, 0x7d6d4c45, 0xeda3f66f, 0xa16976fa, 0x5ee1750c, 0x122bf599, 0x82e54fb3, 0xce2fcf26, 0xe13e9235, 0xadf412a0, 0x3d3aa88a, 0x71f0281f, 0x8e782be9, 0xc2b2ab7c, 0x527c1156, 0x1eb691c3, 0xf8f7d055, 0xb43d50c0, 0x24f3eaea, 0x68396a7f, 0x97b16989, 0xdb7be91c, 0x4bb55336, 0x077fd3a3, 0xd35d07fd, 0x9f978768, 0x0f593d42, 0x4393bdd7, 0xbc1bbe21, 0xf0d13eb4, 0x601f849e, 0x2cd5040b, 0xca94459d, 0x865ec508, 0x16907f22, 0x5a5affb7, 0xa5d2fc41, 0xe9187cd4, 0x79d6c6fe, 0x351c466b, 0x1a0d1b78, 0x56c79bed, 0xc60921c7, 0x8ac3a152, 0x754ba2a4, 0x39812231, 0xa94f981b, 0xe585188e, 0x03c45918, 0x4f0ed98d, 0xdfc063a7, 0x930ae332, 0x6c82e0c4, 0x20486051, 0xb086da7b, 0xfc4c5aee +}, +{ +0x00000000, 0x0507f252, 0x989972a7, 0x9d9e80f5, 0x54f37e44, 0x51f48c16, 0xcc6a0ce3, 0xc96dfeb1, 0x78d58cfd, 0x7dd27eaf, 0xe04cfe5a, 0xe54b0c08, 0x2c26f2b9, 0x292100eb, 0xb4bf801e, 0xb1b8724c, 0xa8ce3d53, 0xadc9cf01, 0x30574ff4, 0x3550bda6, 0xfc3d4317, 0xf93ab145, 0x64a431b0, 0x61a3c3e2, 0xd01bb1ae, 0xd51c43fc, 0x4882c309, 0x4d85315b, 0x84e8cfea, 0x81ef3db8, 0x1c71bd4d, 0x19764f1f, 0xb8186809, 0xbd1f9a5b, 0x20811aae, 0x2586e8fc, 0xeceb164d, 0xe9ece41f, 0x747264ea, 0x717596b8, 0xc0cde4f4, 0xc5ca16a6, 0x58549653, 0x5d536401, 0x943e9ab0, 0x913968e2, 0x0ca7e817, 0x09a01a45, 0x10d6555a, 0x15d1a708, 0x884f27fd, 0x8d48d5af, 0x44252b1e, 0x4122d94c, 0xdcbc59b9, 0xd9bbabeb, 0x6803d9a7, 0x6d042bf5, 0xf09aab00, 0xf59d5952, 0x3cf0a7e3, 0x39f755b1, 0xa469d544, 0xa16e2716, 0x79a943c4, 0x7caeb196, 0xe1303163, 0xe437c331, 0x2d5a3d80, 0x285dcfd2, 0xb5c34f27, 0xb0c4bd75, 0x017ccf39, 0x047b3d6b, 0x99e5bd9e, 0x9ce24fcc, 0x558fb17d, 0x5088432f, 0xcd16c3da, 0xc8113188, 0xd1677e97, 0xd4608cc5, 0x49fe0c30, 0x4cf9fe62, 0x859400d3, 0x8093f281, 0x1d0d7274, 0x180a8026, 0xa9b2f26a, 0xacb50038, 0x312b80cd, 0x342c729f, 0xfd418c2e, 0xf8467e7c, 0x65d8fe89, 0x60df0cdb, 0xc1b12bcd, 0xc4b6d99f, 0x5928596a, 0x5c2fab38, 0x95425589, 0x9045a7db, 0x0ddb272e, 0x08dcd57c, 0xb964a730, 0xbc635562, 0x21fdd597, 0x24fa27c5, 0xed97d974, 0xe8902b26, 0x750eabd3, 0x70095981, 0x697f169e, 0x6c78e4cc, 0xf1e66439, 0xf4e1966b, 0x3d8c68da, 0x388b9a88, 0xa5151a7d, 0xa012e82f, 0x11aa9a63, 0x14ad6831, 0x8933e8c4, 0x8c341a96, 0x4559e427, 0x405e1675, 0xddc09680, 0xd8c764d2, 0x5f4c0bee, 0x5a4bf9bc, 0xc7d57949, 0xc2d28b1b, 0x0bbf75aa, 0x0eb887f8, 0x9326070d, 0x9621f55f, 0x27998713, 0x229e7541, 0xbf00f5b4, 0xba0707e6, 0x736af957, 0x766d0b05, 0xebf38bf0, 0xeef479a2, 0xf78236bd, 0xf285c4ef, 0x6f1b441a, 0x6a1cb648, 0xa37148f9, 0xa676baab, 0x3be83a5e, 0x3eefc80c, 0x8f57ba40, 0x8a504812, 0x17cec8e7, 0x12c93ab5, 0xdba4c404, 0xdea33656, 0x433db6a3, 0x463a44f1, 0xe75463e7, 0xe25391b5, 0x7fcd1140, 0x7acae312, 0xb3a71da3, 0xb6a0eff1, 0x2b3e6f04, 0x2e399d56, 0x9f81ef1a, 0x9a861d48, 0x07189dbd, 0x021f6fef, 0xcb72915e, 0xce75630c, 0x53ebe3f9, 0x56ec11ab, 0x4f9a5eb4, 0x4a9dace6, 0xd7032c13, 0xd204de41, 0x1b6920f0, 0x1e6ed2a2, 0x83f05257, 0x86f7a005, 0x374fd249, 0x3248201b, 0xafd6a0ee, 0xaad152bc, 0x63bcac0d, 0x66bb5e5f, 0xfb25deaa, 0xfe222cf8, 0x26e5482a, 0x23e2ba78, 0xbe7c3a8d, 0xbb7bc8df, 0x7216366e, 0x7711c43c, 0xea8f44c9, 0xef88b69b, 0x5e30c4d7, 0x5b373685, 0xc6a9b670, 0xc3ae4422, 0x0ac3ba93, 0x0fc448c1, 0x925ac834, 0x975d3a66, 0x8e2b7579, 0x8b2c872b, 0x16b207de, 0x13b5f58c, 0xdad80b3d, 0xdfdff96f, 0x4241799a, 0x47468bc8, 0xf6fef984, 0xf3f90bd6, 0x6e678b23, 0x6b607971, 0xa20d87c0, 0xa70a7592, 0x3a94f567, 0x3f930735, 0x9efd2023, 0x9bfad271, 0x06645284, 0x0363a0d6, 0xca0e5e67, 0xcf09ac35, 0x52972cc0, 0x5790de92, 0xe628acde, 0xe32f5e8c, 0x7eb1de79, 0x7bb62c2b, 0xb2dbd29a, 0xb7dc20c8, 0x2a42a03d, 0x2f45526f, 0x36331d70, 0x3334ef22, 0xaeaa6fd7, 0xabad9d85, 0x62c06334, 0x67c79166, 0xfa591193, 0xff5ee3c1, 0x4ee6918d, 0x4be163df, 0xd67fe32a, 0xd3781178, 0x1a15efc9, 0x1f121d9b, 0x828c9d6e, 0x878b6f3c +}, +{ +0x00000000, 0x549e312f, 0x4c1f30dc, 0x188101f3, 0xf062fee2, 0xa4fccfcd, 0xbc7dce3e, 0xe8e3ff11, 0xcdc4dc54, 0x995aed7b, 0x81dbec88, 0xd545dda7, 0x3da622b6, 0x69381399, 0x71b9126a, 0x25272345, 0x2f3fdfb8, 0x7ba1ee97, 0x6320ef64, 0x37bede4b, 0xdf5d215a, 0x8bc31075, 0x93421186, 0xc7dc20a9, 0xe2fb03ec, 0xb66532c3, 0xaee43330, 0xfa7a021f, 0x1299fd0e, 0x4607cc21, 0x5e86cdd2, 0x0a18fcfd, 0x86070ff3, 0xd2993edc, 0xca183f2f, 0x9e860e00, 0x7665f111, 0x22fbc03e, 0x3a7ac1cd, 0x6ee4f0e2, 0x4bc3d3a7, 0x1f5de288, 0x07dce37b, 0x5342d254, 0xbba12d45, 0xef3f1c6a, 0xf7be1d99, 0xa3202cb6, 0xa938d04b, 0xfda6e164, 0xe527e097, 0xb1b9d1b8, 0x595a2ea9, 0x0dc41f86, 0x15451e75, 0x41db2f5a, 0x64fc0c1f, 0x30623d30, 0x28e33cc3, 0x7c7d0dec, 0x949ef2fd, 0xc000c3d2, 0xd881c221, 0x8c1ff30e, 0x939c0109, 0xc7023026, 0xdf8331d5, 0x8b1d00fa, 0x63feffeb, 0x3760cec4, 0x2fe1cf37, 0x7b7ffe18, 0x5e58dd5d, 0x0ac6ec72, 0x1247ed81, 0x46d9dcae, 0xae3a23bf, 0xfaa41290, 0xe2251363, 0xb6bb224c, 0xbca3deb1, 0xe83def9e, 0xf0bcee6d, 0xa422df42, 0x4cc12053, 0x185f117c, 0x00de108f, 0x544021a0, 0x716702e5, 0x25f933ca, 0x3d783239, 0x69e60316, 0x8105fc07, 0xd59bcd28, 0xcd1accdb, 0x9984fdf4, 0x159b0efa, 0x41053fd5, 0x59843e26, 0x0d1a0f09, 0xe5f9f018, 0xb167c137, 0xa9e6c0c4, 0xfd78f1eb, 0xd85fd2ae, 0x8cc1e381, 0x9440e272, 0xc0ded35d, 0x283d2c4c, 0x7ca31d63, 0x64221c90, 0x30bc2dbf, 0x3aa4d142, 0x6e3ae06d, 0x76bbe19e, 0x2225d0b1, 0xcac62fa0, 0x9e581e8f, 0x86d91f7c, 0xd2472e53, 0xf7600d16, 0xa3fe3c39, 0xbb7f3dca, 0xefe10ce5, 0x0702f3f4, 0x539cc2db, 0x4b1dc328, 0x1f83f207, 0xf5ef92ac, 0xa171a383, 0xb9f0a270, 0xed6e935f, 0x058d6c4e, 0x51135d61, 0x49925c92, 0x1d0c6dbd, 0x382b4ef8, 0x6cb57fd7, 0x74347e24, 0x20aa4f0b, 0xc849b01a, 0x9cd78135, 0x845680c6, 0xd0c8b1e9, 0xdad04d14, 0x8e4e7c3b, 0x96cf7dc8, 0xc2514ce7, 0x2ab2b3f6, 0x7e2c82d9, 0x66ad832a, 0x3233b205, 0x17149140, 0x438aa06f, 0x5b0ba19c, 0x0f9590b3, 0xe7766fa2, 0xb3e85e8d, 0xab695f7e, 0xfff76e51, 0x73e89d5f, 0x2776ac70, 0x3ff7ad83, 0x6b699cac, 0x838a63bd, 0xd7145292, 0xcf955361, 0x9b0b624e, 0xbe2c410b, 0xeab27024, 0xf23371d7, 0xa6ad40f8, 0x4e4ebfe9, 0x1ad08ec6, 0x02518f35, 0x56cfbe1a, 0x5cd742e7, 0x084973c8, 0x10c8723b, 0x44564314, 0xacb5bc05, 0xf82b8d2a, 0xe0aa8cd9, 0xb434bdf6, 0x91139eb3, 0xc58daf9c, 0xdd0cae6f, 0x89929f40, 0x61716051, 0x35ef517e, 0x2d6e508d, 0x79f061a2, 0x667393a5, 0x32eda28a, 0x2a6ca379, 0x7ef29256, 0x96116d47, 0xc28f5c68, 0xda0e5d9b, 0x8e906cb4, 0xabb74ff1, 0xff297ede, 0xe7a87f2d, 0xb3364e02, 0x5bd5b113, 0x0f4b803c, 0x17ca81cf, 0x4354b0e0, 0x494c4c1d, 0x1dd27d32, 0x05537cc1, 0x51cd4dee, 0xb92eb2ff, 0xedb083d0, 0xf5318223, 0xa1afb30c, 0x84889049, 0xd016a166, 0xc897a095, 0x9c0991ba, 0x74ea6eab, 0x20745f84, 0x38f55e77, 0x6c6b6f58, 0xe0749c56, 0xb4eaad79, 0xac6bac8a, 0xf8f59da5, 0x101662b4, 0x4488539b, 0x5c095268, 0x08976347, 0x2db04002, 0x792e712d, 0x61af70de, 0x353141f1, 0xddd2bee0, 0x894c8fcf, 0x91cd8e3c, 0xc553bf13, 0xcf4b43ee, 0x9bd572c1, 0x83547332, 0xd7ca421d, 0x3f29bd0c, 0x6bb78c23, 0x73368dd0, 0x27a8bcff, 0x028f9fba, 0x5611ae95, 0x4e90af66, 0x1a0e9e49, 0xf2ed6158, 0xa6735077, 0xbef25184, 0xea6c60ab +}, +{ +0x00000000, 0x0d86ace4, 0x9d8dc6d8, 0x900b6a3c, 0x2fba93f1, 0x223c3f15, 0xb2375529, 0xbfb1f9cd, 0x1a6f1e41, 0x17e9b2a5, 0x87e2d899, 0x8a64747d, 0x35d58db0, 0x38532154, 0xa8584b68, 0xa5dee78c, 0xaf1b9099, 0xa29d3c7d, 0x32965641, 0x3f10faa5, 0x80a10368, 0x8d27af8c, 0x1d2cc5b0, 0x10aa6954, 0xb5748ed8, 0xb8f2223c, 0x28f94800, 0x257fe4e4, 0x9ace1d29, 0x9748b1cd, 0x0743dbf1, 0x0ac57715, 0xa00b8c61, 0xad8d2085, 0x3d864ab9, 0x3000e65d, 0x8fb11f90, 0x8237b374, 0x123cd948, 0x1fba75ac, 0xba649220, 0xb7e23ec4, 0x27e954f8, 0x2a6ff81c, 0x95de01d1, 0x9858ad35, 0x0853c709, 0x05d56bed, 0x0f101cf8, 0x0296b01c, 0x929dda20, 0x9f1b76c4, 0x20aa8f09, 0x2d2c23ed, 0xbd2749d1, 0xb0a1e535, 0x157f02b9, 0x18f9ae5d, 0x88f2c461, 0x85746885, 0x3ac59148, 0x37433dac, 0xa7485790, 0xaacefb74, 0xead35d91, 0xe755f175, 0x775e9b49, 0x7ad837ad, 0xc569ce60, 0xc8ef6284, 0x58e408b8, 0x5562a45c, 0xf0bc43d0, 0xfd3aef34, 0x6d318508, 0x60b729ec, 0xdf06d021, 0xd2807cc5, 0x428b16f9, 0x4f0dba1d, 0x45c8cd08, 0x484e61ec, 0xd8450bd0, 0xd5c3a734, 0x6a725ef9, 0x67f4f21d, 0xf7ff9821, 0xfa7934c5, 0x5fa7d349, 0x52217fad, 0xc22a1591, 0xcfacb975, 0x701d40b8, 0x7d9bec5c, 0xed908660, 0xe0162a84, 0x4ad8d1f0, 0x475e7d14, 0xd7551728, 0xdad3bbcc, 0x65624201, 0x68e4eee5, 0xf8ef84d9, 0xf569283d, 0x50b7cfb1, 0x5d316355, 0xcd3a0969, 0xc0bca58d, 0x7f0d5c40, 0x728bf0a4, 0xe2809a98, 0xef06367c, 0xe5c34169, 0xe845ed8d, 0x784e87b1, 0x75c82b55, 0xca79d298, 0xc7ff7e7c, 0x57f41440, 0x5a72b8a4, 0xffac5f28, 0xf22af3cc, 0x622199f0, 0x6fa73514, 0xd016ccd9, 0xdd90603d, 0x4d9b0a01, 0x401da6e5, 0x6777387e, 0x6af1949a, 0xfafafea6, 0xf77c5242, 0x48cdab8f, 0x454b076b, 0xd5406d57, 0xd8c6c1b3, 0x7d18263f, 0x709e8adb, 0xe095e0e7, 0xed134c03, 0x52a2b5ce, 0x5f24192a, 0xcf2f7316, 0xc2a9dff2, 0xc86ca8e7, 0xc5ea0403, 0x55e16e3f, 0x5867c2db, 0xe7d63b16, 0xea5097f2, 0x7a5bfdce, 0x77dd512a, 0xd203b6a6, 0xdf851a42, 0x4f8e707e, 0x4208dc9a, 0xfdb92557, 0xf03f89b3, 0x6034e38f, 0x6db24f6b, 0xc77cb41f, 0xcafa18fb, 0x5af172c7, 0x5777de23, 0xe8c627ee, 0xe5408b0a, 0x754be136, 0x78cd4dd2, 0xdd13aa5e, 0xd09506ba, 0x409e6c86, 0x4d18c062, 0xf2a939af, 0xff2f954b, 0x6f24ff77, 0x62a25393, 0x68672486, 0x65e18862, 0xf5eae25e, 0xf86c4eba, 0x47ddb777, 0x4a5b1b93, 0xda5071af, 0xd7d6dd4b, 0x72083ac7, 0x7f8e9623, 0xef85fc1f, 0xe20350fb, 0x5db2a936, 0x503405d2, 0xc03f6fee, 0xcdb9c30a, 0x8da465ef, 0x8022c90b, 0x1029a337, 0x1daf0fd3, 0xa21ef61e, 0xaf985afa, 0x3f9330c6, 0x32159c22, 0x97cb7bae, 0x9a4dd74a, 0x0a46bd76, 0x07c01192, 0xb871e85f, 0xb5f744bb, 0x25fc2e87, 0x287a8263, 0x22bff576, 0x2f395992, 0xbf3233ae, 0xb2b49f4a, 0x0d056687, 0x0083ca63, 0x9088a05f, 0x9d0e0cbb, 0x38d0eb37, 0x355647d3, 0xa55d2def, 0xa8db810b, 0x176a78c6, 0x1aecd422, 0x8ae7be1e, 0x876112fa, 0x2dafe98e, 0x2029456a, 0xb0222f56, 0xbda483b2, 0x02157a7f, 0x0f93d69b, 0x9f98bca7, 0x921e1043, 0x37c0f7cf, 0x3a465b2b, 0xaa4d3117, 0xa7cb9df3, 0x187a643e, 0x15fcc8da, 0x85f7a2e6, 0x88710e02, 0x82b47917, 0x8f32d5f3, 0x1f39bfcf, 0x12bf132b, 0xad0eeae6, 0xa0884602, 0x30832c3e, 0x3d0580da, 0x98db6756, 0x955dcbb2, 0x0556a18e, 0x08d00d6a, 0xb761f4a7, 0xbae75843, 0x2aec327f, 0x276a9e9b +}, +{ +0x00000000, 0xf69fe500, 0xc4b2302c, 0x322dd52c, 0xa8ba857e, 0x5e25607e, 0x6c08b552, 0x9a975052, 0x707f42eb, 0x86e0a7eb, 0xb4cd72c7, 0x425297c7, 0xd8c5c795, 0x2e5a2295, 0x1c77f7b9, 0xeae812b9, 0xaf111c43, 0x598ef943, 0x6ba32c6f, 0x9d3cc96f, 0x07ab993d, 0xf1347c3d, 0xc319a911, 0x35864c11, 0xdf6e5ea8, 0x29f1bba8, 0x1bdc6e84, 0xed438b84, 0x77d4dbd6, 0x814b3ed6, 0xb366ebfa, 0x45f90efa, 0x953923cd, 0x63a6c6cd, 0x518b13e1, 0xa714f6e1, 0x3d83a6b3, 0xcb1c43b3, 0xf931969f, 0x0fae739f, 0xe5466126, 0x13d98426, 0x21f4510a, 0xd76bb40a, 0x4dfce458, 0xbb630158, 0x894ed474, 0x7fd13174, 0x3a283f8e, 0xccb7da8e, 0xfe9a0fa2, 0x0805eaa2, 0x9292baf0, 0x640d5ff0, 0x56208adc, 0xa0bf6fdc, 0x4a577d65, 0xbcc89865, 0x8ee54d49, 0x787aa849, 0xe2edf81b, 0x14721d1b, 0x265fc837, 0xd0c02d37, 0x209f5a57, 0xd600bf57, 0xe42d6a7b, 0x12b28f7b, 0x8825df29, 0x7eba3a29, 0x4c97ef05, 0xba080a05, 0x50e018bc, 0xa67ffdbc, 0x94522890, 0x62cdcd90, 0xf85a9dc2, 0x0ec578c2, 0x3ce8adee, 0xca7748ee, 0x8f8e4614, 0x7911a314, 0x4b3c7638, 0xbda39338, 0x2734c36a, 0xd1ab266a, 0xe386f346, 0x15191646, 0xfff104ff, 0x096ee1ff, 0x3b4334d3, 0xcddcd1d3, 0x574b8181, 0xa1d46481, 0x93f9b1ad, 0x656654ad, 0xb5a6799a, 0x43399c9a, 0x711449b6, 0x878bacb6, 0x1d1cfce4, 0xeb8319e4, 0xd9aeccc8, 0x2f3129c8, 0xc5d93b71, 0x3346de71, 0x016b0b5d, 0xf7f4ee5d, 0x6d63be0f, 0x9bfc5b0f, 0xa9d18e23, 0x5f4e6b23, 0x1ab765d9, 0xec2880d9, 0xde0555f5, 0x289ab0f5, 0xb20de0a7, 0x449205a7, 0x76bfd08b, 0x8020358b, 0x6ac82732, 0x9c57c232, 0xae7a171e, 0x58e5f21e, 0xc272a24c, 0x34ed474c, 0x06c09260, 0xf05f7760, 0x2fb6d599, 0xd9293099, 0xeb04e5b5, 0x1d9b00b5, 0x870c50e7, 0x7193b5e7, 0x43be60cb, 0xb52185cb, 0x5fc99772, 0xa9567272, 0x9b7ba75e, 0x6de4425e, 0xf773120c, 0x01ecf70c, 0x33c12220, 0xc55ec720, 0x80a7c9da, 0x76382cda, 0x4415f9f6, 0xb28a1cf6, 0x281d4ca4, 0xde82a9a4, 0xecaf7c88, 0x1a309988, 0xf0d88b31, 0x06476e31, 0x346abb1d, 0xc2f55e1d, 0x58620e4f, 0xaefdeb4f, 0x9cd03e63, 0x6a4fdb63, 0xba8ff654, 0x4c101354, 0x7e3dc678, 0x88a22378, 0x1235732a, 0xe4aa962a, 0xd6874306, 0x2018a606, 0xcaf0b4bf, 0x3c6f51bf, 0x0e428493, 0xf8dd6193, 0x624a31c1, 0x94d5d4c1, 0xa6f801ed, 0x5067e4ed, 0x159eea17, 0xe3010f17, 0xd12cda3b, 0x27b33f3b, 0xbd246f69, 0x4bbb8a69, 0x79965f45, 0x8f09ba45, 0x65e1a8fc, 0x937e4dfc, 0xa15398d0, 0x57cc7dd0, 0xcd5b2d82, 0x3bc4c882, 0x09e91dae, 0xff76f8ae, 0x0f298fce, 0xf9b66ace, 0xcb9bbfe2, 0x3d045ae2, 0xa7930ab0, 0x510cefb0, 0x63213a9c, 0x95bedf9c, 0x7f56cd25, 0x89c92825, 0xbbe4fd09, 0x4d7b1809, 0xd7ec485b, 0x2173ad5b, 0x135e7877, 0xe5c19d77, 0xa038938d, 0x56a7768d, 0x648aa3a1, 0x921546a1, 0x088216f3, 0xfe1df3f3, 0xcc3026df, 0x3aafc3df, 0xd047d166, 0x26d83466, 0x14f5e14a, 0xe26a044a, 0x78fd5418, 0x8e62b118, 0xbc4f6434, 0x4ad08134, 0x9a10ac03, 0x6c8f4903, 0x5ea29c2f, 0xa83d792f, 0x32aa297d, 0xc435cc7d, 0xf6181951, 0x0087fc51, 0xea6feee8, 0x1cf00be8, 0x2edddec4, 0xd8423bc4, 0x42d56b96, 0xb44a8e96, 0x86675bba, 0x70f8beba, 0x3501b040, 0xc39e5540, 0xf1b3806c, 0x072c656c, 0x9dbb353e, 0x6b24d03e, 0x59090512, 0xaf96e012, 0x457ef2ab, 0xb3e117ab, 0x81ccc287, 0x77532787, 0xedc477d5, 0x1b5b92d5, 0x297647f9, 0xdfe9a2f9 +}, +{ +0x00000000, 0xcf4d6e7c, 0xd5b6e5b7, 0x1afb8bcb, 0xd4f2a81f, 0x1bbfc663, 0x01444da8, 0xce0923d4, 0xcfd7bfd1, 0x009ad1ad, 0x1a615a66, 0xd52c341a, 0x1b2517ce, 0xd46879b2, 0xce93f279, 0x01de9c05, 0x2742595c, 0xe80f3720, 0xf2f4bceb, 0x3db9d297, 0xf3b0f143, 0x3cfd9f3f, 0x260614f4, 0xe94b7a88, 0xe895e68d, 0x27d888f1, 0x3d23033a, 0xf26e6d46, 0x3c674e92, 0xf32a20ee, 0xe9d1ab25, 0x269cc559, 0xc23cac15, 0x0d71c269, 0x178a49a2, 0xd8c727de, 0x16ce040a, 0xd9836a76, 0xc378e1bd, 0x0c358fc1, 0x0deb13c4, 0xc2a67db8, 0xd85df673, 0x1710980f, 0xd919bbdb, 0x1654d5a7, 0x0caf5e6c, 0xc3e23010, 0xe57ef549, 0x2a339b35, 0x30c810fe, 0xff857e82, 0x318c5d56, 0xfec1332a, 0xe43ab8e1, 0x2b77d69d, 0x2aa94a98, 0xe5e424e4, 0xff1faf2f, 0x3052c153, 0xfe5be287, 0x31168cfb, 0x2bed0730, 0xe4a0694c, 0x0b9b6577, 0xc4d60b0b, 0xde2d80c0, 0x1160eebc, 0xdf69cd68, 0x1024a314, 0x0adf28df, 0xc59246a3, 0xc44cdaa6, 0x0b01b4da, 0x11fa3f11, 0xdeb7516d, 0x10be72b9, 0xdff31cc5, 0xc508970e, 0x0a45f972, 0x2cd93c2b, 0xe3945257, 0xf96fd99c, 0x3622b7e0, 0xf82b9434, 0x3766fa48, 0x2d9d7183, 0xe2d01fff, 0xe30e83fa, 0x2c43ed86, 0x36b8664d, 0xf9f50831, 0x37fc2be5, 0xf8b14599, 0xe24ace52, 0x2d07a02e, 0xc9a7c962, 0x06eaa71e, 0x1c112cd5, 0xd35c42a9, 0x1d55617d, 0xd2180f01, 0xc8e384ca, 0x07aeeab6, 0x067076b3, 0xc93d18cf, 0xd3c69304, 0x1c8bfd78, 0xd282deac, 0x1dcfb0d0, 0x07343b1b, 0xc8795567, 0xeee5903e, 0x21a8fe42, 0x3b537589, 0xf41e1bf5, 0x3a173821, 0xf55a565d, 0xefa1dd96, 0x20ecb3ea, 0x21322fef, 0xee7f4193, 0xf484ca58, 0x3bc9a424, 0xf5c087f0, 0x3a8de98c, 0x20766247, 0xef3b0c3b, 0x082a60cf, 0xc7670eb3, 0xdd9c8578, 0x12d1eb04, 0xdcd8c8d0, 0x1395a6ac, 0x096e2d67, 0xc623431b, 0xc7fddf1e, 0x08b0b162, 0x124b3aa9, 0xdd0654d5, 0x130f7701, 0xdc42197d, 0xc6b992b6, 0x09f4fcca, 0x2f683993, 0xe02557ef, 0xfadedc24, 0x3593b258, 0xfb9a918c, 0x34d7fff0, 0x2e2c743b, 0xe1611a47, 0xe0bf8642, 0x2ff2e83e, 0x350963f5, 0xfa440d89, 0x344d2e5d, 0xfb004021, 0xe1fbcbea, 0x2eb6a596, 0xca16ccda, 0x055ba2a6, 0x1fa0296d, 0xd0ed4711, 0x1ee464c5, 0xd1a90ab9, 0xcb528172, 0x041fef0e, 0x05c1730b, 0xca8c1d77, 0xd07796bc, 0x1f3af8c0, 0xd133db14, 0x1e7eb568, 0x04853ea3, 0xcbc850df, 0xed549586, 0x2219fbfa, 0x38e27031, 0xf7af1e4d, 0x39a63d99, 0xf6eb53e5, 0xec10d82e, 0x235db652, 0x22832a57, 0xedce442b, 0xf735cfe0, 0x3878a19c, 0xf6718248, 0x393cec34, 0x23c767ff, 0xec8a0983, 0x03b105b8, 0xccfc6bc4, 0xd607e00f, 0x194a8e73, 0xd743ada7, 0x180ec3db, 0x02f54810, 0xcdb8266c, 0xcc66ba69, 0x032bd415, 0x19d05fde, 0xd69d31a2, 0x18941276, 0xd7d97c0a, 0xcd22f7c1, 0x026f99bd, 0x24f35ce4, 0xebbe3298, 0xf145b953, 0x3e08d72f, 0xf001f4fb, 0x3f4c9a87, 0x25b7114c, 0xeafa7f30, 0xeb24e335, 0x24698d49, 0x3e920682, 0xf1df68fe, 0x3fd64b2a, 0xf09b2556, 0xea60ae9d, 0x252dc0e1, 0xc18da9ad, 0x0ec0c7d1, 0x143b4c1a, 0xdb762266, 0x157f01b2, 0xda326fce, 0xc0c9e405, 0x0f848a79, 0x0e5a167c, 0xc1177800, 0xdbecf3cb, 0x14a19db7, 0xdaa8be63, 0x15e5d01f, 0x0f1e5bd4, 0xc05335a8, 0xe6cff0f1, 0x29829e8d, 0x33791546, 0xfc347b3a, 0x323d58ee, 0xfd703692, 0xe78bbd59, 0x28c6d325, 0x29184f20, 0xe655215c, 0xfcaeaa97, 0x33e3c4eb, 0xfdeae73f, 0x32a78943, 0x285c0288, 0xe7116cf4 +}, +{ +0x00000000, 0x142464cc, 0x03181d3a, 0x173c79f6, 0x3a0f3193, 0x2e2b555f, 0x39172ca9, 0x2d334865, 0x251eface, 0x313a9e02, 0x2606e7f4, 0x32228338, 0x1f11cb5d, 0x0b35af91, 0x1c09d667, 0x082db2ab, 0xd54c645b, 0xc1680097, 0xd6547961, 0xc2701dad, 0xef4355c8, 0xfb673104, 0xec5b48f2, 0xf87f2c3e, 0xf0529e95, 0xe476fa59, 0xf34a83af, 0xe76ee763, 0xca5daf06, 0xde79cbca, 0xc945b23c, 0xdd61d6f0, 0xf37f7876, 0xe75b1cba, 0xf067654c, 0xe4430180, 0xc97049e5, 0xdd542d29, 0xca6854df, 0xde4c3013, 0xd66182b8, 0xc245e674, 0xd5799f82, 0xc15dfb4e, 0xec6eb32b, 0xf84ad7e7, 0xef76ae11, 0xfb52cadd, 0x26331c2d, 0x321778e1, 0x252b0117, 0x310f65db, 0x1c3c2dbe, 0x08184972, 0x1f243084, 0x0b005448, 0x032de6e3, 0x1709822f, 0x0035fbd9, 0x14119f15, 0x3922d770, 0x2d06b3bc, 0x3a3aca4a, 0x2e1eae86, 0xda4cc4cc, 0xce68a000, 0xd954d9f6, 0xcd70bd3a, 0xe043f55f, 0xf4679193, 0xe35be865, 0xf77f8ca9, 0xff523e02, 0xeb765ace, 0xfc4a2338, 0xe86e47f4, 0xc55d0f91, 0xd1796b5d, 0xc64512ab, 0xd2617667, 0x0f00a097, 0x1b24c45b, 0x0c18bdad, 0x183cd961, 0x350f9104, 0x212bf5c8, 0x36178c3e, 0x2233e8f2, 0x2a1e5a59, 0x3e3a3e95, 0x29064763, 0x3d2223af, 0x10116bca, 0x04350f06, 0x130976f0, 0x072d123c, 0x2933bcba, 0x3d17d876, 0x2a2ba180, 0x3e0fc54c, 0x133c8d29, 0x0718e9e5, 0x10249013, 0x0400f4df, 0x0c2d4674, 0x180922b8, 0x0f355b4e, 0x1b113f82, 0x362277e7, 0x2206132b, 0x353a6add, 0x211e0e11, 0xfc7fd8e1, 0xe85bbc2d, 0xff67c5db, 0xeb43a117, 0xc670e972, 0xd2548dbe, 0xc568f448, 0xd14c9084, 0xd961222f, 0xcd4546e3, 0xda793f15, 0xce5d5bd9, 0xe36e13bc, 0xf74a7770, 0xe0760e86, 0xf4526a4a, 0xd043a3a8, 0xc467c764, 0xd35bbe92, 0xc77fda5e, 0xea4c923b, 0xfe68f6f7, 0xe9548f01, 0xfd70ebcd, 0xf55d5966, 0xe1793daa, 0xf645445c, 0xe2612090, 0xcf5268f5, 0xdb760c39, 0xcc4a75cf, 0xd86e1103, 0x050fc7f3, 0x112ba33f, 0x0617dac9, 0x1233be05, 0x3f00f660, 0x2b2492ac, 0x3c18eb5a, 0x283c8f96, 0x20113d3d, 0x343559f1, 0x23092007, 0x372d44cb, 0x1a1e0cae, 0x0e3a6862, 0x19061194, 0x0d227558, 0x233cdbde, 0x3718bf12, 0x2024c6e4, 0x3400a228, 0x1933ea4d, 0x0d178e81, 0x1a2bf777, 0x0e0f93bb, 0x06222110, 0x120645dc, 0x053a3c2a, 0x111e58e6, 0x3c2d1083, 0x2809744f, 0x3f350db9, 0x2b116975, 0xf670bf85, 0xe254db49, 0xf568a2bf, 0xe14cc673, 0xcc7f8e16, 0xd85beada, 0xcf67932c, 0xdb43f7e0, 0xd36e454b, 0xc74a2187, 0xd0765871, 0xc4523cbd, 0xe96174d8, 0xfd451014, 0xea7969e2, 0xfe5d0d2e, 0x0a0f6764, 0x1e2b03a8, 0x09177a5e, 0x1d331e92, 0x300056f7, 0x2424323b, 0x33184bcd, 0x273c2f01, 0x2f119daa, 0x3b35f966, 0x2c098090, 0x382de45c, 0x151eac39, 0x013ac8f5, 0x1606b103, 0x0222d5cf, 0xdf43033f, 0xcb6767f3, 0xdc5b1e05, 0xc87f7ac9, 0xe54c32ac, 0xf1685660, 0xe6542f96, 0xf2704b5a, 0xfa5df9f1, 0xee799d3d, 0xf945e4cb, 0xed618007, 0xc052c862, 0xd476acae, 0xc34ad558, 0xd76eb194, 0xf9701f12, 0xed547bde, 0xfa680228, 0xee4c66e4, 0xc37f2e81, 0xd75b4a4d, 0xc06733bb, 0xd4435777, 0xdc6ee5dc, 0xc84a8110, 0xdf76f8e6, 0xcb529c2a, 0xe661d44f, 0xf245b083, 0xe579c975, 0xf15dadb9, 0x2c3c7b49, 0x38181f85, 0x2f246673, 0x3b0002bf, 0x16334ada, 0x02172e16, 0x152b57e0, 0x010f332c, 0x09228187, 0x1d06e54b, 0x0a3a9cbd, 0x1e1ef871, 0x332db014, 0x2709d4d8, 0x3035ad2e, 0x2411c9e2 +}, +{ +0x00000000, 0x50853cc0, 0x904d099c, 0xc0c8355c, 0xdaa106aa, 0x8a243a6a, 0x4aec0f36, 0x1a6933f6, 0xf53f7f31, 0xa5ba43f1, 0x657276ad, 0x35f74a6d, 0x2f9e799b, 0x7f1b455b, 0xbfd37007, 0xef564cc7, 0xdedb72ac, 0x8e5e4e6c, 0x4e967b30, 0x1e1347f0, 0x047a7406, 0x54ff48c6, 0x94377d9a, 0xc4b2415a, 0x2be40d9d, 0x7b61315d, 0xbba90401, 0xeb2c38c1, 0xf1450b37, 0xa1c037f7, 0x610802ab, 0x318d3e6b, 0x334cb340, 0x63c98f80, 0xa301badc, 0xf384861c, 0xe9edb5ea, 0xb968892a, 0x79a0bc76, 0x292580b6, 0xc673cc71, 0x96f6f0b1, 0x563ec5ed, 0x06bbf92d, 0x1cd2cadb, 0x4c57f61b, 0x8c9fc347, 0xdc1aff87, 0xed97c1ec, 0xbd12fd2c, 0x7ddac870, 0x2d5ff4b0, 0x3736c746, 0x67b3fb86, 0xa77bceda, 0xf7fef21a, 0x18a8bedd, 0x482d821d, 0x88e5b741, 0xd8608b81, 0xc209b877, 0x928c84b7, 0x5244b1eb, 0x02c18d2b, 0x958355be, 0xc506697e, 0x05ce5c22, 0x554b60e2, 0x4f225314, 0x1fa76fd4, 0xdf6f5a88, 0x8fea6648, 0x60bc2a8f, 0x3039164f, 0xf0f12313, 0xa0741fd3, 0xba1d2c25, 0xea9810e5, 0x2a5025b9, 0x7ad51979, 0x4b582712, 0x1bdd1bd2, 0xdb152e8e, 0x8b90124e, 0x91f921b8, 0xc17c1d78, 0x01b42824, 0x513114e4, 0xbe675823, 0xeee264e3, 0x2e2a51bf, 0x7eaf6d7f, 0x64c65e89, 0x34436249, 0xf48b5715, 0xa40e6bd5, 0xa6cfe6fe, 0xf64ada3e, 0x3682ef62, 0x6607d3a2, 0x7c6ee054, 0x2cebdc94, 0xec23e9c8, 0xbca6d508, 0x53f099cf, 0x0375a50f, 0xc3bd9053, 0x9338ac93, 0x89519f65, 0xd9d4a3a5, 0x191c96f9, 0x4999aa39, 0x78149452, 0x2891a892, 0xe8599dce, 0xb8dca10e, 0xa2b592f8, 0xf230ae38, 0x32f89b64, 0x627da7a4, 0x8d2beb63, 0xddaed7a3, 0x1d66e2ff, 0x4de3de3f, 0x578aedc9, 0x070fd109, 0xc7c7e455, 0x9742d895, 0x1f644de5, 0x4fe17125, 0x8f294479, 0xdfac78b9, 0xc5c54b4f, 0x9540778f, 0x558842d3, 0x050d7e13, 0xea5b32d4, 0xbade0e14, 0x7a163b48, 0x2a930788, 0x30fa347e, 0x607f08be, 0xa0b73de2, 0xf0320122, 0xc1bf3f49, 0x913a0389, 0x51f236d5, 0x01770a15, 0x1b1e39e3, 0x4b9b0523, 0x8b53307f, 0xdbd60cbf, 0x34804078, 0x64057cb8, 0xa4cd49e4, 0xf4487524, 0xee2146d2, 0xbea47a12, 0x7e6c4f4e, 0x2ee9738e, 0x2c28fea5, 0x7cadc265, 0xbc65f739, 0xece0cbf9, 0xf689f80f, 0xa60cc4cf, 0x66c4f193, 0x3641cd53, 0xd9178194, 0x8992bd54, 0x495a8808, 0x19dfb4c8, 0x03b6873e, 0x5333bbfe, 0x93fb8ea2, 0xc37eb262, 0xf2f38c09, 0xa276b0c9, 0x62be8595, 0x323bb955, 0x28528aa3, 0x78d7b663, 0xb81f833f, 0xe89abfff, 0x07ccf338, 0x5749cff8, 0x9781faa4, 0xc704c664, 0xdd6df592, 0x8de8c952, 0x4d20fc0e, 0x1da5c0ce, 0x8ae7185b, 0xda62249b, 0x1aaa11c7, 0x4a2f2d07, 0x50461ef1, 0x00c32231, 0xc00b176d, 0x908e2bad, 0x7fd8676a, 0x2f5d5baa, 0xef956ef6, 0xbf105236, 0xa57961c0, 0xf5fc5d00, 0x3534685c, 0x65b1549c, 0x543c6af7, 0x04b95637, 0xc471636b, 0x94f45fab, 0x8e9d6c5d, 0xde18509d, 0x1ed065c1, 0x4e555901, 0xa10315c6, 0xf1862906, 0x314e1c5a, 0x61cb209a, 0x7ba2136c, 0x2b272fac, 0xebef1af0, 0xbb6a2630, 0xb9abab1b, 0xe92e97db, 0x29e6a287, 0x79639e47, 0x630aadb1, 0x338f9171, 0xf347a42d, 0xa3c298ed, 0x4c94d42a, 0x1c11e8ea, 0xdcd9ddb6, 0x8c5ce176, 0x9635d280, 0xc6b0ee40, 0x0678db1c, 0x56fde7dc, 0x6770d9b7, 0x37f5e577, 0xf73dd02b, 0xa7b8eceb, 0xbdd1df1d, 0xed54e3dd, 0x2d9cd681, 0x7d19ea41, 0x924fa686, 0xc2ca9a46, 0x0202af1a, 0x528793da, 0x48eea02c, 0x186b9cec, 0xd8a3a9b0, 0x88269570 +}, +{ +0x00000000, 0x7de3c6b9, 0xea43e1c0, 0x97a02779, 0xba655492, 0xc786922b, 0x5026b552, 0x2dc573eb, 0x88a20f28, 0xf541c991, 0x62e1eee8, 0x1f022851, 0x32c75bba, 0x4f249d03, 0xd884ba7a, 0xa5677cc3, 0x2bf62858, 0x5615eee1, 0xc1b5c998, 0xbc560f21, 0x91937cca, 0xec70ba73, 0x7bd09d0a, 0x06335bb3, 0xa3542770, 0xdeb7e1c9, 0x4917c6b0, 0x34f40009, 0x193173e2, 0x64d2b55b, 0xf3729222, 0x8e91549b, 0x83530d73, 0xfeb0cbca, 0x6910ecb3, 0x14f32a0a, 0x393659e1, 0x44d59f58, 0xd375b821, 0xae967e98, 0x0bf1025b, 0x7612c4e2, 0xe1b2e39b, 0x9c512522, 0xb19456c9, 0xcc779070, 0x5bd7b709, 0x263471b0, 0xa8a5252b, 0xd546e392, 0x42e6c4eb, 0x3f050252, 0x12c071b9, 0x6f23b700, 0xf8839079, 0x856056c0, 0x20072a03, 0x5de4ecba, 0xca44cbc3, 0xb7a70d7a, 0x9a627e91, 0xe781b828, 0x70219f51, 0x0dc259e8, 0xf8cead62, 0x852d6bdb, 0x128d4ca2, 0x6f6e8a1b, 0x42abf9f0, 0x3f483f49, 0xa8e81830, 0xd50bde89, 0x706ca24a, 0x0d8f64f3, 0x9a2f438a, 0xe7cc8533, 0xca09f6d8, 0xb7ea3061, 0x204a1718, 0x5da9d1a1, 0xd338853a, 0xaedb4383, 0x397b64fa, 0x4498a243, 0x695dd1a8, 0x14be1711, 0x831e3068, 0xfefdf6d1, 0x5b9a8a12, 0x26794cab, 0xb1d96bd2, 0xcc3aad6b, 0xe1ffde80, 0x9c1c1839, 0x0bbc3f40, 0x765ff9f9, 0x7b9da011, 0x067e66a8, 0x91de41d1, 0xec3d8768, 0xc1f8f483, 0xbc1b323a, 0x2bbb1543, 0x5658d3fa, 0xf33faf39, 0x8edc6980, 0x197c4ef9, 0x649f8840, 0x495afbab, 0x34b93d12, 0xa3191a6b, 0xdefadcd2, 0x506b8849, 0x2d884ef0, 0xba286989, 0xc7cbaf30, 0xea0edcdb, 0x97ed1a62, 0x004d3d1b, 0x7daefba2, 0xd8c98761, 0xa52a41d8, 0x328a66a1, 0x4f69a018, 0x62acd3f3, 0x1f4f154a, 0x88ef3233, 0xf50cf48a, 0x53deb987, 0x2e3d7f3e, 0xb99d5847, 0xc47e9efe, 0xe9bbed15, 0x94582bac, 0x03f80cd5, 0x7e1bca6c, 0xdb7cb6af, 0xa69f7016, 0x313f576f, 0x4cdc91d6, 0x6119e23d, 0x1cfa2484, 0x8b5a03fd, 0xf6b9c544, 0x782891df, 0x05cb5766, 0x926b701f, 0xef88b6a6, 0xc24dc54d, 0xbfae03f4, 0x280e248d, 0x55ede234, 0xf08a9ef7, 0x8d69584e, 0x1ac97f37, 0x672ab98e, 0x4aefca65, 0x370c0cdc, 0xa0ac2ba5, 0xdd4fed1c, 0xd08db4f4, 0xad6e724d, 0x3ace5534, 0x472d938d, 0x6ae8e066, 0x170b26df, 0x80ab01a6, 0xfd48c71f, 0x582fbbdc, 0x25cc7d65, 0xb26c5a1c, 0xcf8f9ca5, 0xe24aef4e, 0x9fa929f7, 0x08090e8e, 0x75eac837, 0xfb7b9cac, 0x86985a15, 0x11387d6c, 0x6cdbbbd5, 0x411ec83e, 0x3cfd0e87, 0xab5d29fe, 0xd6beef47, 0x73d99384, 0x0e3a553d, 0x999a7244, 0xe479b4fd, 0xc9bcc716, 0xb45f01af, 0x23ff26d6, 0x5e1ce06f, 0xab1014e5, 0xd6f3d25c, 0x4153f525, 0x3cb0339c, 0x11754077, 0x6c9686ce, 0xfb36a1b7, 0x86d5670e, 0x23b21bcd, 0x5e51dd74, 0xc9f1fa0d, 0xb4123cb4, 0x99d74f5f, 0xe43489e6, 0x7394ae9f, 0x0e776826, 0x80e63cbd, 0xfd05fa04, 0x6aa5dd7d, 0x17461bc4, 0x3a83682f, 0x4760ae96, 0xd0c089ef, 0xad234f56, 0x08443395, 0x75a7f52c, 0xe207d255, 0x9fe414ec, 0xb2216707, 0xcfc2a1be, 0x586286c7, 0x2581407e, 0x28431996, 0x55a0df2f, 0xc200f856, 0xbfe33eef, 0x92264d04, 0xefc58bbd, 0x7865acc4, 0x05866a7d, 0xa0e116be, 0xdd02d007, 0x4aa2f77e, 0x374131c7, 0x1a84422c, 0x67678495, 0xf0c7a3ec, 0x8d246555, 0x03b531ce, 0x7e56f777, 0xe9f6d00e, 0x941516b7, 0xb9d0655c, 0xc433a3e5, 0x5393849c, 0x2e704225, 0x8b173ee6, 0xf6f4f85f, 0x6154df26, 0x1cb7199f, 0x31726a74, 0x4c91accd, 0xdb318bb4, 0xa6d24d0d +}, +{ +0x00000000, 0x205fd591, 0xa1e662c4, 0x81b9b755, 0x1429589f, 0x34768d0e, 0xb5cf3a5b, 0x9590efca, 0x868cf208, 0xa6d32799, 0x276a90cc, 0x0735455d, 0x92a5aa97, 0xb2fa7f06, 0x3343c853, 0x131c1dc2, 0x715994a4, 0x51064135, 0xd0bff660, 0xf0e023f1, 0x6570cc3b, 0x452f19aa, 0xc496aeff, 0xe4c97b6e, 0xf7d566ac, 0xd78ab33d, 0x56330468, 0x766cd1f9, 0xe3fc3e33, 0xc3a3eba2, 0x421a5cf7, 0x62458966, 0xabdfe33f, 0x8b8036ae, 0x0a3981fb, 0x2a66546a, 0xbff6bba0, 0x9fa96e31, 0x1e10d964, 0x3e4f0cf5, 0x2d531137, 0x0d0cc4a6, 0x8cb573f3, 0xaceaa662, 0x397a49a8, 0x19259c39, 0x989c2b6c, 0xb8c3fefd, 0xda86779b, 0xfad9a20a, 0x7b60155f, 0x5b3fc0ce, 0xceaf2f04, 0xeef0fa95, 0x6f494dc0, 0x4f169851, 0x5c0a8593, 0x7c555002, 0xfdece757, 0xddb332c6, 0x4823dd0c, 0x687c089d, 0xe9c5bfc8, 0xc99a6a59, 0xe8f5fa24, 0xc8aa2fb5, 0x491398e0, 0x694c4d71, 0xfcdca2bb, 0xdc83772a, 0x5d3ac07f, 0x7d6515ee, 0x6e79082c, 0x4e26ddbd, 0xcf9f6ae8, 0xefc0bf79, 0x7a5050b3, 0x5a0f8522, 0xdbb63277, 0xfbe9e7e6, 0x99ac6e80, 0xb9f3bb11, 0x384a0c44, 0x1815d9d5, 0x8d85361f, 0xaddae38e, 0x2c6354db, 0x0c3c814a, 0x1f209c88, 0x3f7f4919, 0xbec6fe4c, 0x9e992bdd, 0x0b09c417, 0x2b561186, 0xaaefa6d3, 0x8ab07342, 0x432a191b, 0x6375cc8a, 0xe2cc7bdf, 0xc293ae4e, 0x57034184, 0x775c9415, 0xf6e52340, 0xd6baf6d1, 0xc5a6eb13, 0xe5f93e82, 0x644089d7, 0x441f5c46, 0xd18fb38c, 0xf1d0661d, 0x7069d148, 0x503604d9, 0x32738dbf, 0x122c582e, 0x9395ef7b, 0xb3ca3aea, 0x265ad520, 0x060500b1, 0x87bcb7e4, 0xa7e36275, 0xb4ff7fb7, 0x94a0aa26, 0x15191d73, 0x3546c8e2, 0xa0d62728, 0x8089f2b9, 0x013045ec, 0x216f907d, 0x81bc0942, 0xa1e3dcd3, 0x205a6b86, 0x0005be17, 0x959551dd, 0xb5ca844c, 0x34733319, 0x142ce688, 0x0730fb4a, 0x276f2edb, 0xa6d6998e, 0x86894c1f, 0x1319a3d5, 0x33467644, 0xb2ffc111, 0x92a01480, 0xf0e59de6, 0xd0ba4877, 0x5103ff22, 0x715c2ab3, 0xe4ccc579, 0xc49310e8, 0x452aa7bd, 0x6575722c, 0x76696fee, 0x5636ba7f, 0xd78f0d2a, 0xf7d0d8bb, 0x62403771, 0x421fe2e0, 0xc3a655b5, 0xe3f98024, 0x2a63ea7d, 0x0a3c3fec, 0x8b8588b9, 0xabda5d28, 0x3e4ab2e2, 0x1e156773, 0x9facd026, 0xbff305b7, 0xacef1875, 0x8cb0cde4, 0x0d097ab1, 0x2d56af20, 0xb8c640ea, 0x9899957b, 0x1920222e, 0x397ff7bf, 0x5b3a7ed9, 0x7b65ab48, 0xfadc1c1d, 0xda83c98c, 0x4f132646, 0x6f4cf3d7, 0xeef54482, 0xceaa9113, 0xddb68cd1, 0xfde95940, 0x7c50ee15, 0x5c0f3b84, 0xc99fd44e, 0xe9c001df, 0x6879b68a, 0x4826631b, 0x6949f366, 0x491626f7, 0xc8af91a2, 0xe8f04433, 0x7d60abf9, 0x5d3f7e68, 0xdc86c93d, 0xfcd91cac, 0xefc5016e, 0xcf9ad4ff, 0x4e2363aa, 0x6e7cb63b, 0xfbec59f1, 0xdbb38c60, 0x5a0a3b35, 0x7a55eea4, 0x181067c2, 0x384fb253, 0xb9f60506, 0x99a9d097, 0x0c393f5d, 0x2c66eacc, 0xaddf5d99, 0x8d808808, 0x9e9c95ca, 0xbec3405b, 0x3f7af70e, 0x1f25229f, 0x8ab5cd55, 0xaaea18c4, 0x2b53af91, 0x0b0c7a00, 0xc2961059, 0xe2c9c5c8, 0x6370729d, 0x432fa70c, 0xd6bf48c6, 0xf6e09d57, 0x77592a02, 0x5706ff93, 0x441ae251, 0x644537c0, 0xe5fc8095, 0xc5a35504, 0x5033bace, 0x706c6f5f, 0xf1d5d80a, 0xd18a0d9b, 0xb3cf84fd, 0x9390516c, 0x1229e639, 0x327633a8, 0xa7e6dc62, 0x87b909f3, 0x0600bea6, 0x265f6b37, 0x354376f5, 0x151ca364, 0x94a51431, 0xb4fac1a0, 0x216a2e6a, 0x0135fbfb, 0x808c4cae, 0xa0d3993f +}, +{ +0x00000000, 0x98f55a03, 0xfdb76d82, 0x65423781, 0x9111ad86, 0x09e4f785, 0x6ca6c004, 0xf4539a07, 0x435ad35a, 0xdbaf8959, 0xbeedbed8, 0x2618e4db, 0xd24b7edc, 0x4abe24df, 0x2ffc135e, 0xb709495d, 0x80a35edd, 0x185604de, 0x7d14335f, 0xe5e1695c, 0x11b2f35b, 0x8947a958, 0xec059ed9, 0x74f0c4da, 0xc3f98d87, 0x5b0cd784, 0x3e4ee005, 0xa6bbba06, 0x52e82001, 0xca1d7a02, 0xaf5f4d83, 0x37aa1780, 0x3f2015d0, 0xa7d54fd3, 0xc2977852, 0x5a622251, 0xae31b856, 0x36c4e255, 0x5386d5d4, 0xcb738fd7, 0x7c7ac68a, 0xe48f9c89, 0x81cdab08, 0x1938f10b, 0xed6b6b0c, 0x759e310f, 0x10dc068e, 0x88295c8d, 0xbf834b0d, 0x2776110e, 0x4234268f, 0xdac17c8c, 0x2e92e68b, 0xb667bc88, 0xd3258b09, 0x4bd0d10a, 0xfcd99857, 0x642cc254, 0x016ef5d5, 0x999bafd6, 0x6dc835d1, 0xf53d6fd2, 0x907f5853, 0x088a0250, 0x3f6c12c1, 0xa79948c2, 0xc2db7f43, 0x5a2e2540, 0xae7dbf47, 0x3688e544, 0x53cad2c5, 0xcb3f88c6, 0x7c36c19b, 0xe4c39b98, 0x8181ac19, 0x1974f61a, 0xed276c1d, 0x75d2361e, 0x1090019f, 0x88655b9c, 0xbfcf4c1c, 0x273a161f, 0x4278219e, 0xda8d7b9d, 0x2edee19a, 0xb62bbb99, 0xd3698c18, 0x4b9cd61b, 0xfc959f46, 0x6460c545, 0x0122f2c4, 0x99d7a8c7, 0x6d8432c0, 0xf57168c3, 0x90335f42, 0x08c60541, 0x004c0711, 0x98b95d12, 0xfdfb6a93, 0x650e3090, 0x915daa97, 0x09a8f094, 0x6ceac715, 0xf41f9d16, 0x4316d44b, 0xdbe38e48, 0xbea1b9c9, 0x2654e3ca, 0xd20779cd, 0x4af223ce, 0x2fb0144f, 0xb7454e4c, 0x80ef59cc, 0x181a03cf, 0x7d58344e, 0xe5ad6e4d, 0x11fef44a, 0x890bae49, 0xec4999c8, 0x74bcc3cb, 0xc3b58a96, 0x5b40d095, 0x3e02e714, 0xa6f7bd17, 0x52a42710, 0xca517d13, 0xaf134a92, 0x37e61091, 0x9dc18565, 0x0534df66, 0x6076e8e7, 0xf883b2e4, 0x0cd028e3, 0x942572e0, 0xf1674561, 0x69921f62, 0xde9b563f, 0x466e0c3c, 0x232c3bbd, 0xbbd961be, 0x4f8afbb9, 0xd77fa1ba, 0xb23d963b, 0x2ac8cc38, 0x1d62dbb8, 0x859781bb, 0xe0d5b63a, 0x7820ec39, 0x8c73763e, 0x14862c3d, 0x71c41bbc, 0xe93141bf, 0x5e3808e2, 0xc6cd52e1, 0xa38f6560, 0x3b7a3f63, 0xcf29a564, 0x57dcff67, 0x329ec8e6, 0xaa6b92e5, 0xa2e190b5, 0x3a14cab6, 0x5f56fd37, 0xc7a3a734, 0x33f03d33, 0xab056730, 0xce4750b1, 0x56b20ab2, 0xe1bb43ef, 0x794e19ec, 0x1c0c2e6d, 0x84f9746e, 0x70aaee69, 0xe85fb46a, 0x8d1d83eb, 0x15e8d9e8, 0x2242ce68, 0xbab7946b, 0xdff5a3ea, 0x4700f9e9, 0xb35363ee, 0x2ba639ed, 0x4ee40e6c, 0xd611546f, 0x61181d32, 0xf9ed4731, 0x9caf70b0, 0x045a2ab3, 0xf009b0b4, 0x68fceab7, 0x0dbedd36, 0x954b8735, 0xa2ad97a4, 0x3a58cda7, 0x5f1afa26, 0xc7efa025, 0x33bc3a22, 0xab496021, 0xce0b57a0, 0x56fe0da3, 0xe1f744fe, 0x79021efd, 0x1c40297c, 0x84b5737f, 0x70e6e978, 0xe813b37b, 0x8d5184fa, 0x15a4def9, 0x220ec979, 0xbafb937a, 0xdfb9a4fb, 0x474cfef8, 0xb31f64ff, 0x2bea3efc, 0x4ea8097d, 0xd65d537e, 0x61541a23, 0xf9a14020, 0x9ce377a1, 0x04162da2, 0xf045b7a5, 0x68b0eda6, 0x0df2da27, 0x95078024, 0x9d8d8274, 0x0578d877, 0x603aeff6, 0xf8cfb5f5, 0x0c9c2ff2, 0x946975f1, 0xf12b4270, 0x69de1873, 0xded7512e, 0x46220b2d, 0x23603cac, 0xbb9566af, 0x4fc6fca8, 0xd733a6ab, 0xb271912a, 0x2a84cb29, 0x1d2edca9, 0x85db86aa, 0xe099b12b, 0x786ceb28, 0x8c3f712f, 0x14ca2b2c, 0x71881cad, 0xe97d46ae, 0x5e740ff3, 0xc68155f0, 0xa3c36271, 0x3b363872, 0xcf65a275, 0x5790f876, 0x32d2cff7, 0xaa2795f4 +}, +{ +0x00000000, 0x9c9b0554, 0x817dc94f, 0x1de6cc1b, 0x19f9fb6b, 0x8562fe3f, 0x98843224, 0x041f3770, 0x36a7a626, 0xaa3ca372, 0xb7da6f69, 0x2b416a3d, 0x2f5e5d4d, 0xb3c55819, 0xae239402, 0x32b89156, 0x970193bd, 0x0b9a96e9, 0x167c5af2, 0x8ae75fa6, 0x8ef868d6, 0x12636d82, 0x0f85a199, 0x931ea4cd, 0xa1a6359b, 0x3d3d30cf, 0x20dbfcd4, 0xbc40f980, 0xb85fcef0, 0x24c4cba4, 0x392207bf, 0xa5b902eb, 0xbbab4fcb, 0x27304a9f, 0x3ad68684, 0xa64d83d0, 0xa252b4a0, 0x3ec9b1f4, 0x232f7def, 0xbfb478bb, 0x8d0ce9ed, 0x1197ecb9, 0x0c7120a2, 0x90ea25f6, 0x94f51286, 0x086e17d2, 0x1588dbc9, 0x8913de9d, 0x2caadc76, 0xb031d922, 0xadd71539, 0x314c106d, 0x3553271d, 0xa9c82249, 0xb42eee52, 0x28b5eb06, 0x1a0d7a50, 0x86967f04, 0x9b70b31f, 0x07ebb64b, 0x03f4813b, 0x9f6f846f, 0x82894874, 0x1e124d20, 0x7ac461e5, 0xe65f64b1, 0xfbb9a8aa, 0x6722adfe, 0x633d9a8e, 0xffa69fda, 0xe24053c1, 0x7edb5695, 0x4c63c7c3, 0xd0f8c297, 0xcd1e0e8c, 0x51850bd8, 0x559a3ca8, 0xc90139fc, 0xd4e7f5e7, 0x487cf0b3, 0xedc5f258, 0x715ef70c, 0x6cb83b17, 0xf0233e43, 0xf43c0933, 0x68a70c67, 0x7541c07c, 0xe9dac528, 0xdb62547e, 0x47f9512a, 0x5a1f9d31, 0xc6849865, 0xc29baf15, 0x5e00aa41, 0x43e6665a, 0xdf7d630e, 0xc16f2e2e, 0x5df42b7a, 0x4012e761, 0xdc89e235, 0xd896d545, 0x440dd011, 0x59eb1c0a, 0xc570195e, 0xf7c88808, 0x6b538d5c, 0x76b54147, 0xea2e4413, 0xee317363, 0x72aa7637, 0x6f4cba2c, 0xf3d7bf78, 0x566ebd93, 0xcaf5b8c7, 0xd71374dc, 0x4b887188, 0x4f9746f8, 0xd30c43ac, 0xceea8fb7, 0x52718ae3, 0x60c91bb5, 0xfc521ee1, 0xe1b4d2fa, 0x7d2fd7ae, 0x7930e0de, 0xe5abe58a, 0xf84d2991, 0x64d62cc5, 0x0a60616f, 0x96fb643b, 0x8b1da820, 0x1786ad74, 0x13999a04, 0x8f029f50, 0x92e4534b, 0x0e7f561f, 0x3cc7c749, 0xa05cc21d, 0xbdba0e06, 0x21210b52, 0x253e3c22, 0xb9a53976, 0xa443f56d, 0x38d8f039, 0x9d61f2d2, 0x01faf786, 0x1c1c3b9d, 0x80873ec9, 0x849809b9, 0x18030ced, 0x05e5c0f6, 0x997ec5a2, 0xabc654f4, 0x375d51a0, 0x2abb9dbb, 0xb62098ef, 0xb23faf9f, 0x2ea4aacb, 0x334266d0, 0xafd96384, 0xb1cb2ea4, 0x2d502bf0, 0x30b6e7eb, 0xac2de2bf, 0xa832d5cf, 0x34a9d09b, 0x294f1c80, 0xb5d419d4, 0x876c8882, 0x1bf78dd6, 0x061141cd, 0x9a8a4499, 0x9e9573e9, 0x020e76bd, 0x1fe8baa6, 0x8373bff2, 0x26cabd19, 0xba51b84d, 0xa7b77456, 0x3b2c7102, 0x3f334672, 0xa3a84326, 0xbe4e8f3d, 0x22d58a69, 0x106d1b3f, 0x8cf61e6b, 0x9110d270, 0x0d8bd724, 0x0994e054, 0x950fe500, 0x88e9291b, 0x14722c4f, 0x70a4008a, 0xec3f05de, 0xf1d9c9c5, 0x6d42cc91, 0x695dfbe1, 0xf5c6feb5, 0xe82032ae, 0x74bb37fa, 0x4603a6ac, 0xda98a3f8, 0xc77e6fe3, 0x5be56ab7, 0x5ffa5dc7, 0xc3615893, 0xde879488, 0x421c91dc, 0xe7a59337, 0x7b3e9663, 0x66d85a78, 0xfa435f2c, 0xfe5c685c, 0x62c76d08, 0x7f21a113, 0xe3baa447, 0xd1023511, 0x4d993045, 0x507ffc5e, 0xcce4f90a, 0xc8fbce7a, 0x5460cb2e, 0x49860735, 0xd51d0261, 0xcb0f4f41, 0x57944a15, 0x4a72860e, 0xd6e9835a, 0xd2f6b42a, 0x4e6db17e, 0x538b7d65, 0xcf107831, 0xfda8e967, 0x6133ec33, 0x7cd52028, 0xe04e257c, 0xe451120c, 0x78ca1758, 0x652cdb43, 0xf9b7de17, 0x5c0edcfc, 0xc095d9a8, 0xdd7315b3, 0x41e810e7, 0x45f72797, 0xd96c22c3, 0xc48aeed8, 0x5811eb8c, 0x6aa97ada, 0xf6327f8e, 0xebd4b395, 0x774fb6c1, 0x735081b1, 0xefcb84e5, 0xf22d48fe, 0x6eb64daa +}, +{ +0x00000000, 0xd527f120, 0x803dfb19, 0x551a0a39, 0x15cad27d, 0xc0ed235d, 0x95f72964, 0x40d0d844, 0x015ac4f1, 0xd47d35d1, 0x81673fe8, 0x5440cec8, 0x1490168c, 0xc1b7e7ac, 0x94aded95, 0x418a1cb5, 0x0ec42d43, 0xdbe3dc63, 0x8ef9d65a, 0x5bde277a, 0x1b0eff3e, 0xce290e1e, 0x9b330427, 0x4e14f507, 0x0f9ee9b2, 0xdab91892, 0x8fa312ab, 0x5a84e38b, 0x1a543bcf, 0xcf73caef, 0x9a69c0d6, 0x4f4e31f6, 0xfd0f3f28, 0x2828ce08, 0x7d32c431, 0xa8153511, 0xe8c5ed55, 0x3de21c75, 0x68f8164c, 0xbddfe76c, 0xfc55fbd9, 0x29720af9, 0x7c6800c0, 0xa94ff1e0, 0xe99f29a4, 0x3cb8d884, 0x69a2d2bd, 0xbc85239d, 0xf3cb126b, 0x26ece34b, 0x73f6e972, 0xa6d11852, 0xe601c016, 0x33263136, 0x663c3b0f, 0xb31bca2f, 0xf291d69a, 0x27b627ba, 0x72ac2d83, 0xa78bdca3, 0xe75b04e7, 0x327cf5c7, 0x6766fffe, 0xb2410ede, 0xec7c8292, 0x395b73b2, 0x6c41798b, 0xb96688ab, 0xf9b650ef, 0x2c91a1cf, 0x798babf6, 0xacac5ad6, 0xed264663, 0x3801b743, 0x6d1bbd7a, 0xb83c4c5a, 0xf8ec941e, 0x2dcb653e, 0x78d16f07, 0xadf69e27, 0xe2b8afd1, 0x379f5ef1, 0x628554c8, 0xb7a2a5e8, 0xf7727dac, 0x22558c8c, 0x774f86b5, 0xa2687795, 0xe3e26b20, 0x36c59a00, 0x63df9039, 0xb6f86119, 0xf628b95d, 0x230f487d, 0x76154244, 0xa332b364, 0x1173bdba, 0xc4544c9a, 0x914e46a3, 0x4469b783, 0x04b96fc7, 0xd19e9ee7, 0x848494de, 0x51a365fe, 0x1029794b, 0xc50e886b, 0x90148252, 0x45337372, 0x05e3ab36, 0xd0c45a16, 0x85de502f, 0x50f9a10f, 0x1fb790f9, 0xca9061d9, 0x9f8a6be0, 0x4aad9ac0, 0x0a7d4284, 0xdf5ab3a4, 0x8a40b99d, 0x5f6748bd, 0x1eed5408, 0xcbcaa528, 0x9ed0af11, 0x4bf75e31, 0x0b278675, 0xde007755, 0x8b1a7d6c, 0x5e3d8c4c, 0x44ddc23e, 0x91fa331e, 0xc4e03927, 0x11c7c807, 0x51171043, 0x8430e163, 0xd12aeb5a, 0x040d1a7a, 0x458706cf, 0x90a0f7ef, 0xc5bafdd6, 0x109d0cf6, 0x504dd4b2, 0x856a2592, 0xd0702fab, 0x0557de8b, 0x4a19ef7d, 0x9f3e1e5d, 0xca241464, 0x1f03e544, 0x5fd33d00, 0x8af4cc20, 0xdfeec619, 0x0ac93739, 0x4b432b8c, 0x9e64daac, 0xcb7ed095, 0x1e5921b5, 0x5e89f9f1, 0x8bae08d1, 0xdeb402e8, 0x0b93f3c8, 0xb9d2fd16, 0x6cf50c36, 0x39ef060f, 0xecc8f72f, 0xac182f6b, 0x793fde4b, 0x2c25d472, 0xf9022552, 0xb88839e7, 0x6dafc8c7, 0x38b5c2fe, 0xed9233de, 0xad42eb9a, 0x78651aba, 0x2d7f1083, 0xf858e1a3, 0xb716d055, 0x62312175, 0x372b2b4c, 0xe20cda6c, 0xa2dc0228, 0x77fbf308, 0x22e1f931, 0xf7c60811, 0xb64c14a4, 0x636be584, 0x3671efbd, 0xe3561e9d, 0xa386c6d9, 0x76a137f9, 0x23bb3dc0, 0xf69ccce0, 0xa8a140ac, 0x7d86b18c, 0x289cbbb5, 0xfdbb4a95, 0xbd6b92d1, 0x684c63f1, 0x3d5669c8, 0xe87198e8, 0xa9fb845d, 0x7cdc757d, 0x29c67f44, 0xfce18e64, 0xbc315620, 0x6916a700, 0x3c0cad39, 0xe92b5c19, 0xa6656def, 0x73429ccf, 0x265896f6, 0xf37f67d6, 0xb3afbf92, 0x66884eb2, 0x3392448b, 0xe6b5b5ab, 0xa73fa91e, 0x7218583e, 0x27025207, 0xf225a327, 0xb2f57b63, 0x67d28a43, 0x32c8807a, 0xe7ef715a, 0x55ae7f84, 0x80898ea4, 0xd593849d, 0x00b475bd, 0x4064adf9, 0x95435cd9, 0xc05956e0, 0x157ea7c0, 0x54f4bb75, 0x81d34a55, 0xd4c9406c, 0x01eeb14c, 0x413e6908, 0x94199828, 0xc1039211, 0x14246331, 0x5b6a52c7, 0x8e4da3e7, 0xdb57a9de, 0x0e7058fe, 0x4ea080ba, 0x9b87719a, 0xce9d7ba3, 0x1bba8a83, 0x5a309636, 0x8f176716, 0xda0d6d2f, 0x0f2a9c0f, 0x4ffa444b, 0x9addb56b, 0xcfc7bf52, 0x1ae04e72 +}, +{ +0x00000000, 0xeb5ac356, 0x17f99ff8, 0xfca35cae, 0x131f1016, 0xf845d340, 0x04e68fee, 0xefbc4cb8, 0x314bb086, 0xda1173d0, 0x26b22f7e, 0xcde8ec28, 0x2254a090, 0xc90e63c6, 0x35ad3f68, 0xdef7fc3e, 0x65ccd9a6, 0x8e961af0, 0x7235465e, 0x996f8508, 0x76d3c9b0, 0x9d890ae6, 0x612a5648, 0x8a70951e, 0x54876920, 0xbfddaa76, 0x437ef6d8, 0xa824358e, 0x47987936, 0xacc2ba60, 0x5061e6ce, 0xbb3b2598, 0x7aedb630, 0x91b77566, 0x6d1429c8, 0x864eea9e, 0x69f2a626, 0x82a86570, 0x7e0b39de, 0x9551fa88, 0x4ba606b6, 0xa0fcc5e0, 0x5c5f994e, 0xb7055a18, 0x58b916a0, 0xb3e3d5f6, 0x4f408958, 0xa41a4a0e, 0x1f216f96, 0xf47bacc0, 0x08d8f06e, 0xe3823338, 0x0c3e7f80, 0xe764bcd6, 0x1bc7e078, 0xf09d232e, 0x2e6adf10, 0xc5301c46, 0x399340e8, 0xd2c983be, 0x3d75cf06, 0xd62f0c50, 0x2a8c50fe, 0xc1d693a8, 0xd7dbe9c8, 0x3c812a9e, 0xc0227630, 0x2b78b566, 0xc4c4f9de, 0x2f9e3a88, 0xd33d6626, 0x3867a570, 0xe690594e, 0x0dca9a18, 0xf169c6b6, 0x1a3305e0, 0xf58f4958, 0x1ed58a0e, 0xe276d6a0, 0x092c15f6, 0xb217306e, 0x594df338, 0xa5eeaf96, 0x4eb46cc0, 0xa1082078, 0x4a52e32e, 0xb6f1bf80, 0x5dab7cd6, 0x835c80e8, 0x680643be, 0x94a51f10, 0x7fffdc46, 0x904390fe, 0x7b1953a8, 0x87ba0f06, 0x6ce0cc50, 0xad365ff8, 0x466c9cae, 0xbacfc000, 0x51950356, 0xbe294fee, 0x55738cb8, 0xa9d0d016, 0x428a1340, 0x9c7def7e, 0x77272c28, 0x8b847086, 0x60deb3d0, 0x8f62ff68, 0x64383c3e, 0x989b6090, 0x73c1a3c6, 0xc8fa865e, 0x23a04508, 0xdf0319a6, 0x3459daf0, 0xdbe59648, 0x30bf551e, 0xcc1c09b0, 0x2746cae6, 0xf9b136d8, 0x12ebf58e, 0xee48a920, 0x05126a76, 0xeaae26ce, 0x01f4e598, 0xfd57b936, 0x160d7a60, 0x8c233ce5, 0x6779ffb3, 0x9bdaa31d, 0x7080604b, 0x9f3c2cf3, 0x7466efa5, 0x88c5b30b, 0x639f705d, 0xbd688c63, 0x56324f35, 0xaa91139b, 0x41cbd0cd, 0xae779c75, 0x452d5f23, 0xb98e038d, 0x52d4c0db, 0xe9efe543, 0x02b52615, 0xfe167abb, 0x154cb9ed, 0xfaf0f555, 0x11aa3603, 0xed096aad, 0x0653a9fb, 0xd8a455c5, 0x33fe9693, 0xcf5dca3d, 0x2407096b, 0xcbbb45d3, 0x20e18685, 0xdc42da2b, 0x3718197d, 0xf6ce8ad5, 0x1d944983, 0xe137152d, 0x0a6dd67b, 0xe5d19ac3, 0x0e8b5995, 0xf228053b, 0x1972c66d, 0xc7853a53, 0x2cdff905, 0xd07ca5ab, 0x3b2666fd, 0xd49a2a45, 0x3fc0e913, 0xc363b5bd, 0x283976eb, 0x93025373, 0x78589025, 0x84fbcc8b, 0x6fa10fdd, 0x801d4365, 0x6b478033, 0x97e4dc9d, 0x7cbe1fcb, 0xa249e3f5, 0x491320a3, 0xb5b07c0d, 0x5eeabf5b, 0xb156f3e3, 0x5a0c30b5, 0xa6af6c1b, 0x4df5af4d, 0x5bf8d52d, 0xb0a2167b, 0x4c014ad5, 0xa75b8983, 0x48e7c53b, 0xa3bd066d, 0x5f1e5ac3, 0xb4449995, 0x6ab365ab, 0x81e9a6fd, 0x7d4afa53, 0x96103905, 0x79ac75bd, 0x92f6b6eb, 0x6e55ea45, 0x850f2913, 0x3e340c8b, 0xd56ecfdd, 0x29cd9373, 0xc2975025, 0x2d2b1c9d, 0xc671dfcb, 0x3ad28365, 0xd1884033, 0x0f7fbc0d, 0xe4257f5b, 0x188623f5, 0xf3dce0a3, 0x1c60ac1b, 0xf73a6f4d, 0x0b9933e3, 0xe0c3f0b5, 0x2115631d, 0xca4fa04b, 0x36ecfce5, 0xddb63fb3, 0x320a730b, 0xd950b05d, 0x25f3ecf3, 0xcea92fa5, 0x105ed39b, 0xfb0410cd, 0x07a74c63, 0xecfd8f35, 0x0341c38d, 0xe81b00db, 0x14b85c75, 0xffe29f23, 0x44d9babb, 0xaf8379ed, 0x53202543, 0xb87ae615, 0x57c6aaad, 0xbc9c69fb, 0x403f3555, 0xab65f603, 0x75920a3d, 0x9ec8c96b, 0x626b95c5, 0x89315693, 0x668d1a2b, 0x8dd7d97d, 0x717485d3, 0x9a2e4685 +}, +{ +0x00000000, 0xd74b1b11, 0x677ddf29, 0xb036c438, 0x26c39217, 0xf1888906, 0x41be4d3e, 0x96f5562f, 0x99e7d3b5, 0x4eacc8a4, 0xfe9a0c9c, 0x29d1178d, 0xbf2441a2, 0x686f5ab3, 0xd8599e8b, 0x0f12859a, 0x377134cb, 0xe03a2fda, 0x500cebe2, 0x8747f0f3, 0x11b2a6dc, 0xc6f9bdcd, 0x76cf79f5, 0xa18462e4, 0xae96e77e, 0x79ddfc6f, 0xc9eb3857, 0x1ea02346, 0x88557569, 0x5f1e6e78, 0xef28aa40, 0x3863b151, 0x98b0b9e6, 0x4ffba2f7, 0xffcd66cf, 0x28867dde, 0xbe732bf1, 0x693830e0, 0xd90ef4d8, 0x0e45efc9, 0x01576a53, 0xd61c7142, 0x662ab57a, 0xb161ae6b, 0x2794f844, 0xf0dfe355, 0x40e9276d, 0x97a23c7c, 0xafc18d2d, 0x788a963c, 0xc8bc5204, 0x1ff74915, 0x89021f3a, 0x5e49042b, 0xee7fc013, 0x3934db02, 0x36265e98, 0xe16d4589, 0x515b81b1, 0x86109aa0, 0x10e5cc8f, 0xc7aed79e, 0x779813a6, 0xa0d308b7, 0x308df13f, 0xe7c6ea2e, 0x57f02e16, 0x80bb3507, 0x164e6328, 0xc1057839, 0x7133bc01, 0xa678a710, 0xa96a228a, 0x7e21399b, 0xce17fda3, 0x195ce6b2, 0x8fa9b09d, 0x58e2ab8c, 0xe8d46fb4, 0x3f9f74a5, 0x07fcc5f4, 0xd0b7dee5, 0x60811add, 0xb7ca01cc, 0x213f57e3, 0xf6744cf2, 0x464288ca, 0x910993db, 0x9e1b1641, 0x49500d50, 0xf966c968, 0x2e2dd279, 0xb8d88456, 0x6f939f47, 0xdfa55b7f, 0x08ee406e, 0xa83d48d9, 0x7f7653c8, 0xcf4097f0, 0x180b8ce1, 0x8efedace, 0x59b5c1df, 0xe98305e7, 0x3ec81ef6, 0x31da9b6c, 0xe691807d, 0x56a74445, 0x81ec5f54, 0x1719097b, 0xc052126a, 0x7064d652, 0xa72fcd43, 0x9f4c7c12, 0x48076703, 0xf831a33b, 0x2f7ab82a, 0xb98fee05, 0x6ec4f514, 0xdef2312c, 0x09b92a3d, 0x06abafa7, 0xd1e0b4b6, 0x61d6708e, 0xb69d6b9f, 0x20683db0, 0xf72326a1, 0x4715e299, 0x905ef988, 0xf14cb659, 0x2607ad48, 0x96316970, 0x417a7261, 0xd78f244e, 0x00c43f5f, 0xb0f2fb67, 0x67b9e076, 0x68ab65ec, 0xbfe07efd, 0x0fd6bac5, 0xd89da1d4, 0x4e68f7fb, 0x9923ecea, 0x291528d2, 0xfe5e33c3, 0xc63d8292, 0x11769983, 0xa1405dbb, 0x760b46aa, 0xe0fe1085, 0x37b50b94, 0x8783cfac, 0x50c8d4bd, 0x5fda5127, 0x88914a36, 0x38a78e0e, 0xefec951f, 0x7919c330, 0xae52d821, 0x1e641c19, 0xc92f0708, 0x69fc0fbf, 0xbeb714ae, 0x0e81d096, 0xd9cacb87, 0x4f3f9da8, 0x987486b9, 0x28424281, 0xff095990, 0xf01bdc0a, 0x2750c71b, 0x97660323, 0x402d1832, 0xd6d84e1d, 0x0193550c, 0xb1a59134, 0x66ee8a25, 0x5e8d3b74, 0x89c62065, 0x39f0e45d, 0xeebbff4c, 0x784ea963, 0xaf05b272, 0x1f33764a, 0xc8786d5b, 0xc76ae8c1, 0x1021f3d0, 0xa01737e8, 0x775c2cf9, 0xe1a97ad6, 0x36e261c7, 0x86d4a5ff, 0x519fbeee, 0xc1c14766, 0x168a5c77, 0xa6bc984f, 0x71f7835e, 0xe702d571, 0x3049ce60, 0x807f0a58, 0x57341149, 0x582694d3, 0x8f6d8fc2, 0x3f5b4bfa, 0xe81050eb, 0x7ee506c4, 0xa9ae1dd5, 0x1998d9ed, 0xced3c2fc, 0xf6b073ad, 0x21fb68bc, 0x91cdac84, 0x4686b795, 0xd073e1ba, 0x0738faab, 0xb70e3e93, 0x60452582, 0x6f57a018, 0xb81cbb09, 0x082a7f31, 0xdf616420, 0x4994320f, 0x9edf291e, 0x2ee9ed26, 0xf9a2f637, 0x5971fe80, 0x8e3ae591, 0x3e0c21a9, 0xe9473ab8, 0x7fb26c97, 0xa8f97786, 0x18cfb3be, 0xcf84a8af, 0xc0962d35, 0x17dd3624, 0xa7ebf21c, 0x70a0e90d, 0xe655bf22, 0x311ea433, 0x8128600b, 0x56637b1a, 0x6e00ca4b, 0xb94bd15a, 0x097d1562, 0xde360e73, 0x48c3585c, 0x9f88434d, 0x2fbe8775, 0xf8f59c64, 0xf7e719fe, 0x20ac02ef, 0x909ac6d7, 0x47d1ddc6, 0xd1248be9, 0x066f90f8, 0xb65954c0, 0x61124fd1 +}, +{ +0x00000000, 0xc870d248, 0x30d51815, 0xf8a5ca5d, 0x977e90a6, 0x5f0e42ee, 0xa7ab88b3, 0x6fdb5afb, 0x09db0315, 0xc1abd15d, 0x390e1b00, 0xf17ec948, 0x9ea593b3, 0x56d541fb, 0xae708ba6, 0x660059ee, 0x21278633, 0xe957547b, 0x11f29e26, 0xd9824c6e, 0xb6591695, 0x7e29c4dd, 0x868c0e80, 0x4efcdcc8, 0x28fc8526, 0xe08c576e, 0x18299d33, 0xd0594f7b, 0xbf821580, 0x77f2c7c8, 0x8f570d95, 0x4727dfdd, 0xf3093661, 0x3b79e429, 0xc3dc2e74, 0x0bacfc3c, 0x6477a6c7, 0xac07748f, 0x54a2bed2, 0x9cd26c9a, 0xfad23574, 0x32a2e73c, 0xca072d61, 0x0277ff29, 0x6daca5d2, 0xa5dc779a, 0x5d79bdc7, 0x95096f8f, 0xd22eb052, 0x1a5e621a, 0xe2fba847, 0x2a8b7a0f, 0x455020f4, 0x8d20f2bc, 0x758538e1, 0xbdf5eaa9, 0xdbf5b347, 0x1385610f, 0xeb20ab52, 0x2350791a, 0x4c8b23e1, 0x84fbf1a9, 0x7c5e3bf4, 0xb42ee9bc, 0x8e5d141b, 0x462dc653, 0xbe880c0e, 0x76f8de46, 0x192384bd, 0xd15356f5, 0x29f69ca8, 0xe1864ee0, 0x8786170e, 0x4ff6c546, 0xb7530f1b, 0x7f23dd53, 0x10f887a8, 0xd88855e0, 0x202d9fbd, 0xe85d4df5, 0xaf7a9228, 0x670a4060, 0x9faf8a3d, 0x57df5875, 0x3804028e, 0xf074d0c6, 0x08d11a9b, 0xc0a1c8d3, 0xa6a1913d, 0x6ed14375, 0x96748928, 0x5e045b60, 0x31df019b, 0xf9afd3d3, 0x010a198e, 0xc97acbc6, 0x7d54227a, 0xb524f032, 0x4d813a6f, 0x85f1e827, 0xea2ab2dc, 0x225a6094, 0xdaffaac9, 0x128f7881, 0x748f216f, 0xbcfff327, 0x445a397a, 0x8c2aeb32, 0xe3f1b1c9, 0x2b816381, 0xd324a9dc, 0x1b547b94, 0x5c73a449, 0x94037601, 0x6ca6bc5c, 0xa4d66e14, 0xcb0d34ef, 0x037de6a7, 0xfbd82cfa, 0x33a8feb2, 0x55a8a75c, 0x9dd87514, 0x657dbf49, 0xad0d6d01, 0xc2d637fa, 0x0aa6e5b2, 0xf2032fef, 0x3a73fda7, 0xcac0916f, 0x02b04327, 0xfa15897a, 0x32655b32, 0x5dbe01c9, 0x95ced381, 0x6d6b19dc, 0xa51bcb94, 0xc31b927a, 0x0b6b4032, 0xf3ce8a6f, 0x3bbe5827, 0x546502dc, 0x9c15d094, 0x64b01ac9, 0xacc0c881, 0xebe7175c, 0x2397c514, 0xdb320f49, 0x1342dd01, 0x7c9987fa, 0xb4e955b2, 0x4c4c9fef, 0x843c4da7, 0xe23c1449, 0x2a4cc601, 0xd2e90c5c, 0x1a99de14, 0x754284ef, 0xbd3256a7, 0x45979cfa, 0x8de74eb2, 0x39c9a70e, 0xf1b97546, 0x091cbf1b, 0xc16c6d53, 0xaeb737a8, 0x66c7e5e0, 0x9e622fbd, 0x5612fdf5, 0x3012a41b, 0xf8627653, 0x00c7bc0e, 0xc8b76e46, 0xa76c34bd, 0x6f1ce6f5, 0x97b92ca8, 0x5fc9fee0, 0x18ee213d, 0xd09ef375, 0x283b3928, 0xe04beb60, 0x8f90b19b, 0x47e063d3, 0xbf45a98e, 0x77357bc6, 0x11352228, 0xd945f060, 0x21e03a3d, 0xe990e875, 0x864bb28e, 0x4e3b60c6, 0xb69eaa9b, 0x7eee78d3, 0x449d8574, 0x8ced573c, 0x74489d61, 0xbc384f29, 0xd3e315d2, 0x1b93c79a, 0xe3360dc7, 0x2b46df8f, 0x4d468661, 0x85365429, 0x7d939e74, 0xb5e34c3c, 0xda3816c7, 0x1248c48f, 0xeaed0ed2, 0x229ddc9a, 0x65ba0347, 0xadcad10f, 0x556f1b52, 0x9d1fc91a, 0xf2c493e1, 0x3ab441a9, 0xc2118bf4, 0x0a6159bc, 0x6c610052, 0xa411d21a, 0x5cb41847, 0x94c4ca0f, 0xfb1f90f4, 0x336f42bc, 0xcbca88e1, 0x03ba5aa9, 0xb794b315, 0x7fe4615d, 0x8741ab00, 0x4f317948, 0x20ea23b3, 0xe89af1fb, 0x103f3ba6, 0xd84fe9ee, 0xbe4fb000, 0x763f6248, 0x8e9aa815, 0x46ea7a5d, 0x293120a6, 0xe141f2ee, 0x19e438b3, 0xd194eafb, 0x96b33526, 0x5ec3e76e, 0xa6662d33, 0x6e16ff7b, 0x01cda580, 0xc9bd77c8, 0x3118bd95, 0xf9686fdd, 0x9f683633, 0x5718e47b, 0xafbd2e26, 0x67cdfc6e, 0x0816a695, 0xc06674dd, 0x38c3be80, 0xf0b36cc8 +} +}, +{ +{ +0x00000000, 0xfa358426, 0x457826d5, 0xbf4da2f3, 0x84f1151b, 0x7ec4913d, 0xc18933ce, 0x3bbcb7e8, 0x5cb36dda, 0xa686e9fc, 0x19cb4b0f, 0xe3fecf29, 0xd84278c1, 0x2277fce7, 0x9d3a5e14, 0x670fda32, 0xde14cf5d, 0x24214b7b, 0x9b6ce988, 0x61596dae, 0x5ae5da46, 0xa0d05e60, 0x1f9dfc93, 0xe5a878b5, 0x82a7a287, 0x789226a1, 0xc7df8452, 0x3dea0074, 0x0656b79c, 0xfc6333ba, 0x432e9149, 0xb91b156f, 0x7fceb32f, 0x85fb3709, 0x3ab695fa, 0xc08311dc, 0xfb3fa634, 0x010a2212, 0xbe4780e1, 0x447204c7, 0x237ddef5, 0xd9485ad3, 0x6605f820, 0x9c307c06, 0xa78ccbee, 0x5db94fc8, 0xe2f4ed3b, 0x18c1691d, 0xa1da7c72, 0x5beff854, 0xe4a25aa7, 0x1e97de81, 0x252b6969, 0xdf1eed4f, 0x60534fbc, 0x9a66cb9a, 0xfd6911a8, 0x075c958e, 0xb811377d, 0x4224b35b, 0x799804b3, 0x83ad8095, 0x3ce02266, 0xc6d5a640, 0x36ac2228, 0xcc99a60e, 0x73d404fd, 0x89e180db, 0xb25d3733, 0x4868b315, 0xf72511e6, 0x0d1095c0, 0x6a1f4ff2, 0x902acbd4, 0x2f676927, 0xd552ed01, 0xeeee5ae9, 0x14dbdecf, 0xab967c3c, 0x51a3f81a, 0xe8b8ed75, 0x128d6953, 0xadc0cba0, 0x57f54f86, 0x6c49f86e, 0x967c7c48, 0x2931debb, 0xd3045a9d, 0xb40b80af, 0x4e3e0489, 0xf173a67a, 0x0b46225c, 0x30fa95b4, 0xcacf1192, 0x7582b361, 0x8fb73747, 0x49629107, 0xb3571521, 0x0c1ab7d2, 0xf62f33f4, 0xcd93841c, 0x37a6003a, 0x88eba2c9, 0x72de26ef, 0x15d1fcdd, 0xefe478fb, 0x50a9da08, 0xaa9c5e2e, 0x9120e9c6, 0x6b156de0, 0xd458cf13, 0x2e6d4b35, 0x97765e5a, 0x6d43da7c, 0xd20e788f, 0x283bfca9, 0x13874b41, 0xe9b2cf67, 0x56ff6d94, 0xaccae9b2, 0xcbc53380, 0x31f0b7a6, 0x8ebd1555, 0x74889173, 0x4f34269b, 0xb501a2bd, 0x0a4c004e, 0xf0798468, 0x7c28840c, 0x861d002a, 0x3950a2d9, 0xc36526ff, 0xf8d99117, 0x02ec1531, 0xbda1b7c2, 0x479433e4, 0x209be9d6, 0xdaae6df0, 0x65e3cf03, 0x9fd64b25, 0xa46afccd, 0x5e5f78eb, 0xe112da18, 0x1b275e3e, 0xa23c4b51, 0x5809cf77, 0xe7446d84, 0x1d71e9a2, 0x26cd5e4a, 0xdcf8da6c, 0x63b5789f, 0x9980fcb9, 0xfe8f268b, 0x04baa2ad, 0xbbf7005e, 0x41c28478, 0x7a7e3390, 0x804bb7b6, 0x3f061545, 0xc5339163, 0x03e63723, 0xf9d3b305, 0x469e11f6, 0xbcab95d0, 0x87172238, 0x7d22a61e, 0xc26f04ed, 0x385a80cb, 0x5f555af9, 0xa560dedf, 0x1a2d7c2c, 0xe018f80a, 0xdba44fe2, 0x2191cbc4, 0x9edc6937, 0x64e9ed11, 0xddf2f87e, 0x27c77c58, 0x988adeab, 0x62bf5a8d, 0x5903ed65, 0xa3366943, 0x1c7bcbb0, 0xe64e4f96, 0x814195a4, 0x7b741182, 0xc439b371, 0x3e0c3757, 0x05b080bf, 0xff850499, 0x40c8a66a, 0xbafd224c, 0x4a84a624, 0xb0b12202, 0x0ffc80f1, 0xf5c904d7, 0xce75b33f, 0x34403719, 0x8b0d95ea, 0x713811cc, 0x1637cbfe, 0xec024fd8, 0x534fed2b, 0xa97a690d, 0x92c6dee5, 0x68f35ac3, 0xd7bef830, 0x2d8b7c16, 0x94906979, 0x6ea5ed5f, 0xd1e84fac, 0x2bddcb8a, 0x10617c62, 0xea54f844, 0x55195ab7, 0xaf2cde91, 0xc82304a3, 0x32168085, 0x8d5b2276, 0x776ea650, 0x4cd211b8, 0xb6e7959e, 0x09aa376d, 0xf39fb34b, 0x354a150b, 0xcf7f912d, 0x703233de, 0x8a07b7f8, 0xb1bb0010, 0x4b8e8436, 0xf4c326c5, 0x0ef6a2e3, 0x69f978d1, 0x93ccfcf7, 0x2c815e04, 0xd6b4da22, 0xed086dca, 0x173de9ec, 0xa8704b1f, 0x5245cf39, 0xeb5eda56, 0x116b5e70, 0xae26fc83, 0x541378a5, 0x6fafcf4d, 0x959a4b6b, 0x2ad7e998, 0xd0e26dbe, 0xb7edb78c, 0x4dd833aa, 0xf2959159, 0x08a0157f, 0x331ca297, 0xc92926b1, 0x76648442, 0x8c510064 +}, +{ +0x00000000, 0xc8e79718, 0x4eccfd06, 0x862b6a1e, 0xc48db21e, 0x0c6a2506, 0x8a414f18, 0x42a6d800, 0x363f4d30, 0xfed8da28, 0x78f3b036, 0xb014272e, 0xf2b2ff2e, 0x3a556836, 0xbc7e0228, 0x74999530, 0x8061d286, 0x4886459e, 0xcead2f80, 0x064ab898, 0x44ec6098, 0x8c0bf780, 0x0a209d9e, 0xc2c70a86, 0xb65e9fb6, 0x7eb908ae, 0xf89262b0, 0x3075f5a8, 0x72d32da8, 0xba34bab0, 0x3c1fd0ae, 0xf4f847b6, 0x8eb02d55, 0x4657ba4d, 0xc07cd053, 0x089b474b, 0x4a3d9f4b, 0x82da0853, 0x04f1624d, 0xcc16f555, 0xb88f6065, 0x7068f77d, 0xf6439d63, 0x3ea40a7b, 0x7c02d27b, 0xb4e54563, 0x32ce2f7d, 0xfa29b865, 0x0ed1ffd3, 0xc63668cb, 0x401d02d5, 0x88fa95cd, 0xca5c4dcd, 0x02bbdad5, 0x8490b0cb, 0x4c7727d3, 0x38eeb2e3, 0xf00925fb, 0x76224fe5, 0xbec5d8fd, 0xfc6300fd, 0x348497e5, 0xb2affdfb, 0x7a486ae3, 0x12ac329c, 0xda4ba584, 0x5c60cf9a, 0x94875882, 0xd6218082, 0x1ec6179a, 0x98ed7d84, 0x500aea9c, 0x24937fac, 0xec74e8b4, 0x6a5f82aa, 0xa2b815b2, 0xe01ecdb2, 0x28f95aaa, 0xaed230b4, 0x6635a7ac, 0x92cde01a, 0x5a2a7702, 0xdc011d1c, 0x14e68a04, 0x56405204, 0x9ea7c51c, 0x188caf02, 0xd06b381a, 0xa4f2ad2a, 0x6c153a32, 0xea3e502c, 0x22d9c734, 0x607f1f34, 0xa898882c, 0x2eb3e232, 0xe654752a, 0x9c1c1fc9, 0x54fb88d1, 0xd2d0e2cf, 0x1a3775d7, 0x5891add7, 0x90763acf, 0x165d50d1, 0xdebac7c9, 0xaa2352f9, 0x62c4c5e1, 0xe4efafff, 0x2c0838e7, 0x6eaee0e7, 0xa64977ff, 0x20621de1, 0xe8858af9, 0x1c7dcd4f, 0xd49a5a57, 0x52b13049, 0x9a56a751, 0xd8f07f51, 0x1017e849, 0x963c8257, 0x5edb154f, 0x2a42807f, 0xe2a51767, 0x648e7d79, 0xac69ea61, 0xeecf3261, 0x2628a579, 0xa003cf67, 0x68e4587f, 0x051fb4d4, 0xcdf823cc, 0x4bd349d2, 0x8334deca, 0xc19206ca, 0x097591d2, 0x8f5efbcc, 0x47b96cd4, 0x3320f9e4, 0xfbc76efc, 0x7dec04e2, 0xb50b93fa, 0xf7ad4bfa, 0x3f4adce2, 0xb961b6fc, 0x718621e4, 0x857e6652, 0x4d99f14a, 0xcbb29b54, 0x03550c4c, 0x41f3d44c, 0x89144354, 0x0f3f294a, 0xc7d8be52, 0xb3412b62, 0x7ba6bc7a, 0xfd8dd664, 0x356a417c, 0x77cc997c, 0xbf2b0e64, 0x3900647a, 0xf1e7f362, 0x8baf9981, 0x43480e99, 0xc5636487, 0x0d84f39f, 0x4f222b9f, 0x87c5bc87, 0x01eed699, 0xc9094181, 0xbd90d4b1, 0x757743a9, 0xf35c29b7, 0x3bbbbeaf, 0x791d66af, 0xb1faf1b7, 0x37d19ba9, 0xff360cb1, 0x0bce4b07, 0xc329dc1f, 0x4502b601, 0x8de52119, 0xcf43f919, 0x07a46e01, 0x818f041f, 0x49689307, 0x3df10637, 0xf516912f, 0x733dfb31, 0xbbda6c29, 0xf97cb429, 0x319b2331, 0xb7b0492f, 0x7f57de37, 0x17b38648, 0xdf541150, 0x597f7b4e, 0x9198ec56, 0xd33e3456, 0x1bd9a34e, 0x9df2c950, 0x55155e48, 0x218ccb78, 0xe96b5c60, 0x6f40367e, 0xa7a7a166, 0xe5017966, 0x2de6ee7e, 0xabcd8460, 0x632a1378, 0x97d254ce, 0x5f35c3d6, 0xd91ea9c8, 0x11f93ed0, 0x535fe6d0, 0x9bb871c8, 0x1d931bd6, 0xd5748cce, 0xa1ed19fe, 0x690a8ee6, 0xef21e4f8, 0x27c673e0, 0x6560abe0, 0xad873cf8, 0x2bac56e6, 0xe34bc1fe, 0x9903ab1d, 0x51e43c05, 0xd7cf561b, 0x1f28c103, 0x5d8e1903, 0x95698e1b, 0x1342e405, 0xdba5731d, 0xaf3ce62d, 0x67db7135, 0xe1f01b2b, 0x29178c33, 0x6bb15433, 0xa356c32b, 0x257da935, 0xed9a3e2d, 0x1962799b, 0xd185ee83, 0x57ae849d, 0x9f491385, 0xddefcb85, 0x15085c9d, 0x93233683, 0x5bc4a19b, 0x2f5d34ab, 0xe7baa3b3, 0x6191c9ad, 0xa9765eb5, 0xebd086b5, 0x233711ad, 0xa51c7bb3, 0x6dfbecab +}, +{ +0x00000000, 0xeb6f6e3b, 0x0a2a26e9, 0xe14548d2, 0x94fbb96d, 0x7f94d756, 0x9ed19f84, 0x75bef1bf, 0x639643a5, 0x88f92d9e, 0x69bc654c, 0x82d30b77, 0xf76dfac8, 0x1c0294f3, 0xfd47dc21, 0x1628b21a, 0x34a71b67, 0xdfc8755c, 0x3e8d3d8e, 0xd5e253b5, 0xa05ca20a, 0x4b33cc31, 0xaa7684e3, 0x4119ead8, 0x573158c2, 0xbc5e36f9, 0x5d1b7e2b, 0xb6741010, 0xc3cae1af, 0x28a58f94, 0xc9e0c746, 0x228fa97d, 0x82a1038e, 0x69ce6db5, 0x888b2567, 0x63e44b5c, 0x165abae3, 0xfd35d4d8, 0x1c709c0a, 0xf71ff231, 0xe137402b, 0x0a582e10, 0xeb1d66c2, 0x007208f9, 0x75ccf946, 0x9ea3977d, 0x7fe6dfaf, 0x9489b194, 0xb60618e9, 0x5d6976d2, 0xbc2c3e00, 0x5743503b, 0x22fda184, 0xc992cfbf, 0x28d7876d, 0xc3b8e956, 0xd5905b4c, 0x3eff3577, 0xdfba7da5, 0x34d5139e, 0x416be221, 0xaa048c1a, 0x4b41c4c8, 0xa02eaaf3, 0x261d608a, 0xcd720eb1, 0x2c374663, 0xc7582858, 0xb2e6d9e7, 0x5989b7dc, 0xb8ccff0e, 0x53a39135, 0x458b232f, 0xaee44d14, 0x4fa105c6, 0xa4ce6bfd, 0xd1709a42, 0x3a1ff479, 0xdb5abcab, 0x3035d290, 0x12ba7bed, 0xf9d515d6, 0x18905d04, 0xf3ff333f, 0x8641c280, 0x6d2eacbb, 0x8c6be469, 0x67048a52, 0x712c3848, 0x9a435673, 0x7b061ea1, 0x9069709a, 0xe5d78125, 0x0eb8ef1e, 0xeffda7cc, 0x0492c9f7, 0xa4bc6304, 0x4fd30d3f, 0xae9645ed, 0x45f92bd6, 0x3047da69, 0xdb28b452, 0x3a6dfc80, 0xd10292bb, 0xc72a20a1, 0x2c454e9a, 0xcd000648, 0x266f6873, 0x53d199cc, 0xb8bef7f7, 0x59fbbf25, 0xb294d11e, 0x901b7863, 0x7b741658, 0x9a315e8a, 0x715e30b1, 0x04e0c10e, 0xef8faf35, 0x0ecae7e7, 0xe5a589dc, 0xf38d3bc6, 0x18e255fd, 0xf9a71d2f, 0x12c87314, 0x677682ab, 0x8c19ec90, 0x6d5ca442, 0x8633ca79, 0xcb60d85b, 0x200fb660, 0xc14afeb2, 0x2a259089, 0x5f9b6136, 0xb4f40f0d, 0x55b147df, 0xbede29e4, 0xa8f69bfe, 0x4399f5c5, 0xa2dcbd17, 0x49b3d32c, 0x3c0d2293, 0xd7624ca8, 0x3627047a, 0xdd486a41, 0xffc7c33c, 0x14a8ad07, 0xf5ede5d5, 0x1e828bee, 0x6b3c7a51, 0x8053146a, 0x61165cb8, 0x8a793283, 0x9c518099, 0x773eeea2, 0x967ba670, 0x7d14c84b, 0x08aa39f4, 0xe3c557cf, 0x02801f1d, 0xe9ef7126, 0x49c1dbd5, 0xa2aeb5ee, 0x43ebfd3c, 0xa8849307, 0xdd3a62b8, 0x36550c83, 0xd7104451, 0x3c7f2a6a, 0x2a579870, 0xc138f64b, 0x207dbe99, 0xcb12d0a2, 0xbeac211d, 0x55c34f26, 0xb48607f4, 0x5fe969cf, 0x7d66c0b2, 0x9609ae89, 0x774ce65b, 0x9c238860, 0xe99d79df, 0x02f217e4, 0xe3b75f36, 0x08d8310d, 0x1ef08317, 0xf59fed2c, 0x14daa5fe, 0xffb5cbc5, 0x8a0b3a7a, 0x61645441, 0x80211c93, 0x6b4e72a8, 0xed7db8d1, 0x0612d6ea, 0xe7579e38, 0x0c38f003, 0x798601bc, 0x92e96f87, 0x73ac2755, 0x98c3496e, 0x8eebfb74, 0x6584954f, 0x84c1dd9d, 0x6faeb3a6, 0x1a104219, 0xf17f2c22, 0x103a64f0, 0xfb550acb, 0xd9daa3b6, 0x32b5cd8d, 0xd3f0855f, 0x389feb64, 0x4d211adb, 0xa64e74e0, 0x470b3c32, 0xac645209, 0xba4ce013, 0x51238e28, 0xb066c6fa, 0x5b09a8c1, 0x2eb7597e, 0xc5d83745, 0x249d7f97, 0xcff211ac, 0x6fdcbb5f, 0x84b3d564, 0x65f69db6, 0x8e99f38d, 0xfb270232, 0x10486c09, 0xf10d24db, 0x1a624ae0, 0x0c4af8fa, 0xe72596c1, 0x0660de13, 0xed0fb028, 0x98b14197, 0x73de2fac, 0x929b677e, 0x79f40945, 0x5b7ba038, 0xb014ce03, 0x515186d1, 0xba3ee8ea, 0xcf801955, 0x24ef776e, 0xc5aa3fbc, 0x2ec55187, 0x38ede39d, 0xd3828da6, 0x32c7c574, 0xd9a8ab4f, 0xac165af0, 0x477934cb, 0xa63c7c19, 0x4d531222 +}, +{ +0x00000000, 0x165ec19c, 0xd60d37e4, 0xc053f678, 0x8498ce74, 0x92c60fe8, 0x5295f990, 0x44cb380c, 0x94224fca, 0x827c8e56, 0x422f782e, 0x5471b9b2, 0x10ba81be, 0x06e44022, 0xc6b7b65a, 0xd0e977c6, 0x490c8fa9, 0x5f524e35, 0x9f01b84d, 0x895f79d1, 0xcd9441dd, 0xdbca8041, 0x1b997639, 0x0dc7b7a5, 0xdd2ec063, 0xcb7001ff, 0x0b23f787, 0x1d7d361b, 0x59b60e17, 0x4fe8cf8b, 0x8fbb39f3, 0x99e5f86f, 0x27d8300f, 0x3186f193, 0xf1d507eb, 0xe78bc677, 0xa340fe7b, 0xb51e3fe7, 0x754dc99f, 0x63130803, 0xb3fa7fc5, 0xa5a4be59, 0x65f74821, 0x73a989bd, 0x3762b1b1, 0x213c702d, 0xe16f8655, 0xf73147c9, 0x6ed4bfa6, 0x788a7e3a, 0xb8d98842, 0xae8749de, 0xea4c71d2, 0xfc12b04e, 0x3c414636, 0x2a1f87aa, 0xfaf6f06c, 0xeca831f0, 0x2cfbc788, 0x3aa50614, 0x7e6e3e18, 0x6830ff84, 0xa86309fc, 0xbe3dc860, 0x54a2926f, 0x42fc53f3, 0x82afa58b, 0x94f16417, 0xd03a5c1b, 0xc6649d87, 0x06376bff, 0x1069aa63, 0xc080dda5, 0xd6de1c39, 0x168dea41, 0x00d32bdd, 0x441813d1, 0x5246d24d, 0x92152435, 0x844be5a9, 0x1dae1dc6, 0x0bf0dc5a, 0xcba32a22, 0xddfdebbe, 0x9936d3b2, 0x8f68122e, 0x4f3be456, 0x596525ca, 0x898c520c, 0x9fd29390, 0x5f8165e8, 0x49dfa474, 0x0d149c78, 0x1b4a5de4, 0xdb19ab9c, 0xcd476a00, 0x737aa260, 0x652463fc, 0xa5779584, 0xb3295418, 0xf7e26c14, 0xe1bcad88, 0x21ef5bf0, 0x37b19a6c, 0xe758edaa, 0xf1062c36, 0x3155da4e, 0x270b1bd2, 0x63c023de, 0x759ee242, 0xb5cd143a, 0xa393d5a6, 0x3a762dc9, 0x2c28ec55, 0xec7b1a2d, 0xfa25dbb1, 0xbeeee3bd, 0xa8b02221, 0x68e3d459, 0x7ebd15c5, 0xae546203, 0xb80aa39f, 0x785955e7, 0x6e07947b, 0x2accac77, 0x3c926deb, 0xfcc19b93, 0xea9f5a0f, 0x77113a4f, 0x614ffbd3, 0xa11c0dab, 0xb742cc37, 0xf389f43b, 0xe5d735a7, 0x2584c3df, 0x33da0243, 0xe3337585, 0xf56db419, 0x353e4261, 0x236083fd, 0x67abbbf1, 0x71f57a6d, 0xb1a68c15, 0xa7f84d89, 0x3e1db5e6, 0x2843747a, 0xe8108202, 0xfe4e439e, 0xba857b92, 0xacdbba0e, 0x6c884c76, 0x7ad68dea, 0xaa3ffa2c, 0xbc613bb0, 0x7c32cdc8, 0x6a6c0c54, 0x2ea73458, 0x38f9f5c4, 0xf8aa03bc, 0xeef4c220, 0x50c90a40, 0x4697cbdc, 0x86c43da4, 0x909afc38, 0xd451c434, 0xc20f05a8, 0x025cf3d0, 0x1402324c, 0xc4eb458a, 0xd2b58416, 0x12e6726e, 0x04b8b3f2, 0x40738bfe, 0x562d4a62, 0x967ebc1a, 0x80207d86, 0x19c585e9, 0x0f9b4475, 0xcfc8b20d, 0xd9967391, 0x9d5d4b9d, 0x8b038a01, 0x4b507c79, 0x5d0ebde5, 0x8de7ca23, 0x9bb90bbf, 0x5beafdc7, 0x4db43c5b, 0x097f0457, 0x1f21c5cb, 0xdf7233b3, 0xc92cf22f, 0x23b3a820, 0x35ed69bc, 0xf5be9fc4, 0xe3e05e58, 0xa72b6654, 0xb175a7c8, 0x712651b0, 0x6778902c, 0xb791e7ea, 0xa1cf2676, 0x619cd00e, 0x77c21192, 0x3309299e, 0x2557e802, 0xe5041e7a, 0xf35adfe6, 0x6abf2789, 0x7ce1e615, 0xbcb2106d, 0xaaecd1f1, 0xee27e9fd, 0xf8792861, 0x382ade19, 0x2e741f85, 0xfe9d6843, 0xe8c3a9df, 0x28905fa7, 0x3ece9e3b, 0x7a05a637, 0x6c5b67ab, 0xac0891d3, 0xba56504f, 0x046b982f, 0x123559b3, 0xd266afcb, 0xc4386e57, 0x80f3565b, 0x96ad97c7, 0x56fe61bf, 0x40a0a023, 0x9049d7e5, 0x86171679, 0x4644e001, 0x501a219d, 0x14d11991, 0x028fd80d, 0xc2dc2e75, 0xd482efe9, 0x4d671786, 0x5b39d61a, 0x9b6a2062, 0x8d34e1fe, 0xc9ffd9f2, 0xdfa1186e, 0x1ff2ee16, 0x09ac2f8a, 0xd945584c, 0xcf1b99d0, 0x0f486fa8, 0x1916ae34, 0x5ddd9638, 0x4b8357a4, 0x8bd0a1dc, 0x9d8e6040 +}, +{ +0x00000000, 0xe05589b9, 0x387844cf, 0xd82dcd76, 0xbe9d1c39, 0x5ec89580, 0x86e558f6, 0x66b0d14f, 0x8a688013, 0x6a3d09aa, 0xb210c4dc, 0x52454d65, 0x34f59c2a, 0xd4a01593, 0x0c8dd8e5, 0xecd8515c, 0x34caa641, 0xd49f2ff8, 0x0cb2e28e, 0xece76b37, 0x8a57ba78, 0x6a0233c1, 0xb22ffeb7, 0x527a770e, 0xbea22652, 0x5ef7afeb, 0x86da629d, 0x668feb24, 0x003f3a6b, 0xe06ab3d2, 0x38477ea4, 0xd812f71d, 0x388616dd, 0xd8d39f64, 0x00fe5212, 0xe0abdbab, 0x861b0ae4, 0x664e835d, 0xbe634e2b, 0x5e36c792, 0xb2ee96ce, 0x52bb1f77, 0x8a96d201, 0x6ac35bb8, 0x0c738af7, 0xec26034e, 0x340bce38, 0xd45e4781, 0x0c4cb09c, 0xec193925, 0x3434f453, 0xd4617dea, 0xb2d1aca5, 0x5284251c, 0x8aa9e86a, 0x6afc61d3, 0x8624308f, 0x6671b936, 0xbe5c7440, 0x5e09fdf9, 0x38b92cb6, 0xd8eca50f, 0x00c16879, 0xe094e1c0, 0xff9d0afb, 0x1fc88342, 0xc7e54e34, 0x27b0c78d, 0x410016c2, 0xa1559f7b, 0x7978520d, 0x992ddbb4, 0x75f58ae8, 0x95a00351, 0x4d8dce27, 0xadd8479e, 0xcb6896d1, 0x2b3d1f68, 0xf310d21e, 0x13455ba7, 0xcb57acba, 0x2b022503, 0xf32fe875, 0x137a61cc, 0x75cab083, 0x959f393a, 0x4db2f44c, 0xade77df5, 0x413f2ca9, 0xa16aa510, 0x79476866, 0x9912e1df, 0xffa23090, 0x1ff7b929, 0xc7da745f, 0x278ffde6, 0xc71b1c26, 0x274e959f, 0xff6358e9, 0x1f36d150, 0x7986001f, 0x99d389a6, 0x41fe44d0, 0xa1abcd69, 0x4d739c35, 0xad26158c, 0x750bd8fa, 0x955e5143, 0xf3ee800c, 0x13bb09b5, 0xcb96c4c3, 0x2bc34d7a, 0xf3d1ba67, 0x138433de, 0xcba9fea8, 0x2bfc7711, 0x4d4ca65e, 0xad192fe7, 0x7534e291, 0x95616b28, 0x79b93a74, 0x99ecb3cd, 0x41c17ebb, 0xa194f702, 0xc724264d, 0x2771aff4, 0xff5c6282, 0x1f09eb3b, 0xe0e0e9a3, 0x00b5601a, 0xd898ad6c, 0x38cd24d5, 0x5e7df59a, 0xbe287c23, 0x6605b155, 0x865038ec, 0x6a8869b0, 0x8adde009, 0x52f02d7f, 0xb2a5a4c6, 0xd4157589, 0x3440fc30, 0xec6d3146, 0x0c38b8ff, 0xd42a4fe2, 0x347fc65b, 0xec520b2d, 0x0c078294, 0x6ab753db, 0x8ae2da62, 0x52cf1714, 0xb29a9ead, 0x5e42cff1, 0xbe174648, 0x663a8b3e, 0x866f0287, 0xe0dfd3c8, 0x008a5a71, 0xd8a79707, 0x38f21ebe, 0xd866ff7e, 0x383376c7, 0xe01ebbb1, 0x004b3208, 0x66fbe347, 0x86ae6afe, 0x5e83a788, 0xbed62e31, 0x520e7f6d, 0xb25bf6d4, 0x6a763ba2, 0x8a23b21b, 0xec936354, 0x0cc6eaed, 0xd4eb279b, 0x34beae22, 0xecac593f, 0x0cf9d086, 0xd4d41df0, 0x34819449, 0x52314506, 0xb264ccbf, 0x6a4901c9, 0x8a1c8870, 0x66c4d92c, 0x86915095, 0x5ebc9de3, 0xbee9145a, 0xd859c515, 0x380c4cac, 0xe02181da, 0x00740863, 0x1f7de358, 0xff286ae1, 0x2705a797, 0xc7502e2e, 0xa1e0ff61, 0x41b576d8, 0x9998bbae, 0x79cd3217, 0x9515634b, 0x7540eaf2, 0xad6d2784, 0x4d38ae3d, 0x2b887f72, 0xcbddf6cb, 0x13f03bbd, 0xf3a5b204, 0x2bb74519, 0xcbe2cca0, 0x13cf01d6, 0xf39a886f, 0x952a5920, 0x757fd099, 0xad521def, 0x4d079456, 0xa1dfc50a, 0x418a4cb3, 0x99a781c5, 0x79f2087c, 0x1f42d933, 0xff17508a, 0x273a9dfc, 0xc76f1445, 0x27fbf585, 0xc7ae7c3c, 0x1f83b14a, 0xffd638f3, 0x9966e9bc, 0x79336005, 0xa11ead73, 0x414b24ca, 0xad937596, 0x4dc6fc2f, 0x95eb3159, 0x75beb8e0, 0x130e69af, 0xf35be016, 0x2b762d60, 0xcb23a4d9, 0x133153c4, 0xf364da7d, 0x2b49170b, 0xcb1c9eb2, 0xadac4ffd, 0x4df9c644, 0x95d40b32, 0x7581828b, 0x9959d3d7, 0x790c5a6e, 0xa1219718, 0x41741ea1, 0x27c4cfee, 0xc7914657, 0x1fbc8b21, 0xffe90298 +}, +{ +0x00000000, 0x7ab7d853, 0x55d6fd79, 0x2f61252a, 0xb8428791, 0xc2f55fc2, 0xed947ae8, 0x9723a2bb, 0xf577ef27, 0x8fc03774, 0xa0a1125e, 0xda16ca0d, 0x4d3568b6, 0x3782b0e5, 0x18e395cf, 0x62544d9c, 0x5be7005b, 0x2150d808, 0x0e31fd22, 0x74862571, 0xe3a587ca, 0x99125f99, 0xb6737ab3, 0xccc4a2e0, 0xae90ef7c, 0xd427372f, 0xfb461205, 0x81f1ca56, 0x16d268ed, 0x6c65b0be, 0x43049594, 0x39b34dc7, 0xd4610c05, 0xaed6d456, 0x81b7f17c, 0xfb00292f, 0x6c238b94, 0x169453c7, 0x39f576ed, 0x4342aebe, 0x2116e322, 0x5ba13b71, 0x74c01e5b, 0x0e77c608, 0x995464b3, 0xe3e3bce0, 0xcc8299ca, 0xb6354199, 0x8f860c5e, 0xf531d40d, 0xda50f127, 0xa0e72974, 0x37c48bcf, 0x4d73539c, 0x621276b6, 0x18a5aee5, 0x7af1e379, 0x00463b2a, 0x2f271e00, 0x5590c653, 0xc2b364e8, 0xb804bcbb, 0x97659991, 0xedd241c2, 0xba6542be, 0xc0d29aed, 0xefb3bfc7, 0x95046794, 0x0227c52f, 0x78901d7c, 0x57f13856, 0x2d46e005, 0x4f12ad99, 0x35a575ca, 0x1ac450e0, 0x607388b3, 0xf7502a08, 0x8de7f25b, 0xa286d771, 0xd8310f22, 0xe18242e5, 0x9b359ab6, 0xb454bf9c, 0xcee367cf, 0x59c0c574, 0x23771d27, 0x0c16380d, 0x76a1e05e, 0x14f5adc2, 0x6e427591, 0x412350bb, 0x3b9488e8, 0xacb72a53, 0xd600f200, 0xf961d72a, 0x83d60f79, 0x6e044ebb, 0x14b396e8, 0x3bd2b3c2, 0x41656b91, 0xd646c92a, 0xacf11179, 0x83903453, 0xf927ec00, 0x9b73a19c, 0xe1c479cf, 0xcea55ce5, 0xb41284b6, 0x2331260d, 0x5986fe5e, 0x76e7db74, 0x0c500327, 0x35e34ee0, 0x4f5496b3, 0x6035b399, 0x1a826bca, 0x8da1c971, 0xf7161122, 0xd8773408, 0xa2c0ec5b, 0xc094a1c7, 0xba237994, 0x95425cbe, 0xeff584ed, 0x78d62656, 0x0261fe05, 0x2d00db2f, 0x57b7037c, 0x42ca78db, 0x387da088, 0x171c85a2, 0x6dab5df1, 0xfa88ff4a, 0x803f2719, 0xaf5e0233, 0xd5e9da60, 0xb7bd97fc, 0xcd0a4faf, 0xe26b6a85, 0x98dcb2d6, 0x0fff106d, 0x7548c83e, 0x5a29ed14, 0x209e3547, 0x192d7880, 0x639aa0d3, 0x4cfb85f9, 0x364c5daa, 0xa16fff11, 0xdbd82742, 0xf4b90268, 0x8e0eda3b, 0xec5a97a7, 0x96ed4ff4, 0xb98c6ade, 0xc33bb28d, 0x54181036, 0x2eafc865, 0x01ceed4f, 0x7b79351c, 0x96ab74de, 0xec1cac8d, 0xc37d89a7, 0xb9ca51f4, 0x2ee9f34f, 0x545e2b1c, 0x7b3f0e36, 0x0188d665, 0x63dc9bf9, 0x196b43aa, 0x360a6680, 0x4cbdbed3, 0xdb9e1c68, 0xa129c43b, 0x8e48e111, 0xf4ff3942, 0xcd4c7485, 0xb7fbacd6, 0x989a89fc, 0xe22d51af, 0x750ef314, 0x0fb92b47, 0x20d80e6d, 0x5a6fd63e, 0x383b9ba2, 0x428c43f1, 0x6ded66db, 0x175abe88, 0x80791c33, 0xfacec460, 0xd5afe14a, 0xaf183919, 0xf8af3a65, 0x8218e236, 0xad79c71c, 0xd7ce1f4f, 0x40edbdf4, 0x3a5a65a7, 0x153b408d, 0x6f8c98de, 0x0dd8d542, 0x776f0d11, 0x580e283b, 0x22b9f068, 0xb59a52d3, 0xcf2d8a80, 0xe04cafaa, 0x9afb77f9, 0xa3483a3e, 0xd9ffe26d, 0xf69ec747, 0x8c291f14, 0x1b0abdaf, 0x61bd65fc, 0x4edc40d6, 0x346b9885, 0x563fd519, 0x2c880d4a, 0x03e92860, 0x795ef033, 0xee7d5288, 0x94ca8adb, 0xbbabaff1, 0xc11c77a2, 0x2cce3660, 0x5679ee33, 0x7918cb19, 0x03af134a, 0x948cb1f1, 0xee3b69a2, 0xc15a4c88, 0xbbed94db, 0xd9b9d947, 0xa30e0114, 0x8c6f243e, 0xf6d8fc6d, 0x61fb5ed6, 0x1b4c8685, 0x342da3af, 0x4e9a7bfc, 0x7729363b, 0x0d9eee68, 0x22ffcb42, 0x58481311, 0xcf6bb1aa, 0xb5dc69f9, 0x9abd4cd3, 0xe00a9480, 0x825ed91c, 0xf8e9014f, 0xd7882465, 0xad3ffc36, 0x3a1c5e8d, 0x40ab86de, 0x6fcaa3f4, 0x157d7ba7 +}, +{ +0x00000000, 0x9d104082, 0x13bf1e34, 0x8eaf5eb6, 0x96447dfa, 0x0b543d78, 0x85fb63ce, 0x18eb234c, 0xb395b6ee, 0x2e85f66c, 0xa02aa8da, 0x3d3ae858, 0x25d1cb14, 0xb8c18b96, 0x366ed520, 0xab7e95a2, 0x45d9abb4, 0xd8c9eb36, 0x5666b580, 0xcb76f502, 0xd39dd64e, 0x4e8d96cc, 0xc022c87a, 0x5d3288f8, 0xf64c1d5a, 0x6b5c5dd8, 0xe5f3036e, 0x78e343ec, 0x600860a0, 0xfd182022, 0x73b77e94, 0xeea73e16, 0x4ff8bd19, 0xd2e8fd9b, 0x5c47a32d, 0xc157e3af, 0xd9bcc0e3, 0x44ac8061, 0xca03ded7, 0x57139e55, 0xfc6d0bf7, 0x617d4b75, 0xefd215c3, 0x72c25541, 0x6a29760d, 0xf739368f, 0x79966839, 0xe48628bb, 0x0a2116ad, 0x9731562f, 0x199e0899, 0x848e481b, 0x9c656b57, 0x01752bd5, 0x8fda7563, 0x12ca35e1, 0xb9b4a043, 0x24a4e0c1, 0xaa0bbe77, 0x371bfef5, 0x2ff0ddb9, 0xb2e09d3b, 0x3c4fc38d, 0xa15f830f, 0x44c7b2d2, 0xd9d7f250, 0x5778ace6, 0xca68ec64, 0xd283cf28, 0x4f938faa, 0xc13cd11c, 0x5c2c919e, 0xf752043c, 0x6a4244be, 0xe4ed1a08, 0x79fd5a8a, 0x611679c6, 0xfc063944, 0x72a967f2, 0xefb92770, 0x011e1966, 0x9c0e59e4, 0x12a10752, 0x8fb147d0, 0x975a649c, 0x0a4a241e, 0x84e57aa8, 0x19f53a2a, 0xb28baf88, 0x2f9bef0a, 0xa134b1bc, 0x3c24f13e, 0x24cfd272, 0xb9df92f0, 0x3770cc46, 0xaa608cc4, 0x0b3f0fcb, 0x962f4f49, 0x188011ff, 0x8590517d, 0x9d7b7231, 0x006b32b3, 0x8ec46c05, 0x13d42c87, 0xb8aab925, 0x25baf9a7, 0xab15a711, 0x3605e793, 0x2eeec4df, 0xb3fe845d, 0x3d51daeb, 0xa0419a69, 0x4ee6a47f, 0xd3f6e4fd, 0x5d59ba4b, 0xc049fac9, 0xd8a2d985, 0x45b29907, 0xcb1dc7b1, 0x560d8733, 0xfd731291, 0x60635213, 0xeecc0ca5, 0x73dc4c27, 0x6b376f6b, 0xf6272fe9, 0x7888715f, 0xe59831dd, 0x11801a6e, 0x8c905aec, 0x023f045a, 0x9f2f44d8, 0x87c46794, 0x1ad42716, 0x947b79a0, 0x096b3922, 0xa215ac80, 0x3f05ec02, 0xb1aab2b4, 0x2cbaf236, 0x3451d17a, 0xa94191f8, 0x27eecf4e, 0xbafe8fcc, 0x5459b1da, 0xc949f158, 0x47e6afee, 0xdaf6ef6c, 0xc21dcc20, 0x5f0d8ca2, 0xd1a2d214, 0x4cb29296, 0xe7cc0734, 0x7adc47b6, 0xf4731900, 0x69635982, 0x71887ace, 0xec983a4c, 0x623764fa, 0xff272478, 0x5e78a777, 0xc368e7f5, 0x4dc7b943, 0xd0d7f9c1, 0xc83cda8d, 0x552c9a0f, 0xdb83c4b9, 0x4693843b, 0xeded1199, 0x70fd511b, 0xfe520fad, 0x63424f2f, 0x7ba96c63, 0xe6b92ce1, 0x68167257, 0xf50632d5, 0x1ba10cc3, 0x86b14c41, 0x081e12f7, 0x950e5275, 0x8de57139, 0x10f531bb, 0x9e5a6f0d, 0x034a2f8f, 0xa834ba2d, 0x3524faaf, 0xbb8ba419, 0x269be49b, 0x3e70c7d7, 0xa3608755, 0x2dcfd9e3, 0xb0df9961, 0x5547a8bc, 0xc857e83e, 0x46f8b688, 0xdbe8f60a, 0xc303d546, 0x5e1395c4, 0xd0bccb72, 0x4dac8bf0, 0xe6d21e52, 0x7bc25ed0, 0xf56d0066, 0x687d40e4, 0x709663a8, 0xed86232a, 0x63297d9c, 0xfe393d1e, 0x109e0308, 0x8d8e438a, 0x03211d3c, 0x9e315dbe, 0x86da7ef2, 0x1bca3e70, 0x956560c6, 0x08752044, 0xa30bb5e6, 0x3e1bf564, 0xb0b4abd2, 0x2da4eb50, 0x354fc81c, 0xa85f889e, 0x26f0d628, 0xbbe096aa, 0x1abf15a5, 0x87af5527, 0x09000b91, 0x94104b13, 0x8cfb685f, 0x11eb28dd, 0x9f44766b, 0x025436e9, 0xa92aa34b, 0x343ae3c9, 0xba95bd7f, 0x2785fdfd, 0x3f6edeb1, 0xa27e9e33, 0x2cd1c085, 0xb1c18007, 0x5f66be11, 0xc276fe93, 0x4cd9a025, 0xd1c9e0a7, 0xc922c3eb, 0x54328369, 0xda9ddddf, 0x478d9d5d, 0xecf308ff, 0x71e3487d, 0xff4c16cb, 0x625c5649, 0x7ab77505, 0xe7a73587, 0x69086b31, 0xf4182bb3 +}, +{ +0x00000000, 0x4ebfdec2, 0xad92a78a, 0xe32d7948, 0x9581c8b7, 0xdb3e1675, 0x38136f3d, 0x76acb1ff, 0x7e28c9c2, 0x30971700, 0xd3ba6e48, 0x9d05b08a, 0xeba90175, 0xa516dfb7, 0x463ba6ff, 0x0884783d, 0xd493e1eb, 0x9a2c3f29, 0x79014661, 0x37be98a3, 0x4112295c, 0x0fadf79e, 0xec808ed6, 0xa23f5014, 0xaabb2829, 0xe404f6eb, 0x07298fa3, 0x49965161, 0x3f3ae09e, 0x71853e5c, 0x92a84714, 0xdc1799d6, 0x90178645, 0xdea85887, 0x3d8521cf, 0x733aff0d, 0x05964ef2, 0x4b299030, 0xa804e978, 0xe6bb37ba, 0xee3f4f87, 0xa0809145, 0x43ade80d, 0x0d1236cf, 0x7bbe8730, 0x350159f2, 0xd62c20ba, 0x9893fe78, 0x448467ae, 0x0a3bb96c, 0xe916c024, 0xa7a91ee6, 0xd105af19, 0x9fba71db, 0x7c970893, 0x3228d651, 0x3aacae6c, 0x741370ae, 0x973e09e6, 0xd981d724, 0xaf2d66db, 0xe192b819, 0x02bfc151, 0x4c001f93, 0xe4e67816, 0xaa59a6d4, 0x4974df9c, 0x07cb015e, 0x7167b0a1, 0x3fd86e63, 0xdcf5172b, 0x924ac9e9, 0x9aceb1d4, 0xd4716f16, 0x375c165e, 0x79e3c89c, 0x0f4f7963, 0x41f0a7a1, 0xa2dddee9, 0xec62002b, 0x307599fd, 0x7eca473f, 0x9de73e77, 0xd358e0b5, 0xa5f4514a, 0xeb4b8f88, 0x0866f6c0, 0x46d92802, 0x4e5d503f, 0x00e28efd, 0xe3cff7b5, 0xad702977, 0xdbdc9888, 0x9563464a, 0x764e3f02, 0x38f1e1c0, 0x74f1fe53, 0x3a4e2091, 0xd96359d9, 0x97dc871b, 0xe17036e4, 0xafcfe826, 0x4ce2916e, 0x025d4fac, 0x0ad93791, 0x4466e953, 0xa74b901b, 0xe9f44ed9, 0x9f58ff26, 0xd1e721e4, 0x32ca58ac, 0x7c75866e, 0xa0621fb8, 0xeeddc17a, 0x0df0b832, 0x434f66f0, 0x35e3d70f, 0x7b5c09cd, 0x98717085, 0xd6ceae47, 0xde4ad67a, 0x90f508b8, 0x73d871f0, 0x3d67af32, 0x4bcb1ecd, 0x0574c00f, 0xe659b947, 0xa8e66785, 0xf56e5416, 0xbbd18ad4, 0x58fcf39c, 0x16432d5e, 0x60ef9ca1, 0x2e504263, 0xcd7d3b2b, 0x83c2e5e9, 0x8b469dd4, 0xc5f94316, 0x26d43a5e, 0x686be49c, 0x1ec75563, 0x50788ba1, 0xb355f2e9, 0xfdea2c2b, 0x21fdb5fd, 0x6f426b3f, 0x8c6f1277, 0xc2d0ccb5, 0xb47c7d4a, 0xfac3a388, 0x19eedac0, 0x57510402, 0x5fd57c3f, 0x116aa2fd, 0xf247dbb5, 0xbcf80577, 0xca54b488, 0x84eb6a4a, 0x67c61302, 0x2979cdc0, 0x6579d253, 0x2bc60c91, 0xc8eb75d9, 0x8654ab1b, 0xf0f81ae4, 0xbe47c426, 0x5d6abd6e, 0x13d563ac, 0x1b511b91, 0x55eec553, 0xb6c3bc1b, 0xf87c62d9, 0x8ed0d326, 0xc06f0de4, 0x234274ac, 0x6dfdaa6e, 0xb1ea33b8, 0xff55ed7a, 0x1c789432, 0x52c74af0, 0x246bfb0f, 0x6ad425cd, 0x89f95c85, 0xc7468247, 0xcfc2fa7a, 0x817d24b8, 0x62505df0, 0x2cef8332, 0x5a4332cd, 0x14fcec0f, 0xf7d19547, 0xb96e4b85, 0x11882c00, 0x5f37f2c2, 0xbc1a8b8a, 0xf2a55548, 0x8409e4b7, 0xcab63a75, 0x299b433d, 0x67249dff, 0x6fa0e5c2, 0x211f3b00, 0xc2324248, 0x8c8d9c8a, 0xfa212d75, 0xb49ef3b7, 0x57b38aff, 0x190c543d, 0xc51bcdeb, 0x8ba41329, 0x68896a61, 0x2636b4a3, 0x509a055c, 0x1e25db9e, 0xfd08a2d6, 0xb3b77c14, 0xbb330429, 0xf58cdaeb, 0x16a1a3a3, 0x581e7d61, 0x2eb2cc9e, 0x600d125c, 0x83206b14, 0xcd9fb5d6, 0x819faa45, 0xcf207487, 0x2c0d0dcf, 0x62b2d30d, 0x141e62f2, 0x5aa1bc30, 0xb98cc578, 0xf7331bba, 0xffb76387, 0xb108bd45, 0x5225c40d, 0x1c9a1acf, 0x6a36ab30, 0x248975f2, 0xc7a40cba, 0x891bd278, 0x550c4bae, 0x1bb3956c, 0xf89eec24, 0xb62132e6, 0xc08d8319, 0x8e325ddb, 0x6d1f2493, 0x23a0fa51, 0x2b24826c, 0x659b5cae, 0x86b625e6, 0xc809fb24, 0xbea54adb, 0xf01a9419, 0x1337ed51, 0x5d883393 +}, +{ +0x00000000, 0xba46a2bf, 0x9716814b, 0x2d5023f4, 0x1e4b4e58, 0xa40dece7, 0x895dcf13, 0x331b6dac, 0x882675cb, 0x3260d774, 0x1f30f480, 0xa576563f, 0x966d3b93, 0x2c2b992c, 0x017bbad8, 0xbb3d1867, 0x2177c26e, 0x9b3160d1, 0xb6614325, 0x0c27e19a, 0x3f3c8c36, 0x857a2e89, 0xa82a0d7d, 0x126cafc2, 0xa951b7a5, 0x1317151a, 0x3e4736ee, 0x84019451, 0xb71af9fd, 0x0d5c5b42, 0x200c78b6, 0x9a4ada09, 0xeba82d51, 0x51ee8fee, 0x7cbeac1a, 0xc6f80ea5, 0xf5e36309, 0x4fa5c1b6, 0x62f5e242, 0xd8b340fd, 0x638e589a, 0xd9c8fa25, 0xf498d9d1, 0x4ede7b6e, 0x7dc516c2, 0xc783b47d, 0xead39789, 0x50953536, 0xcadfef3f, 0x70994d80, 0x5dc96e74, 0xe78fcccb, 0xd494a167, 0x6ed203d8, 0x4382202c, 0xf9c48293, 0x42f99af4, 0xf8bf384b, 0xd5ef1bbf, 0x6fa9b900, 0x5cb2d4ac, 0xe6f47613, 0xcba455e7, 0x71e2f758, 0x1cffdccf, 0xa6b97e70, 0x8be95d84, 0x31afff3b, 0x02b49297, 0xb8f23028, 0x95a213dc, 0x2fe4b163, 0x94d9a904, 0x2e9f0bbb, 0x03cf284f, 0xb9898af0, 0x8a92e75c, 0x30d445e3, 0x1d846617, 0xa7c2c4a8, 0x3d881ea1, 0x87cebc1e, 0xaa9e9fea, 0x10d83d55, 0x23c350f9, 0x9985f246, 0xb4d5d1b2, 0x0e93730d, 0xb5ae6b6a, 0x0fe8c9d5, 0x22b8ea21, 0x98fe489e, 0xabe52532, 0x11a3878d, 0x3cf3a479, 0x86b506c6, 0xf757f19e, 0x4d115321, 0x604170d5, 0xda07d26a, 0xe91cbfc6, 0x535a1d79, 0x7e0a3e8d, 0xc44c9c32, 0x7f718455, 0xc53726ea, 0xe867051e, 0x5221a7a1, 0x613aca0d, 0xdb7c68b2, 0xf62c4b46, 0x4c6ae9f9, 0xd62033f0, 0x6c66914f, 0x4136b2bb, 0xfb701004, 0xc86b7da8, 0x722ddf17, 0x5f7dfce3, 0xe53b5e5c, 0x5e06463b, 0xe440e484, 0xc910c770, 0x735665cf, 0x404d0863, 0xfa0baadc, 0xd75b8928, 0x6d1d2b97, 0xa39e4968, 0x19d8ebd7, 0x3488c823, 0x8ece6a9c, 0xbdd50730, 0x0793a58f, 0x2ac3867b, 0x908524c4, 0x2bb83ca3, 0x91fe9e1c, 0xbcaebde8, 0x06e81f57, 0x35f372fb, 0x8fb5d044, 0xa2e5f3b0, 0x18a3510f, 0x82e98b06, 0x38af29b9, 0x15ff0a4d, 0xafb9a8f2, 0x9ca2c55e, 0x26e467e1, 0x0bb44415, 0xb1f2e6aa, 0x0acffecd, 0xb0895c72, 0x9dd97f86, 0x279fdd39, 0x1484b095, 0xaec2122a, 0x839231de, 0x39d49361, 0x48366439, 0xf270c686, 0xdf20e572, 0x656647cd, 0x567d2a61, 0xec3b88de, 0xc16bab2a, 0x7b2d0995, 0xc01011f2, 0x7a56b34d, 0x570690b9, 0xed403206, 0xde5b5faa, 0x641dfd15, 0x494ddee1, 0xf30b7c5e, 0x6941a657, 0xd30704e8, 0xfe57271c, 0x441185a3, 0x770ae80f, 0xcd4c4ab0, 0xe01c6944, 0x5a5acbfb, 0xe167d39c, 0x5b217123, 0x767152d7, 0xcc37f068, 0xff2c9dc4, 0x456a3f7b, 0x683a1c8f, 0xd27cbe30, 0xbf6195a7, 0x05273718, 0x287714ec, 0x9231b653, 0xa12adbff, 0x1b6c7940, 0x363c5ab4, 0x8c7af80b, 0x3747e06c, 0x8d0142d3, 0xa0516127, 0x1a17c398, 0x290cae34, 0x934a0c8b, 0xbe1a2f7f, 0x045c8dc0, 0x9e1657c9, 0x2450f576, 0x0900d682, 0xb346743d, 0x805d1991, 0x3a1bbb2e, 0x174b98da, 0xad0d3a65, 0x16302202, 0xac7680bd, 0x8126a349, 0x3b6001f6, 0x087b6c5a, 0xb23dcee5, 0x9f6ded11, 0x252b4fae, 0x54c9b8f6, 0xee8f1a49, 0xc3df39bd, 0x79999b02, 0x4a82f6ae, 0xf0c45411, 0xdd9477e5, 0x67d2d55a, 0xdcefcd3d, 0x66a96f82, 0x4bf94c76, 0xf1bfeec9, 0xc2a48365, 0x78e221da, 0x55b2022e, 0xeff4a091, 0x75be7a98, 0xcff8d827, 0xe2a8fbd3, 0x58ee596c, 0x6bf534c0, 0xd1b3967f, 0xfce3b58b, 0x46a51734, 0xfd980f53, 0x47deadec, 0x6a8e8e18, 0xd0c82ca7, 0xe3d3410b, 0x5995e3b4, 0x74c5c040, 0xce8362ff +}, +{ +0x00000000, 0x97e7412b, 0x442795f3, 0xd3c0d4d8, 0x7ced353f, 0xeb0a7414, 0x38caa0cc, 0xaf2de1e7, 0x11535cc4, 0x86b41def, 0x5574c937, 0xc293881c, 0x6dbe69fb, 0xfa5928d0, 0x2999fc08, 0xbe7ebd23, 0xe6bd986d, 0x715ad946, 0xa29a0d9e, 0x357d4cb5, 0x9a50ad52, 0x0db7ec79, 0xde7738a1, 0x4990798a, 0xf7eec4a9, 0x60098582, 0xb3c9515a, 0x242e1071, 0x8b03f196, 0x1ce4b0bd, 0xcf246465, 0x58c3254e, 0x50d620c0, 0xc73161eb, 0x14f1b533, 0x8316f418, 0x2c3b15ff, 0xbbdc54d4, 0x681c800c, 0xfffbc127, 0x41857c04, 0xd6623d2f, 0x05a2e9f7, 0x9245a8dc, 0x3d68493b, 0xaa8f0810, 0x794fdcc8, 0xeea89de3, 0xb66bb8ad, 0x218cf986, 0xf24c2d5e, 0x65ab6c75, 0xca868d92, 0x5d61ccb9, 0x8ea11861, 0x1946594a, 0xa738e469, 0x30dfa542, 0xe31f719a, 0x74f830b1, 0xdbd5d156, 0x4c32907d, 0x9ff244a5, 0x0815058e, 0xd8c1a7e3, 0x4f26e6c8, 0x9ce63210, 0x0b01733b, 0xa42c92dc, 0x33cbd3f7, 0xe00b072f, 0x77ec4604, 0xc992fb27, 0x5e75ba0c, 0x8db56ed4, 0x1a522fff, 0xb57fce18, 0x22988f33, 0xf1585beb, 0x66bf1ac0, 0x3e7c3f8e, 0xa99b7ea5, 0x7a5baa7d, 0xedbceb56, 0x42910ab1, 0xd5764b9a, 0x06b69f42, 0x9151de69, 0x2f2f634a, 0xb8c82261, 0x6b08f6b9, 0xfcefb792, 0x53c25675, 0xc425175e, 0x17e5c386, 0x800282ad, 0x88178723, 0x1ff0c608, 0xcc3012d0, 0x5bd753fb, 0xf4fab21c, 0x631df337, 0xb0dd27ef, 0x273a66c4, 0x9944dbe7, 0x0ea39acc, 0xdd634e14, 0x4a840f3f, 0xe5a9eed8, 0x724eaff3, 0xa18e7b2b, 0x36693a00, 0x6eaa1f4e, 0xf94d5e65, 0x2a8d8abd, 0xbd6acb96, 0x12472a71, 0x85a06b5a, 0x5660bf82, 0xc187fea9, 0x7ff9438a, 0xe81e02a1, 0x3bded679, 0xac399752, 0x031476b5, 0x94f3379e, 0x4733e346, 0xd0d4a26d, 0xf9b5d7f1, 0x6e5296da, 0xbd924202, 0x2a750329, 0x8558e2ce, 0x12bfa3e5, 0xc17f773d, 0x56983616, 0xe8e68b35, 0x7f01ca1e, 0xacc11ec6, 0x3b265fed, 0x940bbe0a, 0x03ecff21, 0xd02c2bf9, 0x47cb6ad2, 0x1f084f9c, 0x88ef0eb7, 0x5b2fda6f, 0xccc89b44, 0x63e57aa3, 0xf4023b88, 0x27c2ef50, 0xb025ae7b, 0x0e5b1358, 0x99bc5273, 0x4a7c86ab, 0xdd9bc780, 0x72b62667, 0xe551674c, 0x3691b394, 0xa176f2bf, 0xa963f731, 0x3e84b61a, 0xed4462c2, 0x7aa323e9, 0xd58ec20e, 0x42698325, 0x91a957fd, 0x064e16d6, 0xb830abf5, 0x2fd7eade, 0xfc173e06, 0x6bf07f2d, 0xc4dd9eca, 0x533adfe1, 0x80fa0b39, 0x171d4a12, 0x4fde6f5c, 0xd8392e77, 0x0bf9faaf, 0x9c1ebb84, 0x33335a63, 0xa4d41b48, 0x7714cf90, 0xe0f38ebb, 0x5e8d3398, 0xc96a72b3, 0x1aaaa66b, 0x8d4de740, 0x226006a7, 0xb587478c, 0x66479354, 0xf1a0d27f, 0x21747012, 0xb6933139, 0x6553e5e1, 0xf2b4a4ca, 0x5d99452d, 0xca7e0406, 0x19bed0de, 0x8e5991f5, 0x30272cd6, 0xa7c06dfd, 0x7400b925, 0xe3e7f80e, 0x4cca19e9, 0xdb2d58c2, 0x08ed8c1a, 0x9f0acd31, 0xc7c9e87f, 0x502ea954, 0x83ee7d8c, 0x14093ca7, 0xbb24dd40, 0x2cc39c6b, 0xff0348b3, 0x68e40998, 0xd69ab4bb, 0x417df590, 0x92bd2148, 0x055a6063, 0xaa778184, 0x3d90c0af, 0xee501477, 0x79b7555c, 0x71a250d2, 0xe64511f9, 0x3585c521, 0xa262840a, 0x0d4f65ed, 0x9aa824c6, 0x4968f01e, 0xde8fb135, 0x60f10c16, 0xf7164d3d, 0x24d699e5, 0xb331d8ce, 0x1c1c3929, 0x8bfb7802, 0x583bacda, 0xcfdcedf1, 0x971fc8bf, 0x00f88994, 0xd3385d4c, 0x44df1c67, 0xebf2fd80, 0x7c15bcab, 0xafd56873, 0x38322958, 0x864c947b, 0x11abd550, 0xc26b0188, 0x558c40a3, 0xfaa1a144, 0x6d46e06f, 0xbe8634b7, 0x2961759c +}, +{ +0x00000000, 0xaad31662, 0x1857cc36, 0xb284da54, 0x091863be, 0xa3cb75dc, 0x114faf88, 0xbb9cb9ea, 0x2346851d, 0x8995937f, 0x3b11492b, 0x91c25f49, 0x2a5ee6a3, 0x808df0c1, 0x32092a95, 0x98da3cf7, 0xc2e9dd9a, 0x683acbf8, 0xdabe11ac, 0x706d07ce, 0xcbf1be24, 0x6122a846, 0xd3a67212, 0x79756470, 0xe1af5887, 0x4b7c4ee5, 0xf9f894b1, 0x532b82d3, 0xe8b73b39, 0x42642d5b, 0xf0e0f70f, 0x5a33e16d, 0x61a69a0a, 0xcb758c68, 0x79f1563c, 0xd322405e, 0x68bef9b4, 0xc26defd6, 0x70e93582, 0xda3a23e0, 0x42e01f17, 0xe8330975, 0x5ab7d321, 0xf064c543, 0x4bf87ca9, 0xe12b6acb, 0x53afb09f, 0xf97ca6fd, 0xa34f4790, 0x099c51f2, 0xbb188ba6, 0x11cb9dc4, 0xaa57242e, 0x0084324c, 0xb200e818, 0x18d3fe7a, 0x8009c28d, 0x2adad4ef, 0x985e0ebb, 0x328d18d9, 0x8911a133, 0x23c2b751, 0x91466d05, 0x3b957b67, 0x99d49f7a, 0x33078918, 0x8183534c, 0x2b50452e, 0x90ccfcc4, 0x3a1feaa6, 0x889b30f2, 0x22482690, 0xba921a67, 0x10410c05, 0xa2c5d651, 0x0816c033, 0xb38a79d9, 0x19596fbb, 0xabddb5ef, 0x010ea38d, 0x5b3d42e0, 0xf1ee5482, 0x436a8ed6, 0xe9b998b4, 0x5225215e, 0xf8f6373c, 0x4a72ed68, 0xe0a1fb0a, 0x787bc7fd, 0xd2a8d19f, 0x602c0bcb, 0xcaff1da9, 0x7163a443, 0xdbb0b221, 0x69346875, 0xc3e77e17, 0xf8720570, 0x52a11312, 0xe025c946, 0x4af6df24, 0xf16a66ce, 0x5bb970ac, 0xe93daaf8, 0x43eebc9a, 0xdb34806d, 0x71e7960f, 0xc3634c5b, 0x69b05a39, 0xd22ce3d3, 0x78fff5b1, 0xca7b2fe5, 0x60a83987, 0x3a9bd8ea, 0x9048ce88, 0x22cc14dc, 0x881f02be, 0x3383bb54, 0x9950ad36, 0x2bd47762, 0x81076100, 0x19dd5df7, 0xb30e4b95, 0x018a91c1, 0xab5987a3, 0x10c53e49, 0xba16282b, 0x0892f27f, 0xa241e41d, 0x583719db, 0xf2e40fb9, 0x4060d5ed, 0xeab3c38f, 0x512f7a65, 0xfbfc6c07, 0x4978b653, 0xe3aba031, 0x7b719cc6, 0xd1a28aa4, 0x632650f0, 0xc9f54692, 0x7269ff78, 0xd8bae91a, 0x6a3e334e, 0xc0ed252c, 0x9adec441, 0x300dd223, 0x82890877, 0x285a1e15, 0x93c6a7ff, 0x3915b19d, 0x8b916bc9, 0x21427dab, 0xb998415c, 0x134b573e, 0xa1cf8d6a, 0x0b1c9b08, 0xb08022e2, 0x1a533480, 0xa8d7eed4, 0x0204f8b6, 0x399183d1, 0x934295b3, 0x21c64fe7, 0x8b155985, 0x3089e06f, 0x9a5af60d, 0x28de2c59, 0x820d3a3b, 0x1ad706cc, 0xb00410ae, 0x0280cafa, 0xa853dc98, 0x13cf6572, 0xb91c7310, 0x0b98a944, 0xa14bbf26, 0xfb785e4b, 0x51ab4829, 0xe32f927d, 0x49fc841f, 0xf2603df5, 0x58b32b97, 0xea37f1c3, 0x40e4e7a1, 0xd83edb56, 0x72edcd34, 0xc0691760, 0x6aba0102, 0xd126b8e8, 0x7bf5ae8a, 0xc97174de, 0x63a262bc, 0xc1e386a1, 0x6b3090c3, 0xd9b44a97, 0x73675cf5, 0xc8fbe51f, 0x6228f37d, 0xd0ac2929, 0x7a7f3f4b, 0xe2a503bc, 0x487615de, 0xfaf2cf8a, 0x5021d9e8, 0xebbd6002, 0x416e7660, 0xf3eaac34, 0x5939ba56, 0x030a5b3b, 0xa9d94d59, 0x1b5d970d, 0xb18e816f, 0x0a123885, 0xa0c12ee7, 0x1245f4b3, 0xb896e2d1, 0x204cde26, 0x8a9fc844, 0x381b1210, 0x92c80472, 0x2954bd98, 0x8387abfa, 0x310371ae, 0x9bd067cc, 0xa0451cab, 0x0a960ac9, 0xb812d09d, 0x12c1c6ff, 0xa95d7f15, 0x038e6977, 0xb10ab323, 0x1bd9a541, 0x830399b6, 0x29d08fd4, 0x9b545580, 0x318743e2, 0x8a1bfa08, 0x20c8ec6a, 0x924c363e, 0x389f205c, 0x62acc131, 0xc87fd753, 0x7afb0d07, 0xd0281b65, 0x6bb4a28f, 0xc167b4ed, 0x73e36eb9, 0xd93078db, 0x41ea442c, 0xeb39524e, 0x59bd881a, 0xf36e9e78, 0x48f22792, 0xe22131f0, 0x50a5eba4, 0xfa76fdc6 +}, +{ +0x00000000, 0x6bac9626, 0x4688c351, 0x2d245577, 0x212c6bdb, 0x4a80fdfd, 0x67a4a88a, 0x0c083eac, 0xe1677bf1, 0x8acbedd7, 0xa7efb8a0, 0xcc432e86, 0xc04b102a, 0xabe7860c, 0x86c3d37b, 0xed6f455d, 0x0c8819cc, 0x67248fea, 0x4a00da9d, 0x21ac4cbb, 0x2da47217, 0x4608e431, 0x6b2cb146, 0x00802760, 0xedef623d, 0x8643f41b, 0xab67a16c, 0xc0cb374a, 0xccc309e6, 0xa76f9fc0, 0x8a4bcab7, 0xe1e75c91, 0x944baa43, 0xffe73c65, 0xd2c36912, 0xb96fff34, 0xb567c198, 0xdecb57be, 0xf3ef02c9, 0x984394ef, 0x752cd1b2, 0x1e804794, 0x33a412e3, 0x580884c5, 0x5400ba69, 0x3fac2c4f, 0x12887938, 0x7924ef1e, 0x98c3b38f, 0xf36f25a9, 0xde4b70de, 0xb5e7e6f8, 0xb9efd854, 0xd2434e72, 0xff671b05, 0x94cb8d23, 0x79a4c87e, 0x12085e58, 0x3f2c0b2f, 0x54809d09, 0x5888a3a5, 0x33243583, 0x1e0060f4, 0x75acf6d2, 0xfcb69078, 0x971a065e, 0xba3e5329, 0xd192c50f, 0xdd9afba3, 0xb6366d85, 0x9b1238f2, 0xf0beaed4, 0x1dd1eb89, 0x767d7daf, 0x5b5928d8, 0x30f5befe, 0x3cfd8052, 0x57511674, 0x7a754303, 0x11d9d525, 0xf03e89b4, 0x9b921f92, 0xb6b64ae5, 0xdd1adcc3, 0xd112e26f, 0xbabe7449, 0x979a213e, 0xfc36b718, 0x1159f245, 0x7af56463, 0x57d13114, 0x3c7da732, 0x3075999e, 0x5bd90fb8, 0x76fd5acf, 0x1d51cce9, 0x68fd3a3b, 0x0351ac1d, 0x2e75f96a, 0x45d96f4c, 0x49d151e0, 0x227dc7c6, 0x0f5992b1, 0x64f50497, 0x899a41ca, 0xe236d7ec, 0xcf12829b, 0xa4be14bd, 0xa8b62a11, 0xc31abc37, 0xee3ee940, 0x85927f66, 0x647523f7, 0x0fd9b5d1, 0x22fde0a6, 0x49517680, 0x4559482c, 0x2ef5de0a, 0x03d18b7d, 0x687d1d5b, 0x85125806, 0xeebece20, 0xc39a9b57, 0xa8360d71, 0xa43e33dd, 0xcf92a5fb, 0xe2b6f08c, 0x891a66aa, 0x9a310048, 0xf19d966e, 0xdcb9c319, 0xb715553f, 0xbb1d6b93, 0xd0b1fdb5, 0xfd95a8c2, 0x96393ee4, 0x7b567bb9, 0x10faed9f, 0x3ddeb8e8, 0x56722ece, 0x5a7a1062, 0x31d68644, 0x1cf2d333, 0x775e4515, 0x96b91984, 0xfd158fa2, 0xd031dad5, 0xbb9d4cf3, 0xb795725f, 0xdc39e479, 0xf11db10e, 0x9ab12728, 0x77de6275, 0x1c72f453, 0x3156a124, 0x5afa3702, 0x56f209ae, 0x3d5e9f88, 0x107acaff, 0x7bd65cd9, 0x0e7aaa0b, 0x65d63c2d, 0x48f2695a, 0x235eff7c, 0x2f56c1d0, 0x44fa57f6, 0x69de0281, 0x027294a7, 0xef1dd1fa, 0x84b147dc, 0xa99512ab, 0xc239848d, 0xce31ba21, 0xa59d2c07, 0x88b97970, 0xe315ef56, 0x02f2b3c7, 0x695e25e1, 0x447a7096, 0x2fd6e6b0, 0x23ded81c, 0x48724e3a, 0x65561b4d, 0x0efa8d6b, 0xe395c836, 0x88395e10, 0xa51d0b67, 0xceb19d41, 0xc2b9a3ed, 0xa91535cb, 0x843160bc, 0xef9df69a, 0x66879030, 0x0d2b0616, 0x200f5361, 0x4ba3c547, 0x47abfbeb, 0x2c076dcd, 0x012338ba, 0x6a8fae9c, 0x87e0ebc1, 0xec4c7de7, 0xc1682890, 0xaac4beb6, 0xa6cc801a, 0xcd60163c, 0xe044434b, 0x8be8d56d, 0x6a0f89fc, 0x01a31fda, 0x2c874aad, 0x472bdc8b, 0x4b23e227, 0x208f7401, 0x0dab2176, 0x6607b750, 0x8b68f20d, 0xe0c4642b, 0xcde0315c, 0xa64ca77a, 0xaa4499d6, 0xc1e80ff0, 0xeccc5a87, 0x8760cca1, 0xf2cc3a73, 0x9960ac55, 0xb444f922, 0xdfe86f04, 0xd3e051a8, 0xb84cc78e, 0x956892f9, 0xfec404df, 0x13ab4182, 0x7807d7a4, 0x552382d3, 0x3e8f14f5, 0x32872a59, 0x592bbc7f, 0x740fe908, 0x1fa37f2e, 0xfe4423bf, 0x95e8b599, 0xb8cce0ee, 0xd36076c8, 0xdf684864, 0xb4c4de42, 0x99e08b35, 0xf24c1d13, 0x1f23584e, 0x748fce68, 0x59ab9b1f, 0x32070d39, 0x3e0f3395, 0x55a3a5b3, 0x7887f0c4, 0x132b66e2 +}, +{ +0x00000000, 0xd654515f, 0x290c48cf, 0xff581990, 0x09d5a5c4, 0xdf81f49b, 0x20d9ed0b, 0xf68dbc54, 0x1dfb4960, 0xcbaf183f, 0x34f701af, 0xe2a350f0, 0x142eeca4, 0xc27abdfb, 0x3d22a46b, 0xeb76f534, 0x0e41214b, 0xd8157014, 0x274d6984, 0xf11938db, 0x0794848f, 0xd1c0d5d0, 0x2e98cc40, 0xf8cc9d1f, 0x13ba682b, 0xc5ee3974, 0x3ab620e4, 0xece271bb, 0x1a6fcdef, 0xcc3b9cb0, 0x33638520, 0xe537d47f, 0xa7766dc2, 0x71223c9d, 0x8e7a250d, 0x582e7452, 0xaea3c806, 0x78f79959, 0x87af80c9, 0x51fbd196, 0xba8d24a2, 0x6cd975fd, 0x93816c6d, 0x45d53d32, 0xb3588166, 0x650cd039, 0x9a54c9a9, 0x4c0098f6, 0xa9374c89, 0x7f631dd6, 0x803b0446, 0x566f5519, 0xa0e2e94d, 0x76b6b812, 0x89eea182, 0x5fbaf0dd, 0xb4cc05e9, 0x629854b6, 0x9dc04d26, 0x4b941c79, 0xbd19a02d, 0x6b4df172, 0x9415e8e2, 0x4241b9bd, 0x72dbd6b0, 0xa48f87ef, 0x5bd79e7f, 0x8d83cf20, 0x7b0e7374, 0xad5a222b, 0x52023bbb, 0x84566ae4, 0x6f209fd0, 0xb974ce8f, 0x462cd71f, 0x90788640, 0x66f53a14, 0xb0a16b4b, 0x4ff972db, 0x99ad2384, 0x7c9af7fb, 0xaacea6a4, 0x5596bf34, 0x83c2ee6b, 0x754f523f, 0xa31b0360, 0x5c431af0, 0x8a174baf, 0x6161be9b, 0xb735efc4, 0x486df654, 0x9e39a70b, 0x68b41b5f, 0xbee04a00, 0x41b85390, 0x97ec02cf, 0xd5adbb72, 0x03f9ea2d, 0xfca1f3bd, 0x2af5a2e2, 0xdc781eb6, 0x0a2c4fe9, 0xf5745679, 0x23200726, 0xc856f212, 0x1e02a34d, 0xe15abadd, 0x370eeb82, 0xc18357d6, 0x17d70689, 0xe88f1f19, 0x3edb4e46, 0xdbec9a39, 0x0db8cb66, 0xf2e0d2f6, 0x24b483a9, 0xd2393ffd, 0x046d6ea2, 0xfb357732, 0x2d61266d, 0xc617d359, 0x10438206, 0xef1b9b96, 0x394fcac9, 0xcfc2769d, 0x199627c2, 0xe6ce3e52, 0x309a6f0d, 0x3d1dacec, 0xeb49fdb3, 0x1411e423, 0xc245b57c, 0x34c80928, 0xe29c5877, 0x1dc441e7, 0xcb9010b8, 0x20e6e58c, 0xf6b2b4d3, 0x09eaad43, 0xdfbefc1c, 0x29334048, 0xff671117, 0x003f0887, 0xd66b59d8, 0x335c8da7, 0xe508dcf8, 0x1a50c568, 0xcc049437, 0x3a892863, 0xecdd793c, 0x138560ac, 0xc5d131f3, 0x2ea7c4c7, 0xf8f39598, 0x07ab8c08, 0xd1ffdd57, 0x27726103, 0xf126305c, 0x0e7e29cc, 0xd82a7893, 0x9a6bc12e, 0x4c3f9071, 0xb36789e1, 0x6533d8be, 0x93be64ea, 0x45ea35b5, 0xbab22c25, 0x6ce67d7a, 0x8790884e, 0x51c4d911, 0xae9cc081, 0x78c891de, 0x8e452d8a, 0x58117cd5, 0xa7496545, 0x711d341a, 0x942ae065, 0x427eb13a, 0xbd26a8aa, 0x6b72f9f5, 0x9dff45a1, 0x4bab14fe, 0xb4f30d6e, 0x62a75c31, 0x89d1a905, 0x5f85f85a, 0xa0dde1ca, 0x7689b095, 0x80040cc1, 0x56505d9e, 0xa908440e, 0x7f5c1551, 0x4fc67a5c, 0x99922b03, 0x66ca3293, 0xb09e63cc, 0x4613df98, 0x90478ec7, 0x6f1f9757, 0xb94bc608, 0x523d333c, 0x84696263, 0x7b317bf3, 0xad652aac, 0x5be896f8, 0x8dbcc7a7, 0x72e4de37, 0xa4b08f68, 0x41875b17, 0x97d30a48, 0x688b13d8, 0xbedf4287, 0x4852fed3, 0x9e06af8c, 0x615eb61c, 0xb70ae743, 0x5c7c1277, 0x8a284328, 0x75705ab8, 0xa3240be7, 0x55a9b7b3, 0x83fde6ec, 0x7ca5ff7c, 0xaaf1ae23, 0xe8b0179e, 0x3ee446c1, 0xc1bc5f51, 0x17e80e0e, 0xe165b25a, 0x3731e305, 0xc869fa95, 0x1e3dabca, 0xf54b5efe, 0x231f0fa1, 0xdc471631, 0x0a13476e, 0xfc9efb3a, 0x2acaaa65, 0xd592b3f5, 0x03c6e2aa, 0xe6f136d5, 0x30a5678a, 0xcffd7e1a, 0x19a92f45, 0xef249311, 0x3970c24e, 0xc628dbde, 0x107c8a81, 0xfb0a7fb5, 0x2d5e2eea, 0xd206377a, 0x04526625, 0xf2dfda71, 0x248b8b2e, 0xdbd392be, 0x0d87c3e1 +}, +{ +0x00000000, 0x71f31b0e, 0x501fb247, 0x21eca949, 0x489a73ad, 0x396968a3, 0x1885c1ea, 0x6976dae4, 0xe78e4615, 0x967d5d1b, 0xb791f452, 0xc662ef5c, 0xaf1435b8, 0xdee72eb6, 0xff0b87ff, 0x8ef89cf1, 0xf1e47e6b, 0x80176565, 0xa1fbcc2c, 0xd008d722, 0xb97e0dc6, 0xc88d16c8, 0xe961bf81, 0x9892a48f, 0x166a387e, 0x67992370, 0x46758a39, 0x37869137, 0x5ef04bd3, 0x2f0350dd, 0x0eeff994, 0x7f1ce29a, 0x8a9a7105, 0xfb696a0b, 0xda85c342, 0xab76d84c, 0xc20002a8, 0xb3f319a6, 0x921fb0ef, 0xe3ecabe1, 0x6d143710, 0x1ce72c1e, 0x3d0b8557, 0x4cf89e59, 0x258e44bd, 0x547d5fb3, 0x7591f6fa, 0x0462edf4, 0x7b7e0f6e, 0x0a8d1460, 0x2b61bd29, 0x5a92a627, 0x33e47cc3, 0x421767cd, 0x63fbce84, 0x1208d58a, 0x9cf0497b, 0xed035275, 0xcceffb3c, 0xbd1ce032, 0xd46a3ad6, 0xa59921d8, 0x84758891, 0xf586939f, 0x57b62cf2, 0x264537fc, 0x07a99eb5, 0x765a85bb, 0x1f2c5f5f, 0x6edf4451, 0x4f33ed18, 0x3ec0f616, 0xb0386ae7, 0xc1cb71e9, 0xe027d8a0, 0x91d4c3ae, 0xf8a2194a, 0x89510244, 0xa8bdab0d, 0xd94eb003, 0xa6525299, 0xd7a14997, 0xf64de0de, 0x87befbd0, 0xeec82134, 0x9f3b3a3a, 0xbed79373, 0xcf24887d, 0x41dc148c, 0x302f0f82, 0x11c3a6cb, 0x6030bdc5, 0x09466721, 0x78b57c2f, 0x5959d566, 0x28aace68, 0xdd2c5df7, 0xacdf46f9, 0x8d33efb0, 0xfcc0f4be, 0x95b62e5a, 0xe4453554, 0xc5a99c1d, 0xb45a8713, 0x3aa21be2, 0x4b5100ec, 0x6abda9a5, 0x1b4eb2ab, 0x7238684f, 0x03cb7341, 0x2227da08, 0x53d4c106, 0x2cc8239c, 0x5d3b3892, 0x7cd791db, 0x0d248ad5, 0x64525031, 0x15a14b3f, 0x344de276, 0x45bef978, 0xcb466589, 0xbab57e87, 0x9b59d7ce, 0xeaaaccc0, 0x83dc1624, 0xf22f0d2a, 0xd3c3a463, 0xa230bf6d, 0xbb081c78, 0xcafb0776, 0xeb17ae3f, 0x9ae4b531, 0xf3926fd5, 0x826174db, 0xa38ddd92, 0xd27ec69c, 0x5c865a6d, 0x2d754163, 0x0c99e82a, 0x7d6af324, 0x141c29c0, 0x65ef32ce, 0x44039b87, 0x35f08089, 0x4aec6213, 0x3b1f791d, 0x1af3d054, 0x6b00cb5a, 0x027611be, 0x73850ab0, 0x5269a3f9, 0x239ab8f7, 0xad622406, 0xdc913f08, 0xfd7d9641, 0x8c8e8d4f, 0xe5f857ab, 0x940b4ca5, 0xb5e7e5ec, 0xc414fee2, 0x31926d7d, 0x40617673, 0x618ddf3a, 0x107ec434, 0x79081ed0, 0x08fb05de, 0x2917ac97, 0x58e4b799, 0xd61c2b68, 0xa7ef3066, 0x8603992f, 0xf7f08221, 0x9e8658c5, 0xef7543cb, 0xce99ea82, 0xbf6af18c, 0xc0761316, 0xb1850818, 0x9069a151, 0xe19aba5f, 0x88ec60bb, 0xf91f7bb5, 0xd8f3d2fc, 0xa900c9f2, 0x27f85503, 0x560b4e0d, 0x77e7e744, 0x0614fc4a, 0x6f6226ae, 0x1e913da0, 0x3f7d94e9, 0x4e8e8fe7, 0xecbe308a, 0x9d4d2b84, 0xbca182cd, 0xcd5299c3, 0xa4244327, 0xd5d75829, 0xf43bf160, 0x85c8ea6e, 0x0b30769f, 0x7ac36d91, 0x5b2fc4d8, 0x2adcdfd6, 0x43aa0532, 0x32591e3c, 0x13b5b775, 0x6246ac7b, 0x1d5a4ee1, 0x6ca955ef, 0x4d45fca6, 0x3cb6e7a8, 0x55c03d4c, 0x24332642, 0x05df8f0b, 0x742c9405, 0xfad408f4, 0x8b2713fa, 0xaacbbab3, 0xdb38a1bd, 0xb24e7b59, 0xc3bd6057, 0xe251c91e, 0x93a2d210, 0x6624418f, 0x17d75a81, 0x363bf3c8, 0x47c8e8c6, 0x2ebe3222, 0x5f4d292c, 0x7ea18065, 0x0f529b6b, 0x81aa079a, 0xf0591c94, 0xd1b5b5dd, 0xa046aed3, 0xc9307437, 0xb8c36f39, 0x992fc670, 0xe8dcdd7e, 0x97c03fe4, 0xe63324ea, 0xc7df8da3, 0xb62c96ad, 0xdf5a4c49, 0xaea95747, 0x8f45fe0e, 0xfeb6e500, 0x704e79f1, 0x01bd62ff, 0x2051cbb6, 0x51a2d0b8, 0x38d40a5c, 0x49271152, 0x68cbb81b, 0x1938a315 +}, +{ +0x00000000, 0x38fbfbd1, 0x23fd0c9f, 0x1b06f74e, 0xa23781ac, 0x9acc7a7d, 0x81ca8d33, 0xb93176e2, 0x1d80e692, 0x257b1d43, 0x3e7dea0d, 0x068611dc, 0xbfb7673e, 0x874c9cef, 0x9c4a6ba1, 0xa4b19070, 0xac6723f0, 0x949cd821, 0x8f9a2f6f, 0xb761d4be, 0x0e50a25c, 0x36ab598d, 0x2dadaec3, 0x15565512, 0xb1e7c562, 0x891c3eb3, 0x921ac9fd, 0xaae1322c, 0x13d044ce, 0x2b2bbf1f, 0x302d4851, 0x08d6b380, 0x05b4820c, 0x3d4f79dd, 0x26498e93, 0x1eb27542, 0xa78303a0, 0x9f78f871, 0x847e0f3f, 0xbc85f4ee, 0x1834649e, 0x20cf9f4f, 0x3bc96801, 0x033293d0, 0xba03e532, 0x82f81ee3, 0x99fee9ad, 0xa105127c, 0xa9d3a1fc, 0x91285a2d, 0x8a2ead63, 0xb2d556b2, 0x0be42050, 0x331fdb81, 0x28192ccf, 0x10e2d71e, 0xb453476e, 0x8ca8bcbf, 0x97ae4bf1, 0xaf55b020, 0x1664c6c2, 0x2e9f3d13, 0x3599ca5d, 0x0d62318c, 0xf46c38fc, 0xcc97c32d, 0xd7913463, 0xef6acfb2, 0x565bb950, 0x6ea04281, 0x75a6b5cf, 0x4d5d4e1e, 0xe9ecde6e, 0xd11725bf, 0xca11d2f1, 0xf2ea2920, 0x4bdb5fc2, 0x7320a413, 0x6826535d, 0x50dda88c, 0x580b1b0c, 0x60f0e0dd, 0x7bf61793, 0x430dec42, 0xfa3c9aa0, 0xc2c76171, 0xd9c1963f, 0xe13a6dee, 0x458bfd9e, 0x7d70064f, 0x6676f101, 0x5e8d0ad0, 0xe7bc7c32, 0xdf4787e3, 0xc44170ad, 0xfcba8b7c, 0xf1d8baf0, 0xc9234121, 0xd225b66f, 0xeade4dbe, 0x53ef3b5c, 0x6b14c08d, 0x701237c3, 0x48e9cc12, 0xec585c62, 0xd4a3a7b3, 0xcfa550fd, 0xf75eab2c, 0x4e6fddce, 0x7694261f, 0x6d92d151, 0x55692a80, 0x5dbf9900, 0x654462d1, 0x7e42959f, 0x46b96e4e, 0xff8818ac, 0xc773e37d, 0xdc751433, 0xe48eefe2, 0x403f7f92, 0x78c48443, 0x63c2730d, 0x5b3988dc, 0xe208fe3e, 0xdaf305ef, 0xc1f5f2a1, 0xf90e0970, 0xe41dbdb6, 0xdce64667, 0xc7e0b129, 0xff1b4af8, 0x462a3c1a, 0x7ed1c7cb, 0x65d73085, 0x5d2ccb54, 0xf99d5b24, 0xc166a0f5, 0xda6057bb, 0xe29bac6a, 0x5baada88, 0x63512159, 0x7857d617, 0x40ac2dc6, 0x487a9e46, 0x70816597, 0x6b8792d9, 0x537c6908, 0xea4d1fea, 0xd2b6e43b, 0xc9b01375, 0xf14be8a4, 0x55fa78d4, 0x6d018305, 0x7607744b, 0x4efc8f9a, 0xf7cdf978, 0xcf3602a9, 0xd430f5e7, 0xeccb0e36, 0xe1a93fba, 0xd952c46b, 0xc2543325, 0xfaafc8f4, 0x439ebe16, 0x7b6545c7, 0x6063b289, 0x58984958, 0xfc29d928, 0xc4d222f9, 0xdfd4d5b7, 0xe72f2e66, 0x5e1e5884, 0x66e5a355, 0x7de3541b, 0x4518afca, 0x4dce1c4a, 0x7535e79b, 0x6e3310d5, 0x56c8eb04, 0xeff99de6, 0xd7026637, 0xcc049179, 0xf4ff6aa8, 0x504efad8, 0x68b50109, 0x73b3f647, 0x4b480d96, 0xf2797b74, 0xca8280a5, 0xd18477eb, 0xe97f8c3a, 0x1071854a, 0x288a7e9b, 0x338c89d5, 0x0b777204, 0xb24604e6, 0x8abdff37, 0x91bb0879, 0xa940f3a8, 0x0df163d8, 0x350a9809, 0x2e0c6f47, 0x16f79496, 0xafc6e274, 0x973d19a5, 0x8c3beeeb, 0xb4c0153a, 0xbc16a6ba, 0x84ed5d6b, 0x9febaa25, 0xa71051f4, 0x1e212716, 0x26dadcc7, 0x3ddc2b89, 0x0527d058, 0xa1964028, 0x996dbbf9, 0x826b4cb7, 0xba90b766, 0x03a1c184, 0x3b5a3a55, 0x205ccd1b, 0x18a736ca, 0x15c50746, 0x2d3efc97, 0x36380bd9, 0x0ec3f008, 0xb7f286ea, 0x8f097d3b, 0x940f8a75, 0xacf471a4, 0x0845e1d4, 0x30be1a05, 0x2bb8ed4b, 0x1343169a, 0xaa726078, 0x92899ba9, 0x898f6ce7, 0xb1749736, 0xb9a224b6, 0x8159df67, 0x9a5f2829, 0xa2a4d3f8, 0x1b95a51a, 0x236e5ecb, 0x3868a985, 0x00935254, 0xa422c224, 0x9cd939f5, 0x87dfcebb, 0xbf24356a, 0x06154388, 0x3eeeb859, 0x25e84f17, 0x1d13b4c6 +}, +{ +0x00000000, 0x3298b96c, 0xd42391ea, 0xe6bb2886, 0xa7ae6cf0, 0x9536d59c, 0x738dfd1a, 0x41154476, 0xa0d13790, 0x92498efc, 0x74f2a67a, 0x466a1f16, 0x077f5b60, 0x35e7e20c, 0xd35cca8a, 0xe1c473e6, 0x60ae286d, 0x52369101, 0xb48db987, 0x861500eb, 0xc700449d, 0xf598fdf1, 0x1323d577, 0x21bb6c1b, 0xc07f1ffd, 0xf2e7a691, 0x145c8e17, 0x26c4377b, 0x67d1730d, 0x5549ca61, 0xb3f2e2e7, 0x816a5b8b, 0xba3e7ff9, 0x88a6c695, 0x6e1dee13, 0x5c85577f, 0x1d901309, 0x2f08aa65, 0xc9b382e3, 0xfb2b3b8f, 0x1aef4869, 0x2877f105, 0xceccd983, 0xfc5460ef, 0xbd412499, 0x8fd99df5, 0x6962b573, 0x5bfa0c1f, 0xda905794, 0xe808eef8, 0x0eb3c67e, 0x3c2b7f12, 0x7d3e3b64, 0x4fa68208, 0xa91daa8e, 0x9b8513e2, 0x7a416004, 0x48d9d968, 0xae62f1ee, 0x9cfa4882, 0xddef0cf4, 0xef77b598, 0x09cc9d1e, 0x3b542472, 0x8a8cbb7f, 0xb8140213, 0x5eaf2a95, 0x6c3793f9, 0x2d22d78f, 0x1fba6ee3, 0xf9014665, 0xcb99ff09, 0x2a5d8cef, 0x18c53583, 0xfe7e1d05, 0xcce6a469, 0x8df3e01f, 0xbf6b5973, 0x59d071f5, 0x6b48c899, 0xea229312, 0xd8ba2a7e, 0x3e0102f8, 0x0c99bb94, 0x4d8cffe2, 0x7f14468e, 0x99af6e08, 0xab37d764, 0x4af3a482, 0x786b1dee, 0x9ed03568, 0xac488c04, 0xed5dc872, 0xdfc5711e, 0x397e5998, 0x0be6e0f4, 0x30b2c486, 0x022a7dea, 0xe491556c, 0xd609ec00, 0x971ca876, 0xa584111a, 0x433f399c, 0x71a780f0, 0x9063f316, 0xa2fb4a7a, 0x444062fc, 0x76d8db90, 0x37cd9fe6, 0x0555268a, 0xe3ee0e0c, 0xd176b760, 0x501ceceb, 0x62845587, 0x843f7d01, 0xb6a7c46d, 0xf7b2801b, 0xc52a3977, 0x239111f1, 0x1109a89d, 0xf0cddb7b, 0xc2556217, 0x24ee4a91, 0x1676f3fd, 0x5763b78b, 0x65fb0ee7, 0x83402661, 0xb1d89f0d, 0xe4689db3, 0xd6f024df, 0x304b0c59, 0x02d3b535, 0x43c6f143, 0x715e482f, 0x97e560a9, 0xa57dd9c5, 0x44b9aa23, 0x7621134f, 0x909a3bc9, 0xa20282a5, 0xe317c6d3, 0xd18f7fbf, 0x37345739, 0x05acee55, 0x84c6b5de, 0xb65e0cb2, 0x50e52434, 0x627d9d58, 0x2368d92e, 0x11f06042, 0xf74b48c4, 0xc5d3f1a8, 0x2417824e, 0x168f3b22, 0xf03413a4, 0xc2acaac8, 0x83b9eebe, 0xb12157d2, 0x579a7f54, 0x6502c638, 0x5e56e24a, 0x6cce5b26, 0x8a7573a0, 0xb8edcacc, 0xf9f88eba, 0xcb6037d6, 0x2ddb1f50, 0x1f43a63c, 0xfe87d5da, 0xcc1f6cb6, 0x2aa44430, 0x183cfd5c, 0x5929b92a, 0x6bb10046, 0x8d0a28c0, 0xbf9291ac, 0x3ef8ca27, 0x0c60734b, 0xeadb5bcd, 0xd843e2a1, 0x9956a6d7, 0xabce1fbb, 0x4d75373d, 0x7fed8e51, 0x9e29fdb7, 0xacb144db, 0x4a0a6c5d, 0x7892d531, 0x39879147, 0x0b1f282b, 0xeda400ad, 0xdf3cb9c1, 0x6ee426cc, 0x5c7c9fa0, 0xbac7b726, 0x885f0e4a, 0xc94a4a3c, 0xfbd2f350, 0x1d69dbd6, 0x2ff162ba, 0xce35115c, 0xfcada830, 0x1a1680b6, 0x288e39da, 0x699b7dac, 0x5b03c4c0, 0xbdb8ec46, 0x8f20552a, 0x0e4a0ea1, 0x3cd2b7cd, 0xda699f4b, 0xe8f12627, 0xa9e46251, 0x9b7cdb3d, 0x7dc7f3bb, 0x4f5f4ad7, 0xae9b3931, 0x9c03805d, 0x7ab8a8db, 0x482011b7, 0x093555c1, 0x3badecad, 0xdd16c42b, 0xef8e7d47, 0xd4da5935, 0xe642e059, 0x00f9c8df, 0x326171b3, 0x737435c5, 0x41ec8ca9, 0xa757a42f, 0x95cf1d43, 0x740b6ea5, 0x4693d7c9, 0xa028ff4f, 0x92b04623, 0xd3a50255, 0xe13dbb39, 0x078693bf, 0x351e2ad3, 0xb4747158, 0x86ecc834, 0x6057e0b2, 0x52cf59de, 0x13da1da8, 0x2142a4c4, 0xc7f98c42, 0xf561352e, 0x14a546c8, 0x263dffa4, 0xc086d722, 0xf21e6e4e, 0xb30b2a38, 0x81939354, 0x6728bbd2, 0x55b002be +} +}, +{ +{ +0x00000000, 0x8e7ee481, 0x8711c961, 0x096f2de0, 0x7116729f, 0xff68961e, 0xf607bbfe, 0x78795f7f, 0x14017b1f, 0x9a7f9f9e, 0x9310b27e, 0x1d6e56ff, 0x65170980, 0xeb69ed01, 0xe206c0e1, 0x6c782460, 0xda3fb929, 0x54415da8, 0x5d2e7048, 0xd35094c9, 0xab29cbb6, 0x25572f37, 0x2c3802d7, 0xa246e656, 0xce3ec236, 0x404026b7, 0x492f0b57, 0xc751efd6, 0xbf28b0a9, 0x31565428, 0x383979c8, 0xb6479d49, 0xc3d8a94a, 0x4da64dcb, 0x44c9602b, 0xcab784aa, 0xb2cedbd5, 0x3cb03f54, 0x35df12b4, 0xbba1f635, 0xd7d9d255, 0x59a736d4, 0x50c81b34, 0xdeb6ffb5, 0xa6cfa0ca, 0x28b1444b, 0x21de69ab, 0xafa08d2a, 0x19e71063, 0x9799f4e2, 0x9ef6d902, 0x10883d83, 0x68f162fc, 0xe68f867d, 0xefe0ab9d, 0x619e4f1c, 0x0de66b7c, 0x83988ffd, 0x8af7a21d, 0x0489469c, 0x7cf019e3, 0xf28efd62, 0xfbe1d082, 0x759f3403, 0xd6ffbe19, 0x58815a98, 0x51ee7778, 0xdf9093f9, 0xa7e9cc86, 0x29972807, 0x20f805e7, 0xae86e166, 0xc2fec506, 0x4c802187, 0x45ef0c67, 0xcb91e8e6, 0xb3e8b799, 0x3d965318, 0x34f97ef8, 0xba879a79, 0x0cc00730, 0x82bee3b1, 0x8bd1ce51, 0x05af2ad0, 0x7dd675af, 0xf3a8912e, 0xfac7bcce, 0x74b9584f, 0x18c17c2f, 0x96bf98ae, 0x9fd0b54e, 0x11ae51cf, 0x69d70eb0, 0xe7a9ea31, 0xeec6c7d1, 0x60b82350, 0x15271753, 0x9b59f3d2, 0x9236de32, 0x1c483ab3, 0x643165cc, 0xea4f814d, 0xe320acad, 0x6d5e482c, 0x01266c4c, 0x8f5888cd, 0x8637a52d, 0x084941ac, 0x70301ed3, 0xfe4efa52, 0xf721d7b2, 0x795f3333, 0xcf18ae7a, 0x41664afb, 0x4809671b, 0xc677839a, 0xbe0edce5, 0x30703864, 0x391f1584, 0xb761f105, 0xdb19d565, 0x556731e4, 0x5c081c04, 0xd276f885, 0xaa0fa7fa, 0x2471437b, 0x2d1e6e9b, 0xa3608a1a, 0x89f36a52, 0x078d8ed3, 0x0ee2a333, 0x809c47b2, 0xf8e518cd, 0x769bfc4c, 0x7ff4d1ac, 0xf18a352d, 0x9df2114d, 0x138cf5cc, 0x1ae3d82c, 0x949d3cad, 0xece463d2, 0x629a8753, 0x6bf5aab3, 0xe58b4e32, 0x53ccd37b, 0xddb237fa, 0xd4dd1a1a, 0x5aa3fe9b, 0x22daa1e4, 0xaca44565, 0xa5cb6885, 0x2bb58c04, 0x47cda864, 0xc9b34ce5, 0xc0dc6105, 0x4ea28584, 0x36dbdafb, 0xb8a53e7a, 0xb1ca139a, 0x3fb4f71b, 0x4a2bc318, 0xc4552799, 0xcd3a0a79, 0x4344eef8, 0x3b3db187, 0xb5435506, 0xbc2c78e6, 0x32529c67, 0x5e2ab807, 0xd0545c86, 0xd93b7166, 0x574595e7, 0x2f3cca98, 0xa1422e19, 0xa82d03f9, 0x2653e778, 0x90147a31, 0x1e6a9eb0, 0x1705b350, 0x997b57d1, 0xe10208ae, 0x6f7cec2f, 0x6613c1cf, 0xe86d254e, 0x8415012e, 0x0a6be5af, 0x0304c84f, 0x8d7a2cce, 0xf50373b1, 0x7b7d9730, 0x7212bad0, 0xfc6c5e51, 0x5f0cd44b, 0xd17230ca, 0xd81d1d2a, 0x5663f9ab, 0x2e1aa6d4, 0xa0644255, 0xa90b6fb5, 0x27758b34, 0x4b0daf54, 0xc5734bd5, 0xcc1c6635, 0x426282b4, 0x3a1bddcb, 0xb465394a, 0xbd0a14aa, 0x3374f02b, 0x85336d62, 0x0b4d89e3, 0x0222a403, 0x8c5c4082, 0xf4251ffd, 0x7a5bfb7c, 0x7334d69c, 0xfd4a321d, 0x9132167d, 0x1f4cf2fc, 0x1623df1c, 0x985d3b9d, 0xe02464e2, 0x6e5a8063, 0x6735ad83, 0xe94b4902, 0x9cd47d01, 0x12aa9980, 0x1bc5b460, 0x95bb50e1, 0xedc20f9e, 0x63bceb1f, 0x6ad3c6ff, 0xe4ad227e, 0x88d5061e, 0x06abe29f, 0x0fc4cf7f, 0x81ba2bfe, 0xf9c37481, 0x77bd9000, 0x7ed2bde0, 0xf0ac5961, 0x46ebc428, 0xc89520a9, 0xc1fa0d49, 0x4f84e9c8, 0x37fdb6b7, 0xb9835236, 0xb0ec7fd6, 0x3e929b57, 0x52eabf37, 0xdc945bb6, 0xd5fb7656, 0x5b8592d7, 0x23fccda8, 0xad822929, 0xa4ed04c9, 0x2a93e048 +}, +{ +0x00000000, 0x09d3516b, 0xe5225dc6, 0xecf10cad, 0x09a16148, 0x00723023, 0xec833c8e, 0xe5506de5, 0xbd5485c2, 0xb487d4a9, 0x5876d804, 0x51a5896f, 0xb4f5e48a, 0xbd26b5e1, 0x51d7b94c, 0x5804e827, 0x37acefea, 0x3e7fbe81, 0xd28eb22c, 0xdb5de347, 0x3e0d8ea2, 0x37dedfc9, 0xdb2fd364, 0xd2fc820f, 0x8af86a28, 0x832b3b43, 0x6fda37ee, 0x66096685, 0x83590b60, 0x8a8a5a0b, 0x667b56a6, 0x6fa807cd, 0x0765a5fb, 0x0eb6f490, 0xe247f83d, 0xeb94a956, 0x0ec4c4b3, 0x071795d8, 0xebe69975, 0xe235c81e, 0xba312039, 0xb3e27152, 0x5f137dff, 0x56c02c94, 0xb3904171, 0xba43101a, 0x56b21cb7, 0x5f614ddc, 0x30c94a11, 0x391a1b7a, 0xd5eb17d7, 0xdc3846bc, 0x39682b59, 0x30bb7a32, 0xdc4a769f, 0xd59927f4, 0x8d9dcfd3, 0x844e9eb8, 0x68bf9215, 0x616cc37e, 0x843cae9b, 0x8deffff0, 0x611ef35d, 0x68cda236, 0x01aed038, 0x087d8153, 0xe48c8dfe, 0xed5fdc95, 0x080fb170, 0x01dce01b, 0xed2decb6, 0xe4febddd, 0xbcfa55fa, 0xb5290491, 0x59d8083c, 0x500b5957, 0xb55b34b2, 0xbc8865d9, 0x50796974, 0x59aa381f, 0x36023fd2, 0x3fd16eb9, 0xd3206214, 0xdaf3337f, 0x3fa35e9a, 0x36700ff1, 0xda81035c, 0xd3525237, 0x8b56ba10, 0x8285eb7b, 0x6e74e7d6, 0x67a7b6bd, 0x82f7db58, 0x8b248a33, 0x67d5869e, 0x6e06d7f5, 0x06cb75c3, 0x0f1824a8, 0xe3e92805, 0xea3a796e, 0x0f6a148b, 0x06b945e0, 0xea48494d, 0xe39b1826, 0xbb9ff001, 0xb24ca16a, 0x5ebdadc7, 0x576efcac, 0xb23e9149, 0xbbedc022, 0x571ccc8f, 0x5ecf9de4, 0x31679a29, 0x38b4cb42, 0xd445c7ef, 0xdd969684, 0x38c6fb61, 0x3115aa0a, 0xdde4a6a7, 0xd437f7cc, 0x8c331feb, 0x85e04e80, 0x6911422d, 0x60c21346, 0x85927ea3, 0x8c412fc8, 0x60b02365, 0x6963720e, 0xeda4ce74, 0xe4779f1f, 0x088693b2, 0x0155c2d9, 0xe405af3c, 0xedd6fe57, 0x0127f2fa, 0x08f4a391, 0x50f04bb6, 0x59231add, 0xb5d21670, 0xbc01471b, 0x59512afe, 0x50827b95, 0xbc737738, 0xb5a02653, 0xda08219e, 0xd3db70f5, 0x3f2a7c58, 0x36f92d33, 0xd3a940d6, 0xda7a11bd, 0x368b1d10, 0x3f584c7b, 0x675ca45c, 0x6e8ff537, 0x827ef99a, 0x8bada8f1, 0x6efdc514, 0x672e947f, 0x8bdf98d2, 0x820cc9b9, 0xeac16b8f, 0xe3123ae4, 0x0fe33649, 0x06306722, 0xe3600ac7, 0xeab35bac, 0x06425701, 0x0f91066a, 0x5795ee4d, 0x5e46bf26, 0xb2b7b38b, 0xbb64e2e0, 0x5e348f05, 0x57e7de6e, 0xbb16d2c3, 0xb2c583a8, 0xdd6d8465, 0xd4bed50e, 0x384fd9a3, 0x319c88c8, 0xd4cce52d, 0xdd1fb446, 0x31eeb8eb, 0x383de980, 0x603901a7, 0x69ea50cc, 0x851b5c61, 0x8cc80d0a, 0x699860ef, 0x604b3184, 0x8cba3d29, 0x85696c42, 0xec0a1e4c, 0xe5d94f27, 0x0928438a, 0x00fb12e1, 0xe5ab7f04, 0xec782e6f, 0x008922c2, 0x095a73a9, 0x515e9b8e, 0x588dcae5, 0xb47cc648, 0xbdaf9723, 0x58fffac6, 0x512cabad, 0xbddda700, 0xb40ef66b, 0xdba6f1a6, 0xd275a0cd, 0x3e84ac60, 0x3757fd0b, 0xd20790ee, 0xdbd4c185, 0x3725cd28, 0x3ef69c43, 0x66f27464, 0x6f21250f, 0x83d029a2, 0x8a0378c9, 0x6f53152c, 0x66804447, 0x8a7148ea, 0x83a21981, 0xeb6fbbb7, 0xe2bceadc, 0x0e4de671, 0x079eb71a, 0xe2cedaff, 0xeb1d8b94, 0x07ec8739, 0x0e3fd652, 0x563b3e75, 0x5fe86f1e, 0xb31963b3, 0xbaca32d8, 0x5f9a5f3d, 0x56490e56, 0xbab802fb, 0xb36b5390, 0xdcc3545d, 0xd5100536, 0x39e1099b, 0x303258f0, 0xd5623515, 0xdcb1647e, 0x304068d3, 0x399339b8, 0x6197d19f, 0x684480f4, 0x84b58c59, 0x8d66dd32, 0x6836b0d7, 0x61e5e1bc, 0x8d14ed11, 0x84c7bc7a +}, +{ +0x00000000, 0x238c92cf, 0x5b985d46, 0x7814cf89, 0x48c459ca, 0x6b48cb05, 0x135c048c, 0x30d09643, 0x45e84365, 0x6664d1aa, 0x1e701e23, 0x3dfc8cec, 0x0d2c1aaf, 0x2ea08860, 0x56b447e9, 0x7538d526, 0x7031e80a, 0x53bd7ac5, 0x2ba9b54c, 0x08252783, 0x38f5b1c0, 0x1b79230f, 0x636dec86, 0x40e17e49, 0x35d9ab6f, 0x165539a0, 0x6e41f629, 0x4dcd64e6, 0x7d1df2a5, 0x5e91606a, 0x2685afe3, 0x05093d2c, 0xb61c6001, 0x9590f2ce, 0xed843d47, 0xce08af88, 0xfed839cb, 0xdd54ab04, 0xa540648d, 0x86ccf642, 0xf3f42364, 0xd078b1ab, 0xa86c7e22, 0x8be0eced, 0xbb307aae, 0x98bce861, 0xe0a827e8, 0xc324b527, 0xc62d880b, 0xe5a11ac4, 0x9db5d54d, 0xbe394782, 0x8ee9d1c1, 0xad65430e, 0xd5718c87, 0xf6fd1e48, 0x83c5cb6e, 0xa04959a1, 0xd85d9628, 0xfbd104e7, 0xcb0192a4, 0xe88d006b, 0x9099cfe2, 0xb3155d2d, 0x32e70522, 0x116b97ed, 0x697f5864, 0x4af3caab, 0x7a235ce8, 0x59afce27, 0x21bb01ae, 0x02379361, 0x770f4647, 0x5483d488, 0x2c971b01, 0x0f1b89ce, 0x3fcb1f8d, 0x1c478d42, 0x645342cb, 0x47dfd004, 0x42d6ed28, 0x615a7fe7, 0x194eb06e, 0x3ac222a1, 0x0a12b4e2, 0x299e262d, 0x518ae9a4, 0x72067b6b, 0x073eae4d, 0x24b23c82, 0x5ca6f30b, 0x7f2a61c4, 0x4ffaf787, 0x6c766548, 0x1462aac1, 0x37ee380e, 0x84fb6523, 0xa777f7ec, 0xdf633865, 0xfcefaaaa, 0xcc3f3ce9, 0xefb3ae26, 0x97a761af, 0xb42bf360, 0xc1132646, 0xe29fb489, 0x9a8b7b00, 0xb907e9cf, 0x89d77f8c, 0xaa5bed43, 0xd24f22ca, 0xf1c3b005, 0xf4ca8d29, 0xd7461fe6, 0xaf52d06f, 0x8cde42a0, 0xbc0ed4e3, 0x9f82462c, 0xe79689a5, 0xc41a1b6a, 0xb122ce4c, 0x92ae5c83, 0xeaba930a, 0xc93601c5, 0xf9e69786, 0xda6a0549, 0xa27ecac0, 0x81f2580f, 0x0cb9857c, 0x2f3517b3, 0x5721d83a, 0x74ad4af5, 0x447ddcb6, 0x67f14e79, 0x1fe581f0, 0x3c69133f, 0x4951c619, 0x6add54d6, 0x12c99b5f, 0x31450990, 0x01959fd3, 0x22190d1c, 0x5a0dc295, 0x7981505a, 0x7c886d76, 0x5f04ffb9, 0x27103030, 0x049ca2ff, 0x344c34bc, 0x17c0a673, 0x6fd469fa, 0x4c58fb35, 0x39602e13, 0x1aecbcdc, 0x62f87355, 0x4174e19a, 0x71a477d9, 0x5228e516, 0x2a3c2a9f, 0x09b0b850, 0xbaa5e57d, 0x992977b2, 0xe13db83b, 0xc2b12af4, 0xf261bcb7, 0xd1ed2e78, 0xa9f9e1f1, 0x8a75733e, 0xff4da618, 0xdcc134d7, 0xa4d5fb5e, 0x87596991, 0xb789ffd2, 0x94056d1d, 0xec11a294, 0xcf9d305b, 0xca940d77, 0xe9189fb8, 0x910c5031, 0xb280c2fe, 0x825054bd, 0xa1dcc672, 0xd9c809fb, 0xfa449b34, 0x8f7c4e12, 0xacf0dcdd, 0xd4e41354, 0xf768819b, 0xc7b817d8, 0xe4348517, 0x9c204a9e, 0xbfacd851, 0x3e5e805e, 0x1dd21291, 0x65c6dd18, 0x464a4fd7, 0x769ad994, 0x55164b5b, 0x2d0284d2, 0x0e8e161d, 0x7bb6c33b, 0x583a51f4, 0x202e9e7d, 0x03a20cb2, 0x33729af1, 0x10fe083e, 0x68eac7b7, 0x4b665578, 0x4e6f6854, 0x6de3fa9b, 0x15f73512, 0x367ba7dd, 0x06ab319e, 0x2527a351, 0x5d336cd8, 0x7ebffe17, 0x0b872b31, 0x280bb9fe, 0x501f7677, 0x7393e4b8, 0x434372fb, 0x60cfe034, 0x18db2fbd, 0x3b57bd72, 0x8842e05f, 0xabce7290, 0xd3dabd19, 0xf0562fd6, 0xc086b995, 0xe30a2b5a, 0x9b1ee4d3, 0xb892761c, 0xcdaaa33a, 0xee2631f5, 0x9632fe7c, 0xb5be6cb3, 0x856efaf0, 0xa6e2683f, 0xdef6a7b6, 0xfd7a3579, 0xf8730855, 0xdbff9a9a, 0xa3eb5513, 0x8067c7dc, 0xb0b7519f, 0x933bc350, 0xeb2f0cd9, 0xc8a39e16, 0xbd9b4b30, 0x9e17d9ff, 0xe6031676, 0xc58f84b9, 0xf55f12fa, 0xd6d38035, 0xaec74fbc, 0x8d4bdd73 +}, +{ +0x00000000, 0x2d011e46, 0x68f77fcb, 0x45f6618d, 0xe196b0e4, 0xcc97aea2, 0x8961cf2f, 0xa460d169, 0xcf88ae41, 0xe289b007, 0xa77fd18a, 0x8a7ecfcc, 0x2e1e1ea5, 0x031f00e3, 0x46e9616e, 0x6be87f28, 0x3560127b, 0x18610c3d, 0x5d976db0, 0x709673f6, 0xd4f6a29f, 0xf9f7bcd9, 0xbc01dd54, 0x9100c312, 0xfae8bc3a, 0xd7e9a27c, 0x921fc3f1, 0xbf1eddb7, 0x1b7e0cde, 0x367f1298, 0x73897315, 0x5e886d53, 0xb9e26c76, 0x94e37230, 0xd11513bd, 0xfc140dfb, 0x5874dc92, 0x7575c2d4, 0x3083a359, 0x1d82bd1f, 0x766ac237, 0x5b6bdc71, 0x1e9dbdfc, 0x339ca3ba, 0x97fc72d3, 0xbafd6c95, 0xff0b0d18, 0xd20a135e, 0x8c827e0d, 0xa183604b, 0xe47501c6, 0xc9741f80, 0x6d14cee9, 0x4015d0af, 0x05e3b122, 0x28e2af64, 0x430ad04c, 0x6e0bce0a, 0x2bfdaf87, 0x06fcb1c1, 0xa29c60a8, 0x8f9d7eee, 0xca6b1f63, 0xe76a0125, 0xf2f7a1cb, 0xdff6bf8d, 0x9a00de00, 0xb701c046, 0x1361112f, 0x3e600f69, 0x7b966ee4, 0x569770a2, 0x3d7f0f8a, 0x107e11cc, 0x55887041, 0x78896e07, 0xdce9bf6e, 0xf1e8a128, 0xb41ec0a5, 0x991fdee3, 0xc797b3b0, 0xea96adf6, 0xaf60cc7b, 0x8261d23d, 0x26010354, 0x0b001d12, 0x4ef67c9f, 0x63f762d9, 0x081f1df1, 0x251e03b7, 0x60e8623a, 0x4de97c7c, 0xe989ad15, 0xc488b353, 0x817ed2de, 0xac7fcc98, 0x4b15cdbd, 0x6614d3fb, 0x23e2b276, 0x0ee3ac30, 0xaa837d59, 0x8782631f, 0xc2740292, 0xef751cd4, 0x849d63fc, 0xa99c7dba, 0xec6a1c37, 0xc16b0271, 0x650bd318, 0x480acd5e, 0x0dfcacd3, 0x20fdb295, 0x7e75dfc6, 0x5374c180, 0x1682a00d, 0x3b83be4b, 0x9fe36f22, 0xb2e27164, 0xf71410e9, 0xda150eaf, 0xb1fd7187, 0x9cfc6fc1, 0xd90a0e4c, 0xf40b100a, 0x506bc163, 0x7d6adf25, 0x389cbea8, 0x159da0ee, 0x8595792b, 0xa894676d, 0xed6206e0, 0xc06318a6, 0x6403c9cf, 0x4902d789, 0x0cf4b604, 0x21f5a842, 0x4a1dd76a, 0x671cc92c, 0x22eaa8a1, 0x0febb6e7, 0xab8b678e, 0x868a79c8, 0xc37c1845, 0xee7d0603, 0xb0f56b50, 0x9df47516, 0xd802149b, 0xf5030add, 0x5163dbb4, 0x7c62c5f2, 0x3994a47f, 0x1495ba39, 0x7f7dc511, 0x527cdb57, 0x178abada, 0x3a8ba49c, 0x9eeb75f5, 0xb3ea6bb3, 0xf61c0a3e, 0xdb1d1478, 0x3c77155d, 0x11760b1b, 0x54806a96, 0x798174d0, 0xdde1a5b9, 0xf0e0bbff, 0xb516da72, 0x9817c434, 0xf3ffbb1c, 0xdefea55a, 0x9b08c4d7, 0xb609da91, 0x12690bf8, 0x3f6815be, 0x7a9e7433, 0x579f6a75, 0x09170726, 0x24161960, 0x61e078ed, 0x4ce166ab, 0xe881b7c2, 0xc580a984, 0x8076c809, 0xad77d64f, 0xc69fa967, 0xeb9eb721, 0xae68d6ac, 0x8369c8ea, 0x27091983, 0x0a0807c5, 0x4ffe6648, 0x62ff780e, 0x7762d8e0, 0x5a63c6a6, 0x1f95a72b, 0x3294b96d, 0x96f46804, 0xbbf57642, 0xfe0317cf, 0xd3020989, 0xb8ea76a1, 0x95eb68e7, 0xd01d096a, 0xfd1c172c, 0x597cc645, 0x747dd803, 0x318bb98e, 0x1c8aa7c8, 0x4202ca9b, 0x6f03d4dd, 0x2af5b550, 0x07f4ab16, 0xa3947a7f, 0x8e956439, 0xcb6305b4, 0xe6621bf2, 0x8d8a64da, 0xa08b7a9c, 0xe57d1b11, 0xc87c0557, 0x6c1cd43e, 0x411dca78, 0x04ebabf5, 0x29eab5b3, 0xce80b496, 0xe381aad0, 0xa677cb5d, 0x8b76d51b, 0x2f160472, 0x02171a34, 0x47e17bb9, 0x6ae065ff, 0x01081ad7, 0x2c090491, 0x69ff651c, 0x44fe7b5a, 0xe09eaa33, 0xcd9fb475, 0x8869d5f8, 0xa568cbbe, 0xfbe0a6ed, 0xd6e1b8ab, 0x9317d926, 0xbe16c760, 0x1a761609, 0x3777084f, 0x728169c2, 0x5f807784, 0x346808ac, 0x196916ea, 0x5c9f7767, 0x719e6921, 0xd5feb848, 0xf8ffa60e, 0xbd09c783, 0x9008d9c5 +}, +{ +0x00000000, 0xf23f3c91, 0x64dba7d9, 0x96e49b48, 0xda29e814, 0x2816d485, 0xbef24fcd, 0x4ccd735c, 0xaae88c5c, 0x58d7b0cd, 0xce332b85, 0x3c0c1714, 0x70c16448, 0x82fe58d9, 0x141ac391, 0xe625ff00, 0x727bd648, 0x8044ead9, 0x16a07191, 0xe49f4d00, 0xa8523e5c, 0x5a6d02cd, 0xcc899985, 0x3eb6a514, 0xd8935a14, 0x2aac6685, 0xbc48fdcd, 0x4e77c15c, 0x02bab200, 0xf0858e91, 0x666115d9, 0x945e2948, 0xe99438c7, 0x1bab0456, 0x8d4f9f1e, 0x7f70a38f, 0x33bdd0d3, 0xc182ec42, 0x5766770a, 0xa5594b9b, 0x437cb49b, 0xb143880a, 0x27a71342, 0xd5982fd3, 0x99555c8f, 0x6b6a601e, 0xfd8efb56, 0x0fb1c7c7, 0x9befee8f, 0x69d0d21e, 0xff344956, 0x0d0b75c7, 0x41c6069b, 0xb3f93a0a, 0x251da142, 0xd7229dd3, 0x310762d3, 0xc3385e42, 0x55dcc50a, 0xa7e3f99b, 0xeb2e8ac7, 0x1911b656, 0x8ff52d1e, 0x7dca118f, 0xa45ba872, 0x566494e3, 0xc0800fab, 0x32bf333a, 0x7e724066, 0x8c4d7cf7, 0x1aa9e7bf, 0xe896db2e, 0x0eb3242e, 0xfc8c18bf, 0x6a6883f7, 0x9857bf66, 0xd49acc3a, 0x26a5f0ab, 0xb0416be3, 0x427e5772, 0xd6207e3a, 0x241f42ab, 0xb2fbd9e3, 0x40c4e572, 0x0c09962e, 0xfe36aabf, 0x68d231f7, 0x9aed0d66, 0x7cc8f266, 0x8ef7cef7, 0x181355bf, 0xea2c692e, 0xa6e11a72, 0x54de26e3, 0xc23abdab, 0x3005813a, 0x4dcf90b5, 0xbff0ac24, 0x2914376c, 0xdb2b0bfd, 0x97e678a1, 0x65d94430, 0xf33ddf78, 0x0102e3e9, 0xe7271ce9, 0x15182078, 0x83fcbb30, 0x71c387a1, 0x3d0ef4fd, 0xcf31c86c, 0x59d55324, 0xabea6fb5, 0x3fb446fd, 0xcd8b7a6c, 0x5b6fe124, 0xa950ddb5, 0xe59daee9, 0x17a29278, 0x81460930, 0x737935a1, 0x955ccaa1, 0x6763f630, 0xf1876d78, 0x03b851e9, 0x4f7522b5, 0xbd4a1e24, 0x2bae856c, 0xd991b9fd, 0x32018ccc, 0xc03eb05d, 0x56da2b15, 0xa4e51784, 0xe82864d8, 0x1a175849, 0x8cf3c301, 0x7eccff90, 0x98e90090, 0x6ad63c01, 0xfc32a749, 0x0e0d9bd8, 0x42c0e884, 0xb0ffd415, 0x261b4f5d, 0xd42473cc, 0x407a5a84, 0xb2456615, 0x24a1fd5d, 0xd69ec1cc, 0x9a53b290, 0x686c8e01, 0xfe881549, 0x0cb729d8, 0xea92d6d8, 0x18adea49, 0x8e497101, 0x7c764d90, 0x30bb3ecc, 0xc284025d, 0x54609915, 0xa65fa584, 0xdb95b40b, 0x29aa889a, 0xbf4e13d2, 0x4d712f43, 0x01bc5c1f, 0xf383608e, 0x6567fbc6, 0x9758c757, 0x717d3857, 0x834204c6, 0x15a69f8e, 0xe799a31f, 0xab54d043, 0x596becd2, 0xcf8f779a, 0x3db04b0b, 0xa9ee6243, 0x5bd15ed2, 0xcd35c59a, 0x3f0af90b, 0x73c78a57, 0x81f8b6c6, 0x171c2d8e, 0xe523111f, 0x0306ee1f, 0xf139d28e, 0x67dd49c6, 0x95e27557, 0xd92f060b, 0x2b103a9a, 0xbdf4a1d2, 0x4fcb9d43, 0x965a24be, 0x6465182f, 0xf2818367, 0x00bebff6, 0x4c73ccaa, 0xbe4cf03b, 0x28a86b73, 0xda9757e2, 0x3cb2a8e2, 0xce8d9473, 0x58690f3b, 0xaa5633aa, 0xe69b40f6, 0x14a47c67, 0x8240e72f, 0x707fdbbe, 0xe421f2f6, 0x161ece67, 0x80fa552f, 0x72c569be, 0x3e081ae2, 0xcc372673, 0x5ad3bd3b, 0xa8ec81aa, 0x4ec97eaa, 0xbcf6423b, 0x2a12d973, 0xd82de5e2, 0x94e096be, 0x66dfaa2f, 0xf03b3167, 0x02040df6, 0x7fce1c79, 0x8df120e8, 0x1b15bba0, 0xe92a8731, 0xa5e7f46d, 0x57d8c8fc, 0xc13c53b4, 0x33036f25, 0xd5269025, 0x2719acb4, 0xb1fd37fc, 0x43c20b6d, 0x0f0f7831, 0xfd3044a0, 0x6bd4dfe8, 0x99ebe379, 0x0db5ca31, 0xff8af6a0, 0x696e6de8, 0x9b515179, 0xd79c2225, 0x25a31eb4, 0xb34785fc, 0x4178b96d, 0xa75d466d, 0x55627afc, 0xc386e1b4, 0x31b9dd25, 0x7d74ae79, 0x8f4b92e8, 0x19af09a0, 0xeb903531 +}, +{ +0x00000000, 0x5ee1d5f6, 0xfbcfc145, 0xa52e14b3, 0x51219201, 0x0fc047f7, 0xaaee5344, 0xf40f86b2, 0x7a5f0b19, 0x24bedeef, 0x8190ca5c, 0xdf711faa, 0x2b7e9918, 0x759f4cee, 0xd0b1585d, 0x8e508dab, 0x1a28d864, 0x44c90d92, 0xe1e71921, 0xbf06ccd7, 0x4b094a65, 0x15e89f93, 0xb0c68b20, 0xee275ed6, 0x6077d37d, 0x3e96068b, 0x9bb81238, 0xc559c7ce, 0x3156417c, 0x6fb7948a, 0xca998039, 0x947855cf, 0xcbab5d43, 0x954a88b5, 0x30649c06, 0x6e8549f0, 0x9a8acf42, 0xc46b1ab4, 0x61450e07, 0x3fa4dbf1, 0xb1f4565a, 0xef1583ac, 0x4a3b971f, 0x14da42e9, 0xe0d5c45b, 0xbe3411ad, 0x1b1a051e, 0x45fbd0e8, 0xd1838527, 0x8f6250d1, 0x2a4c4462, 0x74ad9194, 0x80a21726, 0xde43c2d0, 0x7b6dd663, 0x258c0395, 0xabdc8e3e, 0xf53d5bc8, 0x50134f7b, 0x0ef29a8d, 0xfafd1c3f, 0xa41cc9c9, 0x0132dd7a, 0x5fd3088c, 0xd0ce505b, 0x8e2f85ad, 0x2b01911e, 0x75e044e8, 0x81efc25a, 0xdf0e17ac, 0x7a20031f, 0x24c1d6e9, 0xaa915b42, 0xf4708eb4, 0x515e9a07, 0x0fbf4ff1, 0xfbb0c943, 0xa5511cb5, 0x007f0806, 0x5e9eddf0, 0xcae6883f, 0x94075dc9, 0x3129497a, 0x6fc89c8c, 0x9bc71a3e, 0xc526cfc8, 0x6008db7b, 0x3ee90e8d, 0xb0b98326, 0xee5856d0, 0x4b764263, 0x15979795, 0xe1981127, 0xbf79c4d1, 0x1a57d062, 0x44b60594, 0x1b650d18, 0x4584d8ee, 0xe0aacc5d, 0xbe4b19ab, 0x4a449f19, 0x14a54aef, 0xb18b5e5c, 0xef6a8baa, 0x613a0601, 0x3fdbd3f7, 0x9af5c744, 0xc41412b2, 0x301b9400, 0x6efa41f6, 0xcbd45545, 0x953580b3, 0x014dd57c, 0x5fac008a, 0xfa821439, 0xa463c1cf, 0x506c477d, 0x0e8d928b, 0xaba38638, 0xf54253ce, 0x7b12de65, 0x25f30b93, 0x80dd1f20, 0xde3ccad6, 0x2a334c64, 0x74d29992, 0xd1fc8d21, 0x8f1d58d7, 0x9ee76d69, 0xc006b89f, 0x6528ac2c, 0x3bc979da, 0xcfc6ff68, 0x91272a9e, 0x34093e2d, 0x6ae8ebdb, 0xe4b86670, 0xba59b386, 0x1f77a735, 0x419672c3, 0xb599f471, 0xeb782187, 0x4e563534, 0x10b7e0c2, 0x84cfb50d, 0xda2e60fb, 0x7f007448, 0x21e1a1be, 0xd5ee270c, 0x8b0ff2fa, 0x2e21e649, 0x70c033bf, 0xfe90be14, 0xa0716be2, 0x055f7f51, 0x5bbeaaa7, 0xafb12c15, 0xf150f9e3, 0x547eed50, 0x0a9f38a6, 0x554c302a, 0x0bade5dc, 0xae83f16f, 0xf0622499, 0x046da22b, 0x5a8c77dd, 0xffa2636e, 0xa143b698, 0x2f133b33, 0x71f2eec5, 0xd4dcfa76, 0x8a3d2f80, 0x7e32a932, 0x20d37cc4, 0x85fd6877, 0xdb1cbd81, 0x4f64e84e, 0x11853db8, 0xb4ab290b, 0xea4afcfd, 0x1e457a4f, 0x40a4afb9, 0xe58abb0a, 0xbb6b6efc, 0x353be357, 0x6bda36a1, 0xcef42212, 0x9015f7e4, 0x641a7156, 0x3afba4a0, 0x9fd5b013, 0xc13465e5, 0x4e293d32, 0x10c8e8c4, 0xb5e6fc77, 0xeb072981, 0x1f08af33, 0x41e97ac5, 0xe4c76e76, 0xba26bb80, 0x3476362b, 0x6a97e3dd, 0xcfb9f76e, 0x91582298, 0x6557a42a, 0x3bb671dc, 0x9e98656f, 0xc079b099, 0x5401e556, 0x0ae030a0, 0xafce2413, 0xf12ff1e5, 0x05207757, 0x5bc1a2a1, 0xfeefb612, 0xa00e63e4, 0x2e5eee4f, 0x70bf3bb9, 0xd5912f0a, 0x8b70fafc, 0x7f7f7c4e, 0x219ea9b8, 0x84b0bd0b, 0xda5168fd, 0x85826071, 0xdb63b587, 0x7e4da134, 0x20ac74c2, 0xd4a3f270, 0x8a422786, 0x2f6c3335, 0x718de6c3, 0xffdd6b68, 0xa13cbe9e, 0x0412aa2d, 0x5af37fdb, 0xaefcf969, 0xf01d2c9f, 0x5533382c, 0x0bd2edda, 0x9faab815, 0xc14b6de3, 0x64657950, 0x3a84aca6, 0xce8b2a14, 0x906affe2, 0x3544eb51, 0x6ba53ea7, 0xe5f5b30c, 0xbb1466fa, 0x1e3a7249, 0x40dba7bf, 0xb4d4210d, 0xea35f4fb, 0x4f1be048, 0x11fa35be +}, +{ +0x00000000, 0x00ce7869, 0x2941cb56, 0x298fb33f, 0xa67c4542, 0xa6b23d2b, 0x8f3d8e14, 0x8ff3f67d, 0xff805485, 0xff4e2cec, 0xd6c19fd3, 0xd60fe7ba, 0x59fc11c7, 0x593269ae, 0x70bdda91, 0x7073a2f8, 0xd3caf20a, 0xd3048a63, 0xfa8b395c, 0xfa454135, 0x75b6b748, 0x7578cf21, 0x5cf77c1e, 0x5c390477, 0x2c4aa68f, 0x2c84dee6, 0x050b6dd9, 0x05c515b0, 0x8a36e3cd, 0x8af89ba4, 0xa377289b, 0xa3b950f2, 0xced34e1b, 0xce1d3672, 0xe792854d, 0xe75cfd24, 0x68af0b59, 0x68617330, 0x41eec00f, 0x4120b866, 0x31531a9e, 0x319d62f7, 0x1812d1c8, 0x18dca9a1, 0x972f5fdc, 0x97e127b5, 0xbe6e948a, 0xbea0ece3, 0x1d19bc11, 0x1dd7c478, 0x34587747, 0x34960f2e, 0xbb65f953, 0xbbab813a, 0x92243205, 0x92ea4a6c, 0xe299e894, 0xe25790fd, 0xcbd823c2, 0xcb165bab, 0x44e5add6, 0x442bd5bf, 0x6da46680, 0x6d6a1ee9, 0xd1185304, 0xd1d62b6d, 0xf8599852, 0xf897e03b, 0x77641646, 0x77aa6e2f, 0x5e25dd10, 0x5eeba579, 0x2e980781, 0x2e567fe8, 0x07d9ccd7, 0x0717b4be, 0x88e442c3, 0x882a3aaa, 0xa1a58995, 0xa16bf1fc, 0x02d2a10e, 0x021cd967, 0x2b936a58, 0x2b5d1231, 0xa4aee44c, 0xa4609c25, 0x8def2f1a, 0x8d215773, 0xfd52f58b, 0xfd9c8de2, 0xd4133edd, 0xd4dd46b4, 0x5b2eb0c9, 0x5be0c8a0, 0x726f7b9f, 0x72a103f6, 0x1fcb1d1f, 0x1f056576, 0x368ad649, 0x3644ae20, 0xb9b7585d, 0xb9792034, 0x90f6930b, 0x9038eb62, 0xe04b499a, 0xe08531f3, 0xc90a82cc, 0xc9c4faa5, 0x46370cd8, 0x46f974b1, 0x6f76c78e, 0x6fb8bfe7, 0xcc01ef15, 0xcccf977c, 0xe5402443, 0xe58e5c2a, 0x6a7daa57, 0x6ab3d23e, 0x433c6101, 0x43f21968, 0x3381bb90, 0x334fc3f9, 0x1ac070c6, 0x1a0e08af, 0x95fdfed2, 0x953386bb, 0xbcbc3584, 0xbc724ded, 0xf64b4fa7, 0xf68537ce, 0xdf0a84f1, 0xdfc4fc98, 0x50370ae5, 0x50f9728c, 0x7976c1b3, 0x79b8b9da, 0x09cb1b22, 0x0905634b, 0x208ad074, 0x2044a81d, 0xafb75e60, 0xaf792609, 0x86f69536, 0x8638ed5f, 0x2581bdad, 0x254fc5c4, 0x0cc076fb, 0x0c0e0e92, 0x83fdf8ef, 0x83338086, 0xaabc33b9, 0xaa724bd0, 0xda01e928, 0xdacf9141, 0xf340227e, 0xf38e5a17, 0x7c7dac6a, 0x7cb3d403, 0x553c673c, 0x55f21f55, 0x389801bc, 0x385679d5, 0x11d9caea, 0x1117b283, 0x9ee444fe, 0x9e2a3c97, 0xb7a58fa8, 0xb76bf7c1, 0xc7185539, 0xc7d62d50, 0xee599e6f, 0xee97e606, 0x6164107b, 0x61aa6812, 0x4825db2d, 0x48eba344, 0xeb52f3b6, 0xeb9c8bdf, 0xc21338e0, 0xc2dd4089, 0x4d2eb6f4, 0x4de0ce9d, 0x646f7da2, 0x64a105cb, 0x14d2a733, 0x141cdf5a, 0x3d936c65, 0x3d5d140c, 0xb2aee271, 0xb2609a18, 0x9bef2927, 0x9b21514e, 0x27531ca3, 0x279d64ca, 0x0e12d7f5, 0x0edcaf9c, 0x812f59e1, 0x81e12188, 0xa86e92b7, 0xa8a0eade, 0xd8d34826, 0xd81d304f, 0xf1928370, 0xf15cfb19, 0x7eaf0d64, 0x7e61750d, 0x57eec632, 0x5720be5b, 0xf499eea9, 0xf45796c0, 0xddd825ff, 0xdd165d96, 0x52e5abeb, 0x522bd382, 0x7ba460bd, 0x7b6a18d4, 0x0b19ba2c, 0x0bd7c245, 0x2258717a, 0x22960913, 0xad65ff6e, 0xadab8707, 0x84243438, 0x84ea4c51, 0xe98052b8, 0xe94e2ad1, 0xc0c199ee, 0xc00fe187, 0x4ffc17fa, 0x4f326f93, 0x66bddcac, 0x6673a4c5, 0x1600063d, 0x16ce7e54, 0x3f41cd6b, 0x3f8fb502, 0xb07c437f, 0xb0b23b16, 0x993d8829, 0x99f3f040, 0x3a4aa0b2, 0x3a84d8db, 0x130b6be4, 0x13c5138d, 0x9c36e5f0, 0x9cf89d99, 0xb5772ea6, 0xb5b956cf, 0xc5caf437, 0xc5048c5e, 0xec8b3f61, 0xec454708, 0x63b6b175, 0x6378c91c, 0x4af77a23, 0x4a39024a +}, +{ +0x00000000, 0x40ba1be4, 0xcc8a0917, 0x8c3012f3, 0xb92fffe0, 0xf995e404, 0x75a5f6f7, 0x351fed13, 0xd6245a75, 0x969e4191, 0x1aae5362, 0x5a144886, 0x6f0ba595, 0x2fb1be71, 0xa381ac82, 0xe33bb766, 0xbeab570a, 0xfe114cee, 0x72215e1d, 0x329b45f9, 0x0784a8ea, 0x473eb30e, 0xcb0ea1fd, 0x8bb4ba19, 0x688f0d7f, 0x2835169b, 0xa4050468, 0xe4bf1f8c, 0xd1a0f29f, 0x911ae97b, 0x1d2afb88, 0x5d90e06c, 0x450e11f3, 0x05b40a17, 0x898418e4, 0xc93e0300, 0xfc21ee13, 0xbc9bf5f7, 0x30abe704, 0x7011fce0, 0x932a4b86, 0xd3905062, 0x5fa04291, 0x1f1a5975, 0x2a05b466, 0x6abfaf82, 0xe68fbd71, 0xa635a695, 0xfba546f9, 0xbb1f5d1d, 0x372f4fee, 0x7795540a, 0x428ab919, 0x0230a2fd, 0x8e00b00e, 0xcebaabea, 0x2d811c8c, 0x6d3b0768, 0xe10b159b, 0xa1b10e7f, 0x94aee36c, 0xd414f888, 0x5824ea7b, 0x189ef19f, 0xbb37d5de, 0xfb8dce3a, 0x77bddcc9, 0x3707c72d, 0x02182a3e, 0x42a231da, 0xce922329, 0x8e2838cd, 0x6d138fab, 0x2da9944f, 0xa19986bc, 0xe1239d58, 0xd43c704b, 0x94866baf, 0x18b6795c, 0x580c62b8, 0x059c82d4, 0x45269930, 0xc9168bc3, 0x89ac9027, 0xbcb37d34, 0xfc0966d0, 0x70397423, 0x30836fc7, 0xd3b8d8a1, 0x9302c345, 0x1f32d1b6, 0x5f88ca52, 0x6a972741, 0x2a2d3ca5, 0xa61d2e56, 0xe6a735b2, 0xfe39c42d, 0xbe83dfc9, 0x32b3cd3a, 0x7209d6de, 0x47163bcd, 0x07ac2029, 0x8b9c32da, 0xcb26293e, 0x281d9e58, 0x68a785bc, 0xe497974f, 0xa42d8cab, 0x913261b8, 0xd1887a5c, 0x5db868af, 0x1d02734b, 0x40929327, 0x002888c3, 0x8c189a30, 0xcca281d4, 0xf9bd6cc7, 0xb9077723, 0x353765d0, 0x758d7e34, 0x96b6c952, 0xd60cd2b6, 0x5a3cc045, 0x1a86dba1, 0x2f9936b2, 0x6f232d56, 0xe3133fa5, 0xa3a92441, 0xb30b0c7f, 0xf3b1179b, 0x7f810568, 0x3f3b1e8c, 0x0a24f39f, 0x4a9ee87b, 0xc6aefa88, 0x8614e16c, 0x652f560a, 0x25954dee, 0xa9a55f1d, 0xe91f44f9, 0xdc00a9ea, 0x9cbab20e, 0x108aa0fd, 0x5030bb19, 0x0da05b75, 0x4d1a4091, 0xc12a5262, 0x81904986, 0xb48fa495, 0xf435bf71, 0x7805ad82, 0x38bfb666, 0xdb840100, 0x9b3e1ae4, 0x170e0817, 0x57b413f3, 0x62abfee0, 0x2211e504, 0xae21f7f7, 0xee9bec13, 0xf6051d8c, 0xb6bf0668, 0x3a8f149b, 0x7a350f7f, 0x4f2ae26c, 0x0f90f988, 0x83a0eb7b, 0xc31af09f, 0x202147f9, 0x609b5c1d, 0xecab4eee, 0xac11550a, 0x990eb819, 0xd9b4a3fd, 0x5584b10e, 0x153eaaea, 0x48ae4a86, 0x08145162, 0x84244391, 0xc49e5875, 0xf181b566, 0xb13bae82, 0x3d0bbc71, 0x7db1a795, 0x9e8a10f3, 0xde300b17, 0x520019e4, 0x12ba0200, 0x27a5ef13, 0x671ff4f7, 0xeb2fe604, 0xab95fde0, 0x083cd9a1, 0x4886c245, 0xc4b6d0b6, 0x840ccb52, 0xb1132641, 0xf1a93da5, 0x7d992f56, 0x3d2334b2, 0xde1883d4, 0x9ea29830, 0x12928ac3, 0x52289127, 0x67377c34, 0x278d67d0, 0xabbd7523, 0xeb076ec7, 0xb6978eab, 0xf62d954f, 0x7a1d87bc, 0x3aa79c58, 0x0fb8714b, 0x4f026aaf, 0xc332785c, 0x838863b8, 0x60b3d4de, 0x2009cf3a, 0xac39ddc9, 0xec83c62d, 0xd99c2b3e, 0x992630da, 0x15162229, 0x55ac39cd, 0x4d32c852, 0x0d88d3b6, 0x81b8c145, 0xc102daa1, 0xf41d37b2, 0xb4a72c56, 0x38973ea5, 0x782d2541, 0x9b169227, 0xdbac89c3, 0x579c9b30, 0x172680d4, 0x22396dc7, 0x62837623, 0xeeb364d0, 0xae097f34, 0xf3999f58, 0xb32384bc, 0x3f13964f, 0x7fa98dab, 0x4ab660b8, 0x0a0c7b5c, 0x863c69af, 0xc686724b, 0x25bdc52d, 0x6507dec9, 0xe937cc3a, 0xa98dd7de, 0x9c923acd, 0xdc282129, 0x501833da, 0x10a2283e +}, +{ +0x00000000, 0x21c39573, 0x106fedc8, 0x31ac78bb, 0x418bbf8a, 0x60482af9, 0x51e45242, 0x7027c731, 0xcd82acc8, 0xec4139bb, 0xdded4100, 0xfc2ed473, 0x8c091342, 0xadca8631, 0x9c66fe8a, 0xbda56bf9, 0x18977a78, 0x3954ef0b, 0x08f897b0, 0x293b02c3, 0x591cc5f2, 0x78df5081, 0x4973283a, 0x68b0bd49, 0xd515d6b0, 0xf4d643c3, 0xc57a3b78, 0xe4b9ae0b, 0x949e693a, 0xb55dfc49, 0x84f184f2, 0xa5321181, 0x8dd1a87d, 0xac123d0e, 0x9dbe45b5, 0xbc7dd0c6, 0xcc5a17f7, 0xed998284, 0xdc35fa3f, 0xfdf66f4c, 0x405304b5, 0x619091c6, 0x503ce97d, 0x71ff7c0e, 0x01d8bb3f, 0x201b2e4c, 0x11b756f7, 0x3074c384, 0x9546d205, 0xb4854776, 0x85293fcd, 0xa4eaaabe, 0xd4cd6d8f, 0xf50ef8fc, 0xc4a28047, 0xe5611534, 0x58c47ecd, 0x7907ebbe, 0x48ab9305, 0x69680676, 0x194fc147, 0x388c5434, 0x09202c8f, 0x28e3b9fc, 0xbffad498, 0x9e3941eb, 0xaf953950, 0x8e56ac23, 0xfe716b12, 0xdfb2fe61, 0xee1e86da, 0xcfdd13a9, 0x72787850, 0x53bbed23, 0x62179598, 0x43d400eb, 0x33f3c7da, 0x123052a9, 0x239c2a12, 0x025fbf61, 0xa76daee0, 0x86ae3b93, 0xb7024328, 0x96c1d65b, 0xe6e6116a, 0xc7258419, 0xf689fca2, 0xd74a69d1, 0x6aef0228, 0x4b2c975b, 0x7a80efe0, 0x5b437a93, 0x2b64bda2, 0x0aa728d1, 0x3b0b506a, 0x1ac8c519, 0x322b7ce5, 0x13e8e996, 0x2244912d, 0x0387045e, 0x73a0c36f, 0x5263561c, 0x63cf2ea7, 0x420cbbd4, 0xffa9d02d, 0xde6a455e, 0xefc63de5, 0xce05a896, 0xbe226fa7, 0x9fe1fad4, 0xae4d826f, 0x8f8e171c, 0x2abc069d, 0x0b7f93ee, 0x3ad3eb55, 0x1b107e26, 0x6b37b917, 0x4af42c64, 0x7b5854df, 0x5a9bc1ac, 0xe73eaa55, 0xc6fd3f26, 0xf751479d, 0xd692d2ee, 0xa6b515df, 0x877680ac, 0xb6daf817, 0x97196d64, 0x269cd557, 0x075f4024, 0x36f3389f, 0x1730adec, 0x67176add, 0x46d4ffae, 0x77788715, 0x56bb1266, 0xeb1e799f, 0xcaddecec, 0xfb719457, 0xdab20124, 0xaa95c615, 0x8b565366, 0xbafa2bdd, 0x9b39beae, 0x3e0baf2f, 0x1fc83a5c, 0x2e6442e7, 0x0fa7d794, 0x7f8010a5, 0x5e4385d6, 0x6feffd6d, 0x4e2c681e, 0xf38903e7, 0xd24a9694, 0xe3e6ee2f, 0xc2257b5c, 0xb202bc6d, 0x93c1291e, 0xa26d51a5, 0x83aec4d6, 0xab4d7d2a, 0x8a8ee859, 0xbb2290e2, 0x9ae10591, 0xeac6c2a0, 0xcb0557d3, 0xfaa92f68, 0xdb6aba1b, 0x66cfd1e2, 0x470c4491, 0x76a03c2a, 0x5763a959, 0x27446e68, 0x0687fb1b, 0x372b83a0, 0x16e816d3, 0xb3da0752, 0x92199221, 0xa3b5ea9a, 0x82767fe9, 0xf251b8d8, 0xd3922dab, 0xe23e5510, 0xc3fdc063, 0x7e58ab9a, 0x5f9b3ee9, 0x6e374652, 0x4ff4d321, 0x3fd31410, 0x1e108163, 0x2fbcf9d8, 0x0e7f6cab, 0x996601cf, 0xb8a594bc, 0x8909ec07, 0xa8ca7974, 0xd8edbe45, 0xf92e2b36, 0xc882538d, 0xe941c6fe, 0x54e4ad07, 0x75273874, 0x448b40cf, 0x6548d5bc, 0x156f128d, 0x34ac87fe, 0x0500ff45, 0x24c36a36, 0x81f17bb7, 0xa032eec4, 0x919e967f, 0xb05d030c, 0xc07ac43d, 0xe1b9514e, 0xd01529f5, 0xf1d6bc86, 0x4c73d77f, 0x6db0420c, 0x5c1c3ab7, 0x7ddfafc4, 0x0df868f5, 0x2c3bfd86, 0x1d97853d, 0x3c54104e, 0x14b7a9b2, 0x35743cc1, 0x04d8447a, 0x251bd109, 0x553c1638, 0x74ff834b, 0x4553fbf0, 0x64906e83, 0xd935057a, 0xf8f69009, 0xc95ae8b2, 0xe8997dc1, 0x98bebaf0, 0xb97d2f83, 0x88d15738, 0xa912c24b, 0x0c20d3ca, 0x2de346b9, 0x1c4f3e02, 0x3d8cab71, 0x4dab6c40, 0x6c68f933, 0x5dc48188, 0x7c0714fb, 0xc1a27f02, 0xe061ea71, 0xd1cd92ca, 0xf00e07b9, 0x8029c088, 0xa1ea55fb, 0x90462d40, 0xb185b833 +}, +{ +0x00000000, 0x0b30d8e1, 0x7b5c600d, 0x706cb8ec, 0xfe64e565, 0xf5543d84, 0x85388568, 0x8e085d89, 0x4ef8d6d5, 0x45c80e34, 0x35a4b6d8, 0x3e946e39, 0xb09c33b0, 0xbbaceb51, 0xcbc053bd, 0xc0f08b5c, 0x74232990, 0x7f13f171, 0x0f7f499d, 0x044f917c, 0x8a47ccf5, 0x81771414, 0xf11bacf8, 0xfa2b7419, 0x3adbff45, 0x31eb27a4, 0x41879f48, 0x4ab747a9, 0xc4bf1a20, 0xcf8fc2c1, 0xbfe37a2d, 0xb4d3a2cc, 0x75c0fee4, 0x7ef02605, 0x0e9c9ee9, 0x05ac4608, 0x8ba41b81, 0x8094c360, 0xf0f87b8c, 0xfbc8a36d, 0x3b382831, 0x3008f0d0, 0x4064483c, 0x4b5490dd, 0xc55ccd54, 0xce6c15b5, 0xbe00ad59, 0xb53075b8, 0x01e3d774, 0x0ad30f95, 0x7abfb779, 0x718f6f98, 0xff873211, 0xf4b7eaf0, 0x84db521c, 0x8feb8afd, 0x4f1b01a1, 0x442bd940, 0x344761ac, 0x3f77b94d, 0xb17fe4c4, 0xba4f3c25, 0xca2384c9, 0xc1135c28, 0x6737eae5, 0x6c073204, 0x1c6b8ae8, 0x175b5209, 0x99530f80, 0x9263d761, 0xe20f6f8d, 0xe93fb76c, 0x29cf3c30, 0x22ffe4d1, 0x52935c3d, 0x59a384dc, 0xd7abd955, 0xdc9b01b4, 0xacf7b958, 0xa7c761b9, 0x1314c375, 0x18241b94, 0x6848a378, 0x63787b99, 0xed702610, 0xe640fef1, 0x962c461d, 0x9d1c9efc, 0x5dec15a0, 0x56dccd41, 0x26b075ad, 0x2d80ad4c, 0xa388f0c5, 0xa8b82824, 0xd8d490c8, 0xd3e44829, 0x12f71401, 0x19c7cce0, 0x69ab740c, 0x629baced, 0xec93f164, 0xe7a32985, 0x97cf9169, 0x9cff4988, 0x5c0fc2d4, 0x573f1a35, 0x2753a2d9, 0x2c637a38, 0xa26b27b1, 0xa95bff50, 0xd93747bc, 0xd2079f5d, 0x66d43d91, 0x6de4e570, 0x1d885d9c, 0x16b8857d, 0x98b0d8f4, 0x93800015, 0xe3ecb8f9, 0xe8dc6018, 0x282ceb44, 0x231c33a5, 0x53708b49, 0x584053a8, 0xd6480e21, 0xdd78d6c0, 0xad146e2c, 0xa624b6cd, 0xc02fbb27, 0xcb1f63c6, 0xbb73db2a, 0xb04303cb, 0x3e4b5e42, 0x357b86a3, 0x45173e4f, 0x4e27e6ae, 0x8ed76df2, 0x85e7b513, 0xf58b0dff, 0xfebbd51e, 0x70b38897, 0x7b835076, 0x0befe89a, 0x00df307b, 0xb40c92b7, 0xbf3c4a56, 0xcf50f2ba, 0xc4602a5b, 0x4a6877d2, 0x4158af33, 0x313417df, 0x3a04cf3e, 0xfaf44462, 0xf1c49c83, 0x81a8246f, 0x8a98fc8e, 0x0490a107, 0x0fa079e6, 0x7fccc10a, 0x74fc19eb, 0xb5ef45c3, 0xbedf9d22, 0xceb325ce, 0xc583fd2f, 0x4b8ba0a6, 0x40bb7847, 0x30d7c0ab, 0x3be7184a, 0xfb179316, 0xf0274bf7, 0x804bf31b, 0x8b7b2bfa, 0x05737673, 0x0e43ae92, 0x7e2f167e, 0x751fce9f, 0xc1cc6c53, 0xcafcb4b2, 0xba900c5e, 0xb1a0d4bf, 0x3fa88936, 0x349851d7, 0x44f4e93b, 0x4fc431da, 0x8f34ba86, 0x84046267, 0xf468da8b, 0xff58026a, 0x71505fe3, 0x7a608702, 0x0a0c3fee, 0x013ce70f, 0xa71851c2, 0xac288923, 0xdc4431cf, 0xd774e92e, 0x597cb4a7, 0x524c6c46, 0x2220d4aa, 0x29100c4b, 0xe9e08717, 0xe2d05ff6, 0x92bce71a, 0x998c3ffb, 0x17846272, 0x1cb4ba93, 0x6cd8027f, 0x67e8da9e, 0xd33b7852, 0xd80ba0b3, 0xa867185f, 0xa357c0be, 0x2d5f9d37, 0x266f45d6, 0x5603fd3a, 0x5d3325db, 0x9dc3ae87, 0x96f37666, 0xe69fce8a, 0xedaf166b, 0x63a74be2, 0x68979303, 0x18fb2bef, 0x13cbf30e, 0xd2d8af26, 0xd9e877c7, 0xa984cf2b, 0xa2b417ca, 0x2cbc4a43, 0x278c92a2, 0x57e02a4e, 0x5cd0f2af, 0x9c2079f3, 0x9710a112, 0xe77c19fe, 0xec4cc11f, 0x62449c96, 0x69744477, 0x1918fc9b, 0x1228247a, 0xa6fb86b6, 0xadcb5e57, 0xdda7e6bb, 0xd6973e5a, 0x589f63d3, 0x53afbb32, 0x23c303de, 0x28f3db3f, 0xe8035063, 0xe3338882, 0x935f306e, 0x986fe88f, 0x1667b506, 0x1d576de7, 0x6d3bd50b, 0x660b0dea +}, +{ +0x00000000, 0x1e822f9d, 0xfdb5f671, 0xe337d9ec, 0x39ab618d, 0x27294e10, 0xc41e97fc, 0xda9cb861, 0xbc69ee77, 0xa2ebc1ea, 0x41dc1806, 0x5f5e379b, 0x85c28ffa, 0x9b40a067, 0x7877798b, 0x66f55616, 0x4790c0e2, 0x5912ef7f, 0xba253693, 0xa4a7190e, 0x7e3ba16f, 0x60b98ef2, 0x838e571e, 0x9d0c7883, 0xfbf92e95, 0xe57b0108, 0x064cd8e4, 0x18cef779, 0xc2524f18, 0xdcd06085, 0x3fe7b969, 0x216596f4, 0xf9049662, 0xe786b9ff, 0x04b16013, 0x1a334f8e, 0xc0aff7ef, 0xde2dd872, 0x3d1a019e, 0x23982e03, 0x456d7815, 0x5bef5788, 0xb8d88e64, 0xa65aa1f9, 0x7cc61998, 0x62443605, 0x8173efe9, 0x9ff1c074, 0xbe945680, 0xa016791d, 0x4321a0f1, 0x5da38f6c, 0x873f370d, 0x99bd1890, 0x7a8ac17c, 0x6408eee1, 0x02fdb8f7, 0x1c7f976a, 0xff484e86, 0xe1ca611b, 0x3b56d97a, 0x25d4f6e7, 0xc6e32f0b, 0xd8610096, 0x29b96453, 0x373b4bce, 0xd40c9222, 0xca8ebdbf, 0x101205de, 0x0e902a43, 0xeda7f3af, 0xf325dc32, 0x95d08a24, 0x8b52a5b9, 0x68657c55, 0x76e753c8, 0xac7beba9, 0xb2f9c434, 0x51ce1dd8, 0x4f4c3245, 0x6e29a4b1, 0x70ab8b2c, 0x939c52c0, 0x8d1e7d5d, 0x5782c53c, 0x4900eaa1, 0xaa37334d, 0xb4b51cd0, 0xd2404ac6, 0xccc2655b, 0x2ff5bcb7, 0x3177932a, 0xebeb2b4b, 0xf56904d6, 0x165edd3a, 0x08dcf2a7, 0xd0bdf231, 0xce3fddac, 0x2d080440, 0x338a2bdd, 0xe91693bc, 0xf794bc21, 0x14a365cd, 0x0a214a50, 0x6cd41c46, 0x725633db, 0x9161ea37, 0x8fe3c5aa, 0x557f7dcb, 0x4bfd5256, 0xa8ca8bba, 0xb648a427, 0x972d32d3, 0x89af1d4e, 0x6a98c4a2, 0x741aeb3f, 0xae86535e, 0xb0047cc3, 0x5333a52f, 0x4db18ab2, 0x2b44dca4, 0x35c6f339, 0xd6f12ad5, 0xc8730548, 0x12efbd29, 0x0c6d92b4, 0xef5a4b58, 0xf1d864c5, 0x2adeb81d, 0x345c9780, 0xd76b4e6c, 0xc9e961f1, 0x1375d990, 0x0df7f60d, 0xeec02fe1, 0xf042007c, 0x96b7566a, 0x883579f7, 0x6b02a01b, 0x75808f86, 0xaf1c37e7, 0xb19e187a, 0x52a9c196, 0x4c2bee0b, 0x6d4e78ff, 0x73cc5762, 0x90fb8e8e, 0x8e79a113, 0x54e51972, 0x4a6736ef, 0xa950ef03, 0xb7d2c09e, 0xd1279688, 0xcfa5b915, 0x2c9260f9, 0x32104f64, 0xe88cf705, 0xf60ed898, 0x15390174, 0x0bbb2ee9, 0xd3da2e7f, 0xcd5801e2, 0x2e6fd80e, 0x30edf793, 0xea714ff2, 0xf4f3606f, 0x17c4b983, 0x0946961e, 0x6fb3c008, 0x7131ef95, 0x92063679, 0x8c8419e4, 0x5618a185, 0x489a8e18, 0xabad57f4, 0xb52f7869, 0x944aee9d, 0x8ac8c100, 0x69ff18ec, 0x777d3771, 0xade18f10, 0xb363a08d, 0x50547961, 0x4ed656fc, 0x282300ea, 0x36a12f77, 0xd596f69b, 0xcb14d906, 0x11886167, 0x0f0a4efa, 0xec3d9716, 0xf2bfb88b, 0x0367dc4e, 0x1de5f3d3, 0xfed22a3f, 0xe05005a2, 0x3accbdc3, 0x244e925e, 0xc7794bb2, 0xd9fb642f, 0xbf0e3239, 0xa18c1da4, 0x42bbc448, 0x5c39ebd5, 0x86a553b4, 0x98277c29, 0x7b10a5c5, 0x65928a58, 0x44f71cac, 0x5a753331, 0xb942eadd, 0xa7c0c540, 0x7d5c7d21, 0x63de52bc, 0x80e98b50, 0x9e6ba4cd, 0xf89ef2db, 0xe61cdd46, 0x052b04aa, 0x1ba92b37, 0xc1359356, 0xdfb7bccb, 0x3c806527, 0x22024aba, 0xfa634a2c, 0xe4e165b1, 0x07d6bc5d, 0x195493c0, 0xc3c82ba1, 0xdd4a043c, 0x3e7dddd0, 0x20fff24d, 0x460aa45b, 0x58888bc6, 0xbbbf522a, 0xa53d7db7, 0x7fa1c5d6, 0x6123ea4b, 0x821433a7, 0x9c961c3a, 0xbdf38ace, 0xa371a553, 0x40467cbf, 0x5ec45322, 0x8458eb43, 0x9adac4de, 0x79ed1d32, 0x676f32af, 0x019a64b9, 0x1f184b24, 0xfc2f92c8, 0xe2adbd55, 0x38310534, 0x26b32aa9, 0xc584f345, 0xdb06dcd8 +}, +{ +0x00000000, 0xcda2053a, 0xe7f04a57, 0x2a524f6d, 0xb009f7c2, 0x7dabf2f8, 0x57f9bd95, 0x9a5bb8af, 0x0dfb1c3b, 0xc0591901, 0xea0b566c, 0x27a95356, 0xbdf2ebf9, 0x7050eec3, 0x5a02a1ae, 0x97a0a494, 0xaaf96149, 0x675b6473, 0x4d092b1e, 0x80ab2e24, 0x1af0968b, 0xd75293b1, 0xfd00dcdc, 0x30a2d9e6, 0xa7027d72, 0x6aa07848, 0x40f23725, 0x8d50321f, 0x170b8ab0, 0xdaa98f8a, 0xf0fbc0e7, 0x3d59c5dd, 0x66482a09, 0xabea2f33, 0x81b8605e, 0x4c1a6564, 0xd641ddcb, 0x1be3d8f1, 0x31b1979c, 0xfc1392a6, 0x6bb33632, 0xa6113308, 0x8c437c65, 0x41e1795f, 0xdbbac1f0, 0x1618c4ca, 0x3c4a8ba7, 0xf1e88e9d, 0xccb14b40, 0x01134e7a, 0x2b410117, 0xe6e3042d, 0x7cb8bc82, 0xb11ab9b8, 0x9b48f6d5, 0x56eaf3ef, 0xc14a577b, 0x0ce85241, 0x26ba1d2c, 0xeb181816, 0x7143a0b9, 0xbce1a583, 0x96b3eaee, 0x5b11efd4, 0x842db582, 0x498fb0b8, 0x63ddffd5, 0xae7ffaef, 0x34244240, 0xf986477a, 0xd3d40817, 0x1e760d2d, 0x89d6a9b9, 0x4474ac83, 0x6e26e3ee, 0xa384e6d4, 0x39df5e7b, 0xf47d5b41, 0xde2f142c, 0x138d1116, 0x2ed4d4cb, 0xe376d1f1, 0xc9249e9c, 0x04869ba6, 0x9edd2309, 0x537f2633, 0x792d695e, 0xb48f6c64, 0x232fc8f0, 0xee8dcdca, 0xc4df82a7, 0x097d879d, 0x93263f32, 0x5e843a08, 0x74d67565, 0xb974705f, 0xe2659f8b, 0x2fc79ab1, 0x0595d5dc, 0xc837d0e6, 0x526c6849, 0x9fce6d73, 0xb59c221e, 0x783e2724, 0xef9e83b0, 0x223c868a, 0x086ec9e7, 0xc5ccccdd, 0x5f977472, 0x92357148, 0xb8673e25, 0x75c53b1f, 0x489cfec2, 0x853efbf8, 0xaf6cb495, 0x62ceb1af, 0xf8950900, 0x35370c3a, 0x1f654357, 0xd2c7466d, 0x4567e2f9, 0x88c5e7c3, 0xa297a8ae, 0x6f35ad94, 0xf56e153b, 0x38cc1001, 0x129e5f6c, 0xdf3c5a56, 0x789a9f86, 0xb5389abc, 0x9f6ad5d1, 0x52c8d0eb, 0xc8936844, 0x05316d7e, 0x2f632213, 0xe2c12729, 0x756183bd, 0xb8c38687, 0x9291c9ea, 0x5f33ccd0, 0xc568747f, 0x08ca7145, 0x22983e28, 0xef3a3b12, 0xd263fecf, 0x1fc1fbf5, 0x3593b498, 0xf831b1a2, 0x626a090d, 0xafc80c37, 0x859a435a, 0x48384660, 0xdf98e2f4, 0x123ae7ce, 0x3868a8a3, 0xf5caad99, 0x6f911536, 0xa233100c, 0x88615f61, 0x45c35a5b, 0x1ed2b58f, 0xd370b0b5, 0xf922ffd8, 0x3480fae2, 0xaedb424d, 0x63794777, 0x492b081a, 0x84890d20, 0x1329a9b4, 0xde8bac8e, 0xf4d9e3e3, 0x397be6d9, 0xa3205e76, 0x6e825b4c, 0x44d01421, 0x8972111b, 0xb42bd4c6, 0x7989d1fc, 0x53db9e91, 0x9e799bab, 0x04222304, 0xc980263e, 0xe3d26953, 0x2e706c69, 0xb9d0c8fd, 0x7472cdc7, 0x5e2082aa, 0x93828790, 0x09d93f3f, 0xc47b3a05, 0xee297568, 0x238b7052, 0xfcb72a04, 0x31152f3e, 0x1b476053, 0xd6e56569, 0x4cbeddc6, 0x811cd8fc, 0xab4e9791, 0x66ec92ab, 0xf14c363f, 0x3cee3305, 0x16bc7c68, 0xdb1e7952, 0x4145c1fd, 0x8ce7c4c7, 0xa6b58baa, 0x6b178e90, 0x564e4b4d, 0x9bec4e77, 0xb1be011a, 0x7c1c0420, 0xe647bc8f, 0x2be5b9b5, 0x01b7f6d8, 0xcc15f3e2, 0x5bb55776, 0x9617524c, 0xbc451d21, 0x71e7181b, 0xebbca0b4, 0x261ea58e, 0x0c4ceae3, 0xc1eeefd9, 0x9aff000d, 0x575d0537, 0x7d0f4a5a, 0xb0ad4f60, 0x2af6f7cf, 0xe754f2f5, 0xcd06bd98, 0x00a4b8a2, 0x97041c36, 0x5aa6190c, 0x70f45661, 0xbd56535b, 0x270debf4, 0xeaafeece, 0xc0fda1a3, 0x0d5fa499, 0x30066144, 0xfda4647e, 0xd7f62b13, 0x1a542e29, 0x800f9686, 0x4dad93bc, 0x67ffdcd1, 0xaa5dd9eb, 0x3dfd7d7f, 0xf05f7845, 0xda0d3728, 0x17af3212, 0x8df48abd, 0x40568f87, 0x6a04c0ea, 0xa7a6c5d0 +}, +{ +0x00000000, 0x50eaec40, 0x3fd119a1, 0x6f3bf5e1, 0x370ebc7c, 0x67e4503c, 0x08dfa5dd, 0x5835499d, 0xb3ea028f, 0xe300eecf, 0x8c3b1b2e, 0xdcd1f76e, 0x84e4bef3, 0xd40e52b3, 0xbb35a752, 0xebdf4b12, 0x1515630d, 0x45ff8f4d, 0x2ac47aac, 0x7a2e96ec, 0x221bdf71, 0x72f13331, 0x1dcac6d0, 0x4d202a90, 0xa6ff6182, 0xf6158dc2, 0x992e7823, 0xc9c49463, 0x91f1ddfe, 0xc11b31be, 0xae20c45f, 0xfeca281f, 0x1cd13001, 0x4c3bdc41, 0x230029a0, 0x73eac5e0, 0x2bdf8c7d, 0x7b35603d, 0x140e95dc, 0x44e4799c, 0xaf3b328e, 0xffd1dece, 0x90ea2b2f, 0xc000c76f, 0x98358ef2, 0xc8df62b2, 0xa7e49753, 0xf70e7b13, 0x09c4530c, 0x592ebf4c, 0x36154aad, 0x66ffa6ed, 0x3ecaef70, 0x6e200330, 0x011bf6d1, 0x51f11a91, 0xba2e5183, 0xeac4bdc3, 0x85ff4822, 0xd515a462, 0x8d20edff, 0xddca01bf, 0xb2f1f45e, 0xe21b181e, 0xd7896a48, 0x87638608, 0xe85873e9, 0xb8b29fa9, 0xe087d634, 0xb06d3a74, 0xdf56cf95, 0x8fbc23d5, 0x646368c7, 0x34898487, 0x5bb27166, 0x0b589d26, 0x536dd4bb, 0x038738fb, 0x6cbccd1a, 0x3c56215a, 0xc29c0945, 0x9276e505, 0xfd4d10e4, 0xada7fca4, 0xf592b539, 0xa5785979, 0xca43ac98, 0x9aa940d8, 0x71760bca, 0x219ce78a, 0x4ea7126b, 0x1e4dfe2b, 0x4678b7b6, 0x16925bf6, 0x79a9ae17, 0x29434257, 0xcb585a49, 0x9bb2b609, 0xf48943e8, 0xa463afa8, 0xfc56e635, 0xacbc0a75, 0xc387ff94, 0x936d13d4, 0x78b258c6, 0x2858b486, 0x47634167, 0x1789ad27, 0x4fbce4ba, 0x1f5608fa, 0x706dfd1b, 0x2087115b, 0xde4d3944, 0x8ea7d504, 0xe19c20e5, 0xb176cca5, 0xe9438538, 0xb9a96978, 0xd6929c99, 0x867870d9, 0x6da73bcb, 0x3d4dd78b, 0x5276226a, 0x029cce2a, 0x5aa987b7, 0x0a436bf7, 0x65789e16, 0x35927256, 0x973b31e4, 0xc7d1dda4, 0xa8ea2845, 0xf800c405, 0xa0358d98, 0xf0df61d8, 0x9fe49439, 0xcf0e7879, 0x24d1336b, 0x743bdf2b, 0x1b002aca, 0x4beac68a, 0x13df8f17, 0x43356357, 0x2c0e96b6, 0x7ce47af6, 0x822e52e9, 0xd2c4bea9, 0xbdff4b48, 0xed15a708, 0xb520ee95, 0xe5ca02d5, 0x8af1f734, 0xda1b1b74, 0x31c45066, 0x612ebc26, 0x0e1549c7, 0x5effa587, 0x06caec1a, 0x5620005a, 0x391bf5bb, 0x69f119fb, 0x8bea01e5, 0xdb00eda5, 0xb43b1844, 0xe4d1f404, 0xbce4bd99, 0xec0e51d9, 0x8335a438, 0xd3df4878, 0x3800036a, 0x68eaef2a, 0x07d11acb, 0x573bf68b, 0x0f0ebf16, 0x5fe45356, 0x30dfa6b7, 0x60354af7, 0x9eff62e8, 0xce158ea8, 0xa12e7b49, 0xf1c49709, 0xa9f1de94, 0xf91b32d4, 0x9620c735, 0xc6ca2b75, 0x2d156067, 0x7dff8c27, 0x12c479c6, 0x422e9586, 0x1a1bdc1b, 0x4af1305b, 0x25cac5ba, 0x752029fa, 0x40b25bac, 0x1058b7ec, 0x7f63420d, 0x2f89ae4d, 0x77bce7d0, 0x27560b90, 0x486dfe71, 0x18871231, 0xf3585923, 0xa3b2b563, 0xcc894082, 0x9c63acc2, 0xc456e55f, 0x94bc091f, 0xfb87fcfe, 0xab6d10be, 0x55a738a1, 0x054dd4e1, 0x6a762100, 0x3a9ccd40, 0x62a984dd, 0x3243689d, 0x5d789d7c, 0x0d92713c, 0xe64d3a2e, 0xb6a7d66e, 0xd99c238f, 0x8976cfcf, 0xd1438652, 0x81a96a12, 0xee929ff3, 0xbe7873b3, 0x5c636bad, 0x0c8987ed, 0x63b2720c, 0x33589e4c, 0x6b6dd7d1, 0x3b873b91, 0x54bcce70, 0x04562230, 0xef896922, 0xbf638562, 0xd0587083, 0x80b29cc3, 0xd887d55e, 0x886d391e, 0xe756ccff, 0xb7bc20bf, 0x497608a0, 0x199ce4e0, 0x76a71101, 0x264dfd41, 0x7e78b4dc, 0x2e92589c, 0x41a9ad7d, 0x1143413d, 0xfa9c0a2f, 0xaa76e66f, 0xc54d138e, 0x95a7ffce, 0xcd92b653, 0x9d785a13, 0xf243aff2, 0xa2a943b2 +}, +{ +0x00000000, 0xbae43090, 0xe0ab9a38, 0x5a4faaa8, 0xd2ac54b8, 0x68486428, 0x3207ce80, 0x88e3fe10, 0xf0864d9c, 0x4a627d0c, 0x102dd7a4, 0xaac9e734, 0x222a1924, 0x98ce29b4, 0xc281831c, 0x7865b38c, 0xc08e6725, 0x7a6a57b5, 0x2025fd1d, 0x9ac1cd8d, 0x1222339d, 0xa8c6030d, 0xf289a9a5, 0x486d9935, 0x30082ab9, 0x8aec1a29, 0xd0a3b081, 0x6a478011, 0xe2a47e01, 0x58404e91, 0x020fe439, 0xb8ebd4a9, 0x2980b6ca, 0x9364865a, 0xc92b2cf2, 0x73cf1c62, 0xfb2ce272, 0x41c8d2e2, 0x1b87784a, 0xa16348da, 0xd906fb56, 0x63e2cbc6, 0x39ad616e, 0x834951fe, 0x0baaafee, 0xb14e9f7e, 0xeb0135d6, 0x51e50546, 0xe90ed1ef, 0x53eae17f, 0x09a54bd7, 0xb3417b47, 0x3ba28557, 0x8146b5c7, 0xdb091f6f, 0x61ed2fff, 0x19889c73, 0xa36cace3, 0xf923064b, 0x43c736db, 0xcb24c8cb, 0x71c0f85b, 0x2b8f52f3, 0x916b6263, 0xe7f7c3c8, 0x5d13f358, 0x075c59f0, 0xbdb86960, 0x355b9770, 0x8fbfa7e0, 0xd5f00d48, 0x6f143dd8, 0x17718e54, 0xad95bec4, 0xf7da146c, 0x4d3e24fc, 0xc5dddaec, 0x7f39ea7c, 0x257640d4, 0x9f927044, 0x2779a4ed, 0x9d9d947d, 0xc7d23ed5, 0x7d360e45, 0xf5d5f055, 0x4f31c0c5, 0x157e6a6d, 0xaf9a5afd, 0xd7ffe971, 0x6d1bd9e1, 0x37547349, 0x8db043d9, 0x0553bdc9, 0xbfb78d59, 0xe5f827f1, 0x5f1c1761, 0xce777502, 0x74934592, 0x2edcef3a, 0x9438dfaa, 0x1cdb21ba, 0xa63f112a, 0xfc70bb82, 0x46948b12, 0x3ef1389e, 0x8415080e, 0xde5aa2a6, 0x64be9236, 0xec5d6c26, 0x56b95cb6, 0x0cf6f61e, 0xb612c68e, 0x0ef91227, 0xb41d22b7, 0xee52881f, 0x54b6b88f, 0xdc55469f, 0x66b1760f, 0x3cfedca7, 0x861aec37, 0xfe7f5fbb, 0x449b6f2b, 0x1ed4c583, 0xa430f513, 0x2cd30b03, 0x96373b93, 0xcc78913b, 0x769ca1ab, 0xc1b17176, 0x7b5541e6, 0x211aeb4e, 0x9bfedbde, 0x131d25ce, 0xa9f9155e, 0xf3b6bff6, 0x49528f66, 0x31373cea, 0x8bd30c7a, 0xd19ca6d2, 0x6b789642, 0xe39b6852, 0x597f58c2, 0x0330f26a, 0xb9d4c2fa, 0x013f1653, 0xbbdb26c3, 0xe1948c6b, 0x5b70bcfb, 0xd39342eb, 0x6977727b, 0x3338d8d3, 0x89dce843, 0xf1b95bcf, 0x4b5d6b5f, 0x1112c1f7, 0xabf6f167, 0x23150f77, 0x99f13fe7, 0xc3be954f, 0x795aa5df, 0xe831c7bc, 0x52d5f72c, 0x089a5d84, 0xb27e6d14, 0x3a9d9304, 0x8079a394, 0xda36093c, 0x60d239ac, 0x18b78a20, 0xa253bab0, 0xf81c1018, 0x42f82088, 0xca1bde98, 0x70ffee08, 0x2ab044a0, 0x90547430, 0x28bfa099, 0x925b9009, 0xc8143aa1, 0x72f00a31, 0xfa13f421, 0x40f7c4b1, 0x1ab86e19, 0xa05c5e89, 0xd839ed05, 0x62dddd95, 0x3892773d, 0x827647ad, 0x0a95b9bd, 0xb071892d, 0xea3e2385, 0x50da1315, 0x2646b2be, 0x9ca2822e, 0xc6ed2886, 0x7c091816, 0xf4eae606, 0x4e0ed696, 0x14417c3e, 0xaea54cae, 0xd6c0ff22, 0x6c24cfb2, 0x366b651a, 0x8c8f558a, 0x046cab9a, 0xbe889b0a, 0xe4c731a2, 0x5e230132, 0xe6c8d59b, 0x5c2ce50b, 0x06634fa3, 0xbc877f33, 0x34648123, 0x8e80b1b3, 0xd4cf1b1b, 0x6e2b2b8b, 0x164e9807, 0xacaaa897, 0xf6e5023f, 0x4c0132af, 0xc4e2ccbf, 0x7e06fc2f, 0x24495687, 0x9ead6617, 0x0fc60474, 0xb52234e4, 0xef6d9e4c, 0x5589aedc, 0xdd6a50cc, 0x678e605c, 0x3dc1caf4, 0x8725fa64, 0xff4049e8, 0x45a47978, 0x1febd3d0, 0xa50fe340, 0x2dec1d50, 0x97082dc0, 0xcd478768, 0x77a3b7f8, 0xcf486351, 0x75ac53c1, 0x2fe3f969, 0x9507c9f9, 0x1de437e9, 0xa7000779, 0xfd4fadd1, 0x47ab9d41, 0x3fce2ecd, 0x852a1e5d, 0xdf65b4f5, 0x65818465, 0xed627a75, 0x57864ae5, 0x0dc9e04d, 0xb72dd0dd +}, +{ +0x00000000, 0x2c13451e, 0x6cf43811, 0x40e77d0f, 0x57b91cf2, 0x7baa59ec, 0x3b4d24e3, 0x175e61fd, 0xa8ab6716, 0x84b82208, 0xc45f5f07, 0xe84c1a19, 0xff127be4, 0xd3013efa, 0x93e643f5, 0xbff506eb, 0x5c55eb8b, 0x7046ae95, 0x30a1d39a, 0x1cb29684, 0x0becf779, 0x27ffb267, 0x6718cf68, 0x4b0b8a76, 0xf4fe8c9d, 0xd8edc983, 0x980ab48c, 0xb419f192, 0xa347906f, 0x8f54d571, 0xcfb3a87e, 0xe3a0ed60, 0x615920af, 0x4d4a65b1, 0x0dad18be, 0x21be5da0, 0x36e03c5d, 0x1af37943, 0x5a14044c, 0x76074152, 0xc9f247b9, 0xe5e102a7, 0xa5067fa8, 0x89153ab6, 0x9e4b5b4b, 0xb2581e55, 0xf2bf635a, 0xdeac2644, 0x3d0ccb24, 0x111f8e3a, 0x51f8f335, 0x7debb62b, 0x6ab5d7d6, 0x46a692c8, 0x0641efc7, 0x2a52aad9, 0x95a7ac32, 0xb9b4e92c, 0xf9539423, 0xd540d13d, 0xc21eb0c0, 0xee0df5de, 0xaeea88d1, 0x82f9cdcf, 0x840b8b72, 0xa818ce6c, 0xe8ffb363, 0xc4ecf67d, 0xd3b29780, 0xffa1d29e, 0xbf46af91, 0x9355ea8f, 0x2ca0ec64, 0x00b3a97a, 0x4054d475, 0x6c47916b, 0x7b19f096, 0x570ab588, 0x17edc887, 0x3bfe8d99, 0xd85e60f9, 0xf44d25e7, 0xb4aa58e8, 0x98b91df6, 0x8fe77c0b, 0xa3f43915, 0xe313441a, 0xcf000104, 0x70f507ef, 0x5ce642f1, 0x1c013ffe, 0x30127ae0, 0x274c1b1d, 0x0b5f5e03, 0x4bb8230c, 0x67ab6612, 0xe552abdd, 0xc941eec3, 0x89a693cc, 0xa5b5d6d2, 0xb2ebb72f, 0x9ef8f231, 0xde1f8f3e, 0xf20cca20, 0x4df9cccb, 0x61ea89d5, 0x210df4da, 0x0d1eb1c4, 0x1a40d039, 0x36539527, 0x76b4e828, 0x5aa7ad36, 0xb9074056, 0x95140548, 0xd5f37847, 0xf9e03d59, 0xeebe5ca4, 0xc2ad19ba, 0x824a64b5, 0xae5921ab, 0x11ac2740, 0x3dbf625e, 0x7d581f51, 0x514b5a4f, 0x46153bb2, 0x6a067eac, 0x2ae103a3, 0x06f246bd, 0x688122c3, 0x449267dd, 0x04751ad2, 0x28665fcc, 0x3f383e31, 0x132b7b2f, 0x53cc0620, 0x7fdf433e, 0xc02a45d5, 0xec3900cb, 0xacde7dc4, 0x80cd38da, 0x97935927, 0xbb801c39, 0xfb676136, 0xd7742428, 0x34d4c948, 0x18c78c56, 0x5820f159, 0x7433b447, 0x636dd5ba, 0x4f7e90a4, 0x0f99edab, 0x238aa8b5, 0x9c7fae5e, 0xb06ceb40, 0xf08b964f, 0xdc98d351, 0xcbc6b2ac, 0xe7d5f7b2, 0xa7328abd, 0x8b21cfa3, 0x09d8026c, 0x25cb4772, 0x652c3a7d, 0x493f7f63, 0x5e611e9e, 0x72725b80, 0x3295268f, 0x1e866391, 0xa173657a, 0x8d602064, 0xcd875d6b, 0xe1941875, 0xf6ca7988, 0xdad93c96, 0x9a3e4199, 0xb62d0487, 0x558de9e7, 0x799eacf9, 0x3979d1f6, 0x156a94e8, 0x0234f515, 0x2e27b00b, 0x6ec0cd04, 0x42d3881a, 0xfd268ef1, 0xd135cbef, 0x91d2b6e0, 0xbdc1f3fe, 0xaa9f9203, 0x868cd71d, 0xc66baa12, 0xea78ef0c, 0xec8aa9b1, 0xc099ecaf, 0x807e91a0, 0xac6dd4be, 0xbb33b543, 0x9720f05d, 0xd7c78d52, 0xfbd4c84c, 0x4421cea7, 0x68328bb9, 0x28d5f6b6, 0x04c6b3a8, 0x1398d255, 0x3f8b974b, 0x7f6cea44, 0x537faf5a, 0xb0df423a, 0x9ccc0724, 0xdc2b7a2b, 0xf0383f35, 0xe7665ec8, 0xcb751bd6, 0x8b9266d9, 0xa78123c7, 0x1874252c, 0x34676032, 0x74801d3d, 0x58935823, 0x4fcd39de, 0x63de7cc0, 0x233901cf, 0x0f2a44d1, 0x8dd3891e, 0xa1c0cc00, 0xe127b10f, 0xcd34f411, 0xda6a95ec, 0xf679d0f2, 0xb69eadfd, 0x9a8de8e3, 0x2578ee08, 0x096bab16, 0x498cd619, 0x659f9307, 0x72c1f2fa, 0x5ed2b7e4, 0x1e35caeb, 0x32268ff5, 0xd1866295, 0xfd95278b, 0xbd725a84, 0x91611f9a, 0x863f7e67, 0xaa2c3b79, 0xeacb4676, 0xc6d80368, 0x792d0583, 0x553e409d, 0x15d93d92, 0x39ca788c, 0x2e941971, 0x02875c6f, 0x42602160, 0x6e73647e +}, +{ +0x00000000, 0xbe4c7e13, 0x729f1ce1, 0xccd362f2, 0x70f78511, 0xcebbfb02, 0x026899f0, 0xbc24e7e3, 0x20f989dc, 0x9eb5f7cf, 0x5266953d, 0xec2aeb2e, 0x500e0ccd, 0xee4272de, 0x2291102c, 0x9cdd6e3f, 0x182060bd, 0xa66c1eae, 0x6abf7c5c, 0xd4f3024f, 0x68d7e5ac, 0xd69b9bbf, 0x1a48f94d, 0xa404875e, 0x38d9e961, 0x86959772, 0x4a46f580, 0xf40a8b93, 0x482e6c70, 0xf6621263, 0x3ab17091, 0x84fd0e82, 0x313eb104, 0x8f72cf17, 0x43a1ade5, 0xfdedd3f6, 0x41c93415, 0xff854a06, 0x335628f4, 0x8d1a56e7, 0x11c738d8, 0xaf8b46cb, 0x63582439, 0xdd145a2a, 0x6130bdc9, 0xdf7cc3da, 0x13afa128, 0xade3df3b, 0x291ed1b9, 0x9752afaa, 0x5b81cd58, 0xe5cdb34b, 0x59e954a8, 0xe7a52abb, 0x2b764849, 0x953a365a, 0x09e75865, 0xb7ab2676, 0x7b784484, 0xc5343a97, 0x7910dd74, 0xc75ca367, 0x0b8fc195, 0xb5c3bf86, 0x5d184e3d, 0xe354302e, 0x2f8752dc, 0x91cb2ccf, 0x2defcb2c, 0x93a3b53f, 0x5f70d7cd, 0xe13ca9de, 0x7de1c7e1, 0xc3adb9f2, 0x0f7edb00, 0xb132a513, 0x0d1642f0, 0xb35a3ce3, 0x7f895e11, 0xc1c52002, 0x45382e80, 0xfb745093, 0x37a73261, 0x89eb4c72, 0x35cfab91, 0x8b83d582, 0x4750b770, 0xf91cc963, 0x65c1a75c, 0xdb8dd94f, 0x175ebbbd, 0xa912c5ae, 0x1536224d, 0xab7a5c5e, 0x67a93eac, 0xd9e540bf, 0x6c26ff39, 0xd26a812a, 0x1eb9e3d8, 0xa0f59dcb, 0x1cd17a28, 0xa29d043b, 0x6e4e66c9, 0xd00218da, 0x4cdf76e5, 0xf29308f6, 0x3e406a04, 0x800c1417, 0x3c28f3f4, 0x82648de7, 0x4eb7ef15, 0xf0fb9106, 0x74069f84, 0xca4ae197, 0x06998365, 0xb8d5fd76, 0x04f11a95, 0xbabd6486, 0x766e0674, 0xc8227867, 0x54ff1658, 0xeab3684b, 0x26600ab9, 0x982c74aa, 0x24089349, 0x9a44ed5a, 0x56978fa8, 0xe8dbf1bb, 0xd8a587db, 0x66e9f9c8, 0xaa3a9b3a, 0x1476e529, 0xa85202ca, 0x161e7cd9, 0xdacd1e2b, 0x64816038, 0xf85c0e07, 0x46107014, 0x8ac312e6, 0x348f6cf5, 0x88ab8b16, 0x36e7f505, 0xfa3497f7, 0x4478e9e4, 0xc085e766, 0x7ec99975, 0xb21afb87, 0x0c568594, 0xb0726277, 0x0e3e1c64, 0xc2ed7e96, 0x7ca10085, 0xe07c6eba, 0x5e3010a9, 0x92e3725b, 0x2caf0c48, 0x908bebab, 0x2ec795b8, 0xe214f74a, 0x5c588959, 0xe99b36df, 0x57d748cc, 0x9b042a3e, 0x2548542d, 0x996cb3ce, 0x2720cddd, 0xebf3af2f, 0x55bfd13c, 0xc962bf03, 0x772ec110, 0xbbfda3e2, 0x05b1ddf1, 0xb9953a12, 0x07d94401, 0xcb0a26f3, 0x754658e0, 0xf1bb5662, 0x4ff72871, 0x83244a83, 0x3d683490, 0x814cd373, 0x3f00ad60, 0xf3d3cf92, 0x4d9fb181, 0xd142dfbe, 0x6f0ea1ad, 0xa3ddc35f, 0x1d91bd4c, 0xa1b55aaf, 0x1ff924bc, 0xd32a464e, 0x6d66385d, 0x85bdc9e6, 0x3bf1b7f5, 0xf722d507, 0x496eab14, 0xf54a4cf7, 0x4b0632e4, 0x87d55016, 0x39992e05, 0xa544403a, 0x1b083e29, 0xd7db5cdb, 0x699722c8, 0xd5b3c52b, 0x6bffbb38, 0xa72cd9ca, 0x1960a7d9, 0x9d9da95b, 0x23d1d748, 0xef02b5ba, 0x514ecba9, 0xed6a2c4a, 0x53265259, 0x9ff530ab, 0x21b94eb8, 0xbd642087, 0x03285e94, 0xcffb3c66, 0x71b74275, 0xcd93a596, 0x73dfdb85, 0xbf0cb977, 0x0140c764, 0xb48378e2, 0x0acf06f1, 0xc61c6403, 0x78501a10, 0xc474fdf3, 0x7a3883e0, 0xb6ebe112, 0x08a79f01, 0x947af13e, 0x2a368f2d, 0xe6e5eddf, 0x58a993cc, 0xe48d742f, 0x5ac10a3c, 0x961268ce, 0x285e16dd, 0xaca3185f, 0x12ef664c, 0xde3c04be, 0x60707aad, 0xdc549d4e, 0x6218e35d, 0xaecb81af, 0x1087ffbc, 0x8c5a9183, 0x3216ef90, 0xfec58d62, 0x4089f371, 0xfcad1492, 0x42e16a81, 0x8e320873, 0x307e7660 +} +}, +{ +{ +0x00000000, 0x9892da84, 0x8b2b0bef, 0x13b9d16b, 0xf5a76cd2, 0x6d35b656, 0x7e8c673d, 0xe61ebdb9, 0x8ef6dd2e, 0x166407aa, 0x05ddd6c1, 0x9d4f0c45, 0x7b51b1fc, 0xe3c36b78, 0xf07aba13, 0x68e86097, 0xf0113986, 0x6883e302, 0x7b3a3269, 0xe3a8e8ed, 0x05b65554, 0x9d248fd0, 0x8e9d5ebb, 0x160f843f, 0x7ee7e4a8, 0xe6753e2c, 0xf5ccef47, 0x6d5e35c3, 0x8b40887a, 0x13d252fe, 0x006b8395, 0x98f95911, 0x01885bc1, 0x991a8145, 0x8aa3502e, 0x12318aaa, 0xf42f3713, 0x6cbded97, 0x7f043cfc, 0xe796e678, 0x8f7e86ef, 0x17ec5c6b, 0x04558d00, 0x9cc75784, 0x7ad9ea3d, 0xe24b30b9, 0xf1f2e1d2, 0x69603b56, 0xf1996247, 0x690bb8c3, 0x7ab269a8, 0xe220b32c, 0x043e0e95, 0x9cacd411, 0x8f15057a, 0x1787dffe, 0x7f6fbf69, 0xe7fd65ed, 0xf444b486, 0x6cd66e02, 0x8ac8d3bb, 0x125a093f, 0x01e3d854, 0x997102d0, 0xeb0cff1e, 0x739e259a, 0x6027f4f1, 0xf8b52e75, 0x1eab93cc, 0x86394948, 0x95809823, 0x0d1242a7, 0x65fa2230, 0xfd68f8b4, 0xeed129df, 0x7643f35b, 0x905d4ee2, 0x08cf9466, 0x1b76450d, 0x83e49f89, 0x1b1dc698, 0x838f1c1c, 0x9036cd77, 0x08a417f3, 0xeebaaa4a, 0x762870ce, 0x6591a1a5, 0xfd037b21, 0x95eb1bb6, 0x0d79c132, 0x1ec01059, 0x8652cadd, 0x604c7764, 0xf8deade0, 0xeb677c8b, 0x73f5a60f, 0xea84a4df, 0x72167e5b, 0x61afaf30, 0xf93d75b4, 0x1f23c80d, 0x87b11289, 0x9408c3e2, 0x0c9a1966, 0x647279f1, 0xfce0a375, 0xef59721e, 0x77cba89a, 0x91d51523, 0x0947cfa7, 0x1afe1ecc, 0x826cc448, 0x1a959d59, 0x820747dd, 0x91be96b6, 0x092c4c32, 0xef32f18b, 0x77a02b0f, 0x6419fa64, 0xfc8b20e0, 0x94634077, 0x0cf19af3, 0x1f484b98, 0x87da911c, 0x61c42ca5, 0xf956f621, 0xeaef274a, 0x727dfdce, 0x3f230b8f, 0xa7b1d10b, 0xb4080060, 0x2c9adae4, 0xca84675d, 0x5216bdd9, 0x41af6cb2, 0xd93db636, 0xb1d5d6a1, 0x29470c25, 0x3afedd4e, 0xa26c07ca, 0x4472ba73, 0xdce060f7, 0xcf59b19c, 0x57cb6b18, 0xcf323209, 0x57a0e88d, 0x441939e6, 0xdc8be362, 0x3a955edb, 0xa207845f, 0xb1be5534, 0x292c8fb0, 0x41c4ef27, 0xd95635a3, 0xcaefe4c8, 0x527d3e4c, 0xb46383f5, 0x2cf15971, 0x3f48881a, 0xa7da529e, 0x3eab504e, 0xa6398aca, 0xb5805ba1, 0x2d128125, 0xcb0c3c9c, 0x539ee618, 0x40273773, 0xd8b5edf7, 0xb05d8d60, 0x28cf57e4, 0x3b76868f, 0xa3e45c0b, 0x45fae1b2, 0xdd683b36, 0xced1ea5d, 0x564330d9, 0xceba69c8, 0x5628b34c, 0x45916227, 0xdd03b8a3, 0x3b1d051a, 0xa38fdf9e, 0xb0360ef5, 0x28a4d471, 0x404cb4e6, 0xd8de6e62, 0xcb67bf09, 0x53f5658d, 0xb5ebd834, 0x2d7902b0, 0x3ec0d3db, 0xa652095f, 0xd42ff491, 0x4cbd2e15, 0x5f04ff7e, 0xc79625fa, 0x21889843, 0xb91a42c7, 0xaaa393ac, 0x32314928, 0x5ad929bf, 0xc24bf33b, 0xd1f22250, 0x4960f8d4, 0xaf7e456d, 0x37ec9fe9, 0x24554e82, 0xbcc79406, 0x243ecd17, 0xbcac1793, 0xaf15c6f8, 0x37871c7c, 0xd199a1c5, 0x490b7b41, 0x5ab2aa2a, 0xc22070ae, 0xaac81039, 0x325acabd, 0x21e31bd6, 0xb971c152, 0x5f6f7ceb, 0xc7fda66f, 0xd4447704, 0x4cd6ad80, 0xd5a7af50, 0x4d3575d4, 0x5e8ca4bf, 0xc61e7e3b, 0x2000c382, 0xb8921906, 0xab2bc86d, 0x33b912e9, 0x5b51727e, 0xc3c3a8fa, 0xd07a7991, 0x48e8a315, 0xaef61eac, 0x3664c428, 0x25dd1543, 0xbd4fcfc7, 0x25b696d6, 0xbd244c52, 0xae9d9d39, 0x360f47bd, 0xd011fa04, 0x48832080, 0x5b3af1eb, 0xc3a82b6f, 0xab404bf8, 0x33d2917c, 0x206b4017, 0xb8f99a93, 0x5ee7272a, 0xc675fdae, 0xd5cc2cc5, 0x4d5ef641 +}, +{ +0x00000000, 0x8ae1f9c5, 0xc5884b52, 0x4f69b297, 0x8f929143, 0x05736886, 0x4a1ada11, 0xc0fb23d4, 0xbb383967, 0x31d9c0a2, 0x7eb07235, 0xf4518bf0, 0x34aaa824, 0xbe4b51e1, 0xf122e376, 0x7bc31ab3, 0xaed15c7c, 0x2430a5b9, 0x6b59172e, 0xe1b8eeeb, 0x2143cd3f, 0xaba234fa, 0xe4cb866d, 0x6e2a7fa8, 0x15e9651b, 0x9f089cde, 0xd0612e49, 0x5a80d78c, 0x9a7bf458, 0x109a0d9d, 0x5ff3bf0a, 0xd51246cf, 0xf75c81f6, 0x7dbd7833, 0x32d4caa4, 0xb8353361, 0x78ce10b5, 0xf22fe970, 0xbd465be7, 0x37a7a222, 0x4c64b891, 0xc6854154, 0x89ecf3c3, 0x030d0a06, 0xc3f629d2, 0x4917d017, 0x067e6280, 0x8c9f9b45, 0x598ddd8a, 0xd36c244f, 0x9c0596d8, 0x16e46f1d, 0xd61f4cc9, 0x5cfeb50c, 0x1397079b, 0x9976fe5e, 0xe2b5e4ed, 0x68541d28, 0x273dafbf, 0xaddc567a, 0x6d2775ae, 0xe7c68c6b, 0xa8af3efc, 0x224ec739, 0xfbb2efd3, 0x71531616, 0x3e3aa481, 0xb4db5d44, 0x74207e90, 0xfec18755, 0xb1a835c2, 0x3b49cc07, 0x408ad6b4, 0xca6b2f71, 0x85029de6, 0x0fe36423, 0xcf1847f7, 0x45f9be32, 0x0a900ca5, 0x8071f560, 0x5563b3af, 0xdf824a6a, 0x90ebf8fd, 0x1a0a0138, 0xdaf122ec, 0x5010db29, 0x1f7969be, 0x9598907b, 0xee5b8ac8, 0x64ba730d, 0x2bd3c19a, 0xa132385f, 0x61c91b8b, 0xeb28e24e, 0xa44150d9, 0x2ea0a91c, 0x0cee6e25, 0x860f97e0, 0xc9662577, 0x4387dcb2, 0x837cff66, 0x099d06a3, 0x46f4b434, 0xcc154df1, 0xb7d65742, 0x3d37ae87, 0x725e1c10, 0xf8bfe5d5, 0x3844c601, 0xb2a53fc4, 0xfdcc8d53, 0x772d7496, 0xa23f3259, 0x28decb9c, 0x67b7790b, 0xed5680ce, 0x2dada31a, 0xa74c5adf, 0xe825e848, 0x62c4118d, 0x19070b3e, 0x93e6f2fb, 0xdc8f406c, 0x566eb9a9, 0x96959a7d, 0x1c7463b8, 0x531dd12f, 0xd9fc28ea, 0xa333b3bd, 0x29d24a78, 0x66bbf8ef, 0xec5a012a, 0x2ca122fe, 0xa640db3b, 0xe92969ac, 0x63c89069, 0x180b8ada, 0x92ea731f, 0xdd83c188, 0x5762384d, 0x97991b99, 0x1d78e25c, 0x521150cb, 0xd8f0a90e, 0x0de2efc1, 0x87031604, 0xc86aa493, 0x428b5d56, 0x82707e82, 0x08918747, 0x47f835d0, 0xcd19cc15, 0xb6dad6a6, 0x3c3b2f63, 0x73529df4, 0xf9b36431, 0x394847e5, 0xb3a9be20, 0xfcc00cb7, 0x7621f572, 0x546f324b, 0xde8ecb8e, 0x91e77919, 0x1b0680dc, 0xdbfda308, 0x511c5acd, 0x1e75e85a, 0x9494119f, 0xef570b2c, 0x65b6f2e9, 0x2adf407e, 0xa03eb9bb, 0x60c59a6f, 0xea2463aa, 0xa54dd13d, 0x2fac28f8, 0xfabe6e37, 0x705f97f2, 0x3f362565, 0xb5d7dca0, 0x752cff74, 0xffcd06b1, 0xb0a4b426, 0x3a454de3, 0x41865750, 0xcb67ae95, 0x840e1c02, 0x0eefe5c7, 0xce14c613, 0x44f53fd6, 0x0b9c8d41, 0x817d7484, 0x58815c6e, 0xd260a5ab, 0x9d09173c, 0x17e8eef9, 0xd713cd2d, 0x5df234e8, 0x129b867f, 0x987a7fba, 0xe3b96509, 0x69589ccc, 0x26312e5b, 0xacd0d79e, 0x6c2bf44a, 0xe6ca0d8f, 0xa9a3bf18, 0x234246dd, 0xf6500012, 0x7cb1f9d7, 0x33d84b40, 0xb939b285, 0x79c29151, 0xf3236894, 0xbc4ada03, 0x36ab23c6, 0x4d683975, 0xc789c0b0, 0x88e07227, 0x02018be2, 0xc2faa836, 0x481b51f3, 0x0772e364, 0x8d931aa1, 0xafdddd98, 0x253c245d, 0x6a5596ca, 0xe0b46f0f, 0x204f4cdb, 0xaaaeb51e, 0xe5c70789, 0x6f26fe4c, 0x14e5e4ff, 0x9e041d3a, 0xd16dafad, 0x5b8c5668, 0x9b7775bc, 0x11968c79, 0x5eff3eee, 0xd41ec72b, 0x010c81e4, 0x8bed7821, 0xc484cab6, 0x4e653373, 0x8e9e10a7, 0x047fe962, 0x4b165bf5, 0xc1f7a230, 0xba34b883, 0x30d54146, 0x7fbcf3d1, 0xf55d0a14, 0x35a629c0, 0xbf47d005, 0xf02e6292, 0x7acf9b57 +}, +{ +0x00000000, 0xd4b44853, 0x79d271bb, 0xad6639e8, 0x379845b7, 0xe32c0de4, 0x4e4a340c, 0x9afe7c5f, 0x5f031527, 0x8bb75d74, 0x26d1649c, 0xf2652ccf, 0x689b5090, 0xbc2f18c3, 0x1149212b, 0xc5fd6978, 0x03cfae23, 0xd77be670, 0x7a1ddf98, 0xaea997cb, 0x3457eb94, 0xe0e3a3c7, 0x4d859a2f, 0x9931d27c, 0x5cccbb04, 0x8878f357, 0x251ecabf, 0xf1aa82ec, 0x6b54feb3, 0xbfe0b6e0, 0x12868f08, 0xc632c75b, 0x98faf449, 0x4c4ebc1a, 0xe12885f2, 0x359ccda1, 0xaf62b1fe, 0x7bd6f9ad, 0xd6b0c045, 0x02048816, 0xc7f9e16e, 0x134da93d, 0xbe2b90d5, 0x6a9fd886, 0xf061a4d9, 0x24d5ec8a, 0x89b3d562, 0x5d079d31, 0x9b355a6a, 0x4f811239, 0xe2e72bd1, 0x36536382, 0xacad1fdd, 0x7819578e, 0xd57f6e66, 0x01cb2635, 0xc4364f4d, 0x1082071e, 0xbde43ef6, 0x695076a5, 0xf3ae0afa, 0x271a42a9, 0x8a7c7b41, 0x5ec83312, 0xa701d4a6, 0x73b59cf5, 0xded3a51d, 0x0a67ed4e, 0x90999111, 0x442dd942, 0xe94be0aa, 0x3dffa8f9, 0xf802c181, 0x2cb689d2, 0x81d0b03a, 0x5564f869, 0xcf9a8436, 0x1b2ecc65, 0xb648f58d, 0x62fcbdde, 0xa4ce7a85, 0x707a32d6, 0xdd1c0b3e, 0x09a8436d, 0x93563f32, 0x47e27761, 0xea844e89, 0x3e3006da, 0xfbcd6fa2, 0x2f7927f1, 0x821f1e19, 0x56ab564a, 0xcc552a15, 0x18e16246, 0xb5875bae, 0x613313fd, 0x3ffb20ef, 0xeb4f68bc, 0x46295154, 0x929d1907, 0x08636558, 0xdcd72d0b, 0x71b114e3, 0xa5055cb0, 0x60f835c8, 0xb44c7d9b, 0x192a4473, 0xcd9e0c20, 0x5760707f, 0x83d4382c, 0x2eb201c4, 0xfa064997, 0x3c348ecc, 0xe880c69f, 0x45e6ff77, 0x9152b724, 0x0baccb7b, 0xdf188328, 0x727ebac0, 0xa6caf293, 0x63379beb, 0xb783d3b8, 0x1ae5ea50, 0xce51a203, 0x54afde5c, 0x801b960f, 0x2d7dafe7, 0xf9c9e7b4, 0x69ed9b6e, 0xbd59d33d, 0x103fead5, 0xc48ba286, 0x5e75ded9, 0x8ac1968a, 0x27a7af62, 0xf313e731, 0x36ee8e49, 0xe25ac61a, 0x4f3cfff2, 0x9b88b7a1, 0x0176cbfe, 0xd5c283ad, 0x78a4ba45, 0xac10f216, 0x6a22354d, 0xbe967d1e, 0x13f044f6, 0xc7440ca5, 0x5dba70fa, 0x890e38a9, 0x24680141, 0xf0dc4912, 0x3521206a, 0xe1956839, 0x4cf351d1, 0x98471982, 0x02b965dd, 0xd60d2d8e, 0x7b6b1466, 0xafdf5c35, 0xf1176f27, 0x25a32774, 0x88c51e9c, 0x5c7156cf, 0xc68f2a90, 0x123b62c3, 0xbf5d5b2b, 0x6be91378, 0xae147a00, 0x7aa03253, 0xd7c60bbb, 0x037243e8, 0x998c3fb7, 0x4d3877e4, 0xe05e4e0c, 0x34ea065f, 0xf2d8c104, 0x266c8957, 0x8b0ab0bf, 0x5fbef8ec, 0xc54084b3, 0x11f4cce0, 0xbc92f508, 0x6826bd5b, 0xaddbd423, 0x796f9c70, 0xd409a598, 0x00bdedcb, 0x9a439194, 0x4ef7d9c7, 0xe391e02f, 0x3725a87c, 0xceec4fc8, 0x1a58079b, 0xb73e3e73, 0x638a7620, 0xf9740a7f, 0x2dc0422c, 0x80a67bc4, 0x54123397, 0x91ef5aef, 0x455b12bc, 0xe83d2b54, 0x3c896307, 0xa6771f58, 0x72c3570b, 0xdfa56ee3, 0x0b1126b0, 0xcd23e1eb, 0x1997a9b8, 0xb4f19050, 0x6045d803, 0xfabba45c, 0x2e0fec0f, 0x8369d5e7, 0x57dd9db4, 0x9220f4cc, 0x4694bc9f, 0xebf28577, 0x3f46cd24, 0xa5b8b17b, 0x710cf928, 0xdc6ac0c0, 0x08de8893, 0x5616bb81, 0x82a2f3d2, 0x2fc4ca3a, 0xfb708269, 0x618efe36, 0xb53ab665, 0x185c8f8d, 0xcce8c7de, 0x0915aea6, 0xdda1e6f5, 0x70c7df1d, 0xa473974e, 0x3e8deb11, 0xea39a342, 0x475f9aaa, 0x93ebd2f9, 0x55d915a2, 0x816d5df1, 0x2c0b6419, 0xf8bf2c4a, 0x62415015, 0xb6f51846, 0x1b9321ae, 0xcf2769fd, 0x0ada0085, 0xde6e48d6, 0x7308713e, 0xa7bc396d, 0x3d424532, 0xe9f60d61, 0x44903489, 0x90247cda +}, +{ +0x00000000, 0x9d9d9838, 0x05bce4ff, 0x98217cc7, 0x44c4cb8f, 0xd95953b7, 0x41782f70, 0xdce5b748, 0x6c213710, 0xf1bcaf28, 0x699dd3ef, 0xf4004bd7, 0x28e5fc9f, 0xb57864a7, 0x2d591860, 0xb0c48058, 0x3efe74d6, 0xa363ecee, 0x3b429029, 0xa6df0811, 0x7a3abf59, 0xe7a72761, 0x7f865ba6, 0xe21bc39e, 0x52df43c6, 0xcf42dbfe, 0x5763a739, 0xcafe3f01, 0x161b8849, 0x8b861071, 0x13a76cb6, 0x8e3af48e, 0x9636a4f0, 0x0bab3cc8, 0x938a400f, 0x0e17d837, 0xd2f26f7f, 0x4f6ff747, 0xd74e8b80, 0x4ad313b8, 0xfa1793e0, 0x678a0bd8, 0xffab771f, 0x6236ef27, 0xbed3586f, 0x234ec057, 0xbb6fbc90, 0x26f224a8, 0xa8c8d026, 0x3555481e, 0xad7434d9, 0x30e9ace1, 0xec0c1ba9, 0x71918391, 0xe9b0ff56, 0x742d676e, 0xc4e9e736, 0x59747f0e, 0xc15503c9, 0x5cc89bf1, 0x802d2cb9, 0x1db0b481, 0x8591c846, 0x180c507e, 0x15a5bbca, 0x883823f2, 0x10195f35, 0x8d84c70d, 0x51617045, 0xccfce87d, 0x54dd94ba, 0xc9400c82, 0x79848cda, 0xe41914e2, 0x7c386825, 0xe1a5f01d, 0x3d404755, 0xa0dddf6d, 0x38fca3aa, 0xa5613b92, 0x2b5bcf1c, 0xb6c65724, 0x2ee72be3, 0xb37ab3db, 0x6f9f0493, 0xf2029cab, 0x6a23e06c, 0xf7be7854, 0x477af80c, 0xdae76034, 0x42c61cf3, 0xdf5b84cb, 0x03be3383, 0x9e23abbb, 0x0602d77c, 0x9b9f4f44, 0x83931f3a, 0x1e0e8702, 0x862ffbc5, 0x1bb263fd, 0xc757d4b5, 0x5aca4c8d, 0xc2eb304a, 0x5f76a872, 0xefb2282a, 0x722fb012, 0xea0eccd5, 0x779354ed, 0xab76e3a5, 0x36eb7b9d, 0xaeca075a, 0x33579f62, 0xbd6d6bec, 0x20f0f3d4, 0xb8d18f13, 0x254c172b, 0xf9a9a063, 0x6434385b, 0xfc15449c, 0x6188dca4, 0xd14c5cfc, 0x4cd1c4c4, 0xd4f0b803, 0x496d203b, 0x95889773, 0x08150f4b, 0x9034738c, 0x0da9ebb4, 0xf9b54d95, 0x6428d5ad, 0xfc09a96a, 0x61943152, 0xbd71861a, 0x20ec1e22, 0xb8cd62e5, 0x2550fadd, 0x95947a85, 0x0809e2bd, 0x90289e7a, 0x0db50642, 0xd150b10a, 0x4ccd2932, 0xd4ec55f5, 0x4971cdcd, 0xc74b3943, 0x5ad6a17b, 0xc2f7ddbc, 0x5f6a4584, 0x838ff2cc, 0x1e126af4, 0x86331633, 0x1bae8e0b, 0xab6a0e53, 0x36f7966b, 0xaed6eaac, 0x334b7294, 0xefaec5dc, 0x72335de4, 0xea122123, 0x778fb91b, 0x6f83e965, 0xf21e715d, 0x6a3f0d9a, 0xf7a295a2, 0x2b4722ea, 0xb6dabad2, 0x2efbc615, 0xb3665e2d, 0x03a2de75, 0x9e3f464d, 0x061e3a8a, 0x9b83a2b2, 0x476615fa, 0xdafb8dc2, 0x42daf105, 0xdf47693d, 0x517d9db3, 0xcce0058b, 0x54c1794c, 0xc95ce174, 0x15b9563c, 0x8824ce04, 0x1005b2c3, 0x8d982afb, 0x3d5caaa3, 0xa0c1329b, 0x38e04e5c, 0xa57dd664, 0x7998612c, 0xe405f914, 0x7c2485d3, 0xe1b91deb, 0xec10f65f, 0x718d6e67, 0xe9ac12a0, 0x74318a98, 0xa8d43dd0, 0x3549a5e8, 0xad68d92f, 0x30f54117, 0x8031c14f, 0x1dac5977, 0x858d25b0, 0x1810bd88, 0xc4f50ac0, 0x596892f8, 0xc149ee3f, 0x5cd47607, 0xd2ee8289, 0x4f731ab1, 0xd7526676, 0x4acffe4e, 0x962a4906, 0x0bb7d13e, 0x9396adf9, 0x0e0b35c1, 0xbecfb599, 0x23522da1, 0xbb735166, 0x26eec95e, 0xfa0b7e16, 0x6796e62e, 0xffb79ae9, 0x622a02d1, 0x7a2652af, 0xe7bbca97, 0x7f9ab650, 0xe2072e68, 0x3ee29920, 0xa37f0118, 0x3b5e7ddf, 0xa6c3e5e7, 0x160765bf, 0x8b9afd87, 0x13bb8140, 0x8e261978, 0x52c3ae30, 0xcf5e3608, 0x577f4acf, 0xcae2d2f7, 0x44d82679, 0xd945be41, 0x4164c286, 0xdcf95abe, 0x001cedf6, 0x9d8175ce, 0x05a00909, 0x983d9131, 0x28f91169, 0xb5648951, 0x2d45f596, 0xb0d86dae, 0x6c3ddae6, 0xf1a042de, 0x69813e19, 0xf41ca621 +}, +{ +0x00000000, 0x6e17ac4b, 0xc1ab425f, 0xafbcee14, 0x10b1be80, 0x7ea612cb, 0xd11afcdf, 0xbf0d5094, 0x574b65bf, 0x395cc9f4, 0x96e027e0, 0xf8f78bab, 0x47fadb3f, 0x29ed7774, 0x86519960, 0xe846352b, 0x13cdad0e, 0x7dda0145, 0xd266ef51, 0xbc71431a, 0x037c138e, 0x6d6bbfc5, 0xc2d751d1, 0xacc0fd9a, 0x4486c8b1, 0x2a9164fa, 0x852d8aee, 0xeb3a26a5, 0x54377631, 0x3a20da7a, 0x959c346e, 0xfb8b9825, 0x829131a1, 0xec869dea, 0x433a73fe, 0x2d2ddfb5, 0x92208f21, 0xfc37236a, 0x538bcd7e, 0x3d9c6135, 0xd5da541e, 0xbbcdf855, 0x14711641, 0x7a66ba0a, 0xc56bea9e, 0xab7c46d5, 0x04c0a8c1, 0x6ad7048a, 0x915c9caf, 0xff4b30e4, 0x50f7def0, 0x3ee072bb, 0x81ed222f, 0xeffa8e64, 0x40466070, 0x2e51cc3b, 0xc617f910, 0xa800555b, 0x07bcbb4f, 0x69ab1704, 0xd6a64790, 0xb8b1ebdb, 0x170d05cf, 0x791aa984, 0x0a166d56, 0x6401c11d, 0xcbbd2f09, 0xa5aa8342, 0x1aa7d3d6, 0x74b07f9d, 0xdb0c9189, 0xb51b3dc2, 0x5d5d08e9, 0x334aa4a2, 0x9cf64ab6, 0xf2e1e6fd, 0x4decb669, 0x23fb1a22, 0x8c47f436, 0xe250587d, 0x19dbc058, 0x77cc6c13, 0xd8708207, 0xb6672e4c, 0x096a7ed8, 0x677dd293, 0xc8c13c87, 0xa6d690cc, 0x4e90a5e7, 0x208709ac, 0x8f3be7b8, 0xe12c4bf3, 0x5e211b67, 0x3036b72c, 0x9f8a5938, 0xf19df573, 0x88875cf7, 0xe690f0bc, 0x492c1ea8, 0x273bb2e3, 0x9836e277, 0xf6214e3c, 0x599da028, 0x378a0c63, 0xdfcc3948, 0xb1db9503, 0x1e677b17, 0x7070d75c, 0xcf7d87c8, 0xa16a2b83, 0x0ed6c597, 0x60c169dc, 0x9b4af1f9, 0xf55d5db2, 0x5ae1b3a6, 0x34f61fed, 0x8bfb4f79, 0xe5ece332, 0x4a500d26, 0x2447a16d, 0xcc019446, 0xa216380d, 0x0daad619, 0x63bd7a52, 0xdcb02ac6, 0xb2a7868d, 0x1d1b6899, 0x730cc4d2, 0x71d2276b, 0x1fc58b20, 0xb0796534, 0xde6ec97f, 0x616399eb, 0x0f7435a0, 0xa0c8dbb4, 0xcedf77ff, 0x269942d4, 0x488eee9f, 0xe732008b, 0x8925acc0, 0x3628fc54, 0x583f501f, 0xf783be0b, 0x99941240, 0x621f8a65, 0x0c08262e, 0xa3b4c83a, 0xcda36471, 0x72ae34e5, 0x1cb998ae, 0xb30576ba, 0xdd12daf1, 0x3554efda, 0x5b434391, 0xf4ffad85, 0x9ae801ce, 0x25e5515a, 0x4bf2fd11, 0xe44e1305, 0x8a59bf4e, 0xf34316ca, 0x9d54ba81, 0x32e85495, 0x5cfff8de, 0xe3f2a84a, 0x8de50401, 0x2259ea15, 0x4c4e465e, 0xa4087375, 0xca1fdf3e, 0x65a3312a, 0x0bb49d61, 0xb4b9cdf5, 0xdaae61be, 0x75128faa, 0x1b0523e1, 0xe08ebbc4, 0x8e99178f, 0x2125f99b, 0x4f3255d0, 0xf03f0544, 0x9e28a90f, 0x3194471b, 0x5f83eb50, 0xb7c5de7b, 0xd9d27230, 0x766e9c24, 0x1879306f, 0xa77460fb, 0xc963ccb0, 0x66df22a4, 0x08c88eef, 0x7bc44a3d, 0x15d3e676, 0xba6f0862, 0xd478a429, 0x6b75f4bd, 0x056258f6, 0xaadeb6e2, 0xc4c91aa9, 0x2c8f2f82, 0x429883c9, 0xed246ddd, 0x8333c196, 0x3c3e9102, 0x52293d49, 0xfd95d35d, 0x93827f16, 0x6809e733, 0x061e4b78, 0xa9a2a56c, 0xc7b50927, 0x78b859b3, 0x16aff5f8, 0xb9131bec, 0xd704b7a7, 0x3f42828c, 0x51552ec7, 0xfee9c0d3, 0x90fe6c98, 0x2ff33c0c, 0x41e49047, 0xee587e53, 0x804fd218, 0xf9557b9c, 0x9742d7d7, 0x38fe39c3, 0x56e99588, 0xe9e4c51c, 0x87f36957, 0x284f8743, 0x46582b08, 0xae1e1e23, 0xc009b268, 0x6fb55c7c, 0x01a2f037, 0xbeafa0a3, 0xd0b80ce8, 0x7f04e2fc, 0x11134eb7, 0xea98d692, 0x848f7ad9, 0x2b3394cd, 0x45243886, 0xfa296812, 0x943ec459, 0x3b822a4d, 0x55958606, 0xbdd3b32d, 0xd3c41f66, 0x7c78f172, 0x126f5d39, 0xad620dad, 0xc375a1e6, 0x6cc94ff2, 0x02dee3b9 +}, +{ +0x00000000, 0x1c96d8e1, 0xc61a0597, 0xda8cdd76, 0x33166a9d, 0x2f80b27c, 0xf50c6f0a, 0xe99ab7eb, 0xb2b32153, 0xae25f9b2, 0x74a924c4, 0x683ffc25, 0x81a54bce, 0x9d33932f, 0x47bf4e59, 0x5b2996b8, 0xb6b35239, 0xaa258ad8, 0x70a957ae, 0x6c3f8f4f, 0x85a538a4, 0x9933e045, 0x43bf3d33, 0x5f29e5d2, 0x0400736a, 0x1896ab8b, 0xc21a76fd, 0xde8cae1c, 0x371619f7, 0x2b80c116, 0xf10c1c60, 0xed9ac481, 0x4d03dff1, 0x51950710, 0x8b19da66, 0x978f0287, 0x7e15b56c, 0x62836d8d, 0xb80fb0fb, 0xa499681a, 0xffb0fea2, 0xe3262643, 0x39aafb35, 0x253c23d4, 0xcca6943f, 0xd0304cde, 0x0abc91a8, 0x162a4949, 0xfbb08dc8, 0xe7265529, 0x3daa885f, 0x213c50be, 0xc8a6e755, 0xd4303fb4, 0x0ebce2c2, 0x122a3a23, 0x4903ac9b, 0x5595747a, 0x8f19a90c, 0x938f71ed, 0x7a15c606, 0x66831ee7, 0xbc0fc391, 0xa0991b70, 0xd10a7cab, 0xcd9ca44a, 0x1710793c, 0x0b86a1dd, 0xe21c1636, 0xfe8aced7, 0x240613a1, 0x3890cb40, 0x63b95df8, 0x7f2f8519, 0xa5a3586f, 0xb935808e, 0x50af3765, 0x4c39ef84, 0x96b532f2, 0x8a23ea13, 0x67b92e92, 0x7b2ff673, 0xa1a32b05, 0xbd35f3e4, 0x54af440f, 0x48399cee, 0x92b54198, 0x8e239979, 0xd50a0fc1, 0xc99cd720, 0x13100a56, 0x0f86d2b7, 0xe61c655c, 0xfa8abdbd, 0x200660cb, 0x3c90b82a, 0x9c09a35a, 0x809f7bbb, 0x5a13a6cd, 0x46857e2c, 0xaf1fc9c7, 0xb3891126, 0x6905cc50, 0x759314b1, 0x2eba8209, 0x322c5ae8, 0xe8a0879e, 0xf4365f7f, 0x1dace894, 0x013a3075, 0xdbb6ed03, 0xc72035e2, 0x2abaf163, 0x362c2982, 0xeca0f4f4, 0xf0362c15, 0x19ac9bfe, 0x053a431f, 0xdfb69e69, 0xc3204688, 0x9809d030, 0x849f08d1, 0x5e13d5a7, 0x42850d46, 0xab1fbaad, 0xb789624c, 0x6d05bf3a, 0x719367db, 0x799818de, 0x650ec03f, 0xbf821d49, 0xa314c5a8, 0x4a8e7243, 0x5618aaa2, 0x8c9477d4, 0x9002af35, 0xcb2b398d, 0xd7bde16c, 0x0d313c1a, 0x11a7e4fb, 0xf83d5310, 0xe4ab8bf1, 0x3e275687, 0x22b18e66, 0xcf2b4ae7, 0xd3bd9206, 0x09314f70, 0x15a79791, 0xfc3d207a, 0xe0abf89b, 0x3a2725ed, 0x26b1fd0c, 0x7d986bb4, 0x610eb355, 0xbb826e23, 0xa714b6c2, 0x4e8e0129, 0x5218d9c8, 0x889404be, 0x9402dc5f, 0x349bc72f, 0x280d1fce, 0xf281c2b8, 0xee171a59, 0x078dadb2, 0x1b1b7553, 0xc197a825, 0xdd0170c4, 0x8628e67c, 0x9abe3e9d, 0x4032e3eb, 0x5ca43b0a, 0xb53e8ce1, 0xa9a85400, 0x73248976, 0x6fb25197, 0x82289516, 0x9ebe4df7, 0x44329081, 0x58a44860, 0xb13eff8b, 0xada8276a, 0x7724fa1c, 0x6bb222fd, 0x309bb445, 0x2c0d6ca4, 0xf681b1d2, 0xea176933, 0x038dded8, 0x1f1b0639, 0xc597db4f, 0xd90103ae, 0xa8926475, 0xb404bc94, 0x6e8861e2, 0x721eb903, 0x9b840ee8, 0x8712d609, 0x5d9e0b7f, 0x4108d39e, 0x1a214526, 0x06b79dc7, 0xdc3b40b1, 0xc0ad9850, 0x29372fbb, 0x35a1f75a, 0xef2d2a2c, 0xf3bbf2cd, 0x1e21364c, 0x02b7eead, 0xd83b33db, 0xc4adeb3a, 0x2d375cd1, 0x31a18430, 0xeb2d5946, 0xf7bb81a7, 0xac92171f, 0xb004cffe, 0x6a881288, 0x761eca69, 0x9f847d82, 0x8312a563, 0x599e7815, 0x4508a0f4, 0xe591bb84, 0xf9076365, 0x238bbe13, 0x3f1d66f2, 0xd687d119, 0xca1109f8, 0x109dd48e, 0x0c0b0c6f, 0x57229ad7, 0x4bb44236, 0x91389f40, 0x8dae47a1, 0x6434f04a, 0x78a228ab, 0xa22ef5dd, 0xbeb82d3c, 0x5322e9bd, 0x4fb4315c, 0x9538ec2a, 0x89ae34cb, 0x60348320, 0x7ca25bc1, 0xa62e86b7, 0xbab85e56, 0xe191c8ee, 0xfd07100f, 0x278bcd79, 0x3b1d1598, 0xd287a273, 0xce117a92, 0x149da7e4, 0x080b7f05 +}, +{ +0x00000000, 0xcdf76f31, 0x9f4c08fc, 0x52bb67cd, 0x093f2a3b, 0xc4c8450a, 0x967322c7, 0x5b844df6, 0x1be8a36e, 0xd61fcc5f, 0x84a4ab92, 0x4953c4a3, 0x12d78955, 0xdf20e664, 0x8d9b81a9, 0x406cee98, 0xa26aa548, 0x6f9dca79, 0x3d26adb4, 0xf0d1c285, 0xab558f73, 0x66a2e042, 0x3419878f, 0xf9eee8be, 0xb9820626, 0x74756917, 0x26ce0eda, 0xeb3961eb, 0xb0bd2c1d, 0x7d4a432c, 0x2ff124e1, 0xe2064bd0, 0x03b919e6, 0xce4e76d7, 0x9cf5111a, 0x51027e2b, 0x0a8633dd, 0xc7715cec, 0x95ca3b21, 0x583d5410, 0x1851ba88, 0xd5a6d5b9, 0x871db274, 0x4aeadd45, 0x116e90b3, 0xdc99ff82, 0x8e22984f, 0x43d5f77e, 0xa1d3bcae, 0x6c24d39f, 0x3e9fb452, 0xf368db63, 0xa8ec9695, 0x651bf9a4, 0x37a09e69, 0xfa57f158, 0xba3b1fc0, 0x77cc70f1, 0x2577173c, 0xe880780d, 0xb30435fb, 0x7ef35aca, 0x2c483d07, 0xe1bf5236, 0x9703072f, 0x5af4681e, 0x084f0fd3, 0xc5b860e2, 0x9e3c2d14, 0x53cb4225, 0x017025e8, 0xcc874ad9, 0x8ceba441, 0x411ccb70, 0x13a7acbd, 0xde50c38c, 0x85d48e7a, 0x4823e14b, 0x1a988686, 0xd76fe9b7, 0x3569a267, 0xf89ecd56, 0xaa25aa9b, 0x67d2c5aa, 0x3c56885c, 0xf1a1e76d, 0xa31a80a0, 0x6eedef91, 0x2e810109, 0xe3766e38, 0xb1cd09f5, 0x7c3a66c4, 0x27be2b32, 0xea494403, 0xb8f223ce, 0x75054cff, 0x94ba1ec9, 0x594d71f8, 0x0bf61635, 0xc6017904, 0x9d8534f2, 0x50725bc3, 0x02c93c0e, 0xcf3e533f, 0x8f52bda7, 0x42a5d296, 0x101eb55b, 0xdde9da6a, 0x866d979c, 0x4b9af8ad, 0x19219f60, 0xd4d6f051, 0x36d0bb81, 0xfb27d4b0, 0xa99cb37d, 0x646bdc4c, 0x3fef91ba, 0xf218fe8b, 0xa0a39946, 0x6d54f677, 0x2d3818ef, 0xe0cf77de, 0xb2741013, 0x7f837f22, 0x240732d4, 0xe9f05de5, 0xbb4b3a28, 0x76bc5519, 0x4af9488f, 0x870e27be, 0xd5b54073, 0x18422f42, 0x43c662b4, 0x8e310d85, 0xdc8a6a48, 0x117d0579, 0x5111ebe1, 0x9ce684d0, 0xce5de31d, 0x03aa8c2c, 0x582ec1da, 0x95d9aeeb, 0xc762c926, 0x0a95a617, 0xe893edc7, 0x256482f6, 0x77dfe53b, 0xba288a0a, 0xe1acc7fc, 0x2c5ba8cd, 0x7ee0cf00, 0xb317a031, 0xf37b4ea9, 0x3e8c2198, 0x6c374655, 0xa1c02964, 0xfa446492, 0x37b30ba3, 0x65086c6e, 0xa8ff035f, 0x49405169, 0x84b73e58, 0xd60c5995, 0x1bfb36a4, 0x407f7b52, 0x8d881463, 0xdf3373ae, 0x12c41c9f, 0x52a8f207, 0x9f5f9d36, 0xcde4fafb, 0x001395ca, 0x5b97d83c, 0x9660b70d, 0xc4dbd0c0, 0x092cbff1, 0xeb2af421, 0x26dd9b10, 0x7466fcdd, 0xb99193ec, 0xe215de1a, 0x2fe2b12b, 0x7d59d6e6, 0xb0aeb9d7, 0xf0c2574f, 0x3d35387e, 0x6f8e5fb3, 0xa2793082, 0xf9fd7d74, 0x340a1245, 0x66b17588, 0xab461ab9, 0xddfa4fa0, 0x100d2091, 0x42b6475c, 0x8f41286d, 0xd4c5659b, 0x19320aaa, 0x4b896d67, 0x867e0256, 0xc612ecce, 0x0be583ff, 0x595ee432, 0x94a98b03, 0xcf2dc6f5, 0x02daa9c4, 0x5061ce09, 0x9d96a138, 0x7f90eae8, 0xb26785d9, 0xe0dce214, 0x2d2b8d25, 0x76afc0d3, 0xbb58afe2, 0xe9e3c82f, 0x2414a71e, 0x64784986, 0xa98f26b7, 0xfb34417a, 0x36c32e4b, 0x6d4763bd, 0xa0b00c8c, 0xf20b6b41, 0x3ffc0470, 0xde435646, 0x13b43977, 0x410f5eba, 0x8cf8318b, 0xd77c7c7d, 0x1a8b134c, 0x48307481, 0x85c71bb0, 0xc5abf528, 0x085c9a19, 0x5ae7fdd4, 0x971092e5, 0xcc94df13, 0x0163b022, 0x53d8d7ef, 0x9e2fb8de, 0x7c29f30e, 0xb1de9c3f, 0xe365fbf2, 0x2e9294c3, 0x7516d935, 0xb8e1b604, 0xea5ad1c9, 0x27adbef8, 0x67c15060, 0xaa363f51, 0xf88d589c, 0x357a37ad, 0x6efe7a5b, 0xa309156a, 0xf1b272a7, 0x3c451d96 +}, +{ +0x00000000, 0x33126e19, 0xef1478f8, 0xdc0616e1, 0xa5fadf90, 0x96e8b189, 0x4aeea768, 0x79fcc971, 0xeafc0fef, 0xd9ee61f6, 0x05e87717, 0x36fa190e, 0x4f06d07f, 0x7c14be66, 0xa012a887, 0x9300c69e, 0x95a52c26, 0xa6b7423f, 0x7ab154de, 0x49a33ac7, 0x305ff3b6, 0x034d9daf, 0xdf4b8b4e, 0xec59e557, 0x7f5923c9, 0x4c4b4dd0, 0x904d5b31, 0xa35f3528, 0xdaa3fc59, 0xe9b19240, 0x35b784a1, 0x06a5eab8, 0x9e79368d, 0xad6b5894, 0x716d4e75, 0x427f206c, 0x3b83e91d, 0x08918704, 0xd49791e5, 0xe785fffc, 0x74853962, 0x4797577b, 0x9b91419a, 0xa8832f83, 0xd17fe6f2, 0xe26d88eb, 0x3e6b9e0a, 0x0d79f013, 0x0bdc1aab, 0x38ce74b2, 0xe4c86253, 0xd7da0c4a, 0xae26c53b, 0x9d34ab22, 0x4132bdc3, 0x7220d3da, 0xe1201544, 0xd2327b5d, 0x0e346dbc, 0x3d2603a5, 0x44dacad4, 0x77c8a4cd, 0xabceb22c, 0x98dcdc35, 0xb9e44be6, 0x8af625ff, 0x56f0331e, 0x65e25d07, 0x1c1e9476, 0x2f0cfa6f, 0xf30aec8e, 0xc0188297, 0x53184409, 0x600a2a10, 0xbc0c3cf1, 0x8f1e52e8, 0xf6e29b99, 0xc5f0f580, 0x19f6e361, 0x2ae48d78, 0x2c4167c0, 0x1f5309d9, 0xc3551f38, 0xf0477121, 0x89bbb850, 0xbaa9d649, 0x66afc0a8, 0x55bdaeb1, 0xc6bd682f, 0xf5af0636, 0x29a910d7, 0x1abb7ece, 0x6347b7bf, 0x5055d9a6, 0x8c53cf47, 0xbf41a15e, 0x279d7d6b, 0x148f1372, 0xc8890593, 0xfb9b6b8a, 0x8267a2fb, 0xb175cce2, 0x6d73da03, 0x5e61b41a, 0xcd617284, 0xfe731c9d, 0x22750a7c, 0x11676465, 0x689bad14, 0x5b89c30d, 0x878fd5ec, 0xb49dbbf5, 0xb238514d, 0x812a3f54, 0x5d2c29b5, 0x6e3e47ac, 0x17c28edd, 0x24d0e0c4, 0xf8d6f625, 0xcbc4983c, 0x58c45ea2, 0x6bd630bb, 0xb7d0265a, 0x84c24843, 0xfd3e8132, 0xce2cef2b, 0x122af9ca, 0x213897d3, 0x815bf62b, 0xb2499832, 0x6e4f8ed3, 0x5d5de0ca, 0x24a129bb, 0x17b347a2, 0xcbb55143, 0xf8a73f5a, 0x6ba7f9c4, 0x58b597dd, 0x84b3813c, 0xb7a1ef25, 0xce5d2654, 0xfd4f484d, 0x21495eac, 0x125b30b5, 0x14feda0d, 0x27ecb414, 0xfbeaa2f5, 0xc8f8ccec, 0xb104059d, 0x82166b84, 0x5e107d65, 0x6d02137c, 0xfe02d5e2, 0xcd10bbfb, 0x1116ad1a, 0x2204c303, 0x5bf80a72, 0x68ea646b, 0xb4ec728a, 0x87fe1c93, 0x1f22c0a6, 0x2c30aebf, 0xf036b85e, 0xc324d647, 0xbad81f36, 0x89ca712f, 0x55cc67ce, 0x66de09d7, 0xf5decf49, 0xc6cca150, 0x1acab7b1, 0x29d8d9a8, 0x502410d9, 0x63367ec0, 0xbf306821, 0x8c220638, 0x8a87ec80, 0xb9958299, 0x65939478, 0x5681fa61, 0x2f7d3310, 0x1c6f5d09, 0xc0694be8, 0xf37b25f1, 0x607be36f, 0x53698d76, 0x8f6f9b97, 0xbc7df58e, 0xc5813cff, 0xf69352e6, 0x2a954407, 0x19872a1e, 0x38bfbdcd, 0x0badd3d4, 0xd7abc535, 0xe4b9ab2c, 0x9d45625d, 0xae570c44, 0x72511aa5, 0x414374bc, 0xd243b222, 0xe151dc3b, 0x3d57cada, 0x0e45a4c3, 0x77b96db2, 0x44ab03ab, 0x98ad154a, 0xabbf7b53, 0xad1a91eb, 0x9e08fff2, 0x420ee913, 0x711c870a, 0x08e04e7b, 0x3bf22062, 0xe7f43683, 0xd4e6589a, 0x47e69e04, 0x74f4f01d, 0xa8f2e6fc, 0x9be088e5, 0xe21c4194, 0xd10e2f8d, 0x0d08396c, 0x3e1a5775, 0xa6c68b40, 0x95d4e559, 0x49d2f3b8, 0x7ac09da1, 0x033c54d0, 0x302e3ac9, 0xec282c28, 0xdf3a4231, 0x4c3a84af, 0x7f28eab6, 0xa32efc57, 0x903c924e, 0xe9c05b3f, 0xdad23526, 0x06d423c7, 0x35c64dde, 0x3363a766, 0x0071c97f, 0xdc77df9e, 0xef65b187, 0x969978f6, 0xa58b16ef, 0x798d000e, 0x4a9f6e17, 0xd99fa889, 0xea8dc690, 0x368bd071, 0x0599be68, 0x7c657719, 0x4f771900, 0x93710fe1, 0xa06361f8 +}, +{ +0x00000000, 0x3544ff72, 0xa21e5c60, 0x975aa312, 0x78693ccd, 0x4d2dc3bf, 0xda7760ad, 0xef339fdf, 0x090e3837, 0x3c4ac745, 0xab106457, 0x9e549b25, 0x716704fa, 0x4423fb88, 0xd379589a, 0xe63da7e8, 0x09437ef6, 0x3c078184, 0xab5d2296, 0x9e19dde4, 0x712a423b, 0x446ebd49, 0xd3341e5b, 0xe670e129, 0x004d46c1, 0x3509b9b3, 0xa2531aa1, 0x9717e5d3, 0x78247a0c, 0x4d60857e, 0xda3a266c, 0xef7ed91e, 0x905e7c69, 0xa51a831b, 0x32402009, 0x0704df7b, 0xe83740a4, 0xdd73bfd6, 0x4a291cc4, 0x7f6de3b6, 0x9950445e, 0xac14bb2c, 0x3b4e183e, 0x0e0ae74c, 0xe1397893, 0xd47d87e1, 0x432724f3, 0x7663db81, 0x991d029f, 0xac59fded, 0x3b035eff, 0x0e47a18d, 0xe1743e52, 0xd430c120, 0x436a6232, 0x762e9d40, 0x90133aa8, 0xa557c5da, 0x320d66c8, 0x074999ba, 0xe87a0665, 0xdd3ef917, 0x4a645a05, 0x7f20a577, 0x700ac40a, 0x454e3b78, 0xd214986a, 0xe7506718, 0x0863f8c7, 0x3d2707b5, 0xaa7da4a7, 0x9f395bd5, 0x7904fc3d, 0x4c40034f, 0xdb1aa05d, 0xee5e5f2f, 0x016dc0f0, 0x34293f82, 0xa3739c90, 0x963763e2, 0x7949bafc, 0x4c0d458e, 0xdb57e69c, 0xee1319ee, 0x01208631, 0x34647943, 0xa33eda51, 0x967a2523, 0x704782cb, 0x45037db9, 0xd259deab, 0xe71d21d9, 0x082ebe06, 0x3d6a4174, 0xaa30e266, 0x9f741d14, 0xe054b863, 0xd5104711, 0x424ae403, 0x770e1b71, 0x983d84ae, 0xad797bdc, 0x3a23d8ce, 0x0f6727bc, 0xe95a8054, 0xdc1e7f26, 0x4b44dc34, 0x7e002346, 0x9133bc99, 0xa47743eb, 0x332de0f9, 0x06691f8b, 0xe917c695, 0xdc5339e7, 0x4b099af5, 0x7e4d6587, 0x917efa58, 0xa43a052a, 0x3360a638, 0x0624594a, 0xe019fea2, 0xd55d01d0, 0x4207a2c2, 0x77435db0, 0x9870c26f, 0xad343d1d, 0x3a6e9e0f, 0x0f2a617d, 0xf406140b, 0xc142eb79, 0x5618486b, 0x635cb719, 0x8c6f28c6, 0xb92bd7b4, 0x2e7174a6, 0x1b358bd4, 0xfd082c3c, 0xc84cd34e, 0x5f16705c, 0x6a528f2e, 0x856110f1, 0xb025ef83, 0x277f4c91, 0x123bb3e3, 0xfd456afd, 0xc801958f, 0x5f5b369d, 0x6a1fc9ef, 0x852c5630, 0xb068a942, 0x27320a50, 0x1276f522, 0xf44b52ca, 0xc10fadb8, 0x56550eaa, 0x6311f1d8, 0x8c226e07, 0xb9669175, 0x2e3c3267, 0x1b78cd15, 0x64586862, 0x511c9710, 0xc6463402, 0xf302cb70, 0x1c3154af, 0x2975abdd, 0xbe2f08cf, 0x8b6bf7bd, 0x6d565055, 0x5812af27, 0xcf480c35, 0xfa0cf347, 0x153f6c98, 0x207b93ea, 0xb72130f8, 0x8265cf8a, 0x6d1b1694, 0x585fe9e6, 0xcf054af4, 0xfa41b586, 0x15722a59, 0x2036d52b, 0xb76c7639, 0x8228894b, 0x64152ea3, 0x5151d1d1, 0xc60b72c3, 0xf34f8db1, 0x1c7c126e, 0x2938ed1c, 0xbe624e0e, 0x8b26b17c, 0x840cd001, 0xb1482f73, 0x26128c61, 0x13567313, 0xfc65eccc, 0xc92113be, 0x5e7bb0ac, 0x6b3f4fde, 0x8d02e836, 0xb8461744, 0x2f1cb456, 0x1a584b24, 0xf56bd4fb, 0xc02f2b89, 0x5775889b, 0x623177e9, 0x8d4faef7, 0xb80b5185, 0x2f51f297, 0x1a150de5, 0xf526923a, 0xc0626d48, 0x5738ce5a, 0x627c3128, 0x844196c0, 0xb10569b2, 0x265fcaa0, 0x131b35d2, 0xfc28aa0d, 0xc96c557f, 0x5e36f66d, 0x6b72091f, 0x1452ac68, 0x2116531a, 0xb64cf008, 0x83080f7a, 0x6c3b90a5, 0x597f6fd7, 0xce25ccc5, 0xfb6133b7, 0x1d5c945f, 0x28186b2d, 0xbf42c83f, 0x8a06374d, 0x6535a892, 0x507157e0, 0xc72bf4f2, 0xf26f0b80, 0x1d11d29e, 0x28552dec, 0xbf0f8efe, 0x8a4b718c, 0x6578ee53, 0x503c1121, 0xc766b233, 0xf2224d41, 0x141feaa9, 0x215b15db, 0xb601b6c9, 0x834549bb, 0x6c76d664, 0x59322916, 0xce688a04, 0xfb2c7576 +}, +{ +0x00000000, 0x597a2ce9, 0x8cbad9a0, 0xd5c0f549, 0x6ed1ca42, 0x37abe6ab, 0xe26b13e2, 0xbb113f0b, 0xdeaed05a, 0x87d4fcb3, 0x521409fa, 0x0b6e2513, 0xb07f1a18, 0xe90536f1, 0x3cc5c3b8, 0x65bfef51, 0x3a6594f0, 0x631fb819, 0xb6df4d50, 0xefa561b9, 0x54b45eb2, 0x0dce725b, 0xd80e8712, 0x8174abfb, 0xe4cb44aa, 0xbdb16843, 0x68719d0a, 0x310bb1e3, 0x8a1a8ee8, 0xd360a201, 0x06a05748, 0x5fda7ba1, 0x59d2c101, 0x00a8ede8, 0xd56818a1, 0x8c123448, 0x37030b43, 0x6e7927aa, 0xbbb9d2e3, 0xe2c3fe0a, 0x877c115b, 0xde063db2, 0x0bc6c8fb, 0x52bce412, 0xe9addb19, 0xb0d7f7f0, 0x651702b9, 0x3c6d2e50, 0x63b755f1, 0x3acd7918, 0xef0d8c51, 0xb677a0b8, 0x0d669fb3, 0x541cb35a, 0x81dc4613, 0xd8a66afa, 0xbd1985ab, 0xe463a942, 0x31a35c0b, 0x68d970e2, 0xd3c84fe9, 0x8ab26300, 0x5f729649, 0x0608baa0, 0x22b76e69, 0x7bcd4280, 0xae0db7c9, 0xf7779b20, 0x4c66a42b, 0x151c88c2, 0xc0dc7d8b, 0x99a65162, 0xfc19be33, 0xa56392da, 0x70a36793, 0x29d94b7a, 0x92c87471, 0xcbb25898, 0x1e72add1, 0x47088138, 0x18d2fa99, 0x41a8d670, 0x94682339, 0xcd120fd0, 0x760330db, 0x2f791c32, 0xfab9e97b, 0xa3c3c592, 0xc67c2ac3, 0x9f06062a, 0x4ac6f363, 0x13bcdf8a, 0xa8ade081, 0xf1d7cc68, 0x24173921, 0x7d6d15c8, 0x7b65af68, 0x221f8381, 0xf7df76c8, 0xaea55a21, 0x15b4652a, 0x4cce49c3, 0x990ebc8a, 0xc0749063, 0xa5cb7f32, 0xfcb153db, 0x2971a692, 0x700b8a7b, 0xcb1ab570, 0x92609999, 0x47a06cd0, 0x1eda4039, 0x41003b98, 0x187a1771, 0xcdbae238, 0x94c0ced1, 0x2fd1f1da, 0x76abdd33, 0xa36b287a, 0xfa110493, 0x9faeebc2, 0xc6d4c72b, 0x13143262, 0x4a6e1e8b, 0xf17f2180, 0xa8050d69, 0x7dc5f820, 0x24bfd4c9, 0x4273de27, 0x1b09f2ce, 0xcec90787, 0x97b32b6e, 0x2ca21465, 0x75d8388c, 0xa018cdc5, 0xf962e12c, 0x9cdd0e7d, 0xc5a72294, 0x1067d7dd, 0x491dfb34, 0xf20cc43f, 0xab76e8d6, 0x7eb61d9f, 0x27cc3176, 0x78164ad7, 0x216c663e, 0xf4ac9377, 0xadd6bf9e, 0x16c78095, 0x4fbdac7c, 0x9a7d5935, 0xc30775dc, 0xa6b89a8d, 0xffc2b664, 0x2a02432d, 0x73786fc4, 0xc86950cf, 0x91137c26, 0x44d3896f, 0x1da9a586, 0x1ba11f26, 0x42db33cf, 0x971bc686, 0xce61ea6f, 0x7570d564, 0x2c0af98d, 0xf9ca0cc4, 0xa0b0202d, 0xc50fcf7c, 0x9c75e395, 0x49b516dc, 0x10cf3a35, 0xabde053e, 0xf2a429d7, 0x2764dc9e, 0x7e1ef077, 0x21c48bd6, 0x78bea73f, 0xad7e5276, 0xf4047e9f, 0x4f154194, 0x166f6d7d, 0xc3af9834, 0x9ad5b4dd, 0xff6a5b8c, 0xa6107765, 0x73d0822c, 0x2aaaaec5, 0x91bb91ce, 0xc8c1bd27, 0x1d01486e, 0x447b6487, 0x60c4b04e, 0x39be9ca7, 0xec7e69ee, 0xb5044507, 0x0e157a0c, 0x576f56e5, 0x82afa3ac, 0xdbd58f45, 0xbe6a6014, 0xe7104cfd, 0x32d0b9b4, 0x6baa955d, 0xd0bbaa56, 0x89c186bf, 0x5c0173f6, 0x057b5f1f, 0x5aa124be, 0x03db0857, 0xd61bfd1e, 0x8f61d1f7, 0x3470eefc, 0x6d0ac215, 0xb8ca375c, 0xe1b01bb5, 0x840ff4e4, 0xdd75d80d, 0x08b52d44, 0x51cf01ad, 0xeade3ea6, 0xb3a4124f, 0x6664e706, 0x3f1ecbef, 0x3916714f, 0x606c5da6, 0xb5aca8ef, 0xecd68406, 0x57c7bb0d, 0x0ebd97e4, 0xdb7d62ad, 0x82074e44, 0xe7b8a115, 0xbec28dfc, 0x6b0278b5, 0x3278545c, 0x89696b57, 0xd01347be, 0x05d3b2f7, 0x5ca99e1e, 0x0373e5bf, 0x5a09c956, 0x8fc93c1f, 0xd6b310f6, 0x6da22ffd, 0x34d80314, 0xe118f65d, 0xb862dab4, 0xdddd35e5, 0x84a7190c, 0x5167ec45, 0x081dc0ac, 0xb30cffa7, 0xea76d34e, 0x3fb62607, 0x66cc0aee +}, +{ +0x00000000, 0x587e38ef, 0x93073a5b, 0xcb7902b4, 0x52a82d8b, 0x0ad61564, 0xc1af17d0, 0x99d12f3f, 0x70efc7d8, 0x2891ff37, 0xe3e8fd83, 0xbb96c56c, 0x2247ea53, 0x7a39d2bc, 0xb140d008, 0xe93ee8e7, 0x1db974e6, 0x45c74c09, 0x8ebe4ebd, 0xd6c07652, 0x4f11596d, 0x176f6182, 0xdc166336, 0x84685bd9, 0x6d56b33e, 0x35288bd1, 0xfe518965, 0xa62fb18a, 0x3ffe9eb5, 0x6780a65a, 0xacf9a4ee, 0xf4879c01, 0x362653bc, 0x6e586b53, 0xa52169e7, 0xfd5f5108, 0x648e7e37, 0x3cf046d8, 0xf789446c, 0xaff77c83, 0x46c99464, 0x1eb7ac8b, 0xd5ceae3f, 0x8db096d0, 0x1461b9ef, 0x4c1f8100, 0x876683b4, 0xdf18bb5b, 0x2b9f275a, 0x73e11fb5, 0xb8981d01, 0xe0e625ee, 0x79370ad1, 0x2149323e, 0xea30308a, 0xb24e0865, 0x5b70e082, 0x030ed86d, 0xc877dad9, 0x9009e236, 0x09d8cd09, 0x51a6f5e6, 0x9adff752, 0xc2a1cfbd, 0xfb2997cf, 0xa357af20, 0x682ead94, 0x3050957b, 0xa981ba44, 0xf1ff82ab, 0x3a86801f, 0x62f8b8f0, 0x8bc65017, 0xd3b868f8, 0x18c16a4c, 0x40bf52a3, 0xd96e7d9c, 0x81104573, 0x4a6947c7, 0x12177f28, 0xe690e329, 0xbeeedbc6, 0x7597d972, 0x2de9e19d, 0xb438cea2, 0xec46f64d, 0x273ff4f9, 0x7f41cc16, 0x967f24f1, 0xce011c1e, 0x05781eaa, 0x5d062645, 0xc4d7097a, 0x9ca93195, 0x57d03321, 0x0fae0bce, 0xcd0fc473, 0x9571fc9c, 0x5e08fe28, 0x0676c6c7, 0x9fa7e9f8, 0xc7d9d117, 0x0ca0d3a3, 0x54deeb4c, 0xbde003ab, 0xe59e3b44, 0x2ee739f0, 0x7699011f, 0xef482e20, 0xb73616cf, 0x7c4f147b, 0x24312c94, 0xd0b6b095, 0x88c8887a, 0x43b18ace, 0x1bcfb221, 0x821e9d1e, 0xda60a5f1, 0x1119a745, 0x49679faa, 0xa059774d, 0xf8274fa2, 0x335e4d16, 0x6b2075f9, 0xf2f15ac6, 0xaa8f6229, 0x61f6609d, 0x39885872, 0xbd573a75, 0xe529029a, 0x2e50002e, 0x762e38c1, 0xefff17fe, 0xb7812f11, 0x7cf82da5, 0x2486154a, 0xcdb8fdad, 0x95c6c542, 0x5ebfc7f6, 0x06c1ff19, 0x9f10d026, 0xc76ee8c9, 0x0c17ea7d, 0x5469d292, 0xa0ee4e93, 0xf890767c, 0x33e974c8, 0x6b974c27, 0xf2466318, 0xaa385bf7, 0x61415943, 0x393f61ac, 0xd001894b, 0x887fb1a4, 0x4306b310, 0x1b788bff, 0x82a9a4c0, 0xdad79c2f, 0x11ae9e9b, 0x49d0a674, 0x8b7169c9, 0xd30f5126, 0x18765392, 0x40086b7d, 0xd9d94442, 0x81a77cad, 0x4ade7e19, 0x12a046f6, 0xfb9eae11, 0xa3e096fe, 0x6899944a, 0x30e7aca5, 0xa936839a, 0xf148bb75, 0x3a31b9c1, 0x624f812e, 0x96c81d2f, 0xceb625c0, 0x05cf2774, 0x5db11f9b, 0xc46030a4, 0x9c1e084b, 0x57670aff, 0x0f193210, 0xe627daf7, 0xbe59e218, 0x7520e0ac, 0x2d5ed843, 0xb48ff77c, 0xecf1cf93, 0x2788cd27, 0x7ff6f5c8, 0x467eadba, 0x1e009555, 0xd57997e1, 0x8d07af0e, 0x14d68031, 0x4ca8b8de, 0x87d1ba6a, 0xdfaf8285, 0x36916a62, 0x6eef528d, 0xa5965039, 0xfde868d6, 0x643947e9, 0x3c477f06, 0xf73e7db2, 0xaf40455d, 0x5bc7d95c, 0x03b9e1b3, 0xc8c0e307, 0x90bedbe8, 0x096ff4d7, 0x5111cc38, 0x9a68ce8c, 0xc216f663, 0x2b281e84, 0x7356266b, 0xb82f24df, 0xe0511c30, 0x7980330f, 0x21fe0be0, 0xea870954, 0xb2f931bb, 0x7058fe06, 0x2826c6e9, 0xe35fc45d, 0xbb21fcb2, 0x22f0d38d, 0x7a8eeb62, 0xb1f7e9d6, 0xe989d139, 0x00b739de, 0x58c90131, 0x93b00385, 0xcbce3b6a, 0x521f1455, 0x0a612cba, 0xc1182e0e, 0x996616e1, 0x6de18ae0, 0x359fb20f, 0xfee6b0bb, 0xa6988854, 0x3f49a76b, 0x67379f84, 0xac4e9d30, 0xf430a5df, 0x1d0e4d38, 0x457075d7, 0x8e097763, 0xd6774f8c, 0x4fa660b3, 0x17d8585c, 0xdca15ae8, 0x84df6207 +}, +{ +0x00000000, 0x30a963eb, 0xc3d68cf2, 0xf37fef19, 0x91cbc0a9, 0xa162a342, 0x521d4c5b, 0x62b42fb0, 0xd9ecaf1d, 0xe945ccf6, 0x1a3a23ef, 0x2a934004, 0x48276fb4, 0x788e0c5f, 0x8bf1e346, 0xbb5880ad, 0xb16576e2, 0x81cc1509, 0x72b3fa10, 0x421a99fb, 0x20aeb64b, 0x1007d5a0, 0xe3783ab9, 0xd3d15952, 0x6889d9ff, 0x5820ba14, 0xab5f550d, 0x9bf636e6, 0xf9421956, 0xc9eb7abd, 0x3a9495a4, 0x0a3df64f, 0x21047aba, 0x11ad1951, 0xe2d2f648, 0xd27b95a3, 0xb0cfba13, 0x8066d9f8, 0x731936e1, 0x43b0550a, 0xf8e8d5a7, 0xc841b64c, 0x3b3e5955, 0x0b973abe, 0x6923150e, 0x598a76e5, 0xaaf599fc, 0x9a5cfa17, 0x90610c58, 0xa0c86fb3, 0x53b780aa, 0x631ee341, 0x01aaccf1, 0x3103af1a, 0xc27c4003, 0xf2d523e8, 0x498da345, 0x7924c0ae, 0x8a5b2fb7, 0xbaf24c5c, 0xd84663ec, 0xe8ef0007, 0x1b90ef1e, 0x2b398cf5, 0x4fdf82eb, 0x7f76e100, 0x8c090e19, 0xbca06df2, 0xde144242, 0xeebd21a9, 0x1dc2ceb0, 0x2d6bad5b, 0x96332df6, 0xa69a4e1d, 0x55e5a104, 0x654cc2ef, 0x07f8ed5f, 0x37518eb4, 0xc42e61ad, 0xf4870246, 0xfebaf409, 0xce1397e2, 0x3d6c78fb, 0x0dc51b10, 0x6f7134a0, 0x5fd8574b, 0xaca7b852, 0x9c0edbb9, 0x27565b14, 0x17ff38ff, 0xe480d7e6, 0xd429b40d, 0xb69d9bbd, 0x8634f856, 0x754b174f, 0x45e274a4, 0x6edbf851, 0x5e729bba, 0xad0d74a3, 0x9da41748, 0xff1038f8, 0xcfb95b13, 0x3cc6b40a, 0x0c6fd7e1, 0xb737574c, 0x879e34a7, 0x74e1dbbe, 0x4448b855, 0x26fc97e5, 0x1655f40e, 0xe52a1b17, 0xd58378fc, 0xdfbe8eb3, 0xef17ed58, 0x1c680241, 0x2cc161aa, 0x4e754e1a, 0x7edc2df1, 0x8da3c2e8, 0xbd0aa103, 0x065221ae, 0x36fb4245, 0xc584ad5c, 0xf52dceb7, 0x9799e107, 0xa73082ec, 0x544f6df5, 0x64e60e1e, 0x1d54f60b, 0x2dfd95e0, 0xde827af9, 0xee2b1912, 0x8c9f36a2, 0xbc365549, 0x4f49ba50, 0x7fe0d9bb, 0xc4b85916, 0xf4113afd, 0x076ed5e4, 0x37c7b60f, 0x557399bf, 0x65dafa54, 0x96a5154d, 0xa60c76a6, 0xac3180e9, 0x9c98e302, 0x6fe70c1b, 0x5f4e6ff0, 0x3dfa4040, 0x0d5323ab, 0xfe2cccb2, 0xce85af59, 0x75dd2ff4, 0x45744c1f, 0xb60ba306, 0x86a2c0ed, 0xe416ef5d, 0xd4bf8cb6, 0x27c063af, 0x17690044, 0x3c508cb1, 0x0cf9ef5a, 0xff860043, 0xcf2f63a8, 0xad9b4c18, 0x9d322ff3, 0x6e4dc0ea, 0x5ee4a301, 0xe5bc23ac, 0xd5154047, 0x266aaf5e, 0x16c3ccb5, 0x7477e305, 0x44de80ee, 0xb7a16ff7, 0x87080c1c, 0x8d35fa53, 0xbd9c99b8, 0x4ee376a1, 0x7e4a154a, 0x1cfe3afa, 0x2c575911, 0xdf28b608, 0xef81d5e3, 0x54d9554e, 0x647036a5, 0x970fd9bc, 0xa7a6ba57, 0xc51295e7, 0xf5bbf60c, 0x06c41915, 0x366d7afe, 0x528b74e0, 0x6222170b, 0x915df812, 0xa1f49bf9, 0xc340b449, 0xf3e9d7a2, 0x009638bb, 0x303f5b50, 0x8b67dbfd, 0xbbceb816, 0x48b1570f, 0x781834e4, 0x1aac1b54, 0x2a0578bf, 0xd97a97a6, 0xe9d3f44d, 0xe3ee0202, 0xd34761e9, 0x20388ef0, 0x1091ed1b, 0x7225c2ab, 0x428ca140, 0xb1f34e59, 0x815a2db2, 0x3a02ad1f, 0x0aabcef4, 0xf9d421ed, 0xc97d4206, 0xabc96db6, 0x9b600e5d, 0x681fe144, 0x58b682af, 0x738f0e5a, 0x43266db1, 0xb05982a8, 0x80f0e143, 0xe244cef3, 0xd2edad18, 0x21924201, 0x113b21ea, 0xaa63a147, 0x9acac2ac, 0x69b52db5, 0x591c4e5e, 0x3ba861ee, 0x0b010205, 0xf87eed1c, 0xc8d78ef7, 0xc2ea78b8, 0xf2431b53, 0x013cf44a, 0x319597a1, 0x5321b811, 0x6388dbfa, 0x90f734e3, 0xa05e5708, 0x1b06d7a5, 0x2bafb44e, 0xd8d05b57, 0xe87938bc, 0x8acd170c, 0xba6474e7, 0x491b9bfe, 0x79b2f815 +}, +{ +0x00000000, 0xed9b2751, 0x4edd96b0, 0xa346b1e1, 0x36701cfb, 0xdbeb3baa, 0x78ad8a4b, 0x9536ad1a, 0xabf6699e, 0x466d4ecf, 0xe52bff2e, 0x08b0d87f, 0x9d867565, 0x701d5234, 0xd35be3d5, 0x3ec0c484, 0xfa41ac7e, 0x17da8b2f, 0xb49c3ace, 0x59071d9f, 0xcc31b085, 0x21aa97d4, 0x82ec2635, 0x6f770164, 0x51b7c5e0, 0xbc2ce2b1, 0x1f6a5350, 0xf2f17401, 0x67c7d91b, 0x8a5cfe4a, 0x291a4fab, 0xc48168fa, 0x0bb8ee73, 0xe623c922, 0x456578c3, 0xa8fe5f92, 0x3dc8f288, 0xd053d5d9, 0x73156438, 0x9e8e4369, 0xa04e87ed, 0x4dd5a0bc, 0xee93115d, 0x0308360c, 0x963e9b16, 0x7ba5bc47, 0xd8e30da6, 0x35782af7, 0xf1f9420d, 0x1c62655c, 0xbf24d4bd, 0x52bff3ec, 0xc7895ef6, 0x2a1279a7, 0x8954c846, 0x64cfef17, 0x5a0f2b93, 0xb7940cc2, 0x14d2bd23, 0xf9499a72, 0x6c7f3768, 0x81e41039, 0x22a2a1d8, 0xcf398689, 0x0287384c, 0xef1c1f1d, 0x4c5aaefc, 0xa1c189ad, 0x34f724b7, 0xd96c03e6, 0x7a2ab207, 0x97b19556, 0xa97151d2, 0x44ea7683, 0xe7acc762, 0x0a37e033, 0x9f014d29, 0x729a6a78, 0xd1dcdb99, 0x3c47fcc8, 0xf8c69432, 0x155db363, 0xb61b0282, 0x5b8025d3, 0xceb688c9, 0x232daf98, 0x806b1e79, 0x6df03928, 0x5330fdac, 0xbeabdafd, 0x1ded6b1c, 0xf0764c4d, 0x6540e157, 0x88dbc606, 0x2b9d77e7, 0xc60650b6, 0x093fd63f, 0xe4a4f16e, 0x47e2408f, 0xaa7967de, 0x3f4fcac4, 0xd2d4ed95, 0x71925c74, 0x9c097b25, 0xa2c9bfa1, 0x4f5298f0, 0xec142911, 0x018f0e40, 0x94b9a35a, 0x7922840b, 0xda6435ea, 0x37ff12bb, 0xf37e7a41, 0x1ee55d10, 0xbda3ecf1, 0x5038cba0, 0xc50e66ba, 0x289541eb, 0x8bd3f00a, 0x6648d75b, 0x588813df, 0xb513348e, 0x1655856f, 0xfbcea23e, 0x6ef80f24, 0x83632875, 0x20259994, 0xcdbebec5, 0x0a2eedf7, 0xe7b5caa6, 0x44f37b47, 0xa9685c16, 0x3c5ef10c, 0xd1c5d65d, 0x728367bc, 0x9f1840ed, 0xa1d88469, 0x4c43a338, 0xef0512d9, 0x029e3588, 0x97a89892, 0x7a33bfc3, 0xd9750e22, 0x34ee2973, 0xf06f4189, 0x1df466d8, 0xbeb2d739, 0x5329f068, 0xc61f5d72, 0x2b847a23, 0x88c2cbc2, 0x6559ec93, 0x5b992817, 0xb6020f46, 0x1544bea7, 0xf8df99f6, 0x6de934ec, 0x807213bd, 0x2334a25c, 0xceaf850d, 0x01960384, 0xec0d24d5, 0x4f4b9534, 0xa2d0b265, 0x37e61f7f, 0xda7d382e, 0x793b89cf, 0x94a0ae9e, 0xaa606a1a, 0x47fb4d4b, 0xe4bdfcaa, 0x0926dbfb, 0x9c1076e1, 0x718b51b0, 0xd2cde051, 0x3f56c700, 0xfbd7affa, 0x164c88ab, 0xb50a394a, 0x58911e1b, 0xcda7b301, 0x203c9450, 0x837a25b1, 0x6ee102e0, 0x5021c664, 0xbdbae135, 0x1efc50d4, 0xf3677785, 0x6651da9f, 0x8bcafdce, 0x288c4c2f, 0xc5176b7e, 0x08a9d5bb, 0xe532f2ea, 0x4674430b, 0xabef645a, 0x3ed9c940, 0xd342ee11, 0x70045ff0, 0x9d9f78a1, 0xa35fbc25, 0x4ec49b74, 0xed822a95, 0x00190dc4, 0x952fa0de, 0x78b4878f, 0xdbf2366e, 0x3669113f, 0xf2e879c5, 0x1f735e94, 0xbc35ef75, 0x51aec824, 0xc498653e, 0x2903426f, 0x8a45f38e, 0x67ded4df, 0x591e105b, 0xb485370a, 0x17c386eb, 0xfa58a1ba, 0x6f6e0ca0, 0x82f52bf1, 0x21b39a10, 0xcc28bd41, 0x03113bc8, 0xee8a1c99, 0x4dccad78, 0xa0578a29, 0x35612733, 0xd8fa0062, 0x7bbcb183, 0x962796d2, 0xa8e75256, 0x457c7507, 0xe63ac4e6, 0x0ba1e3b7, 0x9e974ead, 0x730c69fc, 0xd04ad81d, 0x3dd1ff4c, 0xf95097b6, 0x14cbb0e7, 0xb78d0106, 0x5a162657, 0xcf208b4d, 0x22bbac1c, 0x81fd1dfd, 0x6c663aac, 0x52a6fe28, 0xbf3dd979, 0x1c7b6898, 0xf1e04fc9, 0x64d6e2d3, 0x894dc582, 0x2a0b7463, 0xc7905332 +}, +{ +0x00000000, 0x8dd58ed0, 0xbbeeeeb4, 0x363b6064, 0x5f9290f0, 0xd2471e20, 0xe47c7e44, 0x69a9f094, 0x045e86f1, 0x898b0821, 0xbfb06845, 0x3265e695, 0x5bcc1601, 0xd61998d1, 0xe022f8b5, 0x6df77665, 0x4b487a36, 0xc69df4e6, 0xf0a69482, 0x7d731a52, 0x14daeac6, 0x990f6416, 0xaf340472, 0x22e18aa2, 0x4f16fcc7, 0xc2c37217, 0xf4f81273, 0x792d9ca3, 0x10846c37, 0x9d51e2e7, 0xab6a8283, 0x26bf0c53, 0xae2c28f3, 0x23f9a623, 0x15c2c647, 0x98174897, 0xf1beb803, 0x7c6b36d3, 0x4a5056b7, 0xc785d867, 0xaa72ae02, 0x27a720d2, 0x119c40b6, 0x9c49ce66, 0xf5e03ef2, 0x7835b022, 0x4e0ed046, 0xc3db5e96, 0xe56452c5, 0x68b1dc15, 0x5e8abc71, 0xd35f32a1, 0xbaf6c235, 0x37234ce5, 0x01182c81, 0x8ccda251, 0xe13ad434, 0x6cef5ae4, 0x5ad43a80, 0xd701b450, 0xbea844c4, 0x337dca14, 0x0546aa70, 0x889324a0, 0xcd19a0e0, 0x40cc2e30, 0x76f74e54, 0xfb22c084, 0x928b3010, 0x1f5ebec0, 0x2965dea4, 0xa4b05074, 0xc9472611, 0x4492a8c1, 0x72a9c8a5, 0xff7c4675, 0x96d5b6e1, 0x1b003831, 0x2d3b5855, 0xa0eed685, 0x8651dad6, 0x0b845406, 0x3dbf3462, 0xb06abab2, 0xd9c34a26, 0x5416c4f6, 0x622da492, 0xeff82a42, 0x820f5c27, 0x0fdad2f7, 0x39e1b293, 0xb4343c43, 0xdd9dccd7, 0x50484207, 0x66732263, 0xeba6acb3, 0x63358813, 0xeee006c3, 0xd8db66a7, 0x550ee877, 0x3ca718e3, 0xb1729633, 0x8749f657, 0x0a9c7887, 0x676b0ee2, 0xeabe8032, 0xdc85e056, 0x51506e86, 0x38f99e12, 0xb52c10c2, 0x831770a6, 0x0ec2fe76, 0x287df225, 0xa5a87cf5, 0x93931c91, 0x1e469241, 0x77ef62d5, 0xfa3aec05, 0xcc018c61, 0x41d402b1, 0x2c2374d4, 0xa1f6fa04, 0x97cd9a60, 0x1a1814b0, 0x73b1e424, 0xfe646af4, 0xc85f0a90, 0x458a8440, 0x39526ee1, 0xb487e031, 0x82bc8055, 0x0f690e85, 0x66c0fe11, 0xeb1570c1, 0xdd2e10a5, 0x50fb9e75, 0x3d0ce810, 0xb0d966c0, 0x86e206a4, 0x0b378874, 0x629e78e0, 0xef4bf630, 0xd9709654, 0x54a51884, 0x721a14d7, 0xffcf9a07, 0xc9f4fa63, 0x442174b3, 0x2d888427, 0xa05d0af7, 0x96666a93, 0x1bb3e443, 0x76449226, 0xfb911cf6, 0xcdaa7c92, 0x407ff242, 0x29d602d6, 0xa4038c06, 0x9238ec62, 0x1fed62b2, 0x977e4612, 0x1aabc8c2, 0x2c90a8a6, 0xa1452676, 0xc8ecd6e2, 0x45395832, 0x73023856, 0xfed7b686, 0x9320c0e3, 0x1ef54e33, 0x28ce2e57, 0xa51ba087, 0xccb25013, 0x4167dec3, 0x775cbea7, 0xfa893077, 0xdc363c24, 0x51e3b2f4, 0x67d8d290, 0xea0d5c40, 0x83a4acd4, 0x0e712204, 0x384a4260, 0xb59fccb0, 0xd868bad5, 0x55bd3405, 0x63865461, 0xee53dab1, 0x87fa2a25, 0x0a2fa4f5, 0x3c14c491, 0xb1c14a41, 0xf44bce01, 0x799e40d1, 0x4fa520b5, 0xc270ae65, 0xabd95ef1, 0x260cd021, 0x1037b045, 0x9de23e95, 0xf01548f0, 0x7dc0c620, 0x4bfba644, 0xc62e2894, 0xaf87d800, 0x225256d0, 0x146936b4, 0x99bcb864, 0xbf03b437, 0x32d63ae7, 0x04ed5a83, 0x8938d453, 0xe09124c7, 0x6d44aa17, 0x5b7fca73, 0xd6aa44a3, 0xbb5d32c6, 0x3688bc16, 0x00b3dc72, 0x8d6652a2, 0xe4cfa236, 0x691a2ce6, 0x5f214c82, 0xd2f4c252, 0x5a67e6f2, 0xd7b26822, 0xe1890846, 0x6c5c8696, 0x05f57602, 0x8820f8d2, 0xbe1b98b6, 0x33ce1666, 0x5e396003, 0xd3eceed3, 0xe5d78eb7, 0x68020067, 0x01abf0f3, 0x8c7e7e23, 0xba451e47, 0x37909097, 0x112f9cc4, 0x9cfa1214, 0xaac17270, 0x2714fca0, 0x4ebd0c34, 0xc36882e4, 0xf553e280, 0x78866c50, 0x15711a35, 0x98a494e5, 0xae9ff481, 0x234a7a51, 0x4ae38ac5, 0xc7360415, 0xf10d6471, 0x7cd8eaa1 +}, +{ +0x00000000, 0x493d68d1, 0xc0a98496, 0x8994ec47, 0x6d12032a, 0x242f6bfb, 0xadbb87bc, 0xe486ef6d, 0xf2678143, 0xbb5ae992, 0x32ce05d5, 0x7bf36d04, 0x9f758269, 0xd648eab8, 0x5fdc06ff, 0x16e16e2e, 0x976d9401, 0xde50fcd0, 0x57c41097, 0x1ef97846, 0xfa7f972b, 0xb342fffa, 0x3ad613bd, 0x73eb7b6c, 0x650a1542, 0x2c377d93, 0xa5a391d4, 0xec9ef905, 0x08181668, 0x41257eb9, 0xc8b192fe, 0x818cfa2f, 0x9e4d302a, 0xd77058fb, 0x5ee4b4bc, 0x17d9dc6d, 0xf35f3300, 0xba625bd1, 0x33f6b796, 0x7acbdf47, 0x6c2ab169, 0x2517d9b8, 0xac8335ff, 0xe5be5d2e, 0x0138b243, 0x4805da92, 0xc19136d5, 0x88ac5e04, 0x0920a42b, 0x401dccfa, 0xc98920bd, 0x80b4486c, 0x6432a701, 0x2d0fcfd0, 0xa49b2397, 0xeda64b46, 0xfb472568, 0xb27a4db9, 0x3beea1fe, 0x72d3c92f, 0x96552642, 0xdf684e93, 0x56fca2d4, 0x1fc1ca05, 0x797b0673, 0x30466ea2, 0xb9d282e5, 0xf0efea34, 0x14690559, 0x5d546d88, 0xd4c081cf, 0x9dfde91e, 0x8b1c8730, 0xc221efe1, 0x4bb503a6, 0x02886b77, 0xe60e841a, 0xaf33eccb, 0x26a7008c, 0x6f9a685d, 0xee169272, 0xa72bfaa3, 0x2ebf16e4, 0x67827e35, 0x83049158, 0xca39f989, 0x43ad15ce, 0x0a907d1f, 0x1c711331, 0x554c7be0, 0xdcd897a7, 0x95e5ff76, 0x7163101b, 0x385e78ca, 0xb1ca948d, 0xf8f7fc5c, 0xe7363659, 0xae0b5e88, 0x279fb2cf, 0x6ea2da1e, 0x8a243573, 0xc3195da2, 0x4a8db1e5, 0x03b0d934, 0x1551b71a, 0x5c6cdfcb, 0xd5f8338c, 0x9cc55b5d, 0x7843b430, 0x317edce1, 0xb8ea30a6, 0xf1d75877, 0x705ba258, 0x3966ca89, 0xb0f226ce, 0xf9cf4e1f, 0x1d49a172, 0x5474c9a3, 0xdde025e4, 0x94dd4d35, 0x823c231b, 0xcb014bca, 0x4295a78d, 0x0ba8cf5c, 0xef2e2031, 0xa61348e0, 0x2f87a4a7, 0x66bacc76, 0x3513ee6a, 0x7c2e86bb, 0xf5ba6afc, 0xbc87022d, 0x5801ed40, 0x113c8591, 0x98a869d6, 0xd1950107, 0xc7746f29, 0x8e4907f8, 0x07ddebbf, 0x4ee0836e, 0xaa666c03, 0xe35b04d2, 0x6acfe895, 0x23f28044, 0xa27e7a6b, 0xeb4312ba, 0x62d7fefd, 0x2bea962c, 0xcf6c7941, 0x86511190, 0x0fc5fdd7, 0x46f89506, 0x5019fb28, 0x192493f9, 0x90b07fbe, 0xd98d176f, 0x3d0bf802, 0x743690d3, 0xfda27c94, 0xb49f1445, 0xab5ede40, 0xe263b691, 0x6bf75ad6, 0x22ca3207, 0xc64cdd6a, 0x8f71b5bb, 0x06e559fc, 0x4fd8312d, 0x59395f03, 0x100437d2, 0x9990db95, 0xd0adb344, 0x342b5c29, 0x7d1634f8, 0xf482d8bf, 0xbdbfb06e, 0x3c334a41, 0x750e2290, 0xfc9aced7, 0xb5a7a606, 0x5121496b, 0x181c21ba, 0x9188cdfd, 0xd8b5a52c, 0xce54cb02, 0x8769a3d3, 0x0efd4f94, 0x47c02745, 0xa346c828, 0xea7ba0f9, 0x63ef4cbe, 0x2ad2246f, 0x4c68e819, 0x055580c8, 0x8cc16c8f, 0xc5fc045e, 0x217aeb33, 0x684783e2, 0xe1d36fa5, 0xa8ee0774, 0xbe0f695a, 0xf732018b, 0x7ea6edcc, 0x379b851d, 0xd31d6a70, 0x9a2002a1, 0x13b4eee6, 0x5a898637, 0xdb057c18, 0x923814c9, 0x1bacf88e, 0x5291905f, 0xb6177f32, 0xff2a17e3, 0x76befba4, 0x3f839375, 0x2962fd5b, 0x605f958a, 0xe9cb79cd, 0xa0f6111c, 0x4470fe71, 0x0d4d96a0, 0x84d97ae7, 0xcde41236, 0xd225d833, 0x9b18b0e2, 0x128c5ca5, 0x5bb13474, 0xbf37db19, 0xf60ab3c8, 0x7f9e5f8f, 0x36a3375e, 0x20425970, 0x697f31a1, 0xe0ebdde6, 0xa9d6b537, 0x4d505a5a, 0x046d328b, 0x8df9decc, 0xc4c4b61d, 0x45484c32, 0x0c7524e3, 0x85e1c8a4, 0xccdca075, 0x285a4f18, 0x616727c9, 0xe8f3cb8e, 0xa1cea35f, 0xb72fcd71, 0xfe12a5a0, 0x778649e7, 0x3ebb2136, 0xda3dce5b, 0x9300a68a, 0x1a944acd, 0x53a9221c +}, +{ +0x00000000, 0xee6d6a2b, 0xc597b65d, 0x2bfadc76, 0x3ba17cfe, 0xd5cc16d5, 0xfe36caa3, 0x105ba088, 0x22e86286, 0xcc8508ad, 0xe77fd4db, 0x0912bef0, 0x19491e78, 0xf7247453, 0xdcdea825, 0x32b3c20e, 0xcc747ff2, 0x221915d9, 0x09e3c9af, 0xe78ea384, 0xf7d5030c, 0x19b86927, 0x3242b551, 0xdc2fdf7a, 0xee9c1d74, 0x00f1775f, 0x2b0bab29, 0xc566c102, 0xd53d618a, 0x3b500ba1, 0x10aad7d7, 0xfec7bdfc, 0x30e58c41, 0xde88e66a, 0xf5723a1c, 0x1b1f5037, 0x0b44f0bf, 0xe5299a94, 0xced346e2, 0x20be2cc9, 0x120deec7, 0xfc6084ec, 0xd79a589a, 0x39f732b1, 0x29ac9239, 0xc7c1f812, 0xec3b2464, 0x02564e4f, 0xfc91f3b3, 0x12fc9998, 0x390645ee, 0xd76b2fc5, 0xc7308f4d, 0x295de566, 0x02a73910, 0xecca533b, 0xde799135, 0x3014fb1e, 0x1bee2768, 0xf5834d43, 0xe5d8edcb, 0x0bb587e0, 0x204f5b96, 0xce2231bd, 0xa93740e4, 0x475a2acf, 0x6ca0f6b9, 0x82cd9c92, 0x92963c1a, 0x7cfb5631, 0x57018a47, 0xb96ce06c, 0x8bdf2262, 0x65b24849, 0x4e48943f, 0xa025fe14, 0xb07e5e9c, 0x5e1334b7, 0x75e9e8c1, 0x9b8482ea, 0x65433f16, 0x8b2e553d, 0xa0d4894b, 0x4eb9e360, 0x5ee243e8, 0xb08f29c3, 0x9b75f5b5, 0x75189f9e, 0x47ab5d90, 0xa9c637bb, 0x823cebcd, 0x6c5181e6, 0x7c0a216e, 0x92674b45, 0xb99d9733, 0x57f0fd18, 0x99d2cca5, 0x77bfa68e, 0x5c457af8, 0xb22810d3, 0xa273b05b, 0x4c1eda70, 0x67e40606, 0x89896c2d, 0xbb3aae23, 0x5557c408, 0x7ead187e, 0x90c07255, 0x809bd2dd, 0x6ef6b8f6, 0x450c6480, 0xab610eab, 0x55a6b357, 0xbbcbd97c, 0x9031050a, 0x7e5c6f21, 0x6e07cfa9, 0x806aa582, 0xab9079f4, 0x45fd13df, 0x774ed1d1, 0x9923bbfa, 0xb2d9678c, 0x5cb40da7, 0x4cefad2f, 0xa282c704, 0x89781b72, 0x67157159, 0x5fdf8717, 0xb1b2ed3c, 0x9a48314a, 0x74255b61, 0x647efbe9, 0x8a1391c2, 0xa1e94db4, 0x4f84279f, 0x7d37e591, 0x935a8fba, 0xb8a053cc, 0x56cd39e7, 0x4696996f, 0xa8fbf344, 0x83012f32, 0x6d6c4519, 0x93abf8e5, 0x7dc692ce, 0x563c4eb8, 0xb8512493, 0xa80a841b, 0x4667ee30, 0x6d9d3246, 0x83f0586d, 0xb1439a63, 0x5f2ef048, 0x74d42c3e, 0x9ab94615, 0x8ae2e69d, 0x648f8cb6, 0x4f7550c0, 0xa1183aeb, 0x6f3a0b56, 0x8157617d, 0xaaadbd0b, 0x44c0d720, 0x549b77a8, 0xbaf61d83, 0x910cc1f5, 0x7f61abde, 0x4dd269d0, 0xa3bf03fb, 0x8845df8d, 0x6628b5a6, 0x7673152e, 0x981e7f05, 0xb3e4a373, 0x5d89c958, 0xa34e74a4, 0x4d231e8f, 0x66d9c2f9, 0x88b4a8d2, 0x98ef085a, 0x76826271, 0x5d78be07, 0xb315d42c, 0x81a61622, 0x6fcb7c09, 0x4431a07f, 0xaa5cca54, 0xba076adc, 0x546a00f7, 0x7f90dc81, 0x91fdb6aa, 0xf6e8c7f3, 0x1885add8, 0x337f71ae, 0xdd121b85, 0xcd49bb0d, 0x2324d126, 0x08de0d50, 0xe6b3677b, 0xd400a575, 0x3a6dcf5e, 0x11971328, 0xfffa7903, 0xefa1d98b, 0x01ccb3a0, 0x2a366fd6, 0xc45b05fd, 0x3a9cb801, 0xd4f1d22a, 0xff0b0e5c, 0x11666477, 0x013dc4ff, 0xef50aed4, 0xc4aa72a2, 0x2ac71889, 0x1874da87, 0xf619b0ac, 0xdde36cda, 0x338e06f1, 0x23d5a679, 0xcdb8cc52, 0xe6421024, 0x082f7a0f, 0xc60d4bb2, 0x28602199, 0x039afdef, 0xedf797c4, 0xfdac374c, 0x13c15d67, 0x383b8111, 0xd656eb3a, 0xe4e52934, 0x0a88431f, 0x21729f69, 0xcf1ff542, 0xdf4455ca, 0x31293fe1, 0x1ad3e397, 0xf4be89bc, 0x0a793440, 0xe4145e6b, 0xcfee821d, 0x2183e836, 0x31d848be, 0xdfb52295, 0xf44ffee3, 0x1a2294c8, 0x289156c6, 0xc6fc3ced, 0xed06e09b, 0x036b8ab0, 0x13302a38, 0xfd5d4013, 0xd6a79c65, 0x38caf64e +} +}, +{ +{ +0x00000000, 0xf18e06f6, 0x38f5b786, 0xc97bb170, 0xb17281ca, 0x40fc873c, 0x8987364c, 0x780930ba, 0x62fc6ed3, 0x93726825, 0x5a09d955, 0xab87dfa3, 0xd38eef19, 0x2200e9ef, 0xeb7b589f, 0x1af55e69, 0x6a1e200b, 0x9b9026fd, 0x52eb978d, 0xa365917b, 0xdb6ca1c1, 0x2ae2a737, 0xe3991647, 0x121710b1, 0x08e24ed8, 0xf96c482e, 0x3017f95e, 0xc199ffa8, 0xb990cf12, 0x481ec9e4, 0x81657894, 0x70eb7e62, 0x994f0e44, 0x68c108b2, 0xa1bab9c2, 0x5034bf34, 0x283d8f8e, 0xd9b38978, 0x10c83808, 0xe1463efe, 0xfbb36097, 0x0a3d6661, 0xc346d711, 0x32c8d1e7, 0x4ac1e15d, 0xbb4fe7ab, 0x723456db, 0x83ba502d, 0xf3512e4f, 0x02df28b9, 0xcba499c9, 0x3a2a9f3f, 0x4223af85, 0xb3ada973, 0x7ad61803, 0x8b581ef5, 0x91ad409c, 0x6023466a, 0xa958f71a, 0x58d6f1ec, 0x20dfc156, 0xd151c7a0, 0x182a76d0, 0xe9a47026, 0x1107ef8e, 0xe089e978, 0x29f25808, 0xd87c5efe, 0xa0756e44, 0x51fb68b2, 0x9880d9c2, 0x690edf34, 0x73fb815d, 0x827587ab, 0x4b0e36db, 0xba80302d, 0xc2890097, 0x33070661, 0xfa7cb711, 0x0bf2b1e7, 0x7b19cf85, 0x8a97c973, 0x43ec7803, 0xb2627ef5, 0xca6b4e4f, 0x3be548b9, 0xf29ef9c9, 0x0310ff3f, 0x19e5a156, 0xe86ba7a0, 0x211016d0, 0xd09e1026, 0xa897209c, 0x5919266a, 0x9062971a, 0x61ec91ec, 0x8848e1ca, 0x79c6e73c, 0xb0bd564c, 0x413350ba, 0x393a6000, 0xc8b466f6, 0x01cfd786, 0xf041d170, 0xeab48f19, 0x1b3a89ef, 0xd241389f, 0x23cf3e69, 0x5bc60ed3, 0xaa480825, 0x6333b955, 0x92bdbfa3, 0xe256c1c1, 0x13d8c737, 0xdaa37647, 0x2b2d70b1, 0x5324400b, 0xa2aa46fd, 0x6bd1f78d, 0x9a5ff17b, 0x80aaaf12, 0x7124a9e4, 0xb85f1894, 0x49d11e62, 0x31d82ed8, 0xc056282e, 0x092d995e, 0xf8a39fa8, 0xf71e4f40, 0x069049b6, 0xcfebf8c6, 0x3e65fe30, 0x466cce8a, 0xb7e2c87c, 0x7e99790c, 0x8f177ffa, 0x95e22193, 0x646c2765, 0xad179615, 0x5c9990e3, 0x2490a059, 0xd51ea6af, 0x1c6517df, 0xedeb1129, 0x9d006f4b, 0x6c8e69bd, 0xa5f5d8cd, 0x547bde3b, 0x2c72ee81, 0xddfce877, 0x14875907, 0xe5095ff1, 0xfffc0198, 0x0e72076e, 0xc709b61e, 0x3687b0e8, 0x4e8e8052, 0xbf0086a4, 0x767b37d4, 0x87f53122, 0x6e514104, 0x9fdf47f2, 0x56a4f682, 0xa72af074, 0xdf23c0ce, 0x2eadc638, 0xe7d67748, 0x165871be, 0x0cad2fd7, 0xfd232921, 0x34589851, 0xc5d69ea7, 0xbddfae1d, 0x4c51a8eb, 0x852a199b, 0x74a41f6d, 0x044f610f, 0xf5c167f9, 0x3cbad689, 0xcd34d07f, 0xb53de0c5, 0x44b3e633, 0x8dc85743, 0x7c4651b5, 0x66b30fdc, 0x973d092a, 0x5e46b85a, 0xafc8beac, 0xd7c18e16, 0x264f88e0, 0xef343990, 0x1eba3f66, 0xe619a0ce, 0x1797a638, 0xdeec1748, 0x2f6211be, 0x576b2104, 0xa6e527f2, 0x6f9e9682, 0x9e109074, 0x84e5ce1d, 0x756bc8eb, 0xbc10799b, 0x4d9e7f6d, 0x35974fd7, 0xc4194921, 0x0d62f851, 0xfcecfea7, 0x8c0780c5, 0x7d898633, 0xb4f23743, 0x457c31b5, 0x3d75010f, 0xccfb07f9, 0x0580b689, 0xf40eb07f, 0xeefbee16, 0x1f75e8e0, 0xd60e5990, 0x27805f66, 0x5f896fdc, 0xae07692a, 0x677cd85a, 0x96f2deac, 0x7f56ae8a, 0x8ed8a87c, 0x47a3190c, 0xb62d1ffa, 0xce242f40, 0x3faa29b6, 0xf6d198c6, 0x075f9e30, 0x1daac059, 0xec24c6af, 0x255f77df, 0xd4d17129, 0xacd84193, 0x5d564765, 0x942df615, 0x65a3f0e3, 0x15488e81, 0xe4c68877, 0x2dbd3907, 0xdc333ff1, 0xa43a0f4b, 0x55b409bd, 0x9ccfb8cd, 0x6d41be3b, 0x77b4e052, 0x863ae6a4, 0x4f4157d4, 0xbecf5122, 0xc6c66198, 0x3748676e, 0xfe33d61e, 0x0fbdd0e8 +}, +{ +0x00000000, 0xa7ebad53, 0x26ef7e95, 0x8104d3c6, 0x2da57e92, 0x8a4ed3c1, 0x0b4a0007, 0xaca1ad54, 0xb3a01bdd, 0x144bb68e, 0x954f6548, 0x32a4c81b, 0x9e05654f, 0x39eec81c, 0xb8ea1bda, 0x1f01b689, 0xe37f4745, 0x4494ea16, 0xc59039d0, 0x627b9483, 0xceda39d7, 0x69319484, 0xe8354742, 0x4fdeea11, 0x50df5c98, 0xf734f1cb, 0x7630220d, 0xd1db8f5e, 0x7d7a220a, 0xda918f59, 0x5b955c9f, 0xfc7ef1cc, 0xb3dd72c0, 0x1436df93, 0x95320c55, 0x32d9a106, 0x9e780c52, 0x3993a101, 0xb89772c7, 0x1f7cdf94, 0x007d691d, 0xa796c44e, 0x26921788, 0x8179badb, 0x2dd8178f, 0x8a33badc, 0x0b37691a, 0xacdcc449, 0x50a23585, 0xf74998d6, 0x764d4b10, 0xd1a6e643, 0x7d074b17, 0xdaece644, 0x5be83582, 0xfc0398d1, 0xe3022e58, 0x44e9830b, 0xc5ed50cd, 0x6206fd9e, 0xcea750ca, 0x694cfd99, 0xe8482e5f, 0x4fa3830c, 0xd308148b, 0x74e3b9d8, 0xf5e76a1e, 0x520cc74d, 0xfead6a19, 0x5946c74a, 0xd842148c, 0x7fa9b9df, 0x60a80f56, 0xc743a205, 0x464771c3, 0xe1acdc90, 0x4d0d71c4, 0xeae6dc97, 0x6be20f51, 0xcc09a202, 0x307753ce, 0x979cfe9d, 0x16982d5b, 0xb1738008, 0x1dd22d5c, 0xba39800f, 0x3b3d53c9, 0x9cd6fe9a, 0x83d74813, 0x243ce540, 0xa5383686, 0x02d39bd5, 0xae723681, 0x09999bd2, 0x889d4814, 0x2f76e547, 0x60d5664b, 0xc73ecb18, 0x463a18de, 0xe1d1b58d, 0x4d7018d9, 0xea9bb58a, 0x6b9f664c, 0xcc74cb1f, 0xd3757d96, 0x749ed0c5, 0xf59a0303, 0x5271ae50, 0xfed00304, 0x593bae57, 0xd83f7d91, 0x7fd4d0c2, 0x83aa210e, 0x24418c5d, 0xa5455f9b, 0x02aef2c8, 0xae0f5f9c, 0x09e4f2cf, 0x88e02109, 0x2f0b8c5a, 0x300a3ad3, 0x97e19780, 0x16e54446, 0xb10ee915, 0x1daf4441, 0xba44e912, 0x3b403ad4, 0x9cab9787, 0xd6dcf5a3, 0x713758f0, 0xf0338b36, 0x57d82665, 0xfb798b31, 0x5c922662, 0xdd96f5a4, 0x7a7d58f7, 0x657cee7e, 0xc297432d, 0x439390eb, 0xe4783db8, 0x48d990ec, 0xef323dbf, 0x6e36ee79, 0xc9dd432a, 0x35a3b2e6, 0x92481fb5, 0x134ccc73, 0xb4a76120, 0x1806cc74, 0xbfed6127, 0x3ee9b2e1, 0x99021fb2, 0x8603a93b, 0x21e80468, 0xa0ecd7ae, 0x07077afd, 0xaba6d7a9, 0x0c4d7afa, 0x8d49a93c, 0x2aa2046f, 0x65018763, 0xc2ea2a30, 0x43eef9f6, 0xe40554a5, 0x48a4f9f1, 0xef4f54a2, 0x6e4b8764, 0xc9a02a37, 0xd6a19cbe, 0x714a31ed, 0xf04ee22b, 0x57a54f78, 0xfb04e22c, 0x5cef4f7f, 0xddeb9cb9, 0x7a0031ea, 0x867ec026, 0x21956d75, 0xa091beb3, 0x077a13e0, 0xabdbbeb4, 0x0c3013e7, 0x8d34c021, 0x2adf6d72, 0x35dedbfb, 0x923576a8, 0x1331a56e, 0xb4da083d, 0x187ba569, 0xbf90083a, 0x3e94dbfc, 0x997f76af, 0x05d4e128, 0xa23f4c7b, 0x233b9fbd, 0x84d032ee, 0x28719fba, 0x8f9a32e9, 0x0e9ee12f, 0xa9754c7c, 0xb674faf5, 0x119f57a6, 0x909b8460, 0x37702933, 0x9bd18467, 0x3c3a2934, 0xbd3efaf2, 0x1ad557a1, 0xe6aba66d, 0x41400b3e, 0xc044d8f8, 0x67af75ab, 0xcb0ed8ff, 0x6ce575ac, 0xede1a66a, 0x4a0a0b39, 0x550bbdb0, 0xf2e010e3, 0x73e4c325, 0xd40f6e76, 0x78aec322, 0xdf456e71, 0x5e41bdb7, 0xf9aa10e4, 0xb60993e8, 0x11e23ebb, 0x90e6ed7d, 0x370d402e, 0x9baced7a, 0x3c474029, 0xbd4393ef, 0x1aa83ebc, 0x05a98835, 0xa2422566, 0x2346f6a0, 0x84ad5bf3, 0x280cf6a7, 0x8fe75bf4, 0x0ee38832, 0xa9082561, 0x5576d4ad, 0xf29d79fe, 0x7399aa38, 0xd472076b, 0x78d3aa3f, 0xdf38076c, 0x5e3cd4aa, 0xf9d779f9, 0xe6d6cf70, 0x413d6223, 0xc039b1e5, 0x67d21cb6, 0xcb73b1e2, 0x6c981cb1, 0xed9ccf77, 0x4a776224 +}, +{ +0x00000000, 0x428b3ed1, 0x26cb4226, 0x64407cf7, 0x35e5e51e, 0x776edbcf, 0x132ea738, 0x51a599e9, 0xd28acb8e, 0x9001f55f, 0xf44189a8, 0xb6cab779, 0xe76f2e90, 0xa5e41041, 0xc1a46cb6, 0x832f5267, 0x54f23e2f, 0x167900fe, 0x72397c09, 0x30b242d8, 0x6117db31, 0x239ce5e0, 0x47dc9917, 0x0557a7c6, 0x8678f5a1, 0xc4f3cb70, 0xa0b3b787, 0xe2388956, 0xb39d10bf, 0xf1162e6e, 0x95565299, 0xd7dd6c48, 0x60f4be17, 0x227f80c6, 0x463ffc31, 0x04b4c2e0, 0x55115b09, 0x179a65d8, 0x73da192f, 0x315127fe, 0xb27e7599, 0xf0f54b48, 0x94b537bf, 0xd63e096e, 0x879b9087, 0xc510ae56, 0xa150d2a1, 0xe3dbec70, 0x34068038, 0x768dbee9, 0x12cdc21e, 0x5046fccf, 0x01e36526, 0x43685bf7, 0x27282700, 0x65a319d1, 0xe68c4bb6, 0xa4077567, 0xc0470990, 0x82cc3741, 0xd369aea8, 0x91e29079, 0xf5a2ec8e, 0xb729d25f, 0xb7a53f7b, 0xf52e01aa, 0x916e7d5d, 0xd3e5438c, 0x8240da65, 0xc0cbe4b4, 0xa48b9843, 0xe600a692, 0x652ff4f5, 0x27a4ca24, 0x43e4b6d3, 0x016f8802, 0x50ca11eb, 0x12412f3a, 0x760153cd, 0x348a6d1c, 0xe3570154, 0xa1dc3f85, 0xc59c4372, 0x87177da3, 0xd6b2e44a, 0x9439da9b, 0xf079a66c, 0xb2f298bd, 0x31ddcada, 0x7356f40b, 0x171688fc, 0x559db62d, 0x04382fc4, 0x46b31115, 0x22f36de2, 0x60785333, 0xd751816c, 0x95dabfbd, 0xf19ac34a, 0xb311fd9b, 0xe2b46472, 0xa03f5aa3, 0xc47f2654, 0x86f41885, 0x05db4ae2, 0x47507433, 0x231008c4, 0x619b3615, 0x303eaffc, 0x72b5912d, 0x16f5edda, 0x547ed30b, 0x83a3bf43, 0xc1288192, 0xa568fd65, 0xe7e3c3b4, 0xb6465a5d, 0xf4cd648c, 0x908d187b, 0xd20626aa, 0x512974cd, 0x13a24a1c, 0x77e236eb, 0x3569083a, 0x64cc91d3, 0x2647af02, 0x4207d3f5, 0x008ced24, 0x8ee5d628, 0xcc6ee8f9, 0xa82e940e, 0xeaa5aadf, 0xbb003336, 0xf98b0de7, 0x9dcb7110, 0xdf404fc1, 0x5c6f1da6, 0x1ee42377, 0x7aa45f80, 0x382f6151, 0x698af8b8, 0x2b01c669, 0x4f41ba9e, 0x0dca844f, 0xda17e807, 0x989cd6d6, 0xfcdcaa21, 0xbe5794f0, 0xeff20d19, 0xad7933c8, 0xc9394f3f, 0x8bb271ee, 0x089d2389, 0x4a161d58, 0x2e5661af, 0x6cdd5f7e, 0x3d78c697, 0x7ff3f846, 0x1bb384b1, 0x5938ba60, 0xee11683f, 0xac9a56ee, 0xc8da2a19, 0x8a5114c8, 0xdbf48d21, 0x997fb3f0, 0xfd3fcf07, 0xbfb4f1d6, 0x3c9ba3b1, 0x7e109d60, 0x1a50e197, 0x58dbdf46, 0x097e46af, 0x4bf5787e, 0x2fb50489, 0x6d3e3a58, 0xbae35610, 0xf86868c1, 0x9c281436, 0xdea32ae7, 0x8f06b30e, 0xcd8d8ddf, 0xa9cdf128, 0xeb46cff9, 0x68699d9e, 0x2ae2a34f, 0x4ea2dfb8, 0x0c29e169, 0x5d8c7880, 0x1f074651, 0x7b473aa6, 0x39cc0477, 0x3940e953, 0x7bcbd782, 0x1f8bab75, 0x5d0095a4, 0x0ca50c4d, 0x4e2e329c, 0x2a6e4e6b, 0x68e570ba, 0xebca22dd, 0xa9411c0c, 0xcd0160fb, 0x8f8a5e2a, 0xde2fc7c3, 0x9ca4f912, 0xf8e485e5, 0xba6fbb34, 0x6db2d77c, 0x2f39e9ad, 0x4b79955a, 0x09f2ab8b, 0x58573262, 0x1adc0cb3, 0x7e9c7044, 0x3c174e95, 0xbf381cf2, 0xfdb32223, 0x99f35ed4, 0xdb786005, 0x8addf9ec, 0xc856c73d, 0xac16bbca, 0xee9d851b, 0x59b45744, 0x1b3f6995, 0x7f7f1562, 0x3df42bb3, 0x6c51b25a, 0x2eda8c8b, 0x4a9af07c, 0x0811cead, 0x8b3e9cca, 0xc9b5a21b, 0xadf5deec, 0xef7ee03d, 0xbedb79d4, 0xfc504705, 0x98103bf2, 0xda9b0523, 0x0d46696b, 0x4fcd57ba, 0x2b8d2b4d, 0x6906159c, 0x38a38c75, 0x7a28b2a4, 0x1e68ce53, 0x5ce3f082, 0xdfcca2e5, 0x9d479c34, 0xf907e0c3, 0xbb8cde12, 0xea2947fb, 0xa8a2792a, 0xcce205dd, 0x8e693b0c +}, +{ +0x00000000, 0x33b92074, 0x763aafb6, 0x45838fc2, 0x32f16fe3, 0x01484f97, 0x44cbc055, 0x7772e021, 0x45aa60bb, 0x761340cf, 0x3390cf0d, 0x0029ef79, 0x775b0f58, 0x44e22f2c, 0x0161a0ee, 0x32d8809a, 0x4ea27d0f, 0x7d1b5d7b, 0x3898d2b9, 0x0b21f2cd, 0x7c5312ec, 0x4fea3298, 0x0a69bd5a, 0x39d09d2e, 0x0b081db4, 0x38b13dc0, 0x7d32b202, 0x4e8b9276, 0x39f97257, 0x0a405223, 0x4fc3dde1, 0x7c7afd95, 0x85dbdeea, 0xb662fe9e, 0xf3e1715c, 0xc0585128, 0xb72ab109, 0x8493917d, 0xc1101ebf, 0xf2a93ecb, 0xc071be51, 0xf3c89e25, 0xb64b11e7, 0x85f23193, 0xf280d1b2, 0xc139f1c6, 0x84ba7e04, 0xb7035e70, 0xcb79a3e5, 0xf8c08391, 0xbd430c53, 0x8efa2c27, 0xf988cc06, 0xca31ec72, 0x8fb263b0, 0xbc0b43c4, 0x8ed3c35e, 0xbd6ae32a, 0xf8e96ce8, 0xcb504c9c, 0xbc22acbd, 0x8f9b8cc9, 0xca18030b, 0xf9a1237f, 0xed6810a9, 0xded130dd, 0x9b52bf1f, 0xa8eb9f6b, 0xdf997f4a, 0xec205f3e, 0xa9a3d0fc, 0x9a1af088, 0xa8c27012, 0x9b7b5066, 0xdef8dfa4, 0xed41ffd0, 0x9a331ff1, 0xa98a3f85, 0xec09b047, 0xdfb09033, 0xa3ca6da6, 0x90734dd2, 0xd5f0c210, 0xe649e264, 0x913b0245, 0xa2822231, 0xe701adf3, 0xd4b88d87, 0xe6600d1d, 0xd5d92d69, 0x905aa2ab, 0xa3e382df, 0xd49162fe, 0xe728428a, 0xa2abcd48, 0x9112ed3c, 0x68b3ce43, 0x5b0aee37, 0x1e8961f5, 0x2d304181, 0x5a42a1a0, 0x69fb81d4, 0x2c780e16, 0x1fc12e62, 0x2d19aef8, 0x1ea08e8c, 0x5b23014e, 0x689a213a, 0x1fe8c11b, 0x2c51e16f, 0x69d26ead, 0x5a6b4ed9, 0x2611b34c, 0x15a89338, 0x502b1cfa, 0x63923c8e, 0x14e0dcaf, 0x2759fcdb, 0x62da7319, 0x5163536d, 0x63bbd3f7, 0x5002f383, 0x15817c41, 0x26385c35, 0x514abc14, 0x62f39c60, 0x277013a2, 0x14c933d6, 0xc9082820, 0xfab10854, 0xbf328796, 0x8c8ba7e2, 0xfbf947c3, 0xc84067b7, 0x8dc3e875, 0xbe7ac801, 0x8ca2489b, 0xbf1b68ef, 0xfa98e72d, 0xc921c759, 0xbe532778, 0x8dea070c, 0xc86988ce, 0xfbd0a8ba, 0x87aa552f, 0xb413755b, 0xf190fa99, 0xc229daed, 0xb55b3acc, 0x86e21ab8, 0xc361957a, 0xf0d8b50e, 0xc2003594, 0xf1b915e0, 0xb43a9a22, 0x8783ba56, 0xf0f15a77, 0xc3487a03, 0x86cbf5c1, 0xb572d5b5, 0x4cd3f6ca, 0x7f6ad6be, 0x3ae9597c, 0x09507908, 0x7e229929, 0x4d9bb95d, 0x0818369f, 0x3ba116eb, 0x09799671, 0x3ac0b605, 0x7f4339c7, 0x4cfa19b3, 0x3b88f992, 0x0831d9e6, 0x4db25624, 0x7e0b7650, 0x02718bc5, 0x31c8abb1, 0x744b2473, 0x47f20407, 0x3080e426, 0x0339c452, 0x46ba4b90, 0x75036be4, 0x47dbeb7e, 0x7462cb0a, 0x31e144c8, 0x025864bc, 0x752a849d, 0x4693a4e9, 0x03102b2b, 0x30a90b5f, 0x24603889, 0x17d918fd, 0x525a973f, 0x61e3b74b, 0x1691576a, 0x2528771e, 0x60abf8dc, 0x5312d8a8, 0x61ca5832, 0x52737846, 0x17f0f784, 0x2449d7f0, 0x533b37d1, 0x608217a5, 0x25019867, 0x16b8b813, 0x6ac24586, 0x597b65f2, 0x1cf8ea30, 0x2f41ca44, 0x58332a65, 0x6b8a0a11, 0x2e0985d3, 0x1db0a5a7, 0x2f68253d, 0x1cd10549, 0x59528a8b, 0x6aebaaff, 0x1d994ade, 0x2e206aaa, 0x6ba3e568, 0x581ac51c, 0xa1bbe663, 0x9202c617, 0xd78149d5, 0xe43869a1, 0x934a8980, 0xa0f3a9f4, 0xe5702636, 0xd6c90642, 0xe41186d8, 0xd7a8a6ac, 0x922b296e, 0xa192091a, 0xd6e0e93b, 0xe559c94f, 0xa0da468d, 0x936366f9, 0xef199b6c, 0xdca0bb18, 0x992334da, 0xaa9a14ae, 0xdde8f48f, 0xee51d4fb, 0xabd25b39, 0x986b7b4d, 0xaab3fbd7, 0x990adba3, 0xdc895461, 0xef307415, 0x98429434, 0xabfbb440, 0xee783b82, 0xddc11bf6 +}, +{ +0x00000000, 0x898ed6f7, 0x88bb5d2b, 0x01358bdc, 0x6bc40b2f, 0xe24addd8, 0xe37f5604, 0x6af180f3, 0x64764b58, 0xedf89daf, 0xeccd1673, 0x6543c084, 0x0fb24077, 0x863c9680, 0x87091d5c, 0x0e87cbab, 0xfb829bbc, 0x720c4d4b, 0x7339c697, 0xfab71060, 0x90469093, 0x19c84664, 0x18fdcdb8, 0x91731b4f, 0x9ff4d0e4, 0x167a0613, 0x174f8dcf, 0x9ec15b38, 0xf430dbcb, 0x7dbe0d3c, 0x7c8b86e0, 0xf5055017, 0x34f4419f, 0xbd7a9768, 0xbc4f1cb4, 0x35c1ca43, 0x5f304ab0, 0xd6be9c47, 0xd78b179b, 0x5e05c16c, 0x50820ac7, 0xd90cdc30, 0xd83957ec, 0x51b7811b, 0x3b4601e8, 0xb2c8d71f, 0xb3fd5cc3, 0x3a738a34, 0xcf76da23, 0x46f80cd4, 0x47cd8708, 0xce4351ff, 0xa4b2d10c, 0x2d3c07fb, 0x2c098c27, 0xa5875ad0, 0xab00917b, 0x228e478c, 0x23bbcc50, 0xaa351aa7, 0xc0c49a54, 0x494a4ca3, 0x487fc77f, 0xc1f11188, 0xad8f7554, 0x2401a3a3, 0x2534287f, 0xacbafe88, 0xc64b7e7b, 0x4fc5a88c, 0x4ef02350, 0xc77ef5a7, 0xc9f93e0c, 0x4077e8fb, 0x41426327, 0xc8ccb5d0, 0xa23d3523, 0x2bb3e3d4, 0x2a866808, 0xa308beff, 0x560deee8, 0xdf83381f, 0xdeb6b3c3, 0x57386534, 0x3dc9e5c7, 0xb4473330, 0xb572b8ec, 0x3cfc6e1b, 0x327ba5b0, 0xbbf57347, 0xbac0f89b, 0x334e2e6c, 0x59bfae9f, 0xd0317868, 0xd104f3b4, 0x588a2543, 0x997b34cb, 0x10f5e23c, 0x11c069e0, 0x984ebf17, 0xf2bf3fe4, 0x7b31e913, 0x7a0462cf, 0xf38ab438, 0xfd0d7f93, 0x7483a964, 0x75b622b8, 0xfc38f44f, 0x96c974bc, 0x1f47a24b, 0x1e722997, 0x97fcff60, 0x62f9af77, 0xeb777980, 0xea42f25c, 0x63cc24ab, 0x093da458, 0x80b372af, 0x8186f973, 0x08082f84, 0x068fe42f, 0x8f0132d8, 0x8e34b904, 0x07ba6ff3, 0x6d4bef00, 0xe4c539f7, 0xe5f0b22b, 0x6c7e64dc, 0x3451c6d2, 0xbddf1025, 0xbcea9bf9, 0x35644d0e, 0x5f95cdfd, 0xd61b1b0a, 0xd72e90d6, 0x5ea04621, 0x50278d8a, 0xd9a95b7d, 0xd89cd0a1, 0x51120656, 0x3be386a5, 0xb26d5052, 0xb358db8e, 0x3ad60d79, 0xcfd35d6e, 0x465d8b99, 0x47680045, 0xcee6d6b2, 0xa4175641, 0x2d9980b6, 0x2cac0b6a, 0xa522dd9d, 0xaba51636, 0x222bc0c1, 0x231e4b1d, 0xaa909dea, 0xc0611d19, 0x49efcbee, 0x48da4032, 0xc15496c5, 0x00a5874d, 0x892b51ba, 0x881eda66, 0x01900c91, 0x6b618c62, 0xe2ef5a95, 0xe3dad149, 0x6a5407be, 0x64d3cc15, 0xed5d1ae2, 0xec68913e, 0x65e647c9, 0x0f17c73a, 0x869911cd, 0x87ac9a11, 0x0e224ce6, 0xfb271cf1, 0x72a9ca06, 0x739c41da, 0xfa12972d, 0x90e317de, 0x196dc129, 0x18584af5, 0x91d69c02, 0x9f5157a9, 0x16df815e, 0x17ea0a82, 0x9e64dc75, 0xf4955c86, 0x7d1b8a71, 0x7c2e01ad, 0xf5a0d75a, 0x99deb386, 0x10506571, 0x1165eead, 0x98eb385a, 0xf21ab8a9, 0x7b946e5e, 0x7aa1e582, 0xf32f3375, 0xfda8f8de, 0x74262e29, 0x7513a5f5, 0xfc9d7302, 0x966cf3f1, 0x1fe22506, 0x1ed7aeda, 0x9759782d, 0x625c283a, 0xebd2fecd, 0xeae77511, 0x6369a3e6, 0x09982315, 0x8016f5e2, 0x81237e3e, 0x08ada8c9, 0x062a6362, 0x8fa4b595, 0x8e913e49, 0x071fe8be, 0x6dee684d, 0xe460beba, 0xe5553566, 0x6cdbe391, 0xad2af219, 0x24a424ee, 0x2591af32, 0xac1f79c5, 0xc6eef936, 0x4f602fc1, 0x4e55a41d, 0xc7db72ea, 0xc95cb941, 0x40d26fb6, 0x41e7e46a, 0xc869329d, 0xa298b26e, 0x2b166499, 0x2a23ef45, 0xa3ad39b2, 0x56a869a5, 0xdf26bf52, 0xde13348e, 0x579de279, 0x3d6c628a, 0xb4e2b47d, 0xb5d73fa1, 0x3c59e956, 0x32de22fd, 0xbb50f40a, 0xba657fd6, 0x33eba921, 0x591a29d2, 0xd094ff25, 0xd1a174f9, 0x582fa20e +}, +{ +0x00000000, 0xd7582dd6, 0x306c3464, 0xe73419b2, 0x6fcf48e7, 0xb8976531, 0x5fa37c83, 0x88fb5155, 0xaee5d931, 0x79bdf4e7, 0x9e89ed55, 0x49d1c083, 0xc12a91d6, 0x1672bc00, 0xf146a5b2, 0x261e8864, 0xd33c1943, 0x04643495, 0xe3502d27, 0x340800f1, 0xbcf351a4, 0x6bab7c72, 0x8c9f65c0, 0x5bc74816, 0x7dd9c072, 0xaa81eda4, 0x4db5f416, 0x9aedd9c0, 0x12168895, 0xc54ea543, 0x227abcf1, 0xf5229127, 0x279901b3, 0xf0c12c65, 0x17f535d7, 0xc0ad1801, 0x48564954, 0x9f0e6482, 0x783a7d30, 0xaf6250e6, 0x897cd882, 0x5e24f554, 0xb910ece6, 0x6e48c130, 0xe6b39065, 0x31ebbdb3, 0xd6dfa401, 0x018789d7, 0xf4a518f0, 0x23fd3526, 0xc4c92c94, 0x13910142, 0x9b6a5017, 0x4c327dc1, 0xab066473, 0x7c5e49a5, 0x5a40c1c1, 0x8d18ec17, 0x6a2cf5a5, 0xbd74d873, 0x358f8926, 0xe2d7a4f0, 0x05e3bd42, 0xd2bb9094, 0x22f68778, 0xf5aeaaae, 0x129ab31c, 0xc5c29eca, 0x4d39cf9f, 0x9a61e249, 0x7d55fbfb, 0xaa0dd62d, 0x8c135e49, 0x5b4b739f, 0xbc7f6a2d, 0x6b2747fb, 0xe3dc16ae, 0x34843b78, 0xd3b022ca, 0x04e80f1c, 0xf1ca9e3b, 0x2692b3ed, 0xc1a6aa5f, 0x16fe8789, 0x9e05d6dc, 0x495dfb0a, 0xae69e2b8, 0x7931cf6e, 0x5f2f470a, 0x88776adc, 0x6f43736e, 0xb81b5eb8, 0x30e00fed, 0xe7b8223b, 0x008c3b89, 0xd7d4165f, 0x056f86cb, 0xd237ab1d, 0x3503b2af, 0xe25b9f79, 0x6aa0ce2c, 0xbdf8e3fa, 0x5accfa48, 0x8d94d79e, 0xab8a5ffa, 0x7cd2722c, 0x9be66b9e, 0x4cbe4648, 0xc445171d, 0x131d3acb, 0xf4292379, 0x23710eaf, 0xd6539f88, 0x010bb25e, 0xe63fabec, 0x3167863a, 0xb99cd76f, 0x6ec4fab9, 0x89f0e30b, 0x5ea8cedd, 0x78b646b9, 0xafee6b6f, 0x48da72dd, 0x9f825f0b, 0x17790e5e, 0xc0212388, 0x27153a3a, 0xf04d17ec, 0x3921ff3a, 0xee79d2ec, 0x094dcb5e, 0xde15e688, 0x56eeb7dd, 0x81b69a0b, 0x668283b9, 0xb1daae6f, 0x97c4260b, 0x409c0bdd, 0xa7a8126f, 0x70f03fb9, 0xf80b6eec, 0x2f53433a, 0xc8675a88, 0x1f3f775e, 0xea1de679, 0x3d45cbaf, 0xda71d21d, 0x0d29ffcb, 0x85d2ae9e, 0x528a8348, 0xb5be9afa, 0x62e6b72c, 0x44f83f48, 0x93a0129e, 0x74940b2c, 0xa3cc26fa, 0x2b3777af, 0xfc6f5a79, 0x1b5b43cb, 0xcc036e1d, 0x1eb8fe89, 0xc9e0d35f, 0x2ed4caed, 0xf98ce73b, 0x7177b66e, 0xa62f9bb8, 0x411b820a, 0x9643afdc, 0xb05d27b8, 0x67050a6e, 0x803113dc, 0x57693e0a, 0xdf926f5f, 0x08ca4289, 0xeffe5b3b, 0x38a676ed, 0xcd84e7ca, 0x1adcca1c, 0xfde8d3ae, 0x2ab0fe78, 0xa24baf2d, 0x751382fb, 0x92279b49, 0x457fb69f, 0x63613efb, 0xb439132d, 0x530d0a9f, 0x84552749, 0x0cae761c, 0xdbf65bca, 0x3cc24278, 0xeb9a6fae, 0x1bd77842, 0xcc8f5594, 0x2bbb4c26, 0xfce361f0, 0x741830a5, 0xa3401d73, 0x447404c1, 0x932c2917, 0xb532a173, 0x626a8ca5, 0x855e9517, 0x5206b8c1, 0xdafde994, 0x0da5c442, 0xea91ddf0, 0x3dc9f026, 0xc8eb6101, 0x1fb34cd7, 0xf8875565, 0x2fdf78b3, 0xa72429e6, 0x707c0430, 0x97481d82, 0x40103054, 0x660eb830, 0xb15695e6, 0x56628c54, 0x813aa182, 0x09c1f0d7, 0xde99dd01, 0x39adc4b3, 0xeef5e965, 0x3c4e79f1, 0xeb165427, 0x0c224d95, 0xdb7a6043, 0x53813116, 0x84d91cc0, 0x63ed0572, 0xb4b528a4, 0x92aba0c0, 0x45f38d16, 0xa2c794a4, 0x759fb972, 0xfd64e827, 0x2a3cc5f1, 0xcd08dc43, 0x1a50f195, 0xef7260b2, 0x382a4d64, 0xdf1e54d6, 0x08467900, 0x80bd2855, 0x57e50583, 0xb0d11c31, 0x678931e7, 0x4197b983, 0x96cf9455, 0x71fb8de7, 0xa6a3a031, 0x2e58f164, 0xf900dcb2, 0x1e34c500, 0xc96ce8d6 +}, +{ +0x00000000, 0x5b28b123, 0xd9a8ca47, 0x82807b64, 0xaf2850b8, 0xf400e19b, 0x76809aff, 0x2da82bdc, 0xa2914d9b, 0xf9b9fcb8, 0x7b3987dc, 0x201136ff, 0x0db91d23, 0x5691ac00, 0xd411d764, 0x8f396647, 0x8cbbafb2, 0xd7931e91, 0x551365f5, 0x0e3bd4d6, 0x2393ff0a, 0x78bb4e29, 0xfa3b354d, 0xa113846e, 0x2e2ae229, 0x7502530a, 0xf782286e, 0xacaa994d, 0x8102b291, 0xda2a03b2, 0x58aa78d6, 0x0382c9f5, 0x8863d43c, 0xd34b651f, 0x51cb1e7b, 0x0ae3af58, 0x274b8484, 0x7c6335a7, 0xfee34ec3, 0xa5cbffe0, 0x2af299a7, 0x71da2884, 0xf35a53e0, 0xa872e2c3, 0x85dac91f, 0xdef2783c, 0x5c720358, 0x075ab27b, 0x04d87b8e, 0x5ff0caad, 0xdd70b1c9, 0x865800ea, 0xabf02b36, 0xf0d89a15, 0x7258e171, 0x29705052, 0xa6493615, 0xfd618736, 0x7fe1fc52, 0x24c94d71, 0x096166ad, 0x5249d78e, 0xd0c9acea, 0x8be11dc9, 0xd136f482, 0x8a1e45a1, 0x089e3ec5, 0x53b68fe6, 0x7e1ea43a, 0x25361519, 0xa7b66e7d, 0xfc9edf5e, 0x73a7b919, 0x288f083a, 0xaa0f735e, 0xf127c27d, 0xdc8fe9a1, 0x87a75882, 0x052723e6, 0x5e0f92c5, 0x5d8d5b30, 0x06a5ea13, 0x84259177, 0xdf0d2054, 0xf2a50b88, 0xa98dbaab, 0x2b0dc1cf, 0x702570ec, 0xff1c16ab, 0xa434a788, 0x26b4dcec, 0x7d9c6dcf, 0x50344613, 0x0b1cf730, 0x899c8c54, 0xd2b43d77, 0x595520be, 0x027d919d, 0x80fdeaf9, 0xdbd55bda, 0xf67d7006, 0xad55c125, 0x2fd5ba41, 0x74fd0b62, 0xfbc46d25, 0xa0ecdc06, 0x226ca762, 0x79441641, 0x54ec3d9d, 0x0fc48cbe, 0x8d44f7da, 0xd66c46f9, 0xd5ee8f0c, 0x8ec63e2f, 0x0c46454b, 0x576ef468, 0x7ac6dfb4, 0x21ee6e97, 0xa36e15f3, 0xf846a4d0, 0x777fc297, 0x2c5773b4, 0xaed708d0, 0xf5ffb9f3, 0xd857922f, 0x837f230c, 0x01ff5868, 0x5ad7e94b, 0x597cb4c5, 0x025405e6, 0x80d47e82, 0xdbfccfa1, 0xf654e47d, 0xad7c555e, 0x2ffc2e3a, 0x74d49f19, 0xfbedf95e, 0xa0c5487d, 0x22453319, 0x796d823a, 0x54c5a9e6, 0x0fed18c5, 0x8d6d63a1, 0xd645d282, 0xd5c71b77, 0x8eefaa54, 0x0c6fd130, 0x57476013, 0x7aef4bcf, 0x21c7faec, 0xa3478188, 0xf86f30ab, 0x775656ec, 0x2c7ee7cf, 0xaefe9cab, 0xf5d62d88, 0xd87e0654, 0x8356b777, 0x01d6cc13, 0x5afe7d30, 0xd11f60f9, 0x8a37d1da, 0x08b7aabe, 0x539f1b9d, 0x7e373041, 0x251f8162, 0xa79ffa06, 0xfcb74b25, 0x738e2d62, 0x28a69c41, 0xaa26e725, 0xf10e5606, 0xdca67dda, 0x878eccf9, 0x050eb79d, 0x5e2606be, 0x5da4cf4b, 0x068c7e68, 0x840c050c, 0xdf24b42f, 0xf28c9ff3, 0xa9a42ed0, 0x2b2455b4, 0x700ce497, 0xff3582d0, 0xa41d33f3, 0x269d4897, 0x7db5f9b4, 0x501dd268, 0x0b35634b, 0x89b5182f, 0xd29da90c, 0x884a4047, 0xd362f164, 0x51e28a00, 0x0aca3b23, 0x276210ff, 0x7c4aa1dc, 0xfecadab8, 0xa5e26b9b, 0x2adb0ddc, 0x71f3bcff, 0xf373c79b, 0xa85b76b8, 0x85f35d64, 0xdedbec47, 0x5c5b9723, 0x07732600, 0x04f1eff5, 0x5fd95ed6, 0xdd5925b2, 0x86719491, 0xabd9bf4d, 0xf0f10e6e, 0x7271750a, 0x2959c429, 0xa660a26e, 0xfd48134d, 0x7fc86829, 0x24e0d90a, 0x0948f2d6, 0x526043f5, 0xd0e03891, 0x8bc889b2, 0x0029947b, 0x5b012558, 0xd9815e3c, 0x82a9ef1f, 0xaf01c4c3, 0xf42975e0, 0x76a90e84, 0x2d81bfa7, 0xa2b8d9e0, 0xf99068c3, 0x7b1013a7, 0x2038a284, 0x0d908958, 0x56b8387b, 0xd438431f, 0x8f10f23c, 0x8c923bc9, 0xd7ba8aea, 0x553af18e, 0x0e1240ad, 0x23ba6b71, 0x7892da52, 0xfa12a136, 0xa13a1015, 0x2e037652, 0x752bc771, 0xf7abbc15, 0xac830d36, 0x812b26ea, 0xda0397c9, 0x5883ecad, 0x03ab5d8e +}, +{ +0x00000000, 0x5b001a72, 0xac3f037c, 0xf73f190e, 0x6165c87c, 0x3a65d20e, 0xcd5acb00, 0x965ad172, 0xbee45097, 0xe5e44ae5, 0x12db53eb, 0x49db4999, 0xdf8198eb, 0x84818299, 0x73be9b97, 0x28be81e5, 0xd51c6425, 0x8e1c7e57, 0x79236759, 0x22237d2b, 0xb479ac59, 0xef79b62b, 0x1846af25, 0x4346b557, 0x6bf834b2, 0x30f82ec0, 0xc7c737ce, 0x9cc72dbc, 0x0a9dfcce, 0x519de6bc, 0xa6a2ffb2, 0xfda2e5c0, 0x4620b795, 0x1d20ade7, 0xea1fb4e9, 0xb11fae9b, 0x27457fe9, 0x7c45659b, 0x8b7a7c95, 0xd07a66e7, 0xf8c4e702, 0xa3c4fd70, 0x54fbe47e, 0x0ffbfe0c, 0x99a12f7e, 0xc2a1350c, 0x359e2c02, 0x6e9e3670, 0x933cd3b0, 0xc83cc9c2, 0x3f03d0cc, 0x6403cabe, 0xf2591bcc, 0xa95901be, 0x5e6618b0, 0x056602c2, 0x2dd88327, 0x76d89955, 0x81e7805b, 0xdae79a29, 0x4cbd4b5b, 0x17bd5129, 0xe0824827, 0xbb825255, 0x80142c20, 0xdb143652, 0x2c2b2f5c, 0x772b352e, 0xe171e45c, 0xba71fe2e, 0x4d4ee720, 0x164efd52, 0x3ef07cb7, 0x65f066c5, 0x92cf7fcb, 0xc9cf65b9, 0x5f95b4cb, 0x0495aeb9, 0xf3aab7b7, 0xa8aaadc5, 0x55084805, 0x0e085277, 0xf9374b79, 0xa237510b, 0x346d8079, 0x6f6d9a0b, 0x98528305, 0xc3529977, 0xebec1892, 0xb0ec02e0, 0x47d31bee, 0x1cd3019c, 0x8a89d0ee, 0xd189ca9c, 0x26b6d392, 0x7db6c9e0, 0xc6349bb5, 0x9d3481c7, 0x6a0b98c9, 0x310b82bb, 0xa75153c9, 0xfc5149bb, 0x0b6e50b5, 0x506e4ac7, 0x78d0cb22, 0x23d0d150, 0xd4efc85e, 0x8fefd22c, 0x19b5035e, 0x42b5192c, 0xb58a0022, 0xee8a1a50, 0x1328ff90, 0x4828e5e2, 0xbf17fcec, 0xe417e69e, 0x724d37ec, 0x294d2d9e, 0xde723490, 0x85722ee2, 0xadccaf07, 0xf6ccb575, 0x01f3ac7b, 0x5af3b609, 0xcca9677b, 0x97a97d09, 0x60966407, 0x3b967e75, 0x97e9adef, 0xcce9b79d, 0x3bd6ae93, 0x60d6b4e1, 0xf68c6593, 0xad8c7fe1, 0x5ab366ef, 0x01b37c9d, 0x290dfd78, 0x720de70a, 0x8532fe04, 0xde32e476, 0x48683504, 0x13682f76, 0xe4573678, 0xbf572c0a, 0x42f5c9ca, 0x19f5d3b8, 0xeecacab6, 0xb5cad0c4, 0x239001b6, 0x78901bc4, 0x8faf02ca, 0xd4af18b8, 0xfc11995d, 0xa711832f, 0x502e9a21, 0x0b2e8053, 0x9d745121, 0xc6744b53, 0x314b525d, 0x6a4b482f, 0xd1c91a7a, 0x8ac90008, 0x7df61906, 0x26f60374, 0xb0acd206, 0xebacc874, 0x1c93d17a, 0x4793cb08, 0x6f2d4aed, 0x342d509f, 0xc3124991, 0x981253e3, 0x0e488291, 0x554898e3, 0xa27781ed, 0xf9779b9f, 0x04d57e5f, 0x5fd5642d, 0xa8ea7d23, 0xf3ea6751, 0x65b0b623, 0x3eb0ac51, 0xc98fb55f, 0x928faf2d, 0xba312ec8, 0xe13134ba, 0x160e2db4, 0x4d0e37c6, 0xdb54e6b4, 0x8054fcc6, 0x776be5c8, 0x2c6bffba, 0x17fd81cf, 0x4cfd9bbd, 0xbbc282b3, 0xe0c298c1, 0x769849b3, 0x2d9853c1, 0xdaa74acf, 0x81a750bd, 0xa919d158, 0xf219cb2a, 0x0526d224, 0x5e26c856, 0xc87c1924, 0x937c0356, 0x64431a58, 0x3f43002a, 0xc2e1e5ea, 0x99e1ff98, 0x6edee696, 0x35defce4, 0xa3842d96, 0xf88437e4, 0x0fbb2eea, 0x54bb3498, 0x7c05b57d, 0x2705af0f, 0xd03ab601, 0x8b3aac73, 0x1d607d01, 0x46606773, 0xb15f7e7d, 0xea5f640f, 0x51dd365a, 0x0add2c28, 0xfde23526, 0xa6e22f54, 0x30b8fe26, 0x6bb8e454, 0x9c87fd5a, 0xc787e728, 0xef3966cd, 0xb4397cbf, 0x430665b1, 0x18067fc3, 0x8e5caeb1, 0xd55cb4c3, 0x2263adcd, 0x7963b7bf, 0x84c1527f, 0xdfc1480d, 0x28fe5103, 0x73fe4b71, 0xe5a49a03, 0xbea48071, 0x499b997f, 0x129b830d, 0x3a2502e8, 0x6125189a, 0x961a0194, 0xcd1a1be6, 0x5b40ca94, 0x0040d0e6, 0xf77fc9e8, 0xac7fd39a +}, +{ +0x00000000, 0x38d1f237, 0x930e399f, 0xabdfcba8, 0xafbb1b61, 0x976ae956, 0x3cb522fe, 0x0464d0c9, 0xab457bda, 0x939489ed, 0x384b4245, 0x009ab072, 0x04fe60bb, 0x3c2f928c, 0x97f05924, 0xaf21ab13, 0xac80ff37, 0x94510d00, 0x3f8ec6a8, 0x075f349f, 0x033be456, 0x3bea1661, 0x9035ddc9, 0xa8e42ffe, 0x07c584ed, 0x3f1476da, 0x94cbbd72, 0xac1a4f45, 0xa87e9f8c, 0x90af6dbb, 0x3b70a613, 0x03a15424, 0xca29076e, 0xf2f8f559, 0x59273ef1, 0x61f6ccc6, 0x65921c0f, 0x5d43ee38, 0xf69c2590, 0xce4dd7a7, 0x616c7cb4, 0x59bd8e83, 0xf262452b, 0xcab3b71c, 0xced767d5, 0xf60695e2, 0x5dd95e4a, 0x6508ac7d, 0x66a9f859, 0x5e780a6e, 0xf5a7c1c6, 0xcd7633f1, 0xc912e338, 0xf1c3110f, 0x5a1cdaa7, 0x62cd2890, 0xcdec8383, 0xf53d71b4, 0x5ee2ba1c, 0x6633482b, 0x625798e2, 0x5a866ad5, 0xf159a17d, 0xc988534a, 0x87fecd11, 0xbf2f3f26, 0x14f0f48e, 0x2c2106b9, 0x2845d670, 0x10942447, 0xbb4befef, 0x839a1dd8, 0x2cbbb6cb, 0x146a44fc, 0xbfb58f54, 0x87647d63, 0x8300adaa, 0xbbd15f9d, 0x100e9435, 0x28df6602, 0x2b7e3226, 0x13afc011, 0xb8700bb9, 0x80a1f98e, 0x84c52947, 0xbc14db70, 0x17cb10d8, 0x2f1ae2ef, 0x803b49fc, 0xb8eabbcb, 0x13357063, 0x2be48254, 0x2f80529d, 0x1751a0aa, 0xbc8e6b02, 0x845f9935, 0x4dd7ca7f, 0x75063848, 0xded9f3e0, 0xe60801d7, 0xe26cd11e, 0xdabd2329, 0x7162e881, 0x49b31ab6, 0xe692b1a5, 0xde434392, 0x759c883a, 0x4d4d7a0d, 0x4929aac4, 0x71f858f3, 0xda27935b, 0xe2f6616c, 0xe1573548, 0xd986c77f, 0x72590cd7, 0x4a88fee0, 0x4eec2e29, 0x763ddc1e, 0xdde217b6, 0xe533e581, 0x4a124e92, 0x72c3bca5, 0xd91c770d, 0xe1cd853a, 0xe5a955f3, 0xdd78a7c4, 0x76a76c6c, 0x4e769e5b, 0xaf9ff511, 0x974e0726, 0x3c91cc8e, 0x04403eb9, 0x0024ee70, 0x38f51c47, 0x932ad7ef, 0xabfb25d8, 0x04da8ecb, 0x3c0b7cfc, 0x97d4b754, 0xaf054563, 0xab6195aa, 0x93b0679d, 0x386fac35, 0x00be5e02, 0x031f0a26, 0x3bcef811, 0x901133b9, 0xa8c0c18e, 0xaca41147, 0x9475e370, 0x3faa28d8, 0x077bdaef, 0xa85a71fc, 0x908b83cb, 0x3b544863, 0x0385ba54, 0x07e16a9d, 0x3f3098aa, 0x94ef5302, 0xac3ea135, 0x65b6f27f, 0x5d670048, 0xf6b8cbe0, 0xce6939d7, 0xca0de91e, 0xf2dc1b29, 0x5903d081, 0x61d222b6, 0xcef389a5, 0xf6227b92, 0x5dfdb03a, 0x652c420d, 0x614892c4, 0x599960f3, 0xf246ab5b, 0xca97596c, 0xc9360d48, 0xf1e7ff7f, 0x5a3834d7, 0x62e9c6e0, 0x668d1629, 0x5e5ce41e, 0xf5832fb6, 0xcd52dd81, 0x62737692, 0x5aa284a5, 0xf17d4f0d, 0xc9acbd3a, 0xcdc86df3, 0xf5199fc4, 0x5ec6546c, 0x6617a65b, 0x28613800, 0x10b0ca37, 0xbb6f019f, 0x83bef3a8, 0x87da2361, 0xbf0bd156, 0x14d41afe, 0x2c05e8c9, 0x832443da, 0xbbf5b1ed, 0x102a7a45, 0x28fb8872, 0x2c9f58bb, 0x144eaa8c, 0xbf916124, 0x87409313, 0x84e1c737, 0xbc303500, 0x17effea8, 0x2f3e0c9f, 0x2b5adc56, 0x138b2e61, 0xb854e5c9, 0x808517fe, 0x2fa4bced, 0x17754eda, 0xbcaa8572, 0x847b7745, 0x801fa78c, 0xb8ce55bb, 0x13119e13, 0x2bc06c24, 0xe2483f6e, 0xda99cd59, 0x714606f1, 0x4997f4c6, 0x4df3240f, 0x7522d638, 0xdefd1d90, 0xe62cefa7, 0x490d44b4, 0x71dcb683, 0xda037d2b, 0xe2d28f1c, 0xe6b65fd5, 0xde67ade2, 0x75b8664a, 0x4d69947d, 0x4ec8c059, 0x7619326e, 0xddc6f9c6, 0xe5170bf1, 0xe173db38, 0xd9a2290f, 0x727de2a7, 0x4aac1090, 0xe58dbb83, 0xdd5c49b4, 0x7683821c, 0x4e52702b, 0x4a36a0e2, 0x72e752d5, 0xd938997d, 0xe1e96b4a +}, +{ +0x00000000, 0xb054dab9, 0x34eaa8db, 0x84be7262, 0xd06cce42, 0x603814fb, 0xe4866699, 0x54d2bc20, 0xe594e55b, 0x55c03fe2, 0xd17e4d80, 0x612a9739, 0x35f82b19, 0x85acf1a0, 0x011283c2, 0xb146597b, 0xd53672b7, 0x6562a80e, 0xe1dcda6c, 0x518800d5, 0x055abcf5, 0xb50e664c, 0x31b0142e, 0x81e4ce97, 0x30a297ec, 0x80f64d55, 0x04483f37, 0xb41ce58e, 0xe0ce59ae, 0x509a8317, 0xd424f175, 0x64702bcc, 0xea44fd74, 0x5a1027cd, 0xdeae55af, 0x6efa8f16, 0x3a283336, 0x8a7ce98f, 0x0ec29bed, 0xbe964154, 0x0fd0182f, 0xbf84c296, 0x3b3ab0f4, 0x8b6e6a4d, 0xdfbcd66d, 0x6fe80cd4, 0xeb567eb6, 0x5b02a40f, 0x3f728fc3, 0x8f26557a, 0x0b982718, 0xbbccfda1, 0xef1e4181, 0x5f4a9b38, 0xdbf4e95a, 0x6ba033e3, 0xdae66a98, 0x6ab2b021, 0xee0cc243, 0x5e5818fa, 0x0a8aa4da, 0xbade7e63, 0x3e600c01, 0x8e34d6b8, 0xfb5984b8, 0x4b0d5e01, 0xcfb32c63, 0x7fe7f6da, 0x2b354afa, 0x9b619043, 0x1fdfe221, 0xaf8b3898, 0x1ecd61e3, 0xae99bb5a, 0x2a27c938, 0x9a731381, 0xcea1afa1, 0x7ef57518, 0xfa4b077a, 0x4a1fddc3, 0x2e6ff60f, 0x9e3b2cb6, 0x1a855ed4, 0xaad1846d, 0xfe03384d, 0x4e57e2f4, 0xcae99096, 0x7abd4a2f, 0xcbfb1354, 0x7bafc9ed, 0xff11bb8f, 0x4f456136, 0x1b97dd16, 0xabc307af, 0x2f7d75cd, 0x9f29af74, 0x111d79cc, 0xa149a375, 0x25f7d117, 0x95a30bae, 0xc171b78e, 0x71256d37, 0xf59b1f55, 0x45cfc5ec, 0xf4899c97, 0x44dd462e, 0xc063344c, 0x7037eef5, 0x24e552d5, 0x94b1886c, 0x100ffa0e, 0xa05b20b7, 0xc42b0b7b, 0x747fd1c2, 0xf0c1a3a0, 0x40957919, 0x1447c539, 0xa4131f80, 0x20ad6de2, 0x90f9b75b, 0x21bfee20, 0x91eb3499, 0x155546fb, 0xa5019c42, 0xf1d32062, 0x4187fadb, 0xc53988b9, 0x756d5200, 0x314e77f2, 0x811aad4b, 0x05a4df29, 0xb5f00590, 0xe122b9b0, 0x51766309, 0xd5c8116b, 0x659ccbd2, 0xd4da92a9, 0x648e4810, 0xe0303a72, 0x5064e0cb, 0x04b65ceb, 0xb4e28652, 0x305cf430, 0x80082e89, 0xe4780545, 0x542cdffc, 0xd092ad9e, 0x60c67727, 0x3414cb07, 0x844011be, 0x00fe63dc, 0xb0aab965, 0x01ece01e, 0xb1b83aa7, 0x350648c5, 0x8552927c, 0xd1802e5c, 0x61d4f4e5, 0xe56a8687, 0x553e5c3e, 0xdb0a8a86, 0x6b5e503f, 0xefe0225d, 0x5fb4f8e4, 0x0b6644c4, 0xbb329e7d, 0x3f8cec1f, 0x8fd836a6, 0x3e9e6fdd, 0x8ecab564, 0x0a74c706, 0xba201dbf, 0xeef2a19f, 0x5ea67b26, 0xda180944, 0x6a4cd3fd, 0x0e3cf831, 0xbe682288, 0x3ad650ea, 0x8a828a53, 0xde503673, 0x6e04ecca, 0xeaba9ea8, 0x5aee4411, 0xeba81d6a, 0x5bfcc7d3, 0xdf42b5b1, 0x6f166f08, 0x3bc4d328, 0x8b900991, 0x0f2e7bf3, 0xbf7aa14a, 0xca17f34a, 0x7a4329f3, 0xfefd5b91, 0x4ea98128, 0x1a7b3d08, 0xaa2fe7b1, 0x2e9195d3, 0x9ec54f6a, 0x2f831611, 0x9fd7cca8, 0x1b69beca, 0xab3d6473, 0xffefd853, 0x4fbb02ea, 0xcb057088, 0x7b51aa31, 0x1f2181fd, 0xaf755b44, 0x2bcb2926, 0x9b9ff39f, 0xcf4d4fbf, 0x7f199506, 0xfba7e764, 0x4bf33ddd, 0xfab564a6, 0x4ae1be1f, 0xce5fcc7d, 0x7e0b16c4, 0x2ad9aae4, 0x9a8d705d, 0x1e33023f, 0xae67d886, 0x20530e3e, 0x9007d487, 0x14b9a6e5, 0xa4ed7c5c, 0xf03fc07c, 0x406b1ac5, 0xc4d568a7, 0x7481b21e, 0xc5c7eb65, 0x759331dc, 0xf12d43be, 0x41799907, 0x15ab2527, 0xa5ffff9e, 0x21418dfc, 0x91155745, 0xf5657c89, 0x4531a630, 0xc18fd452, 0x71db0eeb, 0x2509b2cb, 0x955d6872, 0x11e31a10, 0xa1b7c0a9, 0x10f199d2, 0xa0a5436b, 0x241b3109, 0x944febb0, 0xc09d5790, 0x70c98d29, 0xf477ff4b, 0x442325f2 +}, +{ +0x00000000, 0x187deff2, 0x79dc4487, 0x61a1ab75, 0x34ff6457, 0x2c828ba5, 0x4d2320d0, 0x555ecf22, 0xaf4e7090, 0xb7339f62, 0xd6923417, 0xceefdbe5, 0x9bb114c7, 0x83ccfb35, 0xe26d5040, 0xfa10bfb2, 0x18e34610, 0x009ea9e2, 0x613f0297, 0x7942ed65, 0x2c1c2247, 0x3461cdb5, 0x55c066c0, 0x4dbd8932, 0xb7ad3680, 0xafd0d972, 0xce717207, 0xd60c9df5, 0x835252d7, 0x9b2fbd25, 0xfa8e1650, 0xe2f3f9a2, 0x1c5161f2, 0x042c8e00, 0x658d2575, 0x7df0ca87, 0x28ae05a5, 0x30d3ea57, 0x51724122, 0x490faed0, 0xb31f1162, 0xab62fe90, 0xcac355e5, 0xd2beba17, 0x87e07535, 0x9f9d9ac7, 0xfe3c31b2, 0xe641de40, 0x04b227e2, 0x1ccfc810, 0x7d6e6365, 0x65138c97, 0x304d43b5, 0x2830ac47, 0x49910732, 0x51ece8c0, 0xabfc5772, 0xb381b880, 0xd22013f5, 0xca5dfc07, 0x9f033325, 0x877edcd7, 0xe6df77a2, 0xfea29850, 0x1ad9e6b8, 0x02a4094a, 0x6305a23f, 0x7b784dcd, 0x2e2682ef, 0x365b6d1d, 0x57fac668, 0x4f87299a, 0xb5979628, 0xadea79da, 0xcc4bd2af, 0xd4363d5d, 0x8168f27f, 0x99151d8d, 0xf8b4b6f8, 0xe0c9590a, 0x023aa0a8, 0x1a474f5a, 0x7be6e42f, 0x639b0bdd, 0x36c5c4ff, 0x2eb82b0d, 0x4f198078, 0x57646f8a, 0xad74d038, 0xb5093fca, 0xd4a894bf, 0xccd57b4d, 0x998bb46f, 0x81f65b9d, 0xe057f0e8, 0xf82a1f1a, 0x0688874a, 0x1ef568b8, 0x7f54c3cd, 0x67292c3f, 0x3277e31d, 0x2a0a0cef, 0x4baba79a, 0x53d64868, 0xa9c6f7da, 0xb1bb1828, 0xd01ab35d, 0xc8675caf, 0x9d39938d, 0x85447c7f, 0xe4e5d70a, 0xfc9838f8, 0x1e6bc15a, 0x06162ea8, 0x67b785dd, 0x7fca6a2f, 0x2a94a50d, 0x32e94aff, 0x5348e18a, 0x4b350e78, 0xb125b1ca, 0xa9585e38, 0xc8f9f54d, 0xd0841abf, 0x85dad59d, 0x9da73a6f, 0xfc06911a, 0xe47b7ee8, 0xa89ed2a9, 0xb0e33d5b, 0xd142962e, 0xc93f79dc, 0x9c61b6fe, 0x841c590c, 0xe5bdf279, 0xfdc01d8b, 0x07d0a239, 0x1fad4dcb, 0x7e0ce6be, 0x6671094c, 0x332fc66e, 0x2b52299c, 0x4af382e9, 0x528e6d1b, 0xb07d94b9, 0xa8007b4b, 0xc9a1d03e, 0xd1dc3fcc, 0x8482f0ee, 0x9cff1f1c, 0xfd5eb469, 0xe5235b9b, 0x1f33e429, 0x074e0bdb, 0x66efa0ae, 0x7e924f5c, 0x2bcc807e, 0x33b16f8c, 0x5210c4f9, 0x4a6d2b0b, 0xb4cfb35b, 0xacb25ca9, 0xcd13f7dc, 0xd56e182e, 0x8030d70c, 0x984d38fe, 0xf9ec938b, 0xe1917c79, 0x1b81c3cb, 0x03fc2c39, 0x625d874c, 0x7a2068be, 0x2f7ea79c, 0x3703486e, 0x56a2e31b, 0x4edf0ce9, 0xac2cf54b, 0xb4511ab9, 0xd5f0b1cc, 0xcd8d5e3e, 0x98d3911c, 0x80ae7eee, 0xe10fd59b, 0xf9723a69, 0x036285db, 0x1b1f6a29, 0x7abec15c, 0x62c32eae, 0x379de18c, 0x2fe00e7e, 0x4e41a50b, 0x563c4af9, 0xb2473411, 0xaa3adbe3, 0xcb9b7096, 0xd3e69f64, 0x86b85046, 0x9ec5bfb4, 0xff6414c1, 0xe719fb33, 0x1d094481, 0x0574ab73, 0x64d50006, 0x7ca8eff4, 0x29f620d6, 0x318bcf24, 0x502a6451, 0x48578ba3, 0xaaa47201, 0xb2d99df3, 0xd3783686, 0xcb05d974, 0x9e5b1656, 0x8626f9a4, 0xe78752d1, 0xfffabd23, 0x05ea0291, 0x1d97ed63, 0x7c364616, 0x644ba9e4, 0x311566c6, 0x29688934, 0x48c92241, 0x50b4cdb3, 0xae1655e3, 0xb66bba11, 0xd7ca1164, 0xcfb7fe96, 0x9ae931b4, 0x8294de46, 0xe3357533, 0xfb489ac1, 0x01582573, 0x1925ca81, 0x788461f4, 0x60f98e06, 0x35a74124, 0x2ddaaed6, 0x4c7b05a3, 0x5406ea51, 0xb6f513f3, 0xae88fc01, 0xcf295774, 0xd754b886, 0x820a77a4, 0x9a779856, 0xfbd63323, 0xe3abdcd1, 0x19bb6363, 0x01c68c91, 0x606727e4, 0x781ac816, 0x2d440734, 0x3539e8c6, 0x549843b3, 0x4ce5ac41 +}, +{ +0x00000000, 0xb904b6c2, 0x80bcb715, 0x39b801d7, 0xb7f532ee, 0x0ef1842c, 0x374985fb, 0x8e4d3339, 0x7d0cb6d2, 0xc4080010, 0xfdb001c7, 0x44b4b705, 0xcaf9843c, 0x73fd32fe, 0x4a453329, 0xf34185eb, 0xae4833b1, 0x174c8573, 0x2ef484a4, 0x97f03266, 0x19bd015f, 0xa0b9b79d, 0x9901b64a, 0x20050088, 0xd3448563, 0x6a4033a1, 0x53f83276, 0xeafc84b4, 0x64b1b78d, 0xddb5014f, 0xe40d0098, 0x5d09b65a, 0x2aa6536a, 0x93a2e5a8, 0xaa1ae47f, 0x131e52bd, 0x9d536184, 0x2457d746, 0x1defd691, 0xa4eb6053, 0x57aae5b8, 0xeeae537a, 0xd71652ad, 0x6e12e46f, 0xe05fd756, 0x595b6194, 0x60e36043, 0xd9e7d681, 0x84ee60db, 0x3dead619, 0x0452d7ce, 0xbd56610c, 0x331b5235, 0x8a1fe4f7, 0xb3a7e520, 0x0aa353e2, 0xf9e2d609, 0x40e660cb, 0x795e611c, 0xc05ad7de, 0x4e17e4e7, 0xf7135225, 0xceab53f2, 0x77afe530, 0x5141c733, 0xe84571f1, 0xd1fd7026, 0x68f9c6e4, 0xe6b4f5dd, 0x5fb0431f, 0x660842c8, 0xdf0cf40a, 0x2c4d71e1, 0x9549c723, 0xacf1c6f4, 0x15f57036, 0x9bb8430f, 0x22bcf5cd, 0x1b04f41a, 0xa20042d8, 0xff09f482, 0x460d4240, 0x7fb54397, 0xc6b1f555, 0x48fcc66c, 0xf1f870ae, 0xc8407179, 0x7144c7bb, 0x82054250, 0x3b01f492, 0x02b9f545, 0xbbbd4387, 0x35f070be, 0x8cf4c67c, 0xb54cc7ab, 0x0c487169, 0x7be79459, 0xc2e3229b, 0xfb5b234c, 0x425f958e, 0xcc12a6b7, 0x75161075, 0x4cae11a2, 0xf5aaa760, 0x06eb228b, 0xbfef9449, 0x8657959e, 0x3f53235c, 0xb11e1065, 0x081aa6a7, 0x31a2a770, 0x88a611b2, 0xd5afa7e8, 0x6cab112a, 0x551310fd, 0xec17a63f, 0x625a9506, 0xdb5e23c4, 0xe2e62213, 0x5be294d1, 0xa8a3113a, 0x11a7a7f8, 0x281fa62f, 0x911b10ed, 0x1f5623d4, 0xa6529516, 0x9fea94c1, 0x26ee2203, 0xcb4920b2, 0x724d9670, 0x4bf597a7, 0xf2f12165, 0x7cbc125c, 0xc5b8a49e, 0xfc00a549, 0x4504138b, 0xb6459660, 0x0f4120a2, 0x36f92175, 0x8ffd97b7, 0x01b0a48e, 0xb8b4124c, 0x810c139b, 0x3808a559, 0x65011303, 0xdc05a5c1, 0xe5bda416, 0x5cb912d4, 0xd2f421ed, 0x6bf0972f, 0x524896f8, 0xeb4c203a, 0x180da5d1, 0xa1091313, 0x98b112c4, 0x21b5a406, 0xaff8973f, 0x16fc21fd, 0x2f44202a, 0x964096e8, 0xe1ef73d8, 0x58ebc51a, 0x6153c4cd, 0xd857720f, 0x561a4136, 0xef1ef7f4, 0xd6a6f623, 0x6fa240e1, 0x9ce3c50a, 0x25e773c8, 0x1c5f721f, 0xa55bc4dd, 0x2b16f7e4, 0x92124126, 0xabaa40f1, 0x12aef633, 0x4fa74069, 0xf6a3f6ab, 0xcf1bf77c, 0x761f41be, 0xf8527287, 0x4156c445, 0x78eec592, 0xc1ea7350, 0x32abf6bb, 0x8baf4079, 0xb21741ae, 0x0b13f76c, 0x855ec455, 0x3c5a7297, 0x05e27340, 0xbce6c582, 0x9a08e781, 0x230c5143, 0x1ab45094, 0xa3b0e656, 0x2dfdd56f, 0x94f963ad, 0xad41627a, 0x1445d4b8, 0xe7045153, 0x5e00e791, 0x67b8e646, 0xdebc5084, 0x50f163bd, 0xe9f5d57f, 0xd04dd4a8, 0x6949626a, 0x3440d430, 0x8d4462f2, 0xb4fc6325, 0x0df8d5e7, 0x83b5e6de, 0x3ab1501c, 0x030951cb, 0xba0de709, 0x494c62e2, 0xf048d420, 0xc9f0d5f7, 0x70f46335, 0xfeb9500c, 0x47bde6ce, 0x7e05e719, 0xc70151db, 0xb0aeb4eb, 0x09aa0229, 0x301203fe, 0x8916b53c, 0x075b8605, 0xbe5f30c7, 0x87e73110, 0x3ee387d2, 0xcda20239, 0x74a6b4fb, 0x4d1eb52c, 0xf41a03ee, 0x7a5730d7, 0xc3538615, 0xfaeb87c2, 0x43ef3100, 0x1ee6875a, 0xa7e23198, 0x9e5a304f, 0x275e868d, 0xa913b5b4, 0x10170376, 0x29af02a1, 0x90abb463, 0x63ea3188, 0xdaee874a, 0xe356869d, 0x5a52305f, 0xd41f0366, 0x6d1bb5a4, 0x54a3b473, 0xeda702b1 +}, +{ +0x00000000, 0xe2e25123, 0x1ea37996, 0xfc4128b5, 0x01efeeee, 0xe30dbfcd, 0x1f4c9778, 0xfdaec65b, 0x13c89b28, 0xf12aca0b, 0x0d6be2be, 0xef89b39d, 0x122775c6, 0xf0c524e5, 0x0c840c50, 0xee665d73, 0xd6e92286, 0x340b73a5, 0xc84a5b10, 0x2aa80a33, 0xd706cc68, 0x35e49d4b, 0xc9a5b5fe, 0x2b47e4dd, 0xc521b9ae, 0x27c3e88d, 0xdb82c038, 0x3960911b, 0xc4ce5740, 0x262c0663, 0xda6d2ed6, 0x388f7ff5, 0xf46ac8d5, 0x168899f6, 0xeac9b143, 0x082be060, 0xf585263b, 0x17677718, 0xeb265fad, 0x09c40e8e, 0xe7a253fd, 0x054002de, 0xf9012a6b, 0x1be37b48, 0xe64dbd13, 0x04afec30, 0xf8eec485, 0x1a0c95a6, 0x2283ea53, 0xc061bb70, 0x3c2093c5, 0xdec2c2e6, 0x236c04bd, 0xc18e559e, 0x3dcf7d2b, 0xdf2d2c08, 0x314b717b, 0xd3a92058, 0x2fe808ed, 0xcd0a59ce, 0x30a49f95, 0xd246ceb6, 0x2e07e603, 0xcce5b720, 0x922fa2a8, 0x70cdf38b, 0x8c8cdb3e, 0x6e6e8a1d, 0x93c04c46, 0x71221d65, 0x8d6335d0, 0x6f8164f3, 0x81e73980, 0x630568a3, 0x9f444016, 0x7da61135, 0x8008d76e, 0x62ea864d, 0x9eabaef8, 0x7c49ffdb, 0x44c6802e, 0xa624d10d, 0x5a65f9b8, 0xb887a89b, 0x45296ec0, 0xa7cb3fe3, 0x5b8a1756, 0xb9684675, 0x570e1b06, 0xb5ec4a25, 0x49ad6290, 0xab4f33b3, 0x56e1f5e8, 0xb403a4cb, 0x48428c7e, 0xaaa0dd5d, 0x66456a7d, 0x84a73b5e, 0x78e613eb, 0x9a0442c8, 0x67aa8493, 0x8548d5b0, 0x7909fd05, 0x9bebac26, 0x758df155, 0x976fa076, 0x6b2e88c3, 0x89ccd9e0, 0x74621fbb, 0x96804e98, 0x6ac1662d, 0x8823370e, 0xb0ac48fb, 0x524e19d8, 0xae0f316d, 0x4ced604e, 0xb143a615, 0x53a1f736, 0xafe0df83, 0x4d028ea0, 0xa364d3d3, 0x418682f0, 0xbdc7aa45, 0x5f25fb66, 0xa28b3d3d, 0x40696c1e, 0xbc2844ab, 0x5eca1588, 0xfb94f4b7, 0x1976a594, 0xe5378d21, 0x07d5dc02, 0xfa7b1a59, 0x18994b7a, 0xe4d863cf, 0x063a32ec, 0xe85c6f9f, 0x0abe3ebc, 0xf6ff1609, 0x141d472a, 0xe9b38171, 0x0b51d052, 0xf710f8e7, 0x15f2a9c4, 0x2d7dd631, 0xcf9f8712, 0x33deafa7, 0xd13cfe84, 0x2c9238df, 0xce7069fc, 0x32314149, 0xd0d3106a, 0x3eb54d19, 0xdc571c3a, 0x2016348f, 0xc2f465ac, 0x3f5aa3f7, 0xddb8f2d4, 0x21f9da61, 0xc31b8b42, 0x0ffe3c62, 0xed1c6d41, 0x115d45f4, 0xf3bf14d7, 0x0e11d28c, 0xecf383af, 0x10b2ab1a, 0xf250fa39, 0x1c36a74a, 0xfed4f669, 0x0295dedc, 0xe0778fff, 0x1dd949a4, 0xff3b1887, 0x037a3032, 0xe1986111, 0xd9171ee4, 0x3bf54fc7, 0xc7b46772, 0x25563651, 0xd8f8f00a, 0x3a1aa129, 0xc65b899c, 0x24b9d8bf, 0xcadf85cc, 0x283dd4ef, 0xd47cfc5a, 0x369ead79, 0xcb306b22, 0x29d23a01, 0xd59312b4, 0x37714397, 0x69bb561f, 0x8b59073c, 0x77182f89, 0x95fa7eaa, 0x6854b8f1, 0x8ab6e9d2, 0x76f7c167, 0x94159044, 0x7a73cd37, 0x98919c14, 0x64d0b4a1, 0x8632e582, 0x7b9c23d9, 0x997e72fa, 0x653f5a4f, 0x87dd0b6c, 0xbf527499, 0x5db025ba, 0xa1f10d0f, 0x43135c2c, 0xbebd9a77, 0x5c5fcb54, 0xa01ee3e1, 0x42fcb2c2, 0xac9aefb1, 0x4e78be92, 0xb2399627, 0x50dbc704, 0xad75015f, 0x4f97507c, 0xb3d678c9, 0x513429ea, 0x9dd19eca, 0x7f33cfe9, 0x8372e75c, 0x6190b67f, 0x9c3e7024, 0x7edc2107, 0x829d09b2, 0x607f5891, 0x8e1905e2, 0x6cfb54c1, 0x90ba7c74, 0x72582d57, 0x8ff6eb0c, 0x6d14ba2f, 0x9155929a, 0x73b7c3b9, 0x4b38bc4c, 0xa9daed6f, 0x559bc5da, 0xb77994f9, 0x4ad752a2, 0xa8350381, 0x54742b34, 0xb6967a17, 0x58f02764, 0xba127647, 0x46535ef2, 0xa4b10fd1, 0x591fc98a, 0xbbfd98a9, 0x47bcb01c, 0xa55ee13f +}, +{ +0x00000000, 0xf396e861, 0x764a34b4, 0x85dcdcd5, 0x710e61d8, 0x829889b9, 0x0744556c, 0xf4d2bd0d, 0xa45cecee, 0x57ca048f, 0xd216d85a, 0x2180303b, 0xd5528d36, 0x26c46557, 0xa318b982, 0x508e51e3, 0x1edb048c, 0xed4deced, 0x68913038, 0x9b07d859, 0x6fd56554, 0x9c438d35, 0x199f51e0, 0xea09b981, 0xba87e862, 0x49110003, 0xcccddcd6, 0x3f5b34b7, 0xcb8989ba, 0x381f61db, 0xbdc3bd0e, 0x4e55556f, 0x5f887c17, 0xac1e9476, 0x29c248a3, 0xda54a0c2, 0x2e861dcf, 0xdd10f5ae, 0x58cc297b, 0xab5ac11a, 0xfbd490f9, 0x08427898, 0x8d9ea44d, 0x7e084c2c, 0x8adaf121, 0x794c1940, 0xfc90c595, 0x0f062df4, 0x4153789b, 0xb2c590fa, 0x37194c2f, 0xc48fa44e, 0x305d1943, 0xc3cbf122, 0x46172df7, 0xb581c596, 0xe50f9475, 0x16997c14, 0x9345a0c1, 0x60d348a0, 0x9401f5ad, 0x67971dcc, 0xe24bc119, 0x11dd2978, 0x77a7ff9a, 0x843117fb, 0x01edcb2e, 0xf27b234f, 0x06a99e42, 0xf53f7623, 0x70e3aaf6, 0x83754297, 0xd3fb1374, 0x206dfb15, 0xa5b127c0, 0x5627cfa1, 0xa2f572ac, 0x51639acd, 0xd4bf4618, 0x2729ae79, 0x697cfb16, 0x9aea1377, 0x1f36cfa2, 0xeca027c3, 0x18729ace, 0xebe472af, 0x6e38ae7a, 0x9dae461b, 0xcd2017f8, 0x3eb6ff99, 0xbb6a234c, 0x48fccb2d, 0xbc2e7620, 0x4fb89e41, 0xca644294, 0x39f2aaf5, 0x282f838d, 0xdbb96bec, 0x5e65b739, 0xadf35f58, 0x5921e255, 0xaab70a34, 0x2f6bd6e1, 0xdcfd3e80, 0x8c736f63, 0x7fe58702, 0xfa395bd7, 0x09afb3b6, 0xfd7d0ebb, 0x0eebe6da, 0x8b373a0f, 0x78a1d26e, 0x36f48701, 0xc5626f60, 0x40beb3b5, 0xb3285bd4, 0x47fae6d9, 0xb46c0eb8, 0x31b0d26d, 0xc2263a0c, 0x92a86bef, 0x613e838e, 0xe4e25f5b, 0x1774b73a, 0xe3a60a37, 0x1030e256, 0x95ec3e83, 0x667ad6e2, 0x339b9daa, 0xc00d75cb, 0x45d1a91e, 0xb647417f, 0x4295fc72, 0xb1031413, 0x34dfc8c6, 0xc74920a7, 0x97c77144, 0x64519925, 0xe18d45f0, 0x121bad91, 0xe6c9109c, 0x155ff8fd, 0x90832428, 0x6315cc49, 0x2d409926, 0xded67147, 0x5b0aad92, 0xa89c45f3, 0x5c4ef8fe, 0xafd8109f, 0x2a04cc4a, 0xd992242b, 0x891c75c8, 0x7a8a9da9, 0xff56417c, 0x0cc0a91d, 0xf8121410, 0x0b84fc71, 0x8e5820a4, 0x7dcec8c5, 0x6c13e1bd, 0x9f8509dc, 0x1a59d509, 0xe9cf3d68, 0x1d1d8065, 0xee8b6804, 0x6b57b4d1, 0x98c15cb0, 0xc84f0d53, 0x3bd9e532, 0xbe0539e7, 0x4d93d186, 0xb9416c8b, 0x4ad784ea, 0xcf0b583f, 0x3c9db05e, 0x72c8e531, 0x815e0d50, 0x0482d185, 0xf71439e4, 0x03c684e9, 0xf0506c88, 0x758cb05d, 0x861a583c, 0xd69409df, 0x2502e1be, 0xa0de3d6b, 0x5348d50a, 0xa79a6807, 0x540c8066, 0xd1d05cb3, 0x2246b4d2, 0x443c6230, 0xb7aa8a51, 0x32765684, 0xc1e0bee5, 0x353203e8, 0xc6a4eb89, 0x4378375c, 0xb0eedf3d, 0xe0608ede, 0x13f666bf, 0x962aba6a, 0x65bc520b, 0x916eef06, 0x62f80767, 0xe724dbb2, 0x14b233d3, 0x5ae766bc, 0xa9718edd, 0x2cad5208, 0xdf3bba69, 0x2be90764, 0xd87fef05, 0x5da333d0, 0xae35dbb1, 0xfebb8a52, 0x0d2d6233, 0x88f1bee6, 0x7b675687, 0x8fb5eb8a, 0x7c2303eb, 0xf9ffdf3e, 0x0a69375f, 0x1bb41e27, 0xe822f646, 0x6dfe2a93, 0x9e68c2f2, 0x6aba7fff, 0x992c979e, 0x1cf04b4b, 0xef66a32a, 0xbfe8f2c9, 0x4c7e1aa8, 0xc9a2c67d, 0x3a342e1c, 0xcee69311, 0x3d707b70, 0xb8aca7a5, 0x4b3a4fc4, 0x056f1aab, 0xf6f9f2ca, 0x73252e1f, 0x80b3c67e, 0x74617b73, 0x87f79312, 0x022b4fc7, 0xf1bda7a6, 0xa133f645, 0x52a51e24, 0xd779c2f1, 0x24ef2a90, 0xd03d979d, 0x23ab7ffc, 0xa677a329, 0x55e14b48 +}, +{ +0x00000000, 0x88ed38ab, 0xe3ed354e, 0x6b000de5, 0x105952d2, 0x98b46a79, 0xf3b4679c, 0x7b595f37, 0xe75208ef, 0x6fbf3044, 0x04bf3da1, 0x8c52050a, 0xf70b5a3d, 0x7fe66296, 0x14e66f73, 0x9c0b57d8, 0x947053ee, 0x1c9d6b45, 0x779d66a0, 0xff705e0b, 0x8429013c, 0x0cc43997, 0x67c43472, 0xef290cd9, 0x73225b01, 0xfbcf63aa, 0x90cf6e4f, 0x182256e4, 0x637b09d3, 0xeb963178, 0x80963c9d, 0x087b0436, 0x3d86998d, 0xb56ba126, 0xde6bacc3, 0x56869468, 0x2ddfcb5f, 0xa532f3f4, 0xce32fe11, 0x46dfc6ba, 0xdad49162, 0x5239a9c9, 0x3939a42c, 0xb1d49c87, 0xca8dc3b0, 0x4260fb1b, 0x2960f6fe, 0xa18dce55, 0xa9f6ca63, 0x211bf2c8, 0x4a1bff2d, 0xc2f6c786, 0xb9af98b1, 0x3142a01a, 0x5a42adff, 0xd2af9554, 0x4ea4c28c, 0xc649fa27, 0xad49f7c2, 0x25a4cf69, 0x5efd905e, 0xd610a8f5, 0xbd10a510, 0x35fd9dbb, 0x1f301062, 0x97dd28c9, 0xfcdd252c, 0x74301d87, 0x0f6942b0, 0x87847a1b, 0xec8477fe, 0x64694f55, 0xf862188d, 0x708f2026, 0x1b8f2dc3, 0x93621568, 0xe83b4a5f, 0x60d672f4, 0x0bd67f11, 0x833b47ba, 0x8b40438c, 0x03ad7b27, 0x68ad76c2, 0xe0404e69, 0x9b19115e, 0x13f429f5, 0x78f42410, 0xf0191cbb, 0x6c124b63, 0xe4ff73c8, 0x8fff7e2d, 0x07124686, 0x7c4b19b1, 0xf4a6211a, 0x9fa62cff, 0x174b1454, 0x22b689ef, 0xaa5bb144, 0xc15bbca1, 0x49b6840a, 0x32efdb3d, 0xba02e396, 0xd102ee73, 0x59efd6d8, 0xc5e48100, 0x4d09b9ab, 0x2609b44e, 0xaee48ce5, 0xd5bdd3d2, 0x5d50eb79, 0x3650e69c, 0xbebdde37, 0xb6c6da01, 0x3e2be2aa, 0x552bef4f, 0xddc6d7e4, 0xa69f88d3, 0x2e72b078, 0x4572bd9d, 0xcd9f8536, 0x5194d2ee, 0xd979ea45, 0xb279e7a0, 0x3a94df0b, 0x41cd803c, 0xc920b897, 0xa220b572, 0x2acd8dd9, 0xa1fb0554, 0x29163dff, 0x4216301a, 0xcafb08b1, 0xb1a25786, 0x394f6f2d, 0x524f62c8, 0xdaa25a63, 0x46a90dbb, 0xce443510, 0xa54438f5, 0x2da9005e, 0x56f05f69, 0xde1d67c2, 0xb51d6a27, 0x3df0528c, 0x358b56ba, 0xbd666e11, 0xd66663f4, 0x5e8b5b5f, 0x25d20468, 0xad3f3cc3, 0xc63f3126, 0x4ed2098d, 0xd2d95e55, 0x5a3466fe, 0x31346b1b, 0xb9d953b0, 0xc2800c87, 0x4a6d342c, 0x216d39c9, 0xa9800162, 0x9c7d9cd9, 0x1490a472, 0x7f90a997, 0xf77d913c, 0x8c24ce0b, 0x04c9f6a0, 0x6fc9fb45, 0xe724c3ee, 0x7b2f9436, 0xf3c2ac9d, 0x98c2a178, 0x102f99d3, 0x6b76c6e4, 0xe39bfe4f, 0x889bf3aa, 0x0076cb01, 0x080dcf37, 0x80e0f79c, 0xebe0fa79, 0x630dc2d2, 0x18549de5, 0x90b9a54e, 0xfbb9a8ab, 0x73549000, 0xef5fc7d8, 0x67b2ff73, 0x0cb2f296, 0x845fca3d, 0xff06950a, 0x77ebada1, 0x1ceba044, 0x940698ef, 0xbecb1536, 0x36262d9d, 0x5d262078, 0xd5cb18d3, 0xae9247e4, 0x267f7f4f, 0x4d7f72aa, 0xc5924a01, 0x59991dd9, 0xd1742572, 0xba742897, 0x3299103c, 0x49c04f0b, 0xc12d77a0, 0xaa2d7a45, 0x22c042ee, 0x2abb46d8, 0xa2567e73, 0xc9567396, 0x41bb4b3d, 0x3ae2140a, 0xb20f2ca1, 0xd90f2144, 0x51e219ef, 0xcde94e37, 0x4504769c, 0x2e047b79, 0xa6e943d2, 0xddb01ce5, 0x555d244e, 0x3e5d29ab, 0xb6b01100, 0x834d8cbb, 0x0ba0b410, 0x60a0b9f5, 0xe84d815e, 0x9314de69, 0x1bf9e6c2, 0x70f9eb27, 0xf814d38c, 0x641f8454, 0xecf2bcff, 0x87f2b11a, 0x0f1f89b1, 0x7446d686, 0xfcabee2d, 0x97abe3c8, 0x1f46db63, 0x173ddf55, 0x9fd0e7fe, 0xf4d0ea1b, 0x7c3dd2b0, 0x07648d87, 0x8f89b52c, 0xe489b8c9, 0x6c648062, 0xf06fd7ba, 0x7882ef11, 0x1382e2f4, 0x9b6fda5f, 0xe0368568, 0x68dbbdc3, 0x03dbb026, 0x8b36888d +}, +{ +0x00000000, 0x173ecd66, 0xdfabc439, 0xc895095f, 0x5c819d8f, 0x4bbf50e9, 0x832a59b6, 0x941494d0, 0x3e28c0ce, 0x29160da8, 0xe18304f7, 0xf6bdc991, 0x62a95d41, 0x75979027, 0xbd029978, 0xaa3c541e, 0xa292bcb7, 0xb5ac71d1, 0x7d39788e, 0x6a07b5e8, 0xfe132138, 0xe92dec5e, 0x21b8e501, 0x36862867, 0x9cba7c79, 0x8b84b11f, 0x4311b840, 0x542f7526, 0xc03be1f6, 0xd7052c90, 0x1f9025cf, 0x08aee8a9, 0xada118ea, 0xba9fd58c, 0x720adcd3, 0x653411b5, 0xf1208565, 0xe61e4803, 0x2e8b415c, 0x39b58c3a, 0x9389d824, 0x84b71542, 0x4c221c1d, 0x5b1cd17b, 0xcf0845ab, 0xd83688cd, 0x10a38192, 0x079d4cf4, 0x0f33a45d, 0x180d693b, 0xd0986064, 0xc7a6ad02, 0x53b239d2, 0x448cf4b4, 0x8c19fdeb, 0x9b27308d, 0x311b6493, 0x2625a9f5, 0xeeb0a0aa, 0xf98e6dcc, 0x6d9af91c, 0x7aa4347a, 0xb2313d25, 0xa50ff043, 0xd806d3bb, 0xcf381edd, 0x07ad1782, 0x1093dae4, 0x84874e34, 0x93b98352, 0x5b2c8a0d, 0x4c12476b, 0xe62e1375, 0xf110de13, 0x3985d74c, 0x2ebb1a2a, 0xbaaf8efa, 0xad91439c, 0x65044ac3, 0x723a87a5, 0x7a946f0c, 0x6daaa26a, 0xa53fab35, 0xb2016653, 0x2615f283, 0x312b3fe5, 0xf9be36ba, 0xee80fbdc, 0x44bcafc2, 0x538262a4, 0x9b176bfb, 0x8c29a69d, 0x183d324d, 0x0f03ff2b, 0xc796f674, 0xd0a83b12, 0x75a7cb51, 0x62990637, 0xaa0c0f68, 0xbd32c20e, 0x292656de, 0x3e189bb8, 0xf68d92e7, 0xe1b35f81, 0x4b8f0b9f, 0x5cb1c6f9, 0x9424cfa6, 0x831a02c0, 0x170e9610, 0x00305b76, 0xc8a55229, 0xdf9b9f4f, 0xd73577e6, 0xc00bba80, 0x089eb3df, 0x1fa07eb9, 0x8bb4ea69, 0x9c8a270f, 0x541f2e50, 0x4321e336, 0xe91db728, 0xfe237a4e, 0x36b67311, 0x2188be77, 0xb59c2aa7, 0xa2a2e7c1, 0x6a37ee9e, 0x7d0923f8, 0x130c701a, 0x0432bd7c, 0xcca7b423, 0xdb997945, 0x4f8ded95, 0x58b320f3, 0x902629ac, 0x8718e4ca, 0x2d24b0d4, 0x3a1a7db2, 0xf28f74ed, 0xe5b1b98b, 0x71a52d5b, 0x669be03d, 0xae0ee962, 0xb9302404, 0xb19eccad, 0xa6a001cb, 0x6e350894, 0x790bc5f2, 0xed1f5122, 0xfa219c44, 0x32b4951b, 0x258a587d, 0x8fb60c63, 0x9888c105, 0x501dc85a, 0x4723053c, 0xd33791ec, 0xc4095c8a, 0x0c9c55d5, 0x1ba298b3, 0xbead68f0, 0xa993a596, 0x6106acc9, 0x763861af, 0xe22cf57f, 0xf5123819, 0x3d873146, 0x2ab9fc20, 0x8085a83e, 0x97bb6558, 0x5f2e6c07, 0x4810a161, 0xdc0435b1, 0xcb3af8d7, 0x03aff188, 0x14913cee, 0x1c3fd447, 0x0b011921, 0xc394107e, 0xd4aadd18, 0x40be49c8, 0x578084ae, 0x9f158df1, 0x882b4097, 0x22171489, 0x3529d9ef, 0xfdbcd0b0, 0xea821dd6, 0x7e968906, 0x69a84460, 0xa13d4d3f, 0xb6038059, 0xcb0aa3a1, 0xdc346ec7, 0x14a16798, 0x039faafe, 0x978b3e2e, 0x80b5f348, 0x4820fa17, 0x5f1e3771, 0xf522636f, 0xe21cae09, 0x2a89a756, 0x3db76a30, 0xa9a3fee0, 0xbe9d3386, 0x76083ad9, 0x6136f7bf, 0x69981f16, 0x7ea6d270, 0xb633db2f, 0xa10d1649, 0x35198299, 0x22274fff, 0xeab246a0, 0xfd8c8bc6, 0x57b0dfd8, 0x408e12be, 0x881b1be1, 0x9f25d687, 0x0b314257, 0x1c0f8f31, 0xd49a866e, 0xc3a44b08, 0x66abbb4b, 0x7195762d, 0xb9007f72, 0xae3eb214, 0x3a2a26c4, 0x2d14eba2, 0xe581e2fd, 0xf2bf2f9b, 0x58837b85, 0x4fbdb6e3, 0x8728bfbc, 0x901672da, 0x0402e60a, 0x133c2b6c, 0xdba92233, 0xcc97ef55, 0xc43907fc, 0xd307ca9a, 0x1b92c3c5, 0x0cac0ea3, 0x98b89a73, 0x8f865715, 0x47135e4a, 0x502d932c, 0xfa11c732, 0xed2f0a54, 0x25ba030b, 0x3284ce6d, 0xa6905abd, 0xb1ae97db, 0x793b9e84, 0x6e0553e2 +} +}, +{ +{ +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 +}, +{ +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 +}, +{ +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 +}, +{ +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 +}, +{ +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 +}, +{ +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 +}, +{ +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 +}, +{ +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 +}, +{ +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 +}, +{ +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 +}, +{ +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 +}, +{ +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 +}, +{ +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 +}, +{ +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 +}, +{ +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 +}, +{ +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 +} +} +}; +unsigned char xorTable[9][96][16][16] = +{ +{ +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +} +}, +{ +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +} +}, +{ +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +} +}, +{ +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +} +}, +{ +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +} +}, +{ +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +} +}, +{ +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +} +}, +{ +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +} +}, +{ +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +}, +{ +{ +0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf +}, +{ +0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe +}, +{ +0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd +}, +{ +0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc +}, +{ +0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb +}, +{ +0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa +}, +{ +0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9 +}, +{ +0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8 +}, +{ +0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 +}, +{ +0x9, 0x8, 0xb, 0xa, 0xd, 0xc, 0xf, 0xe, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6 +}, +{ +0xa, 0xb, 0x8, 0x9, 0xe, 0xf, 0xc, 0xd, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5 +}, +{ +0xb, 0xa, 0x9, 0x8, 0xf, 0xe, 0xd, 0xc, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4 +}, +{ +0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xa, 0xb, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3 +}, +{ +0xd, 0xc, 0xf, 0xe, 0x9, 0x8, 0xb, 0xa, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2 +}, +{ +0xe, 0xf, 0xc, 0xd, 0xa, 0xb, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1 +}, +{ +0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 +} + +} +} +}; diff --git a/Android/Level4/app/src/main/ic_launcher-playstore.png b/Android/Level4/app/src/main/ic_launcher-playstore.png new file mode 100644 index 0000000000000000000000000000000000000000..249c9019bbd86bd63d024c04473646b41dac0585 GIT binary patch literal 36634 zcmce-bx>W+(=NL9#wEB1C%8j!cLD@=cM{y)B@mn!cMC2Xch}$~1a}DT?r`>d??2~P zb#C2T-~G<{YgW~oH8tIdlpjJ1D5c_Q zR3(qegMZuffP>}E#Jvk;(IwlL5@&y(zzwbcJu}t@A6b5SJ>q4dy90eDpGUmKM}1$zhEv(iMd03a%>`k#tv2^8PGL9M-IjjmT@)omw4N=>P7{JoFQH$M8tE&e8 z&Un!(rTQT<{&qmdei?U$yDiNxW$HJ-g$yf z++#d#*~FiXX3Wp2Ka+8e##O3aK_qqStNgPF`9h;9L0KZ)8_dz8+<+gBPBt)-NbAIM zA^3Z6!Jze7;L?6Kzp??RP0s1r6xA9oIp4D5vtsS(l-uCKYUpAvWggK6aRrVz12gkG zoB8T~t%`2VCf%iS-3l+?Ss~Ky7Y`2~-y5NvHz02Pb*)0PsyEfhx9AjN@WjkrxgJ`j z=dsa#)-??2CLLI;@7~-R9HYbAYsEoSCI0i`4~^6LfTvsv!&$8B{oYh=f2`edjroPC zLTt=nkFejgKo6Np^(y9E*E`CrV@wO1urFgN5p^GBLX!z8!=!XFsg{~>3r+^lvQ98( z@<|@sT1`cbF{E!#;^?ur&tHSX7Fzs;6p2M*p&Lh%$>W?XC_j7hs`w0YLqBkIg(sNQZ@vQ)MnRNPY{8k(g;3z_>2h%wiynJEQ4#1-zU_qR_YyMzt*@i)S|D8%;32!kj( zeax=�W%8KhVUGg!7nfvzZ-!98YJ5LD`+?|4mJ{u^lJecgWg3z_VW2UmWwk)*$)? zef=#k7oE807nO|D?l|EGY8nb5A(+KQ{PU-?ZYo+@golR*I(m8)@rl1*UhjP%5Uyx| zj+J%z_2r4(xQF~Y`jojcu5Q0nw|&{{#&6|%f$Zf}j5IFxFy?0jfm^qhLcsM2CkD(T zdT)&h6}$WK`!wzoyN4UPL=TChv^`L%zpifyWhdacgpn^VeXwjWa1 zl00_77@M9{?d}7Jo5btB+wXiEeBt~TJb=_eCY=&aQCi_jMX9~9ymq550;Tie3v#$J>C=FTE|F`PTmjB zf)Lu4%^)>rZG7bU6);U6PCb@RzUxiRLs}Z^{^h0# z_QgXDg&I#nvjNW-4j;^ru)O`{V`@n*FHk8$g#3pFC+uQ_WPHdw@oW-| zwK+nQ>?Mi<8>@kqw)_$YI?50q3QA}40`C~@?ZoH@q>|%2J%jLA& zIi~R}K6ID8uDGzM6w{G^aJ6f<)O>FbQpMFPdzZM5YF;yM7CM|bn;cfZ83=foOyvmO zZ-$@MI;_X>I&RQDUygx@pKtJq`CSpAu0NDOCF6L#uR@GZd2&CJ$m?~82i% z`I7N?wVmvMP=^jLc%q?C%_9?<41>-Wvb)=iD}=rfp3`J?8-_a@z{xSlJ86tZ+?_ok zG2(T_vHLwyHc05*f5b`eeZR5o1C~3CN^@96l2oO#|pvs_Z-m~q7`48hMFXz%7&RuOwOx+8izlz zX22_7Y!+`&)|RRIsGs`<-@8Y-o7T@k9@dM?${JH;N&kra9Bcnxgo0miB=Q!UEkvAf zY7+O6Rquz_(t1B}Qjzx@sa{>P`|)?_#BC?V1sw;gEKGOZ1$tJKt=rHRp{>)h+Sd9F;pg2 z)cl%G@|K7i_NOtEP7ML>Z?Eqr^CG{!qra_y7icFtOG|SQ<0r2PKL${s{h*78I1a<4 z8a6)lL8%o(teq*DDkZ??gU=wC2FoHrGmM6x;2Hle`w^Bj6GpWwD1dDTbK)XLO(S-cvKE3T6+u7z|wLQZ3e#O!_q92ah1> z9M(4sIdxAiVElTYh!7Clb5SzQ#{wg?CL1!J_QA8uU3!7OB~~!lzTaPLuh-|7(}u_X zvO_-SYSNVKZIfSLv2@*{Lp1iBJd27D`a*p2dAl(*yTmzmkWcL~l912$%k zaj!3~hM%tRjn5$6kg3>6w1`eFIvc2JGrCk^=wi5@Y_5xGjJnBt==c_d0y-nY(jRn)K4a6K^mFM6aX zh%(BeAH1dS`hT?0Yd_u0^Lm_qjEuZ&r4~hm>oL22>lLtacrLd(`o0lrj_|JKde$5IsXZ_ z-tXY=j9^y7{B?sy%8q@>8taTiCOfUqn2wW8)}3t>45{5kKE{WTaiecCiTD^K$5BP{ z_}c>`YIICYDqD8sD8{&)8_`@)OnTE9Lc2HIbEjkaZm2HtyA zCtijb(_x9oGh(Db3=8#qh1(QZFjC^G6CKI}W(+!{?>wE11kW_b!aa_0d3{(#Wwis6 zaB%5B(UAJnNY$nHjx>@374JOw>3^XUx zb6TI<|7+jqGnpi0m%J^XD8D8STUz9_J-G&ma6jtt7R4O{D6W(D zHjj=&TRE*Z&M&sH!}hEW<+&5v#>hWs6ji(gY}ei|AW>LQ zkv2<4#uc?VP!BDWc0WEDyQvee5!B-PJ1y>W^C>Yu+(odea0Y0x7v5!fN<;)_j+)#> zFt!XTaNe9=EZvHtUpN@hu6~@nb+BfHbuJcpfSN6#%xC` z_R5$@s^R|)mf@x3A{t?e=-FLZt$ch7Ovb_zJM#IAv_PO4jNd6J1wK3cwxUL#PgxZv@!xN4iKnTr|)2o&}vuO z%4mDqC0XsvNo%Y->XV8xo#9!rE^fSd57#YL8=7KZ;+x=t&qQ$5p29-9{p<^2pXHh* z=f>YFyo^P76c8ImSQwlsoty4ih>W1o+bDQr?E-9qh>SK|vq@EJGDD;P_`<>9mfUfP z1r;9wEXvy|=cH3z%1yp!iN;;67nO5bjp*~><@tSN=p}l-7{AHN}aB^}e_|YN?_of1Tv|Y+;NHg?1 z|20fT_0$Ik4+j;^v3uvuT4SMPJWs;j3A4#oKaQaJG{W{#uKAv^+HRMcOyynN0Eh?cKAdJnLznaA1nx+qqYkALbe|CWw=(~+9inbC8 zoD;afH?3}Op5lg(b-#fK%gTN#$V(J=aIHe5^~J1ZA4YLQ@Rz|bKF z!eao9jG!Q~e8jkjzCNia$A?P`Giotp5EPZL_i%7NFfxh_{zu&R?ZtzDZtRxZ3zX|o z+y6;~wh^DzD%Tl_e`J|-WbKwq%wMT}WQtKrw73MfE_9^RO~=zJTuY$CWD&KRwKI@s zIBu{kkyb@pzaZmM@UtGkQ7kt3IQ6i!+2DY1j1<||@p@J;b>Dd&+YWRiX>Abc1uI@8 zn>P95<~ZS#MFGmo2n^>+%Zld&K15BcG(D^>tdm7Q^2D<^lZTpyMh7|!5nf0vMZ*ZX zoS9FQ@G8qV8s+^zB8h?=+ry~H$;CNuTuN&&aPir!CW+0htSZ>4paA;{1z>Kya-c@b z?kyT{&*O!Z+fXl6&>WTGPD^ai)SiuenuyleMenENj?$wtQJ~gQ6{czp9>3xz<$lMRhTAo!oiOWF^Btpk#$0#C8vC?HRGn=~3Gr<&sRY~uk5(kNQXprsU1I&pDvc9&fy{WjP13Lx~k z2rjU!P*$UH>8hIBJ+$5bglH|DANO?k^F?(%wc>ZeOE?}q{rEDgQ?#K50fe1sju_0B z7%@QK(PaS6!v|L=_wO&@@#(_jW$U$Ls$|= z)%gv>%fj{rciJ*uJmMI!;*y1$Z~=OzzjpKYrmpW(VaG_F5D`zKl74(N6U$v5cPtrk zn#tg^`5vHK{QWs>GeL1%1`n_m0Y;1Lv&B+1Log#CkpNR{4I8O#B)(sdr_g2w(^0?L3ZrO>=(L@DAZv%=JCd zve{hkA{kox*vp!uE9}=+TkPj|d6&zbs3^R=3XdTM#s95LJRm9?oa_6sPH6z)ub%WxLENHOT2*H ztY>&%=rnq?;w<0!+Cg~0w%cC^U>G*4W*NXo1jVCPoF-ym{6VLuFH`E+TA@M$c4P}f zv173~|H_8SNK#Q!B4cg}z5mnK|8eG2hUx<^Rz5`n;y<~ckiqmobaN0F=VR$I)7C5H zMs+b#&_+BPlin-ECCXLIB1r!o`CryXa30YUL1yhwoxn9?QB^sPZ#M^FKX+NTGplcT z_l`;<$5$#mmCUe!?_IhqFVsAGjsGNUZ3e41H*IO+5pZbETsiibbfcv$&tX-w3Wr~W zz;BN)*3MbV+LwRUSe#T>#7ddHbC#98zBZ(Q0oKT&LY3rr%Zy{(m{`fZ zs%s1@TguS{6r>zrhDuI%ymCW=92FUJ;`aX5Q^CyA`@L7i{QLMs7d4G@z2?*R3K<^> zJH2nj935NkeKEx`BnbMIE$OHTKKaSm(h%C$;DrZz@iQx zb?#+K=BcRZ319lee=Q$N9Uq*AqL5Dh#ECW1%#i1qTXh%*ldJLGnnRivRtkkEjl9uz z-=5xjE8dPAzPtsz8b#OJM@|UaIZZ-h7_72REoddh5IQWDvFssT(Tg+deT|uXrPIm% zc@VZH7{k!&I6dH})9uH3qE}D;jo=Dw|67#aXfZPK%b3LThzW_*Ps#guS~REY>d7xF z+b!U8M=<%HFBuZa;JlU}3u(#c=2ip0F|`oIa?;WwcE+^wjNT}?dVPzBL}@B=7rs}H zpq*dMOZJ2!IkkA-5cwcrTxwwf#h%Pw7js&NHO`CS=WaFq`l*_{+so26;#9Dr<;|Zb zjvLrf0757nJpTM7{Ko3q+&tK<$Fq5VfSvX_x9rHyBO#l(S5uscJ&8n-hr3og44QIJ zGq!*ydvD|0fNkje%~f z72KA=uW>4XU?qS!M_gW$jpP#w(0Tu@3>|J1H_k}Vis+t5`lG;PaEs}EM`*0yht58^ zb=1CuStJ?Qt@~-Z2{u@wuhx2&0S6DSP8y&HAOtDfp;}|RZ$ENHlYRseG$(4iGD-eX zzw2C9`%MG^;&ZQpD@bDDU4!S>-$WFMcu33eSqt^`^{?c|pe}%R-*^`KQ_Dz|a)Zan z>W9w=E)2fy*&1HRcn0O~Duk}(dX(gEaw{$AP>(k-`$AA;8z)cw(wcgt|Cyn8{sQYkF)(#$aMy_WN0orO$4fu zM+!6*WCl4EJ0-`oTt70*M%%1+!I%ySBZ)ch8d*v8G(=v62L-vABA7eo>%+w#1id_= z52SNi{V5N*HP8$S3JMiG0{4*Ly+)to1XJlHFvd*^;kfwVU zHsrG#y>G&1ioFKom!I99eFU2#0+4|n*qzq^(X_}eCE0s4YU(1T6DbL_T3ZvpS6{5% z$?UlE^Zkrc|A2r*mpI>ujUHuKgmBZ|V5y%I6I}kO@R5Lcjs^%Is0ZHF?FMk+1)PKW zPV8zss^0luIeG2E2I_(wn|len=hDn)hz%;4oVFV9p3O1PB#rWA#QfPc10D&*vq;!` z%lU5Gn&*}Xee^b4;)Hga?2$a=IXi@2n12{`gg%_HO3&}T1+A`T#c%qb;RgCxDe+Q{ zv^TQR?mS!M?KrHF)NpyyS)ywPb(x{}GHUX^wWzx0WW}+lDa_tO$*D-N=*xtrM%nhn zWLI7tZb5<1e5L7%4ycB7myB|V6@EA_mrWDt#})10bUdIAORuO4*~?;wfb)^-x{9W$d;a+hk_v9ESm*0b+;7C&6q z?gab#2(pZCcEX`qtgVvE^Iyw2Om60l`C2OBw`+MO?Q0Of&>i{*R}bmp^4Kp1N}#+O z)t|RDeQ&&N6bY*Ks{ z{ef_C*q=*q&V=3eNdcYw2=JrZ=;7T)hU$bcQxP6T0|*|` z0_NYsR^VGUOoGfEtd5b;hPS%v*^S3Ru!=2+xk#=1{H;KC@mlE951aGoBH-QzIna8A zsHq~IX(KTsrCjr@ua7DwC@B9%@twL8?5l}2@#76is9MQnd9ZPSH2()E=&B?OsH-umf) z<0EF^_fBL`jX8zfEyAP8r*)lufm`wpQ%H{i{|c{8@cf?yi0IL%4Covm7x0+VO7X)P z9hKK0eXI1?EB)fn%t_vmlMXV`1@Z%UgF`55yl-?@I?_vm(UB;o3V`_Jw{nJje6aD@ zH)h16HO$-?=iXVVY)6ZKg#LL--)zpal)bH$EUx^-de<-1Xw234=ftFla;_1py{VjD zIirO0x1hc{(sBvA0QqM`U~y`r#lZ?z@D5$U)9)jT{!dK}j9KTBN)6V~z)9ntn_MmH6*a*8`^6|0 zr(f0InnG)Z4`lLq+qY_gtSNWiDE%^LVS3N+W*vwBOb>Ih7$Jf-UAIxfaKB_fK)tVk z5orE!R_+bQ5z*MtfYVJX7<#d77IP9n))W+PSzD_XpOa8l{Z1c5{+AF3xCEvXs3_xB<-XL=d)7HRbi>FH++4 zDw6n^HKu>1?OLkQhMgbO;Lrmrc8;UX*rtZwr2XDE;@;lU*-=^U3CSX38$TtwNhNcE z094x>jxG-u@s!LE$0ao0gH=4njE zH3tT++Y1+`VM-+6zX%}|6h3X?JDsK`r_!g3A$q~X1u{LVe4RG=)dv^h+C0?6$E;E} zhL$W)soXk9gllu6+|UP_x6-9DGe`Lm+ALZghpTFFMLb(NWQY{#YNpkrz+RXfW6L3E zA=y5m)(no{va84dWnUZwQZO5eB|*^tN&Lr&XPugCjFoOE*kh0UPaAbgt2X7Y`YLPE z4=%59Edra%)wc`37m@aa`02uPywH28)Sk?ZE&gc^!2-(53kV=HT_hJ$*Rat9jp(n~ ztQGnJItwM6GcR;N4hbkPrX8p9YZ;-Z!>M>xzOv}P1Y#iK{gX`TVX#rPZp=z%E3{8W zaE1}k;2+O;Kr0BFS>szLmTG5GX&X~O1i2)g)JQ&P3M5rG%WRf#|ID_DiGt{nv)57o z^K2Wxc~V*qW9j{K$H{6(zg|Ov1X9k2 z3{8oU4aDb>M{}ft{y7P4aT4>Ci~LmiMZGn^>(TKX%EH*!f*&9o{aV6*wGmrs|E8;Q-N z+%bk+Bv7T&Cb2+cgHu%}HYqNkpYtU=ngHd;eWPSuT$N+BDg5zi1QU;yd5Zwm?95IX zHZZd0-m-7WOx%n@vzXqyI;aAttg*iRyS!rVH+XL%EeHdJ)Avs=>388Ojinsdzs^Is z`Eu~flq18^jJqzWcN4c?!k8L4OsVXv)KUA|BJv4DT!qAG%u7W@;#!EQ0si4sM8;wu z5AYNP<-x&fj@{#ikP;FSrg0suF5z^0BLj;#pDf|7$=DD}rm{34pAi2&+_Sj$lYq2~ zNxg{M8mT^Cz0GG5<)#@`UjJ5-Y1QvRzq9+?b@I$h8Z_w^t%C|6ObN{k@LDChRCYCl zlVJ_eq}H}&y8yhRo|l)pOU{`?3342nki%U|-!=Yb-=xXw^>{4=8;JT(rD%E=s$R2$ zRD%tVLWBJ`vo*VcXhUpn9a3(FWTjgbh?k6x8ZNNZNFuc>3%g?Jz7Y0%dx$#>2}?ye>`b zLr4qOH)ldbhIBvvAObQS2VY_*HLDyC|CY7egG6VIA(BP;;7?!aJrybjDZ~PiFLBT; zj#ydK(@2Q-lhiKk3UgQX*5*5^1Ea$ZJ}j$k(=@y>&e@bB6(J1!!nYM@3nid__uO(vJ{@+V+y>_`Q(+X~L-$#6tSM zL6s4v&aY0NP!=!Ns91T_wfpXoS@g__c9ZL%&H0&TZ@H6ZROBvYm>!@54#$e*Q_oMc z?n0^1HH&v1!$lmw8_$&Y{w`uv&)lGWd4Xb~(-?Yy=`92wym7@UEEQ3KJ=bX$-j{vb zSC;t}1e9{MYADB(o53>;bk|EB(CGd3GYw~SVNMWQ1Apqw+~Voh3cG4lA9Su;&5Djy z%}f}x@H+U=2=Fh%;{*5>7V5FC5gEH1Rn>SszNqh}#k=*w?;Iu$3b2I|dh5^Fmyh)SS3*0vG++G$ zA0+0c2^>-Y3fwNc#Ir7e%)v2odPTZ$u`|ovC?sTuek>>FcX?bg@RiDx+xblh|<27aPnm9Cj>v`tT?p+Sye|RoZ zj!ht!_$?d%uu!{qI|+5!n_3t8Ri--zNtrZ)hZ)rl%4ZkSDCr4V^S}l;-u>1sLL9~G zyKG_c)GoKf(DB%q$-!pZXoPXhb=7FROt$m$8Cds?%o2g?siy=+N5^WlqGdcK)$KHT zyb%FHUOFw1sTnO57qbBrh`~$4xU573T8FDDG~EDyA#aRc!|F7F6(W3Yeq@=oa#BiB zcqCnVMwQ;+q2W-C+k4{8T@74vLd{#fA5&WIBs;>*_DS&c@1a}G&_I#6wxLVQQTDJ@@5a9}-NI8HUGR%)>}rC(YY2AEmHgo5vB>iQWQHZbm% zH2j61@;)qJ>&8SPK0Vv-j2YmQo`u(7&2MQyl}}*~gIKuuu1#)LgGJ$mM`Z)j(b6}+ z2C2QWEMP5>CBi#MF1#mnjB97fI{0j6@FrduQuOb6&>HtXRz7G%@oHZqE#2y6yvn0k@DQwo1^S7 zPEtcav0cAO#F+W?x1b{9WnHrQlT;rvA&e+!8i?|lmHi~&|5F9>9_G>d=y~4C7pjah zSkad*J+-Oer+}_@K9|{CNr;4rNj|dh`1q)}sVSCX4u1@lOx))ACRO=f?<-7q#F>xC z?Tagb;QtEO{pv0Id`cHfA`&}eHA&9L2d5*xVASqTGB`-hMJdM3^G|VSbMKdTjg1$> z+vn$y2PRn(HTW?jwWgO7`c_rCJxdHq4K&n367YYSl_tuW?e!21U zi5Oh)St_ApZZv57Y!XWj#4gf1!oGO!L^t;b(igPp4K=%^Vksk*#+fxl#E0B zYXv#MqR*)rIp0(uF+tq{Ewyb%o}KNmXrvtAy=d@8Z`ZnBChjTAo`+&r4yAayxbGNxryDd)eV{0_oMh<8HCV7if zy?hC&+4p()aD}uvq+%Jju2w*C#_5?$s%Hih_6rVBM?O7iw~TqXgegCyyEW==g>!-j zHug~4#_BF&=j^F8)PuRJ15+>|4<6y4S{Fy6YS=c(j4;Tor0oS(@(eI_8ZrKW)hjD~ zah?4>4X0zT$dJu8)~{R9x2N)!Cq|e=I|fYI*o7-Xx`I2O2H?62w6lWIX#mAs{xHl= zpF*Q6d?$4aFfaKp8JpY06P6GnJtWMHP_r(3Z4xd#3BxxKX>F=TZEnffFQ}H6p~<$a z;-{eq%tEqH0BQnwW97ly7Nq{RDP_R_8XOEZx3r`$>9AW?^lkB_F8=KIJ_P=qjJ7sT za7aHU&IgeS`WSX?JBvSaAE#AuKNpi|MO^R|2Nb>#6BB=vbux^`0h>Htr{DigoT~8~ zX1Q3SO-N3TDJU@Au1(K6+QtW*pa1gds;FGZ7SCvupZv7y|7yJ#Nt~Hs#uSiL`-`hw zbhcXv?$k(cjr*s_sq>GLlDq(O-XW>w_h($&_6SB3;!L>#mJ319mb38SR>&h}VdgL-R1A^wX;#E|+wxed{KkvwC zW-iSk!TtUuYzvi0!ENqC4?nKxW>Wi=?d~N&gGbyH{$wIFdD@tgXhIZzTGl}&{wPUoHXwll@GYmv zpWo<#O5K!~xf zjcli?u5-((a8~fvEPMFJNd@}@QEO|f9PG#2JOw@$)#;yhM6Kd#cf4etzDX~1LpKOc zhS@3=pKt(l-$-jI`y`;0LConZ=~@OqT!N{4r&l$VGj`UWF2D4QqD&EK&@}Q6wC=23 z#Yz_V>sR&L`14BOIO&3ARHU0CoxW)l8^4noOXCBs(dhtZ`<0&KuQMAjTivy*6H*$t@?6Nk!xFUBbh|ws zW1O%BW7FYB#9~0s?nmhHQUZ8d)&T>y`{%#<_X%g-2gw1FLP-F@%Mx#6?kgK3umooq z2W>6VZ@U*jd-aATgFK@`Vo1ZMrxCf<#7605R=!?xB775(l;3X0;c5#XITP#=!PzwV zmBvPaR-xq=W;PtVdAT!YEluA{OZuACr2+h$jpbR-imj=Um6W{3IU_96@pP?9CvD%p zATSY1en-p(i-7h_In+@33kC2}#Kpley(+GXh~EDyC_Ph~F;pPVPtX=&}uC`&!Fu4aJ2JL8zYd?xEh4veNP zT`*yR6_t0YC_=@f{<4)P*%?>+e$$--hkGIaOA#|m=PK5x{!9w?C1U#56kX!L;VRDO zr-@e$R)E#YcVQ84?(Ny3a=ivAOp2OqpYe?iUR14emJWB)WaRn5(dRYyzNx;@Q;7Bl z;oVDOhyJ;lG6vpFdYGXDv3T<*FUL6MU?2V1@>3a*DCpcuMO8I8RHz*ji^v`os9Z-5 zY-%74zQ6w}t29+Q>`}od>}8j*{vGwNfaf_I6llbGd3uMp&9t^IGVmo|JS((MshF4n zrF+mi81HDwPpWtIE#}P*qWAPjaejx+?N4)|GvI=7O%{nR@{CBUnAH=Ll_i4#YDNz1 z=i;MSL})vx*S^dnHS8%w^)yz?3$=KWST{t zr*>u0Y{PIi183ARNf%v*4T~NuN@)ad%U|rjSuatMdGx59xf9sGVhQp$4z~U<-)DR$ z4(y-3N7B~<_6Nrg>vzUBFLL*4+X|^BecH)a^~MZ&59djYBtH+FtBB++|E<{nC?)-n z+Q-atMn8TBb%G{XQMZ`-gmsC@7=7QzMf@dUPf=}>y@z3FiB{wOV32~{<$3X2sB8I< zf9$!DCficXgkm!5)Aac%7I2Myx6Zn@_H6#?nYwzt#Xq;mpE*Xct3)A@ znVDHe^Oo9nspB1_QomsH2=alN*e|zGhC`Q z^~-U+dQpOnOK5W2PMv4$$c&OQx`fsrR1Kv1-%=IkSQET$^Xt=#jdGT$x z8>gR%kR@zS^>e{`JtHP`vQfS z!bVW8iYGEpF|{>3zPIc0z4Zl~X7TzHUF~+qMf@bFDl}I16w<>I@j}7jbV=u<(1Lw_ zk@y99Gp>Aid~a@Lgj27nhSSx%|4hb2qLhq-zqfxdQ}U~1io9y4E+DjSX*LGIX8MEO zVZ#A~fW(}_G^{8tk(y_iE~d+uiTee&5Fu^sfSjc!T&To&e4%w@hp0Zu87B5^|uX9Ps4^$($yrh^-3MX$RgasnRw|Ud_(2 z`m910rB<{JLj7B4JpP0Q24UH_#K*?@KZFK4rX;%jV$S(jl|foSxf??c z_1@6uN}c*O-Y0)v5P3jsWNa@hLV%Q%#h@Q8D#tYInWb>on?37LYbv#(RW&`FX zm6Wb!Vd|NpscZ; z)v|Ugs*UMi&zVEF#E87SOdgBKB|ur9{9J2Y%vDXzTcFOnR+l}I69|;X2q_-~w~s@M z_ks@r&2Y$Af9FES8EV4pLtq%R1U84%8Gqab;L_(q$hms(p8VRk-RgH8zpjCyCyS(0 zdbAe?n!%t5!67xkZMOgz(F%;aa}TSmliqV5yG0W>BAg~x7tZ{pY&NAXVJP?&$KVH{k15X{GhEkwVJPLlk_7RLa8XRh)m6-1H}*zrHVd6( zqpi%2H6Q*U2Qsk7#U@@KpE%~OHF|7orY(fTO3Ig6==xe|Yk^cpUh<_A(ZEAig}-A^2AYP&2zMg< zfo=Y($a%;eWh+<#aOHM4k%}4T;kD4!GUH|x5<~9#h^=7 zZ7m(V!ET`F+Q)~Nif?vv2-%#?CowI|ptR_$L|ag0MCefC-?8lD;s%%3f~_C#=F+%r7=z z@+ocPw10hFzl;um9aH@mpOGEX;^^IN_a(068X^TKn33pBHiyl+-f&_Ug*y&suzd>%k* z6f!O45OlmCe^@qk@~1w2MWdil(VY`BUVx%hghFo*Ruzuh()NWIKrvDh)ALm?!q^{n z8$w!4x0E-kGneW=55j}%712ct&1Y5@%@Cih`CKb#sCxl1gdx&N+l#T_bv0vT+hv*z zVQ`w;*)dx#b7(*aN8Pz_X`11fa+DqOT9>fm&mbH)>b9aTjU>u#tH^`vI+T9$0@ufv zU?xMmZ;5+K`Kr9HGD6?6p&g-T3-1z0Oxc{(!M!Kb4mzDJhLk)0Z_qgV+5di6yfw)|k7xKUym@SqnE^oUhIYQ*EZ@ z$Dcn}g^>BMtufO(V>bJC3Apt3TWgZr2l&4*BCjdwe}PcL%olfaVs~c?lr(`+;a{o@ zkSfmnUgE`1>e3oxNx4Wt{>AD&;SXKn>`vl>&^wf~U$Sy>V)v$~zj9HKKKdeR4GTjd z*&jtkJWJk)N{v8idATw;Z$+6!agKQ0>&U>h&KIs8VR@@>m(=>efYoxn&CcBv&;CVn z3oNJ3B#l63MS4;OVZE4@j@$# zLEB?t{gI@kf?!m2-@%yQ+i9PUDgb3VS}WW*VvFQkiTD>XVAEVihB_wbEZ zm)=>2(UX%O=T9o}Y1TO#_f@Z26GQn?V{}nB#7aEMyf)OGHfM8l%gyYsYQNUDs5=&y z@pO(>2P)TzcG@$(ECWcEO5|+Hc<3Bjra#mpFw%>ZyDA8whycaKG8)0@8}fLL4{2_| z1(zJ7yn1i0%)~z`VB=wX*L^%V1c;aE?OVHJtOdjVl#u4>&7K-mFCXt!tv}Bxy5Wv8 zGHCd$Boq!2km$8Ied_YZUm)MERK@FC?D8uatw`bYXP*A-VsBxwQ{KLoC)R%`6jG7v zf}-VwSUiP;MO@ZIBpu^Ra*-{_Q#f4ckQ-#} z)p6_Dzz@4LDl0o-_tGpAE&qoh*a#c+>sRN+>|tX|dS=P*Y3uhlD*`nO>I8IZ`f3QM z1o~=(=O(cKM1M*XvO!Z-n>lRYtM+G@((!uzQDRX#8X$)5#dI+(5MRvM~$yw39Bv_<(rn(Kx!|1H z-$?$3u`nsvGMJ-V`}#dNRI{aa8EIJ4P1NB|%Xp>|N%-Y23XbMqv2fond;xL(lxHgm zIdGF`@{{ElmxpVH_=j^@LUTYo9umtSv%AfkyDxVNSJI7rJQvr|R5cE%ovrhvv zs8nk+I^uJjIxD>`?yDQ~H6&aF$iE{}mygex3JeUQe=nF-I`s`4 z&FmmE#}K&j-$OMh3%@WPQqZO z_xhayC}(GmT!Ct!j1w$bAJNUz&C(5dl;HWO7I#8MZFiEo3FI)?qBO1SM!S$AO&E9Xm3qUVrivAIdxXGXVz_lkD2%B+!>1b zs=Ghn27TUqP%}0vEB&fCHG>JCo_1>!_D@NRR-GO)n5n`xL$usu0}|h#`AdK^cxoadqDzlZhK09ECsxDmX{?E!0^>Wz!r>kAg}{MxfNJobMYH zURF<{>ld+&F6|nk^XmEh=d^LcdSRp(`;~pfX4&F~Wl(S_W%1$!?sn_&YYw`LqrV)l ztR2e_`SoyyA(FDIJSgT=AQ&4#@+9K;1gJFnQOUgBuu#5x zT-ov$ak$9XL~Z+rAoC?T7Z>RVxuY4_21hr&)U&=5yvEhRB za{8+s!6%1Js|EG-1LBtGOWee-qo33t*HsHJ)LC_wjX3U8)x95l9(Rnq+jj~-U)Ljx zx~U%tFN-py2kCP^*ScA3b-4C9ncqgKnqkTy4{(;6U3xe?s5LKp`bbb-e`0DmCwl8* zgzE#&vjZf3$&W{JK9BN=p12_>$YW}|e~cMx)wj2+k?{O^EG0x8Y4GSQO@${5(2(Nj z#4M*RnzrbuAD4|BI(?%CN-h+r4CBncGe5qK%Pm*p;4uvkvXeA+-iXBC^WVPrbgco; zIxFn3q*7&m*}s1&*&)^Li@Nph$C&q&PF_4d6w-hFaGGq2KAX3(^DsD;V!n>I1-8hM zt<7Ww@c%v-5lDD9n4#i&+l!pppQ{e&QHct0z*XpBW>`Fs6z3qe>v&i6uHIJIAlpT> z%)d(L&eX)K6N&Kc?blTC^7{HGcIL`r9~%xj5#(c7)MbU+#xB*v&Bs3+s^0 z+Z0>a-?o4b1>){|q<@FgBdbq1*q}+9{yWJeyq8)YB3Ysi)Ec=m`4a1;z827Fn^gOQ zw442^FhXKt1YuxO!}cc@mix6xemxdV+SMrz;G@;As#!ml5R+vE+5AiLVxf-Bn;IRp zX%P>^?7U1hIn8Thb62dhFKJ{CjC`1zrVNpdjek#E{pg*ph57^84xKI3pKKjl2NxK7 z45sU03g#`Y5Z_hI4lb0H29&l{|8PFCEM9t#|0t^dUblG3k&Ql)8>PaQ1@T#6U~xD6 zV8r;eXHp|=Wfd1ufs7u-=N0hjea-5JMBy`O4bnD_Pvd+mI{cdlwJW8p-*E#~48y0`^sqxk zFjNAlwjx*C9c|^C0S`AWOKsjd{$Wij6S9a35~|`Sn`j@|TB<-H{!Wg+V}+vWm=9X% zCu2By^?a+IDcC`)kYSek0FXQj)HfvqH>aEIGQEvz#WhprU*G*oyZY;vMU+^}#kP_| z|FNy-wpXe5RR+6^)pQRI@cw+oFk~n-peoT~qWKx4s4c|#e$p`6#V)VB4K>~1_w)I7 zvKo@U0#!+jdb`uro#k!iVH(@O<;X=wcXh+1`NOC-;~0)V>rn;SjU2k%&_9zMjZj9V zu1Y;ErgASmoUJGNOrA|Fm2CC$gH07RzWH>2qo1leHKmSs?@64>Xrw(2kn(U?jk$=j zCrwT%bHEPHUrK9T5`dbWr;J!{&Z29eEOy;*zHauXMXUN&xORnD+(E3Q?wroPzXnc2MRaLqCNg#Wm_`;>+k7}no+s5b^f4}6Df9Uvh&%QFB6#nWI z`(~X^yKv}_x%DrJoeuWg8uc%~en|ZVu1I|I<2=otkx+CQDOBRej~f%(Pq`f^(Z2$s zcmqL^L|z1ZEe~_p%StpMQ9Jq+`z?rQe$C_JF6+8-kOW(*{kc}AVK4lU$W2N(UZ!Y4 zL2X-ie~nC1QVQm3HO<6?zZ3U`PG??!@c?CmGAmk(htc&|BiQpdTL2a_eg5u>4dn{D zTuDw$wY7CFYpJF+8$A}3&p6OKvW>=n@5!FHA~4Xs9%-iT8hR&PMD>v|Y*#$h{ec!0 zF3z8E@L^jaiVV-z{(Xy?=cPBjZp2H8uKQUp!z(awj&>t~q**>R4RrFfI&En`?Vh}@ zIsTU$7oX0~_wE+ty?jhwf!nq>hf`AX5vm}xhVX6pr2ll)z*N2br`0jx)?St2A&Y|o zZl;2ml{n;G?tibH{e{t_zdty-mGhu2aiDf-yaJ}BQ!qe++PRmpFt6{BVMT>w`WMU9 zR!@c$9)mA6n=5iJUz(aD+-@qiZ5i@=D}OKW7_>me9HqPz$!4I=ybeVeXPbLYOBJSa2>f5=KNCZY^_qntvoo zXKkC&Fn;A`Q*Ygk&9RAJyDi>#&FoMj6knFfRlF7BgY}6~Tt~iFYex@4OSHKpSNvYj zKlwl$N2|IDqpAE_#hHJO(e>P4{)z%e$(IymCxu?^pCTff12)mQ2Gu@q@`uTr=BMXt z^NQ_${4t6CEPb0{Rwcjo8{kYm56NNp+;f;{=0d|9BFESQBgUK~Ls`4(mUPZWO85*f zMLOyTg`il7b@f%Fo$MBw7F+WF8+$UV|6wCrH@E-z`q`i3u`>T%@SG}hs}!-D{eXD* z%r)l?4gPFvkkeNPFlR#bLXmDe}M^*P35ha@>>>L%){2KaH*v>n7BCx zKXGV-aTM}7{P*t-g80-_B(lkKWmU_>pans4beMiWWn6bO>~`&N{c=?#dr5eC>IgmA zd8|H}iyM*zpT2k72YKb*uDvOcTMAW4e4v$yCCCgXx@-O|NMlL9PD8J zRE&arvH7O2p@0nz@@$ds^W68K?h?WRGqBlFKjek z*7d2FIsyC07e$g1dzZUKx$l4WzSw&uDNnIJ@o#44IN>k9u+?baOxf!G-sd~7`A40&|ORVQ5D>)*r5)VI5%Y%Y116~{XQIzRceO_Kiyq89j#~S$z zk0v-~b3F4JaQ63)T7a$jZ;;E)dvz0_u+yi1eb3YRTkCrmSFzsSWC0o3w$JmRc-D#O z*$gcCz9~+|!p>8dszP!nbze0&Ih?QaS5*?A^jC7?n}7xue2NerB+d&EsbMpp(S;A} zmnfMDFi%JEZA3eSQ^Lp_Ym~nON$B=?NjvBY2u33{h?gaFTp`r`3GG$0*JEEsR@N8Z zT>H6y2NsL@(k2qRC2O1gnrnwmdihSPfqU0K+<*UZ+3ee&iD_v$8CnCG!V%$M(RR}J zB>f3#7G#lkMOTb@FIxi0lwGj=t6fiDVk}@cOY2`QT-_vJ9pPH28awkjanIi{e@p?O zhE>-x)xn7J1s;Jc6&Pvn;c8}KZ^Yw&Z!ET6kmqw3Z3-Sc(%v; zY89PRsl*KH3hTzk6A*&4_GH{m5+AeOS_QiC;8r}mmJw&|53zA*a-sE>DO}-*k3agX z_<-69rerEHrxNj@@yk zjc$5h0X46nfOxY{W4fI{fecu9mLX+BJ(`PikaW$Hf<)QVEw;N|_DmJ@bksOOi-9(6 zZ)By3A$gZLxg1@E!k}_Fxq!W`Jb=9!^$jL%6h3fX9B<|~>`CJqM-f{YsggHz09AUq z5FL(HWJcpF&3Kb4gaL=1yxBXre)+qrrD5OY-Xk8{BUbiku2GIKE&EV*a$c+1y$rKQ zH7c-&iorFI@kP0m>sA_nf1dl|ljwKQM#qJiuf3#o9daCOLB>1Tf?#B=%sO&Qc7v0L zeV6Ma{)wv9F2W%d$&s%UN(akL32jR67}&Scaodl{$WqH@;Y9WWN7S3_t5LeAj;(LcoB~3vn~Wd4W-sK+6X4=XYIK3hitjVe$?bKTm_BT9y3uhrpnNp!;$Z!V z8o)v*`&a?Nmg}d7JRXfuKWd01ChMRxz#g!^s2_>i(JZdaOlPDDIofZI`Al0^9m9sT z+gfD$V{+vzEoJKzKiJisqBI)#T>Jzr6Yd)I-s#k>?71@%GxCO#kobg5vpy%5+Wa6r zKrKYOR_V<`3a8Kq=+jYef_VX| zE6bi?A^{|?c7)v5J1HSCw0NiJFo#(#x9nOBqRq-39Y|x1>$|*p%+W$lfE3<;n2MfL z;jzQi&CS$-!LFI}#kkd@u(tM$%3`f)?wrxty?{Ot%`M=@jym_@QNFEjXmIGV1g&Ul zllv3xu=&O%yZP?~schU`{&!P%j2@>y*>Gv&zLAIqQvk8#DZL>%1BQ*X*GJ0);zTDG z^qBsq}i`^+x&o5CTi)ae=LUy%U2 z420=VkYb}?LgRR>G3+2&cJf$c!R|L#3=dTun(sR7UEtz z&T@9kUEfYys=et97~GZRmV3)q<|;J*T&?{0gfUlXtS3Bp{6;{$h=v(t$IzoG}h}gc5`H5CJeHz9*5{(zNopq7c>ZM3g}2qnwzYxbZyoGG?f>~O zf2v|Tvc)!^nzS^7=B1G(UZM_jT18NSEYI-m&rX{aP2`&+Vpisp`#J)a!{SktGSoex zF_T!1!5Fb!gqJQi)q<4Lwo-kuzQ!1>3w8hApKchH8~soj*^upxp_6paMZ3K{^ZgR3 z{_Z7DUCs~&KCP09isf@CV-ch;COaI5f)5q5E3vY*v%|kV;9<{AxY%SjUETxh0tdcy zg?Pj$HMpga*JH;emvFr~Y{Hl^7o2UgJR&6K$UgB&biO&!YIm41OZGnQ5(-|L?V6}NQ##4EAcd@xA&$3*z zDjOOucp(D0ny06~-+ldho)5eK`pDp3B6V}rN)w-y^x@&i%!g{{_|smfo_T-t9G!%P z$bipF>TWWCSOq$6@&aDLpe;8LIj|HEKAeuW7)3xRxJ%g*)0z*h#U5-4asFWntyOPE z8xLh|(Kl60v6753x9U5Njktm(nQ@G`Y3umBAJ5}?nJz?TH``X2+Ql}(lXm`B^OkG_ z=Ywt{V>*@En6Jc`|HBrR{UU;soX;er{Jmm)Tw1s|S#faYdSg4gg2D#^kReL>>F;oN z3a_E_!Mxy7n+wU?w*;4aFS4=!ge3uAxgp_L`B;glT?Yp)9djy%jn75fI^}JN_YRU8~x{x5)M~p|MrPW8}zEE{M=S1k5 zy0uwWb+tY?Q&wDD-W#YG7GGHj`q^+I(dRZ6_xybjRAfk;0*IBstc_<#eo#xqx3_kk~!T#fMpR z7E{5|)3Z&`{TZUs{7Iwza?Eu7Fd-~fo!=si3kWO&w9)uGoh1?yw1dgvT{>6`3nZtH zGy5YgsErOb%RWbB6ck|Ex4648KS{=kwmWwAsRrGer|%mpsU_Wc@&UIukok)?)GjQ; zoPKeMI0lO-3lk+idSJ25p!yY(u<-@Pdm7K49Zo`RoqP%rtZ|OKI-ikeSyJxrMp`O& z((^7VVbqGXJr)E15_b8V@;r}I_H+9qtl^W-y$tbDM-JJJ%9K@4hd0QbA5uylQagIy9ucCvvZ%f zUeQW>&?<&T34P|Qw@XEwSo9W~xqqc^vUJZ>)$cTwt zHQsY$gZ)=`c+iNxz)vy{_QuamBz8T^}Cy*(q(*H$1V1bShkwjlx{Z23y=J`FeIv+D}&;9i>p2J zN~|FQtBQnFE0zi&4f7lrf&bA1Y%f!kG)9RpA2hHe3}z11e%6=NX?Y)a{6J&u?ra=^ zo~(7FlxuBdWo1o%%w(g4IExbtg5C0)nKwEBW)nc)gvQv8_SGlv)uV}_NgK7vd9NI9 zO9biG_a62|sIVyW#${nRr7w40teiIvGvU15+AkwW+@MA6RzTI+iZG1C$F(Nogc#VT z%ykbn73%u7eLQU=?1qxILm9?z*J&f#d``3}fd%(zV-VRARaTaq_OI5ULG9F@$bm8% zay7WS&$s*X-(3$0;h;zauk0oCDfr*x&c-Gt9gsl;uoW8|a6sQdb+66n-Dj!H^GYww zEe6WA@>5%kRg(|gj{ITRa!-ih{}NGeLXsh6X>s->Jk;omS;~F3T_ICysE(OfLDwiT zIPX-^)uDUnZC(<=zo{ar|_}-YxC*GrMXuI z)GS;VEHErz=9XBVVKKeIc&hvUtE`-(BVTD5L)xn^MVRs|~pA z&gJwR{p!Wid3{-}f^6%fFo(dQTNoN5!e~WU09!%h;w2KHa`Q4RMc0lq^yj|OT51_8jkaPW9#8myLAiu1V$FsGO4lawRhtyP&2YO2?-rl znpq#}vGAX*J-bBim(cU?elnwN!0BL@TRS&HBAf)>b_Vhc5qFu0X7{fDdWlYgA8ng2GYi%$(DTnH2uS}XNPA~IYK`=!(4#o5#r7V%)gvvyDo*l`& z@xbswnWXOBK5>X@6*ib@UK;{LcW>ZBJDhnzofV8~6nI}a!rv+`v$H`u5`HG|$1M^p zyRL*Bj^KrRJ%(!#AC%f*Bz24at;D|C+qA~IyS`Ax?!u8p&ZTcQG|YgzQ>?aDWk*G+ z&wlZcznE0vBsGuKf0HfJDCP6!SB_X2QR``>r+C}WiZmXm)0yJ+NaY*pmppbHzh5`? ztD*7jTnUr*y?#G;RCRLuueHW~-=nPz;csBVWI37@OvF+*QKrYxK4(AEAA4z$FZl>- z@)77ow?z8p-V1hp=LRl8ev*oOx2y4}`1jw34!eTZJ}{}AqZS+OR}N&`#L3UL0uF#q9|$1vfD$f+4|}q> z8gSX;s4{)q(Tw*K+=gBqyyOV-_0n-Q~$e{wpIIJH1+Tn;9% zM#=D3m)Kd~liAr!=~!HBD^mUhd40|FObZqpZs?=JVASj;xO3~_uSj=9N@hNLK-+Be z8}y#BS>`*Z&S=L~f(rRu|C%UNmGmD0k4P&r_ys->;EiSL^?s<1#npyj-j$tYW5n~l z?<1zYd1n~!eF}BcNUT^gki-Gu$Oqb*$NZK#tS4+6dm?|hd*t077 z0JhEICx`NM_1iUZ{klQEW`SS3vuB4r|twS2UbU*_GSih%YbYA6B^GFh%@7U*7qb+f>Kwx{e~R1tA*c$4!%i}P~$W5 zC(kL@O)cqdD%e;y6-dOh0e?lNxdDx4>4-Ez^Y47j|2xyX=p|5|xd^EJ!*(;AC5ev= zV{|?8oBtjVh4~vV4z*kB`eLH1asdQHL{1D1kO`-}yzUj-XC6aadfjEdu3XqSD}BFk zD73V+zFVHYeHByE@b?GVjejgxF{#(qD|Pt_t*)J;<<=W8?Sn>u_FnB+KDviP447F4 zVG)47LY>_;Jy}TD?HzSJ4=|FlF|sJ`{5r*isiwC;q!ao6Qjuq5Nb$o5HEv%LFF$UQ zKJ%mLThJKae_@vf@fvtm2-xqTLSIu_pu-lh1$0r|Y}PH7Cmh!Gl}3%iDytY2Qfu@k z*zUhmga7~XmJiK*aEPn=ql*mjhECMlY9Fd37AkS`*B2u+I^Q=>@(Wuif`~%s^)3ab zaZmdnrDSX0GIHblULABdpOU!q1Evkqc9M*^sEl!oo?is5j-cXMrxm1dxPfdc-T&-M1huX9Rak8-Wss<(#`%N>iXu|Iltf8AhJ?f2g+hyK?k2SC>(InCy- zI(P1ZhVU@>l=}w2T#)n}AFN_6}_(XHYn~b*tK&{NOe=uXw z_PrEJd@3z3`oy)sN-g7#ilN^2S0Gfb8SSLr7GtY_?+(%!B))k8_qKlxs}R6$Y(rJz zp$)FA!PqQRGjh6qMyTOFmjiUuC zp$-iWP9JCDhaFw7*O@;q68s4)h+;tN%04qB=fCdR3fE~Ie4nh;+5 zfoYk-_v+=8DrY9Gh5dHiPr0EKGW2?^D^B#NPq*&x0M;7q#^-kgl(aw1o!Ukd5+}if zlNh{ghZN{&e+~R}C8adRV8KoTND*SpDM+yvwV18~`5jSDzLwz|OxWPcmsEQLHNZy; zcy@^moE!!QQznR%@8)=6&LBSirZ(mdF#4f>V?W&lSzN>YFc0}aweG4in$4R zCMYzNL}h9Ft_9z=8(YrI0TB{Hub*L?G`%G7(4&{{H)#*px{h~S;4HXarx(E--9>K#i2+7 zJ}2;%1-t9}C=WpVP&mvBXYXQ%Zm|^(WsyEeUB!mGNPuBWxjQD~ zx#HI>each;==bk_%~(BoU-*XbcGTz!gFZQ$fe*?!w0zvrO27Q=uY4M|+}dF>O9qQ- z)ahFhTsFDbk(@Pkbo-SwRa=g>P8X6%ZQrohJ1+t{Q2g(&bgCxCv<&s8zJ{Wp!NG6I z%iq;ROlVh$+8j*=_cIsCQ`dMJ;D~G>1|-q)NIo^yzhsDvjQ$kL0|@zC?0oiI@z&Hk zNnEo^do7o+O1Yff>a$>-k0p)2w6f7i?nEhxw=b}ANZ0*luWL*TurkxJK`G-|;JQxOWS z8n88xcXxj_M<^(Zjr@Ql`>^Cf3fH)yZL+jZu#mC8;h=lS6rHn?2QpYOpScUrN_|Yb zGf2(gy${nn%Z1GpYUFA$h}f3%dE2ADv6{z*izue@MnX_9F#HV*&FO6CFOk0c70N9k zuKxZNGU@rUrDpA(V{>4{!Q-t6x5iTUQ*%}@7y>ThTN*|7e5UtKnP(o005>7X&h!ho ztT>(7oGPljr@Rf%8_M8;+ld>!etx3Eh;M+KLb;s(TGxBBH=*dap$uMXU65EYNS)=_ z%+L^>`C=itY7D*N@o*s5ngJQmV+efg3)mhc+uGuRFB2IBS-#0qjJ3Y>epmID^+VLmk0E6 zLBa)5yVM~&!)3svRFURtAQLuRCw1minrC@8W++%={H zu&Tp`QYv_APnj- zDs-Uw4vyUV#9d@yJpDI&W3)$Go6?k3R5=cCcn2BSS;lDXeAvTixa~PayxVlN!BUB( zDl6M^CxujN@MXQN`UMtRXqjiKi1}UI_xupb-ClMDZFnGO-joWuoS3t|CC?pqKutDNKF+ zncwY<g9)J+5dJL_6dM&6vwbq_XBbk;d*C_3rx zyflyH{H)DVq;suOS>c1`*5AMR1qB5Qzk~WH5F#qzBVU673x@nI6AruvZM!t$wdUrnU<T1k0@MrqyW&vBSt1#?Oi|xT` zCxL+h%Wz(W<*}OehupOG7SjxpJMzdS$T#c7`{MT+9?i;JM2OLU5y;3>Z3EFVm9<&(Fm0gwUJjU)& za(>PWTfTdyktRR|%Fu*j5vL7GkTq~;{fARD0=9Ph0-ydGNk_)wNl>=LCuIeZIdwWD zrQ_j1tf#w?)4!)EGejomDs@#o?k#jqn54M`gM%4V_zO5#FK^#=IIW6NN{Oo*Gg!$9rmdlTTTFzDfmD-`Z4;0KGBQo8~!=+_?I7Z5v<1<>vaShpPNK_EMWaiHQ5# z7P*(cx%ekdPaVgN4{dE3xZ;0A$IAQ(s-Nzt?q}aCzbqoh%{8Y3Hm%Luk6XwoR)2wX zfb}?*K$oK;kK98KvA-iD-5?VuQyEs?Crb)|y(2M@14<6t!*yk<|=vG%zU1Kx61HH~4h%h!R2 zl_3CX=DsM*D#t}juN`Y@X$dop&%H9ajl0iGNeR@HStzLTR#c>$zx;0w_uoDa28pml{eNsqgHVPT(v=ZBBacomu)mlYfxJ0|iq8(sf+v&kJDgB$6; z+uG`OHM5UJDVxH;M^BJZ*oW1*)ti{%&j~2wZX#U{Jl$on8mTmi zMQwpj1hjJA%4oJDqV+<)mvhb6oe0(eD&(x&jt|29viMEx>aMWWr6`z~1D>tz3ZGaC z(jsj_Q%ct*i0BTVI+Z=ynF;!riDJgve%}Pyn(mpq?~vEl)?6+SYc#lBjic{@%b;LI z{MJXV_`Yjlol`*nuc*m31kzBSL%af&)&jOsws;L4E1~tP#I-!Cs>+LR$K5{M48-49 zpZ7O=JU*k>eOtC*7i=*9U5jAfI(?>n%y!-P*o18~rxhN33=2OcVK0MED~d4-Q4^yr z^sF4=6OzSF5Q`5qcCEW&GoJXX`_R42mC*r-O*{k#*rlzxF!5LUXQg)g6VZua&W%xuI*b7C}<9V>crMWvrV(6&`_+1Ld-$KST^%iiEw^5+O*u$byYz&C1v4CLvxt$Gm&7A%PAoW;Xiw(aPOApY z`UE&D?}E0D+Wi*E=?nl=&Y@PjxzuL{RsN`5g_<7XS@h-a>fZf(Cv|)c!3Mn9pma?jDAUoEO~nXyT`2Axd?)gChJ^RgzmQE-M; zd#~VkXkO-fng6j*OYKTsZU(eIUL2V>PPlt~Ap=Tw!Sc;>CsE>cRi#qNv-N5g1vF%(trEHTX{xuzL)pIG%_%=DXxgOx zVQ#w3M3KQ$I?SS^-;6`I;$1Mt%-dou81>e`YsJMCR!%@u2cU+A#^W#=LJ|l-9-NeT z_NirPd-C!zzWCX{ON@L}JWz74f}{e+T=-~`sg zKVmaTdf*}-Her3Sut$=I3t7{jnx@`ZvbR&}H>bJLr-^z|RU!;$(t(@(pjQm?Jq)Js(uxz5JGKSlxdzJ z0hJZ&R1H0StfGSHt(s?2eRg#EUE54TG-TmnKNnbQm{X^NE%)^Y9V2x7ZKG7uj@wX# za&Oe!MT3p2KfSxd$e5`=3x4Mpe=3bwlH~2}V!LAbiVTCGg=N&g->1sNU1=o2(flvSRjVHR_$yz>s%&bQW6W}kI4GbJ|a&f7Q zK73}%{!8dWypSmnAf%BkMKb=s^n*DiR@M_nun9vv#-4=5i@F(pK(jSy(Sx+Dohl-h z*;nnN{aCs@hf?7Tg_gf+d<>+18bNl-yJdy=oyp{moOoJ(4@6EOEpa!ge_#46xjzmG z5dupu?q1N0R|3m&EqZ^CZ)c3KTYXP_Z za;2dnjgKS$`vhHsIC1?Nu27J&^?8KBse3%1h0w~=hA2*Mhr5^rzb?SoZ6JSfb2LrH zaLlZ%tZd|dt5Y`H08pC$?@HhmDu2a6NVwLV)BJe6xZe)P-d?$Fu)8G+qXGoe3PMQ~ zsFyl_YMTS=T=~-qyCf=HH18|(_IQ{R5-Bv^>n+pVbR+TOw%DCX2 zEz@N(EhBdCVZ)c+z50LUE{G`tQXeFH*~GOByiGq7Eg-A3jx`(%QNaFy0CJL=nQUS9 zTY#UJw_j|PzH8}L;`z%xsyJx|`XQt?x&G)?mC1RfNkef-$&`Hg?&EG2)NBNCyuv&4 zqFKe)%If3=d{2;^^cYC^*aU*?jHPjMw1ca~>zAU*e9q{bx!EHJkM# zD8Hwt(Z`YLo7vj$6BsO1)7IH;zjx43^K)VCDjjjc{f!DcIf3w*w1m9Ml$lJw`U)zOCarDe57I3c#&JX3@;c+qfw=i}Mx zN!{uLt}OC#?DSmrre7UqeRn+@4ZH33;@rxeiB~zlr&~fkrXp|j9xf>OL29$Dl&=2S~6gRJwQEH3sbxur&07sMhEzN?jQH*~~ZF z?#wkt6^z<_M0k!UK=gsgyC5Ysbu&>@rW=EytxEmYRVue;JviFSYSVYV?%3|lT%+c_ zo*kOpl?VSdu_zTDv-x>D6mRm&avR%_LHjXTiWD|Eg z!JO@EB}!y}r94J&Q@yARrS%C#?EI9eOewpU{(y=OyIo)o1{p8&-debk#rR%?R|a$JPv2HK1-jtPrMs!rovkAoSHG^9E|Zsvt`4;nchen zuHI0$Y@exmcj--9T2g`1Jx=?p|IiJ$JTW%zA4NHv5-~m^rQg1{xw$4T$WkwU`;ym2 zwcH6aZC_vM8_8@6q80O33{X)-S)KoL=Tnyw8a-zm%(+e`?tjOFxN6GQZ{#sOjxYLl zsV#hQ!@elc#}znLyjzusA>Gj@97_R+9k|f5vR`z?G4%+5Fe2MM!`gU$aPucsG{hgD z^YWJDYTfIQd$aoS_D}yby3Sde|GjzfB0@vJFXye$<6+V_TxSUxkWJO}uU3nzMQEQc-*kL|k^ zMi2=>M#$Mfe4!dT;(O~Oub-VDyJkjdu&0j?dqSd5*XFB`DKdhvDV)}xO&Sf)w!0?Q z?2l=)+$4&%DrS>kZS>o`(y{LtKs4tO6e!2MoA1LqC z$h{|c0>Q-9Mwlu8`QmPDH?mHkQp?QvL&DWZk$Tz)l#@Tv%$e=>1-Y~HZMP(#gBzr5 zuDpAZTd%k8&o=Xtd>cH>)k{Ar;qmF>ni`TDhqR;BMqYRa;*fpqwi5jAS02Un;dv65U_Sy>7+nqv%!GgE>~wb~t;Zd+RyD}N*Y4)ULw*hJb5Hora* zd8~=C_L-10XT+zI3gz;@_^(xE3?U@$gPIK^wx9L{HIXxq9^u#S=XPrJ{A^0uxT;{D z&TJ>fL<8?wem?)+0rGT@HWIY?1TjU;veA1n3ZP^rE@>JCq;*gAn=ihr3w{k?GKEOZ zyamjcI{Y!vZn+A?U;>0? zgn3Cpv;TcjGcwO;PGb!r`@g3)hX$OJD!I5|=~kK8i9TZGduvD01Y_X!T(6qW{0@nZ zZm@)~{f9Du&kdoQG*!$%&`P;sf+S6wS%H#EQ1#R$xi1PLI`nRzP_y+pE@_*w|Np8} zpw3P8q{o%3K+_W~Ph;F~Y@bwoWV0lFAv149{!W6)3;uua$76bSW__oIgi`i>E!D%a zk5bbInyv&in}@oOFX#t{j`AC4pWXeFHU7VaMS)+q2D~RTE^dAb7m+h7f~<)_rW+&i z>10YXsb+3R5p@de|680sv&-GV51juRl)q7{bmKE)%cW!hRbtVwoPqZbK33M?U!Vf> zzn8@_%~D+zn0(7Gd<9|+p<72KmU3dXw~xI347sQL34~1hf3sG_0lNU6w2iB5XCHn6*rz^h=hCzE|Z5BRdzpfuc(O*XEG_x5oKQ4jhUq zdsr9TGyi>m+uPtJUr*&sI&-~>@xvjx=SPq6%Fjxz-}%NLoLJg^+?MTT0N(v)`sB%v z+5cR&Z~Ha>-H+$jrv3+(3yXIA$a8pR53&AmC_}TA=!Wt?Z;QXYwmz}qx4h3~c}rCR zU8RKMlT^D)uhly<16Rm{(pE)wL)X>vJn`g@i&8fnuZ*()yxr*k;=5JS2VQ>#?u<0H zn!X^AlR+HVKL-Vd(FbYo|6jj;y|MMRH)wr++9yBL#pUdp41PD>>iNvGiDa!``78YV zxq1->Cl1Aj+6>18_fDF$8+gA?^X;h%fU5USm(RH!KmByKZS}WJkL1BlaG&`XxSQV& zw3fNhYO#F^gfdi4CP^mEWK_&-CD4+@^oNu@M_irA>5#`I#BL&sS%wat>U~t z&P^HEqiN<8UiKn#&-#!4Io_uK?=tc>x-iIic={gSSuFl#=l^BL|49I^%K!zI(vR1Z z_V)s3FjuY4`T$($8_IB=L+R!DEG`vo20n|}xILD|W~)}Ms_cX)4`%4u^}kn%ftPnj z#X}=C-+6qy4@+S>Y<@cFy#;q5gbOJcl=PqSd`@;}88NTy2Bw2l9 z3W#rB8@+uI@MIUq>3_DeIBer>)L;(7lK`Ae0OgZ-#tDH@QC)N9Y@aaU!d-!e1;71rt>=+xLg(zS&H8OpFVvG ztOPlQgqObTcjjGgcUu0;gtCLdz}ePIyHl%N9og$);do!P0od+NdUzmvv4FO#rxdaM1t& literal 0 HcmV?d00001 diff --git a/Android/Level4/app/src/main/java/re/pwnme/MainActivity.java b/Android/Level4/app/src/main/java/re/pwnme/MainActivity.java new file mode 100644 index 0000000..37ae3d6 --- /dev/null +++ b/Android/Level4/app/src/main/java/re/pwnme/MainActivity.java @@ -0,0 +1,138 @@ +package re.pwnme; + +import android.content.pm.ActivityInfo; +import android.graphics.Color; +import android.os.Bundle; + +import androidx.appcompat.app.AppCompatActivity; +import android.widget.Button; +import android.view.View; +import android.widget.TextView; +import android.widget.Toast; + +import java.lang.NullPointerException; + +import com.scottyab.rootbeer.RootBeer; + + +public class MainActivity extends AppCompatActivity { + + // Used to load the 'native-lib' library on application startup. + static { + System.loadLibrary("native-lib"); + } + + private String pincode; + private String amount; + private byte rt; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); + setContentView(R.layout.activity_main); + + rt = (byte) 0xf0; + RootBeer rb = new RootBeer(getApplicationContext()); + if (rb.isRooted() || rb.canLoadNativeLibrary() && rb.checkForRootNative()) { + int a = 1337 / 0; + rt |= 0x0f; + } + generateR2coin(); + } + + private void generateR2coin() { + final Button pay = (Button) findViewById(R.id.pay); + pay.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (pay != null) { + TextView r2coin_token = (TextView) findViewById(R.id.r2coin_token); + if (filledInputData()) { + try { + if (pincode.length() != 4) { + Toast.makeText(getApplicationContext(), + "PIN code must be 4 digits long...", + Toast.LENGTH_SHORT).show(); + return; + } + pincode = String.format("%08d", Integer.parseInt(pincode)); + if (amount.length() <= 8) { + amount = String.format("%08d", Integer.parseInt(amount)); + } else { + Toast.makeText(getApplicationContext(), + "Enormous amount to tokenize r2coins.\n" + + "Radare2 is a non-profit organization :)", + Toast.LENGTH_SHORT).show(); + return; + } + } catch (Exception e) { + Toast.makeText(getApplicationContext(), + "Enter PIN code/amount as numeric...", + Toast.LENGTH_SHORT).show(); + return; + } + + byte[] inBuff = (pincode + amount).getBytes(); + + + RootBeer rb = new RootBeer(getApplicationContext()); + if (rb.isRooted() || + rb.canLoadNativeLibrary() && rb.checkForRootNative()) { + rt |= 0x0f; + NullPointerException np = new NullPointerException(); + np.notify(); + } + + Toast.makeText(getApplicationContext(), + "Tokenizing your r2coin...", + Toast.LENGTH_SHORT).show(); + + // wbaes_ecb_128_encrypt + byte[] out = gXftm3iswpkVgBNDUp(inBuff, rt); + + byte ret = out[0]; + if (ret == 0x51) + r2coin_token.setTextColor(Color.RED); + else + r2coin_token.setTextColor(Color.parseColor("#10b010")); + + r2coin_token.setText("r2c-" + byteArrayToHex(out, 1)); + + } else { + String empty = String.format("%032d", 0); + r2coin_token.setTextColor(Color.RED); + r2coin_token.setText("r2c-" + empty); + } + } + } + }); + + } + + private boolean filledInputData() { + TextView tv_pincode = findViewById(R.id.pincode); + TextView tv_amount = findViewById(R.id.amount); + pincode = tv_pincode.getText().toString(); + amount = tv_amount.getText().toString(); + + if (pincode.equals("") || amount.equals("")) { + Toast.makeText(getApplicationContext(), + "Enter PIN code/amount...", Toast.LENGTH_SHORT).show(); + return false; + } + return true; + } + + public static String byteArrayToHex(byte[] a, int offset) { + StringBuilder sb = new StringBuilder(a.length * 2); + for (int i = offset; i < a.length; i++) + sb.append(String.format("%02x", a[i])); + return sb.toString(); + } + + /** + * Perform an AES 128 encryption via Whitebox in native + */ + public native byte[] gXftm3iswpkVgBNDUp(byte[] inBuff, byte rt); // wbaes_ecb_128_encrypt +} diff --git a/Android/Level4/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/Android/Level4/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..1f6bb29 --- /dev/null +++ b/Android/Level4/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/Android/Level4/app/src/main/res/drawable/btn_background.xml b/Android/Level4/app/src/main/res/drawable/btn_background.xml new file mode 100644 index 0000000..5ee059a --- /dev/null +++ b/Android/Level4/app/src/main/res/drawable/btn_background.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/Android/Level4/app/src/main/res/drawable/ic_launcher_background.xml b/Android/Level4/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..ca3826a --- /dev/null +++ b/Android/Level4/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Android/Level4/app/src/main/res/drawable/r2card.jpg b/Android/Level4/app/src/main/res/drawable/r2card.jpg new file mode 100644 index 0000000000000000000000000000000000000000..563dcb170ca2dd0dcd52ed0a2afdf91ff427a5ec GIT binary patch literal 33270 zcmeFZ2UJttx-J|C(l^#MeoPuUsLfzD5qYPEP}6pr@guV`S!HVZ6n` zL`TOec$ecI4?jOYltoxvh*yk@kDvE!5`s&YE)icLzCl8AgZC!gP2T_IpVN8}*~N1p z!YhOXw?OB}2nfjtPMbkc5Qu;Xc-pfE{>Kl&Il}Wq7r+-UUA_W*p!6!}904KWx$}fX zMCZ=~pY{gELFdVcuHEF3yg;sM0>0&No%c<6@d}@O%62z5j=R zz=+6CQPDA zh?tN7*gQfq5DavPWlec~`TwBnT6ET$NLhU9*w=Uk{8Tq-f_ZcD1)q$Hpq>zht8Y4W zzk6qY6ANOOu^TG$!_ZjW=l?pgr=YNtiJ7#hzUO9a;IbdiBz5#sVB8JXa?h>pfs)?T zn7+9c1Jm_1N-cH2f#4@|!?UcNqNzz~2qAP#^E#5)Ey=RX2TBuk#jL`LWX7L1h#2$) z>(b-V2BmQ^p4(PG1=YLA_24^{9x55$in`lj$TY%=U@{JIl{&HTd)ane9$vneiD>P^ z`CJn+K#`q!Vf%z zZ;u#tdWWf})YN#{_aTFt>X@O5a^0|<+oE`?SN^A<2T-!G{8%`;Q`me&JnonwUfMko z$F+F{|JsNNc(B{2pt)7}?5h>n9ub-fPr!W&qEd`Hpkl6Oh>>-2v9ce)Fjb*C-t`SnxKuMybnD~u=pjmRkoPXNKQh3dW{ zm47A97PxDSF|1=a1tlpXPeHGxPC;E&87R%WD0Co-o z|8u=xPeE6Z4}fI~et>UZf@7+Flhgn!g6~X(N$_6UW*Fu?5@!hAt}cOK3EhBg1;w0# zf>NUn&LqVfxT}IOtb&{ncu50-QalB<^Z|30O9FFpe?b0YPLrMA_8s21*$ZE}GRKWO zXN>0x`};rsw(Wo#W#YId!T8s8xBj7UD`(r5bPDRFYBv7$G=HknfB%#Tw_u9DtO5y$ zh#O1b7WTV{!hebAe&8-Q#t=(&0;-Yyi-@Wp0wSXNa0>cOM$j{58n8t0p2|MxNS4;TbIW+V)GX$({6Y>``U0IBIdf>F-VN0=O3_RLj zCjpfCm#uS?0or`+6ohtm{Qk{T_(1%(haH3d{b2zM_{+ooh74b&-DCcK%fCN8UC{ca%p|D{@g16*15 z4GF;b*kgr%1E0T|#+ji)vF9*BziS}?&c%NLzYTahi!to5L z${XDIg7$0}3&uaH@>?BX2*`S50-km_lAW_DEvxk1Axao_TYlH7CHI-Pyf^SsNuT(2 z)dxg>yGUBxr<=Jy*v%fHr23db=k=q-H+s5WeSn9cCk~98(XTy^1Nx_?xFwPih6RKf0>o zcU@u^eiDvq|IFG0IcNtQFPl@6XvJzZr1End>Xm_iqP_ZJBMZEIn!@f<-qiM%`2EQdP%x{)o&0 zuHuMW&z^n6iqK_4{plTA^iwjP1V?8$rC-XGXZSt?p+*EdTQMh4ln-u9chr`vHFmiz?3yvyD#9l&t z!NE>Jw@zYC94Q9gVZN-GPd7i0x~^)t{EcFD`aJMoiSY6LHoU))sZsp43SR#31Ze6Dh7YE(7i@S-n@&L_^f$O?l2QWM zo$^>y0zv~G3oV4@Qm2G{uxh4JYhY>Kyc>6P* z`DgiV>xV_MH^C2O)q4XEeh4aj>*p9AP%856p7fACZz78d&77)ad-h_JybBSw7?tF; zb_yDMk{n@2YSSkp%qySKdEHxiDt?XDR=FG9W#644EyNR->$k_qAQ829Anu+AC3BOK zM2lA%>MOs0PPkY>XjX`|b!cxxF{BjhWV`T$ny7jyN;T$OvEoK_EvxkI>#xjwYGIBp zn|k&hbWKRy9nA1nV=VoX2l3*jfTy?3Lo2V(`xlwDEunF;_oo(|ef-h$eLjF$wUZm4 zg1*%xV%gY+)8VeMEJ`mdehy|QyjahX;p2W^BS{mwnejcWhk|fT{?f@wK91RCmt*k; z7FW7YbcY?9|9DaNo%&)lnl#!U;_?kJQCi5-UD*%Ley1SrZ9EIKzbbP%xm>TSDQZPD(Imn~QEIy_ zz)QDG>3)~a>SoXQ)~76!bvkc-#Q7Ph-aa=mj;Gg4oXw~!EPE};@1VMiM+)C~GPs-x z_gKmfP@EOAF`cEqnJcD7JDP^1+!>kBXCDukw|UFjfAd+gZ+Ltr`22p`@~bLnKog$p zGazg+W9)ssq;+8bQNX`o!^H&5M~)M z8y@zb>ACKfY8I{!H?{f!NLD-hc$guZ3XCKwOc;t=YrUdns!euTaq9W)$<5MW&!5jV zz)8ZltBDCZV2=l1p`3nrI@vmyI#@6hkbZy1wjjiOEzQg!6tZeGKO5%n0e(06GUW|I zfZ-5jCeH;Q-H6ApKttRuf&mN8#zdZs8=qWbzoG3EUq$z+Fd|o1`o;4;X^KG)=37#b z4`PD%gzo0)?TEZKAjHsMt?P`C&mvbN;636plm0Vvb;(;sJ}mQMk3CLSN>rtt;()dO zfy6}g7WfAq{wJRDfJcozifNkO;U0yfxY3A=(!?WzHR%2(3*Oge$ru7}N1g$Y|9(Ln zcXN*v7oLfKB_(i6{53)u!*U8@KE_WM!1hFTY4&=2A7|DRC%<8b+utBf`q>SsyNFv4 zqbL&V`feG=5<=?3jtLtRRXqiLEY=-Lp0^*KrW6>8*MpTxzc^TII47;sSg0OqFGcIHGH1UA$F%_qC=X%biH;WG#PCv18`& z(Y>0DrSrqms8~ERs~z@4yy18@P(ze7{;)#TlswM$`I9a2Z@++L_IXJa@^uMD z*MF>J@tCC1RV&z*8e1@s=&_mG?pnFasXH3|E|Ih{>!G($JZ_8e`?smI?MA(H9~7NC8Vh)={2vb>d^UWhu}<3LE%kJ z$o+LETz_pujomy17s^0?3PR{7E=8qthtL8a2qF(l2{bE~J^x(Z&@|ZPIU|8ldjC-3 z!!fPU9)PhtOn&k515W~vEl26 zQ}^x;b%;bHZ0xMfv1$730t!~lBgQ`Gii_eo1wC~`?!74OK}n)T@d|%p#(E#%6NwM+ z!5So`r5&7z(q!}l)cB#z%>)>aM3Wy@mOeMo+(Gx{Gse9ARP2u6b!y4}c@Fz8A>els zrD+S_Kpi*LK_;r3p(r-(#m4ma#YO%nxdgJn`V&JxSrKxF!6#4Wt~|$YP5|}})x$>A>7bPP zdnbo2!|)QN`{M2xL@?S3G8ZI$U0b;Ex~eqj_e*scws7f>ki|><6vTLi8@mAe0-y~1 z=p5kx{t?Zb4V^_ZPWX%}dnCCyaWy7*00=&64$g(JYYx^x^U8`-?}jroZI)5rL*><=C&4e}sU!?L&0eo~`i08CZe1kTb~Z~Z2zwSUHyFnMFpxEeL~$@GA(YyQCSIE`_dv z&3n8HUi*r7vv*k*czkwYaj9(4C%PQ=#j;1c64NwOVR~m;Jp!vT`@Vln_Br-ilF##+ z>1I6JAkM+*YE}7t5i!V;w3z|*9h1Ivrq^I|dhBxklax>QI=MDtbuKpS%1^MP@YmoS z9KFbOAkbZDMKB_aF+eqhxfn?B3VcYpc^=bo$?&q}f*fSQ*o*o~t~! zLgQ}p%zo_MuxYumVa-dp$|r|5g*_xG?si|vsM@YxcxkPqJBeeG6!j_S8CT-ru!;|R zK(CnRoE-);aRQ391Zwoso4LZp5yKE$HC}O5o=VJ55JQ^gR*;@|T{4=7DPHA!T61S- zi|)nP$5*|ryZzBD&9N6oTpo%1Ot>f3(r73Hla6G-u!!4aaHVAa-0-*>Xjk;h~7P%11efV)l zqE?*5E_Aez`FGBRyn;FROaoW}#L7VC<0bk#R+R2d0rf>j{ZkP3@VA7C#UH+4Tm$uEtb#Kxw2f~}9;7#h&Lo6&G#sutO0p!d>o8cwF*T&^+DsQi+6%g zQ0gNLBEiS!E;7{41NhoDYpJa~pvhIb9(B?M{@IA!?N^be_lI|dF_f2wKac(S)3s`l zOQ*J_E73y+@Ar-H28dWo$eew(u;X=zvQ68wA3z$|_U(5F{;zzcSU&|_f-gi{!uDHE zL3^g!AGHy<+ozxi-DEh53h*Q$25xo!F<-nR%K$77-f2eAVgT2|k z-3mRT69abCs2ui#ZPm*XP#T>$Z>_3t<<+eHnOjW4p&GXhFA5Xs(1p5Vhho_Wt;DJK zt_4O1Pxj((xg|DLo7A!x4WJO8A5JnJybN34b@Z0@$b4U8mxL+c<^SGy@QFI2-=xSA zpXG5PBU|g{qE%VwyV|d%73$V*xfBv8PfdUM8>8R!fOu}Ko7sNoGSQ239s?3_;;frS z)X6w`G>doHSdxIG8T-vR_t8`ntwdH|^%FBQ{ffJsQ3;YLi&t_qSjp)gMp&^C{dnaA2f~ zzr+4YlM8j1>ph-Ox%L&!H|;P3lzuW!2~GO0i2gZbvznrQckW4yoH*)dNBsdyfz8*H z9A{JUA8fN$LlcK^h+DZ7TB-1>95VEk@&3oeXq}TU5T=9^adyW#)96;gO2vupw95y01gX1rl#St#;rm zck0Zxw{SrR#``^3lrq(vMRE+BEY?|7+BKnG!>NZN55nJ_eT}%7ydFAuP`{9H*DU;5 z$b!>b>4~<;*TP~htA?UT!yNb3@e&U;C~uR>M|iC@;PxW>WKE`b`Mn;XaXysqoF|2^ts7PvG=R7Nu>TAtxBc3hAbymqQ|)lFW6Mu2 zGhr)QENMM4P|MS%yUA9x6u#J>F825+{hR)HXR(s2tLUWhM4@NU7m2-)6VM76_#DOa zK=wMGq9XCEhxZJ!02EL0{jbcde$CAmnrnGj_KaC>`Wn-xPag{iI>2IgZ_^ni4VO4tRk(&F9ix^F?<%7Y5)jJw;-TN{)qlgFI?z3^dRPv{TjZ!sTNMSQ+o zeck-5I6{Whl`s-1HXll2shxc3enH=+T3iO=_EVtZ_v2iyiYf7~tbO`yRj?mL7qMvs zuZYQ;^JH7G#nN{oC&^i}+2vOGVF6P&d&{Kqnoi1}3hmAkaD8+b^4a(dedx}N%EoxM zRIvow29HVOoQfb*4}Ek^56r|u-B!aCwgdAyKRFu6x{`mlbq8?dez%&2_&3Q8EX`u} zdlj7o?-#Y=R`Dulh$QtpBIWF=sWqYOX41U*gs92{&fkv5W_ zCEZGCp?r<>`jHvnQmmcd0VQmTgdfslQ{zek@q2K`wb3p|?l}=(p@ub~f*vVMZoU=m zQ#5_%L44Bu=I{qfbLeJUUtMl!Jc(n8mU=36+|ajAYcD+y{O35Cnxl4^ABjAcnSz5cs$3 zYu_CCjM*@$cGm)K2LBTEQmb)W$zJoZjF1 zRUuI!1xk6pN+hSCY(&Ps@e$$F@3G2f+*z!$f0oyj{!yk)|5c{d8iXy-x&Vb0{Ue&g zF#p6IWiLS>Spyoy1V)f7csuVpz5)qUV5TG(;2px-(@@0qNE{j=qq3|&487Uto}Q55O~E@04XhQ z9p~a&yj37rAnTrhcGl^jVYr|evPA0+7(Tm z4P+Va8x*CGqYIO86eV7!c7Apl7nw+M3K|iCoPf0b)}TAYRlnsXNwI(1F9V_4zJ(>& zb(QOXmH%KY3ik<00Y@F;+u1}`l5za6W==tVR{^hQnsydH|GQotXu&__J`8j_H>r+; zaJh?#O zWQ_5z*pu7{y}gT*J1BN zC!pKU07!fB3)23Ycl9=?Xs^2uFPO68;^%{;bLj{;JAc9`ncfy+p1D!I}Op z_=bJJiVT0n|Gi3{ZB0E#EE2SU={iHPpaMFhl^rK&AWNW)@y-)3%~O!^^f6=BnvxA( z0TPH@KRyMSQP4X-!PAJ^!y7)RN>dc}16%V)J?Y==y%{D3FFihe2tM;9iYk~LKYS%( z2N5F%)G}@@E+6|H1!6;c@M1umx*mH9x@m9&5x{WY1oub<034qBzb;2}5V=6@3K#+O zSLYAx4_hz-5?Lo~EEaxNGB=+-aeyz_EJ1!53x0WD;D5J6`DfEm`==dRPx0UG8~4K# zKMZ8e5B-?(XAu5-F#hlIO32cT+~EQ|a0P7drm@=CDX1+Dy8i7a^TSZ=(*G2`3}pd$fuF$(U<+b@+Cp6-;Jc~Me7Ert%@Mo_zQe5xuRJ+(CrrKH zksp2lnM!rf(|o{--v_*S`HsLA6arg_!`R^)07B2X8t9X=4MhPPdUF0>P;Iv5XBZ0) zCdDlSsKwp}w;1oAoPvrj|BG{$AtgHO0K8K`tljE18ipq0ysm1{2Kv>PJL}C!Unc<6 z6E9i*3+mGEXu2J4t_+r1)DSm!mS}Pc#g`U^dGSn;EVqjYXNnT z9nwm`11SL>XbXsw+N;g+v-szA$#sBkd-t3;0$}yqK<%%AD*HsTUo3_E|2^UF|2kTo zQ*^siRUyYYZ*|+LRFwcIQzrI08J7Ato+!KdO&K;>%XQaZ`G(yAuj@!$8?r62Ba?K0 z1&K(G`b-?vz8;E?bLz-Xyyk|-?(AiRJKZjgwZFkdBQ>$x&fvGZcjL#PlRNe#4^lBv=G1oVew<#1V>9={E+Unp@4zj|n;@><158wngg0bBJ%rQMn9oJiV z?%dOP%HVy35I}z-8+WT#4P`v%{^pyw&IMSu0Dq2rN8=-tTn#7Z<=)Ps!m7cS{lnc< zu@=W!6&={fdWPk5RqK%VBDJkFJ8qoU54sPauj_FkPBan-mlW$Op3l|0K-r|#Z@`71 zy%jfcX^*hiILR!V^(^tdtj7Bf0zX{ma<#}DsIwaWG*?i@z?N=p6HCjWn`_mRwpMyVUkvu*VDPyssU)9F zFZ1pQ-y|OpbM%RatD*!ObCW4&a~_%DS3k_}_UsiPWlQ`T@mIB-8v@D2maFgc`qcSt zBZO5x=&cO440Pv{Zj{!wjFyWNv`QX!z&b0B)|Bd${lR4jJ*ECWCMw;XjXw@1OEPCI_g%@ z;Lpd~6NS>xLD!uIk`~BY#oHchiS3)k4Y%>;f5@g%6J>f^SsvRxr|9`%OxRS^kT#16 zw@*jbK9`D6#3ZL>M%w1efIi-PuLhn1-H0XIzIi?9+A zKPY|0nPd_KMCKj%0*bL)uG+o9xT0Ob@W!dB=y&ECn&N4c0ttUcIR^m=> zI;okd)OOBlO4nGL9OgKi%;abR&Q_1Ap~|u3p$#~vVoge1XtB6A0bztkt}4zcdFtAc z8L>|pG%R$rhqo~?YMy^n-|Dt3zKfz*W1vg0)o;}5U$drP3V2&x-^3+%KFpzKUPpM) zSIt{lS1VusZpS2F6PfM^TW}#G!J7Q4;WvzN-bYyfi{inM%{IKKftOl-Db6wL8nfej z(B9LFOcGztRnu$FX{Cy-I1f=45-o`MbHE!*vp4B0Nn^WC|Y$95y<0-_L8|EKPw}vVqA}c zp`lNXjRSsEm8lK$Fz~gibiqI4a&EFE3`EQD=V%>Fb-!3(Pw&TFDX{*S_WhjXm4Ze0 z&&0k$^`Jzb2L;yEhLBe5#39xw&OE?`PxcB$@JknFV!8$Ay%rnQ4)*4if;HADA}F~V zuN}!qgUjtXl_iPBoUgCq%uJaV?7d-nOYFlEcLCJA(1Wk@$NLT~>}7Ry3YyJYE2N9I z7n@{GTE_%fSzJ-%TfTe`MBgC}IxHAN&6;lne2tg6kytPoT!HI=c2|?+((4Ig=v7|I3e19OLnr3r zEDA)`QU%$w$=>GQ-Ieh^52OQ5-_BCmv3@c3+;xYevgqlG?&q0WpC~m zt0Sn2mWuH-doHvluWm5JqQJfsEVWz&| zb)`W(^_teJ9|G}Ru3sG=n<(&L9c9M&~Yo1P6+c%$rCgr|EdYF#1pdZA@vsTDx zqs=Nx!6eL2eJfXV7!nP_*8>r*^PE0E=euncEVmuA$;MK*>EU#Efpu=4%5B}RY9Rh- z(aiSNOOF#owZ$^kNSycrU2OWSeoQUDMVVM^&uiBdzhAT{k&dDmGW^O&mf&MlQ6Nzr zG#x;d_^iZF>9yYHUXI`y3AcJeaj=n+t!j@nVNP{!W-$b#S=EC((E)0>Kn+14at;DE z#=Pnl&CRx*WQKEG94(F`@0Kk`q&qWEqAfnSAg_+=)^@tHaC6;+Iuj>$&3MbDVbZgx zx${c)VH}p`CTlt~K1|@uM%?a)~+e z^#zeQ^c%y1uiHHu)$hz|Dgp=WZ#=eh*lz$qoADIJv$b*BMy$KHpG;f4OM83@@??bH zvay+yKxU0vQ)0c-yQ0yb-{$r4Xg!k$nR!Ee@I!BxStR7*G;@`P4m7$9EoPUp)5pcT zcyBMr@y^}T9CQ^D?wN5ic;`{x6#wc_qrAGLE^7H$VmMS*^eaiirL6&Ez5@f_fN4KY z#f6xSlA4E&b%oH;A#}7IDk&}e{Y#@%vfj&=QA&N`rY0`ghWYt%5dI(S(yea$%rlSz ziBi;v7tc@u$fo)OC)GfVUHelXnaU7ao$6jh%iENP9)RE%*Bd-PUXXAYi{>&(H6GN|W_+>gmI7^x1Rp<**QM@TRbI&sw@ zGW3hMb-FF42`@9Lh_8lA>O_?o&cAX|2R!_6FHSVe&37@SIOO3S!On%ZkFn^E1L}gp zI*LhmVM8@0mcz%7AU&}DY7*Wt$Yr+&e0PYiQfIVjdztO-&-hR*U&TqHv^A*Ix*15O z1IiYxc8NppPcir{^H>82bD z!+ttjr~^_x6=FE(=dC(uWlSpIiHX*a4(+^8eT9(&KT4Q6Cv8}Z(f1}M+T@@Y|4gvR7=fp%r!{|T3HSY8zvVp?r=qxDKNC!E}&PM>ci7;5af0R zci0oTj#H5MI|qTjOHMM&wloR-mnEgIYsP+IUz9~+6MFgmAo4!5+;@_`)p#8;ooQPcj+zjgb6i|Z+fA#&O3HQTW>R(4Z zevSP1XRvyDcLLlI#`*av9#kKfUzm!^NbKRJ5udv&=g9`jDegO8jOkBDIClE6_DeiDnma(CL82nx?h<%eTjnBoI|nE! zitTT8V*KT3D9a@h?(pWh-R#_CVG@!^h+~*64vb~HyOqmyF_~K2?v6Ps!wc9rb)ddk z3&sC1@;1pZwvN1!XKR-5K=7(x(xG^*@H)WAUY8x@|Lj5lx8A0vzW=gK=!e!V#qiuP zTGrz`i0nqU0lX}UA|5y=bY6?@0reBXNoI@PrD`apn~iQYn)76+E|LGE=zDF0t3ImZ z!W%XrjJ}fR$yzTqfGY%?7vj`p2F=oyZjT&7X`&fO2VX5q=-|qU@lms-KRsS-yJa@4 z(LC_!BM3Bb(Qc*Pf%VtaijftRWpTv*7<}0fcM8gF^;kv@Aj+*9-+m&0Jl~)ZBEZ_U z4eIYiV+09`WN(gK za3tW+TE$yPl+@iEXQ zN{&7Sz4cROKdc*KfNdokmCq}Y;G~k0ipF-Er(Q@gE#Fum{7LGQbFX*qe zF&a?IXaLVTQLdf<7DJI4wQSGH88^y>KUIhniiA$FFzvONe27YNG<`lVzhY@UfHAad zT=Q2FG$lNoRU|;g?NMmA@>ru7piZgsWaT`OY)MC>uo0#*Q5W%A_OAU+DlI?5YTeD3 z%Ycd#(gG4Rwcco09U)o!GW5wUo?`3%`9m(!)$GodCAIsq>l>;(F%DK8T# zIHceBp@5h5S5-GGaWv}Q4t~_n^8idBFLc7AGO#iIWYBhF?s!-3DxDeWm!5CbFiAsH zQMGvVMnR7z#`|fN_PYc;{Nu#)=gd#v(m|Sh;WRs6kIRsQTwK#zN=))$k0TuRmMJzE zcq_uBw>8SPabNpvpQ)~RgdH!?pgoqGj(>E`HhBKjgg(jVCPmK~a^vd&LQC(v=Q+`g zAbA!LL4?Xv@%5bE8qR{I{8bdMRV0VJ18wpB3!tZtj*j9s))5LK@tSF$XeyZ0()h)GGE#s?5DY{5-5{vUw0 zk|_^cQ^*hYtGu4}r0~aTMs6xbMPEB36)Wsy0tB-UJD2y{dbJ|$W2#0=wUu2n@9OM} z`}Et9W1L=vWo-sZGqZ(7o1FAJM6Kcl=7NJmHQx|to@cnoIO8iyhbqHxD^>L2c&-bk ze*Y959u+nLF2o5VXov17#vARpA%{9dtI#8bOnbKqo2mt`J3Wn0XXOmn0?<6Q?^o0A z06_-t5c!I)RmW;ajk%fX*Ou!CdEa*p*w(BE-P;TX3^v4Ls@&YgX(l@_`CY=oc*@1& z2%d0*(uK-Y)9#jTF8ks&Hy4WJEK84sD4GsWa}J)$`sZ}yVNcxlmlKCWXl1KWE<{De zmzF3vbjL3zxiAMGGCHr>WPZ_Gb`^7XFEHK?IS9{OLvR&?qRFW>Ccf6c2zBT=!lH7e zT&?CfDJ}On<@CdM+{0yk6UOCk0C0(lvX;1vDp_vQ5nE4S7(aZC2U+YD%+J;Zz%%rX z4UFoyFLj;|X&pXtijZ6&l{J=XbNX%^Rp8tMqs;D<=;s~W*Cc%CZ^0z5nwUwZdm=0?UhEom=Cr~2|XP;bGDUH z?GyHw2tfyJEcDXOcgNV&L`^i=tephCDDp9Oj|84!G`%fU+|#@xqmV{FI;)|+=)hbs^OWxzI79wc_*tAv z6#wCJYJ|KP!B*@><=S4gxZv!on8ne_wFoZaw^Gy+e$h-LaS#lN1H;`xSP4$a+mTeG zqmZXJ2bapwMvaZ#5Aelk*XQLt@U(fxD?$x{w}iO4cL@BDo%)nvKMQx)($oRKtKStU z4?mzyxHcT~5H(j7BOw*WrrvW|PM8oWhK>xzqO#W$=m*3MZS90V`)i&IZhv%yn2v<) zt{dId-WwiDP+@xP+1O>THu>4pY-XNe`8E6Hl7gei!Zss+{@OIdFB^4qy?a}bHi4+P z3`IZxFQ0v_ zn_NxOr>!GC13tCFh4zDF{c`Z~n-iNs33@A<_mQ?fphpz6yNLnpjX)DR}MNo1(!L+Ofs6?5JmZdlSGp?Vqolq~;LdEG}5TZI>hb8>Rsl z;_fAJ5oI<+6scPU8nME*QdNSJ=gW;o=-Dq{Q&r*%BU0m^XZ`LpxW^0e&3hX!(O8Ln zfw+WtiI!fV0sCbH@=_h%8YAivW}@@HpfYR3XKpT$>`9ScM13c!EN8FBQ6-6x`GiCa zrYjy;zj?RzZBbFhAlH0pX+V1H!*e;IDyVJ5vtE8r7}1KlimM2iQM|b=LsnXK@J(ds zLSke3_Vjzk?bf)T;U^g<1H2+Ll&2tbr(j3{AFfi#P8RJNurCz-vukW50Hi_A#PM|h z8KLUEwB?48+Xefp#-MDZPYn!vKjrGr*cXAoT-|`cpIo zO)@B(q939ExnC)t5ATpfYoEa38@{OpfzT$|mkP+xyMu)lVrdFa_|H zg7;a16X2wNcLLe^<#lOVc>;?@*2P5U$2UnwZJ)n;x%tV2A}*KZn~*T!gb!2ti%Fbj zcrv?H2AiBLgroX3?7;;%kCBV?^Oc6`kyafAHLoAmD(>zMS%w`hE==@o#;KNcx&cXr3LNN~qA z7ml|asM=nCRMvOXwk=5HQB(i8nH>;<50?;X2@1I`{NUNexo-OSTm zc=uv>T*>D&`Qg?$xI^rgsG_437`?_?i^7T}5L`T$Qa z7f3}PjKH>vjo{K|D+3-Q%Wevslg+C*>3JLE)sghH=su|%_6y0(5kfdoe4;{g|GsEG z^hxN!k4A+!N8TH*;6bQz?asZ6nbLZ1)rv;?`IB$#+)iGloTgBTCK`^3A&d?*g3QQ5 zzvOrzn%Bp(XgDSMYK>MfzXw4P`vs(d?;gf)ncntGi9eEdwW5z7Ddy?mkY^E# zP*HR0Rkj}U0-h*2)KNJAvPk~LLYs@}){yT8TAhZ_!>#~Sr zG?33XKok0Kxp8Q!P!|#pa_hqU^i;YMOUIs#w&1WAKHinq>_UCM!>#ukRsE_Ywf4TZ z43vu648MJR(|(TEp(0dPX#PAQ#yRJcRFd@;j1C8t4;yRJcorD3hb$Av*x1&T zz={@5vb<+0`Q%PbJ}gz+gS$0X+t|85=3b#P4g+g&5#Spq0C0IV@DB{rQ250BvoCIY zFXLz5G^|DR4|FjNTa2A$4o{C-bQI*_kfXaM&$8N)p{jf@_&&YJz07R@y{1@^+Y4R8 zEoSf9xv!iIOC&A(h4PA^Kiabw*ad!HTy%cFD^5I5h#ohxmAs7xjKF7 zfnjVTdk~BsYI={v4}Z)LZyW~nKIsMYa1;ScNgYw&Fx^*xb=qPgnbhk>lwD({bYvuikCh{I0CK$I3$%*r-^3me&g`-34DItSX29d zLSrsH#QFV%uSde!jywS}0oN$J0{#V&g+MMqodA--SAb;T`rF_C|4TBUSZ5$kY#RHj zNc2AVV-4ARtLFq?0_OdC=-~UgB9ZpmJP7Sk*;tfVLSV$=!-=jWV(?SYim*_N%hZkP z?VnLe6V_DQZ7x{>_uB|x%hQp)b_A^hWrlV2PnDW|nrx13U)bYpDc1E2Vr9elb1N45 zO-rM>qjc>RmW3E!i$kD20t;Q~It4P44NMW>Lh=JiH7E-Tg+my}gk zl)KGTQU`S3n-0e(#_MeVj2N4$wtYr0vRNeqZS;#?F5D1r&qsa`DKfHA%p9N58{v+o z@OU}zs@(Ku(@&{m*D<*>^&s%#0&4-PDQ1eUuSNv>Zn8!@_RGhdMqGIr0UfbZ_4Zyt zM3XfIcq?R`)NXp<_t%)5y}sfe(Lu^1`mWAP-xEO z_b-!zSIV@n8c++$?U4JDItrV1%ZZT=mCtfhu85EZe^a!z=Nb+8GDI-l^S#^Y^}V~5 zrB~9k7PYLS=IIqFWno+QBH9o~TSlHVEiPF()gMfvpHTNaBB}(A+2h!(tUOchq2$X-MG;qI5@@yo zmH3dUdJxbS^WuifG9mrZOP@dz_q_=I2>#HPFJGN_gqaiMB{IcOrt?3n$CebunUun5 zTDy6=Y@?pn6DG_+q$Wa#T8GqC=DZb~T1wW$N0U=6QL&p?J>3kQoo=U6u%n6zcDb-% zS#NMdj6O-we=l2Xe3f7~?MCOq)512i>1$D9XdVL<`n_NBik0=j;a&StJ`qOI9+brX zv!0d&l7Rx|%94QsHP`cepE`sW_D!cLK24;v3ncewsmJXH6$wofTdA%~+$t@KDkQ(w z%{K^AhA||Dm3rv*mg?3x*yOa^#weGP(DATGbf#b4YbEID83=VS61nky;u5$(a&@m@ zph;xweaYwif`VkEtpewG91oj(`^?LRnfdUo73*9X{S>su(#gt4%;CeYDuWAy>9M!U zBYEW7rU(fW9$-B!vNzkc<>w|&_<$?zsxVL{{ua+ywF}%DPNMw7~2s=voSFwL}U?u{ga|0P5Ic88_?2Z`>^H|KRUuM|}Ugxj>+le?JBzp`hWi65%j#{#*c&ox2!s z_m$N@zl-TtH1SzG5x`cedwA~lvtv-*0E_(3V^Fn+I5z`0>JDCWXA5XnEEod3QTtO6 zpRuYjyzSi?6>HI$3m_j#k8>Zwele_nk=}FvFX{cyW?9d$aCsR+xqTSU+h$GS$Vro0 zk!Rf#1h7Y2yk&oVjfO!JCI#?C-S%fSwcn}X6kEvo#(8|DAVB&(JHPRJDI)L~FUEBi z(lPxZdEl#(&YT+k5gbkZo9Ltdk3Mg3ZuURPN+qIKj2URlKdJa7Y-wX|<6VdJFhiLM z_&o3(CI}cgI^hoNH`zPHUi4KE;_u0Ecky;AQFzx2JJIWyU|D zCl}8S|B3DZj3K_W`ugrDyESx&1gJ0I;?YHofae8QeOV7^^Ya14B_$&$U`i>t5eJ!XQjJ}$HS)ic1^ z-i<8^9R-#49rwo~_M@ta$qhL6SZ9i_k7x4z!q`9Qi|ZR~PrjS-_avzeDN^o(az@-% zuW-EgV86x9+?xfpYD6?=3p?g(jyXsI<=!>h8yhhROJekvmZ4Od=po`0No$DOK>yUPsSt;BGv(N{q%3KyL$k?GS;f>$~NddWjR05J|TA z^TnlsV-#1e%aO?@5uVE>7v<70k|^iUAdAW#U8yqq>g3H8Z&h^Td-y_DPtxjix;yM` zUMph$ig~Pn8P|YZvdk2(hld3rx}a_DJz`OJ+={1+#&oHZ566@w(Y$*KBFKSW;V3sY zp1yYq(xz$7oD5aL`@%#%c$UO{iKiWC>P%hpfE+MH0@aJ}u;U%%tdTJqy76sY>ma&p zyYZI4(~%_=M;memylhmjLNSxTR(lK&6u5*9<4?kJQDF%&gR=$8uPk0GYjRDsgb}-` zZ8b-VvLD?Kzsmf%z#YFr-y<<{p_X!B7UjR$d&wkr5q+5cDXh<)UA9rn%6!&PLa0@+ zv8eE;ZY8X{xW;O3R7{ZW>R4--ix3C#7q&oBUJtW4eBu|8$hf0t6zoI!>JeYL;f)lt z6Q;*p9Nzjk>*&-OByoeegVUYF!e_zl3JUW{J^A+E(a`3bMdsxuCj(cZ?Mw0AXo&it zb8ZlAkmu7oO7G^0(+D@@d#EWCqRb9CP5wuF-x<|Z*R2bpqM#H3r3V3}gEXZkATK2# zAiW3#LAr=k>7hyyh=711Md=-prqZNH5ioQR>Agq^#e|T=vv}X{eCPdsoO{PTW8Crm zxc6Tmi@E1sYi;(L&wS=Hs{|?oFtSv&g{Hm5&NqMEMa|rqC-1rgw38%)Lq^RHU{6_L zuiV{BzqSY?KSd-G)Kg)pXM?)8ERFbjsk0*eV>55@G}Q0@N<7o}I9~31gd^RR7`P0X zXP5blHGdtzu?MBZ!6pPDrRS8_)0md`C0CD@1E!9K@7CTlPw6k_!%EZyVq1A&1J#f5Pl>vvM|59bc&SK_ILhXK{BWT>gq*U_AnRa%o|cY0`)4WY zGX>G56z5sKVKSLJVKH5kI%u90tuz<*#xpLvV~jI@5k_}!qdrl!SgwnGyF{U8?ySs4 zBS|_+QC-x~y(A@Lim68SxL@K}$6D;+YPbRgHyv%od1hFoQKjK-Ry|*wuvksGy;MfY z*-NJ>xK@kSnBBuD_j>lJi!PQ={aOmMNqn9-@LYrMpfuu#tCp9GW?A0U^;)&M(0NO( z4&i?1*ymR#_u1-l^>HYio>U2Zee z#)Fb>wkK`unUc(Q#yM-&(dq1cUM`*nt7*!gd=iVChhCP6@Mb=hFtipMNe;y&n(yIg zI}%k_IAq>+YQXO%;y@lW`3omE=j8-NirYq^xk^J{$*y@Qf`}&puK3C1n$yCT|Im`o zrx$zdVfrSbQR7@0Daz+_8rIRo!=99KmpYLbj@gcC6 z*c@pDpHvug)X$97f$m`f58%7Tl$SxiDsoJ4L0?WO!$PF`wb~}flCQk>yU*Pr*Bv1j zx}lkz5ae#&%!QdLEJA3c2lY;V7wE8ovV~ba0Jk?$TYeYVr8NSo8fML6s`Q^buvpRH@(&+ep&))l>Bk@>7&-!yn$%Tv#>Cv-S)5&aY+5$`Yw z4flPjk&e1@;i(A@qGd41inyg)M?ld|qkP`=_5UON*tBb^%u4eAO-Ad%kRbIfdqR{7hxwkS|{Dg$K^9GiI(ENeG~(W075v(s0wqN$n7qXyIWY)Vc78Hfj9+cbyhGWr@YD+tYtsCZUwykgY}lB@}Sh96HLGo7PI{!CG1R~=Y(Ler0ylKM=O;Ih1X@NMk?u@0Bn_c$Gm(4&e6 zrctXP?hp=^UX?bU8e6JNROg)((}a9NiuFXwxTWd{_4K7KuYvR_afJLg70{{I4sySq!re?6l<=*L5@#`E>81ZG)YWhBH6zi=YhrK5?k*1wa^s!oSd&-IzjMBV9`pS;EZPa8o(0h8kHs;eg)-S2ppD}(xAlN z4I}>r>d2HU#sn@qCYg5gZ?NbVNzak^MiZ(R*h=5QQ9j*Gr^Lumm57eQ1q1o+_Ol|YPcXz%u(K@IJFEf2CbxZHTu`0?bIA^<>#HD_!gB>BKw z#CGt}wp4bMvBVFvFH-pUuiLcT8SGv?pPAWrVVt$g@8#h<@=4$NOp`~FJmA=V|H!=O zI3Sfm>n6!R>PprQ+3|s?tp)9`TiFWhD@(RZNN7Zq3ehN^P6#?Sx;t2d6{CKzl#lUd zv1|z=2v^%$jD|eZ4PRB}J9Qft4T@XEvpw>jfLpBj^4*dmM(MbpX22>xdLgEB_ zaEe2ld7EPvcm1aqi4^v-8fdC%Qpg%o^g5ErGLc#e-9Y*CgOCOpXbiw4?* zXA6CKBB{xjC4+Y6*0+@;dZT?aF1VHnAtlDZu4N=( z#lf;VVw_N)1CB^>scHNZlvoe?$ix78oNXKioo~837V2KPQS~``*1`C!pDek_FtqRu zgy>YB!yKrq{6zr%v7+N9TaVLisj0d${(d1gMmX8V5d1LwwNQ+@l#i+ywv zK@Bh)CZ$YWrG=I-*IrSHi8OvRAihyYxQEdW=$TCER&(-Uo$_m1Bs;GCCIc0sJFKp9 zh{H+}rnt2BInZrCLYDOb(2U$#14rmhePYGXZ!*a_2vop@~VZ;2eVq@A1yP- zhOf|WFTok8)Z{b1&;M3*uG5rA;;?1`6v`JE`SAtQu|dDn3gXjndy?# zYcU*om&f00^G|)2uYwF(R=f5%>u%utB-;6jUByxp{zBUlgIJ%3p$aMikSN}PQJZ6- z4;~#HN8Jy-yY9*d7|*uDj#vSsboQv+ee`>vlmU=&)9Z#|wu!-|dV1H++D6COY8r2N zo*d*7(*WJM@+0zqN8iQjYSXy!;G+)fdsqM9zo8-1qk#Qe6V%!~>frTyaZ*9dVqURqiWAqu(5~K?D@Q29@(@zS;7? z=GR5md$`c{UstPwTr?Y|s|%|T>J-h1D8I+U@bKcT_@)|y7; zTk;EUesO;g*Q=@U{T?A=@XDKJbaD2Qv|GJz=)=W_U+f!nTK zOA@qt+VHN*fK+~=jPm1WlG+C%+wJCYyL5R*HOJ?&7eMXoSzQ+V;^t;RC$_~Erx zx)d{(;X(yfb=zUsJm;Xg_VupadcR8>F`^&Ajv5b7zZ13hmKQPU;cbHGCms*i- zU9?2Dqv>X*Ha*M`R@!p?mu>egsxCCnITR@K?UwW1*1Yv_vVta$dubZ2HY#$4l=8#{ zu!P<^l3txQL7!&grBi0N9o|I11584F)6qXUuaCH5Laqxpw>Dc-&N;t(Kh3&4G}_Sv z4jwg!8uKg|SY#JbZ3}rIhqq~Vs#^tAJjfwS9W2>oXmr&E8SU$fJ)Q?B*5}2)%RUKi z!1gXQ0JK|-5FgkwkN#6YfmG1^W(2u(<;jVf#lI+zR3JxA@bW*8JpVS)7oSwvC22M` zW)b6WgQ<+Bt*tCw9Fkw`eWSi$gSqQtsh_#{j@_D}qG(XSZjDQ$^~_4{>iin{a(}(k zqQ}|Maq`PdRFTMX?!`H#2M_04H)!{_2Kj~Hina0_w-!Y63)TnB%Ja)&s7~vvP=wr&L0iyvmLuDSM)rZm&dqEb7B_xg zRlO>FtkaDezOmpHd=-OXCc^)ZP`cIuFWe zQ+7@kMAFskr(NzH67bwZsVX*Spqyuu7cv@{TXR*}3vrV+?J&> z?q#G&pHwZH&u<8aJ3a!++$L7Mbkr}oqHn_um}OU4NGhn+NwZ9DCc(H9=)?S6f7 z+NX1@Q-W5pA;3gdRm_3SCl*zlle5w%;LhMV(DkMQwLNf1q>vX78BlZX2(?U@Ma9E-nq~GQ&sM6;VxH2 zp$cZDI9DkZ{eJuVS*B|;b{rx1f7Bx%nuw?Z5z)m=nSOJP1D0li{$+ZXJQc<$T$X9J3Z5zHYOiVY$A6#)Sscu_P zs*ot;Y$3W0HR$5Z&9h*Oox_{xlkFjE5Latktd^<1!&CPWmsV^s*-QSu_LQn1{Pf}C zc>024PR4!awJ4nz0+rqzwe=nSnv;|Kswr>ji^SD%@hAaMj0MkiKhkJEa!YNK;O?#Z})Qz?CS zT@Sl+yVkF&p*jSCuk2| zFlgS)G5GCc`HzXE5^<5M9Jdp6D;2CE`T})16Nu@xcTdI6mV!|~@u}0fx#R{OJU%(SZA4m8 ztD}CGEl%4*DdrTvWk-@9McmS{u@k~Lj)&9DU(Z;;a%LLw&A#D7k{>Nwo{jrK&s>m9 zsobObqO}F(!l@e0`)9h1qd+9*x&Xsd!GDtl z0!OtEiDQL6<0i>0_SOD@=-;x&XB6))!W&@+AdC91!hJ!qrR4-18vP))ly~kiMw3~~l=C_qGqJ8UfVy5H%u)FHb3l&D8r`hRzc}5_CV}(zj z2I>~j;{9}2EiaNX=h5^Q&|JH+_QGEAS&`cAPUb_drJw-RvRUFir%z%rUUgB%342m0 zR(^U^Wq}D%8L?Txjz5Z%OY+YqjkO2fD?wQJM(KrV72gpOi2H**qAeq6CQ}J!$ zYWbJ5OUyd1ddeKx=?#P@q7fsuO@HLtUAB{vX7<_Oi?*-ly!gI4*{E(r%=)9e)vc*E z3AQl*!>%QPK$j=(`I+*n)vxAjpN=w@Ij~J6CuwXBD;$rVtt>Qk>Y*~56l`67=Isl&(78dUvpV5f-c%YD}ln6j|;o)d$={FITl2&s-Ci4E3|Qo z!6Hy{c*e;}?aCKrAKqO^LV$s{D3oK&$eE2~ zxju7;7V%=dZ-#>l7u-vU5`z?17QYu-MPKo~js2W9eueHH+7k+UA_kw4xOs3{@qH=x^OATHFmE+SwomMK})s(R^3kCXmCJ%IS z3O?pNB0#Hy3>M;FR0)VXUEb@L|8NYQD)vYZ+s5wmiTYU_ZH#ijKY~slhAfeP<3XK~esQCfEPP_P=nV~} z1r9zRWbW{(F3j~h1|{i)UfzbTf6WRa;~V?PHXC8ZU%jd|UM4ntoHigOOgSob=)nK8H`1(q-r?J)sIW#qjai(q@hL$c+0Tb9PHs*ct=D2Rw*snRw_-j4J z$8S8uJI_fg5n#9wT0+=C`?eUY!=!mYv0r8^-S|$?g7X)1;axGDk^&MiJ2K^elToPS z^nR0_qeKBPi=hxX=Ln=;up0u${+Ye_Ww#Xt3KE@IGzH1J4idRH2nIq<2A;S5O%~b< zP(fABnZn2T<=|EH>gQk>1xYEDZ#}Rkdp8Wgr;t7JYJhbdRK9V{{V}o)u_z~Wp+Pe0 zF;8R+wxD62X+MH38nK#xMelD&n@D`k3Go$hgpNGV%Rc!qqG&U_R)B zuT(SwIY1XHT;2c>?A3u_D&O+wZZgS7{d45Z$w+PFt^+OZWNMzETGk8@1eSJ^^uaa8 zAR90=BB{u1Ul8Sy+&-wYQ*k_4aQ47%DY z!x6h9BA~;F$snWNVQgmmW^F?@Sm!pOMKqoP%+P1tpFS{QR*C0_K)=sG(2F;S{?8dj zT2@XSjg#n691hu(7Qt8E0bv_MWSjV6HlCpZwtEvo5^RpmL6sS9Lo7k;FoJXF5|rKb z?%^Bdwl3j5EY!zB6^K#Cv8^adN}?upr`_GW30K#nIk z3soX(bKDo^{KMGL!;NV)z#Qixm_p)tYzvkoMiNBf)Co>NM9~`yHpR1(8O#00GL$}n zx|7;4X-G9-! zKtOh97n7X8LIwS`P=}9Jzd4)hqw1fWK=SXciX~WLH&PSC8pB7VV%;H8 zAP+a!<@oXaO87(DmC7nyR7(U{g|@yS;xmwa=HCRpkIw@4Q^3NGfa!ud-OS>m;A`XL z0)`}zn$Z4ATaqe-4r~=_lc5^D!*sArUHu5V@s>3`(DRw>7H)_w$P3w*3p%%w*&?*S zygP&2gGdpxfiG{>LFZaAe<->FEPp;2az!yn1Z<2xXp7-d_SbP3Fv7Q3(8OsBj<>f_ zF|b|p!-Fr3LH73#@r8XWiVsf=BM6t_@MV;wxEZ^bTA4m+2Dx=E4sMX$boXuYxr^xi4ocHgB0mTkDRO1-K{KG%iWZO zjBjL%AEl=esjavOUhA+nl%zhmoEyN5TD?*Zmj807t53~RRqbAT`Yu+^D+DR1TZ2Fj zw17LCYX*i2!ILaWTR94~Iab9IsV8?x)Ight%IQ-hC8hFM*I3)hn3Id0jIlnp94C@X zR}#pQ3H*QiEVMzT39Y^XTwdO(*Pc}$1^+S6>h9(rd(9qD{^N(rBJc$KX~jw|;?09~ zxp$leUzK1fe7}-yNy_PkByu>3>5vKdYzyqHD$=%F@n9mmk_*kX3rq!0x!&Hplt-&E zu-Csc@PsEUsI;w_b|?^1_}cR3r3cTSe)yQSlInA4i_4Ou33AEFm430I8IUpRqEp)V c60p6L0oUwL#nS&P)Xx8J`~P@u$$x+U532mD2><{9 literal 0 HcmV?d00001 diff --git a/Android/Level4/app/src/main/res/drawable/r2pay.jpg b/Android/Level4/app/src/main/res/drawable/r2pay.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3d9a48c4731dc9e4ade921f4b6305b3a1d9f2ef7 GIT binary patch literal 33090 zcmeEu2Ut_vwr(gA6eJ>DAwh~%L8|niNK+9(nsh}4=|!Xn1VKP)p@;>M-UWh6k=~1< z(g}jndjt{)5JE`a!oByo>e>6A^X|L%p7-8&;agv_QdZ_%YmPDge~f=D$}nXDbm*Lx zt`>-jiVCCy{DUZ?APo>b9UYi%A3Ych-oKyz03+)`Mg|5(uEQ)4R-Pj;D9;gYZe9Ti zAznUler|5zQzGIgrDSDgVM2?`oYKd*k4gV;|4|x2 z%=FY|w5>E$d?0FODjH@gN-GEk0#WS)M!PrQ-~XtnX=wM+f$8@jU;sW)eh5TOMMFbP zOS5kuEiLfrK;V54E%Uy^$D~fvu^3zh^LemJ-;2+n=RfnRiOsMVDXH(C@N{3)zs3~(LHzB$k@cx?25VF^&2#-S)oYHgRuWR3Mt)ruDa({W33RU|!U;v^2Efy?Iel`v4maGwr@( zQgnw;8-TBRu<%LWqh~!6pYf_`KfjD2mhGBn?*VoJ*-1g%-qgO&?4O%h$bV>Nf1B99 z&1(e2NJ9l&JQ`*Y9JECg&I~^AKimJDga26r|FZ`Ee_aD&DMKWmNjIi95-&@xH1Tab zfIs6^Tc~pDdwWoS^8vQ4KqT)LF=i*Uh0QFEERaY6#rA+pY0lfg^>GwXtEr!o>HR6= zZ#VpoQ$Rgu2D#KENf+M2tNY3b;2rso6wn*R0rJxx_8J5U6))c|haFJI zjK4puNqjN*CXd`(Egn;Oxo34*zewT@)yAihvi{G{&ZSIOtCmDg-9|*I(GNuyDSbP1 z4l(;;_+{7st+(163lXkCN)CY3+4-JjPzJMDLLVa!=98i<2XW(0*KL2h%$$#LzM{IF&UxwkE zayc)IsFG>d`Jw>5s1@Hr6Jl4|T)DJw%~Y+>EV?Do?mh)1o4<*tfS!&nai-1K4{&Cq zo;~THfY`Gz2-*g-6CG>Rx%!bdtm!+On})l#HoHk-awch>P?kgWEj!5U22u0vk3q5l zS`V)2(dZ@e=zq@XUKG5T#uIQ0CPOg%9I+$yzTrc1jzWF55}OImzNgIep3w5a!Zr#B zrpELYQ!$&kol(%g86ONACm2q_w_IBgvaJ1Q6?9#ZKAE*9k|P?Y;TXKC9{h{&_=m_k z*fPt+Ry#)ZCVZ=Snw)Ut+8b5R$aVT4Rl*Vd29H3Foz3E18PiMx8cQ^wfQ~Ik^e!KV zm3+9w-{VjsAsMAc`+SA)xCc?sgGi37<7m~V)7uI#$cAjK^dg?IQuP~{y&_b$Tt*b) zm=Y+Um9cijrehWKRjwZSrQsWd-kSn)8I^zJHJt5{h z88Kxi_EqU~lg{?49K3#HQ(uj!`9as4@Y%(dfD1LKUA#=-8Q&o7I4YbTkLhB87x5kOXZ*-2ah!;OGElFU6 znXkL(+Ymyh&y0_lKfg7kPXS5vz(m~dve`U~*qIr8aZ0na@5wGZ2$m6FYDrul#kM(^ zrd>X=c@NL&oFHQTM)4(_cJcAV(NMvztuJ>9h*aGei^oLoq;!~lS-8q=(O_8Xv=Hv4 ztSR@>CyO`eoUkn2yYT=*eWN7KYM=>XV;$ZZyI z38bhlU7Q~}6XG;)b1=XT2M)7G>f-{-s>7Z&T9kF9WW{>*o!)4gPaLTmJ&P`DU|uXh zWRGcjI|BhIB1tV;sbG_@=CYm@R3JlGS@%lvfPtp;nMmPuhyr1e0usnFq<~6F5etJT ze(WkKY6!mZ0U={uh3hBlYUNNsR<;yS?@Md#$?Lcfd(~8G2el>nq)#a8>tlY<}rgrq?|` zPVn%~AGVV0MN>cz^DQPf?(IA=<;R4Q+0eZfwRAkYp-(V!cT=ts?t&Ec&fVCX|APXS zCQ}dF7Sxx#Tvp_6YBf>R+A5rE^TCPDwCcTNM1Ted5yfVW>bn9ae>5z4J}ulZ=-Xjn zlQYvo0o^P~j(n0dSp&f&-A!3QPEiMrA6WwLViu9>1+?SL1Gc{H7+g&vF>)+3XI3Go z#q519Y*bAUrO$Bzu{=uw5t0oG0`x9-LWDhI1wo0e)Grt3cCc)k;mI=cN+ zRbe+nj1z>oOf}+ylGa|h_#)c;E5qj@cJ2WQr+s0M5SFnWi%68?;~GYyb>ysy*mUu! zR$S4!pzZ+hN7wnpmAtnlC2{{~fdAd^ADot(YhWP@j}oLI-##h`eyULlh~F@yTIgO~ zs3YPr1vs&eIA4~QV)vTs10`NODMB?qcVJ(wAyvFSAAO;rIhJ3o-l3eNRfu6-TvUk( z`^o$Z`fjI*H%toipf|m3v5Bn%GY^to!@Ll8kH47`NnIh|89SRN1YfpCIaBrLl`fWo z+E`7IhDC+SojWROM^d2&PM+3eHPM>XWW7Z7CmXFPJNB!3&zG~WwOaO>F(DdvVztfZ z(<{*dECmQBg87;z%`+D=_6GjOLJR6GCUrVDvm(dZC^h1^*uL|Ji{%Oy$00!?i`I(w zT+&<~zmD4J(sG6In9GnfM)SA0Qz;-49+kL(Vk&!6l9OFyz9e<(Y4K4P@s_yL;P7e1 z>9kLE7LyTeNjTPr>As=t#HoW1j~z9cr%8o}?P_a`_SN|tXBk_;_@kNzn&0;gZ@d@I zELZ$b_gTOBt~}8#c<@Ha7k0W5>C7-$4?7&b)ab>zH0+e2=xgYq5iSULnorXrJV$c9m6LgFAx31#L zdDq3c=>d8yhiro#aYR(q68gE=DhP7M~Iajj=z1*21@C(TCme7yKNXoauGk7gD|Cj^#?`r}rS^+JKlE%IZqa<9!7CKq%# z^22mGDWH2&1}jwQY@cVhMshk@-MFos(2*_r!QU#vszo8y4Led>YWGbwjcy03%GOC7 zHKy^5uHyN!L5v*_emOXGO|&|(YV>+tr1f!4&}G*!t{UsK34t?{Rd6w*ya{Gm1YtQUfzn%x*k+%c=s~D#HM3>O;Tt#KyuA-rUOy) zVH83#OFK_cCZ7$YAvXa8iFm@v^_2=Rd_J{%6p-yGVwb(V(&otBtH1jCA569U3;H0= ziG21kfDoQiK*bZSx%u|tl@Wos@QFCzrq$#b%z|XN z%^L6G_!R`+&d^O=WuD9idx)sBqks@d3W!CUBnm%F0Rd+bV9?~_bwiP+T$47~eA4+{ z3~YylASA;l4G2$mhTvNSz&XjSlo`0Ii2b8uNPxo-%~?3fts=xK4)B0`Y*2g3X4MSf zlhXjUMOXJ~Heyi(qaXn?aFNJv zY{%u^_!Vc)@hc^|2c-BQ-rUS9aM4LWFy~?uUE$Op(3dgJ%eoue-=25*-fb(b3u9*+ z-o_(|tswV6GsuTPMO@_Lp*bh9w^%6etPZ;@|WUz~pIOcsZWwy?+@xTt;8M$f2K^SoVd zW{5EA&`$8)lKXcyuBfRRw=%+=8LG#~!;%#cp|#_64U=^F-Zo)G@#xX)5cvu>w-b>l zvJ!i3!X}G{od*ab;GFi9uLknDk92-w_hMs8c{wibu2|;uh6xEX(Af3GVLM>+MPYkj zw=V8f`0a7_g~UbwY_;pso+S#t&)*b$)5dhFu-M2v*VAZJ6G>}PYPm_RVWA(w_Gotq z8oUOvJQRq*NF+4|m}2>S`vS1@a>Rpa4FNqy^SE&_no%cXU0o24#A>eGj(dCD8 zavuek=UY}e%n6C-Xh)S@s_tE68(4dXSLjrkxVL!O*VNQSt8w&`{z!4X>A|fB3;Vl+ zIu^Ulhil8iiG3Eg(6>Dg=8eAP|H2Jxu6=sWNc8i!Kr8=C9g`>?A~Y1|WL$<;+y7^42(EWmivTg*6_(9oU+F1;q1e&@Fx$xdQrr4 zp6c6snGNV%HJph8>Z}3m*s^0?4jpr=Uk_@c3uZh!wR7Z=fu^5*|DJ-Bx|4Ln*SYW8BrM3chXGM_nh^oWVlSnbm6q<&N(C*SiOLY z+xMG$`y(6juXb~&bTSvBGc+&oI>2jVY}8D95R45or~B()BNp1T+r0s_qw~v<$*TY>SOQw>2I3y%!k)eMrkc%Mxr9Z@{Ae8cuME!0yfH2KC| zn^rfPl456K{fk2!IEfpYFw7(1TtjKn{Bai!c^EwfB6aRwAOYKBM_cXB;`l5+%$QqG z3DIJUNhgp69X)C1wwAUP4%73d#Cj_5?wIze9UN+?td+F)|He2PP=y%39J-A~9C;jm z8;JhAe|V#R)uZAn_m{vYjcUi9aVQdcj z5nQHtA*8qG5V(=G?l4X@+Dd4m4xAhC@V?ul2;=^0Wp`McQq)(zPg}=zLK?RELkUE( zVu}A&%M+7r2RH&|DcnM}qD7e+v{5 zYp5wLud~!Y@QRymLA!?n((fyk43H7MQ7mv+(kfQ{>hdZ9opYY&qW^iVJN<2E%vG6! zA`={Lgq%sp;%E9mPtwlc%Ey$;4)*sf>B;S#WYC{&Y&kp1T{BKlky5qNx6tS2>WHUB zBjs3;kN|C*tW~r)LPVQ@&ItA|^W|FG;_c3G$c)4zlhqsvZ_;7=0@OoW<>Qn3%g>nK zunw`=c92?)8@D7HK$!ey*t3lBp=g@5*Wi%F)WY&GFFbc?z@OLn3!+<2s5Bh}qA6!1YFRz$Z!)|TyL)B(@r|bg9mZad zza9b(G3M9wD1zzYt zgEyetn<(!h2*Fe(A9sJP7*8MP1Nzsb{-fEmIZYU@65^+BMSML}N}7dD z8Z&`}RO|#&o68&Qbr{jsLIY0&x5DM%m-$bTyR5^h96zsb6@~s2SoO=EJv#|{GQ5>oM9yI0TXY#k94uo zf~Mzc?dLQ!SxrL%Ck!-se0lVYc;^K*D zY|DAtHGG|Oi6D#X=a7Ek9cHP&7%D18we(kfS8{X;O?r3&uyQF1$b7{qoKOz1m-7hp z2gFdY3N%vqCEzbuK|h6LRN7B=YG|jlB%GN|{pVxQ!&Bk5iFLHJ$j0RhZZhZI*bOvBP(VCvuIYcrv;N-8{p>XUli#QIL8Yu_ zsIl#)yG_^{j+)S&6(ZC&)$o%?#10T8YA&I>VC=5GtQ3;~^W{$xd>_6-$#-4r>tS9d2z zUpkj5yimfbT_r#pBGd-s-gmZLIafLn!leC*N7Mi0%LB=6FG>rzz6k>4^%AgTs5H#0 z*!@q;%uGCZ0PcyuM~t_Q$1U0CFMQe9vU|7if*&tR2Zp3( z(WrJWh#c}tyZDH>!yPI*V{@gje35M5?!n};3>&3Oo9zY3uC3)GP!M(o}; zmytukYFT|UyD>hsd@;K%#K4Vh2sQNL5sK z)Cg%N%0Ybj5&jrMDd`hrMyz`w@4DEF6Wy&4)-Q=Qrq8IBIgL7IsMvsv7&==q(8<89 zxNCZQ$cojB0afJa=}C+kwcqJKwIO@_O<~8DoLF1Omc1LU(C9La37iFkjk6mnXY07? zITOUM0FQAPC7r?Pz2Y3qN#w~k_SlY3wEW0g1kU&zU^_H<%yn6Oh1Hu^T8ea zQ`c|INGH&%zFKg4-9tW(898mXBEYdZ4a(mBinPaU&n49`ZY_yD#*WA05r_9ha$VrK z@8u@Ri1?~{6ia$pko|8!i*2fb4PQ{U>&jyYj<>Dlv@KFUEI~zThfFxA-!*1iOB=BV zWD09Q4#=M5uycU|S|8Kj`9=Z7C{u0R_;=oBr&)S0HVZH724oFDk*&U)fJTw{(8){9 z7@gEJed+quL7#DtM7IJZ}mHFyt({N;v%6N*cCPPG(VWel^ga}LO(!J>>Z&XktsPe~1El?1t3W7=UTScEH45Or!{HJU9U*=M~>WeW>E9 z0su;PYVfbX+}Np3ZD_+ot-nQP4O{#ddRz6B5u4pdwrPdNb)X3bsXp6Q$Zo|meYR7Z54PD*x0krar%F?tg zKL8-Nsk|CJ765#xx3VCbI$5GxpOU)6>-lYn?nw=T-S~7!8cATMR?cbpEn>QLXe6eC zt($OizU37}`znzF+Q4MfICS`@pu~w|BA*b9Hh84Z$&YF;@7=$OdxyAS4T25;@nB6? zjDO;}%h$bn0QJ9<33$5ir<#<(kErimECuBAtO7=OrS=5tLwZ02?}h@hAH4a{*K58% zXQ1n4H=BP2V?UIWovMBYeITsAaAwi>h-Gt{1eEXN!54`D@5?$;AMkT(MmHJ*pyjx~ zoI%Laobq|yk{h=CK>m>kl6Lf8ACDa4wNh3;Vkt>Z3~+CR)o^0AQy{qx7Wbx=k}yk3 zIfLJxeO38*tlOnE4HH?c$#(7g(fhEw&l+${FC6L4R?=tRz0N|Uxl%q#677#!jW(Pp zu`7F+BUGXPz5yvf1{m1gL4X*ZEIg9>@4AZVuNO;~Tk8=(=4G)BHfH{tS%{Q(_x}#rvRbUCFch zPaPSy9s;3XHlZzPUVU%*Qxa441(JmeOGAD=zd!7Q*tHn5L+E*%Xtu@$KOUm?a4qkx-(LbZQb#cJO+ldq9Ja@QB_)8Hy9I%4%wbJ9>uPiZl9nWVxb-&X+K8 zILKBlLTEwLQ_kl*+BZSp-^fb$ef)`(a<;hQ>Ts6(xTQDoo>|!?@ZkHVN78XdYxH?& z9_+XU`7<_!xpSw)xjSA+B~EP-up@Ukja7{1Pvq=JqQ+`q29+9Wzc(2*I%s?R^J|!o zD|i--O^0w0!ip&%7vJi|_)3e>YxJ*r!anH`EA;!>-uHN3)D@UX&==@6iTmx$i}^GW zxp3fz#p02POv~%s?#zC?yS^|(VVdFkqYgI1W2})^SX@3%u4i}7&}?bXc27CI&Mmxu zDIEk>SH4_G_w$H;%OGhjlthoFZxre47NT4o7dXW>d$yWGGgVqa}VRxVMOqb z{Ys^4#Q4Hev5&nQ;?{|rFH+rZ(vK2EI7FBHLm=j#+@q%^1#fq7Db!#0dmK}2h9Nrp zY_ja<3!k1xAraLX9II$TS#zJ48Zar&w{PIf`jdQ9z1wz^l5+Fw}gqHFoRwB-AQQ6oBH)`x>a1*LgxuA7yC`beFAb2MC z%)RoK(-e%9h&+rKRzmE80Q2Z>l|e>81%S-bZJ?G$l@579Vv?Dhh2sYsVM(`>KKa7P znq`1As(4o{3x(<`Xy)`?+fa$Nx?)tgojL-5O{+ZNUjy7P`;9-PwW=d$Nr3?0T|=Oo zDWKye7kqYVKbBHJZ4dDcp$#+IJ@9Ww-6){Up$ZI3)A$`Rs6b$ z*nZ4vS$+JWHs1pd?ft{G5h0ULNDq{JhV*wi2iIo*_1|i)LzSo?Q)*s(Mj<02F01uzcG}+G*z<_36Vi#Kd8UpFrj zNNhBSc@buZ#g9axRwb`*>yoFgLt2zyc9a#%yVx05^e;E9+sE-LbkYtqjJAF zXY}KD?h11-t4AGy*h(1=cNr(4obCj{`f?g-1NhwYm1^!7tT^d@(TZN~)za^)_rWzp z+T-NQme&PS7!B#4D{`-O^rYCQK1!fbZdE&0hdZ9XRT=Hq8GG{LFuD}hjh0LL=ipN7L0`%&|Lcgg6&pwj;#pq5Rzd=Xxnq zM)Nc9F(|n{Ye6hNGaP`ZB6i6FkL8(SX~bxnz!?Q%U23ep`5&3FyI;~|?E+sybNpYE zd9eDXW%IjeSl;!z*KmhE9t+60?;m(cd5JI*CG9l{I zg8K9E6c9DaAN7bYY2vY>-8IxvIv}U7Mc=g1Er;)pkh_h(&7i93@$8ZtG*;p2_Q0z> zS>vA19f*cSHzBrtjsG!vPw&B(j2e9Ht5ae zZDqbhwp;H$=BY}x04|*f+$Xya@Oa-xN@d-PMV^sQRvD>%`Ox)K=euu_{>Xyv8L>`$ zjJ%bNNqPSyII#7eOmy)6nKWDJppg2M*KZ=5+Zl9N#V={`pZ-QCYQc3gQuqhD^RqOI z+LjsFSNo)Woc8wawaIe*gBN52jd*r0^KrP@Jb9#s+4e!1XO&aETGuBDlEtxdeYeOm zea92Hm(Q1T*Q;^{pteIXi&m*I(>x5;#_ZpYU6RRRzt zD+*}mz?`3&RA5@$k)j*W`2quL+Xj|$Odp3n)_Wj2@YK7so!Nb6vFlS~WoOI?wx4N8 zhE21uPbO`a(ibc%bpzf#mX9392TWBJJ9VT&ds@V|-l1_1Y8oF{|W>+Q>&pD-&r85;{aOkSB76=-Ar$7Hs8S!5Q(-qUXKPC8RaLPx?L7t33#-+jfB3b3`)r8K12wiVU6*U@o0@mXXM&ad#k%DnQ6oIn z@%CAwq)=c0gdvlJ0HO zXE!c7Es}Deo-Z;oz^=eIcV4D4$>ILfx&mIZ@ z>pgMhR=Mu6zeRvZu`H}jST0VhtTe96o(Vd2y5BWuVM`U9r}l{IE9p4)T{s827+oXfhFN%u_N>oVbq#O!Zdk;CydG=24S915dtE|H(K_6+Kqbthtn`X zwNj?M>yNh41O@a?K@Kd{A9=gBnyzLbAh57Mh8$5jjm)`*9yB#6wH~dj`ye7Kak6uo z7a4#~BD|bbme^^4yy8z7ibdcL`|m>LN0M#*^wk2c6x zVwW+qoweDagSyprvS$ zy*e7UG#@PwufB_HoC#uETfPf!TDI-7^UK!xe6lo|S07u+2(Iwh?sLlTHUR2a>S7<& zBo=HO`_hMwS#~)FROu|)sX`_?0969&d|~D0r6qX|cCY-C-CQvpuQ)TP*4o(IO!{;B zk+j2#@zvy&yN zZslv~uUuzTSNPJ<3VB6~YzJ^-zC*steC*tq*n_9Cp6R#w-}3Y2{;AxFYCes&n{m*8Em*dK%{jAM@&hb;}iB8veWd#t;0P`k#GXrT;K(?E*;~$VW>fM3*p+2+x4#i|$s$ z#k?lw&d#KXe@r!>XZF3|b zTF_*H0h7LVX}^6lDgt&@*TArg*;rw!YW4`fDIP=RqrzJg*Ug7^Uih=(x7^dF}J+0{3g~ zzt=?&Yj!8t=o%d}Ctj_dI^C`M2zHvdQL@K4|7ifamC=2rS|Q5%co=_9&RW_ z0R<$lJC^b8{YpvR41$mtz(B&iz$MqoDc}B#MjNj;pbQJ4 zCpiFla8ZUULrb3+!rDI@STZkYIsR4*fx>Z!Gixiw*~KJt@^{~YlZ{#bj`+R8?c zfYe4>_ejdlx8KkQ*o=3FD1v%lK)0;4#YX|@4BbOXH?D@z3mghuHwwN1RAIiO`YMtL z8eUc_?=0y2@!F{BCah-L6MkUzPMCg(yE6u$dI|Vy z;UTEAu8=^2?mM9Z**{e2H4S0@9Ghtm_3$sBii3i*_jMnDKO=#Q-IMU}U|Gp;k_SdR z_?D~Q?&8O)RKXKcx}{2mKh!&^{<^^Sk1M>Ed9B^s$Ak8;8W%jt+xvY00Cp4Xr{F|f z;`SwQFoB<}`2aDFn73l{s;37MqSqw1_5ho;xBkOaHpEmXV9B9}_AWCklDk~6?wE56XYoV(%3jNt`&2K&55{%B8q6R)L?s$yDW%>#vO>Wv`V z%S+!aAJ8WL>Vl5D3sX51)vO*`Al~9zzg&Jlwy-Z|{E7Me3R#$7J$k=7d9sc#tYOpH z9-Ge87rCxWmR@w!3B6F0`1P3)YyfEPmh*am7e{WE?C}?Ia8a-InIPHj(X&Wg6`Z7} z7$kR2ZS#J_;%#km=dI88Fpo@=+Hjd)02Owxpv{&94ML7B%MBNLCXxEC#c<%J7}Yj6 z`4Ld2>$NP-YqeppisLXc8|`!W3>d%FzT({%_`Ayz=`U36+{fPsp8%#q)k)IrZ=--h z+$>zLSF~c5%hriEfvkGo2I2k~&p;M`ctspyI=9|7cW;4Y?9mIDEL z9A&jPKQskYMFe&=kqGdZfN`K^A7!~Cf%3>cH(pb7bea~+<3GIw5W;{yJJnnu^!?~k zsf#zhDFxo&N=(tD=HlF;O5TpT-0;L`V8ty@@v$G*Xv##YI<(~;p6wfqeWT&k!lgw6 z_^R7c39!RJX!pQ0maf($Ssh5KT?zprI8$O{H3v{!jx0`(_pvw|u(;kil6?p=FcBzY zqlHc*3HLO-sZ|5I!#_F*=J*MQ$l zZ~fig_iP?S4^F09lh*KJ{<-<^Kj) zaM!H`=<9JvjtCWZMakCOn)l+pC7`amJ?w>P7m)`)G_W~`Xy%$k5ve{S#xt}@$5M|_ zKU0HGmFAPvVnHC#74WROAI0G~RSh3;re*DT0hXS!LS#l)C@X& z9b5b~+s4Tf;PAz9`VCBGvEPaE6#M)WbrcYY4sO1TcMJ1pPwo;NP9Pg}ufEmanL!vj z)nq0$Msi-O47(OC8!N|29|{Tt6*&Ca-FFJNo;==UM|t^3Yfv-3sj;O}XBQJP!?7o& zx6C=7de!U^_pGb3SNnJ^x(&vDGby{ghocLbQ5_#-M_y2&T0tDMw)gT@omp1>(5ENH z{id@uA#lwvHx8OnM7nm(T=hr`O?vV?YIjX3$h&zdRRUceqB)nNtc93O=6L|lrK2Kw z24W6J-Z?|9E3gGb-;+Nv{ea6|ZoCOx)~9&5I711CZaumLHq8mp!bvhh8J$(n=Iz@hG;;q&Q2W>*nSN1=RASf5cK#MbG6p z^b{lHeW2LfxvIP+H1P`Jl~osg{5hS%4kw^478}uEIbD1?V=p!M^t;Pb4>-w*6-?V% zLoD2^IWkS=M07^nAd}LFTqVuFX}WZm&jWA_Grh~O18(zS=3B0Ks}`WZ4Qic%WOR1q zsyaPI-6rH^AZ`(ymT|{j#rMa>548KbEg)#DIezCJqMyn(Lo6BhsZ3V#fYq0mE~%$yTDozSTqHXENp+~?bg|oxPuml(EY}eJnU>JB zBu@n*pkAt~X7aq~r;_0Co3zd(_Fne85~qsf+qUHG#+x)NC=+<_yP~Cyv``}ZKsEZf zwf@R6q5hE8pir!AYNLNrE%V5zrrUwASONM%Wzb1cN8vwZYX2c0_@D0czWcv+hs=@} zSNfjF@;q&y=)1glAk@a-UU%Y_6wKGsg*A^ap+1%+dT^>8@cm~0kC(uIxi!lH;i6qT zlk#5KcjXKn42&8$JD^76K+SX4`W1HN>DH4z7lUTr*=#pW9ttSOS12;TCZCYI8rZ_Q zZ16Dhv;O<~`B?obqV4T`mGe`|<1CKFez#kBJHvT_vPciaT3X)_0g@{Gx7y9$qD`KF zVZ)c0QMKT-#mg~j_~_#78Kx=ujb2Jf*^LQ9uXozZ7W^0r!Ne@Bb4( z4eo(6!e=x9e;uU1%ZR>eiD-drANtlXo=5>{$PF9qG1~8uEz-fzS0LQ@;L!q;%U_`M zsALu0toqO?hC0QjQI& zSYGjXZRMz$QP~@vd?0n<4qkFvtm8NzrPW(3yWmkl-<$v*Q|+Gebn2{Uaje5l{n*#1F8EJe-??sDX;c9O`2QSmvWJ!bYmD{xOL|bYfFv?tdIus^9Oe_+U)pY< z&kMcvl&`*FU$Q})n9!{|Jk5XE9l7}5(H;4-Hsyb#ZRpQfkFR7al8wjfioARu%TH`j`AP#Qq-ZC+{e`ORJ z&=nmL6cwGe{?R`zTn)CU#;y4*&T8E5xF3hI{tkaS*&97DUfQkF2b3=!2g{NA$2ygw zzv*{+5z)r>lX}#RkT(vS=d`t?=-hS|W`;hpmeA_DG1@Fm#vs045;Yf2r)}h?4PvuC ze^j^W@QC`vrf(DZT2Ze$_wIa1?J0lA^DJ`_cpK|g2w6FDZUc5-NwE3xtGCrcxqGZp}NX;soz}Uq9;=^eKPechXer?eGz3>U8AP zQsQ^r$sS|ELw@oxrZ8*^`K+?!7Et5p`FMwo=5O#Nr|?$K(#VaEVU4>3xJPczTO_7~ zR)EySq~Y~*y#WdF5)S9mDs7lXG}4s;=eL%$g2Vus(s4GculzS@)r{1hoANSmD8ggB27i~#2Jh#!OKb=Gixm;PGY~F> z5*oghit=4j)q;DF0ii+xPZ!>}3E$_S(L&}dE4x8`2YP*;d)3v0zzAus78TClOQijW z;{Tt0@4wW|e2*X)P1fW6)pu-9xgq+h+<=bj1{ly}O%53xM4yAU|Cq5gOj`?0~HCi#adS2_d?B;#8F3<6^NvG3^R z{QDmz8v{>2RsX_!f8@ZwKBs9VOFHJx+f?=&)Sox2JP8}OOPkr}H|RvjB`m3l46MA? zxf^~!U*VFDO+WQ((LH(7Ui%?qVl18tHQ4~MB0MoYf7GBn2>+UUN_JXcXLC!%e|o`+ z0g&~OpYy~#I&B=ZlUB!X_Y!8_PPjYS)}wNYMJL$Wib}k7gKOs{frf-BDR923$!hrP z(DwGJV_#3HGVQ*bbeVw@7Ew@Br#Y*SCppdKX~k-386gs!HFVGdy74@WpQ zwIiW(f^Bu!^>8p1@g#8`Ox~wQ)dn=IeGkE^_7j_xNwvL#L1_*5VI*G!|2DeF^n)7D z;P@Hzw+&XIL!As%Um=We=J*X%?$soTW4f8Pz186+JWY#+?dJhCr8nvueE-)A$cm|} zGcCx~QazSQ45>fd44-|6gZEdnsKB?Q_V@WJNQ$v^LxJZX=?0;Le`zWQJKjsC7N zF!S!cUs2{icO!)Vv{0|%IVE-_o4h0wbSAejIgb?LhQNdZMeyUnY8LSy5|m%fJ``HI zs3-r2BX~8bs_5;;c5BG>6#oZ?*ft|}-W}T`9VK0pj^Vi3XZ$N2A~37_h?wKx2KRj@ z{;~})E51*7MB6q$%S&njwB$hZp;4Rhikr|rhRQ-YEmO_i~JyCnBB#`Fkh}c0o31q05x^}nWcp0lOpf&u5d%aXa z9spUi@h~B&5?2=)6*KM>nzupx@VJutWc8~d(y9wIvj@b|aV6omA*@#Bh4D0L@-*a@ z!|E`Nc!DYX_i~~S!2(cbI{I3g>ujgC)n+B8C_u0$<$M|cNG_r8ipRu`BdP1J)z?0`RG+$X=d1XN)w>m4 zf$7ndy9YK_0YT8`vKkjYp_VU|&xB!Ltka%*Q9x9vBiV7ljP_j5mHuzJ1La4Zgz0Xi zYHC97$0=^oq}dA745=M*u+|LwR4#f=_gy$Q1-Qe*G$92-IOrc{*e}l4hwrlB1TmjJ z(q2zkC2YLhE0_Nn0{lOD?Z?!h@gVxA#GyKrX3zG3TLArLd!N2n7aG1-7yJg*j{5@b zNKw2%=wUqbFgE-L_zGr*(%fpBplb>i13|KHG^ z`=i}ovT8s6CRK8^y=yz#2>-%?W)^H1`(B%O0(s`3pd%r)pqRcfcCrF#ED(p_ zJ9y*w_TX&nzNKN`@e4_v2R>aBO5biWNNWwX{Hi2!gv-!u_+`eIA_d;q(_nNRD9}dp zy06>+YVXRUq2BxdAdM1JYAjjCp0y1{VYsekDuzmfFhxR>gk(3e6iE}ZwU`i*%Umgn zvSn`}OCw7dME1#GFf%=$X}Qnso?HEX=iK|8^W3LDzUSlnHD}Iz*7x#yz20AI0=8LI zL%6<2+CdK)QMU@YgZ$^d5hf*YFZE<$q1*CCG%bqElsdB%#q3@rqS1No^sd^|ETPuM zpAVQC9gcL+5n^V|v5r1m{^kwtNy>>6a<1|T(K`zo9L&tn3pMH?=RX-rw*U42GM4Of zSbK_68!^Y^)-c&O|I&13;GtXPVqYIq&0Y>`+1*v+gHydbDxtVPBWIGQl9ZzHOv!HT z!P3^F&qu_vWrKz^mGGDYL*sh>Y$?z-84b&8t!ukR?b9*;_h6@WFxNz$-% z6}JG61q9Nd6T(H-pphcfEt|EqTyORHoxhr?oA2kiK&9_>+&1zpmB81`%=exT>B{39 z)TjuiZv!JYHy>o#8SzK}%9Ae;8$-0Am56sL0E-0NkCEK#Z0LRs{v&cfb31U)bS{vt zgABud;qUH!&(}zBo_Zt4N`PHZwKM(l9oXZyv2SgdVjg$58LjAPDT135a%yt z7k`)5mh*Qf2W$Ru(j}TJ zZoemT4Y8%nzY+>(=TEZ0nWVsVXBv8;>8$ti;u4ipU5TP~`$Rp?iPtX%_;c9LETh_1 ziZ$2YF_b=w*>|a89{w)Vy9`DhnvWP<_M#PYTsaH{PNqld zR_ajF*)&{$XVUt3SfZpap@%>l#Sy6JnyCDQ3H5a@GTItX!}#$%A_JqILAg%{V~1jI z#-{W{sXR3U0CarYwR!cH$z|kuvd#7J;-q->)Jwb-}qD5mj{eW7*d>m*{-yEXXKV5I$AKXA zq?||vRSKg4h1Cw!2Gu_{iu=QZ672fz0F;6wc73nzmVMOZ=ZXBS{T(O&tM&5A!stL$ zD$Rd=7Nj|iGy)g?po)qYA%loS^79ORua&A4CPC=Y{a!b4&pbFCYNwM3;_#9?ENJWm zO@qdLgdS!9^ntOu#8aE|w_b!QJkEe+t~fIz2T#j$nZLrH0|+QiP8X&hXYi+;bKn{7 zx@C^j{ixOgHg(x0+a}i?&)n26HQrL97AyPqQpwQfjDAF& zMfTg84$Zz!JK6f$_KAm@x1U%6W2-N~ea$V*sy@aVxg|#NK6#@jJFJcDU9DhF;te#2 z7fbI3uMOht6hp7r-Q~9Qy~rmj7fsBUn{Zu34Gwg?QUfY40!C;M<0M0xh6bgk|jPkJqYsECbZa+`mFCsztky8D@AX)HpOlDT1v^I_CY=;NcsB z*H5|H-}mIh?|6)NU6Eyq(2tPyjv2muC+zX++zS`!4UA_23BH&K#rF`&UJ$F1{mSFa zq1Qlx??(hyXgt2RfTfQA_um?w7PbTbECDfEwin)9(ONU<)ev?3Si6yS#M)uJf=w%SnqCbwJMFu~W1A z{!gf*!m@+cmiXKK&ns{1YEMQLO;!OiKHKzwQT_V$%Y?fL;b1H4iENC7n5Gk?FT_~) z5!z#H!bW|cX`VTy+wKLRU3}$ZeigF&2>N9Me#-X6cKcx=0D;UQ7gw4Bh@+1F z;)^@7t0CzA<1x$96a+7=Fg@^St4hnz(1D_qC>fDPq-Z3a~c(y6=W z%U_s|by*+%3R~qE>$flLUY)}&VVU0IJ^Y422G;AR&H?q+nvQ#U435&9(T{6`_P6eV zrMTqh*4T5kF}6-@Z1p;vx=}`?bLVn#LOD9Py|G>XD-%X;*4D_O$4%=WUf##kt9(Qj zzmL#-WXYUce5YASyL#AP2qwb&&G3|Ym9XFqE_iVShnaz$21G)5=*^e5kTPhRM1$RPQ zxOvwputh1{e#VtdSm6AQ?uM#h3a7DGOm)z5CG$bxzyFNA4;9lt zG)$mP=!zain;+7Kdraln4!=shHvfy zQagMW*n^7#=e010ethFs2mF6|9JO&3M4s6xKHpBVeY^KnTy^O7J&Li{CimWO3aJ=O zogKfQezD!)rxzfJ{=pW;(a+t)j-?81^FJkV>dld$tD)0sqlVr<%iM&V&I>#U*h#?8 z!vmawk`30S8>M$~8F7gTGA(edfdv4rX26Oh*Ob#%Am>>~mJ)$};I%3^Sis>@4h#m> zlBTiF7M6S`IDn`(__r=_m-Jz-l`Js&V-}gb=W#Xq+*L9RVNIOfPk&@1ulkTDjev zx2{7b!-W`1Q}AKL;b`D&u0=eLP80Kn_ZUtmRksB7J0tSnM%4}S9qSAfdE}t`>UO2@ zq|}AtnHnKIzX&$1&oF~o4*)H{2WOBlUj@%mDiqCHGTKZhAuDfrAWU)=P5*m z^9=kYIfStXgs??{W^+{CF`QU+vbJE~14b>fPdYqg031ypU+56Drca!AiMOigg-P-Q z;(Y57uf#!E#i3yDfmE($P*>E_jW>VH7e?IX58t~P1QWsXWzk|DdwcbxzXIuf({KKk zPyG-49~Y6DSfZ`de>J!L&<2?&;rkD8tFx`r%_B2@<$~;Q{~M5p&ra$;r9DEA zwj$^^pO_Wdl6+|#@!G43@cdqGo$e+aD`=uDig!qoIbMMn&{_#=cAiO-)P6~E-FQMa z^{A?BzFqRQIFRP+)owfWseU@?ARU=@{QTI#gw5E^dgvQNgyA#v_3v_bTDy}Z@15Db zTP@sByg?F1eiWpY;Tr4Gsgr-5f1AFrErFtgVwjoAFRm*8dOe1}j$!d%ejsw}wro4x za;o&|!gHC>t%LrHuxcuH>#^;v$82J1W*?up;>TOi#HFPvQQ>j10+YkQlIINE(kd9` zQ@8346E7p`HcZ0@y-{qy1mr&TxFaEAsSvR^7p@n&0wY+rmqYDY*dFVAnfku^-aa)N zkyqR6#W)hZmF5qA*8F?)_KK|+QvTk_#wep zJUW+7mM0I7ng*b&6=&t9s}rx--JI#RBPu?;tXi-oaf8G|ST*@PzDkaQSmeUudlR!l z>e7pl{Q^`Nlf%7y>WKw-lTA`2euNKT(!n;_Mmlhi-TUx__rntc{pW`uIMBmQExl`l z_+pIQ@YRW@A!|i--=c3iCNfTLnUyX}j1km)scwEdY$f!N^7Aq{-C+P#RN6+GNafAB z+W2# + + +