├── config.py ├── examples └── G4_MariaDB_test │ ├── Main.tscn │ ├── project.godot │ ├── icon.svg.import │ ├── main.gd │ ├── icon.svg │ └── create_db.sql.txt ├── SCsub ├── LICENSE.md ├── register_types.h ├── README.md ├── ed25519_ref10 ├── ed25519_sc.h ├── ed25519_auth.h ├── ed25519_fe.h ├── ed25519_sign.cpp ├── ed25519_ge.h ├── ed25519_auth.cpp ├── ed25519_ge.cpp ├── ed25519_sc.cpp └── ed25519_fe.cpp ├── register_types.cpp ├── mariadb_auth.h ├── mariadb_auth.cpp ├── mariadb_conversions.h ├── .gitignore ├── mariadb.h └── mariadb.cpp /config.py: -------------------------------------------------------------------------------- 1 | def can_build(env, platform): 2 | return True 3 | 4 | def configure(env): 5 | pass 6 | -------------------------------------------------------------------------------- /examples/G4_MariaDB_test/Main.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=3 uid="uid://bnx22kqnnvyxf"] 2 | 3 | [ext_resource type="Script" path="res://main.gd" id="1_gmex7"] 4 | 5 | [node name="Main" type="Node2D"] 6 | script = ExtResource("1_gmex7") 7 | 8 | [node name="Timer" type="Timer" parent="."] 9 | unique_name_in_owner = true 10 | wait_time = 0.1 11 | 12 | [connection signal="timeout" from="Timer" to="." method="_on_timer_timeout"] 13 | -------------------------------------------------------------------------------- /SCsub: -------------------------------------------------------------------------------- 1 | Import('env') 2 | Import("env_modules") 3 | 4 | env.Append(CPPPATH=["#thirdparty/mbedtls/include/", "ed25519_ref10/"]) 5 | 6 | 7 | # Make includes relative to the folder path specified here so our includes are clean 8 | env.Prepend(CPPPATH=["#modules/mariadb/"]) 9 | 10 | env.add_source_files(env.modules_sources, "*.cpp") # Add all cpp files to the build 11 | env.add_source_files(env.modules_sources, "ed25519_ref10/*.cpp") # Add all cpp files to the build 12 | -------------------------------------------------------------------------------- /examples/G4_MariaDB_test/project.godot: -------------------------------------------------------------------------------- 1 | ; Engine configuration file. 2 | ; It's best edited using the editor UI and not directly, 3 | ; since the parameters that go here are not all obvious. 4 | ; 5 | ; Format: 6 | ; [section] ; section goes between [] 7 | ; param=value ; assign values to parameters 8 | 9 | config_version=5 10 | 11 | [application] 12 | 13 | config/name="G4_MariaDB_test" 14 | run/main_scene="res://Main.tscn" 15 | config/features=PackedStringArray("4.2") 16 | config/icon="res://icon.svg" 17 | 18 | [filesystem] 19 | 20 | import/blender/enabled=false 21 | import/fbx/enabled=false 22 | -------------------------------------------------------------------------------- /examples/G4_MariaDB_test/icon.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://bedkr75tqprf3" 6 | path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://icon.svg" 14 | dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/lossy_quality=0.7 20 | compress/hdr_compression=1 21 | compress/bptc_ldr=0 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | svg/scale=1.0 36 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Shawn Shipton 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /register_types.h: -------------------------------------------------------------------------------- 1 | void register_mariadb_types(); 2 | void unregister_mariadb_types(); 3 | 4 | /*************************************************************************/ 5 | /* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ 6 | /* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ 7 | /* */ 8 | /* Permission is hereby granted, free of charge, to any person obtaining */ 9 | /* a copy of this software and associated documentation files (the */ 10 | /* "Software"), to deal in the Software without restriction, including */ 11 | /* without limitation the rights to use, copy, modify, merge, publish, */ 12 | /* distribute, sublicense, and/or sell copies of the Software, and to */ 13 | /* permit persons to whom the Software is furnished to do so, subject to */ 14 | /* the following conditions: */ 15 | /* */ 16 | /* The above copyright notice and this permission notice shall be */ 17 | /* included in all copies or substantial portions of the Software. */ 18 | /* */ 19 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 20 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 21 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ 22 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 23 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 24 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 25 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 26 | /*************************************************************************/ 27 | 28 | #ifndef MARIADB_REGISTER_TYPES_H 29 | #define MARIADB_REGISTER_TYPES_H 30 | 31 | #include "modules/register_module_types.h" 32 | 33 | void initialize_mariadb_module(ModuleInitializationLevel p_level); 34 | void uninitialize_mariadb_module(ModuleInitializationLevel p_level); 35 | 36 | #endif // MARIADB_REGISTER_TYPES_H 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

Announcement

2 |

3 | 4 | Godot MariaDB Connector Plugin 5 | 6 |

7 |

Now available on the Godot AssetLib version 4.3+

8 | # godot-mariadb 9 | A Godot engine module for MariaDB that is a MIT licensed connector separate from the Maria/MySQL GPL connectors. 10 | This module will compile on Linux, Windows, probably Mac. However, it is extremely suggested that you use this on Linux, there have been reports of unconfirmed Windows issues. 11 | 12 | Originally created for Godot 3.4 and currently works on 3.5.3 and 4.1.3, the main branch will stay current with Godot stable releases for Godot 3.x checkout the relevant release or branch. 13 | 14 | **To compile on to a stable version you will need to clone the Godot repo...** 15 | git clone https://github.com/godotengine/godot.git 16 | 17 | **List the stable releases with...** 18 | git tag 19 | **-or- find a major release with, eg 4.x-stable** 20 | git tag -l '4.\*stable' 21 | 22 | **Checkout the stable release you want, in this case 4.0.3-stable...** 23 | git checkout 4.0.3-stable 24 | 25 | **Change to the modules directory...** 26 | cd modules 27 | 28 | **Clone this repo as a git submodule...** 29 | git submodule add https://github.com/sigrudds1/godot-mariadb.git mariadb 30 | 31 | **Change to the just created mariadb directory...** 32 | cd mariadb 33 | 34 | **Find the relevant release to the Godot version...** 35 | git tag 36 | 37 | **Checkout/switch to the relevant release, e.g. match Godot 4.0.4-stable, git version 2.23+** 38 | git checkout v4.0.3 39 | 40 | **Alternately you can use a branch rather than release...** 41 | git branch -v -a 42 | 43 | **Checkout the branch, e.g. 4.x, git version 2.23+** 44 | git checkout 4.x 45 | 46 | **Change back to the main Godot directory...** 47 | cd ../.. 48 | 49 | **Compile Godot, e.g. editor version Linux 64 bit, see the Godot manual for compilation instructions for other releases and export templates, make sure you're on the correct manual version.** 50 | Godot 4.x 51 | scons -j$(nproc) platform=linuxbsd target=editor arch=x86_64 52 | Godot 3.x 53 | scons -j$(nproc) platform=x11 54 | 55 | [Buy Me A Coffee](https://buymeacoffee.com/VikingTinkerer) 56 | or 57 | [Buy Me A Ko-Fi](https://ko-fi.com/vikingtinkerer) 58 | 59 | -------------------------------------------------------------------------------- /ed25519_ref10/ed25519_sc.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************/ 2 | /* ed25519_sc.h */ 3 | /*************************************************************************/ 4 | /* This file is part of: */ 5 | /* GODOT ENGINE */ 6 | /* https://godotengine.org */ 7 | /*************************************************************************/ 8 | /* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ 9 | /* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ 10 | /* */ 11 | /* Permission is hereby granted, free of charge, to any person obtaining */ 12 | /* a copy of this software and associated documentation files (the */ 13 | /* "Software"), to deal in the Software without restriction, including */ 14 | /* without limitation the rights to use, copy, modify, merge, publish, */ 15 | /* distribute, sublicense, and/or sell copies of the Software, and to */ 16 | /* permit persons to whom the Software is furnished to do so, subject to */ 17 | /* the following conditions: */ 18 | /* */ 19 | /* The above copyright notice and this permission notice shall be */ 20 | /* included in all copies or substantial portions of the Software. */ 21 | /* */ 22 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 23 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 24 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ 25 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 26 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 27 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 28 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 29 | /*************************************************************************/ 30 | 31 | /* This file was derived from information found at */ 32 | /* https://tools.ietf.org/html/rfc8032#page-44 */ 33 | 34 | #ifndef ED25519_SC_H 35 | #define ED25519_SC_H 36 | 37 | #include 38 | 39 | void sc_reduce(uint8_t *s); 40 | void sc_muladd(uint8_t *s, const uint8_t *a, const uint8_t *b, const uint8_t *c); 41 | 42 | #endif // !ED25519_SC_H 43 | -------------------------------------------------------------------------------- /register_types.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************/ 2 | /* register_types.cpp */ 3 | /*************************************************************************/ 4 | /* This file is part of: */ 5 | /* GODOT ENGINE */ 6 | /* https://godotengine.org */ 7 | /*************************************************************************/ 8 | /* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ 9 | /* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ 10 | /* */ 11 | /* Permission is hereby granted, free of charge, to any person obtaining */ 12 | /* a copy of this software and associated documentation files (the */ 13 | /* "Software"), to deal in the Software without restriction, including */ 14 | /* without limitation the rights to use, copy, modify, merge, publish, */ 15 | /* distribute, sublicense, and/or sell copies of the Software, and to */ 16 | /* permit persons to whom the Software is furnished to do so, subject to */ 17 | /* the following conditions: */ 18 | /* */ 19 | /* The above copyright notice and this permission notice shall be */ 20 | /* included in all copies or substantial portions of the Software. */ 21 | /* */ 22 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 23 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 24 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ 25 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 26 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 27 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 28 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 29 | /*************************************************************************/ 30 | 31 | #include "register_types.h" 32 | #include "mariadb.h" 33 | 34 | 35 | void initialize_mariadb_module(ModuleInitializationLevel p_level) { 36 | if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) { 37 | return; 38 | } 39 | GDREGISTER_CLASS(MariaDB); 40 | } 41 | 42 | void uninitialize_mariadb_module(ModuleInitializationLevel p_level) { 43 | if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) { 44 | return; 45 | } 46 | 47 | 48 | } 49 | -------------------------------------------------------------------------------- /mariadb_auth.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************/ 2 | /* mariadb_auth.h */ 3 | /*************************************************************************/ 4 | /* This file is part of: */ 5 | /* GODOT ENGINE */ 6 | /* https://godotengine.org */ 7 | /*************************************************************************/ 8 | /* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ 9 | /* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ 10 | /* */ 11 | /* Permission is hereby granted, free of charge, to any person obtaining */ 12 | /* a copy of this software and associated documentation files (the */ 13 | /* "Software"), to deal in the Software without restriction, including */ 14 | /* without limitation the rights to use, copy, modify, merge, publish, */ 15 | /* distribute, sublicense, and/or sell copies of the Software, and to */ 16 | /* permit persons to whom the Software is furnished to do so, subject to */ 17 | /* the following conditions: */ 18 | /* */ 19 | /* The above copyright notice and this permission notice shall be */ 20 | /* included in all copies or substantial portions of the Software. */ 21 | /* */ 22 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 23 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 24 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ 25 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 26 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 27 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 28 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 29 | /*************************************************************************/ 30 | 31 | #ifndef MARIADB_AUTH_H 32 | #define MARIADB_AUTH_H 33 | 34 | #include "core/templates/vector.h" 35 | 36 | Vector get_caching_sha2_passwd_hash(Vector p_sha256_hashed_passwd, Vector p_srvr_salt); 37 | 38 | Vector get_client_ed25519_signature(Vector p_sha512_hashed_passwd, Vector p_svr_msg); 39 | 40 | Vector get_mysql_native_password_hash(Vector p_sha1_hashed_passwd, Vector p_srvr_salt); 41 | 42 | #endif // !MARIADB_AUTH_H 43 | -------------------------------------------------------------------------------- /examples/G4_MariaDB_test/main.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | 3 | # See the create_db.sql file to insall the data needed for this test 4 | # Run the insert record functions once, then comment it out. 5 | 6 | var ed:Dictionary = { 7 | "db_plain_text_pwd": "secret", 8 | "db_sha512_hashed_pwd": "bd2b1aaf7ef4f09be9f52ce2d8d599674d81aa9d6a4421696dc4d93dd0619d682ce56b4d64a9ef097761ced99e0f67265b5f76085e5b0ee7ca4696b2ad6fe2b2", 9 | "db_hostname": "127.0.0.1", 10 | "db_max_conns": 5, 11 | "db_name": "Godot_Test", 12 | "db_port": 3306, 13 | "db_user": "godot_user" 14 | } 15 | 16 | var qry_stmt_array: PackedStringArray = [ 17 | "SELECT * FROM Godot_Test.many_records;", 18 | "SELECT * FROM Godot_Test.many_columns;" 19 | ] 20 | 21 | var query_tmr: float = 0 22 | var itr: int = 0 23 | var db: MariaDB 24 | 25 | func _ready() -> void: 26 | db = MariaDB.new() 27 | _connect_to_db_srvr() 28 | # _insert_many_columns() 29 | # _insert_many_records() 30 | %Timer.start() 31 | # _run_db() 32 | 33 | func _exit_tree() -> void: 34 | db.disconnect_db() 35 | 36 | 37 | func print_db_response(pba: PackedByteArray) -> void: 38 | for idx in range(pba.size() - 1, -1, -1): 39 | if pba[idx] < 32: 40 | pba.remove_at(idx) 41 | print(pba.get_string_from_ascii()) 42 | 43 | 44 | func _run_db() -> void: 45 | if !db.is_connected_db(): 46 | _connect_to_db_srvr() 47 | else: 48 | var start_uticks := Time.get_ticks_usec() 49 | var stmt: String = qry_stmt_array[itr % qry_stmt_array.size()] 50 | # var stmt: String = qry_stmt_array[0] 51 | # print(stmt) 52 | var qry = db.query(stmt) 53 | if typeof(qry) == TYPE_ARRAY: 54 | var end_uticks := Time.get_ticks_usec() 55 | print("total records received:", qry.size(), " time:", Time.get_ticks_usec() - start_uticks, " usecs itr:", itr) 56 | else: 57 | %Timer.stop() 58 | print(stmt) 59 | print("itr:", itr, " - ERROR:", qry) 60 | 61 | itr += 1 62 | 63 | 64 | func _connect_to_db_srvr() -> void: 65 | var err = db.connect_db( 66 | ed["db_hostname"], 67 | ed["db_port"], 68 | ed["db_name"], 69 | ed["db_user"], 70 | ed["db_sha512_hashed_pwd"], 71 | MariaDB.AUTH_TYPE_ED25519, 72 | true 73 | ); 74 | if err: 75 | print("db connect err:", err) 76 | 77 | 78 | func _insert_many_columns() -> void: 79 | var stmt: String = "INSERT INTO Godot_Test.many_columns VALUES " 80 | for i in range(1, 253): 81 | stmt += "(%d)" % i 82 | 83 | stmt += ";" 84 | print(stmt) 85 | var err = db.query(stmt) 86 | if err != OK: 87 | printerr("Insert fail:" , err) 88 | 89 | 90 | func _insert_many_records() -> void: 91 | var stmt: String = "INSERT INTO Godot_Test.`many_records (type, zone_id, player_id, map_id, " +\ 92 | "text_field) VALUES " 93 | for i in 10: 94 | stmt += "(%d, %d, %d, %d, %s)" % [i * 10 + 1, i * 10 + 2, i * 10 + 3, i * 10 + 4, "Some text for record %d" % i] 95 | 96 | stmt += ";" 97 | print(stmt) 98 | var err = db.query(stmt) 99 | if err != OK: 100 | printerr("Insert fail:" , err) 101 | 102 | 103 | func _on_timer_timeout() -> void: 104 | _run_db() 105 | -------------------------------------------------------------------------------- /ed25519_ref10/ed25519_auth.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************/ 2 | /* ed25519_auth.h */ 3 | /*************************************************************************/ 4 | /* This file is part of: */ 5 | /* GODOT ENGINE */ 6 | /* https://godotengine.org */ 7 | /*************************************************************************/ 8 | /* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ 9 | /* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ 10 | /* */ 11 | /* Permission is hereby granted, free of charge, to any person obtaining */ 12 | /* a copy of this software and associated documentation files (the */ 13 | /* "Software"), to deal in the Software without restriction, including */ 14 | /* without limitation the rights to use, copy, modify, merge, publish, */ 15 | /* distribute, sublicense, and/or sell copies of the Software, and to */ 16 | /* permit persons to whom the Software is furnished to do so, subject to */ 17 | /* the following conditions: */ 18 | /* */ 19 | /* The above copyright notice and this permission notice shall be */ 20 | /* included in all copies or substantial portions of the Software. */ 21 | /* */ 22 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 23 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 24 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ 25 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 26 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 27 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 28 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 29 | /*************************************************************************/ 30 | 31 | /* This file was derived from information found at */ 32 | /* https://tools.ietf.org/html/rfc8032#page-44 */ 33 | /* REF https://security.stackexchange.com/questions/218046/how-does-mariadbs-ed25519-auth-scheme-work */ 34 | 35 | #ifndef ED25519_AUTH_H 36 | #define ED25519_AUTH_H 37 | 38 | #include 39 | #include 40 | 41 | void ed25519_sign_msg(const uint8_t *pwd_sha512_src, const uint8_t *message_src, size_t message_len, uint8_t *signature_dst); 42 | void ed25519_create_keypair(const uint8_t *pwd_sha512_src, uint8_t *private_key_dst, uint8_t *public_key_dst); 43 | void ed25519_sign(const uint8_t *message_src, size_t message_len, const uint8_t *public_key_src, const uint8_t *private_key_src, uint8_t *signature_dst); 44 | 45 | 46 | #endif // !ED25519_AUTH_H 47 | -------------------------------------------------------------------------------- /ed25519_ref10/ed25519_fe.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************/ 2 | /* ed25519_fe.h */ 3 | /*************************************************************************/ 4 | /* This file is part of: */ 5 | /* GODOT ENGINE */ 6 | /* https://godotengine.org */ 7 | /*************************************************************************/ 8 | /* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ 9 | /* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ 10 | /* */ 11 | /* Permission is hereby granted, free of charge, to any person obtaining */ 12 | /* a copy of this software and associated documentation files (the */ 13 | /* "Software"), to deal in the Software without restriction, including */ 14 | /* without limitation the rights to use, copy, modify, merge, publish, */ 15 | /* distribute, sublicense, and/or sell copies of the Software, and to */ 16 | /* permit persons to whom the Software is furnished to do so, subject to */ 17 | /* the following conditions: */ 18 | /* */ 19 | /* The above copyright notice and this permission notice shall be */ 20 | /* included in all copies or substantial portions of the Software. */ 21 | /* */ 22 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 23 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 24 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ 25 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 26 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 27 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 28 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 29 | /*************************************************************************/ 30 | 31 | /* This file was derived from information found at */ 32 | /* https://tools.ietf.org/html/rfc8032 */ 33 | 34 | //REF https://tools.ietf.org/html/rfc8032#page-13 35 | 36 | #ifndef ED25519_FE_H 37 | #define ED25519_FE_H 38 | 39 | #include 40 | 41 | typedef int32_t fe[10]; 42 | 43 | void fe_0(fe h); 44 | void fe_1(fe h); 45 | 46 | void fe_frombytes(fe h, const uint8_t *s); 47 | void fe_tobytes(uint8_t *s, const fe h); 48 | 49 | void fe_copy(fe h, const fe f); 50 | int fe_isnegative(const fe f); 51 | int fe_isnonzero(const fe f); 52 | void fe_cmov(fe f, const fe g, unsigned int b); 53 | void fe_cswap(fe f, fe g, unsigned int b); 54 | 55 | void fe_neg(fe h, const fe f); 56 | void fe_add(fe h, const fe f, const fe g); 57 | void fe_invert(fe out, const fe z); 58 | void fe_sq(fe h, const fe f); 59 | void fe_sq2(fe h, const fe f); 60 | void fe_mul(fe h, const fe f, const fe g); 61 | void fe_mul121666(fe h, fe f); 62 | void fe_pow22523(fe out, const fe z); 63 | void fe_sub(fe h, const fe f, const fe g); 64 | 65 | #endif // !ED25519_FE_H 66 | -------------------------------------------------------------------------------- /mariadb_auth.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************/ 2 | /* mariadb_auth.cpp */ 3 | /*************************************************************************/ 4 | /* This file is part of: */ 5 | /* GODOT ENGINE */ 6 | /* https://godotengine.org */ 7 | /*************************************************************************/ 8 | /* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ 9 | /* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ 10 | /* */ 11 | /* Permission is hereby granted, free of charge, to any person obtaining */ 12 | /* a copy of this software and associated documentation files (the */ 13 | /* "Software"), to deal in the Software without restriction, including */ 14 | /* without limitation the rights to use, copy, modify, merge, publish, */ 15 | /* distribute, sublicense, and/or sell copies of the Software, and to */ 16 | /* permit persons to whom the Software is furnished to do so, subject to */ 17 | /* the following conditions: */ 18 | /* */ 19 | /* The above copyright notice and this permission notice shall be */ 20 | /* included in all copies or substantial portions of the Software. */ 21 | /* */ 22 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 23 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 24 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ 25 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 26 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 27 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 28 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 29 | /*************************************************************************/ 30 | 31 | #include "mariadb_auth.h" 32 | #include "ed25519_ref10/ed25519_auth.h" 33 | #include 34 | 35 | 36 | Vector get_client_ed25519_signature(const Vector p_sha512_hashed_passwd, const Vector p_svr_msg) { 37 | //MySQL does not supprt this auth method 38 | Vector rtn_val; 39 | rtn_val.resize(64); 40 | ed25519_sign_msg(p_sha512_hashed_passwd.ptr(), p_svr_msg.ptr(), 32, rtn_val.ptrw()); 41 | return rtn_val; 42 | } 43 | 44 | Vector get_mysql_native_password_hash(Vector p_sha1_hashed_passwd, Vector p_srvr_salt) { 45 | //per https://mariadb.com/kb/en/connection/#mysql_native_password-plugin 46 | //Both MariaDB and MySQL support this auth method 47 | uint8_t hash[20] = {}; 48 | CryptoCore::sha1(p_sha1_hashed_passwd.ptr(), 20, hash); 49 | uint8_t combined_salt_pwd[40] = {}; 50 | for (size_t i = 0; i < 20; i++) { 51 | combined_salt_pwd[i] = p_srvr_salt[i]; 52 | combined_salt_pwd[i + 20] = hash[i]; 53 | } 54 | 55 | CryptoCore::sha1((const uint8_t *)combined_salt_pwd, 40, hash); 56 | Vector hash_out; 57 | for (size_t i = 0; i < 20; i++) { 58 | hash_out.push_back(p_sha1_hashed_passwd[i] ^ hash[i]); 59 | } 60 | 61 | return hash_out; 62 | } 63 | -------------------------------------------------------------------------------- /ed25519_ref10/ed25519_sign.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************/ 2 | /* ed25519_sign.cpp */ 3 | /*************************************************************************/ 4 | /* This file is part of: */ 5 | /* GODOT ENGINE */ 6 | /* https://godotengine.org */ 7 | /*************************************************************************/ 8 | /* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ 9 | /* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ 10 | /* */ 11 | /* Permission is hereby granted, free of charge, to any person obtaining */ 12 | /* a copy of this software and associated documentation files (the */ 13 | /* "Software"), to deal in the Software without restriction, including */ 14 | /* without limitation the rights to use, copy, modify, merge, publish, */ 15 | /* distribute, sublicense, and/or sell copies of the Software, and to */ 16 | /* permit persons to whom the Software is furnished to do so, subject to */ 17 | /* the following conditions: */ 18 | /* */ 19 | /* The above copyright notice and this permission notice shall be */ 20 | /* included in all copies or substantial portions of the Software. */ 21 | /* */ 22 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 23 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 24 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ 25 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 26 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 27 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 28 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 29 | /*************************************************************************/ 30 | 31 | /* This file was derived from information found at */ 32 | /* https://tools.ietf.org/html/rfc8032#page-44 */ 33 | 34 | #include "ed25519_auth.h" 35 | #include "ed25519_ge.h" 36 | #include "ed25519_sc.h" 37 | 38 | #include 39 | #include 40 | 41 | void ed25519_sign(const uint8_t *message_src, size_t message_len, const uint8_t *public_key_src, const uint8_t *private_key_src, uint8_t *signature_dst) { 42 | //message_len should be 32 coming from server 43 | 44 | void *ctx = memalloc(sizeof(mbedtls_sha512_context)); 45 | uint8_t sha512[64]; 46 | uint8_t hram[64]; 47 | ge_p3 R; 48 | 49 | mbedtls_sha512_starts_ret((mbedtls_sha512_context *)ctx, 0); 50 | mbedtls_sha512_update_ret((mbedtls_sha512_context *)ctx, private_key_src + 32, 32); 51 | mbedtls_sha512_update_ret((mbedtls_sha512_context *)ctx, message_src, message_len); 52 | mbedtls_sha512_finish_ret((mbedtls_sha512_context *)ctx, sha512); 53 | mbedtls_sha512_free((mbedtls_sha512_context *)ctx); 54 | 55 | sc_reduce(sha512); 56 | ge_scalarmult_base(&R, sha512); 57 | ge_p3_tobytes(signature_dst, &R); 58 | 59 | mbedtls_sha512_starts_ret((mbedtls_sha512_context *)ctx, 0); 60 | mbedtls_sha512_update_ret((mbedtls_sha512_context *)ctx, signature_dst, 32); 61 | mbedtls_sha512_update_ret((mbedtls_sha512_context *)ctx, public_key_src, 32); 62 | mbedtls_sha512_update_ret((mbedtls_sha512_context *)ctx, message_src, message_len); 63 | mbedtls_sha512_finish_ret((mbedtls_sha512_context *)ctx, hram); 64 | mbedtls_sha512_free((mbedtls_sha512_context *)ctx); 65 | 66 | sc_reduce(hram); 67 | sc_muladd(signature_dst + 32, hram, private_key_src, sha512); 68 | 69 | memfree((mbedtls_sha512_context *)ctx); 70 | } 71 | -------------------------------------------------------------------------------- /examples/G4_MariaDB_test/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ed25519_ref10/ed25519_ge.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************/ 2 | /* ed25519_ge.h */ 3 | /*************************************************************************/ 4 | /* This file is part of the */ 5 | /* Maria and Mysql database connection module */ 6 | /* for use in the Godot Engine */ 7 | /* GODOT ENGINE */ 8 | /* https://godotengine.org */ 9 | /* This file was derived from information found at */ 10 | /* https://tools.ietf.org/html/rfc8032#page-44 */ 11 | /*************************************************************************/ 12 | /* Copyright (c) 2021 Shawn Shipton. https://vikingtinkerer.com */ 13 | /* */ 14 | /* Permission is hereby granted, free of charge, to any person obtaining */ 15 | /* a copy of this software and associated documentation files (the */ 16 | /* "Software"), to deal in the Software without restriction, including */ 17 | /* without limitation the rights to use, copy, modify, merge, publish, */ 18 | /* distribute, sublicense, and/or sell copies of the Software, and to */ 19 | /* permit persons to whom the Software is furnished to do so, subject to */ 20 | /* the following conditions: */ 21 | /* */ 22 | /* The above copyright notice and this permission notice shall be */ 23 | /* included in all copies or substantial portions of the Software. */ 24 | /* */ 25 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 26 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 27 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ 28 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 29 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 30 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 31 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 32 | /*************************************************************************/ 33 | 34 | #ifndef ED25519_GE_H 35 | #define ED25519_GE_H 36 | 37 | #include "ed25519_fe.h" 38 | 39 | /* 40 | ge means group element. 41 | 42 | Here the group is the set of pairs (x,y) of field elements (see fe.h) 43 | satisfying -x^2 + y^2 = 1 + d x^2y^2 44 | where d = -121665/121666. 45 | 46 | Representations: 47 | ge_p2 (projective): (X:Y:Z) satisfying x=X/Z, y=Y/Z 48 | ge_p3 (extended): (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT 49 | ge_p1p1 (completed): ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T 50 | ge_precomp (Duif): (y+x,y-x,2dxy) 51 | */ 52 | 53 | typedef struct { 54 | fe X; 55 | fe Y; 56 | fe Z; 57 | } ge_p2; 58 | 59 | typedef struct { 60 | fe X; 61 | fe Y; 62 | fe Z; 63 | fe T; 64 | } ge_p3; 65 | 66 | typedef struct { 67 | fe X; 68 | fe Y; 69 | fe Z; 70 | fe T; 71 | } ge_p1p1; 72 | 73 | typedef struct { 74 | fe yplusx; 75 | fe yminusx; 76 | fe xy2d; 77 | } ge_precomp; 78 | 79 | typedef struct { 80 | fe YplusX; 81 | fe YminusX; 82 | fe Z; 83 | fe T2d; 84 | } ge_cached; 85 | 86 | void ge_p3_tobytes(uint8_t *s, const ge_p3 *h); 87 | void ge_tobytes(uint8_t *s, const ge_p2 *h); 88 | int ge_frombytes_negate_vartime(ge_p3 *h, const uint8_t *s); 89 | 90 | void ge_add(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q); 91 | void ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q); 92 | void ge_double_scalarmult_vartime(ge_p2 *r, const uint8_t *a, const ge_p3 *A, const uint8_t *b); 93 | void ge_madd(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q); 94 | void ge_msub(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q); 95 | void ge_scalarmult_base(ge_p3 *h, const uint8_t *a); 96 | 97 | void ge_p1p1_to_p2(ge_p2 *r, const ge_p1p1 *p); 98 | void ge_p1p1_to_p3(ge_p3 *r, const ge_p1p1 *p); 99 | void ge_p2_0(ge_p2 *h); 100 | void ge_p2_dbl(ge_p1p1 *r, const ge_p2 *p); 101 | void ge_p3_0(ge_p3 *h); 102 | void ge_p3_dbl(ge_p1p1 *r, const ge_p3 *p); 103 | void ge_p3_to_cached(ge_cached *r, const ge_p3 *p); 104 | void ge_p3_to_p2(ge_p2 *r, const ge_p3 *p); 105 | 106 | #endif // !ED25519_GE_H 107 | -------------------------------------------------------------------------------- /mariadb_conversions.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************/ 2 | /* mariadb_conversions.h */ 3 | /*************************************************************************/ 4 | /* This file is part of: */ 5 | /* GODOT ENGINE */ 6 | /* https://godotengine.org */ 7 | /*************************************************************************/ 8 | /* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ 9 | /* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ 10 | /* */ 11 | /* Permission is hereby granted, free of charge, to any person obtaining */ 12 | /* a copy of this software and associated documentation files (the */ 13 | /* "Software"), to deal in the Software without restriction, including */ 14 | /* without limitation the rights to use, copy, modify, merge, publish, */ 15 | /* distribute, sublicense, and/or sell copies of the Software, and to */ 16 | /* permit persons to whom the Software is furnished to do so, subject to */ 17 | /* the following conditions: */ 18 | /* */ 19 | /* The above copyright notice and this permission notice shall be */ 20 | /* included in all copies or substantial portions of the Software. */ 21 | /* */ 22 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 23 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 24 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ 25 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 26 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 27 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 28 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 29 | /*************************************************************************/ 30 | 31 | #ifndef MARIADB_CONVERSIONS_H 32 | #define MARIADB_CONVERSIONS_H 33 | 34 | #include 35 | #include 36 | #include 37 | 38 | namespace { 39 | 40 | template 41 | inline T bytes_to_num_itr_pos(const uint8_t *src, const size_t byte_count, size_t &start_pos) { 42 | size_t count = byte_count; 43 | 44 | if (sizeof(T) < byte_count) 45 | count = sizeof(T); 46 | 47 | T result = 0; 48 | for (size_t i = 0; i < count; ++i) 49 | result |= static_cast(src[++start_pos]) << (i * 8); 50 | return result; 51 | } 52 | 53 | inline Vector hex_str_to_v_bytes(const String &hex_str) { 54 | Vector bytes; 55 | for (size_t i = 0; i < (size_t)hex_str.length(); i += 2) { 56 | String byteString = hex_str.substr(i, 2); 57 | uint8_t byte = (uint8_t)strtol(byteString.utf8().ptr(), NULL, 16); 58 | bytes.push_back(byte); 59 | } 60 | 61 | return bytes; 62 | } 63 | 64 | template 65 | inline Vector little_endian_to_vbytes(const T p_value, const size_t p_max_bytes = 0, 66 | const size_t p_start_idx = 0) { 67 | //little endian bytes 68 | size_t count = sizeof(T); 69 | if (p_max_bytes > 0 && p_max_bytes <= count) 70 | count = p_max_bytes; 71 | 72 | Vector vec; 73 | for (size_t i = 0 + p_start_idx; i < count + p_start_idx; i++) { 74 | vec.push_back((uint8_t)(p_value >> (i * 8)) & 0xff); 75 | } 76 | 77 | return vec; 78 | } 79 | 80 | // For testing 81 | // String vbytes_to_int_str(const PackedByteArray p_bytes, String p_delimiter = ",", 82 | // int p_out_len = 0, int p_start_idx = 0){ 83 | // int count = p_bytes.size(); 84 | // if (p_out_len > count) return ""; 85 | 86 | // if (p_out_len > 0) count = p_out_len + p_start_idx; 87 | // String out; 88 | // for (int idx = 0 + p_start_idx; idx < count; ++idx) out += itos(p_bytes[idx]) + p_delimiter; 89 | 90 | // return out; 91 | // } 92 | 93 | 94 | // TODO DO we need other character sets? 95 | // String vbytes_to_ascii_itr_at(const Vector &p_src_buf, size_t &p_last_pos, size_t p_byte_cnt) { 96 | // String rtn; 97 | // for (size_t itr = 0; itr < p_byte_cnt; ++itr) 98 | // rtn += p_src_buf[++p_last_pos]; 99 | 100 | // return rtn; 101 | // } 102 | 103 | // Thanks @gladman for testing and suggestion 104 | /** 105 | * \brief This method returns a string from packets using length encoding. 106 | * 107 | * \param src_buf const Vector packet buffer. 108 | * \param last_pos size_t packet buffer position iterator of the last position used, 109 | * this will be incremented by byte count. 110 | * \param byte_cnt size_t byte count to be copied from the packet buffer. 111 | * \return String. 112 | */ 113 | String vbytes_to_utf8_itr_at(const Vector &p_src_buf, size_t &p_last_pos, const size_t p_byte_cnt) { 114 | if (p_byte_cnt <= 0 || p_last_pos + p_byte_cnt > (size_t)p_src_buf.size()){ 115 | return ""; 116 | } 117 | 118 | String rtn_val; 119 | rtn_val.parse_utf8((const char *)p_src_buf.ptr() + p_last_pos + 1, p_byte_cnt); 120 | p_last_pos += p_byte_cnt; 121 | return rtn_val; 122 | } 123 | 124 | } //namespace 125 | #endif // !MARIADB_CONVERSIONS_H 126 | -------------------------------------------------------------------------------- /ed25519_ref10/ed25519_auth.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************/ 2 | /* ed25519_auth.cpp */ 3 | /*************************************************************************/ 4 | /* This file is part of: */ 5 | /* GODOT ENGINE */ 6 | /* https://godotengine.org */ 7 | /*************************************************************************/ 8 | /* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ 9 | /* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ 10 | /* */ 11 | /* Permission is hereby granted, free of charge, to any person obtaining */ 12 | /* a copy of this software and associated documentation files (the */ 13 | /* "Software"), to deal in the Software without restriction, including */ 14 | /* without limitation the rights to use, copy, modify, merge, publish, */ 15 | /* distribute, sublicense, and/or sell copies of the Software, and to */ 16 | /* permit persons to whom the Software is furnished to do so, subject to */ 17 | /* the following conditions: */ 18 | /* */ 19 | /* The above copyright notice and this permission notice shall be */ 20 | /* included in all copies or substantial portions of the Software. */ 21 | /* */ 22 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 23 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 24 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ 25 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 26 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 27 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 28 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 29 | /*************************************************************************/ 30 | 31 | /* This file was derived from information found at */ 32 | /* https://tools.ietf.org/html/rfc8032 */ 33 | 34 | #include "ed25519_auth.h" 35 | #include "ed25519_ge.h" 36 | 37 | #include 38 | 39 | void ed25519_sign_msg(const uint8_t *pwd_sha512_src, const uint8_t *message_src, size_t message_len, uint8_t *signature_dst) { 40 | uint8_t private_key[64]; 41 | uint8_t public_key[64]; 42 | 43 | ed25519_create_keypair(pwd_sha512_src, private_key, public_key); 44 | ed25519_sign(message_src, message_len, public_key, private_key, signature_dst); 45 | } 46 | 47 | void ed25519_create_keypair(const uint8_t *pwd_sha512_src, uint8_t *private_key_dst, uint8_t *public_key_dst) { 48 | /*REF RFC 8032 5.1.5 Key Generation https://tools.ietf.org/html/rfc8032#page-13 49 | * The referenced private key that is ran thru sha512 is the password, since we are storing the hashed password 50 | * in the module in case of a needed reconnection, the 1st step in RFC Key Generation will be skipped here. 51 | */ 52 | 53 | ge_p3 A; 54 | std::copy(pwd_sha512_src, pwd_sha512_src + 64, private_key_dst); 55 | 56 | /*Step 2 of the RFC 57 | * It references the first and last bits, but that is after pruning, 58 | * I cheated and skipped pruning and reused the variable for the scalar functions. 59 | */ 60 | private_key_dst[0] &= 248; 61 | private_key_dst[31] &= 63; 62 | private_key_dst[31] |= 64; 63 | 64 | ge_scalarmult_base(&A, private_key_dst); 65 | ge_p3_tobytes(public_key_dst, &A); //working, public key matched maria server. 66 | } 67 | 68 | //#include "core/templates/vector.h" 69 | // 70 | // 71 | //// 72 | //void ed25519_sign_msg(const Vector pwd_sha512_src, const Vector message_src, Vector signature_dst) { 73 | // Vector private_key; 74 | // Vector public_key; 75 | // 76 | // ed25519_create_keypair(pwd_sha512_src, private_key, public_key); 77 | // ed25519_sign(message_src.ptr(), message_src.size(), public_key.ptrw(), private_key.ptrw(), signature_dst.ptrw()); 78 | //} 79 | // 80 | //void ed25519_create_keypair(const Vector pwd_sha512_src, Vector private_key_dst, Vector public_key_dst) { 81 | // /*REF RFC 8032 5.1.5 Key Generation https://tools.ietf.org/html/rfc8032#page-13 82 | // * The referenced private key that is ran thru sha512 is the password, since we are storing the hashed password 83 | // * in the module in case of a needed reconnection, the 1st step in RFC Key Generation will be skipped here. 84 | // */ 85 | // 86 | // ge_p3 A; 87 | // private_key_dst = pwd_sha512_src.slice(0); 88 | // 89 | // /*Step 2 of the RFC 90 | // * It references the first and last bits, but that is after pruning, 91 | // * I cheated and skipped pruning and reused the variable for the scalar functions. 92 | // */ 93 | // private_key_dst.set(0, private_key_dst[0] & 248); 94 | // private_key_dst.set(31, private_key_dst[0] & 63); 95 | // private_key_dst.set(31, private_key_dst[0] | 248); 96 | // 97 | // 98 | // ge_scalarmult_base(&A, private_key_dst.ptr()); 99 | // ge_p3_tobytes(public_key_dst.ptrw(), &A); //working, public key matched maria server. 100 | //} 101 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Godot executables 2 | *.exe 3 | *.64 4 | *.x86_64 5 | *.app 6 | 7 | # Godot-specific ignores 8 | *.pck 9 | .import/ 10 | .godot/ 11 | */.import/ 12 | export.cfg 13 | export_presets.cfg 14 | 15 | ## Ignore Visual Studio temporary files, build results, and 16 | ## files generated by popular Visual Studio add-ons. 17 | ## 18 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 19 | 20 | # User-specific files 21 | *.rsuser 22 | *.suo 23 | *.user 24 | *.userosscache 25 | *.sln.docstates 26 | 27 | # User-specific files (MonoDevelop/Xamarin Studio) 28 | *.userprefs 29 | 30 | # Mono auto generated files 31 | mono_crash.* 32 | 33 | # Build results 34 | [Dd]ebug/ 35 | [Dd]ebugPublic/ 36 | [Rr]elease/ 37 | [Rr]eleases/ 38 | x64/ 39 | x86/ 40 | [Aa][Rr][Mm]/ 41 | [Aa][Rr][Mm]64/ 42 | bld/ 43 | [Bb]in/ 44 | [Oo]bj/ 45 | [Ll]og/ 46 | [Ll]ogs/ 47 | *.o 48 | 49 | # VSCode 50 | *.vscode 51 | 52 | # Visual Studio 2015/2017 cache/options directory 53 | .vs/ 54 | # Uncomment if you have tasks that create the project's static files in wwwroot 55 | #wwwroot/ 56 | 57 | # Visual Studio 2017 auto generated files 58 | Generated\ Files/ 59 | 60 | # MSTest test Results 61 | [Tt]est[Rr]esult*/ 62 | [Bb]uild[Ll]og.* 63 | 64 | # NUnit 65 | *.VisualState.xml 66 | TestResult.xml 67 | nunit-*.xml 68 | 69 | # Build Results of an ATL Project 70 | [Dd]ebugPS/ 71 | [Rr]eleasePS/ 72 | dlldata.c 73 | 74 | # Benchmark Results 75 | BenchmarkDotNet.Artifacts/ 76 | 77 | # .NET Core 78 | project.lock.json 79 | project.fragment.lock.json 80 | artifacts/ 81 | 82 | # StyleCop 83 | StyleCopReport.xml 84 | 85 | # Files built by Visual Studio 86 | *_i.c 87 | *_p.c 88 | *_h.h 89 | *.ilk 90 | *.meta 91 | *.obj 92 | *.iobj 93 | *.pch 94 | *.pdb 95 | *.ipdb 96 | *.pgc 97 | *.pgd 98 | *.rsp 99 | *.sbr 100 | *.tlb 101 | *.tli 102 | *.tlh 103 | *.tmp 104 | *.tmp_proj 105 | *_wpftmp.csproj 106 | *.log 107 | *.vspscc 108 | *.vssscc 109 | .builds 110 | *.pidb 111 | *.svclog 112 | *.scc 113 | 114 | # Chutzpah Test files 115 | _Chutzpah* 116 | 117 | # Visual C++ cache files 118 | ipch/ 119 | *.aps 120 | *.ncb 121 | *.opendb 122 | *.opensdf 123 | *.sdf 124 | *.cachefile 125 | *.VC.db 126 | *.VC.VC.opendb 127 | 128 | # Visual Studio profiler 129 | *.psess 130 | *.vsp 131 | *.vspx 132 | *.sap 133 | 134 | # Visual Studio Trace Files 135 | *.e2e 136 | 137 | # TFS 2012 Local Workspace 138 | $tf/ 139 | 140 | # Guidance Automation Toolkit 141 | *.gpState 142 | 143 | # ReSharper is a .NET coding add-in 144 | _ReSharper*/ 145 | *.[Rr]e[Ss]harper 146 | *.DotSettings.user 147 | 148 | # TeamCity is a build add-in 149 | _TeamCity* 150 | 151 | # DotCover is a Code Coverage Tool 152 | *.dotCover 153 | 154 | # AxoCover is a Code Coverage Tool 155 | .axoCover/* 156 | !.axoCover/settings.json 157 | 158 | # Visual Studio code coverage results 159 | *.coverage 160 | *.coveragexml 161 | 162 | # NCrunch 163 | _NCrunch_* 164 | .*crunch*.local.xml 165 | nCrunchTemp_* 166 | 167 | # MightyMoose 168 | *.mm.* 169 | AutoTest.Net/ 170 | 171 | # Web workbench (sass) 172 | .sass-cache/ 173 | 174 | # Installshield output folder 175 | [Ee]xpress/ 176 | 177 | # DocProject is a documentation generator add-in 178 | DocProject/buildhelp/ 179 | DocProject/Help/*.HxT 180 | DocProject/Help/*.HxC 181 | DocProject/Help/*.hhc 182 | DocProject/Help/*.hhk 183 | DocProject/Help/*.hhp 184 | DocProject/Help/Html2 185 | DocProject/Help/html 186 | 187 | # Click-Once directory 188 | publish/ 189 | 190 | # Publish Web Output 191 | *.[Pp]ublish.xml 192 | *.azurePubxml 193 | # Note: Comment the next line if you want to checkin your web deploy settings, 194 | # but database connection strings (with potential passwords) will be unencrypted 195 | *.pubxml 196 | *.publishproj 197 | 198 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 199 | # checkin your Azure Web App publish settings, but sensitive information contained 200 | # in these scripts will be unencrypted 201 | PublishScripts/ 202 | 203 | # NuGet Packages 204 | *.nupkg 205 | # NuGet Symbol Packages 206 | *.snupkg 207 | # The packages folder can be ignored because of Package Restore 208 | **/[Pp]ackages/* 209 | # except build/, which is used as an MSBuild target. 210 | !**/[Pp]ackages/build/ 211 | # Uncomment if necessary however generally it will be regenerated when needed 212 | #!**/[Pp]ackages/repositories.config 213 | # NuGet v3's project.json files produces more ignorable files 214 | *.nuget.props 215 | *.nuget.targets 216 | 217 | # Microsoft Azure Build Output 218 | csx/ 219 | *.build.csdef 220 | 221 | # Microsoft Azure Emulator 222 | ecf/ 223 | rcf/ 224 | 225 | # Windows Store app package directories and files 226 | AppPackages/ 227 | BundleArtifacts/ 228 | Package.StoreAssociation.xml 229 | _pkginfo.txt 230 | *.appx 231 | *.appxbundle 232 | *.appxupload 233 | 234 | # Visual Studio cache files 235 | # files ending in .cache can be ignored 236 | *.[Cc]ache 237 | # but keep track of directories ending in .cache 238 | !?*.[Cc]ache/ 239 | 240 | # Others 241 | ClientBin/ 242 | ~$* 243 | *~ 244 | *.dbmdl 245 | *.dbproj.schemaview 246 | *.jfm 247 | *.pfx 248 | *.publishsettings 249 | orleans.codegen.cs 250 | 251 | # Including strong name files can present a security risk 252 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 253 | #*.snk 254 | 255 | # Since there are multiple workflows, uncomment next line to ignore bower_components 256 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 257 | #bower_components/ 258 | 259 | # RIA/Silverlight projects 260 | Generated_Code/ 261 | 262 | # Backup & report files from converting an old project file 263 | # to a newer Visual Studio version. Backup files are not needed, 264 | # because we have git ;-) 265 | _UpgradeReport_Files/ 266 | Backup*/ 267 | UpgradeLog*.XML 268 | UpgradeLog*.htm 269 | ServiceFabricBackup/ 270 | *.rptproj.bak 271 | 272 | # SQL Server files 273 | *.mdf 274 | *.ldf 275 | *.ndf 276 | 277 | # Business Intelligence projects 278 | *.rdl.data 279 | *.bim.layout 280 | *.bim_*.settings 281 | *.rptproj.rsuser 282 | *- [Bb]ackup.rdl 283 | *- [Bb]ackup ([0-9]).rdl 284 | *- [Bb]ackup ([0-9][0-9]).rdl 285 | 286 | # Microsoft Fakes 287 | FakesAssemblies/ 288 | 289 | # GhostDoc plugin setting file 290 | *.GhostDoc.xml 291 | 292 | # Node.js Tools for Visual Studio 293 | .ntvs_analysis.dat 294 | node_modules/ 295 | 296 | # Visual Studio 6 build log 297 | *.plg 298 | 299 | # Visual Studio 6 workspace options file 300 | *.opt 301 | 302 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 303 | *.vbw 304 | 305 | # Visual Studio LightSwitch build output 306 | **/*.HTMLClient/GeneratedArtifacts 307 | **/*.DesktopClient/GeneratedArtifacts 308 | **/*.DesktopClient/ModelManifest.xml 309 | **/*.Server/GeneratedArtifacts 310 | **/*.Server/ModelManifest.xml 311 | _Pvt_Extensions 312 | 313 | # Paket dependency manager 314 | .paket/paket.exe 315 | paket-files/ 316 | 317 | # FAKE - F# Make 318 | .fake/ 319 | 320 | # CodeRush personal settings 321 | .cr/personal 322 | 323 | # Python Tools for Visual Studio (PTVS) 324 | __pycache__/ 325 | *.pyc 326 | 327 | # Cake - Uncomment if you are using it 328 | # tools/** 329 | # !tools/packages.config 330 | 331 | # Tabs Studio 332 | *.tss 333 | 334 | # Telerik's JustMock configuration file 335 | *.jmconfig 336 | 337 | # BizTalk build output 338 | *.btp.cs 339 | *.btm.cs 340 | *.odx.cs 341 | *.xsd.cs 342 | 343 | # OpenCover UI analysis results 344 | OpenCover/ 345 | 346 | # Azure Stream Analytics local run output 347 | ASALocalRun/ 348 | 349 | # MSBuild Binary and Structured Log 350 | *.binlog 351 | 352 | # NVidia Nsight GPU debugger configuration file 353 | *.nvuser 354 | 355 | # MFractors (Xamarin productivity tool) working folder 356 | .mfractor/ 357 | 358 | # Local History for Visual Studio 359 | .localhistory/ 360 | 361 | # BeatPulse healthcheck temp database 362 | healthchecksdb 363 | 364 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 365 | MigrationBackup/ 366 | 367 | # Ionide (cross platform F# VS Code tools) working folder 368 | .ionide/ 369 | -------------------------------------------------------------------------------- /mariadb.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************/ 2 | /* mariadb.h */ 3 | /*************************************************************************/ 4 | /* This file is part of: */ 5 | /* GODOT ENGINE */ 6 | /* https://godotengine.org */ 7 | /*************************************************************************/ 8 | /* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ 9 | /* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ 10 | /* */ 11 | /* Permission is hereby granted, free of charge, to any person obtaining */ 12 | /* a copy of this software and associated documentation files (the */ 13 | /* "Software"), to deal in the Software without restriction, including */ 14 | /* without limitation the rights to use, copy, modify, merge, publish, */ 15 | /* distribute, sublicense, and/or sell copies of the Software, and to */ 16 | /* permit persons to whom the Software is furnished to do so, subject to */ 17 | /* the following conditions: */ 18 | /* */ 19 | /* The above copyright notice and this permission notice shall be */ 20 | /* included in all copies or substantial portions of the Software. */ 21 | /* */ 22 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 23 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 24 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ 25 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 26 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 27 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 28 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 29 | /*************************************************************************/ 30 | 31 | //TODO(sigrudds1) Add sha256 Authentication for MySQL alternative authentication 32 | //TODO(sigrudds1) Add cashing_sha2_password for MySQL alternative authentication 33 | //TODO(sigrudds1) Use virtuallock(windows) or mlock(linux) to prevent memory dump of username and password 34 | //TODO(sigrudds1) ASYNC callbacks using the username, signals maybe. 35 | 36 | #ifndef MARIADB_H 37 | #define MARIADB_H 38 | 39 | #define DEBUG_OUTPUT 40 | 41 | #include 42 | #include 43 | #include 44 | // #include "core/os/thread.h" 45 | // #include "core/os/mutex.h" 46 | #include "core/object/ref_counted.h" 47 | #include "core/string/ustring.h" 48 | #include "core/templates/vector.h" 49 | #include "core/variant/variant.h" 50 | 51 | 52 | constexpr uint8_t kCharacterCollationId = 33; //utf8_general_ci 53 | constexpr char *kCharacterCollationName = (char *)"utf8_general_ci"; 54 | 55 | class MariaDB : public RefCounted { 56 | GDCLASS(MariaDB, RefCounted); 57 | 58 | public: 59 | enum AuthType { 60 | AUTH_TYPE_ED25519, 61 | AUTH_TYPE_MYSQL_NATIVE, 62 | AUTH_TYPE_LAST, 63 | }; 64 | 65 | enum IpType { 66 | IP_TYPE_IPV4 = IP::TYPE_IPV4, 67 | IP_TYPE_IPV6 = IP::TYPE_IPV6, 68 | IP_TYPE_ANY = IP::TYPE_ANY, 69 | }; 70 | 71 | enum ErrorCodes { 72 | OK = 0, 73 | ERR_NO_RESPONSE, 74 | ERR_NOT_CONNECTED, 75 | ERR_PACKET_LENGTH_MISMATCH, 76 | ERR_PACKET_SEQUENCE_ERROR, 77 | ERR_SERVER_PROTOCOL_INCOMPATIBLE, 78 | ERR_CLIENT_PROTOCOL_INCOMPATIBLE, 79 | ERR_AUTH_PLUGIN_NOT_SET, 80 | ERR_AUTH_PLUGIN_INCOMPATIBLE, 81 | ERR_AUTH_FAILED, 82 | ERR_USERNAME_EMPTY, 83 | ERR_PASSWORD_EMPTY, 84 | ERR_DB_EMPTY 85 | }; 86 | 87 | private: 88 | //https://mariadb.com/kb/en/connection/#capabilities 89 | enum class Capabilities : uint64_t { 90 | LONG_PASSWORD = (1UL << 0), //MySQL 91 | CLIENT_MYSQL = (1UL << 0), //MariaDB - lets server know this is a mysql client 92 | FOUND_ROWS = (1UL << 1), 93 | LONG_FLAG = (1UL << 2), //Not listed in MariaDB 94 | CONNECT_WITH_DB = (1UL << 3), 95 | NO_SCHEMA = (1UL << 4), //Not listed in MariaDB 96 | NO_DB_TABLE_COLUMN = (1UL << 4), //Alternate name, Not listed in MariaDB 97 | COMPRESS = (1UL << 5), 98 | ODBC = (1UL << 6), //Not listed in MariaDB 99 | LOCAL_FILES = (1UL << 7), 100 | IGNORE_SPACE = (1UL << 8), 101 | CLIENT_PROTOCOL_41 = (1UL << 9), 102 | CLIENT_INTERACTIVE = (1UL << 10), 103 | SSL = (1UL << 11), 104 | IGNORE_SIGPIPE = (1UL << 12), //MySQL 105 | TRANSACTIONS_MARIA = (1UL << 12), //MariaDB 106 | TRANSACTIONS_MYSQL = (1UL << 13), //MySQL 107 | SECURE_CONNECTION = (1UL << 13), //MariaDB 108 | RESERVED = (1UL << 14), //Not listed in MariaDB 109 | RESERVED2 = (1UL << 15), //Not in Maria Docs but needed 110 | MULTI_STATEMENTS = (1UL << 16), 111 | MULTI_RESULTS = (1UL << 17), 112 | PS_MULTI_RESULTS = (1UL << 18), 113 | PLUGIN_AUTH = (1UL << 19), 114 | CLIENT_SEND_CONNECT_ATTRS = (1UL << 20), 115 | PLUGIN_AUTH_LENENC_CLIENT_DATA = (1UL << 21), //TODO Add compatibility 116 | CAN_HANDLE_EXPIRED_PASSWORDS = (1UL << 22), //Not listed in MariaDB 117 | SESSION_TRACK = (1UL << 23), 118 | CLIENT_DEPRECATE_EOF = (1UL << 24), 119 | OPTIONAL_RESULTSET_METADATA = (1UL << 25), 120 | CLIENT_ZSTD_COMPRESSION_ALGORITHM = (1UL << 26), 121 | CLIENT_QUERY_ATTRIBUTES = (1UL << 27), //Not listed in MariaDB 122 | //NOT_USED = (1UL << 28), 123 | CLIENT_CAPABILITY_EXTENSION = (1UL << 29), //MariaDB reserved for future use. 124 | SSL_VERIFY_SERVER_CERT = (1UL << 30), //Not listed in MariaDB 125 | REMEMBER_OPTIONS = (1UL << 31), //Not listed in MariaDB 126 | MARIADB_CLIENT_PROGRESS = (1UL << 32), 127 | MARIADB_CLIENT_COM_MULTI = (1UL << 33), 128 | MARIADB_CLIENT_STMT_BULK_OPERATIONS = (1UL << 34), 129 | MARIADB_CLIENT_EXTENDED_TYPE_INFO = (1UL << 35), 130 | MARIADB_CLIENT_CACHE_METADATA = (1UL << 36) 131 | }; 132 | 133 | struct ColumnData { 134 | String name; 135 | uint16_t char_set; 136 | uint8_t field_type; 137 | }; 138 | 139 | const Vector kAuthTypeNames = { "client_ed25519", "mysql_native_password" }; 140 | bool _dbl_to_string = false; 141 | IpType _ip_type = IpType::IP_TYPE_ANY; 142 | AuthType _client_auth_type = AUTH_TYPE_ED25519; 143 | bool _is_pre_hashed = true; 144 | bool _authenticated = false; 145 | uint64_t _client_capabilities = 0; 146 | //uint32_t _client_extended_capabilities = 0; 147 | uint64_t _server_capabilities = 0; 148 | //uint32_t _server_extended_capabilities = 0; 149 | 150 | Vector _username; 151 | Vector _password_hashed; 152 | Vector _dbname; 153 | 154 | // Ref tcp_connection; 155 | 156 | StreamPeerTCP _stream; 157 | IPAddress _ip; 158 | int _port = 0; 159 | 160 | // bool _running = true; 161 | // bool _tcp_polling = false; 162 | // Mutex _tcp_mutex; 163 | // Thread _tcp_thread; 164 | // Vector _tcp_thread_data; 165 | 166 | String _protocol_ver; 167 | String _server_ver_str; 168 | uint8_t _srvr_major_ver = 0; 169 | uint8_t _srvr_minor_ver = 0; 170 | String _last_query; 171 | Vector _last_query_converted; 172 | Vector _last_transmitted; 173 | Vector _last_response; 174 | 175 | 176 | /** 177 | * \brief Adds the packet size and sequence number to the beginning of the packet, 178 | * it must be used once just before sending stream to server. 179 | * \param stream std::vector the stream to be modified. 180 | * \param sequance int 181 | */ 182 | void m_add_packet_header(Vector &p_pkt, uint8_t p_pkt_seq); 183 | 184 | // void m_append_thread_data(PackedByteArray &p_data, const uint64_t p_timeout = 1000); 185 | 186 | uint32_t m_chk_rcv_bfr(Vector &bfr, int &bfr_size, const size_t cur_pos, const size_t need); 187 | 188 | Error m_client_protocol_v41(const AuthType p_srvr_auth_type, const Vector p_srvr_salt); 189 | Error m_connect(); 190 | static void m_tcp_thread_func(void *instance); 191 | 192 | String m_find_vbytes_str_at(Vector p_buf, size_t &p_start_pos); 193 | String m_find_vbytes_str(Vector p_buf); 194 | 195 | PackedByteArray m_get_pkt_bytes(const Vector &src_buf, size_t &start_pos, const size_t byte_cnt); 196 | size_t m_get_pkt_len_at(const Vector p_src_buf, size_t &p_start_pos); 197 | AuthType m_get_server_auth_type(String p_srvr_auth_name); 198 | Variant m_get_type_data(const int p_db_field_type, const PackedByteArray p_data); 199 | 200 | Vector m_recv_data(); 201 | Vector m_recv_data(uint32_t p_timeout); 202 | //TODO(sigrudds1) Add error log file using the username in the filename 203 | void m_handle_server_error(const Vector p_src_buffer, size_t &p_last_pos); 204 | Error m_server_init_handshake_v10(const Vector &p_src_buffer); 205 | void m_update_password(String p_password); 206 | void m_update_username(String P_username); 207 | 208 | protected: 209 | static void _bind_methods(); 210 | 211 | public: 212 | /** 213 | * \brief This method sets the authentication type used. 214 | * 215 | * \param host 216 | * \param port 217 | * \param dbname 218 | * \param username 219 | * \param password 220 | * \param auth_type enum AuthType determines what authoriztion type will be statically used. 221 | * \param is_pre_hash bool if set the password used will be hashed by the required type before used. 222 | * \return uint32_t 0 = no error, see error enum class ErrorCode 223 | */ 224 | Error connect_db(String host, int port, String dbname, String username, String password, 225 | AuthType auth_type = AuthType::AUTH_TYPE_ED25519, bool is_prehashed = true); 226 | void disconnect_db(); 227 | 228 | String get_last_query(); 229 | PackedByteArray get_last_query_converted(); 230 | PackedByteArray get_last_response(); 231 | PackedByteArray get_last_transmitted(); 232 | 233 | bool is_connected_db(); 234 | 235 | Variant query(String sql_stmt); 236 | 237 | 238 | //TODO(sigrudds1) Implement SSL/TLS 239 | //void tls_enable(bool enable); 240 | 241 | void set_dbl_to_string(bool is_to_str); 242 | void set_db_name(String p_db_name); 243 | void set_ip_type(IpType p_type); 244 | //TODO(sigrudds1) Async Callbacks 245 | 246 | MariaDB(); 247 | ~MariaDB(); 248 | }; 249 | 250 | VARIANT_ENUM_CAST(MariaDB::AuthType); 251 | VARIANT_ENUM_CAST(MariaDB::IpType); 252 | 253 | #endif 254 | -------------------------------------------------------------------------------- /examples/G4_MariaDB_test/create_db.sql.txt: -------------------------------------------------------------------------------- 1 | INSTALL PLUGIN IF NOT EXISTS ed25519 SONAME 'auth_ed25519'; 2 | 3 | CREATE DATABASE IF NOT EXISTS `Godot_Test` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci */; 4 | 5 | CREATE TABLE IF NOT EXISTS Godot_Test.`many_columns` ( 6 | `Column1` int(11) DEFAULT NULL, 7 | `Column2` int(11) DEFAULT NULL, 8 | `Column3` int(11) DEFAULT NULL, 9 | `Column4` int(11) DEFAULT NULL, 10 | `Column5` int(11) DEFAULT NULL, 11 | `Column6` int(11) DEFAULT NULL, 12 | `Column7` int(11) DEFAULT NULL, 13 | `Column8` int(11) DEFAULT NULL, 14 | `Column9` int(11) DEFAULT NULL, 15 | `Column10` int(11) DEFAULT NULL, 16 | `Column11` int(11) DEFAULT NULL, 17 | `Column12` int(11) DEFAULT NULL, 18 | `Column13` int(11) DEFAULT NULL, 19 | `Column14` int(11) DEFAULT NULL, 20 | `Column15` int(11) DEFAULT NULL, 21 | `Column16` int(11) DEFAULT NULL, 22 | `Column17` int(11) DEFAULT NULL, 23 | `Column18` int(11) DEFAULT NULL, 24 | `Column19` int(11) DEFAULT NULL, 25 | `Column20` int(11) DEFAULT NULL, 26 | `Column21` int(11) DEFAULT NULL, 27 | `Column22` int(11) DEFAULT NULL, 28 | `Column23` int(11) DEFAULT NULL, 29 | `Column24` int(11) DEFAULT NULL, 30 | `Column25` int(11) DEFAULT NULL, 31 | `Column26` int(11) DEFAULT NULL, 32 | `Column27` int(11) DEFAULT NULL, 33 | `Column28` int(11) DEFAULT NULL, 34 | `Column29` int(11) DEFAULT NULL, 35 | `Column30` int(11) DEFAULT NULL, 36 | `Column31` int(11) DEFAULT NULL, 37 | `Column32` int(11) DEFAULT NULL, 38 | `Column33` int(11) DEFAULT NULL, 39 | `Column34` int(11) DEFAULT NULL, 40 | `Column35` int(11) DEFAULT NULL, 41 | `Column36` int(11) DEFAULT NULL, 42 | `Column37` int(11) DEFAULT NULL, 43 | `Column38` int(11) DEFAULT NULL, 44 | `Column39` int(11) DEFAULT NULL, 45 | `Column40` int(11) DEFAULT NULL, 46 | `Column41` int(11) DEFAULT NULL, 47 | `Column42` int(11) DEFAULT NULL, 48 | `Column43` int(11) DEFAULT NULL, 49 | `Column44` int(11) DEFAULT NULL, 50 | `Column45` int(11) DEFAULT NULL, 51 | `Column46` int(11) DEFAULT NULL, 52 | `Column47` int(11) DEFAULT NULL, 53 | `Column48` int(11) DEFAULT NULL, 54 | `Column49` int(11) DEFAULT NULL, 55 | `Column50` int(11) DEFAULT NULL, 56 | `Column51` int(11) DEFAULT NULL, 57 | `Column52` int(11) DEFAULT NULL, 58 | `Column53` int(11) DEFAULT NULL, 59 | `Column54` int(11) DEFAULT NULL, 60 | `Column55` int(11) DEFAULT NULL, 61 | `Column56` int(11) DEFAULT NULL, 62 | `Column57` int(11) DEFAULT NULL, 63 | `Column58` int(11) DEFAULT NULL, 64 | `Column59` int(11) DEFAULT NULL, 65 | `Column60` int(11) DEFAULT NULL, 66 | `Column61` int(11) DEFAULT NULL, 67 | `Column62` int(11) DEFAULT NULL, 68 | `Column63` int(11) DEFAULT NULL, 69 | `Column64` int(11) DEFAULT NULL, 70 | `Column65` int(11) DEFAULT NULL, 71 | `Column66` int(11) DEFAULT NULL, 72 | `Column67` int(11) DEFAULT NULL, 73 | `Column68` int(11) DEFAULT NULL, 74 | `Column69` int(11) DEFAULT NULL, 75 | `Column70` int(11) DEFAULT NULL, 76 | `Column71` int(11) DEFAULT NULL, 77 | `Column72` int(11) DEFAULT NULL, 78 | `Column73` int(11) DEFAULT NULL, 79 | `Column74` int(11) DEFAULT NULL, 80 | `Column75` int(11) DEFAULT NULL, 81 | `Column76` int(11) DEFAULT NULL, 82 | `Column77` int(11) DEFAULT NULL, 83 | `Column78` int(11) DEFAULT NULL, 84 | `Column79` int(11) DEFAULT NULL, 85 | `Column80` int(11) DEFAULT NULL, 86 | `Column81` int(11) DEFAULT NULL, 87 | `Column82` int(11) DEFAULT NULL, 88 | `Column83` int(11) DEFAULT NULL, 89 | `Column84` int(11) DEFAULT NULL, 90 | `Column85` int(11) DEFAULT NULL, 91 | `Column86` int(11) DEFAULT NULL, 92 | `Column87` int(11) DEFAULT NULL, 93 | `Column88` int(11) DEFAULT NULL, 94 | `Column89` int(11) DEFAULT NULL, 95 | `Column90` int(11) DEFAULT NULL, 96 | `Column91` int(11) DEFAULT NULL, 97 | `Column92` int(11) DEFAULT NULL, 98 | `Column93` int(11) DEFAULT NULL, 99 | `Column94` int(11) DEFAULT NULL, 100 | `Column95` int(11) DEFAULT NULL, 101 | `Column96` int(11) DEFAULT NULL, 102 | `Column97` int(11) DEFAULT NULL, 103 | `Column98` int(11) DEFAULT NULL, 104 | `Column99` int(11) DEFAULT NULL, 105 | `Column100` int(11) DEFAULT NULL, 106 | `Column101` int(11) DEFAULT NULL, 107 | `Column102` int(11) DEFAULT NULL, 108 | `Column103` int(11) DEFAULT NULL, 109 | `Column104` int(11) DEFAULT NULL, 110 | `Column105` int(11) DEFAULT NULL, 111 | `Column106` int(11) DEFAULT NULL, 112 | `Column107` int(11) DEFAULT NULL, 113 | `Column108` int(11) DEFAULT NULL, 114 | `Column109` int(11) DEFAULT NULL, 115 | `Column110` int(11) DEFAULT NULL, 116 | `Column111` int(11) DEFAULT NULL, 117 | `Column112` int(11) DEFAULT NULL, 118 | `Column113` int(11) DEFAULT NULL, 119 | `Column114` int(11) DEFAULT NULL, 120 | `Column115` int(11) DEFAULT NULL, 121 | `Column116` int(11) DEFAULT NULL, 122 | `Column117` int(11) DEFAULT NULL, 123 | `Column118` int(11) DEFAULT NULL, 124 | `Column119` int(11) DEFAULT NULL, 125 | `Column120` int(11) DEFAULT NULL, 126 | `Column121` int(11) DEFAULT NULL, 127 | `Column122` int(11) DEFAULT NULL, 128 | `Column123` int(11) DEFAULT NULL, 129 | `Column124` int(11) DEFAULT NULL, 130 | `Column125` int(11) DEFAULT NULL, 131 | `Column126` int(11) DEFAULT NULL, 132 | `Column127` int(11) DEFAULT NULL, 133 | `Column128` int(11) DEFAULT NULL, 134 | `Column129` int(11) DEFAULT NULL, 135 | `Column130` int(11) DEFAULT NULL, 136 | `Column131` int(11) DEFAULT NULL, 137 | `Column132` int(11) DEFAULT NULL, 138 | `Column133` int(11) DEFAULT NULL, 139 | `Column134` int(11) DEFAULT NULL, 140 | `Column135` int(11) DEFAULT NULL, 141 | `Column136` int(11) DEFAULT NULL, 142 | `Column137` int(11) DEFAULT NULL, 143 | `Column138` int(11) DEFAULT NULL, 144 | `Column139` int(11) DEFAULT NULL, 145 | `Column140` int(11) DEFAULT NULL, 146 | `Column141` int(11) DEFAULT NULL, 147 | `Column142` int(11) DEFAULT NULL, 148 | `Column143` int(11) DEFAULT NULL, 149 | `Column144` int(11) DEFAULT NULL, 150 | `Column145` int(11) DEFAULT NULL, 151 | `Column146` int(11) DEFAULT NULL, 152 | `Column147` int(11) DEFAULT NULL, 153 | `Column148` int(11) DEFAULT NULL, 154 | `Column149` int(11) DEFAULT NULL, 155 | `Column150` int(11) DEFAULT NULL, 156 | `Column151` int(11) DEFAULT NULL, 157 | `Column152` int(11) DEFAULT NULL, 158 | `Column153` int(11) DEFAULT NULL, 159 | `Column154` int(11) DEFAULT NULL, 160 | `Column155` int(11) DEFAULT NULL, 161 | `Column156` int(11) DEFAULT NULL, 162 | `Column157` int(11) DEFAULT NULL, 163 | `Column158` int(11) DEFAULT NULL, 164 | `Column159` int(11) DEFAULT NULL, 165 | `Column160` int(11) DEFAULT NULL, 166 | `Column161` int(11) DEFAULT NULL, 167 | `Column162` int(11) DEFAULT NULL, 168 | `Column163` int(11) DEFAULT NULL, 169 | `Column164` int(11) DEFAULT NULL, 170 | `Column165` int(11) DEFAULT NULL, 171 | `Column166` int(11) DEFAULT NULL, 172 | `Column167` int(11) DEFAULT NULL, 173 | `Column168` int(11) DEFAULT NULL, 174 | `Column169` int(11) DEFAULT NULL, 175 | `Column170` int(11) DEFAULT NULL, 176 | `Column171` int(11) DEFAULT NULL, 177 | `Column172` int(11) DEFAULT NULL, 178 | `Column173` int(11) DEFAULT NULL, 179 | `Column174` int(11) DEFAULT NULL, 180 | `Column175` int(11) DEFAULT NULL, 181 | `Column176` int(11) DEFAULT NULL, 182 | `Column177` int(11) DEFAULT NULL, 183 | `Column178` int(11) DEFAULT NULL, 184 | `Column179` int(11) DEFAULT NULL, 185 | `Column180` int(11) DEFAULT NULL, 186 | `Column181` int(11) DEFAULT NULL, 187 | `Column182` int(11) DEFAULT NULL, 188 | `Column183` int(11) DEFAULT NULL, 189 | `Column184` int(11) DEFAULT NULL, 190 | `Column185` int(11) DEFAULT NULL, 191 | `Column186` int(11) DEFAULT NULL, 192 | `Column187` int(11) DEFAULT NULL, 193 | `Column188` int(11) DEFAULT NULL, 194 | `Column189` int(11) DEFAULT NULL, 195 | `Column190` int(11) DEFAULT NULL, 196 | `Column191` int(11) DEFAULT NULL, 197 | `Column192` int(11) DEFAULT NULL, 198 | `Column193` int(11) DEFAULT NULL, 199 | `Column194` int(11) DEFAULT NULL, 200 | `Column195` int(11) DEFAULT NULL, 201 | `Column196` int(11) DEFAULT NULL, 202 | `Column197` int(11) DEFAULT NULL, 203 | `Column198` int(11) DEFAULT NULL, 204 | `Column199` int(11) DEFAULT NULL, 205 | `Column200` int(11) DEFAULT NULL, 206 | `Column201` int(11) DEFAULT NULL, 207 | `Column202` int(11) DEFAULT NULL, 208 | `Column203` int(11) DEFAULT NULL, 209 | `Column204` int(11) DEFAULT NULL, 210 | `Column205` int(11) DEFAULT NULL, 211 | `Column206` int(11) DEFAULT NULL, 212 | `Column207` int(11) DEFAULT NULL, 213 | `Column208` int(11) DEFAULT NULL, 214 | `Column209` int(11) DEFAULT NULL, 215 | `Column210` int(11) DEFAULT NULL, 216 | `Column211` int(11) DEFAULT NULL, 217 | `Column212` int(11) DEFAULT NULL, 218 | `Column213` int(11) DEFAULT NULL, 219 | `Column214` int(11) DEFAULT NULL, 220 | `Column215` int(11) DEFAULT NULL, 221 | `Column216` int(11) DEFAULT NULL, 222 | `Column217` int(11) DEFAULT NULL, 223 | `Column218` int(11) DEFAULT NULL, 224 | `Column219` int(11) DEFAULT NULL, 225 | `Column220` int(11) DEFAULT NULL, 226 | `Column221` int(11) DEFAULT NULL, 227 | `Column222` int(11) DEFAULT NULL, 228 | `Column223` int(11) DEFAULT NULL, 229 | `Column224` int(11) DEFAULT NULL, 230 | `Column225` int(11) DEFAULT NULL, 231 | `Column226` int(11) DEFAULT NULL, 232 | `Column227` int(11) DEFAULT NULL, 233 | `Column228` int(11) DEFAULT NULL, 234 | `Column229` int(11) DEFAULT NULL, 235 | `Column230` int(11) DEFAULT NULL, 236 | `Column231` int(11) DEFAULT NULL, 237 | `Column232` int(11) DEFAULT NULL, 238 | `Column233` int(11) DEFAULT NULL, 239 | `Column234` int(11) DEFAULT NULL, 240 | `Column235` int(11) DEFAULT NULL, 241 | `Column236` int(11) DEFAULT NULL, 242 | `Column237` int(11) DEFAULT NULL, 243 | `Column238` int(11) DEFAULT NULL, 244 | `Column239` int(11) DEFAULT NULL, 245 | `Column240` int(11) DEFAULT NULL, 246 | `Column241` int(11) DEFAULT NULL, 247 | `Column242` int(11) DEFAULT NULL, 248 | `Column243` int(11) DEFAULT NULL, 249 | `Column244` int(11) DEFAULT NULL, 250 | `Column245` int(11) DEFAULT NULL, 251 | `Column246` int(11) DEFAULT NULL, 252 | `Column247` int(11) DEFAULT NULL, 253 | `Column248` int(11) DEFAULT NULL, 254 | `Column249` int(11) DEFAULT NULL, 255 | `Column250` int(11) DEFAULT NULL, 256 | `Column251` int(11) DEFAULT NULL, 257 | `Column252` int(11) DEFAULT NULL 258 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; 259 | 260 | CREATE TABLE IF NOT EXISTS Godot_Test.`many_records` ( 261 | `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 262 | `type` smallint(5) unsigned NOT NULL, 263 | `zone_id` int(10) unsigned NOT NULL, 264 | `player_id` smallint(5) unsigned DEFAULT NULL, 265 | `map_id` tinyint(3) unsigned NOT NULL, 266 | `text_field` text DEFAULT NULL, 267 | PRIMARY KEY (`id`) 268 | ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; 269 | 270 | CREATE USER IF NOT EXISTS `godot_user`@'localhost' IDENTIFIED VIA ed25519 USING PASSWORD('secret'); 271 | CREATE USER IF NOT EXISTS `godot_user`@'::1' IDENTIFIED VIA ed25519 USING PASSWORD('secret'); 272 | GRANT ALL PRIVILEGES ON `Godot_Test`.* TO 'godot_user'@'localhost'; 273 | GRANT ALL PRIVILEGES ON `Godot_Test`.* TO 'godot_user'@'::1'; 274 | -------------------------------------------------------------------------------- /ed25519_ref10/ed25519_ge.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************/ 2 | /* ed25519_ge.cpp */ 3 | /*************************************************************************/ 4 | /* This file is part of: */ 5 | /* GODOT ENGINE */ 6 | /* https://godotengine.org */ 7 | /*************************************************************************/ 8 | /* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ 9 | /* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ 10 | /* */ 11 | /* Permission is hereby granted, free of charge, to any person obtaining */ 12 | /* a copy of this software and associated documentation files (the */ 13 | /* "Software"), to deal in the Software without restriction, including */ 14 | /* without limitation the rights to use, copy, modify, merge, publish, */ 15 | /* distribute, sublicense, and/or sell copies of the Software, and to */ 16 | /* permit persons to whom the Software is furnished to do so, subject to */ 17 | /* the following conditions: */ 18 | /* */ 19 | /* The above copyright notice and this permission notice shall be */ 20 | /* included in all copies or substantial portions of the Software. */ 21 | /* */ 22 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 23 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 24 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ 25 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 26 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 27 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 28 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 29 | /*************************************************************************/ 30 | 31 | /* This file was derived from information found at */ 32 | /* https://tools.ietf.org/html/rfc8032 */ 33 | 34 | #include 35 | 36 | #include "ed25519_ge.h" 37 | #include "ed25519_precomputed.h" 38 | 39 | /* 40 | r = p + q 41 | */ 42 | 43 | void ge_add(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) { 44 | fe t0; 45 | fe_add(r->X, p->Y, p->X); 46 | fe_sub(r->Y, p->Y, p->X); 47 | fe_mul(r->Z, r->X, q->YplusX); 48 | fe_mul(r->Y, r->Y, q->YminusX); 49 | fe_mul(r->T, q->T2d, p->T); 50 | fe_mul(r->X, p->Z, q->Z); 51 | fe_add(t0, r->X, r->X); 52 | fe_sub(r->X, r->Z, r->Y); 53 | fe_add(r->Y, r->Z, r->Y); 54 | fe_add(r->Z, t0, r->T); 55 | fe_sub(r->T, t0, r->T); 56 | } 57 | 58 | static void slide(int8_t *r, const uint8_t *a) { 59 | int i; 60 | int b; 61 | int k; 62 | 63 | for (i = 0; i < 256; ++i) { 64 | r[i] = 1 & (a[i >> 3] >> (i & 7)); 65 | } 66 | 67 | for (i = 0; i < 256; ++i) 68 | if (r[i]) { 69 | for (b = 1; b <= 6 && i + b < 256; ++b) { 70 | if (r[i + b]) { 71 | if (r[i] + (r[i + b] << b) <= 15) { 72 | r[i] += r[i + b] << b; 73 | r[i + b] = 0; 74 | } else if (r[i] - (r[i + b] << b) >= -15) { 75 | r[i] -= r[i + b] << b; 76 | 77 | for (k = i + b; k < 256; ++k) { 78 | if (!r[k]) { 79 | r[k] = 1; 80 | break; 81 | } 82 | 83 | r[k] = 0; 84 | } 85 | } else { 86 | break; 87 | } 88 | } 89 | } 90 | } 91 | } 92 | 93 | /* 94 | r = a * A + b * B 95 | where a = a[0]+256*a[1]+...+256^31 a[31]. 96 | and b = b[0]+256*b[1]+...+256^31 b[31]. 97 | B is the Ed25519 base point (x,4/5) with x positive. 98 | */ 99 | 100 | void ge_double_scalarmult_vartime(ge_p2 *r, const uint8_t *a, const ge_p3 *A, const uint8_t *b) { 101 | int8_t aslide[256]; 102 | int8_t bslide[256]; 103 | ge_cached Ai[8]; /* A,3A,5A,7A,9A,11A,13A,15A */ 104 | ge_p1p1 t; 105 | ge_p3 u; 106 | ge_p3 A2; 107 | int i; 108 | slide(aslide, a); 109 | slide(bslide, b); 110 | ge_p3_to_cached(&Ai[0], A); 111 | ge_p3_dbl(&t, A); 112 | ge_p1p1_to_p3(&A2, &t); 113 | ge_add(&t, &A2, &Ai[0]); 114 | ge_p1p1_to_p3(&u, &t); 115 | ge_p3_to_cached(&Ai[1], &u); 116 | ge_add(&t, &A2, &Ai[1]); 117 | ge_p1p1_to_p3(&u, &t); 118 | ge_p3_to_cached(&Ai[2], &u); 119 | ge_add(&t, &A2, &Ai[2]); 120 | ge_p1p1_to_p3(&u, &t); 121 | ge_p3_to_cached(&Ai[3], &u); 122 | ge_add(&t, &A2, &Ai[3]); 123 | ge_p1p1_to_p3(&u, &t); 124 | ge_p3_to_cached(&Ai[4], &u); 125 | ge_add(&t, &A2, &Ai[4]); 126 | ge_p1p1_to_p3(&u, &t); 127 | ge_p3_to_cached(&Ai[5], &u); 128 | ge_add(&t, &A2, &Ai[5]); 129 | ge_p1p1_to_p3(&u, &t); 130 | ge_p3_to_cached(&Ai[6], &u); 131 | ge_add(&t, &A2, &Ai[6]); 132 | ge_p1p1_to_p3(&u, &t); 133 | ge_p3_to_cached(&Ai[7], &u); 134 | ge_p2_0(r); 135 | 136 | for (i = 255; i >= 0; --i) { 137 | if (aslide[i] || bslide[i]) { 138 | break; 139 | } 140 | } 141 | 142 | for (; i >= 0; --i) { 143 | ge_p2_dbl(&t, r); 144 | 145 | if (aslide[i] > 0) { 146 | ge_p1p1_to_p3(&u, &t); 147 | ge_add(&t, &u, &Ai[aslide[i] / 2]); 148 | } else if (aslide[i] < 0) { 149 | ge_p1p1_to_p3(&u, &t); 150 | ge_sub(&t, &u, &Ai[(-aslide[i]) / 2]); 151 | } 152 | 153 | if (bslide[i] > 0) { 154 | ge_p1p1_to_p3(&u, &t); 155 | ge_madd(&t, &u, &Bi[bslide[i] / 2]); 156 | } else if (bslide[i] < 0) { 157 | ge_p1p1_to_p3(&u, &t); 158 | ge_msub(&t, &u, &Bi[(-bslide[i]) / 2]); 159 | } 160 | 161 | ge_p1p1_to_p2(r, &t); 162 | } 163 | } 164 | 165 | static const fe d = { 166 | -10913610, 13857413, -15372611, 6949391, 114729, -8787816, -6275908, -3247719, -18696448, -12055116 167 | }; 168 | 169 | static const fe sqrtm1 = { 170 | -32595792, -7943725, 9377950, 3500415, 12389472, -272473, -25146209, -2005654, 326686, 11406482 171 | }; 172 | 173 | int ge_frombytes_negate_vartime(ge_p3 *h, const uint8_t *s) { 174 | fe u; 175 | fe v; 176 | fe v3; 177 | fe vxx; 178 | fe check; 179 | fe_frombytes(h->Y, s); 180 | fe_1(h->Z); 181 | fe_sq(u, h->Y); 182 | fe_mul(v, u, d); 183 | fe_sub(u, u, h->Z); /* u = y^2-1 */ 184 | fe_add(v, v, h->Z); /* v = dy^2+1 */ 185 | fe_sq(v3, v); 186 | fe_mul(v3, v3, v); /* v3 = v^3 */ 187 | fe_sq(h->X, v3); 188 | fe_mul(h->X, h->X, v); 189 | fe_mul(h->X, h->X, u); /* x = uv^7 */ 190 | fe_pow22523(h->X, h->X); /* x = (uv^7)^((q-5)/8) */ 191 | fe_mul(h->X, h->X, v3); 192 | fe_mul(h->X, h->X, u); /* x = uv^3(uv^7)^((q-5)/8) */ 193 | fe_sq(vxx, h->X); 194 | fe_mul(vxx, vxx, v); 195 | fe_sub(check, vxx, u); /* vx^2-u */ 196 | 197 | if (fe_isnonzero(check)) { 198 | fe_add(check, vxx, u); /* vx^2+u */ 199 | 200 | if (fe_isnonzero(check)) { 201 | return -1; 202 | } 203 | 204 | fe_mul(h->X, h->X, sqrtm1); 205 | } 206 | 207 | if (fe_isnegative(h->X) == (s[31] >> 7)) { 208 | fe_neg(h->X, h->X); 209 | } 210 | 211 | fe_mul(h->T, h->X, h->Y); 212 | return 0; 213 | } 214 | 215 | /* 216 | r = p + q 217 | */ 218 | 219 | void ge_madd(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q) { 220 | fe t0; 221 | fe_add(r->X, p->Y, p->X); 222 | fe_sub(r->Y, p->Y, p->X); 223 | fe_mul(r->Z, r->X, q->yplusx); 224 | fe_mul(r->Y, r->Y, q->yminusx); 225 | fe_mul(r->T, q->xy2d, p->T); 226 | fe_add(t0, p->Z, p->Z); 227 | fe_sub(r->X, r->Z, r->Y); 228 | fe_add(r->Y, r->Z, r->Y); 229 | fe_add(r->Z, t0, r->T); 230 | fe_sub(r->T, t0, r->T); 231 | } 232 | 233 | /* 234 | r = p - q 235 | */ 236 | 237 | void ge_msub(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q) { 238 | fe t0; 239 | 240 | fe_add(r->X, p->Y, p->X); 241 | fe_sub(r->Y, p->Y, p->X); 242 | fe_mul(r->Z, r->X, q->yminusx); 243 | fe_mul(r->Y, r->Y, q->yplusx); 244 | fe_mul(r->T, q->xy2d, p->T); 245 | fe_add(t0, p->Z, p->Z); 246 | fe_sub(r->X, r->Z, r->Y); 247 | fe_add(r->Y, r->Z, r->Y); 248 | fe_sub(r->Z, t0, r->T); 249 | fe_add(r->T, t0, r->T); 250 | } 251 | 252 | /* 253 | r = p 254 | */ 255 | 256 | void ge_p1p1_to_p2(ge_p2 *r, const ge_p1p1 *p) { 257 | fe_mul(r->X, p->X, p->T); 258 | fe_mul(r->Y, p->Y, p->Z); 259 | fe_mul(r->Z, p->Z, p->T); 260 | } 261 | 262 | /* 263 | r = p 264 | */ 265 | 266 | void ge_p1p1_to_p3(ge_p3 *r, const ge_p1p1 *p) { 267 | fe_mul(r->X, p->X, p->T); 268 | fe_mul(r->Y, p->Y, p->Z); 269 | fe_mul(r->Z, p->Z, p->T); 270 | fe_mul(r->T, p->X, p->Y); 271 | } 272 | 273 | void ge_p2_0(ge_p2 *h) { 274 | fe_0(h->X); 275 | fe_1(h->Y); 276 | fe_1(h->Z); 277 | } 278 | 279 | /* 280 | r = 2 * p 281 | */ 282 | 283 | void ge_p2_dbl(ge_p1p1 *r, const ge_p2 *p) { 284 | fe t0; 285 | 286 | fe_sq(r->X, p->X); 287 | fe_sq(r->Z, p->Y); 288 | fe_sq2(r->T, p->Z); 289 | fe_add(r->Y, p->X, p->Y); 290 | fe_sq(t0, r->Y); 291 | fe_add(r->Y, r->Z, r->X); 292 | fe_sub(r->Z, r->Z, r->X); 293 | fe_sub(r->X, t0, r->Y); 294 | fe_sub(r->T, r->T, r->Z); 295 | } 296 | 297 | void ge_p3_0(ge_p3 *h) { 298 | fe_0(h->X); 299 | fe_1(h->Y); 300 | fe_1(h->Z); 301 | fe_0(h->T); 302 | } 303 | 304 | /* 305 | r = 2 * p 306 | */ 307 | 308 | void ge_p3_dbl(ge_p1p1 *r, const ge_p3 *p) { 309 | ge_p2 q; 310 | ge_p3_to_p2(&q, p); 311 | ge_p2_dbl(r, &q); 312 | } 313 | 314 | /* 315 | r = p 316 | */ 317 | 318 | static const fe d2 = { 319 | -21827239, -5839606, -30745221, 13898782, 229458, 15978800, -12551817, -6495438, 29715968, 9444199 320 | }; 321 | 322 | void ge_p3_to_cached(ge_cached *r, const ge_p3 *p) { 323 | fe_add(r->YplusX, p->Y, p->X); 324 | fe_sub(r->YminusX, p->Y, p->X); 325 | fe_copy(r->Z, p->Z); 326 | fe_mul(r->T2d, p->T, d2); 327 | } 328 | 329 | /* 330 | r = p 331 | */ 332 | 333 | void ge_p3_to_p2(ge_p2 *r, const ge_p3 *p) { 334 | fe_copy(r->X, p->X); 335 | fe_copy(r->Y, p->Y); 336 | fe_copy(r->Z, p->Z); 337 | } 338 | 339 | void ge_p3_tobytes(uint8_t *s, const ge_p3 *h) { 340 | fe recip; 341 | fe x; 342 | fe y; 343 | fe_invert(recip, h->Z); 344 | fe_mul(x, h->X, recip); 345 | fe_mul(y, h->Y, recip); 346 | fe_tobytes(s, y); 347 | s[31] ^= fe_isnegative(x) << 7; 348 | } 349 | 350 | static uint8_t equal(int8_t b, int8_t c) { 351 | uint8_t ub = b; 352 | uint8_t uc = c; 353 | uint8_t x = ub ^ uc; /* 0: yes; 1..255: no */ 354 | uint64_t y = x; /* 0: yes; 1..255: no */ 355 | y -= 1; /* large: yes; 0..254: no */ 356 | y >>= 63; /* 1: yes; 0: no */ 357 | return (uint8_t)y; 358 | } 359 | 360 | static uint8_t negative(int8_t b) { 361 | uint64_t x = b; /* 18446744073709551361..18446744073709551615: yes; 0..255: no */ 362 | x >>= 63; /* 1: yes; 0: no */ 363 | return (uint8_t)x; 364 | } 365 | 366 | static void cmov(ge_precomp *t, const ge_precomp *u, uint8_t b) { 367 | fe_cmov(t->yplusx, u->yplusx, b); 368 | fe_cmov(t->yminusx, u->yminusx, b); 369 | fe_cmov(t->xy2d, u->xy2d, b); 370 | } 371 | 372 | static void select(ge_precomp *t, int pos, int8_t b) { 373 | ge_precomp minust; 374 | uint8_t bnegative = negative(b); 375 | uint8_t babs = b - (((-bnegative) & b) << 1); 376 | fe_1(t->yplusx); 377 | fe_1(t->yminusx); 378 | fe_0(t->xy2d); 379 | cmov(t, &base[pos][0], equal(babs, 1)); 380 | cmov(t, &base[pos][1], equal(babs, 2)); 381 | cmov(t, &base[pos][2], equal(babs, 3)); 382 | cmov(t, &base[pos][3], equal(babs, 4)); 383 | cmov(t, &base[pos][4], equal(babs, 5)); 384 | cmov(t, &base[pos][5], equal(babs, 6)); 385 | cmov(t, &base[pos][6], equal(babs, 7)); 386 | cmov(t, &base[pos][7], equal(babs, 8)); 387 | fe_copy(minust.yplusx, t->yminusx); 388 | fe_copy(minust.yminusx, t->yplusx); 389 | fe_neg(minust.xy2d, t->xy2d); 390 | cmov(t, &minust, bnegative); 391 | } 392 | 393 | /* 394 | h = a * B 395 | where a = a[0]+256*a[1]+...+256^31 a[31] 396 | B is the Ed25519 base point (x,4/5) with x positive. 397 | 398 | Preconditions: 399 | a[31] <= 127 400 | */ 401 | 402 | void ge_scalarmult_base(ge_p3 *h, const uint8_t *a) { 403 | int8_t e[64]; 404 | int8_t carry; 405 | ge_p1p1 r; 406 | ge_p2 s; 407 | ge_precomp t; 408 | int i; 409 | 410 | for (i = 0; i < 32; ++i) { 411 | e[2 * i + 0] = (a[i] >> 0) & 15; 412 | e[2 * i + 1] = (a[i] >> 4) & 15; 413 | } 414 | 415 | /* each e[i] is between 0 and 15 */ 416 | /* e[63] is between 0 and 7 */ 417 | carry = 0; 418 | 419 | for (i = 0; i < 63; ++i) { 420 | e[i] += carry; 421 | carry = e[i] + 8; 422 | carry >>= 4; 423 | e[i] -= carry << 4; 424 | } 425 | 426 | e[63] += carry; 427 | /* each e[i] is between -8 and 8 */ 428 | ge_p3_0(h); 429 | 430 | for (i = 1; i < 64; i += 2) { 431 | select(&t, i / 2, e[i]); 432 | ge_madd(&r, h, &t); 433 | ge_p1p1_to_p3(h, &r); 434 | } 435 | 436 | ge_p3_dbl(&r, h); 437 | ge_p1p1_to_p2(&s, &r); 438 | ge_p2_dbl(&r, &s); 439 | ge_p1p1_to_p2(&s, &r); 440 | ge_p2_dbl(&r, &s); 441 | ge_p1p1_to_p2(&s, &r); 442 | ge_p2_dbl(&r, &s); 443 | ge_p1p1_to_p3(h, &r); 444 | 445 | for (i = 0; i < 64; i += 2) { 446 | select(&t, i / 2, e[i]); 447 | ge_madd(&r, h, &t); 448 | ge_p1p1_to_p3(h, &r); 449 | } 450 | } 451 | 452 | /* 453 | r = p - q 454 | */ 455 | 456 | void ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) { 457 | fe t0; 458 | 459 | fe_add(r->X, p->Y, p->X); 460 | fe_sub(r->Y, p->Y, p->X); 461 | fe_mul(r->Z, r->X, q->YminusX); 462 | fe_mul(r->Y, r->Y, q->YplusX); 463 | fe_mul(r->T, q->T2d, p->T); 464 | fe_mul(r->X, p->Z, q->Z); 465 | fe_add(t0, r->X, r->X); 466 | fe_sub(r->X, r->Z, r->Y); 467 | fe_add(r->Y, r->Z, r->Y); 468 | fe_sub(r->Z, t0, r->T); 469 | fe_add(r->T, t0, r->T); 470 | } 471 | 472 | void ge_tobytes(uint8_t *s, const ge_p2 *h) { 473 | fe recip; 474 | fe x; 475 | fe y; 476 | fe_invert(recip, h->Z); 477 | fe_mul(x, h->X, recip); 478 | fe_mul(y, h->Y, recip); 479 | fe_tobytes(s, y); 480 | s[31] ^= fe_isnegative(x) << 7; 481 | } 482 | -------------------------------------------------------------------------------- /ed25519_ref10/ed25519_sc.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************/ 2 | /* ed25519_sc.cpp */ 3 | /*************************************************************************/ 4 | /* This file is part of: */ 5 | /* GODOT ENGINE */ 6 | /* https://godotengine.org */ 7 | /*************************************************************************/ 8 | /* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ 9 | /* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ 10 | /* */ 11 | /* Permission is hereby granted, free of charge, to any person obtaining */ 12 | /* a copy of this software and associated documentation files (the */ 13 | /* "Software"), to deal in the Software without restriction, including */ 14 | /* without limitation the rights to use, copy, modify, merge, publish, */ 15 | /* distribute, sublicense, and/or sell copies of the Software, and to */ 16 | /* permit persons to whom the Software is furnished to do so, subject to */ 17 | /* the following conditions: */ 18 | /* */ 19 | /* The above copyright notice and this permission notice shall be */ 20 | /* included in all copies or substantial portions of the Software. */ 21 | /* */ 22 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 23 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 24 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ 25 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 26 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 27 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 28 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 29 | /*************************************************************************/ 30 | 31 | /* This file was derived from information found at */ 32 | /* https://tools.ietf.org/html/rfc8032#page-44 */ 33 | 34 | #include "ed25519_sc.h" 35 | 36 | static uint64_t load_3(const uint8_t *in) { 37 | uint64_t result; 38 | 39 | result = (uint64_t)in[0]; 40 | result |= ((uint64_t)in[1]) << 8; 41 | result |= ((uint64_t)in[2]) << 16; 42 | 43 | return result; 44 | } 45 | 46 | static uint64_t load_4(const uint8_t *in) { 47 | uint64_t result; 48 | 49 | result = (uint64_t)in[0]; 50 | result |= ((uint64_t)in[1]) << 8; 51 | result |= ((uint64_t)in[2]) << 16; 52 | result |= ((uint64_t)in[3]) << 24; 53 | 54 | return result; 55 | } 56 | 57 | /* 58 | Input: 59 | s[0]+256*s[1]+...+256^63*s[63] = s 60 | 61 | Output: 62 | s[0]+256*s[1]+...+256^31*s[31] = s mod l 63 | where l = 2^252 + 27742317777372353535851937790883648493. 64 | Overwrites s in place. 65 | */ 66 | 67 | void sc_reduce(uint8_t *s) { 68 | int64_t s0 = 2097151 & load_3(s); 69 | int64_t s1 = 2097151 & (load_4(s + 2) >> 5); 70 | int64_t s2 = 2097151 & (load_3(s + 5) >> 2); 71 | int64_t s3 = 2097151 & (load_4(s + 7) >> 7); 72 | int64_t s4 = 2097151 & (load_4(s + 10) >> 4); 73 | int64_t s5 = 2097151 & (load_3(s + 13) >> 1); 74 | int64_t s6 = 2097151 & (load_4(s + 15) >> 6); 75 | int64_t s7 = 2097151 & (load_3(s + 18) >> 3); 76 | int64_t s8 = 2097151 & load_3(s + 21); 77 | int64_t s9 = 2097151 & (load_4(s + 23) >> 5); 78 | int64_t s10 = 2097151 & (load_3(s + 26) >> 2); 79 | int64_t s11 = 2097151 & (load_4(s + 28) >> 7); 80 | int64_t s12 = 2097151 & (load_4(s + 31) >> 4); 81 | int64_t s13 = 2097151 & (load_3(s + 34) >> 1); 82 | int64_t s14 = 2097151 & (load_4(s + 36) >> 6); 83 | int64_t s15 = 2097151 & (load_3(s + 39) >> 3); 84 | int64_t s16 = 2097151 & load_3(s + 42); 85 | int64_t s17 = 2097151 & (load_4(s + 44) >> 5); 86 | int64_t s18 = 2097151 & (load_3(s + 47) >> 2); 87 | int64_t s19 = 2097151 & (load_4(s + 49) >> 7); 88 | int64_t s20 = 2097151 & (load_4(s + 52) >> 4); 89 | int64_t s21 = 2097151 & (load_3(s + 55) >> 1); 90 | int64_t s22 = 2097151 & (load_4(s + 57) >> 6); 91 | int64_t s23 = (load_4(s + 60) >> 3); 92 | int64_t carry0; 93 | int64_t carry1; 94 | int64_t carry2; 95 | int64_t carry3; 96 | int64_t carry4; 97 | int64_t carry5; 98 | int64_t carry6; 99 | int64_t carry7; 100 | int64_t carry8; 101 | int64_t carry9; 102 | int64_t carry10; 103 | int64_t carry11; 104 | int64_t carry12; 105 | int64_t carry13; 106 | int64_t carry14; 107 | int64_t carry15; 108 | int64_t carry16; 109 | 110 | s11 += s23 * 666643; 111 | s12 += s23 * 470296; 112 | s13 += s23 * 654183; 113 | s14 -= s23 * 997805; 114 | s15 += s23 * 136657; 115 | s16 -= s23 * 683901; 116 | s23 = 0; 117 | s10 += s22 * 666643; 118 | s11 += s22 * 470296; 119 | s12 += s22 * 654183; 120 | s13 -= s22 * 997805; 121 | s14 += s22 * 136657; 122 | s15 -= s22 * 683901; 123 | s22 = 0; 124 | s9 += s21 * 666643; 125 | s10 += s21 * 470296; 126 | s11 += s21 * 654183; 127 | s12 -= s21 * 997805; 128 | s13 += s21 * 136657; 129 | s14 -= s21 * 683901; 130 | s21 = 0; 131 | s8 += s20 * 666643; 132 | s9 += s20 * 470296; 133 | s10 += s20 * 654183; 134 | s11 -= s20 * 997805; 135 | s12 += s20 * 136657; 136 | s13 -= s20 * 683901; 137 | s20 = 0; 138 | s7 += s19 * 666643; 139 | s8 += s19 * 470296; 140 | s9 += s19 * 654183; 141 | s10 -= s19 * 997805; 142 | s11 += s19 * 136657; 143 | s12 -= s19 * 683901; 144 | s19 = 0; 145 | s6 += s18 * 666643; 146 | s7 += s18 * 470296; 147 | s8 += s18 * 654183; 148 | s9 -= s18 * 997805; 149 | s10 += s18 * 136657; 150 | s11 -= s18 * 683901; 151 | s18 = 0; 152 | carry6 = (s6 + (1 << 20)) >> 21; 153 | s7 += carry6; 154 | s6 -= carry6 << 21; 155 | carry8 = (s8 + (1 << 20)) >> 21; 156 | s9 += carry8; 157 | s8 -= carry8 << 21; 158 | carry10 = (s10 + (1 << 20)) >> 21; 159 | s11 += carry10; 160 | s10 -= carry10 << 21; 161 | carry12 = (s12 + (1 << 20)) >> 21; 162 | s13 += carry12; 163 | s12 -= carry12 << 21; 164 | carry14 = (s14 + (1 << 20)) >> 21; 165 | s15 += carry14; 166 | s14 -= carry14 << 21; 167 | carry16 = (s16 + (1 << 20)) >> 21; 168 | s17 += carry16; 169 | s16 -= carry16 << 21; 170 | carry7 = (s7 + (1 << 20)) >> 21; 171 | s8 += carry7; 172 | s7 -= carry7 << 21; 173 | carry9 = (s9 + (1 << 20)) >> 21; 174 | s10 += carry9; 175 | s9 -= carry9 << 21; 176 | carry11 = (s11 + (1 << 20)) >> 21; 177 | s12 += carry11; 178 | s11 -= carry11 << 21; 179 | carry13 = (s13 + (1 << 20)) >> 21; 180 | s14 += carry13; 181 | s13 -= carry13 << 21; 182 | carry15 = (s15 + (1 << 20)) >> 21; 183 | s16 += carry15; 184 | s15 -= carry15 << 21; 185 | s5 += s17 * 666643; 186 | s6 += s17 * 470296; 187 | s7 += s17 * 654183; 188 | s8 -= s17 * 997805; 189 | s9 += s17 * 136657; 190 | s10 -= s17 * 683901; 191 | s17 = 0; 192 | s4 += s16 * 666643; 193 | s5 += s16 * 470296; 194 | s6 += s16 * 654183; 195 | s7 -= s16 * 997805; 196 | s8 += s16 * 136657; 197 | s9 -= s16 * 683901; 198 | s16 = 0; 199 | s3 += s15 * 666643; 200 | s4 += s15 * 470296; 201 | s5 += s15 * 654183; 202 | s6 -= s15 * 997805; 203 | s7 += s15 * 136657; 204 | s8 -= s15 * 683901; 205 | s15 = 0; 206 | s2 += s14 * 666643; 207 | s3 += s14 * 470296; 208 | s4 += s14 * 654183; 209 | s5 -= s14 * 997805; 210 | s6 += s14 * 136657; 211 | s7 -= s14 * 683901; 212 | s14 = 0; 213 | s1 += s13 * 666643; 214 | s2 += s13 * 470296; 215 | s3 += s13 * 654183; 216 | s4 -= s13 * 997805; 217 | s5 += s13 * 136657; 218 | s6 -= s13 * 683901; 219 | s13 = 0; 220 | s0 += s12 * 666643; 221 | s1 += s12 * 470296; 222 | s2 += s12 * 654183; 223 | s3 -= s12 * 997805; 224 | s4 += s12 * 136657; 225 | s5 -= s12 * 683901; 226 | s12 = 0; 227 | carry0 = (s0 + (1 << 20)) >> 21; 228 | s1 += carry0; 229 | s0 -= carry0 << 21; 230 | carry2 = (s2 + (1 << 20)) >> 21; 231 | s3 += carry2; 232 | s2 -= carry2 << 21; 233 | carry4 = (s4 + (1 << 20)) >> 21; 234 | s5 += carry4; 235 | s4 -= carry4 << 21; 236 | carry6 = (s6 + (1 << 20)) >> 21; 237 | s7 += carry6; 238 | s6 -= carry6 << 21; 239 | carry8 = (s8 + (1 << 20)) >> 21; 240 | s9 += carry8; 241 | s8 -= carry8 << 21; 242 | carry10 = (s10 + (1 << 20)) >> 21; 243 | s11 += carry10; 244 | s10 -= carry10 << 21; 245 | carry1 = (s1 + (1 << 20)) >> 21; 246 | s2 += carry1; 247 | s1 -= carry1 << 21; 248 | carry3 = (s3 + (1 << 20)) >> 21; 249 | s4 += carry3; 250 | s3 -= carry3 << 21; 251 | carry5 = (s5 + (1 << 20)) >> 21; 252 | s6 += carry5; 253 | s5 -= carry5 << 21; 254 | carry7 = (s7 + (1 << 20)) >> 21; 255 | s8 += carry7; 256 | s7 -= carry7 << 21; 257 | carry9 = (s9 + (1 << 20)) >> 21; 258 | s10 += carry9; 259 | s9 -= carry9 << 21; 260 | carry11 = (s11 + (1 << 20)) >> 21; 261 | s12 += carry11; 262 | s11 -= carry11 << 21; 263 | s0 += s12 * 666643; 264 | s1 += s12 * 470296; 265 | s2 += s12 * 654183; 266 | s3 -= s12 * 997805; 267 | s4 += s12 * 136657; 268 | s5 -= s12 * 683901; 269 | s12 = 0; 270 | carry0 = s0 >> 21; 271 | s1 += carry0; 272 | s0 -= carry0 << 21; 273 | carry1 = s1 >> 21; 274 | s2 += carry1; 275 | s1 -= carry1 << 21; 276 | carry2 = s2 >> 21; 277 | s3 += carry2; 278 | s2 -= carry2 << 21; 279 | carry3 = s3 >> 21; 280 | s4 += carry3; 281 | s3 -= carry3 << 21; 282 | carry4 = s4 >> 21; 283 | s5 += carry4; 284 | s4 -= carry4 << 21; 285 | carry5 = s5 >> 21; 286 | s6 += carry5; 287 | s5 -= carry5 << 21; 288 | carry6 = s6 >> 21; 289 | s7 += carry6; 290 | s6 -= carry6 << 21; 291 | carry7 = s7 >> 21; 292 | s8 += carry7; 293 | s7 -= carry7 << 21; 294 | carry8 = s8 >> 21; 295 | s9 += carry8; 296 | s8 -= carry8 << 21; 297 | carry9 = s9 >> 21; 298 | s10 += carry9; 299 | s9 -= carry9 << 21; 300 | carry10 = s10 >> 21; 301 | s11 += carry10; 302 | s10 -= carry10 << 21; 303 | carry11 = s11 >> 21; 304 | s12 += carry11; 305 | s11 -= carry11 << 21; 306 | s0 += s12 * 666643; 307 | s1 += s12 * 470296; 308 | s2 += s12 * 654183; 309 | s3 -= s12 * 997805; 310 | s4 += s12 * 136657; 311 | s5 -= s12 * 683901; 312 | s12 = 0; 313 | carry0 = s0 >> 21; 314 | s1 += carry0; 315 | s0 -= carry0 << 21; 316 | carry1 = s1 >> 21; 317 | s2 += carry1; 318 | s1 -= carry1 << 21; 319 | carry2 = s2 >> 21; 320 | s3 += carry2; 321 | s2 -= carry2 << 21; 322 | carry3 = s3 >> 21; 323 | s4 += carry3; 324 | s3 -= carry3 << 21; 325 | carry4 = s4 >> 21; 326 | s5 += carry4; 327 | s4 -= carry4 << 21; 328 | carry5 = s5 >> 21; 329 | s6 += carry5; 330 | s5 -= carry5 << 21; 331 | carry6 = s6 >> 21; 332 | s7 += carry6; 333 | s6 -= carry6 << 21; 334 | carry7 = s7 >> 21; 335 | s8 += carry7; 336 | s7 -= carry7 << 21; 337 | carry8 = s8 >> 21; 338 | s9 += carry8; 339 | s8 -= carry8 << 21; 340 | carry9 = s9 >> 21; 341 | s10 += carry9; 342 | s9 -= carry9 << 21; 343 | carry10 = s10 >> 21; 344 | s11 += carry10; 345 | s10 -= carry10 << 21; 346 | 347 | s[0] = (uint8_t)(s0 >> 0); 348 | s[1] = (uint8_t)(s0 >> 8); 349 | s[2] = (uint8_t)((s0 >> 16) | (s1 << 5)); 350 | s[3] = (uint8_t)(s1 >> 3); 351 | s[4] = (uint8_t)(s1 >> 11); 352 | s[5] = (uint8_t)((s1 >> 19) | (s2 << 2)); 353 | s[6] = (uint8_t)(s2 >> 6); 354 | s[7] = (uint8_t)((s2 >> 14) | (s3 << 7)); 355 | s[8] = (uint8_t)(s3 >> 1); 356 | s[9] = (uint8_t)(s3 >> 9); 357 | s[10] = (uint8_t)((s3 >> 17) | (s4 << 4)); 358 | s[11] = (uint8_t)(s4 >> 4); 359 | s[12] = (uint8_t)(s4 >> 12); 360 | s[13] = (uint8_t)((s4 >> 20) | (s5 << 1)); 361 | s[14] = (uint8_t)(s5 >> 7); 362 | s[15] = (uint8_t)((s5 >> 15) | (s6 << 6)); 363 | s[16] = (uint8_t)(s6 >> 2); 364 | s[17] = (uint8_t)(s6 >> 10); 365 | s[18] = (uint8_t)((s6 >> 18) | (s7 << 3)); 366 | s[19] = (uint8_t)(s7 >> 5); 367 | s[20] = (uint8_t)(s7 >> 13); 368 | s[21] = (uint8_t)(s8 >> 0); 369 | s[22] = (uint8_t)(s8 >> 8); 370 | s[23] = (uint8_t)((s8 >> 16) | (s9 << 5)); 371 | s[24] = (uint8_t)(s9 >> 3); 372 | s[25] = (uint8_t)(s9 >> 11); 373 | s[26] = (uint8_t)((s9 >> 19) | (s10 << 2)); 374 | s[27] = (uint8_t)(s10 >> 6); 375 | s[28] = (uint8_t)((s10 >> 14) | (s11 << 7)); 376 | s[29] = (uint8_t)(s11 >> 1); 377 | s[30] = (uint8_t)(s11 >> 9); 378 | s[31] = (uint8_t)(s11 >> 17); 379 | } 380 | 381 | /* 382 | Input: 383 | a[0]+256*a[1]+...+256^31*a[31] = a 384 | b[0]+256*b[1]+...+256^31*b[31] = b 385 | c[0]+256*c[1]+...+256^31*c[31] = c 386 | 387 | Output: 388 | s[0]+256*s[1]+...+256^31*s[31] = (ab+c) mod l 389 | where l = 2^252 + 27742317777372353535851937790883648493. 390 | */ 391 | 392 | void sc_muladd(uint8_t *s, const uint8_t *a, const uint8_t *b, const uint8_t *c) { 393 | int64_t a0 = 2097151 & load_3(a); 394 | int64_t a1 = 2097151 & (load_4(a + 2) >> 5); 395 | int64_t a2 = 2097151 & (load_3(a + 5) >> 2); 396 | int64_t a3 = 2097151 & (load_4(a + 7) >> 7); 397 | int64_t a4 = 2097151 & (load_4(a + 10) >> 4); 398 | int64_t a5 = 2097151 & (load_3(a + 13) >> 1); 399 | int64_t a6 = 2097151 & (load_4(a + 15) >> 6); 400 | int64_t a7 = 2097151 & (load_3(a + 18) >> 3); 401 | int64_t a8 = 2097151 & load_3(a + 21); 402 | int64_t a9 = 2097151 & (load_4(a + 23) >> 5); 403 | int64_t a10 = 2097151 & (load_3(a + 26) >> 2); 404 | int64_t a11 = (load_4(a + 28) >> 7); 405 | int64_t b0 = 2097151 & load_3(b); 406 | int64_t b1 = 2097151 & (load_4(b + 2) >> 5); 407 | int64_t b2 = 2097151 & (load_3(b + 5) >> 2); 408 | int64_t b3 = 2097151 & (load_4(b + 7) >> 7); 409 | int64_t b4 = 2097151 & (load_4(b + 10) >> 4); 410 | int64_t b5 = 2097151 & (load_3(b + 13) >> 1); 411 | int64_t b6 = 2097151 & (load_4(b + 15) >> 6); 412 | int64_t b7 = 2097151 & (load_3(b + 18) >> 3); 413 | int64_t b8 = 2097151 & load_3(b + 21); 414 | int64_t b9 = 2097151 & (load_4(b + 23) >> 5); 415 | int64_t b10 = 2097151 & (load_3(b + 26) >> 2); 416 | int64_t b11 = (load_4(b + 28) >> 7); 417 | int64_t c0 = 2097151 & load_3(c); 418 | int64_t c1 = 2097151 & (load_4(c + 2) >> 5); 419 | int64_t c2 = 2097151 & (load_3(c + 5) >> 2); 420 | int64_t c3 = 2097151 & (load_4(c + 7) >> 7); 421 | int64_t c4 = 2097151 & (load_4(c + 10) >> 4); 422 | int64_t c5 = 2097151 & (load_3(c + 13) >> 1); 423 | int64_t c6 = 2097151 & (load_4(c + 15) >> 6); 424 | int64_t c7 = 2097151 & (load_3(c + 18) >> 3); 425 | int64_t c8 = 2097151 & load_3(c + 21); 426 | int64_t c9 = 2097151 & (load_4(c + 23) >> 5); 427 | int64_t c10 = 2097151 & (load_3(c + 26) >> 2); 428 | int64_t c11 = (load_4(c + 28) >> 7); 429 | int64_t s0; 430 | int64_t s1; 431 | int64_t s2; 432 | int64_t s3; 433 | int64_t s4; 434 | int64_t s5; 435 | int64_t s6; 436 | int64_t s7; 437 | int64_t s8; 438 | int64_t s9; 439 | int64_t s10; 440 | int64_t s11; 441 | int64_t s12; 442 | int64_t s13; 443 | int64_t s14; 444 | int64_t s15; 445 | int64_t s16; 446 | int64_t s17; 447 | int64_t s18; 448 | int64_t s19; 449 | int64_t s20; 450 | int64_t s21; 451 | int64_t s22; 452 | int64_t s23; 453 | int64_t carry0; 454 | int64_t carry1; 455 | int64_t carry2; 456 | int64_t carry3; 457 | int64_t carry4; 458 | int64_t carry5; 459 | int64_t carry6; 460 | int64_t carry7; 461 | int64_t carry8; 462 | int64_t carry9; 463 | int64_t carry10; 464 | int64_t carry11; 465 | int64_t carry12; 466 | int64_t carry13; 467 | int64_t carry14; 468 | int64_t carry15; 469 | int64_t carry16; 470 | int64_t carry17; 471 | int64_t carry18; 472 | int64_t carry19; 473 | int64_t carry20; 474 | int64_t carry21; 475 | int64_t carry22; 476 | 477 | s0 = c0 + a0 * b0; 478 | s1 = c1 + a0 * b1 + a1 * b0; 479 | s2 = c2 + a0 * b2 + a1 * b1 + a2 * b0; 480 | s3 = c3 + a0 * b3 + a1 * b2 + a2 * b1 + a3 * b0; 481 | s4 = c4 + a0 * b4 + a1 * b3 + a2 * b2 + a3 * b1 + a4 * b0; 482 | s5 = c5 + a0 * b5 + a1 * b4 + a2 * b3 + a3 * b2 + a4 * b1 + a5 * b0; 483 | s6 = c6 + a0 * b6 + a1 * b5 + a2 * b4 + a3 * b3 + a4 * b2 + a5 * b1 + a6 * b0; 484 | s7 = c7 + a0 * b7 + a1 * b6 + a2 * b5 + a3 * b4 + a4 * b3 + a5 * b2 + a6 * b1 + a7 * b0; 485 | s8 = c8 + a0 * b8 + a1 * b7 + a2 * b6 + a3 * b5 + a4 * b4 + a5 * b3 + a6 * b2 + a7 * b1 + a8 * b0; 486 | s9 = c9 + a0 * b9 + a1 * b8 + a2 * b7 + a3 * b6 + a4 * b5 + a5 * b4 + a6 * b3 + a7 * b2 + a8 * b1 + a9 * b0; 487 | s10 = c10 + a0 * b10 + a1 * b9 + a2 * b8 + a3 * b7 + a4 * b6 + a5 * b5 + a6 * b4 + a7 * b3 + a8 * b2 + a9 * b1 + a10 * b0; 488 | s11 = c11 + a0 * b11 + a1 * b10 + a2 * b9 + a3 * b8 + a4 * b7 + a5 * b6 + a6 * b5 + a7 * b4 + a8 * b3 + a9 * b2 + a10 * b1 + a11 * b0; 489 | s12 = a1 * b11 + a2 * b10 + a3 * b9 + a4 * b8 + a5 * b7 + a6 * b6 + a7 * b5 + a8 * b4 + a9 * b3 + a10 * b2 + a11 * b1; 490 | s13 = a2 * b11 + a3 * b10 + a4 * b9 + a5 * b8 + a6 * b7 + a7 * b6 + a8 * b5 + a9 * b4 + a10 * b3 + a11 * b2; 491 | s14 = a3 * b11 + a4 * b10 + a5 * b9 + a6 * b8 + a7 * b7 + a8 * b6 + a9 * b5 + a10 * b4 + a11 * b3; 492 | s15 = a4 * b11 + a5 * b10 + a6 * b9 + a7 * b8 + a8 * b7 + a9 * b6 + a10 * b5 + a11 * b4; 493 | s16 = a5 * b11 + a6 * b10 + a7 * b9 + a8 * b8 + a9 * b7 + a10 * b6 + a11 * b5; 494 | s17 = a6 * b11 + a7 * b10 + a8 * b9 + a9 * b8 + a10 * b7 + a11 * b6; 495 | s18 = a7 * b11 + a8 * b10 + a9 * b9 + a10 * b8 + a11 * b7; 496 | s19 = a8 * b11 + a9 * b10 + a10 * b9 + a11 * b8; 497 | s20 = a9 * b11 + a10 * b10 + a11 * b9; 498 | s21 = a10 * b11 + a11 * b10; 499 | s22 = a11 * b11; 500 | s23 = 0; 501 | carry0 = (s0 + (1 << 20)) >> 21; 502 | s1 += carry0; 503 | s0 -= carry0 << 21; 504 | carry2 = (s2 + (1 << 20)) >> 21; 505 | s3 += carry2; 506 | s2 -= carry2 << 21; 507 | carry4 = (s4 + (1 << 20)) >> 21; 508 | s5 += carry4; 509 | s4 -= carry4 << 21; 510 | carry6 = (s6 + (1 << 20)) >> 21; 511 | s7 += carry6; 512 | s6 -= carry6 << 21; 513 | carry8 = (s8 + (1 << 20)) >> 21; 514 | s9 += carry8; 515 | s8 -= carry8 << 21; 516 | carry10 = (s10 + (1 << 20)) >> 21; 517 | s11 += carry10; 518 | s10 -= carry10 << 21; 519 | carry12 = (s12 + (1 << 20)) >> 21; 520 | s13 += carry12; 521 | s12 -= carry12 << 21; 522 | carry14 = (s14 + (1 << 20)) >> 21; 523 | s15 += carry14; 524 | s14 -= carry14 << 21; 525 | carry16 = (s16 + (1 << 20)) >> 21; 526 | s17 += carry16; 527 | s16 -= carry16 << 21; 528 | carry18 = (s18 + (1 << 20)) >> 21; 529 | s19 += carry18; 530 | s18 -= carry18 << 21; 531 | carry20 = (s20 + (1 << 20)) >> 21; 532 | s21 += carry20; 533 | s20 -= carry20 << 21; 534 | carry22 = (s22 + (1 << 20)) >> 21; 535 | s23 += carry22; 536 | s22 -= carry22 << 21; 537 | carry1 = (s1 + (1 << 20)) >> 21; 538 | s2 += carry1; 539 | s1 -= carry1 << 21; 540 | carry3 = (s3 + (1 << 20)) >> 21; 541 | s4 += carry3; 542 | s3 -= carry3 << 21; 543 | carry5 = (s5 + (1 << 20)) >> 21; 544 | s6 += carry5; 545 | s5 -= carry5 << 21; 546 | carry7 = (s7 + (1 << 20)) >> 21; 547 | s8 += carry7; 548 | s7 -= carry7 << 21; 549 | carry9 = (s9 + (1 << 20)) >> 21; 550 | s10 += carry9; 551 | s9 -= carry9 << 21; 552 | carry11 = (s11 + (1 << 20)) >> 21; 553 | s12 += carry11; 554 | s11 -= carry11 << 21; 555 | carry13 = (s13 + (1 << 20)) >> 21; 556 | s14 += carry13; 557 | s13 -= carry13 << 21; 558 | carry15 = (s15 + (1 << 20)) >> 21; 559 | s16 += carry15; 560 | s15 -= carry15 << 21; 561 | carry17 = (s17 + (1 << 20)) >> 21; 562 | s18 += carry17; 563 | s17 -= carry17 << 21; 564 | carry19 = (s19 + (1 << 20)) >> 21; 565 | s20 += carry19; 566 | s19 -= carry19 << 21; 567 | carry21 = (s21 + (1 << 20)) >> 21; 568 | s22 += carry21; 569 | s21 -= carry21 << 21; 570 | s11 += s23 * 666643; 571 | s12 += s23 * 470296; 572 | s13 += s23 * 654183; 573 | s14 -= s23 * 997805; 574 | s15 += s23 * 136657; 575 | s16 -= s23 * 683901; 576 | s23 = 0; 577 | s10 += s22 * 666643; 578 | s11 += s22 * 470296; 579 | s12 += s22 * 654183; 580 | s13 -= s22 * 997805; 581 | s14 += s22 * 136657; 582 | s15 -= s22 * 683901; 583 | s22 = 0; 584 | s9 += s21 * 666643; 585 | s10 += s21 * 470296; 586 | s11 += s21 * 654183; 587 | s12 -= s21 * 997805; 588 | s13 += s21 * 136657; 589 | s14 -= s21 * 683901; 590 | s21 = 0; 591 | s8 += s20 * 666643; 592 | s9 += s20 * 470296; 593 | s10 += s20 * 654183; 594 | s11 -= s20 * 997805; 595 | s12 += s20 * 136657; 596 | s13 -= s20 * 683901; 597 | s20 = 0; 598 | s7 += s19 * 666643; 599 | s8 += s19 * 470296; 600 | s9 += s19 * 654183; 601 | s10 -= s19 * 997805; 602 | s11 += s19 * 136657; 603 | s12 -= s19 * 683901; 604 | s19 = 0; 605 | s6 += s18 * 666643; 606 | s7 += s18 * 470296; 607 | s8 += s18 * 654183; 608 | s9 -= s18 * 997805; 609 | s10 += s18 * 136657; 610 | s11 -= s18 * 683901; 611 | s18 = 0; 612 | carry6 = (s6 + (1 << 20)) >> 21; 613 | s7 += carry6; 614 | s6 -= carry6 << 21; 615 | carry8 = (s8 + (1 << 20)) >> 21; 616 | s9 += carry8; 617 | s8 -= carry8 << 21; 618 | carry10 = (s10 + (1 << 20)) >> 21; 619 | s11 += carry10; 620 | s10 -= carry10 << 21; 621 | carry12 = (s12 + (1 << 20)) >> 21; 622 | s13 += carry12; 623 | s12 -= carry12 << 21; 624 | carry14 = (s14 + (1 << 20)) >> 21; 625 | s15 += carry14; 626 | s14 -= carry14 << 21; 627 | carry16 = (s16 + (1 << 20)) >> 21; 628 | s17 += carry16; 629 | s16 -= carry16 << 21; 630 | carry7 = (s7 + (1 << 20)) >> 21; 631 | s8 += carry7; 632 | s7 -= carry7 << 21; 633 | carry9 = (s9 + (1 << 20)) >> 21; 634 | s10 += carry9; 635 | s9 -= carry9 << 21; 636 | carry11 = (s11 + (1 << 20)) >> 21; 637 | s12 += carry11; 638 | s11 -= carry11 << 21; 639 | carry13 = (s13 + (1 << 20)) >> 21; 640 | s14 += carry13; 641 | s13 -= carry13 << 21; 642 | carry15 = (s15 + (1 << 20)) >> 21; 643 | s16 += carry15; 644 | s15 -= carry15 << 21; 645 | s5 += s17 * 666643; 646 | s6 += s17 * 470296; 647 | s7 += s17 * 654183; 648 | s8 -= s17 * 997805; 649 | s9 += s17 * 136657; 650 | s10 -= s17 * 683901; 651 | s17 = 0; 652 | s4 += s16 * 666643; 653 | s5 += s16 * 470296; 654 | s6 += s16 * 654183; 655 | s7 -= s16 * 997805; 656 | s8 += s16 * 136657; 657 | s9 -= s16 * 683901; 658 | s16 = 0; 659 | s3 += s15 * 666643; 660 | s4 += s15 * 470296; 661 | s5 += s15 * 654183; 662 | s6 -= s15 * 997805; 663 | s7 += s15 * 136657; 664 | s8 -= s15 * 683901; 665 | s15 = 0; 666 | s2 += s14 * 666643; 667 | s3 += s14 * 470296; 668 | s4 += s14 * 654183; 669 | s5 -= s14 * 997805; 670 | s6 += s14 * 136657; 671 | s7 -= s14 * 683901; 672 | s14 = 0; 673 | s1 += s13 * 666643; 674 | s2 += s13 * 470296; 675 | s3 += s13 * 654183; 676 | s4 -= s13 * 997805; 677 | s5 += s13 * 136657; 678 | s6 -= s13 * 683901; 679 | s13 = 0; 680 | s0 += s12 * 666643; 681 | s1 += s12 * 470296; 682 | s2 += s12 * 654183; 683 | s3 -= s12 * 997805; 684 | s4 += s12 * 136657; 685 | s5 -= s12 * 683901; 686 | s12 = 0; 687 | carry0 = (s0 + (1 << 20)) >> 21; 688 | s1 += carry0; 689 | s0 -= carry0 << 21; 690 | carry2 = (s2 + (1 << 20)) >> 21; 691 | s3 += carry2; 692 | s2 -= carry2 << 21; 693 | carry4 = (s4 + (1 << 20)) >> 21; 694 | s5 += carry4; 695 | s4 -= carry4 << 21; 696 | carry6 = (s6 + (1 << 20)) >> 21; 697 | s7 += carry6; 698 | s6 -= carry6 << 21; 699 | carry8 = (s8 + (1 << 20)) >> 21; 700 | s9 += carry8; 701 | s8 -= carry8 << 21; 702 | carry10 = (s10 + (1 << 20)) >> 21; 703 | s11 += carry10; 704 | s10 -= carry10 << 21; 705 | carry1 = (s1 + (1 << 20)) >> 21; 706 | s2 += carry1; 707 | s1 -= carry1 << 21; 708 | carry3 = (s3 + (1 << 20)) >> 21; 709 | s4 += carry3; 710 | s3 -= carry3 << 21; 711 | carry5 = (s5 + (1 << 20)) >> 21; 712 | s6 += carry5; 713 | s5 -= carry5 << 21; 714 | carry7 = (s7 + (1 << 20)) >> 21; 715 | s8 += carry7; 716 | s7 -= carry7 << 21; 717 | carry9 = (s9 + (1 << 20)) >> 21; 718 | s10 += carry9; 719 | s9 -= carry9 << 21; 720 | carry11 = (s11 + (1 << 20)) >> 21; 721 | s12 += carry11; 722 | s11 -= carry11 << 21; 723 | s0 += s12 * 666643; 724 | s1 += s12 * 470296; 725 | s2 += s12 * 654183; 726 | s3 -= s12 * 997805; 727 | s4 += s12 * 136657; 728 | s5 -= s12 * 683901; 729 | s12 = 0; 730 | carry0 = s0 >> 21; 731 | s1 += carry0; 732 | s0 -= carry0 << 21; 733 | carry1 = s1 >> 21; 734 | s2 += carry1; 735 | s1 -= carry1 << 21; 736 | carry2 = s2 >> 21; 737 | s3 += carry2; 738 | s2 -= carry2 << 21; 739 | carry3 = s3 >> 21; 740 | s4 += carry3; 741 | s3 -= carry3 << 21; 742 | carry4 = s4 >> 21; 743 | s5 += carry4; 744 | s4 -= carry4 << 21; 745 | carry5 = s5 >> 21; 746 | s6 += carry5; 747 | s5 -= carry5 << 21; 748 | carry6 = s6 >> 21; 749 | s7 += carry6; 750 | s6 -= carry6 << 21; 751 | carry7 = s7 >> 21; 752 | s8 += carry7; 753 | s7 -= carry7 << 21; 754 | carry8 = s8 >> 21; 755 | s9 += carry8; 756 | s8 -= carry8 << 21; 757 | carry9 = s9 >> 21; 758 | s10 += carry9; 759 | s9 -= carry9 << 21; 760 | carry10 = s10 >> 21; 761 | s11 += carry10; 762 | s10 -= carry10 << 21; 763 | carry11 = s11 >> 21; 764 | s12 += carry11; 765 | s11 -= carry11 << 21; 766 | s0 += s12 * 666643; 767 | s1 += s12 * 470296; 768 | s2 += s12 * 654183; 769 | s3 -= s12 * 997805; 770 | s4 += s12 * 136657; 771 | s5 -= s12 * 683901; 772 | s12 = 0; 773 | carry0 = s0 >> 21; 774 | s1 += carry0; 775 | s0 -= carry0 << 21; 776 | carry1 = s1 >> 21; 777 | s2 += carry1; 778 | s1 -= carry1 << 21; 779 | carry2 = s2 >> 21; 780 | s3 += carry2; 781 | s2 -= carry2 << 21; 782 | carry3 = s3 >> 21; 783 | s4 += carry3; 784 | s3 -= carry3 << 21; 785 | carry4 = s4 >> 21; 786 | s5 += carry4; 787 | s4 -= carry4 << 21; 788 | carry5 = s5 >> 21; 789 | s6 += carry5; 790 | s5 -= carry5 << 21; 791 | carry6 = s6 >> 21; 792 | s7 += carry6; 793 | s6 -= carry6 << 21; 794 | carry7 = s7 >> 21; 795 | s8 += carry7; 796 | s7 -= carry7 << 21; 797 | carry8 = s8 >> 21; 798 | s9 += carry8; 799 | s8 -= carry8 << 21; 800 | carry9 = s9 >> 21; 801 | s10 += carry9; 802 | s9 -= carry9 << 21; 803 | carry10 = s10 >> 21; 804 | s11 += carry10; 805 | s10 -= carry10 << 21; 806 | 807 | s[0] = (uint8_t)(s0 >> 0); 808 | s[1] = (uint8_t)(s0 >> 8); 809 | s[2] = (uint8_t)((s0 >> 16) | (s1 << 5)); 810 | s[3] = (uint8_t)(s1 >> 3); 811 | s[4] = (uint8_t)(s1 >> 11); 812 | s[5] = (uint8_t)((s1 >> 19) | (s2 << 2)); 813 | s[6] = (uint8_t)(s2 >> 6); 814 | s[7] = (uint8_t)((s2 >> 14) | (s3 << 7)); 815 | s[8] = (uint8_t)(s3 >> 1); 816 | s[9] = (uint8_t)(s3 >> 9); 817 | s[10] = (uint8_t)((s3 >> 17) | (s4 << 4)); 818 | s[11] = (uint8_t)(s4 >> 4); 819 | s[12] = (uint8_t)(s4 >> 12); 820 | s[13] = (uint8_t)((s4 >> 20) | (s5 << 1)); 821 | s[14] = (uint8_t)(s5 >> 7); 822 | s[15] = (uint8_t)((s5 >> 15) | (s6 << 6)); 823 | s[16] = (uint8_t)(s6 >> 2); 824 | s[17] = (uint8_t)(s6 >> 10); 825 | s[18] = (uint8_t)((s6 >> 18) | (s7 << 3)); 826 | s[19] = (uint8_t)(s7 >> 5); 827 | s[20] = (uint8_t)(s7 >> 13); 828 | s[21] = (uint8_t)(s8 >> 0); 829 | s[22] = (uint8_t)(s8 >> 8); 830 | s[23] = (uint8_t)((s8 >> 16) | (s9 << 5)); 831 | s[24] = (uint8_t)(s9 >> 3); 832 | s[25] = (uint8_t)(s9 >> 11); 833 | s[26] = (uint8_t)((s9 >> 19) | (s10 << 2)); 834 | s[27] = (uint8_t)(s10 >> 6); 835 | s[28] = (uint8_t)((s10 >> 14) | (s11 << 7)); 836 | s[29] = (uint8_t)(s11 >> 1); 837 | s[30] = (uint8_t)(s11 >> 9); 838 | s[31] = (uint8_t)(s11 >> 17); 839 | } 840 | -------------------------------------------------------------------------------- /mariadb.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************/ 2 | /* mariadb.cpp */ 3 | /*************************************************************************/ 4 | /* This file is part of: */ 5 | /* GODOT ENGINE */ 6 | /* https://godotengine.org */ 7 | /*************************************************************************/ 8 | /* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ 9 | /* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ 10 | /* */ 11 | /* Permission is hereby granted, free of charge, to any person obtaining */ 12 | /* a copy of this software and associated documentation files (the */ 13 | /* "Software"), to deal in the Software without restriction, including */ 14 | /* without limitation the rights to use, copy, modify, merge, publish, */ 15 | /* distribute, sublicense, and/or sell copies of the Software, and to */ 16 | /* permit persons to whom the Software is furnished to do so, subject to */ 17 | /* the following conditions: */ 18 | /* */ 19 | /* The above copyright notice and this permission notice shall be */ 20 | /* included in all copies or substantial portions of the Software. */ 21 | /* */ 22 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 23 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 24 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ 25 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 26 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 27 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 28 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 29 | /*************************************************************************/ 30 | 31 | #include "mariadb.h" 32 | 33 | #include "mariadb_auth.h" 34 | //#include "utils/console.h" //removed for iostream removal 35 | #include "mariadb_conversions.h" 36 | //#include "utils/print_funcs.h" 37 | 38 | #include //for std::cout Using ERR_FAIL_COND_MSG(false, msg) 39 | //#include 40 | //#include //remove for Godot usage guidelines no stl 41 | //#include //remove for Godot usage guidelines no stl 42 | //#include //remove for Godot usage guidelines no stl 43 | 44 | #include "core/os/memory.h" 45 | #include "core/variant/variant.h" 46 | #include 47 | 48 | MariaDB::MariaDB() { 49 | } 50 | 51 | MariaDB::~MariaDB() { 52 | disconnect_db(); 53 | // _tcp_polling = false; 54 | // _running = false; 55 | 56 | // if (_tcp_thread.is_started()) 57 | // _tcp_thread.wait_to_finish(); 58 | } 59 | 60 | //Bind all your methods used in this class 61 | void MariaDB::_bind_methods() { 62 | ClassDB::bind_method(D_METHOD("connect_db", "hostname", "port", "database", "username", "password", "authtype", 63 | "is_prehashed"), 64 | &MariaDB::connect_db, DEFVAL(AUTH_TYPE_ED25519), DEFVAL(true)); 65 | ClassDB::bind_method(D_METHOD("disconnect_db"), &MariaDB::disconnect_db); 66 | ClassDB::bind_method(D_METHOD("get_last_query"), &MariaDB::get_last_query); 67 | ClassDB::bind_method(D_METHOD("get_last_query_converted"), &MariaDB::get_last_query_converted); 68 | ClassDB::bind_method(D_METHOD("get_last_response"), &MariaDB::get_last_response); 69 | ClassDB::bind_method(D_METHOD("get_last_transmitted"), &MariaDB::get_last_transmitted); 70 | ClassDB::bind_method(D_METHOD("is_connected_db"), &MariaDB::is_connected_db); 71 | ClassDB::bind_method(D_METHOD("set_dbl_to_string", "is_to_str"), &MariaDB::set_dbl_to_string); 72 | ClassDB::bind_method(D_METHOD("set_db_name", "db_name"), &MariaDB::set_db_name); 73 | ClassDB::bind_method(D_METHOD("query", "sql_stmt"), &MariaDB::query); 74 | 75 | BIND_ENUM_CONSTANT(IP_TYPE_IPV4); 76 | BIND_ENUM_CONSTANT(IP_TYPE_IPV6); 77 | BIND_ENUM_CONSTANT(IP_TYPE_ANY); 78 | 79 | BIND_ENUM_CONSTANT(AUTH_TYPE_MYSQL_NATIVE); 80 | BIND_ENUM_CONSTANT(AUTH_TYPE_ED25519); 81 | } 82 | 83 | //Custom Functions 84 | //private 85 | void MariaDB::m_add_packet_header(Vector &p_pkt, uint8_t p_pkt_seq) { 86 | Vector t = little_endian_to_vbytes(p_pkt.size(), 3); 87 | t.push_back(p_pkt_seq); 88 | t.append_array(p_pkt); 89 | p_pkt = t.duplicate(); 90 | } 91 | 92 | // void MariaDB::m_append_thread_data(PackedByteArray &p_data, const uint64_t p_timeout) { 93 | // int sz = 0; 94 | // uint64_t start = OS::get_singleton()->get_ticks_msec(); 95 | // while (sz == 0 && OS::get_singleton()->get_ticks_msec() - start <= p_timeout) { 96 | // _tcp_mutex.lock(); 97 | // sz = _tcp_thread_data.size(); 98 | // if (sz > 0) { 99 | // p_data.append_array(_tcp_thread_data); 100 | // _tcp_thread_data.clear(); 101 | // } 102 | // _tcp_mutex.unlock(); 103 | // if (sz == 0) { 104 | // OS::get_singleton()->delay_usec(1000); 105 | // } 106 | // } 107 | // } 108 | 109 | uint32_t MariaDB::m_chk_rcv_bfr(Vector &p_bfr, int &p_bfr_size, const size_t p_cur_pos, const size_t p_need) { 110 | if (p_bfr_size - p_cur_pos < p_need) 111 | // m_append_thread_data(p_bfr); 112 | p_bfr.append_array(m_recv_data(1000)); 113 | 114 | p_bfr_size = p_bfr.size(); 115 | if (p_bfr_size - p_cur_pos < p_need) { 116 | return (uint32_t)ERR_PACKET_LENGTH_MISMATCH; 117 | } else { 118 | return (uint32_t)OK; 119 | } 120 | } 121 | 122 | //client protocol 4.1 123 | Error MariaDB::m_client_protocol_v41(const AuthType p_srvr_auth_type, const Vector p_srvr_salt) { 124 | Vector srvr_response; 125 | Vector srvr_auth_msg; 126 | uint8_t seq_num = 0; 127 | AuthType user_auth_type = AUTH_TYPE_ED25519; 128 | 129 | //Per https://mariadb.com/kb/en/connection/#handshake-response-packet 130 | //int<4> client capabilities 131 | _client_capabilities = 0; 132 | _client_capabilities |= (_server_capabilities & (uint64_t)Capabilities::CLIENT_MYSQL); 133 | //client_capabilities |= (uint64_t)Capabilities::FOUND_ROWS; 134 | _client_capabilities |= (uint64_t)Capabilities::LONG_FLAG; //?? 135 | _client_capabilities |= (_server_capabilities & (uint64_t)Capabilities::CONNECT_WITH_DB); 136 | _client_capabilities |= (uint64_t)Capabilities::LOCAL_FILES; 137 | _client_capabilities |= (uint64_t)Capabilities::CLIENT_PROTOCOL_41; 138 | _client_capabilities |= (uint64_t)Capabilities::CLIENT_INTERACTIVE; 139 | _client_capabilities |= (uint64_t)Capabilities::SECURE_CONNECTION; 140 | 141 | // Not listed in MariaDB docs but if not set it won't parse the stream correctly 142 | _client_capabilities |= (uint64_t)Capabilities::RESERVED2; 143 | 144 | _client_capabilities |= (uint64_t)Capabilities::MULTI_STATEMENTS; 145 | _client_capabilities |= (uint64_t)Capabilities::MULTI_RESULTS; 146 | _client_capabilities |= (uint64_t)Capabilities::PS_MULTI_RESULTS; 147 | _client_capabilities |= (uint64_t)Capabilities::PLUGIN_AUTH; 148 | 149 | // Don't think this is needed for game dev needs, maybe for prepared statements? 150 | // _client_capabilities |= (_server_capabilities & (uint64_t)Capabilities::CLIENT_SEND_CONNECT_ATTRS); 151 | 152 | _client_capabilities |= (uint64_t)Capabilities::CAN_HANDLE_EXPIRED_PASSWORDS; //?? 153 | _client_capabilities |= (uint64_t)Capabilities::SESSION_TRACK; 154 | _client_capabilities |= (_server_capabilities & (uint64_t)Capabilities::CLIENT_DEPRECATE_EOF); 155 | _client_capabilities |= (uint64_t)Capabilities::REMEMBER_OPTIONS; //?? 156 | 157 | // Only send the first 4 bytes(32 bits) of capabilities the remaining will be sent later in another 4 byte 158 | Vector send_buffer_vec = little_endian_to_vbytes(_client_capabilities, 4); 159 | 160 | // int<4> max packet size 161 | // temp_vec = little_endian_bytes((uint32_t)0x40000000, 4); 162 | // send_buffer_vec.insert(send_buffer_vec.end(), temp_vec.begin(), temp_vec.end()); 163 | send_buffer_vec.append_array(little_endian_to_vbytes((uint32_t)0x40000000, 4)); 164 | 165 | // int<1> client character collation 166 | send_buffer_vec.push_back(33); //utf8_general_ci 167 | 168 | // string<19> reserved 169 | // send_buffer_vec.insert(send_buffer_vec.end(), 19, 0); 170 | Vector temp_vec; 171 | temp_vec.resize_zeroed(19); 172 | send_buffer_vec.append_array(temp_vec); 173 | 174 | if (!(_server_capabilities & (uint64_t)Capabilities::CLIENT_MYSQL) && _srvr_major_ver >= 10 && 175 | _srvr_minor_ver >= 2) { 176 | // TODO implement Extended capabilities, if needed, this will result in more data between 177 | // _client_capabilities |= (_server_capabilities & (uint64_t)Capabilities::MARIADB_CLIENT_PROGRESS); 178 | // _client_capabilities |= (_server_capabilities & (uint64_t)Capabilities::MARIADB_CLIENT_COM_MULTI); 179 | // _client_capabilities |= (_server_capabilities & (uint64_t)Capabilities::MARIADB_CLIENT_STMT_BULK_OPERATIONS); 180 | // _client_capabilities |= (_server_capabilities & (uint64_t)Capabilities::MARIADB_CLIENT_EXTENDED_TYPE_INFO); 181 | 182 | // we need the metadata in the stream so we can form the dictionary ?? 183 | _client_capabilities |= (_server_capabilities & (uint64_t)Capabilities::MARIADB_CLIENT_CACHE_METADATA); 184 | // int<4> extended client capabilities 185 | temp_vec = little_endian_to_vbytes(_client_capabilities, 4, 4); 186 | send_buffer_vec.append_array(temp_vec); 187 | } else { 188 | // string<4> reserved 189 | temp_vec.resize_zeroed(4); 190 | send_buffer_vec.append_array(temp_vec); 191 | } 192 | 193 | // string username 194 | //send_buffer_vec.insert(send_buffer_vec.end(), _username.begin(), _username.end()); 195 | send_buffer_vec.append_array(_username); 196 | send_buffer_vec.push_back(0); //NUL terminated 197 | 198 | Vector auth_response; 199 | if (p_srvr_auth_type == AUTH_TYPE_MYSQL_NATIVE && (_client_auth_type == AUTH_TYPE_MYSQL_NATIVE)) 200 | auth_response = get_mysql_native_password_hash(_password_hashed, p_srvr_salt); 201 | 202 | // if (server_capabilities & PLUGIN_AUTH_LENENC_CLIENT_DATA) 203 | // string authentication data 204 | // else if (server_capabilities & SECURE_CONNECTION) //mysql uses secure connection flag for transactions 205 | if (!(_server_capabilities & (uint64_t)Capabilities::CLIENT_MYSQL) && 206 | (_server_capabilities & (uint64_t)Capabilities::SECURE_CONNECTION)) { 207 | //int<1> length of authentication response 208 | send_buffer_vec.push_back((uint8_t)auth_response.size()); 209 | //string authentication response 210 | send_buffer_vec.append_array(auth_response); 211 | } else { 212 | //else string authentication response null ended 213 | send_buffer_vec.append_array(auth_response); 214 | send_buffer_vec.push_back(0); //NUL terminated 215 | } 216 | 217 | // if (server_capabilities & CLIENT_CONNECT_WITH_DB) 218 | // string default database name 219 | if (_client_capabilities & (uint64_t)Capabilities::CONNECT_WITH_DB) { 220 | send_buffer_vec.append_array(_dbname); 221 | send_buffer_vec.push_back(0); //NUL terminated 222 | } 223 | 224 | //if (server_capabilities & CLIENT_PLUGIN_AUTH) 225 | //string authentication plugin name 226 | Vector auth_plugin_name = kAuthTypeNames[(size_t)AUTH_TYPE_MYSQL_NATIVE].to_ascii_buffer(); 227 | send_buffer_vec.append_array(auth_plugin_name); 228 | send_buffer_vec.push_back(0); //NUL terminated 229 | 230 | // Implementing CLIENT_SEND_CONNECT_ATTRS will just add more data, I don't think it is needed for game dev use 231 | // if (server_capabilities & CLIENT_SEND_CONNECT_ATTRS) 232 | //int size of connection attributes 233 | //while packet has remaining data 234 | //string key 235 | //string value 236 | 237 | m_add_packet_header(send_buffer_vec, ++seq_num); 238 | _stream.put_data(send_buffer_vec.ptr(), send_buffer_vec.size()); 239 | 240 | srvr_response = m_recv_data(1000); 241 | size_t itr = 4; 242 | 243 | if (srvr_response.size() > 0) { 244 | //4th byte is seq should be 2 245 | seq_num = srvr_response[3]; 246 | //5th byte is status 247 | uint8_t status = srvr_response[itr]; 248 | if (status == 0x00) { 249 | _authenticated = true; 250 | return Error::OK; 251 | } else if (status == 0xFE) { 252 | user_auth_type = m_get_server_auth_type(m_find_vbytes_str_at(srvr_response, itr)); 253 | } else if (status == 0xFF) { 254 | m_handle_server_error(srvr_response, itr); 255 | _authenticated = false; 256 | return Error::ERR_UNAUTHORIZED; 257 | } else { 258 | ERR_FAIL_V_EDMSG(Error::ERR_BUG, "Unhandled response code:" + String::num_uint64(srvr_response[itr], 16, true)); 259 | } 260 | } 261 | 262 | if (user_auth_type == AUTH_TYPE_ED25519 && _client_auth_type == AUTH_TYPE_ED25519) { 263 | //srvr_auth_msg.assign(srvr_response.begin() + itr + 1, srvr_response.end()); 264 | srvr_auth_msg.append_array(srvr_response.slice(itr + 1)); 265 | auth_response = get_client_ed25519_signature(_password_hashed, srvr_auth_msg); 266 | send_buffer_vec = auth_response; 267 | } else { 268 | return Error::ERR_INVALID_PARAMETER; 269 | } 270 | 271 | m_add_packet_header(send_buffer_vec, ++seq_num); 272 | 273 | Error err = _stream.put_data(send_buffer_vec.ptr(), send_buffer_vec.size()); 274 | ERR_FAIL_COND_V_MSG(err != Error::OK, err, "Failed to put data!"); 275 | 276 | srvr_response = m_recv_data(1000); 277 | 278 | if (srvr_response.size() > 0) { 279 | //4th byte is seq should be 2 280 | seq_num = srvr_response[3]; 281 | //5th byte is status 282 | itr = 4; 283 | if (srvr_response[itr] == 0x00) { 284 | _authenticated = true; 285 | } else if (srvr_response[itr] == 0xFF) { 286 | m_handle_server_error(srvr_response, itr); 287 | _authenticated = false; 288 | return Error::ERR_UNAUTHORIZED; 289 | } else { 290 | ERR_FAIL_V_MSG(Error::ERR_BUG, "Unhandled response code:" + String::num_uint64(srvr_response[itr], 16, true)); 291 | } 292 | } 293 | 294 | return Error::OK; 295 | } 296 | 297 | Error MariaDB::m_connect() { 298 | disconnect_db(); 299 | 300 | Error err; 301 | if (_ip.is_valid() && _port > 0) { 302 | err = _stream.connect_to_host(_ip, _port); 303 | } else { 304 | err = Error::ERR_INVALID_PARAMETER; 305 | } 306 | 307 | ERR_FAIL_COND_V_MSG(err != Error::OK, err, "Cannot connect to host with IP: " + String(_ip) + " and port: " + itos(_port)); 308 | 309 | for (size_t i = 0; i < 1000; i++) { 310 | _stream.poll(); 311 | if (_stream.get_status() == StreamPeerTCP::STATUS_CONNECTED) { 312 | break; 313 | } else { 314 | OS::get_singleton()->delay_usec(1000); 315 | } 316 | } 317 | 318 | ERR_FAIL_COND_V_MSG(_stream.get_status() != StreamPeerTCP::STATUS_CONNECTED, Error::ERR_CONNECTION_ERROR, 319 | "Cannot connect to host with IP: " + String(_ip) + " and port: " + itos(_port)); 320 | 321 | // if (_stream.get_status() != StreamPeerTCP::STATUS_CONNECTED) { 322 | // ERR_FAIL_V_MSG(Error::ERR_CONNECTION_ERROR, "Can't connect to DB server!"); 323 | // } 324 | 325 | Vector recv_buffer = m_recv_data(250); 326 | //std::cout << "recv_bfr:" << recv_buffer.size() << std::endl; 327 | if (recv_buffer.size() <= 4) { 328 | ERR_FAIL_V_MSG(Error::ERR_UNAVAILABLE, "connect: Recv buffer empty!"); 329 | } 330 | 331 | // per https://mariadb.com/kb/en/connection/ 332 | // The first packet from the server on a connection is a greeting giving/suggesting the requirements to login 333 | 334 | /* Per https://mariadb.com/kb/en/0-packet/ 335 | * On all packet stages between packet segment the standard packet is sent 336 | * int<3> rcvd_bfr[0] to rcvd_bfr[2] First 3 bytes are packet length 337 | * int<1> rcvd_bfr[3] 4th byte is sequence number 338 | * byte rcvd_bfr[4] to rcvd_bfr[4 + n] remaining bytes are the packet body n = packet length 339 | */ 340 | 341 | uint32_t packet_length = (uint32_t)recv_buffer[0] + ((uint32_t)recv_buffer[1] << 8) + 342 | ((uint32_t)recv_buffer[2] << 16); 343 | // On initial connect the packet length should be 4 byte less than buffer length 344 | if (packet_length != ((uint32_t)recv_buffer.size() - 4)) { 345 | ERR_FAIL_V_MSG(Error::FAILED, "Recv bfr does not match expected size!"); 346 | } 347 | 348 | // 4th byte is sequence number, increment this when replying with login request, if client starts then start at 0 349 | if (recv_buffer[3] != 0) { 350 | ERR_FAIL_V_MSG(Error::FAILED, "Packet sequence error!"); 351 | } 352 | 353 | // From the 5th byte on is the packet body 354 | 355 | /* 5th byte is protocol version, currently only 10 for MariaDB and MySQL v3.21.0+, 356 | * protocol version 9 for older MySQL versions. 357 | */ 358 | if (recv_buffer[4] == 10) { 359 | m_server_init_handshake_v10(recv_buffer); 360 | } else { 361 | ERR_FAIL_V_MSG(Error::FAILED, "Protocol version incompatible!"); 362 | } 363 | 364 | // _tcp_thread.start(m_tcp_thread_func, this); 365 | 366 | return Error::OK; 367 | } //m_connect 368 | 369 | // void MariaDB::m_tcp_thread_func(void *_instance) { 370 | // MariaDB *inst = (MariaDB *)_instance; 371 | 372 | // int byte_cnt = 0; 373 | // Vector rcv_bfr; 374 | // Vector transfer_bfr; 375 | 376 | // while (inst->_running) { 377 | // while (inst->_tcp_polling) { 378 | // if (! inst->is_connected_db()) 379 | // continue; 380 | // byte_cnt = inst->_stream.get_available_bytes(); 381 | // if (byte_cnt > 0) { 382 | // rcv_bfr.resize(byte_cnt); 383 | // inst->_stream.get_data(rcv_bfr.ptrw(), byte_cnt); 384 | // transfer_bfr.append_array(rcv_bfr); 385 | // } 386 | 387 | // if (transfer_bfr.size() > 0) { 388 | // inst->_tcp_mutex.lock(); 389 | // inst->_tcp_thread_data.append_array(transfer_bfr); 390 | // transfer_bfr.clear(); 391 | // inst->_tcp_mutex.unlock(); 392 | // } 393 | // } 394 | // OS::get_singleton()->delay_usec(1000); 395 | // } 396 | // } 397 | 398 | Variant MariaDB::m_get_type_data(const int p_db_field_type, const PackedByteArray p_data) { 399 | String rtn_val; 400 | rtn_val.parse_utf8((const char *)p_data.ptr(), p_data.size()); 401 | switch (p_db_field_type) { 402 | case 1: // MYSQL_TYPE_TINY 403 | case 2: // MYSQL_TYPE_SHORT 404 | case 3: // MYSQL_TYPE_LONG 405 | case 8: // MYSQL_TYPE_LONGLONG 406 | case 9: // MYSQL_TYPE_INT24 aka MEDIUM INT 407 | case 13: // MYSQL_TYPE_YEAR 408 | return rtn_val.to_int(); 409 | break; 410 | case 0: // MYSQL_TYPE_DECIMAL 411 | case 4: // MYSQL_TYPE_FLOAT 412 | return rtn_val.to_float(); 413 | break; 414 | case 5: // MYSQL_TYPE_DOUBLE 415 | if (_dbl_to_string) { 416 | return rtn_val; 417 | } else { 418 | return rtn_val.to_float(); 419 | } 420 | break; 421 | default: 422 | 423 | return rtn_val; 424 | } 425 | return 0; 426 | } 427 | 428 | MariaDB::AuthType MariaDB::m_get_server_auth_type(String p_srvr_auth_name) { 429 | AuthType server_auth_type = AUTH_TYPE_ED25519; 430 | if (p_srvr_auth_name == "mysql_native_password") { 431 | server_auth_type = AUTH_TYPE_MYSQL_NATIVE; 432 | } else if (p_srvr_auth_name == "client_ed25519") { 433 | server_auth_type = AUTH_TYPE_ED25519; 434 | } 435 | //TODO(sigrudds1) Add cached_sha2 for mysql 436 | return server_auth_type; 437 | } 438 | 439 | Vector MariaDB::m_recv_data() { 440 | int byte_cnt = _stream.get_available_bytes(); 441 | Vector recv_buffer; 442 | if (byte_cnt > 0) { 443 | recv_buffer.resize(byte_cnt); 444 | _stream.get_data(recv_buffer.ptrw(), byte_cnt); 445 | } 446 | 447 | return recv_buffer; 448 | } 449 | 450 | Vector MariaDB::m_recv_data(uint32_t p_timeout) { 451 | int byte_cnt = 0; 452 | // int rcvd_bytes = 0; 453 | Vector recv_buffer, out_buffer; 454 | uint64_t start_msec = OS::get_singleton()->get_ticks_msec(); 455 | uint64_t time_lapse = 0; 456 | bool data_rcvd = false; 457 | 458 | while (is_connected_db() && time_lapse < p_timeout) { 459 | byte_cnt = _stream.get_available_bytes(); 460 | if (byte_cnt > 0) { 461 | recv_buffer.resize(byte_cnt); 462 | _stream.get_data(recv_buffer.ptrw(), byte_cnt); 463 | data_rcvd = true; 464 | out_buffer.append_array(recv_buffer); 465 | start_msec = OS::get_singleton()->get_ticks_msec(); 466 | } else if (data_rcvd) { 467 | break; 468 | } 469 | time_lapse = OS::get_singleton()->get_ticks_msec() - start_msec; 470 | } 471 | 472 | // if (out_buffer.size() > 0) 473 | // print_line("m_recv_data time_lapse:", time_lapse, " data:", out_buffer.size()); 474 | 475 | return out_buffer; 476 | } 477 | 478 | void MariaDB::m_handle_server_error(const Vector p_src_buffer, size_t &p_last_pos) { 479 | //REF https://mariadb.com/kb/en/err_packet/ 480 | uint16_t srvr_error_code = (uint16_t)p_src_buffer[++p_last_pos]; 481 | srvr_error_code += (uint16_t)p_src_buffer[++p_last_pos] << 8; 482 | String msg = String::num_uint64((uint64_t)srvr_error_code) + " - "; 483 | if (srvr_error_code == 0xFFFF) { 484 | //int<1> stage 485 | //int<1> max_stage 486 | //int<3> progress 487 | //string progress_info 488 | } else { 489 | if (p_src_buffer[p_last_pos + 1] == '#') { 490 | msg += "SQL State:"; 491 | for (size_t itr = 0; itr < 6; ++itr) 492 | msg += (char)p_src_buffer[++p_last_pos]; 493 | msg += " - "; 494 | while (p_last_pos < (size_t)p_src_buffer.size() - 1) { 495 | msg += (char)p_src_buffer[++p_last_pos]; 496 | } 497 | } else { 498 | //string human - readable error message 499 | while (p_last_pos < (size_t)p_src_buffer.size() - 1) { 500 | msg += (char)p_src_buffer[++p_last_pos]; 501 | } 502 | } 503 | } 504 | ERR_FAIL_COND_EDMSG(srvr_error_code != OK, msg); 505 | } 506 | 507 | String MariaDB::m_find_vbytes_str(Vector p_buf) { 508 | size_t start_pos = 0; 509 | return m_find_vbytes_str_at(p_buf, start_pos); 510 | } 511 | 512 | String MariaDB::m_find_vbytes_str_at(Vector p_buf, size_t &p_start_pos) { 513 | Vector vc; 514 | while (p_buf[++p_start_pos] != 0 && p_start_pos < (size_t)p_buf.size()) { 515 | vc.push_back(p_buf[p_start_pos]); 516 | } 517 | vc.push_back(0); //for proper char * string convertion 518 | return (String)vc.ptr(); 519 | } 520 | 521 | PackedByteArray MariaDB::m_get_pkt_bytes(const Vector &p_src_buf, size_t &p_start_pos, 522 | const size_t p_byte_cnt){ 523 | 524 | PackedByteArray rtn; 525 | if (p_byte_cnt <= 0 || p_start_pos + p_byte_cnt > (size_t)p_src_buf.size()) { 526 | return rtn; 527 | } 528 | rtn = p_src_buf.slice(p_start_pos, p_start_pos + p_byte_cnt); 529 | p_start_pos += p_byte_cnt - 1; 530 | return rtn; 531 | } 532 | 533 | size_t MariaDB::m_get_pkt_len_at(const Vector p_src_buf, size_t &p_start_pos) { 534 | size_t len = (size_t)p_src_buf[p_start_pos]; 535 | len += (size_t)p_src_buf[++p_start_pos] << 8; 536 | len += (size_t)p_src_buf[++p_start_pos] << 16; 537 | return len; 538 | } 539 | 540 | Error MariaDB::m_server_init_handshake_v10(const Vector &p_src_buffer) { 541 | Vector v_chr_temp; 542 | 543 | //nul string - read the 5th byte until the first nul(00), this is server version string, it is nul terminated 544 | size_t pkt_itr = 3; 545 | _server_ver_str = ""; 546 | while (p_src_buffer[++pkt_itr] != 0 && pkt_itr < (size_t)p_src_buffer.size()) { 547 | _server_ver_str += (char)p_src_buffer[pkt_itr]; 548 | } 549 | 550 | _server_ver_str = _server_ver_str.strip_escapes(); 551 | 552 | if (_server_ver_str.begins_with("5.5.5-")) { 553 | PackedStringArray split_ver_str = _server_ver_str.split("-"); 554 | PackedStringArray split_ver_str_seg = split_ver_str[1].split("."); 555 | 556 | _srvr_major_ver = split_ver_str_seg[0].to_int(); 557 | _srvr_minor_ver = split_ver_str_seg[1].to_int(); 558 | } 559 | 560 | //4bytes - doesn't appear to be needed. 561 | pkt_itr += 4; 562 | 563 | //salt part 1 - 8 bytes 564 | Vector server_salt; 565 | for (size_t j = 0; j < 8; j++) 566 | server_salt.push_back(p_src_buffer[++pkt_itr]); 567 | 568 | //reserved byte 569 | pkt_itr++; 570 | 571 | _server_capabilities = 0; 572 | //2bytes -server capabilities part 1 573 | _server_capabilities = (uint64_t)p_src_buffer[++pkt_itr]; 574 | _server_capabilities += ((uint64_t)p_src_buffer[++pkt_itr]) << 8; 575 | 576 | //1byte - server default collation code 577 | ++pkt_itr; 578 | 579 | //2bytes - Status flags 580 | //uint16_t status = 0; 581 | //status = (uint16_t)p_src_buffer[++pkt_itr]; 582 | //status += ((uint16_t)p_src_buffer[++pkt_itr]) << 8; 583 | pkt_itr += 2; 584 | 585 | //2bytes - server capabilities part 2 586 | _server_capabilities += ((uint64_t)p_src_buffer[++pkt_itr]) << 16; 587 | _server_capabilities += ((uint64_t)p_src_buffer[++pkt_itr]) << 24; 588 | 589 | if (!(_server_capabilities & (uint64_t)Capabilities::CLIENT_PROTOCOL_41)) { 590 | ERR_FAIL_V_MSG(Error::FAILED, "Incompatible authorization protocol!"); 591 | } 592 | //TODO(sigrudds1) Make auth plugin not required if using ssl/tls 593 | if (!(_server_capabilities & (uint64_t)Capabilities::PLUGIN_AUTH)) { 594 | ERR_FAIL_V_MSG(Error::FAILED, "Authorization protocol not set!"); 595 | } 596 | 597 | //1byte - salt length 0 for none 598 | uint8_t server_salt_length = p_src_buffer[++pkt_itr]; 599 | 600 | //6bytes - filler 601 | pkt_itr += 6; 602 | 603 | // 4bytes - filler or server capabilities part 3 (mariadb v10.2 or later) "MariaDB extended capablities" 604 | if (!(_server_capabilities & (uint64_t)Capabilities::CLIENT_MYSQL) && 605 | _srvr_major_ver >= 10 && _srvr_minor_ver >= 2) { 606 | _server_capabilities += ((uint64_t)p_src_buffer[++pkt_itr]) << 32; 607 | _server_capabilities += ((uint64_t)p_src_buffer[++pkt_itr]) << 40; 608 | _server_capabilities += ((uint64_t)p_src_buffer[++pkt_itr]) << 48; 609 | _server_capabilities += ((uint64_t)p_src_buffer[++pkt_itr]) << 56; 610 | } else { 611 | pkt_itr += 4; 612 | } 613 | 614 | //12bytes - salt part 2 615 | for (size_t j = 0; j < (size_t)std::max(13, server_salt_length - 8); j++) 616 | server_salt.push_back(p_src_buffer[++pkt_itr]); 617 | 618 | //1byte - reserved 619 | //nul string - auth plugin name, length = auth plugin string length 620 | 621 | v_chr_temp.clear(); 622 | while (p_src_buffer[++pkt_itr] != 0 && pkt_itr < (size_t)p_src_buffer.size()) { 623 | v_chr_temp.push_back(p_src_buffer[pkt_itr]); 624 | } 625 | v_chr_temp.push_back(0); //for proper char * string convertion 626 | 627 | //determine which auth method the server can use 628 | AuthType p_srvr_auth_type = m_get_server_auth_type((String)v_chr_temp.ptr()); 629 | 630 | return m_client_protocol_v41(p_srvr_auth_type, server_salt); 631 | } //server_init_handshake_v10 632 | 633 | void MariaDB::m_update_password(String p_password) { 634 | if (_is_pre_hashed) 635 | return; 636 | 637 | //take the password and store it as the hash, only the hash is needed 638 | if (_client_auth_type == AUTH_TYPE_MYSQL_NATIVE) { 639 | _password_hashed = p_password.sha1_buffer(); 640 | } else if (_client_auth_type == AUTH_TYPE_ED25519) { 641 | _password_hashed.resize(64); 642 | void *ctx = memalloc(sizeof(mbedtls_sha512_context)); 643 | mbedtls_sha512_init((mbedtls_sha512_context *)ctx); 644 | mbedtls_sha512_starts_ret((mbedtls_sha512_context *)ctx, 0); 645 | mbedtls_sha512_update_ret((mbedtls_sha512_context *)ctx, (uint8_t *)p_password.ascii().ptr(), 646 | p_password.length()); 647 | mbedtls_sha512_finish_ret((mbedtls_sha512_context *)ctx, _password_hashed.ptrw()); 648 | mbedtls_sha512_free((mbedtls_sha512_context *)ctx); 649 | memfree((mbedtls_sha512_context *)ctx); 650 | } 651 | 652 | //TODO(sigrudds1) mysql caching_sha2_password 653 | } 654 | 655 | void MariaDB::m_update_username(String p_username) { 656 | _username = p_username.to_ascii_buffer(); 657 | } 658 | 659 | //public 660 | Error MariaDB::connect_db(String p_host, int p_port, String p_dbname, String p_username, String p_hashed_password, 661 | AuthType p_authtype, bool p_is_prehashed) { 662 | IPAddress ip; 663 | 664 | if (p_host.is_valid_ip_address()) { 665 | _ip = p_host; 666 | } else { 667 | _ip = IP::get_singleton()->resolve_hostname(p_host, (IP::Type)_ip_type); 668 | } 669 | _port = p_port; 670 | // _tcp_polling = false; 671 | // _running = true; 672 | 673 | _client_auth_type = p_authtype; 674 | _is_pre_hashed = p_is_prehashed; 675 | 676 | if (p_username.size() <= 0) { 677 | ERR_PRINT("username not set"); 678 | return Error::ERR_INVALID_PARAMETER; 679 | } 680 | 681 | if (p_hashed_password.size() <= 0) { 682 | ERR_PRINT("password not set"); 683 | return Error::ERR_INVALID_PARAMETER; 684 | } 685 | 686 | if (p_dbname.length() <= 0 && _client_capabilities & (uint64_t)Capabilities::CONNECT_WITH_DB) { 687 | ERR_PRINT("dbname not set"); 688 | return Error::ERR_INVALID_PARAMETER; 689 | } else { 690 | set_db_name(p_dbname); 691 | } 692 | 693 | m_update_username(p_username); 694 | 695 | if (p_is_prehashed) { 696 | _password_hashed = hex_str_to_v_bytes(p_hashed_password); 697 | } else { 698 | m_update_password(p_hashed_password); 699 | } 700 | 701 | return m_connect(); 702 | } 703 | 704 | void MariaDB::disconnect_db() { 705 | // _tcp_polling = false; 706 | if (is_connected_db()) { 707 | //say goodbye too the server 708 | uint8_t output[5] = { 0x01, 0x00, 0x00, 0x00, 0x01 }; 709 | _stream.put_data(output, 5); 710 | _stream.disconnect_from_host(); 711 | } 712 | _authenticated = false; 713 | } 714 | 715 | String MariaDB::get_last_query() { 716 | return _last_query; 717 | } 718 | 719 | PackedByteArray MariaDB::get_last_query_converted() { 720 | return _last_query_converted; 721 | } 722 | 723 | PackedByteArray MariaDB::get_last_response() { 724 | return _last_response; 725 | } 726 | 727 | PackedByteArray MariaDB::get_last_transmitted() { 728 | return _last_transmitted; 729 | } 730 | 731 | bool MariaDB::is_connected_db() { 732 | _stream.poll(); 733 | return _stream.get_status() == StreamPeerTCP::STATUS_CONNECTED; 734 | } 735 | 736 | Variant MariaDB::query(String sql_stmt) { 737 | if (!is_connected_db()) 738 | return (uint32_t)ERR_NOT_CONNECTED; 739 | if (!_authenticated) 740 | return (uint32_t)ERR_AUTH_FAILED; 741 | 742 | // _tcp_polling = true; 743 | 744 | _last_query = sql_stmt; 745 | Vector send_buffer_vec; 746 | int bfr_size = 0; 747 | 748 | /* For interest of speed over memory I am working with the entire buffer 749 | * and keeping track of the iteration point, as most queries for 750 | * game dev should be small but speedy. 751 | */ 752 | 753 | size_t pkt_itr = 0; 754 | size_t pkt_len; //techinically section length everything arrives in one stream packet 755 | size_t len_encode = 0; 756 | bool done = false; 757 | // From MariaDB version 10.2 dep_eof should be true 758 | bool dep_eof = (_client_capabilities & (uint64_t)Capabilities::CLIENT_DEPRECATE_EOF); 759 | 760 | Vector col_data; 761 | 762 | send_buffer_vec.push_back(0x03); 763 | _last_query_converted = sql_stmt.to_utf8_buffer(); 764 | 765 | send_buffer_vec.append_array(_last_query_converted); 766 | m_add_packet_header(send_buffer_vec, 0); 767 | 768 | _last_transmitted = send_buffer_vec; 769 | // _tcp_mutex.lock(); 770 | _stream.put_data(send_buffer_vec.ptr(), send_buffer_vec.size()); 771 | // _tcp_mutex.unlock(); 772 | 773 | Vector srvr_response = m_recv_data(1000); 774 | // m_append_thread_data(srvr_response); 775 | bfr_size = srvr_response.size(); 776 | 777 | // srvr_response = m_recv_data(1000); 778 | if (bfr_size == 0) { 779 | return (uint32_t)ERR_NO_RESPONSE; 780 | } 781 | 782 | pkt_len = m_get_pkt_len_at(srvr_response, pkt_itr); 783 | 784 | // uint8_t seq_num = srvr_response[++pkt_itr]; 785 | ++pkt_itr; 786 | 787 | /* https://mariadb.com/kb/en/result-set-packets/ 788 | * The pkt_itr should be at 3, we are on teh 4th byte and wlll iterate before use 789 | * Resultset metadata 790 | * All segment packets start with packet length(3 bytes) and sequence number 791 | * This is a small packet with packet length of 1 to 9 of 4 to 19 bytes 792 | * to determine how many columns of data are being sent. 793 | */ 794 | 795 | uint64_t col_cnt = 0; 796 | uint8_t test = srvr_response[++pkt_itr]; 797 | // https://mariadb.com/kb/en/protocol-data-types/#length-encoded-integers 798 | if (test == 0xFF) { 799 | int err = srvr_response[pkt_itr + 1] + (srvr_response[pkt_itr + 2] << 8); 800 | m_handle_server_error(srvr_response, pkt_itr); 801 | return err; 802 | } else if (test == 0xFE) { 803 | col_cnt = bytes_to_num_itr_pos(srvr_response.ptr(), 8, pkt_itr); 804 | } else if (test == 0xFD) { 805 | col_cnt = bytes_to_num_itr_pos(srvr_response.ptr(), 3, pkt_itr); 806 | } else if (test == 0xFC) { 807 | col_cnt = bytes_to_num_itr_pos(srvr_response.ptr(), 2, pkt_itr); 808 | } else if (test == 0xFB) { 809 | // null value 810 | // TODO needs investigation, not sure why this would happen 811 | } else if (test == 0x00) { 812 | return 0; 813 | } else { 814 | col_cnt = srvr_response[pkt_itr]; 815 | } 816 | if (_client_capabilities & (uint64_t)Capabilities::MARIADB_CLIENT_CACHE_METADATA) { 817 | // print_line("send metadata:", srvr_response[++pkt_itr] == true); 818 | ++pkt_itr; 819 | } 820 | // for each column (i.e column_count times) 821 | for (size_t itr = 0; itr < col_cnt; ++itr) { 822 | ERR_FAIL_COND_V_EDMSG(m_chk_rcv_bfr(srvr_response, bfr_size, pkt_itr, 24) != OK, ERR_PACKET_LENGTH_MISMATCH, 823 | vformat("ERR_PACKET_LENGTH_MISMATCH rcvd %d expect %d", bfr_size, pkt_itr + 24)); 824 | 825 | pkt_len = m_get_pkt_len_at(srvr_response, ++pkt_itr); 826 | 827 | // seq_num = srvr_response[++pkt_itr]; 828 | ++pkt_itr; 829 | 830 | // Column Definition packet 831 | // https://mariadb.com/kb/en/result-set-packets/#column-definition-packet 832 | 833 | // string catalog (always 'def') 834 | len_encode = srvr_response[++pkt_itr]; 835 | vbytes_to_utf8_itr_at(srvr_response, pkt_itr, len_encode); 836 | 837 | // string schema (database name) 838 | len_encode = srvr_response[++pkt_itr]; 839 | ERR_FAIL_COND_V_EDMSG(m_chk_rcv_bfr(srvr_response, bfr_size, pkt_itr, len_encode) != OK, ERR_PACKET_LENGTH_MISMATCH, 840 | vformat("ERR_PACKET_LENGTH_MISMATCH rcvd %d expect %d", bfr_size, pkt_itr + len_encode)); 841 | vbytes_to_utf8_itr_at(srvr_response, pkt_itr, len_encode); 842 | 843 | // string table alias 844 | len_encode = srvr_response[++pkt_itr]; 845 | ERR_FAIL_COND_V_EDMSG(m_chk_rcv_bfr(srvr_response, bfr_size, pkt_itr, len_encode) != OK, ERR_PACKET_LENGTH_MISMATCH, 846 | vformat("ERR_PACKET_LENGTH_MISMATCH rcvd %d expect %d", bfr_size, pkt_itr + len_encode)); 847 | vbytes_to_utf8_itr_at(srvr_response, pkt_itr, len_encode); 848 | 849 | // string table 850 | len_encode = srvr_response[++pkt_itr]; 851 | ERR_FAIL_COND_V_EDMSG(m_chk_rcv_bfr(srvr_response, bfr_size, pkt_itr, len_encode) != OK, ERR_PACKET_LENGTH_MISMATCH, 852 | vformat("ERR_PACKET_LENGTH_MISMATCH rcvd %d expect %d", bfr_size, pkt_itr + len_encode)); 853 | vbytes_to_utf8_itr_at(srvr_response, pkt_itr, len_encode); 854 | 855 | // string column alias 856 | len_encode = srvr_response[++pkt_itr]; 857 | ERR_FAIL_COND_V_EDMSG(m_chk_rcv_bfr(srvr_response, bfr_size, pkt_itr, len_encode) != OK, ERR_PACKET_LENGTH_MISMATCH, 858 | vformat("ERR_PACKET_LENGTH_MISMATCH rcvd %d expect %d", bfr_size, pkt_itr + len_encode)); 859 | String column_name = vbytes_to_utf8_itr_at(srvr_response, pkt_itr, len_encode); 860 | 861 | // string column 862 | len_encode = srvr_response[++pkt_itr]; 863 | ERR_FAIL_COND_V_EDMSG(m_chk_rcv_bfr(srvr_response, bfr_size, pkt_itr, len_encode) != OK, ERR_PACKET_LENGTH_MISMATCH, 864 | vformat("ERR_PACKET_LENGTH_MISMATCH rcvd %d expect %d", bfr_size, pkt_itr + len_encode)); 865 | vbytes_to_utf8_itr_at(srvr_response, pkt_itr, len_encode); 866 | 867 | // TODO(sigrudds1) Handle "MariaDB extended capablities" (several locations) 868 | // if extended type supported (see MARIADB_CLIENT_EXTENDED_TYPE_INFO ) 869 | // int length extended info 870 | // loop 871 | // int<1> data type: 0x00:type, 0x01: format 872 | // string value 873 | 874 | // int length of fixed fields (=0xC) 875 | uint8_t remaining = srvr_response[++pkt_itr]; 876 | ERR_FAIL_COND_V_EDMSG(m_chk_rcv_bfr(srvr_response, bfr_size, pkt_itr, remaining) != OK, ERR_PACKET_LENGTH_MISMATCH, 877 | vformat("ERR_PACKET_LENGTH_MISMATCH rcvd %d expect %d", bfr_size, pkt_itr + remaining)); 878 | // ++pkt_itr; //remaining bytes in packet section 879 | 880 | // int<2> character set number 881 | uint16_t char_set = bytes_to_num_itr_pos(srvr_response.ptr(), 2, pkt_itr); 882 | // print_line("char set id:", char_set); 883 | 884 | // int<4> max. column size the number in parenthesis eg int(10), varchar(255) 885 | // uint32_t col_size = bytes_to_num_itr(srvr_response.data(), 4, pkt_itr); 886 | pkt_itr += 4; 887 | 888 | // int<1> Field types 889 | // https://mariadb.com/kb/en/result-set-packets/#field-types 890 | uint8_t field_type = srvr_response[++pkt_itr]; 891 | 892 | // int<2> Field detail flag 893 | // https://mariadb.com/kb/en/result-set-packets/#field-details-flag 894 | pkt_itr += 2; 895 | 896 | // int<1> decimals 897 | pkt_itr += 1; 898 | // int<2> - unused - 899 | pkt_itr += 2; 900 | 901 | col_data.push_back({ column_name, char_set, field_type }); 902 | } 903 | 904 | // if not (CLIENT_DEPRECATE_EOF capability set) get EOF_Packet 905 | if (!dep_eof) { 906 | pkt_itr += 5; //bypass for now 907 | } 908 | 909 | Array arr; 910 | 911 | //process values 912 | while (!done && pkt_itr < (size_t)srvr_response.size()) { 913 | // Last packet is always 11 byte, pkt len code= 3 bytes, seq= 1 byte, pkt data = 7 bytes 914 | ERR_FAIL_COND_V_EDMSG(m_chk_rcv_bfr(srvr_response, bfr_size, pkt_itr, 11) != OK, ERR_PACKET_LENGTH_MISMATCH, 915 | vformat("ERR_PACKET_LENGTH_MISMATCH rcvd %d expect %d", bfr_size, pkt_itr + 11)); 916 | 917 | pkt_len = m_get_pkt_len_at(srvr_response, ++pkt_itr); 918 | ERR_FAIL_COND_V_EDMSG(m_chk_rcv_bfr(srvr_response, bfr_size, pkt_itr, pkt_len) != OK, ERR_PACKET_LENGTH_MISMATCH, 919 | vformat("ERR_PACKET_LENGTH_MISMATCH rcvd %d expect %d", bfr_size, pkt_itr + pkt_len)); 920 | 921 | // seq_num = srvr_response[++pkt_itr]; 922 | ++pkt_itr; 923 | test = srvr_response[pkt_itr + 1]; 924 | 925 | if (test == 0xFE && dep_eof && pkt_len < 0xFFFFFF) { 926 | done = true; 927 | break; 928 | } 929 | Dictionary dict; 930 | //https://mariadb.com/kb/en/protocol-data-types/#length-encoded-strings 931 | for (size_t itr = 0; itr < col_cnt; ++itr) { 932 | ERR_FAIL_COND_V_EDMSG(m_chk_rcv_bfr(srvr_response, bfr_size, pkt_itr, 2) != OK, ERR_PACKET_LENGTH_MISMATCH, vformat("ERR_PACKET_LENGTH_MISMATCH rcvd %d expect %d", bfr_size, pkt_itr + 2)); 933 | test = srvr_response[++pkt_itr]; 934 | if (test == 0xFF) { 935 | //ERR_Packet 936 | ERR_FAIL_COND_V_EDMSG(m_chk_rcv_bfr(srvr_response, bfr_size, pkt_itr, 2) != OK, ERR_PACKET_LENGTH_MISMATCH, vformat("ERR_PACKET_LENGTH_MISMATCH rcvd %d expect %d", bfr_size, pkt_itr + 2)); 937 | // Don't think these two if's are needed for column data 938 | // } else if ((test == 0x00 && !dep_eof /* && pkt_len < 0xFFFFFF */) || 939 | // (test == 0xFE && pkt_len < 0xFFFFFF && dep_eof)) { 940 | // //OK_Packet 941 | // done = true; 942 | // break; 943 | // } else if (test == 0xFE && pkt_len < 0xFFFFFF && !dep_eof) { 944 | // //EOF_Packet 945 | // done = true; 946 | // break; 947 | } else { 948 | if (test == 0xFE) { 949 | ERR_FAIL_COND_V_EDMSG(m_chk_rcv_bfr(srvr_response, bfr_size, pkt_itr, 8) != OK, ERR_PACKET_LENGTH_MISMATCH, vformat("ERR_PACKET_LENGTH_MISMATCH rcvd %d expect %d", bfr_size, pkt_itr + 8)); 950 | len_encode = bytes_to_num_itr_pos(srvr_response.ptr(), 8, pkt_itr); 951 | } else if (test == 0xFD) { 952 | ERR_FAIL_COND_V_EDMSG(m_chk_rcv_bfr(srvr_response, bfr_size, pkt_itr, 3) != OK, ERR_PACKET_LENGTH_MISMATCH, vformat("ERR_PACKET_LENGTH_MISMATCH rcvd %d expect %d", bfr_size, pkt_itr + 3)); 953 | len_encode = bytes_to_num_itr_pos(srvr_response.ptr(), 3, pkt_itr); 954 | } else if (test == 0xFC) { 955 | ERR_FAIL_COND_V_EDMSG(m_chk_rcv_bfr(srvr_response, bfr_size, pkt_itr, 2) != OK, ERR_PACKET_LENGTH_MISMATCH, vformat("ERR_PACKET_LENGTH_MISMATCH rcvd %d expect %d", bfr_size, pkt_itr + 2)); 956 | len_encode = bytes_to_num_itr_pos(srvr_response.ptr(), 2, pkt_itr); 957 | } else if (test == 0xFB) { 958 | //null value need to skip 959 | len_encode = 0; 960 | } else { 961 | len_encode = srvr_response[pkt_itr]; 962 | } 963 | 964 | ERR_FAIL_COND_V_EDMSG(m_chk_rcv_bfr(srvr_response, bfr_size, pkt_itr, len_encode) != OK, ERR_PACKET_LENGTH_MISMATCH, 965 | vformat("ERR_PACKET_LENGTH_MISMATCH rcvd %d expect %d", bfr_size, pkt_itr + len_encode)); 966 | if (len_encode > 0) { 967 | PackedByteArray data = m_get_pkt_bytes(srvr_response, ++pkt_itr, len_encode); 968 | dict[col_data[itr].name] = m_get_type_data(col_data[itr].field_type, data); 969 | } else { 970 | dict[col_data[itr].name] = Variant(); 971 | } 972 | } 973 | } 974 | 975 | if (!done) 976 | arr.push_back(dict); 977 | } 978 | // _tcp_polling = false; 979 | _last_response = PackedByteArray(srvr_response); 980 | 981 | return Variant(arr); 982 | } 983 | 984 | void MariaDB::set_dbl_to_string(bool p_is_to_str) { 985 | _dbl_to_string = p_is_to_str; 986 | } 987 | 988 | // TODO If db is not the same and connected then change db on server 989 | void MariaDB::set_db_name(String p_dbname) { 990 | _dbname = p_dbname.to_utf8_buffer(); 991 | // _dbname = p_dbname.to_ascii_buffer(); // TODO Add character set compatibility?? 992 | } 993 | 994 | void MariaDB::set_ip_type(IpType p_type) { 995 | _ip_type = p_type; 996 | } 997 | -------------------------------------------------------------------------------- /ed25519_ref10/ed25519_fe.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************/ 2 | /* ed25519_fe.cpp */ 3 | /*************************************************************************/ 4 | /* This file is part of the */ 5 | /* Maria and Mysql database connection module */ 6 | /* for use in the Godot Engine */ 7 | /* GODOT ENGINE */ 8 | /* https://godotengine.org */ 9 | /* This file was derived from information found at */ 10 | /* https://tools.ietf.org/html/rfc8032#page-44 */ 11 | /*************************************************************************/ 12 | /* Copyright (c) 2021 Shawn Shipton. https://vikingtinkerer.com */ 13 | /* */ 14 | /* Permission is hereby granted, free of charge, to any person obtaining */ 15 | /* a copy of this software and associated documentation files (the */ 16 | /* "Software"), to deal in the Software without restriction, including */ 17 | /* without limitation the rights to use, copy, modify, merge, publish, */ 18 | /* distribute, sublicense, and/or sell copies of the Software, and to */ 19 | /* permit persons to whom the Software is furnished to do so, subject to */ 20 | /* the following conditions: */ 21 | /* */ 22 | /* The above copyright notice and this permission notice shall be */ 23 | /* included in all copies or substantial portions of the Software. */ 24 | /* */ 25 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 26 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 27 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ 28 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 29 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 30 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 31 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 32 | /*************************************************************************/ 33 | 34 | #include "ed25519_fe.h" 35 | #include 36 | 37 | //#include 38 | //#include 39 | //#include 40 | 41 | static uint64_t bytes_to_u64(const uint8_t *src, size_t byte_count) { 42 | uint64_t result = 0; 43 | 44 | for (size_t i = 0; i < byte_count; ++i) 45 | result |= static_cast(src[i]) << (i * 8); 46 | return result; 47 | } 48 | 49 | void fe_0(fe h) { 50 | h[0] = 0; 51 | h[1] = 0; 52 | h[2] = 0; 53 | h[3] = 0; 54 | h[4] = 0; 55 | h[5] = 0; 56 | h[6] = 0; 57 | h[7] = 0; 58 | h[8] = 0; 59 | h[9] = 0; 60 | } 61 | 62 | /* 63 | h = 1 64 | */ 65 | 66 | void fe_1(fe h) { 67 | h[0] = 1; 68 | h[1] = 0; 69 | h[2] = 0; 70 | h[3] = 0; 71 | h[4] = 0; 72 | h[5] = 0; 73 | h[6] = 0; 74 | h[7] = 0; 75 | h[8] = 0; 76 | h[9] = 0; 77 | } 78 | 79 | /* 80 | h = f + g 81 | Can overlap h with f or g. 82 | 83 | Preconditions: 84 | |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. 85 | |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. 86 | 87 | Postconditions: 88 | |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. 89 | */ 90 | 91 | void fe_add(fe h, const fe f, const fe g) { 92 | for (size_t i = 0; i < 10; ++i) 93 | h[i] = f[i] + g[i]; 94 | } 95 | 96 | /* 97 | Replace (f,g) with (g,g) if b == 1; 98 | replace (f,g) with (f,g) if b == 0. 99 | 100 | Preconditions: b in {0,1}. 101 | */ 102 | 103 | void fe_cmov(fe f, const fe g, unsigned int b) { 104 | int32_t f0 = f[0]; 105 | int32_t f1 = f[1]; 106 | int32_t f2 = f[2]; 107 | int32_t f3 = f[3]; 108 | int32_t f4 = f[4]; 109 | int32_t f5 = f[5]; 110 | int32_t f6 = f[6]; 111 | int32_t f7 = f[7]; 112 | int32_t f8 = f[8]; 113 | int32_t f9 = f[9]; 114 | int32_t g0 = g[0]; 115 | int32_t g1 = g[1]; 116 | int32_t g2 = g[2]; 117 | int32_t g3 = g[3]; 118 | int32_t g4 = g[4]; 119 | int32_t g5 = g[5]; 120 | int32_t g6 = g[6]; 121 | int32_t g7 = g[7]; 122 | int32_t g8 = g[8]; 123 | int32_t g9 = g[9]; 124 | int32_t x0 = f0 ^ g0; 125 | int32_t x1 = f1 ^ g1; 126 | int32_t x2 = f2 ^ g2; 127 | int32_t x3 = f3 ^ g3; 128 | int32_t x4 = f4 ^ g4; 129 | int32_t x5 = f5 ^ g5; 130 | int32_t x6 = f6 ^ g6; 131 | int32_t x7 = f7 ^ g7; 132 | int32_t x8 = f8 ^ g8; 133 | int32_t x9 = f9 ^ g9; 134 | 135 | b = (unsigned int)(-(int)b); /* silence warning */ 136 | x0 &= b; 137 | x1 &= b; 138 | x2 &= b; 139 | x3 &= b; 140 | x4 &= b; 141 | x5 &= b; 142 | x6 &= b; 143 | x7 &= b; 144 | x8 &= b; 145 | x9 &= b; 146 | 147 | f[0] = f0 ^ x0; 148 | f[1] = f1 ^ x1; 149 | f[2] = f2 ^ x2; 150 | f[3] = f3 ^ x3; 151 | f[4] = f4 ^ x4; 152 | f[5] = f5 ^ x5; 153 | f[6] = f6 ^ x6; 154 | f[7] = f7 ^ x7; 155 | f[8] = f8 ^ x8; 156 | f[9] = f9 ^ x9; 157 | } 158 | 159 | /* 160 | Replace (f,g) with (g,f) if b == 1; 161 | replace (f,g) with (f,g) if b == 0. 162 | 163 | Preconditions: b in {0,1}. 164 | */ 165 | 166 | void fe_cswap(fe f, fe g, unsigned int b) { 167 | int32_t f0 = f[0]; 168 | int32_t f1 = f[1]; 169 | int32_t f2 = f[2]; 170 | int32_t f3 = f[3]; 171 | int32_t f4 = f[4]; 172 | int32_t f5 = f[5]; 173 | int32_t f6 = f[6]; 174 | int32_t f7 = f[7]; 175 | int32_t f8 = f[8]; 176 | int32_t f9 = f[9]; 177 | int32_t g0 = g[0]; 178 | int32_t g1 = g[1]; 179 | int32_t g2 = g[2]; 180 | int32_t g3 = g[3]; 181 | int32_t g4 = g[4]; 182 | int32_t g5 = g[5]; 183 | int32_t g6 = g[6]; 184 | int32_t g7 = g[7]; 185 | int32_t g8 = g[8]; 186 | int32_t g9 = g[9]; 187 | int32_t x0 = f0 ^ g0; 188 | int32_t x1 = f1 ^ g1; 189 | int32_t x2 = f2 ^ g2; 190 | int32_t x3 = f3 ^ g3; 191 | int32_t x4 = f4 ^ g4; 192 | int32_t x5 = f5 ^ g5; 193 | int32_t x6 = f6 ^ g6; 194 | int32_t x7 = f7 ^ g7; 195 | int32_t x8 = f8 ^ g8; 196 | int32_t x9 = f9 ^ g9; 197 | b = (unsigned int)(-(int)b); /* silence warning */ 198 | x0 &= b; 199 | x1 &= b; 200 | x2 &= b; 201 | x3 &= b; 202 | x4 &= b; 203 | x5 &= b; 204 | x6 &= b; 205 | x7 &= b; 206 | x8 &= b; 207 | x9 &= b; 208 | f[0] = f0 ^ x0; 209 | f[1] = f1 ^ x1; 210 | f[2] = f2 ^ x2; 211 | f[3] = f3 ^ x3; 212 | f[4] = f4 ^ x4; 213 | f[5] = f5 ^ x5; 214 | f[6] = f6 ^ x6; 215 | f[7] = f7 ^ x7; 216 | f[8] = f8 ^ x8; 217 | f[9] = f9 ^ x9; 218 | g[0] = g0 ^ x0; 219 | g[1] = g1 ^ x1; 220 | g[2] = g2 ^ x2; 221 | g[3] = g3 ^ x3; 222 | g[4] = g4 ^ x4; 223 | g[5] = g5 ^ x5; 224 | g[6] = g6 ^ x6; 225 | g[7] = g7 ^ x7; 226 | g[8] = g8 ^ x8; 227 | g[9] = g9 ^ x9; 228 | } 229 | 230 | /* 231 | h = f 232 | */ 233 | 234 | void fe_copy(fe h, const fe f) { 235 | int32_t f0 = f[0]; 236 | int32_t f1 = f[1]; 237 | int32_t f2 = f[2]; 238 | int32_t f3 = f[3]; 239 | int32_t f4 = f[4]; 240 | int32_t f5 = f[5]; 241 | int32_t f6 = f[6]; 242 | int32_t f7 = f[7]; 243 | int32_t f8 = f[8]; 244 | int32_t f9 = f[9]; 245 | 246 | h[0] = f0; 247 | h[1] = f1; 248 | h[2] = f2; 249 | h[3] = f3; 250 | h[4] = f4; 251 | h[5] = f5; 252 | h[6] = f6; 253 | h[7] = f7; 254 | h[8] = f8; 255 | h[9] = f9; 256 | } 257 | 258 | /* 259 | Ignores top bit of h. 260 | */ 261 | void fe_frombytes(fe h, const uint8_t *s) { 262 | int64_t h0 = bytes_to_u64(s, 4); 263 | int64_t h1 = bytes_to_u64(s + 4, 3) << 6; 264 | int64_t h2 = bytes_to_u64(s + 7, 3) << 5; 265 | int64_t h3 = bytes_to_u64(s + 10, 3) << 3; 266 | int64_t h4 = bytes_to_u64(s + 13, 3) << 2; 267 | int64_t h5 = bytes_to_u64(s + 16, 4); 268 | int64_t h6 = bytes_to_u64(s + 20, 3) << 7; 269 | int64_t h7 = bytes_to_u64(s + 23, 3) << 5; 270 | int64_t h8 = bytes_to_u64(s + 26, 3) << 4; 271 | int64_t h9 = (bytes_to_u64(s + 29, 3) & 8388607) << 2; 272 | int64_t carry0; 273 | int64_t carry1; 274 | int64_t carry2; 275 | int64_t carry3; 276 | int64_t carry4; 277 | int64_t carry5; 278 | int64_t carry6; 279 | int64_t carry7; 280 | int64_t carry8; 281 | int64_t carry9; 282 | 283 | carry9 = (h9 + (int64_t)(1 << 24)) >> 25; 284 | h0 += carry9 * 19; 285 | h9 -= carry9 << 25; 286 | carry1 = (h1 + (int64_t)(1 << 24)) >> 25; 287 | h2 += carry1; 288 | h1 -= carry1 << 25; 289 | carry3 = (h3 + (int64_t)(1 << 24)) >> 25; 290 | h4 += carry3; 291 | h3 -= carry3 << 25; 292 | carry5 = (h5 + (int64_t)(1 << 24)) >> 25; 293 | h6 += carry5; 294 | h5 -= carry5 << 25; 295 | carry7 = (h7 + (int64_t)(1 << 24)) >> 25; 296 | h8 += carry7; 297 | h7 -= carry7 << 25; 298 | carry0 = (h0 + (int64_t)(1 << 25)) >> 26; 299 | h1 += carry0; 300 | h0 -= carry0 << 26; 301 | carry2 = (h2 + (int64_t)(1 << 25)) >> 26; 302 | h3 += carry2; 303 | h2 -= carry2 << 26; 304 | carry4 = (h4 + (int64_t)(1 << 25)) >> 26; 305 | h5 += carry4; 306 | h4 -= carry4 << 26; 307 | carry6 = (h6 + (int64_t)(1 << 25)) >> 26; 308 | h7 += carry6; 309 | h6 -= carry6 << 26; 310 | carry8 = (h8 + (int64_t)(1 << 25)) >> 26; 311 | h9 += carry8; 312 | h8 -= carry8 << 26; 313 | 314 | h[0] = (int32_t)h0; 315 | h[1] = (int32_t)h1; 316 | h[2] = (int32_t)h2; 317 | h[3] = (int32_t)h3; 318 | h[4] = (int32_t)h4; 319 | h[5] = (int32_t)h5; 320 | h[6] = (int32_t)h6; 321 | h[7] = (int32_t)h7; 322 | h[8] = (int32_t)h8; 323 | h[9] = (int32_t)h9; 324 | } 325 | 326 | void fe_invert(fe out, const fe z) { 327 | fe t0; 328 | fe t1; 329 | fe t2; 330 | fe t3; 331 | int i; 332 | 333 | fe_sq(t0, z); 334 | 335 | //for (i = 1; i < 1; ++i) { 336 | // fe_sq(t0, t0); 337 | //} 338 | 339 | fe_sq(t1, t0); 340 | 341 | for (i = 1; i < 2; ++i) { 342 | fe_sq(t1, t1); 343 | } 344 | 345 | fe_mul(t1, z, t1); 346 | fe_mul(t0, t0, t1); 347 | fe_sq(t2, t0); 348 | 349 | //for (i = 1; i < 1; ++i) { 350 | // fe_sq(t2, t2); 351 | //} 352 | 353 | fe_mul(t1, t1, t2); 354 | fe_sq(t2, t1); 355 | 356 | for (i = 1; i < 5; ++i) { 357 | fe_sq(t2, t2); 358 | } 359 | 360 | fe_mul(t1, t2, t1); 361 | fe_sq(t2, t1); 362 | 363 | for (i = 1; i < 10; ++i) { 364 | fe_sq(t2, t2); 365 | } 366 | 367 | fe_mul(t2, t2, t1); 368 | fe_sq(t3, t2); 369 | 370 | for (i = 1; i < 20; ++i) { 371 | fe_sq(t3, t3); 372 | } 373 | 374 | fe_mul(t2, t3, t2); 375 | fe_sq(t2, t2); 376 | 377 | for (i = 1; i < 10; ++i) { 378 | fe_sq(t2, t2); 379 | } 380 | 381 | fe_mul(t1, t2, t1); 382 | fe_sq(t2, t1); 383 | 384 | for (i = 1; i < 50; ++i) { 385 | fe_sq(t2, t2); 386 | } 387 | 388 | fe_mul(t2, t2, t1); 389 | fe_sq(t3, t2); 390 | 391 | for (i = 1; i < 100; ++i) { 392 | fe_sq(t3, t3); 393 | } 394 | 395 | fe_mul(t2, t3, t2); 396 | fe_sq(t2, t2); 397 | 398 | for (i = 1; i < 50; ++i) { 399 | fe_sq(t2, t2); 400 | } 401 | 402 | fe_mul(t1, t2, t1); 403 | fe_sq(t1, t1); 404 | 405 | for (i = 1; i < 5; ++i) { 406 | fe_sq(t1, t1); 407 | } 408 | 409 | fe_mul(out, t1, t0); 410 | } 411 | 412 | /* 413 | return 1 if f is in {1,3,5,...,q-2} 414 | return 0 if f is in {0,2,4,...,q-1} 415 | 416 | Preconditions: 417 | |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. 418 | */ 419 | 420 | int fe_isnegative(const fe f) { 421 | uint8_t s[32]; 422 | 423 | fe_tobytes(s, f); 424 | 425 | return s[0] & 1; 426 | } 427 | 428 | /* 429 | return 1 if f == 0 430 | return 0 if f != 0 431 | 432 | Preconditions: 433 | |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. 434 | */ 435 | 436 | int fe_isnonzero(const fe f) { 437 | uint8_t s[32]; 438 | uint8_t r; 439 | 440 | fe_tobytes(s, f); 441 | r = s[0]; 442 | 443 | for (size_t i = 1; i < 32; ++i) 444 | r |= s[i]; 445 | 446 | return r != 0; 447 | } 448 | 449 | /* 450 | h = f * g 451 | Can overlap h with f or g. 452 | 453 | Preconditions: 454 | |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. 455 | |g| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. 456 | 457 | Postconditions: 458 | |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc. 459 | */ 460 | 461 | /* 462 | Notes on implementation strategy: 463 | 464 | Using schoolbook multiplication. 465 | Karatsuba would save a little in some cost models. 466 | 467 | Most multiplications by 2 and 19 are 32-bit precomputations; 468 | cheaper than 64-bit postcomputations. 469 | 470 | There is one remaining multiplication by 19 in the carry chain; 471 | one *19 precomputation can be merged into this, 472 | but the resulting data flow is considerably less clean. 473 | 474 | There are 12 carries below. 475 | 10 of them are 2-way parallelizable and vectorizable. 476 | Can get away with 11 carries, but then data flow is much deeper. 477 | 478 | With tighter constraints on inputs can squeeze carries into int32. 479 | */ 480 | 481 | void fe_mul(fe h, const fe f, const fe g) { 482 | int32_t f0 = f[0]; 483 | int32_t f1 = f[1]; 484 | int32_t f2 = f[2]; 485 | int32_t f3 = f[3]; 486 | int32_t f4 = f[4]; 487 | int32_t f5 = f[5]; 488 | int32_t f6 = f[6]; 489 | int32_t f7 = f[7]; 490 | int32_t f8 = f[8]; 491 | int32_t f9 = f[9]; 492 | int32_t g0 = g[0]; 493 | int32_t g1 = g[1]; 494 | int32_t g2 = g[2]; 495 | int32_t g3 = g[3]; 496 | int32_t g4 = g[4]; 497 | int32_t g5 = g[5]; 498 | int32_t g6 = g[6]; 499 | int32_t g7 = g[7]; 500 | int32_t g8 = g[8]; 501 | int32_t g9 = g[9]; 502 | int32_t g1_19 = 19 * g1; /* 1.959375*2^29 */ 503 | int32_t g2_19 = 19 * g2; /* 1.959375*2^30; still ok */ 504 | int32_t g3_19 = 19 * g3; 505 | int32_t g4_19 = 19 * g4; 506 | int32_t g5_19 = 19 * g5; 507 | int32_t g6_19 = 19 * g6; 508 | int32_t g7_19 = 19 * g7; 509 | int32_t g8_19 = 19 * g8; 510 | int32_t g9_19 = 19 * g9; 511 | int32_t f1_2 = 2 * f1; 512 | int32_t f3_2 = 2 * f3; 513 | int32_t f5_2 = 2 * f5; 514 | int32_t f7_2 = 2 * f7; 515 | int32_t f9_2 = 2 * f9; 516 | int64_t f0g0 = f0 * (int64_t)g0; 517 | int64_t f0g1 = f0 * (int64_t)g1; 518 | int64_t f0g2 = f0 * (int64_t)g2; 519 | int64_t f0g3 = f0 * (int64_t)g3; 520 | int64_t f0g4 = f0 * (int64_t)g4; 521 | int64_t f0g5 = f0 * (int64_t)g5; 522 | int64_t f0g6 = f0 * (int64_t)g6; 523 | int64_t f0g7 = f0 * (int64_t)g7; 524 | int64_t f0g8 = f0 * (int64_t)g8; 525 | int64_t f0g9 = f0 * (int64_t)g9; 526 | int64_t f1g0 = f1 * (int64_t)g0; 527 | int64_t f1g1_2 = f1_2 * (int64_t)g1; 528 | int64_t f1g2 = f1 * (int64_t)g2; 529 | int64_t f1g3_2 = f1_2 * (int64_t)g3; 530 | int64_t f1g4 = f1 * (int64_t)g4; 531 | int64_t f1g5_2 = f1_2 * (int64_t)g5; 532 | int64_t f1g6 = f1 * (int64_t)g6; 533 | int64_t f1g7_2 = f1_2 * (int64_t)g7; 534 | int64_t f1g8 = f1 * (int64_t)g8; 535 | int64_t f1g9_38 = f1_2 * (int64_t)g9_19; 536 | int64_t f2g0 = f2 * (int64_t)g0; 537 | int64_t f2g1 = f2 * (int64_t)g1; 538 | int64_t f2g2 = f2 * (int64_t)g2; 539 | int64_t f2g3 = f2 * (int64_t)g3; 540 | int64_t f2g4 = f2 * (int64_t)g4; 541 | int64_t f2g5 = f2 * (int64_t)g5; 542 | int64_t f2g6 = f2 * (int64_t)g6; 543 | int64_t f2g7 = f2 * (int64_t)g7; 544 | int64_t f2g8_19 = f2 * (int64_t)g8_19; 545 | int64_t f2g9_19 = f2 * (int64_t)g9_19; 546 | int64_t f3g0 = f3 * (int64_t)g0; 547 | int64_t f3g1_2 = f3_2 * (int64_t)g1; 548 | int64_t f3g2 = f3 * (int64_t)g2; 549 | int64_t f3g3_2 = f3_2 * (int64_t)g3; 550 | int64_t f3g4 = f3 * (int64_t)g4; 551 | int64_t f3g5_2 = f3_2 * (int64_t)g5; 552 | int64_t f3g6 = f3 * (int64_t)g6; 553 | int64_t f3g7_38 = f3_2 * (int64_t)g7_19; 554 | int64_t f3g8_19 = f3 * (int64_t)g8_19; 555 | int64_t f3g9_38 = f3_2 * (int64_t)g9_19; 556 | int64_t f4g0 = f4 * (int64_t)g0; 557 | int64_t f4g1 = f4 * (int64_t)g1; 558 | int64_t f4g2 = f4 * (int64_t)g2; 559 | int64_t f4g3 = f4 * (int64_t)g3; 560 | int64_t f4g4 = f4 * (int64_t)g4; 561 | int64_t f4g5 = f4 * (int64_t)g5; 562 | int64_t f4g6_19 = f4 * (int64_t)g6_19; 563 | int64_t f4g7_19 = f4 * (int64_t)g7_19; 564 | int64_t f4g8_19 = f4 * (int64_t)g8_19; 565 | int64_t f4g9_19 = f4 * (int64_t)g9_19; 566 | int64_t f5g0 = f5 * (int64_t)g0; 567 | int64_t f5g1_2 = f5_2 * (int64_t)g1; 568 | int64_t f5g2 = f5 * (int64_t)g2; 569 | int64_t f5g3_2 = f5_2 * (int64_t)g3; 570 | int64_t f5g4 = f5 * (int64_t)g4; 571 | int64_t f5g5_38 = f5_2 * (int64_t)g5_19; 572 | int64_t f5g6_19 = f5 * (int64_t)g6_19; 573 | int64_t f5g7_38 = f5_2 * (int64_t)g7_19; 574 | int64_t f5g8_19 = f5 * (int64_t)g8_19; 575 | int64_t f5g9_38 = f5_2 * (int64_t)g9_19; 576 | int64_t f6g0 = f6 * (int64_t)g0; 577 | int64_t f6g1 = f6 * (int64_t)g1; 578 | int64_t f6g2 = f6 * (int64_t)g2; 579 | int64_t f6g3 = f6 * (int64_t)g3; 580 | int64_t f6g4_19 = f6 * (int64_t)g4_19; 581 | int64_t f6g5_19 = f6 * (int64_t)g5_19; 582 | int64_t f6g6_19 = f6 * (int64_t)g6_19; 583 | int64_t f6g7_19 = f6 * (int64_t)g7_19; 584 | int64_t f6g8_19 = f6 * (int64_t)g8_19; 585 | int64_t f6g9_19 = f6 * (int64_t)g9_19; 586 | int64_t f7g0 = f7 * (int64_t)g0; 587 | int64_t f7g1_2 = f7_2 * (int64_t)g1; 588 | int64_t f7g2 = f7 * (int64_t)g2; 589 | int64_t f7g3_38 = f7_2 * (int64_t)g3_19; 590 | int64_t f7g4_19 = f7 * (int64_t)g4_19; 591 | int64_t f7g5_38 = f7_2 * (int64_t)g5_19; 592 | int64_t f7g6_19 = f7 * (int64_t)g6_19; 593 | int64_t f7g7_38 = f7_2 * (int64_t)g7_19; 594 | int64_t f7g8_19 = f7 * (int64_t)g8_19; 595 | int64_t f7g9_38 = f7_2 * (int64_t)g9_19; 596 | int64_t f8g0 = f8 * (int64_t)g0; 597 | int64_t f8g1 = f8 * (int64_t)g1; 598 | int64_t f8g2_19 = f8 * (int64_t)g2_19; 599 | int64_t f8g3_19 = f8 * (int64_t)g3_19; 600 | int64_t f8g4_19 = f8 * (int64_t)g4_19; 601 | int64_t f8g5_19 = f8 * (int64_t)g5_19; 602 | int64_t f8g6_19 = f8 * (int64_t)g6_19; 603 | int64_t f8g7_19 = f8 * (int64_t)g7_19; 604 | int64_t f8g8_19 = f8 * (int64_t)g8_19; 605 | int64_t f8g9_19 = f8 * (int64_t)g9_19; 606 | int64_t f9g0 = f9 * (int64_t)g0; 607 | int64_t f9g1_38 = f9_2 * (int64_t)g1_19; 608 | int64_t f9g2_19 = f9 * (int64_t)g2_19; 609 | int64_t f9g3_38 = f9_2 * (int64_t)g3_19; 610 | int64_t f9g4_19 = f9 * (int64_t)g4_19; 611 | int64_t f9g5_38 = f9_2 * (int64_t)g5_19; 612 | int64_t f9g6_19 = f9 * (int64_t)g6_19; 613 | int64_t f9g7_38 = f9_2 * (int64_t)g7_19; 614 | int64_t f9g8_19 = f9 * (int64_t)g8_19; 615 | int64_t f9g9_38 = f9_2 * (int64_t)g9_19; 616 | int64_t h0 = f0g0 + f1g9_38 + f2g8_19 + f3g7_38 + f4g6_19 + f5g5_38 + f6g4_19 + f7g3_38 + f8g2_19 + f9g1_38; 617 | int64_t h1 = f0g1 + f1g0 + f2g9_19 + f3g8_19 + f4g7_19 + f5g6_19 + f6g5_19 + f7g4_19 + f8g3_19 + f9g2_19; 618 | int64_t h2 = f0g2 + f1g1_2 + f2g0 + f3g9_38 + f4g8_19 + f5g7_38 + f6g6_19 + f7g5_38 + f8g4_19 + f9g3_38; 619 | int64_t h3 = f0g3 + f1g2 + f2g1 + f3g0 + f4g9_19 + f5g8_19 + f6g7_19 + f7g6_19 + f8g5_19 + f9g4_19; 620 | int64_t h4 = f0g4 + f1g3_2 + f2g2 + f3g1_2 + f4g0 + f5g9_38 + f6g8_19 + f7g7_38 + f8g6_19 + f9g5_38; 621 | int64_t h5 = f0g5 + f1g4 + f2g3 + f3g2 + f4g1 + f5g0 + f6g9_19 + f7g8_19 + f8g7_19 + f9g6_19; 622 | int64_t h6 = f0g6 + f1g5_2 + f2g4 + f3g3_2 + f4g2 + f5g1_2 + f6g0 + f7g9_38 + f8g8_19 + f9g7_38; 623 | int64_t h7 = f0g7 + f1g6 + f2g5 + f3g4 + f4g3 + f5g2 + f6g1 + f7g0 + f8g9_19 + f9g8_19; 624 | int64_t h8 = f0g8 + f1g7_2 + f2g6 + f3g5_2 + f4g4 + f5g3_2 + f6g2 + f7g1_2 + f8g0 + f9g9_38; 625 | int64_t h9 = f0g9 + f1g8 + f2g7 + f3g6 + f4g5 + f5g4 + f6g3 + f7g2 + f8g1 + f9g0; 626 | int64_t carry0; 627 | int64_t carry1; 628 | int64_t carry2; 629 | int64_t carry3; 630 | int64_t carry4; 631 | int64_t carry5; 632 | int64_t carry6; 633 | int64_t carry7; 634 | int64_t carry8; 635 | int64_t carry9; 636 | 637 | carry0 = (h0 + (int64_t)(1 << 25)) >> 26; 638 | h1 += carry0; 639 | h0 -= carry0 << 26; 640 | carry4 = (h4 + (int64_t)(1 << 25)) >> 26; 641 | h5 += carry4; 642 | h4 -= carry4 << 26; 643 | 644 | carry1 = (h1 + (int64_t)(1 << 24)) >> 25; 645 | h2 += carry1; 646 | h1 -= carry1 << 25; 647 | carry5 = (h5 + (int64_t)(1 << 24)) >> 25; 648 | h6 += carry5; 649 | h5 -= carry5 << 25; 650 | 651 | carry2 = (h2 + (int64_t)(1 << 25)) >> 26; 652 | h3 += carry2; 653 | h2 -= carry2 << 26; 654 | carry6 = (h6 + (int64_t)(1 << 25)) >> 26; 655 | h7 += carry6; 656 | h6 -= carry6 << 26; 657 | 658 | carry3 = (h3 + (int64_t)(1 << 24)) >> 25; 659 | h4 += carry3; 660 | h3 -= carry3 << 25; 661 | carry7 = (h7 + (int64_t)(1 << 24)) >> 25; 662 | h8 += carry7; 663 | h7 -= carry7 << 25; 664 | 665 | carry4 = (h4 + (int64_t)(1 << 25)) >> 26; 666 | h5 += carry4; 667 | h4 -= carry4 << 26; 668 | carry8 = (h8 + (int64_t)(1 << 25)) >> 26; 669 | h9 += carry8; 670 | h8 -= carry8 << 26; 671 | 672 | carry9 = (h9 + (int64_t)(1 << 24)) >> 25; 673 | h0 += carry9 * 19; 674 | h9 -= carry9 << 25; 675 | 676 | carry0 = (h0 + (int64_t)(1 << 25)) >> 26; 677 | h1 += carry0; 678 | h0 -= carry0 << 26; 679 | 680 | h[0] = (int32_t)h0; 681 | h[1] = (int32_t)h1; 682 | h[2] = (int32_t)h2; 683 | h[3] = (int32_t)h3; 684 | h[4] = (int32_t)h4; 685 | h[5] = (int32_t)h5; 686 | h[6] = (int32_t)h6; 687 | h[7] = (int32_t)h7; 688 | h[8] = (int32_t)h8; 689 | h[9] = (int32_t)h9; 690 | } 691 | 692 | /* 693 | h = f * 121666 694 | Can overlap h with f. 695 | 696 | Preconditions: 697 | |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. 698 | 699 | Postconditions: 700 | |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. 701 | */ 702 | 703 | void fe_mul121666(fe h, fe f) { 704 | int32_t f0 = f[0]; 705 | int32_t f1 = f[1]; 706 | int32_t f2 = f[2]; 707 | int32_t f3 = f[3]; 708 | int32_t f4 = f[4]; 709 | int32_t f5 = f[5]; 710 | int32_t f6 = f[6]; 711 | int32_t f7 = f[7]; 712 | int32_t f8 = f[8]; 713 | int32_t f9 = f[9]; 714 | int64_t h0 = f0 * (int64_t)121666; 715 | int64_t h1 = f1 * (int64_t)121666; 716 | int64_t h2 = f2 * (int64_t)121666; 717 | int64_t h3 = f3 * (int64_t)121666; 718 | int64_t h4 = f4 * (int64_t)121666; 719 | int64_t h5 = f5 * (int64_t)121666; 720 | int64_t h6 = f6 * (int64_t)121666; 721 | int64_t h7 = f7 * (int64_t)121666; 722 | int64_t h8 = f8 * (int64_t)121666; 723 | int64_t h9 = f9 * (int64_t)121666; 724 | int64_t carry0; 725 | int64_t carry1; 726 | int64_t carry2; 727 | int64_t carry3; 728 | int64_t carry4; 729 | int64_t carry5; 730 | int64_t carry6; 731 | int64_t carry7; 732 | int64_t carry8; 733 | int64_t carry9; 734 | 735 | carry9 = (h9 + (int64_t)(1 << 24)) >> 25; 736 | h0 += carry9 * 19; 737 | h9 -= carry9 << 25; 738 | carry1 = (h1 + (int64_t)(1 << 24)) >> 25; 739 | h2 += carry1; 740 | h1 -= carry1 << 25; 741 | carry3 = (h3 + (int64_t)(1 << 24)) >> 25; 742 | h4 += carry3; 743 | h3 -= carry3 << 25; 744 | carry5 = (h5 + (int64_t)(1 << 24)) >> 25; 745 | h6 += carry5; 746 | h5 -= carry5 << 25; 747 | carry7 = (h7 + (int64_t)(1 << 24)) >> 25; 748 | h8 += carry7; 749 | h7 -= carry7 << 25; 750 | 751 | carry0 = (h0 + (int64_t)(1 << 25)) >> 26; 752 | h1 += carry0; 753 | h0 -= carry0 << 26; 754 | carry2 = (h2 + (int64_t)(1 << 25)) >> 26; 755 | h3 += carry2; 756 | h2 -= carry2 << 26; 757 | carry4 = (h4 + (int64_t)(1 << 25)) >> 26; 758 | h5 += carry4; 759 | h4 -= carry4 << 26; 760 | carry6 = (h6 + (int64_t)(1 << 25)) >> 26; 761 | h7 += carry6; 762 | h6 -= carry6 << 26; 763 | carry8 = (h8 + (int64_t)(1 << 25)) >> 26; 764 | h9 += carry8; 765 | h8 -= carry8 << 26; 766 | 767 | h[0] = (int32_t)h0; 768 | h[1] = (int32_t)h1; 769 | h[2] = (int32_t)h2; 770 | h[3] = (int32_t)h3; 771 | h[4] = (int32_t)h4; 772 | h[5] = (int32_t)h5; 773 | h[6] = (int32_t)h6; 774 | h[7] = (int32_t)h7; 775 | h[8] = (int32_t)h8; 776 | h[9] = (int32_t)h9; 777 | } 778 | 779 | /* 780 | h = -f 781 | 782 | Preconditions: 783 | |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. 784 | 785 | Postconditions: 786 | |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. 787 | */ 788 | 789 | void fe_neg(fe h, const fe f) { 790 | int32_t f0 = f[0]; 791 | int32_t f1 = f[1]; 792 | int32_t f2 = f[2]; 793 | int32_t f3 = f[3]; 794 | int32_t f4 = f[4]; 795 | int32_t f5 = f[5]; 796 | int32_t f6 = f[6]; 797 | int32_t f7 = f[7]; 798 | int32_t f8 = f[8]; 799 | int32_t f9 = f[9]; 800 | int32_t h0 = -f0; 801 | int32_t h1 = -f1; 802 | int32_t h2 = -f2; 803 | int32_t h3 = -f3; 804 | int32_t h4 = -f4; 805 | int32_t h5 = -f5; 806 | int32_t h6 = -f6; 807 | int32_t h7 = -f7; 808 | int32_t h8 = -f8; 809 | int32_t h9 = -f9; 810 | 811 | h[0] = h0; 812 | h[1] = h1; 813 | h[2] = h2; 814 | h[3] = h3; 815 | h[4] = h4; 816 | h[5] = h5; 817 | h[6] = h6; 818 | h[7] = h7; 819 | h[8] = h8; 820 | h[9] = h9; 821 | } 822 | 823 | void fe_pow22523(fe out, const fe z) { 824 | fe t0; 825 | fe t1; 826 | fe t2; 827 | int i; 828 | fe_sq(t0, z); 829 | 830 | //for (i = 1; i < 1; ++i) { 831 | // fe_sq(t0, t0); 832 | //} 833 | 834 | fe_sq(t1, t0); 835 | 836 | for (i = 1; i < 2; ++i) { 837 | fe_sq(t1, t1); 838 | } 839 | 840 | fe_mul(t1, z, t1); 841 | fe_mul(t0, t0, t1); 842 | fe_sq(t0, t0); 843 | 844 | //for (i = 1; i < 1; ++i) { 845 | // fe_sq(t0, t0); 846 | //} 847 | 848 | fe_mul(t0, t1, t0); 849 | fe_sq(t1, t0); 850 | 851 | for (i = 1; i < 5; ++i) { 852 | fe_sq(t1, t1); 853 | } 854 | 855 | fe_mul(t0, t1, t0); 856 | fe_sq(t1, t0); 857 | 858 | for (i = 1; i < 10; ++i) { 859 | fe_sq(t1, t1); 860 | } 861 | 862 | fe_mul(t1, t1, t0); 863 | fe_sq(t2, t1); 864 | 865 | for (i = 1; i < 20; ++i) { 866 | fe_sq(t2, t2); 867 | } 868 | 869 | fe_mul(t1, t2, t1); 870 | fe_sq(t1, t1); 871 | 872 | for (i = 1; i < 10; ++i) { 873 | fe_sq(t1, t1); 874 | } 875 | 876 | fe_mul(t0, t1, t0); 877 | fe_sq(t1, t0); 878 | 879 | for (i = 1; i < 50; ++i) { 880 | fe_sq(t1, t1); 881 | } 882 | 883 | fe_mul(t1, t1, t0); 884 | fe_sq(t2, t1); 885 | 886 | for (i = 1; i < 100; ++i) { 887 | fe_sq(t2, t2); 888 | } 889 | 890 | fe_mul(t1, t2, t1); 891 | fe_sq(t1, t1); 892 | 893 | for (i = 1; i < 50; ++i) { 894 | fe_sq(t1, t1); 895 | } 896 | 897 | fe_mul(t0, t1, t0); 898 | fe_sq(t0, t0); 899 | 900 | for (i = 1; i < 2; ++i) { 901 | fe_sq(t0, t0); 902 | } 903 | 904 | fe_mul(out, t0, z); 905 | return; 906 | } 907 | 908 | /* 909 | h = f * f 910 | Can overlap h with f. 911 | 912 | Preconditions: 913 | |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. 914 | 915 | Postconditions: 916 | |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc. 917 | */ 918 | 919 | /* 920 | See fe_mul.c for discussion of implementation strategy. 921 | */ 922 | 923 | void fe_sq(fe h, const fe f) { 924 | int32_t f0 = f[0]; 925 | int32_t f1 = f[1]; 926 | int32_t f2 = f[2]; 927 | int32_t f3 = f[3]; 928 | int32_t f4 = f[4]; 929 | int32_t f5 = f[5]; 930 | int32_t f6 = f[6]; 931 | int32_t f7 = f[7]; 932 | int32_t f8 = f[8]; 933 | int32_t f9 = f[9]; 934 | int32_t f0_2 = 2 * f0; 935 | int32_t f1_2 = 2 * f1; 936 | int32_t f2_2 = 2 * f2; 937 | int32_t f3_2 = 2 * f3; 938 | int32_t f4_2 = 2 * f4; 939 | int32_t f5_2 = 2 * f5; 940 | int32_t f6_2 = 2 * f6; 941 | int32_t f7_2 = 2 * f7; 942 | int32_t f5_38 = 38 * f5; /* 1.959375*2^30 */ 943 | int32_t f6_19 = 19 * f6; /* 1.959375*2^30 */ 944 | int32_t f7_38 = 38 * f7; /* 1.959375*2^30 */ 945 | int32_t f8_19 = 19 * f8; /* 1.959375*2^30 */ 946 | int32_t f9_38 = 38 * f9; /* 1.959375*2^30 */ 947 | int64_t f0f0 = f0 * (int64_t)f0; 948 | int64_t f0f1_2 = f0_2 * (int64_t)f1; 949 | int64_t f0f2_2 = f0_2 * (int64_t)f2; 950 | int64_t f0f3_2 = f0_2 * (int64_t)f3; 951 | int64_t f0f4_2 = f0_2 * (int64_t)f4; 952 | int64_t f0f5_2 = f0_2 * (int64_t)f5; 953 | int64_t f0f6_2 = f0_2 * (int64_t)f6; 954 | int64_t f0f7_2 = f0_2 * (int64_t)f7; 955 | int64_t f0f8_2 = f0_2 * (int64_t)f8; 956 | int64_t f0f9_2 = f0_2 * (int64_t)f9; 957 | int64_t f1f1_2 = f1_2 * (int64_t)f1; 958 | int64_t f1f2_2 = f1_2 * (int64_t)f2; 959 | int64_t f1f3_4 = f1_2 * (int64_t)f3_2; 960 | int64_t f1f4_2 = f1_2 * (int64_t)f4; 961 | int64_t f1f5_4 = f1_2 * (int64_t)f5_2; 962 | int64_t f1f6_2 = f1_2 * (int64_t)f6; 963 | int64_t f1f7_4 = f1_2 * (int64_t)f7_2; 964 | int64_t f1f8_2 = f1_2 * (int64_t)f8; 965 | int64_t f1f9_76 = f1_2 * (int64_t)f9_38; 966 | int64_t f2f2 = f2 * (int64_t)f2; 967 | int64_t f2f3_2 = f2_2 * (int64_t)f3; 968 | int64_t f2f4_2 = f2_2 * (int64_t)f4; 969 | int64_t f2f5_2 = f2_2 * (int64_t)f5; 970 | int64_t f2f6_2 = f2_2 * (int64_t)f6; 971 | int64_t f2f7_2 = f2_2 * (int64_t)f7; 972 | int64_t f2f8_38 = f2_2 * (int64_t)f8_19; 973 | int64_t f2f9_38 = f2 * (int64_t)f9_38; 974 | int64_t f3f3_2 = f3_2 * (int64_t)f3; 975 | int64_t f3f4_2 = f3_2 * (int64_t)f4; 976 | int64_t f3f5_4 = f3_2 * (int64_t)f5_2; 977 | int64_t f3f6_2 = f3_2 * (int64_t)f6; 978 | int64_t f3f7_76 = f3_2 * (int64_t)f7_38; 979 | int64_t f3f8_38 = f3_2 * (int64_t)f8_19; 980 | int64_t f3f9_76 = f3_2 * (int64_t)f9_38; 981 | int64_t f4f4 = f4 * (int64_t)f4; 982 | int64_t f4f5_2 = f4_2 * (int64_t)f5; 983 | int64_t f4f6_38 = f4_2 * (int64_t)f6_19; 984 | int64_t f4f7_38 = f4 * (int64_t)f7_38; 985 | int64_t f4f8_38 = f4_2 * (int64_t)f8_19; 986 | int64_t f4f9_38 = f4 * (int64_t)f9_38; 987 | int64_t f5f5_38 = f5 * (int64_t)f5_38; 988 | int64_t f5f6_38 = f5_2 * (int64_t)f6_19; 989 | int64_t f5f7_76 = f5_2 * (int64_t)f7_38; 990 | int64_t f5f8_38 = f5_2 * (int64_t)f8_19; 991 | int64_t f5f9_76 = f5_2 * (int64_t)f9_38; 992 | int64_t f6f6_19 = f6 * (int64_t)f6_19; 993 | int64_t f6f7_38 = f6 * (int64_t)f7_38; 994 | int64_t f6f8_38 = f6_2 * (int64_t)f8_19; 995 | int64_t f6f9_38 = f6 * (int64_t)f9_38; 996 | int64_t f7f7_38 = f7 * (int64_t)f7_38; 997 | int64_t f7f8_38 = f7_2 * (int64_t)f8_19; 998 | int64_t f7f9_76 = f7_2 * (int64_t)f9_38; 999 | int64_t f8f8_19 = f8 * (int64_t)f8_19; 1000 | int64_t f8f9_38 = f8 * (int64_t)f9_38; 1001 | int64_t f9f9_38 = f9 * (int64_t)f9_38; 1002 | int64_t h0 = f0f0 + f1f9_76 + f2f8_38 + f3f7_76 + f4f6_38 + f5f5_38; 1003 | int64_t h1 = f0f1_2 + f2f9_38 + f3f8_38 + f4f7_38 + f5f6_38; 1004 | int64_t h2 = f0f2_2 + f1f1_2 + f3f9_76 + f4f8_38 + f5f7_76 + f6f6_19; 1005 | int64_t h3 = f0f3_2 + f1f2_2 + f4f9_38 + f5f8_38 + f6f7_38; 1006 | int64_t h4 = f0f4_2 + f1f3_4 + f2f2 + f5f9_76 + f6f8_38 + f7f7_38; 1007 | int64_t h5 = f0f5_2 + f1f4_2 + f2f3_2 + f6f9_38 + f7f8_38; 1008 | int64_t h6 = f0f6_2 + f1f5_4 + f2f4_2 + f3f3_2 + f7f9_76 + f8f8_19; 1009 | int64_t h7 = f0f7_2 + f1f6_2 + f2f5_2 + f3f4_2 + f8f9_38; 1010 | int64_t h8 = f0f8_2 + f1f7_4 + f2f6_2 + f3f5_4 + f4f4 + f9f9_38; 1011 | int64_t h9 = f0f9_2 + f1f8_2 + f2f7_2 + f3f6_2 + f4f5_2; 1012 | int64_t carry0; 1013 | int64_t carry1; 1014 | int64_t carry2; 1015 | int64_t carry3; 1016 | int64_t carry4; 1017 | int64_t carry5; 1018 | int64_t carry6; 1019 | int64_t carry7; 1020 | int64_t carry8; 1021 | int64_t carry9; 1022 | carry0 = (h0 + (int64_t)(1 << 25)) >> 26; 1023 | h1 += carry0; 1024 | h0 -= carry0 << 26; 1025 | carry4 = (h4 + (int64_t)(1 << 25)) >> 26; 1026 | h5 += carry4; 1027 | h4 -= carry4 << 26; 1028 | carry1 = (h1 + (int64_t)(1 << 24)) >> 25; 1029 | h2 += carry1; 1030 | h1 -= carry1 << 25; 1031 | carry5 = (h5 + (int64_t)(1 << 24)) >> 25; 1032 | h6 += carry5; 1033 | h5 -= carry5 << 25; 1034 | carry2 = (h2 + (int64_t)(1 << 25)) >> 26; 1035 | h3 += carry2; 1036 | h2 -= carry2 << 26; 1037 | carry6 = (h6 + (int64_t)(1 << 25)) >> 26; 1038 | h7 += carry6; 1039 | h6 -= carry6 << 26; 1040 | carry3 = (h3 + (int64_t)(1 << 24)) >> 25; 1041 | h4 += carry3; 1042 | h3 -= carry3 << 25; 1043 | carry7 = (h7 + (int64_t)(1 << 24)) >> 25; 1044 | h8 += carry7; 1045 | h7 -= carry7 << 25; 1046 | carry4 = (h4 + (int64_t)(1 << 25)) >> 26; 1047 | h5 += carry4; 1048 | h4 -= carry4 << 26; 1049 | carry8 = (h8 + (int64_t)(1 << 25)) >> 26; 1050 | h9 += carry8; 1051 | h8 -= carry8 << 26; 1052 | carry9 = (h9 + (int64_t)(1 << 24)) >> 25; 1053 | h0 += carry9 * 19; 1054 | h9 -= carry9 << 25; 1055 | carry0 = (h0 + (int64_t)(1 << 25)) >> 26; 1056 | h1 += carry0; 1057 | h0 -= carry0 << 26; 1058 | h[0] = (int32_t)h0; 1059 | h[1] = (int32_t)h1; 1060 | h[2] = (int32_t)h2; 1061 | h[3] = (int32_t)h3; 1062 | h[4] = (int32_t)h4; 1063 | h[5] = (int32_t)h5; 1064 | h[6] = (int32_t)h6; 1065 | h[7] = (int32_t)h7; 1066 | h[8] = (int32_t)h8; 1067 | h[9] = (int32_t)h9; 1068 | } 1069 | 1070 | /* 1071 | h = 2 * f * f 1072 | Can overlap h with f. 1073 | 1074 | Preconditions: 1075 | |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. 1076 | 1077 | Postconditions: 1078 | |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc. 1079 | */ 1080 | 1081 | /* 1082 | See fe_mul.c for discussion of implementation strategy. 1083 | */ 1084 | 1085 | void fe_sq2(fe h, const fe f) { 1086 | int32_t f0 = f[0]; 1087 | int32_t f1 = f[1]; 1088 | int32_t f2 = f[2]; 1089 | int32_t f3 = f[3]; 1090 | int32_t f4 = f[4]; 1091 | int32_t f5 = f[5]; 1092 | int32_t f6 = f[6]; 1093 | int32_t f7 = f[7]; 1094 | int32_t f8 = f[8]; 1095 | int32_t f9 = f[9]; 1096 | int32_t f0_2 = 2 * f0; 1097 | int32_t f1_2 = 2 * f1; 1098 | int32_t f2_2 = 2 * f2; 1099 | int32_t f3_2 = 2 * f3; 1100 | int32_t f4_2 = 2 * f4; 1101 | int32_t f5_2 = 2 * f5; 1102 | int32_t f6_2 = 2 * f6; 1103 | int32_t f7_2 = 2 * f7; 1104 | int32_t f5_38 = 38 * f5; /* 1.959375*2^30 */ 1105 | int32_t f6_19 = 19 * f6; /* 1.959375*2^30 */ 1106 | int32_t f7_38 = 38 * f7; /* 1.959375*2^30 */ 1107 | int32_t f8_19 = 19 * f8; /* 1.959375*2^30 */ 1108 | int32_t f9_38 = 38 * f9; /* 1.959375*2^30 */ 1109 | int64_t f0f0 = f0 * (int64_t)f0; 1110 | int64_t f0f1_2 = f0_2 * (int64_t)f1; 1111 | int64_t f0f2_2 = f0_2 * (int64_t)f2; 1112 | int64_t f0f3_2 = f0_2 * (int64_t)f3; 1113 | int64_t f0f4_2 = f0_2 * (int64_t)f4; 1114 | int64_t f0f5_2 = f0_2 * (int64_t)f5; 1115 | int64_t f0f6_2 = f0_2 * (int64_t)f6; 1116 | int64_t f0f7_2 = f0_2 * (int64_t)f7; 1117 | int64_t f0f8_2 = f0_2 * (int64_t)f8; 1118 | int64_t f0f9_2 = f0_2 * (int64_t)f9; 1119 | int64_t f1f1_2 = f1_2 * (int64_t)f1; 1120 | int64_t f1f2_2 = f1_2 * (int64_t)f2; 1121 | int64_t f1f3_4 = f1_2 * (int64_t)f3_2; 1122 | int64_t f1f4_2 = f1_2 * (int64_t)f4; 1123 | int64_t f1f5_4 = f1_2 * (int64_t)f5_2; 1124 | int64_t f1f6_2 = f1_2 * (int64_t)f6; 1125 | int64_t f1f7_4 = f1_2 * (int64_t)f7_2; 1126 | int64_t f1f8_2 = f1_2 * (int64_t)f8; 1127 | int64_t f1f9_76 = f1_2 * (int64_t)f9_38; 1128 | int64_t f2f2 = f2 * (int64_t)f2; 1129 | int64_t f2f3_2 = f2_2 * (int64_t)f3; 1130 | int64_t f2f4_2 = f2_2 * (int64_t)f4; 1131 | int64_t f2f5_2 = f2_2 * (int64_t)f5; 1132 | int64_t f2f6_2 = f2_2 * (int64_t)f6; 1133 | int64_t f2f7_2 = f2_2 * (int64_t)f7; 1134 | int64_t f2f8_38 = f2_2 * (int64_t)f8_19; 1135 | int64_t f2f9_38 = f2 * (int64_t)f9_38; 1136 | int64_t f3f3_2 = f3_2 * (int64_t)f3; 1137 | int64_t f3f4_2 = f3_2 * (int64_t)f4; 1138 | int64_t f3f5_4 = f3_2 * (int64_t)f5_2; 1139 | int64_t f3f6_2 = f3_2 * (int64_t)f6; 1140 | int64_t f3f7_76 = f3_2 * (int64_t)f7_38; 1141 | int64_t f3f8_38 = f3_2 * (int64_t)f8_19; 1142 | int64_t f3f9_76 = f3_2 * (int64_t)f9_38; 1143 | int64_t f4f4 = f4 * (int64_t)f4; 1144 | int64_t f4f5_2 = f4_2 * (int64_t)f5; 1145 | int64_t f4f6_38 = f4_2 * (int64_t)f6_19; 1146 | int64_t f4f7_38 = f4 * (int64_t)f7_38; 1147 | int64_t f4f8_38 = f4_2 * (int64_t)f8_19; 1148 | int64_t f4f9_38 = f4 * (int64_t)f9_38; 1149 | int64_t f5f5_38 = f5 * (int64_t)f5_38; 1150 | int64_t f5f6_38 = f5_2 * (int64_t)f6_19; 1151 | int64_t f5f7_76 = f5_2 * (int64_t)f7_38; 1152 | int64_t f5f8_38 = f5_2 * (int64_t)f8_19; 1153 | int64_t f5f9_76 = f5_2 * (int64_t)f9_38; 1154 | int64_t f6f6_19 = f6 * (int64_t)f6_19; 1155 | int64_t f6f7_38 = f6 * (int64_t)f7_38; 1156 | int64_t f6f8_38 = f6_2 * (int64_t)f8_19; 1157 | int64_t f6f9_38 = f6 * (int64_t)f9_38; 1158 | int64_t f7f7_38 = f7 * (int64_t)f7_38; 1159 | int64_t f7f8_38 = f7_2 * (int64_t)f8_19; 1160 | int64_t f7f9_76 = f7_2 * (int64_t)f9_38; 1161 | int64_t f8f8_19 = f8 * (int64_t)f8_19; 1162 | int64_t f8f9_38 = f8 * (int64_t)f9_38; 1163 | int64_t f9f9_38 = f9 * (int64_t)f9_38; 1164 | int64_t h0 = f0f0 + f1f9_76 + f2f8_38 + f3f7_76 + f4f6_38 + f5f5_38; 1165 | int64_t h1 = f0f1_2 + f2f9_38 + f3f8_38 + f4f7_38 + f5f6_38; 1166 | int64_t h2 = f0f2_2 + f1f1_2 + f3f9_76 + f4f8_38 + f5f7_76 + f6f6_19; 1167 | int64_t h3 = f0f3_2 + f1f2_2 + f4f9_38 + f5f8_38 + f6f7_38; 1168 | int64_t h4 = f0f4_2 + f1f3_4 + f2f2 + f5f9_76 + f6f8_38 + f7f7_38; 1169 | int64_t h5 = f0f5_2 + f1f4_2 + f2f3_2 + f6f9_38 + f7f8_38; 1170 | int64_t h6 = f0f6_2 + f1f5_4 + f2f4_2 + f3f3_2 + f7f9_76 + f8f8_19; 1171 | int64_t h7 = f0f7_2 + f1f6_2 + f2f5_2 + f3f4_2 + f8f9_38; 1172 | int64_t h8 = f0f8_2 + f1f7_4 + f2f6_2 + f3f5_4 + f4f4 + f9f9_38; 1173 | int64_t h9 = f0f9_2 + f1f8_2 + f2f7_2 + f3f6_2 + f4f5_2; 1174 | int64_t carry0; 1175 | int64_t carry1; 1176 | int64_t carry2; 1177 | int64_t carry3; 1178 | int64_t carry4; 1179 | int64_t carry5; 1180 | int64_t carry6; 1181 | int64_t carry7; 1182 | int64_t carry8; 1183 | int64_t carry9; 1184 | h0 += h0; 1185 | h1 += h1; 1186 | h2 += h2; 1187 | h3 += h3; 1188 | h4 += h4; 1189 | h5 += h5; 1190 | h6 += h6; 1191 | h7 += h7; 1192 | h8 += h8; 1193 | h9 += h9; 1194 | carry0 = (h0 + (int64_t)(1 << 25)) >> 26; 1195 | h1 += carry0; 1196 | h0 -= carry0 << 26; 1197 | carry4 = (h4 + (int64_t)(1 << 25)) >> 26; 1198 | h5 += carry4; 1199 | h4 -= carry4 << 26; 1200 | carry1 = (h1 + (int64_t)(1 << 24)) >> 25; 1201 | h2 += carry1; 1202 | h1 -= carry1 << 25; 1203 | carry5 = (h5 + (int64_t)(1 << 24)) >> 25; 1204 | h6 += carry5; 1205 | h5 -= carry5 << 25; 1206 | carry2 = (h2 + (int64_t)(1 << 25)) >> 26; 1207 | h3 += carry2; 1208 | h2 -= carry2 << 26; 1209 | carry6 = (h6 + (int64_t)(1 << 25)) >> 26; 1210 | h7 += carry6; 1211 | h6 -= carry6 << 26; 1212 | carry3 = (h3 + (int64_t)(1 << 24)) >> 25; 1213 | h4 += carry3; 1214 | h3 -= carry3 << 25; 1215 | carry7 = (h7 + (int64_t)(1 << 24)) >> 25; 1216 | h8 += carry7; 1217 | h7 -= carry7 << 25; 1218 | carry4 = (h4 + (int64_t)(1 << 25)) >> 26; 1219 | h5 += carry4; 1220 | h4 -= carry4 << 26; 1221 | carry8 = (h8 + (int64_t)(1 << 25)) >> 26; 1222 | h9 += carry8; 1223 | h8 -= carry8 << 26; 1224 | carry9 = (h9 + (int64_t)(1 << 24)) >> 25; 1225 | h0 += carry9 * 19; 1226 | h9 -= carry9 << 25; 1227 | carry0 = (h0 + (int64_t)(1 << 25)) >> 26; 1228 | h1 += carry0; 1229 | h0 -= carry0 << 26; 1230 | h[0] = (int32_t)h0; 1231 | h[1] = (int32_t)h1; 1232 | h[2] = (int32_t)h2; 1233 | h[3] = (int32_t)h3; 1234 | h[4] = (int32_t)h4; 1235 | h[5] = (int32_t)h5; 1236 | h[6] = (int32_t)h6; 1237 | h[7] = (int32_t)h7; 1238 | h[8] = (int32_t)h8; 1239 | h[9] = (int32_t)h9; 1240 | } 1241 | 1242 | /* 1243 | h = f - g 1244 | Can overlap h with f or g. 1245 | 1246 | Preconditions: 1247 | |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. 1248 | |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. 1249 | 1250 | Postconditions: 1251 | |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. 1252 | */ 1253 | 1254 | void fe_sub(fe h, const fe f, const fe g) { 1255 | int32_t f0 = f[0]; 1256 | int32_t f1 = f[1]; 1257 | int32_t f2 = f[2]; 1258 | int32_t f3 = f[3]; 1259 | int32_t f4 = f[4]; 1260 | int32_t f5 = f[5]; 1261 | int32_t f6 = f[6]; 1262 | int32_t f7 = f[7]; 1263 | int32_t f8 = f[8]; 1264 | int32_t f9 = f[9]; 1265 | int32_t g0 = g[0]; 1266 | int32_t g1 = g[1]; 1267 | int32_t g2 = g[2]; 1268 | int32_t g3 = g[3]; 1269 | int32_t g4 = g[4]; 1270 | int32_t g5 = g[5]; 1271 | int32_t g6 = g[6]; 1272 | int32_t g7 = g[7]; 1273 | int32_t g8 = g[8]; 1274 | int32_t g9 = g[9]; 1275 | int32_t h0 = f0 - g0; 1276 | int32_t h1 = f1 - g1; 1277 | int32_t h2 = f2 - g2; 1278 | int32_t h3 = f3 - g3; 1279 | int32_t h4 = f4 - g4; 1280 | int32_t h5 = f5 - g5; 1281 | int32_t h6 = f6 - g6; 1282 | int32_t h7 = f7 - g7; 1283 | int32_t h8 = f8 - g8; 1284 | int32_t h9 = f9 - g9; 1285 | 1286 | h[0] = h0; 1287 | h[1] = h1; 1288 | h[2] = h2; 1289 | h[3] = h3; 1290 | h[4] = h4; 1291 | h[5] = h5; 1292 | h[6] = h6; 1293 | h[7] = h7; 1294 | h[8] = h8; 1295 | h[9] = h9; 1296 | } 1297 | 1298 | /* 1299 | Preconditions: 1300 | |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. 1301 | 1302 | Write p=2^255-19; q=floor(h/p). 1303 | Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))). 1304 | 1305 | Proof: 1306 | Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4. 1307 | Also have |h-2^230 h9|<2^231 so |19 2^(-255)(h-2^230 h9)|<1/4. 1308 | 1309 | Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9). 1310 | Then 0> 25; 1346 | q = (h0 + q) >> 26; 1347 | q = (h1 + q) >> 25; 1348 | q = (h2 + q) >> 26; 1349 | q = (h3 + q) >> 25; 1350 | q = (h4 + q) >> 26; 1351 | q = (h5 + q) >> 25; 1352 | q = (h6 + q) >> 26; 1353 | q = (h7 + q) >> 25; 1354 | q = (h8 + q) >> 26; 1355 | q = (h9 + q) >> 25; 1356 | /* Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20. */ 1357 | h0 += 19 * q; 1358 | /* Goal: Output h-2^255 q, which is between 0 and 2^255-20. */ 1359 | carry0 = h0 >> 26; 1360 | h1 += carry0; 1361 | h0 -= carry0 << 26; 1362 | carry1 = h1 >> 25; 1363 | h2 += carry1; 1364 | h1 -= carry1 << 25; 1365 | carry2 = h2 >> 26; 1366 | h3 += carry2; 1367 | h2 -= carry2 << 26; 1368 | carry3 = h3 >> 25; 1369 | h4 += carry3; 1370 | h3 -= carry3 << 25; 1371 | carry4 = h4 >> 26; 1372 | h5 += carry4; 1373 | h4 -= carry4 << 26; 1374 | carry5 = h5 >> 25; 1375 | h6 += carry5; 1376 | h5 -= carry5 << 25; 1377 | carry6 = h6 >> 26; 1378 | h7 += carry6; 1379 | h6 -= carry6 << 26; 1380 | carry7 = h7 >> 25; 1381 | h8 += carry7; 1382 | h7 -= carry7 << 25; 1383 | carry8 = h8 >> 26; 1384 | h9 += carry8; 1385 | h8 -= carry8 << 26; 1386 | carry9 = h9 >> 25; 1387 | h9 -= carry9 << 25; 1388 | 1389 | /* h10 = carry9 */ 1390 | /* 1391 | Goal: Output h0+...+2^255 h10-2^255 q, which is between 0 and 2^255-20. 1392 | Have h0+...+2^230 h9 between 0 and 2^255-1; 1393 | evidently 2^255 h10-2^255 q = 0. 1394 | Goal: Output h0+...+2^230 h9. 1395 | */ 1396 | s[0] = (uint8_t)(h0 >> 0); 1397 | s[1] = (uint8_t)(h0 >> 8); 1398 | s[2] = (uint8_t)(h0 >> 16); 1399 | s[3] = (uint8_t)((h0 >> 24) | (h1 << 2)); 1400 | s[4] = (uint8_t)(h1 >> 6); 1401 | s[5] = (uint8_t)(h1 >> 14); 1402 | s[6] = (uint8_t)((h1 >> 22) | (h2 << 3)); 1403 | s[7] = (uint8_t)(h2 >> 5); 1404 | s[8] = (uint8_t)(h2 >> 13); 1405 | s[9] = (uint8_t)((h2 >> 21) | (h3 << 5)); 1406 | s[10] = (uint8_t)(h3 >> 3); 1407 | s[11] = (uint8_t)(h3 >> 11); 1408 | s[12] = (uint8_t)((h3 >> 19) | (h4 << 6)); 1409 | s[13] = (uint8_t)(h4 >> 2); 1410 | s[14] = (uint8_t)(h4 >> 10); 1411 | s[15] = (uint8_t)(h4 >> 18); 1412 | s[16] = (uint8_t)(h5 >> 0); 1413 | s[17] = (uint8_t)(h5 >> 8); 1414 | s[18] = (uint8_t)(h5 >> 16); 1415 | s[19] = (uint8_t)((h5 >> 24) | (h6 << 1)); 1416 | s[20] = (uint8_t)(h6 >> 7); 1417 | s[21] = (uint8_t)(h6 >> 15); 1418 | s[22] = (uint8_t)((h6 >> 23) | (h7 << 3)); 1419 | s[23] = (uint8_t)(h7 >> 5); 1420 | s[24] = (uint8_t)(h7 >> 13); 1421 | s[25] = (uint8_t)((h7 >> 21) | (h8 << 4)); 1422 | s[26] = (uint8_t)(h8 >> 4); 1423 | s[27] = (uint8_t)(h8 >> 12); 1424 | s[28] = (uint8_t)((h8 >> 20) | (h9 << 6)); 1425 | s[29] = (uint8_t)(h9 >> 2); 1426 | s[30] = (uint8_t)(h9 >> 10); 1427 | s[31] = (uint8_t)(h9 >> 18); 1428 | } 1429 | --------------------------------------------------------------------------------