diff --git a/CMakeLists.txt b/CMakeLists.txt index b9e259b3..4d89700a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,7 @@ cmake_minimum_required(VERSION 3.13) list(INSERT CMAKE_MODULE_PATH 0 "${CMAKE_CURRENT_LIST_DIR}/cmake/Modules") include(ABYCacheVariables) +set(CMAKE_CXX_STANDARD 14) project(ABY LANGUAGES C CXX) # Write built executables and libraries to bin/ and lib/, respectively. if(NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY) @@ -12,8 +13,10 @@ endif() if(NOT CMAKE_ARCHIVE_OUTPUT_DIRECTORY) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib") endif() +if(ANDROID) + add_definitions(-DANDROID) +endif() -include(AddENCRYPTO_utils) add_subdirectory(src/abycore) if(ABY_BUILD_EXE) diff --git a/LICENSE b/LICENSE index dbbe3558..0a041280 100644 --- a/LICENSE +++ b/LICENSE @@ -1,661 +1,165 @@ - GNU AFFERO GENERAL PUBLIC LICENSE - Version 3, 19 November 2007 + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 - Copyright (C) 2007 Free Software Foundation, Inc. + Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. - Preamble - - The GNU Affero General Public License is a free, copyleft license for -software and other kinds of works, specifically designed to ensure -cooperation with the community in the case of network server software. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -our General Public Licenses are intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - Developers that use our General Public Licenses protect your rights -with two steps: (1) assert copyright on the software, and (2) offer -you this License which gives you legal permission to copy, distribute -and/or modify the software. - - A secondary benefit of defending all users' freedom is that -improvements made in alternate versions of the program, if they -receive widespread use, become available for other developers to -incorporate. Many developers of free software are heartened and -encouraged by the resulting cooperation. However, in the case of -software used on network servers, this result may fail to come about. -The GNU General Public License permits making a modified version and -letting the public access it on a server without ever releasing its -source code to the public. - - The GNU Affero General Public License is designed specifically to -ensure that, in such cases, the modified source code becomes available -to the community. It requires the operator of a network server to -provide the source code of the modified version running there to the -users of that server. Therefore, public use of a modified version, on -a publicly accessible server, gives the public access to the source -code of the modified version. - - An older license, called the Affero General Public License and -published by Affero, was designed to accomplish similar goals. This is -a different license, not a version of the Affero GPL, but Affero has -released a new version of the Affero GPL which permits relicensing under -this license. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU Affero General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Remote Network Interaction; Use with the GNU General Public License. - - Notwithstanding any other provision of this License, if you modify the -Program, your modified version must prominently offer all users -interacting with it remotely through a computer network (if your version -supports such interaction) an opportunity to receive the Corresponding -Source of your version by providing access to the Corresponding Source -from a network server at no charge, through some standard or customary -means of facilitating copying of software. This Corresponding Source -shall include the Corresponding Source for any work covered by version 3 -of the GNU General Public License that is incorporated pursuant to the -following paragraph. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the work with which it is combined will remain governed by version -3 of the GNU General Public License. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU Affero General Public License from time to time. Such new versions -will be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU Affero General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU Affero General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU Affero General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If your software can interact with users remotely through a computer -network, you should also make sure that it provides a way for users to -get its source. For example, if your program is a web application, its -interface could display a "Source" link that leads users to an archive -of the code. There are many ways you could offer source, and different -solutions will be better for different programs; see section 13 for the -specific requirements. - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU AGPL, see -. + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/README.md b/README.md index 15be7c8b..87f9cd6c 100644 --- a/README.md +++ b/README.md @@ -20,13 +20,13 @@ By *Daniel Demmler, Thomas Schneider and Michael Zohner* ([ENCRYPTO](http://www. - [Build Options](#build-options) - [Cleaning the Build Directory](#cleaning-the-build-directory) - [Installation](#installation) - - [Developer Guide and Documentation](#developer-guide-and-documentation) + - [Building for Android](#building-for-android) + - [Developer Guide and Documentation](#developer-guide-and-documentation) - [ABY Applications](#aby-applications) - [Included Example Applications](#included-example-applications) - [Running Applications](#running-applications) - [Creating and Building your own ABY Application](#creating-and-building-your-own-aby-application) - ### Features --- ABY efficiently combines secure computation schemes based on **Arithmetic sharing**, **Boolean sharing**, and **Yao’s garbled circuits** and makes available best-practice solutions in secure two-party computation. @@ -182,12 +182,36 @@ make make install ``` - #### Developer Guide and Documentation We provide an extensive [developer guide](https://www.informatik.tu-darmstadt.de/media/encrypto/encrypto_code/abydevguide.pdf) with many examples and explanations of how to use ABY. Also, see the [online doxygen documentation of ABY](http://encryptogroup.github.io/ABY/docs/index.html) for further information and comments on the code. +## Building for Android + +1. Clone the ABY git repository by running: + ``` + git clone https://github.com/encryptogroup/ABY.git + ``` + +2. Enter the Framework directory: `cd ABY/` + +3. Create and enter the build directory: `mkdir build && cd build` + +4. Use CMake to configure the build and setting android variables: + ``` + cmake -DANDROID_NDK= -DANDROID_NATIVE_API_LEVEL= -DANDROID_ABI= .. + ``` + where is a number between 16 and the latest Android API and is the target platform (one of armeabi-v7a, arm64-v8a, x86 and x86_64 respectively). + + Please note that when using ABY with Android Studio that needs to be the path to the NDK used by Android Studio (often located at $HOME/Android/Sdk/ndk-bundle on Linux). + + +5. Call `make` in the build directory. + You can find the build executables and libraries in the directories `bin/` + and `lib/`, respectively. + +6. Call 'make install' after the build has finished. This will install the libraries into the provided NDK. ### ABY Applications --- @@ -234,6 +258,8 @@ Also, see the [online doxygen documentation of ABY](http://encryptogroup.github. add_executable(my_application my_application.cpp) target_link_libraries(my_application ABY::aby) ``` +* If you are using ABY for Android in Android Studio and you encounter the "library libc++_shared.so not found" error, make sure to pass '-DANDROID_STL=c++_shared' as an argument to cmake within the gradle script. Setting ANDROID_STL within the cmake script won't work. + * Otherwise, setup the include path such that the headers of ABY and its dependencies can be found and link your application to the `libaby.a` library and the other dependencies (see above). diff --git a/cmake/ABYConfig.cmake.in b/cmake/ABYConfig.cmake.in index 11e6b490..44181f59 100644 --- a/cmake/ABYConfig.cmake.in +++ b/cmake/ABYConfig.cmake.in @@ -4,10 +4,18 @@ include(CMakeFindDependencyMacro) find_dependency(OTExtension) find_dependency(ENCRYPTO_utils) -find_dependency(MIRACL) find_dependency(GMP) find_dependency(Threads) if(NOT TARGET ABY::aby) include("${ABY_CMAKE_DIR}/ABYTargets.cmake") endif() + +if(NOT "${ABY_LIBRARY_TYPE}" STREQUAL "STATIC" AND NOT "${ABY_LIBRARY_TYPE}" STREQUAL "SHARED") + set(ABY_LIBRARY_TYPE "@ABY_LIBRARY_TYPE@") +endif() +set(LIB_PREFIX "${CMAKE_${ABY_LIBRARY_TYPE}_LIBRARY_PREFIX}") +set(LIB_SUFFIX "${CMAKE_${ABY_LIBRARY_TYPE}_LIBRARY_SUFFIX}") + +set(LIBRARIES_FULL_PATH "@ANDROID_NDK@/@ABY_INSTALL_LIB@/${LIB_PREFIX}aby${LIB_SUFFIX}") +set(LIB_NAME "ABY") diff --git a/cmake/GMPConfig.cmake.in b/cmake/GMPConfig.cmake.in new file mode 100644 index 00000000..d1ecc1ff --- /dev/null +++ b/cmake/GMPConfig.cmake.in @@ -0,0 +1,31 @@ +if(NOT "${GMP_LIBRARY_TYPE}" STREQUAL "STATIC" AND NOT "${GMP_LIBRARY_TYPE}" STREQUAL "SHARED") + set(GMP_LIBRARY_TYPE "@GMP_LIBRARY_TYPE@") +endif() +set(LIB_PREFIX "${CMAKE_${GMP_LIBRARY_TYPE}_LIBRARY_PREFIX}") +set(LIB_SUFFIX "${CMAKE_${GMP_LIBRARY_TYPE}_LIBRARY_SUFFIX}") + +find_path(GMP_INCLUDE_DIR gmp.h PATHS "@ANDROID_NDK@/@ABY_INSTALL_INCLUDE@") + +set(GMP_LIBRARY "@ANDROID_NDK@/@ABY_INSTALL_LIB@/${LIB_PREFIX}gmp${LIB_SUFFIX}") +if(EXISTS "${GMP_INCLUDE_DIR}" AND EXISTS "${GMP_LIBRARY}") + set(GMP_FOUND TRUE) +else() + set(GMP_LIBRARY ) + set(GMP_FOUND FALSE) +endif() + +if(GMP_FOUND AND NOT TARGET GMP::GMP) + add_library(GMP::GMP UNKNOWN IMPORTED) + set_target_properties(GMP::GMP PROPERTIES + IMPORTED_LOCATION "${GMP_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${GMP_INCLUDE_DIR}" + ) +endif() + +mark_as_advanced( + GMP_INCLUDE_DIR + GMP_LIBRARY +) + +set(LIBRARIES_FULL_PATH "@ANDROID_NDK@/@ABY_INSTALL_LIB@/${LIB_PREFIX}gmp${LIB_SUFFIX}") +set(LIB_NAME "GMP") diff --git a/cmake/GMPXXConfig.cmake.in b/cmake/GMPXXConfig.cmake.in new file mode 100644 index 00000000..a84a703c --- /dev/null +++ b/cmake/GMPXXConfig.cmake.in @@ -0,0 +1,31 @@ +if(NOT "${GMP_LIBRARY_TYPE}" STREQUAL "STATIC" AND NOT "${GMP_LIBRARY_TYPE}" STREQUAL "SHARED") + set(GMP_LIBRARY_TYPE "@GMP_LIBRARY_TYPE@") +endif() +set(LIB_PREFIX "${CMAKE_${GMP_LIBRARY_TYPE}_LIBRARY_PREFIX}") +set(LIB_SUFFIX "${CMAKE_${GMP_LIBRARY_TYPE}_LIBRARY_SUFFIX}") + +find_path(GMPXX_INCLUDE_DIR gmpxx.h PATHS "@ANDROID_NDK@/@ABY_INSTALL_INCLUDE@") + +set(GMPXX_LIBRARY "@ANDROID_NDK@/@ABY_INSTALL_LIB@/${LIB_PREFIX}gmpxx${LIB_SUFFIX}") +if(EXISTS "${GMPXX_INCLUDE_DIR}" AND EXISTS "${GMPXX_LIBRARY}") + set(GMPXX_FOUND TRUE) +else() + set(GMPXX_LIBRARY ) + set(GMPXX_FOUND FALSE) +endif() + +if(GMPXX_FOUND AND NOT TARGET GMP::GMPXX) + add_library(GMP::GMPXX UNKNOWN IMPORTED) + set_target_properties(GMP::GMPXX PROPERTIES + IMPORTED_LOCATION "${GMPXX_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${GMPXX_INCLUDE_DIR}" + ) +endif() + +mark_as_advanced( + GMPXX_INCLUDE_DIR + GMPXX_LIBRARY +) + +set(LIBRARIES_FULL_PATH "@ANDROID_NDK@/@ABY_INSTALL_LIB@/${LIB_PREFIX}gmpxx${LIB_SUFFIX}") +set(LIB_NAME "GMP") diff --git a/cmake/ImportIntoAndroidStudio.cmake b/cmake/ImportIntoAndroidStudio.cmake new file mode 100644 index 00000000..db7baaa4 --- /dev/null +++ b/cmake/ImportIntoAndroidStudio.cmake @@ -0,0 +1,15 @@ + +function(import_into_android_studio IMPORT_LOCATION) + if(ANDROID AND "${${LIB_NAME}_LIBRARY_TYPE}" STREQUAL "SHARED" AND EXISTS "${IMPORT_LOCATION}") + foreach(lib IN LISTS LIBRARIES_FULL_PATH) + get_filename_component(lib_name "${lib}" NAME) + file(COPY "${lib}" DESTINATION "${IMPORT_LOCATION}") + endforeach() + endif() +endfunction() + +if(NOT IMPORT_LOCATION) + import_into_android_studio("${PROJECT_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}") +else() + import_into_android_studio("${IMPORT_LOCATION}") +endif() diff --git a/cmake/Modules/ABYCacheVariables.cmake b/cmake/Modules/ABYCacheVariables.cmake index e18833ce..85ae27af 100644 --- a/cmake/Modules/ABYCacheVariables.cmake +++ b/cmake/Modules/ABYCacheVariables.cmake @@ -1,6 +1,6 @@ option(ABY_BUILD_EXE "Build executables" OFF) set(ABY_LIBRARY_TYPE "${ABY_LIBRARY_TYPE}" CACHE STRING - "[STATIC | SHARED | MODULE] The type of library in which ABY will be built. Default: SHARED" + "[STATIC | SHARED | MODULE] The type of library in which ABY will be built. Default: STATIC" ) set_property(CACHE ABY_LIBRARY_TYPE PROPERTY STRINGS "STATIC" "SHARED" "MODULE") string(TOUPPER "${ABY_LIBRARY_TYPE}" ABY_LIBRARY_TYPE) @@ -16,11 +16,12 @@ elseif(NOT "${ABY_LIBRARY_TYPE}" STREQUAL "STATIC" AND set(ABY_LIBRARY_TYPE "SHARED") endif() -set(DEPENDENCY_DIR "${DEPENDENCY_DIR}" CACHE PATH - "Path to directory, where dependencies will be downloaded." -) -if("${DEPENDENCY_DIR}" STREQUAL "" AND EXISTS "${PROJECT_SOURCE_DIR}/dependencies") - set(DEPENDENCY_DIR "${PROJECT_SOURCE_DIR}/dependencies") +set(DEPENDENCY_DIR "${DEPENDENCY_DIR}" CACHE PATH "Path to directory, where dependencies will be downloaded.") +if(DEPENDENCY_DIR STREQUAL "") + if(NOT EXISTS "${CMAKE_SOURCE_DIR}/extern/dependencies") + file(MAKE_DIRECTORY "${CMAKE_SOURCE_DIR}/extern/dependencies") + endif() + set(DEPENDENCY_DIR "${CMAKE_SOURCE_DIR}/extern/dependencies") endif() # Set build type to `Release` if none was specified: diff --git a/cmake/Modules/AndroidCacheVariables.cmake b/cmake/Modules/AndroidCacheVariables.cmake index 74e36ed7..a584558f 100644 --- a/cmake/Modules/AndroidCacheVariables.cmake +++ b/cmake/Modules/AndroidCacheVariables.cmake @@ -38,7 +38,7 @@ endif() if(ANDROID) set(CMAKE_TOOLCHAIN_FILE ${ANDROID_TOOLCHAIN_FILE}) endif(ANDROID) -if(ANDROID AND CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) +if(ANDROID AND NOT CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) set(CMAKE_INSTALL_PREFIX "${ANDROID_NDK}" CACHE PATH "Default install directory for android builds." diff --git a/cmake/Modules/ImportSharedLibs.cmake b/cmake/Modules/ImportSharedLibs.cmake new file mode 100644 index 00000000..d5bf8c67 --- /dev/null +++ b/cmake/Modules/ImportSharedLibs.cmake @@ -0,0 +1,16 @@ + + +function(import_shared_libs) + set(DEFAULT_IMPORT_LOCATION "${PROJECT_SOURCE_DIR}/../jniLibs") + if(${ARGC} LESS 1) + set(IMPORT_LOCATION "${DEFAULT_IMPORT_LOCATION}") + else() + set(IMPORT_LOCATION "${ARGV0}") + endif() + if(NOT EXISTS "${IMPORT_LOCATION}") + file(MAKE_DIRECTORY "${IMPORT_LOCATION}") + endif() + foreach(lib IN LISTS SHARED_LIBS) + file(COPY "${lib}" DESTINATION "${IMPORT_LOCATION}") + endforeach() +endfunction() diff --git a/extern/boost-cmake b/extern/boost-cmake deleted file mode 160000 index f0f64add..00000000 --- a/extern/boost-cmake +++ /dev/null @@ -1 +0,0 @@ -Subproject commit f0f64adda5ac1312549056dab502da55b9c45b7b diff --git a/src/abycore/ABY_utils/ABYconstants.h b/src/abycore/ABY_utils/ABYconstants.h index 202823a9..306ed2e2 100644 --- a/src/abycore/ABY_utils/ABYconstants.h +++ b/src/abycore/ABY_utils/ABYconstants.h @@ -2,17 +2,17 @@ \file ABYconstants.h \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2017 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief File containing all ABY constants used throughout the source */ @@ -64,6 +64,10 @@ #define USE_MULTI_MUX_GATES +// default directory containing ABY circuit files. +// can also be passed to ABYParty constructor at runtime +#define ABY_CIRCUIT_DIR "../../bin/circ/" + /** \enum e_role \brief Defines the role of the party or the source / target for certain operations (e.g., input/output) @@ -208,7 +212,7 @@ typedef struct { std::string opname; } aby_ops_t; -static std::string get_circuit_type_name(e_circuit c) { +inline std::string get_circuit_type_name(e_circuit c) { switch(c) { case C_BOOLEAN: return "BOOLEAN"; @@ -219,7 +223,7 @@ static std::string get_circuit_type_name(e_circuit c) { } } -static std::string get_role_name(e_role r) { +inline std::string get_role_name(e_role r) { switch(r) { case SERVER: return "SERVER"; @@ -232,7 +236,7 @@ static std::string get_role_name(e_role r) { } } -static std::string get_sharing_name(e_sharing s) { +inline std::string get_sharing_name(e_sharing s) { switch (s) { case S_BOOL: return "Bool"; @@ -249,7 +253,7 @@ static std::string get_sharing_name(e_sharing s) { } } -static std::string get_gate_type_name(e_gatetype g) { +inline std::string get_gate_type_name(e_gatetype g) { switch (g) { case G_LIN: return "Linear"; case G_NON_LIN: return "Non-Linear"; @@ -279,13 +283,13 @@ typedef enum op_t{ ADD, MUL, SUB, DIV, SIN, SQRT, EXP, EXP2, CMP, LN, LOG2, COS, SQR }op_t; -// Floating point operation cinfiguration. +// Floating point operation cinfiguration. typedef enum fp_op_setting{ ieee, no_status }fp_op_setting; -static std::string get_op_name(e_operation op) { +inline std::string get_op_name(e_operation op) { switch (op) { case OP_XOR: return "XOR"; diff --git a/src/abycore/ABY_utils/yaokey.h b/src/abycore/ABY_utils/yaokey.h index 2b0e9da5..8535795c 100644 --- a/src/abycore/ABY_utils/yaokey.h +++ b/src/abycore/ABY_utils/yaokey.h @@ -2,17 +2,17 @@ \file yaokey.h \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief YaoKey Implementation */ @@ -22,8 +22,8 @@ #include /* an interface to operations on yaos garbled circuits keys for pre-defined symmetric security sizes */ -#define _MSB_UINT64_T 0x80000000000000L -#define _TWO_MSB_UINT64_T 0xC0000000000000L +#define _MSB_uint64_t 0x80000000000000L +#define _TWO_MSB_uint64_t 0xC0000000000000L #define _TWO_MSB_DOWNSHIFT 62 class YaoKey { @@ -45,18 +45,18 @@ class YaoKeyST: public YaoKey { } ; void XOR(BYTE* out, BYTE* ina, BYTE* inb) { - (((UINT64_T*) (out))[0] = ((UINT64_T*) (ina))[0] ^ ((UINT64_T*) (inb))[0]); - (((UINT16_T*) (out))[4] = ((UINT16_T*) (ina))[4] ^ ((UINT16_T*) (inb))[4]); + (((uint64_t*) (out))[0] = ((uint64_t*) (ina))[0] ^ ((uint64_t*) (inb))[0]); + (((uint16_t*) (out))[4] = ((uint16_t*) (ina))[4] ^ ((uint16_t*) (inb))[4]); }; void XOR_DOUBLE_B(BYTE* out, BYTE* ina, BYTE* inb) { - (((UINT64_T*) (out))[0] = ((UINT64_T*) (ina))[0] ^ ((UINT64_T*) (inb))[0]<<1); - ((UINT16_T*) (out))[4] = ((UINT16_T*) (ina))[4] ^ ((((UINT16_T*) (inb))[4]<<1) ^ (!!(((UINT64_T*) (inb))[0] & _MSB_UINT64_T))); + (((uint64_t*) (out))[0] = ((uint64_t*) (ina))[0] ^ ((uint64_t*) (inb))[0]<<1); + ((uint16_t*) (out))[4] = ((uint16_t*) (ina))[4] ^ ((((uint16_t*) (inb))[4]<<1) ^ (!!(((uint64_t*) (inb))[0] & _MSB_uint64_t))); }; void XOR_QUAD_B(BYTE* out, BYTE* ina, BYTE* inb) { - (((UINT64_T*) (out))[0] = ((UINT64_T*) (ina))[0] ^ ((UINT64_T*) (inb))[0]<<2); - ((UINT16_T*) (out))[4] = ((UINT16_T*) (ina))[4] ^ ((((UINT16_T*) (inb))[4]<<2) ^ ((((UINT64_T*) (inb))[0] & _TWO_MSB_UINT64_T))>>_TWO_MSB_DOWNSHIFT); + (((uint64_t*) (out))[0] = ((uint64_t*) (ina))[0] ^ ((uint64_t*) (inb))[0]<<2); + ((uint16_t*) (out))[4] = ((uint16_t*) (ina))[4] ^ ((((uint16_t*) (inb))[4]<<2) ^ ((((uint64_t*) (inb))[0] & _TWO_MSB_uint64_t))>>_TWO_MSB_DOWNSHIFT); }; }; @@ -70,18 +70,18 @@ class YaoKeyMT: public YaoKey { } ; void XOR(BYTE* out, BYTE* ina, BYTE* inb) { - (((UINT64_T*) (out))[0] = ((UINT64_T*) (ina))[0] ^ ((UINT64_T*) (inb))[0]); - (((UINT32_T*) (out))[3] = ((UINT32_T*) (ina))[3] ^ ((UINT32_T*) (inb))[3]); + (((uint64_t*) (out))[0] = ((uint64_t*) (ina))[0] ^ ((uint64_t*) (inb))[0]); + (((uint32_t*) (out))[3] = ((uint32_t*) (ina))[3] ^ ((uint32_t*) (inb))[3]); }; void XOR_DOUBLE_B(BYTE* out, BYTE* ina, BYTE* inb) { - (((UINT64_T*) (out))[0] = ((UINT64_T*) (ina))[0] ^ ((UINT64_T*) (inb))[0]<<1); - (((UINT32_T*) (out))[3] = ((UINT32_T*) (ina))[3] ^ ((UINT32_T*) (inb))[3]<<1); - (((UINT32_T*) (out))[3] = ((UINT32_T*) (ina))[3] ^ (((UINT32_T*) (inb))[3]<<1) ^ (!!(((UINT64_T*) (inb))[0] & _MSB_UINT64_T))); + (((uint64_t*) (out))[0] = ((uint64_t*) (ina))[0] ^ ((uint64_t*) (inb))[0]<<1); + (((uint32_t*) (out))[3] = ((uint32_t*) (ina))[3] ^ ((uint32_t*) (inb))[3]<<1); + (((uint32_t*) (out))[3] = ((uint32_t*) (ina))[3] ^ (((uint32_t*) (inb))[3]<<1) ^ (!!(((uint64_t*) (inb))[0] & _MSB_uint64_t))); }; void XOR_QUAD_B(BYTE* out, BYTE* ina, BYTE* inb) { - (((UINT64_T*) (out))[0] = ((UINT64_T*) (ina))[0] ^ ((UINT64_T*) (inb))[0]<<2); - //(((UINT32_T*) (out))[3] = ((UINT32_T*) (ina))[3] ^ ((UINT32_T*) (inb))[3]<<2); - (((UINT32_T*) (out))[3] = ((UINT32_T*) (ina))[3] ^ (((UINT32_T*) (inb))[3]<<2) ^ ((((UINT64_T*) (inb))[0] & _TWO_MSB_UINT64_T))>>_TWO_MSB_DOWNSHIFT); + (((uint64_t*) (out))[0] = ((uint64_t*) (ina))[0] ^ ((uint64_t*) (inb))[0]<<2); + //(((uint32_t*) (out))[3] = ((uint32_t*) (ina))[3] ^ ((uint32_t*) (inb))[3]<<2); + (((uint32_t*) (out))[3] = ((uint32_t*) (ina))[3] ^ (((uint32_t*) (inb))[3]<<2) ^ ((((uint64_t*) (inb))[0] & _TWO_MSB_uint64_t))>>_TWO_MSB_DOWNSHIFT); }; }; class YaoKeyLT: public YaoKey { @@ -91,16 +91,16 @@ class YaoKeyLT: public YaoKey { } ; void XOR(BYTE* out, BYTE* ina, BYTE* inb) { - (((UINT64_T*) (out))[0] = ((UINT64_T*) (ina))[0] ^ ((UINT64_T*) (inb))[0]); - (((UINT64_T*) (out))[1] = ((UINT64_T*) (ina))[1] ^ ((UINT64_T*) (inb))[1]); + (((uint64_t*) (out))[0] = ((uint64_t*) (ina))[0] ^ ((uint64_t*) (inb))[0]); + (((uint64_t*) (out))[1] = ((uint64_t*) (ina))[1] ^ ((uint64_t*) (inb))[1]); }; void XOR_DOUBLE_B(BYTE* out, BYTE* ina, BYTE* inb) { - (((UINT64_T*) (out))[0] = ((UINT64_T*) (ina))[0] ^ ((UINT64_T*) (inb))[0]<<1); - (((UINT64_T*) (out))[1] = ((UINT64_T*) (ina))[1] ^ (((UINT64_T*) (inb))[1]<<1) ^ (!!(((UINT64_T*) (inb))[0] & _MSB_UINT64_T))); + (((uint64_t*) (out))[0] = ((uint64_t*) (ina))[0] ^ ((uint64_t*) (inb))[0]<<1); + (((uint64_t*) (out))[1] = ((uint64_t*) (ina))[1] ^ (((uint64_t*) (inb))[1]<<1) ^ (!!(((uint64_t*) (inb))[0] & _MSB_uint64_t))); }; void XOR_QUAD_B(BYTE* out, BYTE* ina, BYTE* inb) { - (((UINT64_T*) (out))[0] = ((UINT64_T*) (ina))[0] ^ ((UINT64_T*) (inb))[0]<<2); - (((UINT64_T*) (out))[1] = ((UINT64_T*) (ina))[1] ^ (((UINT64_T*) (inb))[1]<<2) ^ ((((UINT64_T*) (inb))[0] & _TWO_MSB_UINT64_T))>>_TWO_MSB_DOWNSHIFT); + (((uint64_t*) (out))[0] = ((uint64_t*) (ina))[0] ^ ((uint64_t*) (inb))[0]<<2); + (((uint64_t*) (out))[1] = ((uint64_t*) (ina))[1] ^ (((uint64_t*) (inb))[1]<<2) ^ ((((uint64_t*) (inb))[0] & _TWO_MSB_uint64_t))>>_TWO_MSB_DOWNSHIFT); }; }; @@ -111,21 +111,21 @@ class YaoKeyXLT: public YaoKey { } ; void XOR(BYTE* out, BYTE* ina, BYTE* inb) { - (((UINT64_T*) (out))[0] = ((UINT64_T*) (ina))[0] ^ ((UINT64_T*) (inb))[0]); - (((UINT64_T*) (out))[1] = ((UINT64_T*) (ina))[1] ^ ((UINT64_T*) (inb))[1]); - (((UINT64_T*) (out))[2] = ((UINT64_T*) (ina))[2] ^ ((UINT64_T*) (inb))[2]); + (((uint64_t*) (out))[0] = ((uint64_t*) (ina))[0] ^ ((uint64_t*) (inb))[0]); + (((uint64_t*) (out))[1] = ((uint64_t*) (ina))[1] ^ ((uint64_t*) (inb))[1]); + (((uint64_t*) (out))[2] = ((uint64_t*) (ina))[2] ^ ((uint64_t*) (inb))[2]); }; void XOR_DOUBLE_B(BYTE* out, BYTE* ina, BYTE* inb) { - (((UINT64_T*) (out))[0] = ((UINT64_T*) (ina))[0] ^ ((UINT64_T*) (inb))[0]<<1); - (((UINT64_T*) (out))[1] = ((UINT64_T*) (ina))[1] ^ (((UINT64_T*) (inb))[1]<<1) ^ (!!(((UINT64_T*) (inb))[0] & _MSB_UINT64_T))); - (((UINT64_T*) (out))[2] = ((UINT64_T*) (ina))[2] ^ (((UINT64_T*) (inb))[2]<<1) ^ (!!(((UINT64_T*) (inb))[1] & _MSB_UINT64_T))); + (((uint64_t*) (out))[0] = ((uint64_t*) (ina))[0] ^ ((uint64_t*) (inb))[0]<<1); + (((uint64_t*) (out))[1] = ((uint64_t*) (ina))[1] ^ (((uint64_t*) (inb))[1]<<1) ^ (!!(((uint64_t*) (inb))[0] & _MSB_uint64_t))); + (((uint64_t*) (out))[2] = ((uint64_t*) (ina))[2] ^ (((uint64_t*) (inb))[2]<<1) ^ (!!(((uint64_t*) (inb))[1] & _MSB_uint64_t))); }; void XOR_QUAD_B(BYTE* out, BYTE* ina, BYTE* inb) { - (((UINT64_T*) (out))[0] = ((UINT64_T*) (ina))[0] ^ ((UINT64_T*) (inb))[0]<<2); - (((UINT64_T*) (out))[1] = ((UINT64_T*) (ina))[1] ^ (((UINT64_T*) (inb))[1]<<2) ^ ((((UINT64_T*) (inb))[0] & _TWO_MSB_UINT64_T))>>_TWO_MSB_DOWNSHIFT); - (((UINT64_T*) (out))[2] = ((UINT64_T*) (ina))[2] ^ (((UINT64_T*) (inb))[2]<<2) ^ ((((UINT64_T*) (inb))[1] & _TWO_MSB_UINT64_T))>>_TWO_MSB_DOWNSHIFT); + (((uint64_t*) (out))[0] = ((uint64_t*) (ina))[0] ^ ((uint64_t*) (inb))[0]<<2); + (((uint64_t*) (out))[1] = ((uint64_t*) (ina))[1] ^ (((uint64_t*) (inb))[1]<<2) ^ ((((uint64_t*) (inb))[0] & _TWO_MSB_uint64_t))>>_TWO_MSB_DOWNSHIFT); + (((uint64_t*) (out))[2] = ((uint64_t*) (ina))[2] ^ (((uint64_t*) (inb))[2]<<2) ^ ((((uint64_t*) (inb))[1] & _TWO_MSB_uint64_t))>>_TWO_MSB_DOWNSHIFT); }; }; @@ -136,26 +136,26 @@ class YaoKeyXXLT: public YaoKey { } ; void XOR(BYTE* out, BYTE* ina, BYTE* inb) { - (((UINT64_T*) (out))[0] = ((UINT64_T*) (ina))[0] ^ ((UINT64_T*) (inb))[0]); - (((UINT64_T*) (out))[1] = ((UINT64_T*) (ina))[1] ^ ((UINT64_T*) (inb))[1]); - (((UINT64_T*) (out))[2] = ((UINT64_T*) (ina))[2] ^ ((UINT64_T*) (inb))[2]); - (((UINT64_T*) (out))[3] = ((UINT64_T*) (ina))[3] ^ ((UINT64_T*) (inb))[3]); + (((uint64_t*) (out))[0] = ((uint64_t*) (ina))[0] ^ ((uint64_t*) (inb))[0]); + (((uint64_t*) (out))[1] = ((uint64_t*) (ina))[1] ^ ((uint64_t*) (inb))[1]); + (((uint64_t*) (out))[2] = ((uint64_t*) (ina))[2] ^ ((uint64_t*) (inb))[2]); + (((uint64_t*) (out))[3] = ((uint64_t*) (ina))[3] ^ ((uint64_t*) (inb))[3]); }; void XOR_DOUBLE_B(BYTE* out, BYTE* ina, BYTE* inb) { - (((UINT64_T*) (out))[0] = ((UINT64_T*) (ina))[0] ^ ((UINT64_T*) (inb))[0]<<1); - (((UINT64_T*) (out))[1] = ((UINT64_T*) (ina))[1] ^ (((UINT64_T*) (inb))[1]<<1) ^ (!!(((UINT64_T*) (inb))[0] & _MSB_UINT64_T))); - (((UINT64_T*) (out))[2] = ((UINT64_T*) (ina))[2] ^ (((UINT64_T*) (inb))[2]<<1) ^ (!!(((UINT64_T*) (inb))[1] & _MSB_UINT64_T))); - (((UINT64_T*) (out))[3] = ((UINT64_T*) (ina))[3] ^ (((UINT64_T*) (inb))[3]<<1) ^ (!!(((UINT64_T*) (inb))[2] & _MSB_UINT64_T))); + (((uint64_t*) (out))[0] = ((uint64_t*) (ina))[0] ^ ((uint64_t*) (inb))[0]<<1); + (((uint64_t*) (out))[1] = ((uint64_t*) (ina))[1] ^ (((uint64_t*) (inb))[1]<<1) ^ (!!(((uint64_t*) (inb))[0] & _MSB_uint64_t))); + (((uint64_t*) (out))[2] = ((uint64_t*) (ina))[2] ^ (((uint64_t*) (inb))[2]<<1) ^ (!!(((uint64_t*) (inb))[1] & _MSB_uint64_t))); + (((uint64_t*) (out))[3] = ((uint64_t*) (ina))[3] ^ (((uint64_t*) (inb))[3]<<1) ^ (!!(((uint64_t*) (inb))[2] & _MSB_uint64_t))); }; void XOR_QUAD_B(BYTE* out, BYTE* ina, BYTE* inb) { - (((UINT64_T*) (out))[0] = ((UINT64_T*) (ina))[0] ^ ((UINT64_T*) (inb))[0]<<2); - (((UINT64_T*) (out))[1] = ((UINT64_T*) (ina))[1] ^ (((UINT64_T*) (inb))[1]<<2) ^ ((((UINT64_T*) (inb))[0] & _TWO_MSB_UINT64_T))>>_TWO_MSB_DOWNSHIFT); - (((UINT64_T*) (out))[2] = ((UINT64_T*) (ina))[2] ^ (((UINT64_T*) (inb))[2]<<2) ^ ((((UINT64_T*) (inb))[1] & _TWO_MSB_UINT64_T))>>_TWO_MSB_DOWNSHIFT); - (((UINT64_T*) (out))[3] = ((UINT64_T*) (ina))[3] ^ (((UINT64_T*) (inb))[3]<<2) ^ ((((UINT64_T*) (inb))[2] & _TWO_MSB_UINT64_T))>>_TWO_MSB_DOWNSHIFT); + (((uint64_t*) (out))[0] = ((uint64_t*) (ina))[0] ^ ((uint64_t*) (inb))[0]<<2); + (((uint64_t*) (out))[1] = ((uint64_t*) (ina))[1] ^ (((uint64_t*) (inb))[1]<<2) ^ ((((uint64_t*) (inb))[0] & _TWO_MSB_uint64_t))>>_TWO_MSB_DOWNSHIFT); + (((uint64_t*) (out))[2] = ((uint64_t*) (ina))[2] ^ (((uint64_t*) (inb))[2]<<2) ^ ((((uint64_t*) (inb))[1] & _TWO_MSB_uint64_t))>>_TWO_MSB_DOWNSHIFT); + (((uint64_t*) (out))[3] = ((uint64_t*) (ina))[3] ^ (((uint64_t*) (inb))[3]<<2) ^ ((((uint64_t*) (inb))[2] & _TWO_MSB_uint64_t))>>_TWO_MSB_DOWNSHIFT); }; }; -static void InitYaoKey(YaoKey** key, int symbits) { +inline void InitYaoKey(YaoKey** key, uint32_t symbits) { if (symbits == ST.symbits) *key = new YaoKeyST(); else if (symbits == MT.symbits) diff --git a/src/abycore/CMakeLists.txt b/src/abycore/CMakeLists.txt index aa709d5c..f157f8ff 100644 --- a/src/abycore/CMakeLists.txt +++ b/src/abycore/CMakeLists.txt @@ -2,11 +2,6 @@ cmake_minimum_required(VERSION 3.13) list(INSERT CMAKE_MODULE_PATH 0 "${CMAKE_CURRENT_LIST_DIR}/cmake/Modules") -include(AddGMP) -include(AddBoost) -include(AddOTExtension) -find_package(Threads REQUIRED) - set(INSTALL_NAME ${PROJECT_NAME}) if(ANDROID) @@ -19,16 +14,23 @@ if(ANDROID) set(ABY_INSTALL_INCLUDE "${ABY_INSTALL_PREFIX}/include") set(ABY_INSTALL_LIB "${ABY_INSTALL_PREFIX}/lib") set(ABY_INSTALL_ARCHIVE "${ABY_INSTALL_PREFIX}/lib") - set(ABY_INSTALL_CONFIG "sysroot/share/cmake") + set(ABY_INSTALL_CONFIG "usr/local") else(ANDROID) set(INSTALL_BOOST_DEPENDENCIES FALSE) set(ABY_INSTALL_PREFIX "") set(ABY_INSTALL_INCLUDE "include") set(ABY_INSTALL_LIB "lib") set(ABY_INSTALL_ARCHIVE "lib") - set(ABY_INSTALL_CONFIG "share/cmake") + set(ABY_INSTALL_CONFIG "usr/local") endif(ANDROID) + +include(AddGMP) +include(AddBoost) +include(AddENCRYPTO_utils) +include(AddOTExtension) +find_package(Threads REQUIRED) + add_library(aby ${ABY_LIBRARY_TYPE} aby/abyparty.cpp aby/abysetup.cpp @@ -49,7 +51,6 @@ add_library(aby ${ABY_LIBRARY_TYPE} ) add_library(ABY::aby ALIAS aby) -target_compile_features(aby PUBLIC cxx_std_14) #target_compile_options(aby PRIVATE "-Wall" "-Wextra" "-Weffc++") target_compile_options(aby PRIVATE "-Wall" "-Wextra") @@ -64,22 +65,21 @@ target_link_libraries(aby PUBLIC ENCRYPTO_utils::encrypto_utils PUBLIC GMP::GMP PUBLIC Threads::Threads - PRIVATE Boost::boost Boost::filesystem + PRIVATE Boost::filesystem ) if(INSTALL_BOOST_DEPENDENCIES) set_target_properties(Boost_filesystem PROPERTIES EXCLUDE_FROM_ALL 0) - set(ABY_TARGETS aby Boost_filesystem) + set(ABY_TARGETS aby) + set(ABY_DEPENDENCIES Boost_filesystem Boost::boost) else() set(ABY_TARGETS aby) endif() - - include(InstallConfig) install_config(ABY_INSTALL_LOCATION "${PROJECT_NAME}" "${ABY_INSTALL_CONFIG}") -install(TARGETS ${ABY_TARGETS} +install(TARGETS ${ABY_TARGETS} ${ABY_DEPENDENCIES} EXPORT "${INSTALL_NAME}Targets" ARCHIVE DESTINATION "${ABY_INSTALL_LIB}" LIBRARY DESTINATION "${ABY_INSTALL_LIB}" @@ -93,6 +93,9 @@ export(TARGETS ${ABY_TARGETS} NAMESPACE "${INSTALL_NAME}::" FILE "${INSTALL_NAME}Targets.cmake" ) +export(TARGETS ${ABY_DEPENDENCIES} + APPEND FILE "${INSTALL_NAME}Targets.cmake" +) install(EXPORT "${INSTALL_NAME}Targets" NAMESPACE "${INSTALL_NAME}::" DESTINATION "${ABY_INSTALL_LOCATION}" diff --git a/src/abycore/DGK/dgkparty.cpp b/src/abycore/DGK/dgkparty.cpp index d14269f1..4c6e2477 100644 --- a/src/abycore/DGK/dgkparty.cpp +++ b/src/abycore/DGK/dgkparty.cpp @@ -2,41 +2,34 @@ \file dgkparty.cpp \author daniel.demmler@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief DGKParty implementation */ #include "dgkparty.h" -#include -#include - -#define CHECKMT 0 -#define DGK_DEBUG 0 -#define NETDEBUG 0 -#define WINDOWSIZE 65536 //maximum size of a network packet in Byte /** * initializes a DGK_Party with the asymmetric security parameter and the sharelength and exchanges public keys. * @param mode - 0 = generate new key; 1 = read key */ -DGKParty::DGKParty(UINT DGKbits, UINT sharelen, channel* chan, UINT readkey) { +DGKParty::DGKParty(uint32_t DGKModulusBits, uint32_t shareBitLength, channel* chan, uint32_t readkey) { - m_nShareLength = sharelen; - m_nDGKbits = DGKbits; - m_nBuflen = DGKbits / 8 + 1; //size of one ciphertext to send via network. DGK uses n bits == n/8 bytes + m_nShareBitLength = shareBitLength; + m_nDGKModulusBits = DGKModulusBits; + m_nBuflen = DGKModulusBits / 8 + 1; //size of one ciphertext to send via network. DGK uses n bits == n/8 bytes -#if DEBUG - cout << "Created party with " << DGKbits << " key bits and" << sharelen << " bit shares" << endl; +#if DGK_DEBUG + std::cout << "Created party with " << DGKModulusBits << " key bits and " << shareBitLength << " bit shares" << std::endl; #endif if (readkey) { @@ -53,14 +46,14 @@ DGKParty::DGKParty(UINT DGKbits, UINT sharelen, channel* chan, UINT readkey) { * @param mode - 0 = generate new key; 1 = read key * Public keys must be exchanged manually when using this constructor! */ -DGKParty::DGKParty(UINT DGKbits, UINT sharelen, UINT readkey) { +DGKParty::DGKParty(uint32_t DGKModulusBits, uint32_t shareBitLength, uint32_t readkey) { - m_nShareLength = sharelen; - m_nDGKbits = DGKbits; - m_nBuflen = DGKbits / 8 + 1; //size of one ciphertext to send via network. DGK uses n bits == n/8 bytes + m_nShareBitLength = shareBitLength; + m_nDGKModulusBits = DGKModulusBits; + m_nBuflen = DGKModulusBits / 8 + 1; //size of one ciphertext to send via network. DGK uses n bits == n/8 bytes #if DGK_DEBUG - cout << "Created party with " << DGKbits << " key bits and" << sharelen << " bit shares" << endl; + std::cout << "Created party with " << DGKModulusBits << " key bits and " << shareBitLength << " bit shares" << std::endl; #endif if (readkey) { @@ -72,21 +65,21 @@ DGKParty::DGKParty(UINT DGKbits, UINT sharelen, UINT readkey) { void DGKParty::readKey() { #if DGK_DEBUG - cout << "KeyGen" << endl; + std::cout << "Reading DGK key…" << std::endl; #endif - dgk_readkey(m_nDGKbits, m_nShareLength, &m_localpub, &m_prv); + dgk_readkey(m_nDGKModulusBits, m_nShareBitLength, &m_localpub, &m_prv); #if DGK_DEBUG - cout << "key read." << endl; + std::cout << "key read." << std::endl; #endif } void DGKParty::generateKey() { -#if DEBUG - cout << "KeyGen" << endl; +#if DGK_DEBUG + std::cout << "Generating DKG key…" << std::endl; #endif - dgk_keygen(m_nDGKbits, m_nShareLength, &m_localpub, &m_prv); -#if DEBUG - cout << "key generated." << endl; + dgk_keygen(m_nDGKModulusBits, m_nShareBitLength, &m_localpub, &m_prv); +#if DGK_DEBUG + std::cout << "key generated." << std::endl; #endif } @@ -95,28 +88,27 @@ void DGKParty::generateKey() { */ DGKParty::~DGKParty() { #if DGK_DEBUG - cout << "Deleting DGKParty..." << endl; + std::cout << "Deleting DGKParty…" << std::endl; #endif dgk_freeprvkey(m_prv); dgk_freepubkey(m_localpub); dgk_freepubkey(m_remotepub); - } /** - * inputs pre-allocates byte buffers for aMT calculation. - * numMTs must be the total number of MTs and divisible by 2 + * inputs: pre-allocates byte buffers for aMT calculation. + * numMTs is the total number of MTs */ -void DGKParty::preCompBench(BYTE * bA, BYTE * bB, BYTE * bC, BYTE * bA1, BYTE * bB1, BYTE * bC1, UINT numMTs, channel* chan) { +void DGKParty::computeArithmeticMTs(BYTE * bA, BYTE * bB, BYTE * bC, BYTE * bA1, BYTE * bB1, BYTE * bC1, uint32_t numMTs, channel* chan) { struct timespec start, end; - numMTs = numMTs / 2; // We can be both sender and receiver at the same time. + numMTs = ceil_divide(numMTs, 2); // We can be both sender and receiver at the same time. - UINT shareBytes = m_nShareLength / 8; - UINT offset = 0; + uint32_t shareBytes = m_nShareBitLength / 8; + uint32_t offset = 0; #if DGK_DEBUG - cout << "dgkbits: " << m_nDGKbits << " sharelen: " << m_nShareLength << endl; + std::cout << "DGKModulusBits: " << m_nDGKModulusBits << " shareBitLength: " << m_nShareBitLength << std::endl; #endif mpz_t r, x, y, z; @@ -132,7 +124,7 @@ void DGKParty::preCompBench(BYTE * bA, BYTE * bB, BYTE * bC, BYTE * bA1, BYTE * mpz_t b1[numMTs]; mpz_t c1[numMTs]; - for (UINT i = 0; i < numMTs; i++) { + for (uint32_t i = 0; i < numMTs; i++) { mpz_inits(a[i], b[i], c[i], a1[i], b1[i], c1[i], NULL); } @@ -144,7 +136,7 @@ void DGKParty::preCompBench(BYTE * bA, BYTE * bB, BYTE * bC, BYTE * bA1, BYTE * clock_gettime(CLOCK_MONOTONIC, &start); // read server a,b shares and encrypt them into buffer - for (UINT i = 0; i < numMTs; i++) { + for (uint32_t i = 0; i < numMTs; i++) { mpz_import(x, 1, 1, shareBytes, 0, 0, bA + i * shareBytes); mpz_import(y, 1, 1, shareBytes, 0, 0, bB + i * shareBytes); @@ -156,7 +148,7 @@ void DGKParty::preCompBench(BYTE * bA, BYTE * bB, BYTE * bC, BYTE * bA1, BYTE * } // send & receive encrypted values - int window = WINDOWSIZE; + int window = DGK_WINDOWSIZE; int tosend = m_nBuflen * numMTs; offset = 0; @@ -180,7 +172,7 @@ void DGKParty::preCompBench(BYTE * bA, BYTE * bB, BYTE * bC, BYTE * bA1, BYTE * offset = 0; //read shares from client byte arrays - for (UINT j = 0; j < numMTs; j++) { + for (uint32_t j = 0; j < numMTs; j++) { mpz_import(a1[j], 1, 1, shareBytes, 0, 0, bA1 + offset); mpz_import(b1[j], 1, 1, shareBytes, 0, 0, bB1 + offset); @@ -190,7 +182,7 @@ void DGKParty::preCompBench(BYTE * bA, BYTE * bB, BYTE * bC, BYTE * bA1, BYTE * dbpowmod(c1[j], x, b1[j], y, a1[j], m_remotepub->n); // pick random r for masking - aby_prng(x, 2 * m_nShareLength + 1); + aby_prng(x, 2 * m_nShareBitLength + 1); dgk_encrypt_fb(y, m_remotepub, x); @@ -201,7 +193,7 @@ void DGKParty::preCompBench(BYTE * bA, BYTE * bB, BYTE * bC, BYTE * bA1, BYTE * mpz_mul(c1[j], a1[j], b1[j]); //c = a * b mpz_sub(c1[j], c1[j], x); // c = c - x - mpz_mod_2exp(c1[j], c1[j], m_nShareLength); // c = c mod 2^shareLength + mpz_mod_2exp(c1[j], c1[j], m_nShareBitLength); // c = c mod 2^shareLength mpz_export(bC1 + offset, NULL, 1, shareBytes, 0, 0, c1[j]); @@ -211,7 +203,7 @@ void DGKParty::preCompBench(BYTE * bA, BYTE * bB, BYTE * bC, BYTE * bA1, BYTE * // ----------------############# ###############----------------------- // all packets packed. exchange these packets - window = WINDOWSIZE; + window = DGK_WINDOWSIZE; tosend = m_nBuflen * numMTs; offset = 0; @@ -229,7 +221,7 @@ void DGKParty::preCompBench(BYTE * bA, BYTE * bB, BYTE * bC, BYTE * bA1, BYTE * offset = 0; - for (UINT i = 0; i < numMTs; i++) { + for (uint32_t i = 0; i < numMTs; i++) { mpz_import(r, m_nBuflen, -1, 1, 1, 0, zbuf + i * m_nBuflen); dgk_decrypt(r, m_localpub, m_prv, r); @@ -237,16 +229,17 @@ void DGKParty::preCompBench(BYTE * bA, BYTE * bB, BYTE * bC, BYTE * bA1, BYTE * mpz_import(a[i], 1, 1, shareBytes, 0, 0, bA + offset); mpz_import(b[i], 1, 1, shareBytes, 0, 0, bB + offset); - mpz_mod_2exp(c[i], r, m_nShareLength); // c = x mod 2^shareLength == read the share from least significant bits + mpz_mod_2exp(c[i], r, m_nShareBitLength); // c = x mod 2^shareLength == read the share from least significant bits mpz_addmul(c[i], a[i], b[i]); //c = a*b + c - mpz_mod_2exp(c[i], c[i], m_nShareLength); // c = c mod 2^shareLength + mpz_mod_2exp(c[i], c[i], m_nShareBitLength); // c = c mod 2^shareLength mpz_export(bC + offset, NULL, 1, shareBytes, 0, 0, c[i]); offset += shareBytes; } -#if CHECKMT - cout << "Checking MT validity with values from other party:" << endl; +#if DGK_CHECKMT + //TODO: This overwrites generated MTs and should be put in a separate function. + std::cout << "Checking MT validity with values from other party:" << std::endl; mpz_t ai, bi, ci, ai1, bi1, ci1, ta, tb; mpz_inits(ai, bi, ci, ai1, bi1, ci1, ta, tb, NULL); @@ -258,7 +251,7 @@ void DGKParty::preCompBench(BYTE * bA, BYTE * bB, BYTE * bC, BYTE * bA1, BYTE * chan->send(bC, numMTs * shareBytes); chan->blocking_receive(bC, numMTs * shareBytes); - for (UINT i = 0; i < numMTs; i++) { + for (uint32_t i = 0; i < numMTs; i++) { mpz_import(ai, 1, 1, shareBytes, 0, 0, bA + i * shareBytes); mpz_import(bi, 1, 1, shareBytes, 0, 0, bB + i * shareBytes); @@ -272,25 +265,27 @@ void DGKParty::preCompBench(BYTE * bA, BYTE * bB, BYTE * bC, BYTE * bA1, BYTE * mpz_add(tb, bi, bi1); mpz_mul(ta, ta, tb); mpz_add(tb, ci, ci1); - mpz_mod_2exp(ta, ta, m_nShareLength); - mpz_mod_2exp(tb, tb, m_nShareLength); + mpz_mod_2exp(ta, ta, m_nShareBitLength); + mpz_mod_2exp(tb, tb, m_nShareBitLength); if (mpz_cmp(ta, tb) == 0) { - cout << "MT is fine - i:" << i << "| " << ai << " " << bi << " " << ci << " . " << ai1 << " " << bi1 << " " << ci1 << endl; + std::cout << "MT is fine - i:" << i << "| " << ai << " " << bi << " " << ci << " . " << ai1 << " " << bi1 << " " << ci1 << std::endl; } else { - cout << "Error in MT - i:" << i << "| " << ai << " " << bi << " " << ci << " . " << ai1 << " " << bi1 << " " << ci1 << endl; + std::cout << "Error in MT - i:" << i << "| " << ai << " " << bi << " " << ci << " . " << ai1 << " " << bi1 << " " << ci1 << std::endl; } - - //cout << (mpz_cmp(c1[i], a1[i]) == 0 ? "MT is fine." : "Error in MT!") << endl; + //cout << (mpz_cmp(c1[i], a1[i]) == 0 ? "MT is fine." : "Error in MT!") << std::endl; } mpz_clears(ai, bi, ci, ai1, bi1, ci1, ta, tb, NULL); #endif clock_gettime(CLOCK_MONOTONIC, &end); + +#if DGK_BENCH printf("generating 2x %u MTs took %f\n", numMTs, getMillies(start, end)); +#endif //clean up after ourselves - for (UINT i = 0; i < numMTs; i++) { + for (uint32_t i = 0; i < numMTs; i++) { mpz_clears(a[i], b[i], c[i], a1[i], b1[i], c1[i], NULL); } @@ -318,17 +313,17 @@ void DGKParty::keyExchange(channel* chan) { receivempz_t(g, chan); //g receivempz_t(h, chan); //h - dgk_complete_pubkey(m_nDGKbits, m_nShareLength, &m_remotepub, n, g, h); + dgk_complete_pubkey(m_nDGKModulusBits, m_nShareBitLength, &m_remotepub, n, g, h); // pre calculate table for fixed-base exponentiation for client - fbpowmod_init_g(m_remotepub->g, m_remotepub->n, 2 * m_nShareLength + 2); + fbpowmod_init_g(m_remotepub->g, m_remotepub->n, 2 * m_nShareBitLength + 2); fbpowmod_init_h(m_remotepub->h, m_remotepub->n, 400); // 2.5 * t = 2.5 * 160 = 400 bit //free a and b mpz_clears(n, g, h, NULL); -#if DEBUG - cout << "KX done. This pubkey: " << m_localpub->n << " remotekey: " << m_remotepub->n << endl; +#if DGK_DEBUG + std::cout << "KX done. Local pubkey: " << m_localpub->n << " remote pubkey: " << m_remotepub->n << std::endl; #endif } @@ -338,12 +333,12 @@ void DGKParty::keyExchange(channel* chan) { void DGKParty::sendmpz_t(mpz_t t, channel* chan, BYTE * buf) { //clear upper bytes of the buffer, so tailing bytes are zero - for (int i = mpz_sizeinbase(t, 256); i < m_nBuflen; i++) { + for (uint32_t i = mpz_sizeinbase(t, 256); i < m_nBuflen; i++) { *(buf + i) = 0; } -#if NETDEBUG - cout << mpz_sizeinbase(t, 256) << " vs. " << m_nBuflen << endl; +#if DGK_NETDEBUG + std::cout << mpz_sizeinbase(t, 256) << " vs. " << m_nBuflen << std::endl; #endif mpz_export(buf, NULL, -1, 1, 1, 0, t); @@ -351,13 +346,13 @@ void DGKParty::sendmpz_t(mpz_t t, channel* chan, BYTE * buf) { //send bytes of t chan->send(buf, (uint64_t) m_nBuflen); -#if NETDEBUG - cout << endl << "SEND" << endl; - for (int i = 0; i < m_nBuflen; i++) { +#if DGK_NETDEBUG + std::cout << std::endl << "SEND" << std::endl; + for (uint32_t i = 0; i < m_nBuflen; i++) { printf("%02x.", *(buf + i)); } - cout << endl << "sent: " << t << " with len: " << m_nBuflen << " should have been " << mpz_sizeinbase(t, 256) << endl; + std::cout << std::endl << "sent: " << t << " with len: " << m_nBuflen << " should have been " << mpz_sizeinbase(t, 256) << std::endl; #endif } @@ -368,13 +363,13 @@ void DGKParty::receivempz_t(mpz_t t, channel* chan, BYTE * buf) { chan->blocking_receive(buf, (uint64_t) m_nBuflen); mpz_import(t, m_nBuflen, -1, 1, 1, 0, buf); -#if NETDEBUG - cout << endl << "RECEIVE" << endl; - for (int i = 0; i < m_nBuflen; i++) { +#if DGK_NETDEBUG + std::cout << std::endl << "RECEIVE" << std::endl; + for (uint32_t i = 0; i < m_nBuflen; i++) { printf("%02x.", *(buf + i)); } - cout << "received: " << t << " with len: " << m_nBuflen << endl; + std::cout << "received: " << t << " with len: " << m_nBuflen << std::endl; #endif } @@ -393,8 +388,8 @@ void DGKParty::sendmpz_t(mpz_t t, channel* chan) { chan->send(arr, (uint64_t) bytelen); free(arr); -#if NETDEBUG - cout << "sent: " << t << " with len: " << bytelen << endl; +#if DGK_NETDEBUG + std::cout << "sent: " << t << " with len: " << bytelen << std::endl; #endif } @@ -413,25 +408,25 @@ void DGKParty::receivempz_t(mpz_t t, channel* chan) { mpz_import(t, bytelen, 1, 1, 1, 0, arr); free(arr); -#if NETDEBUG - cout << "received: " << t << " with len: " << bytelen << endl; +#if DGK_NETDEBUG + std::cout << "received: " << t << " with len: " << bytelen << std::endl; #endif } #if DEBUG -void DGKParty::printBuf(BYTE* b, UINT len) { - for (UINT i = 0; i < len; i++) { +void DGKParty::printBuf(BYTE* b, uint32_t len) { + for (uint32_t i = 0; i < len; i++) { printf("%02x.", *(b + i)); } - cout << endl; + std::cout << std::endl; } #endif /** * reads a new key from disk (to be used when parameters change) */ -void DGKParty::loadNewKey(UINT DGKbits, UINT sharelen) { - m_nDGKbits = DGKbits; - m_nShareLength = sharelen; - dgk_readkey(m_nDGKbits, m_nShareLength, &m_localpub, &m_prv); +void DGKParty::loadNewKey(uint32_t DGKModulusBits, uint32_t shareBitLength) { + m_nDGKModulusBits = DGKModulusBits; + m_nShareBitLength = shareBitLength; + dgk_readkey(m_nDGKModulusBits, m_nShareBitLength, &m_localpub, &m_prv); } diff --git a/src/abycore/DGK/dgkparty.h b/src/abycore/DGK/dgkparty.h index 9634af12..a749a391 100644 --- a/src/abycore/DGK/dgkparty.h +++ b/src/abycore/DGK/dgkparty.h @@ -2,23 +2,29 @@ \file dgkparty.h \author daniel.demmler@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief DGKParty */ #ifndef __DGKPARTY_H__ #define __DGKPARTY_H__ +#define DGK_CHECKMT 0 +#define DGK_DEBUG 0 +#define DGK_BENCH 0 +#define DGK_NETDEBUG 0 +#define DGK_WINDOWSIZE 65536 //maximum size of a network packet in Byte + #include #include #include @@ -26,34 +32,39 @@ #include #include #include +#include +#include +#if DGK_DEBUG || DGK_BENCH +#include +#endif class DGKParty { public: - DGKParty(UINT DGKbits, UINT sharelen, UINT readkey); - DGKParty(UINT DGKbits, UINT sharelen, channel* chan, UINT readkey); + DGKParty(uint32_t DGKModulusBits, uint32_t shareBitLength, uint32_t readkey); + DGKParty(uint32_t DGKModulusBits, uint32_t shareBitLength, channel* chan, uint32_t readkey); ~DGKParty(); void keyExchange(channel* chan); - void preCompBench(BYTE * bA, BYTE * bB, BYTE * bC, BYTE * bA1, BYTE * bB1, BYTE * bC1, UINT numMTs, channel* chan); + void computeArithmeticMTs(BYTE * bA, BYTE * bB, BYTE * bC, BYTE * bA1, BYTE * bB1, BYTE * bC1, uint32_t numMTs, channel* chan); void readKey(); void generateKey(); - void loadNewKey(UINT DGKbits, UINT sharelen); + void loadNewKey(uint32_t DGKModulusBits, uint32_t shareBitLength); private: - USHORT m_nNumMTThreads; - USHORT m_nShareLength; - UINT m_nDGKbits; - UINT m_nBuflen; + uint16_t m_nNumMTThreads; + uint16_t m_nShareBitLength; + uint32_t m_nDGKModulusBits; + uint32_t m_nBuflen; // Crypto and GMP PRNG dgk_pubkey_t *m_localpub, *m_remotepub; dgk_prvkey_t *m_prv; - void benchPreCompPacking1(channel* chan, BYTE * buf, UINT packlen, UINT numshares, mpz_t * a, mpz_t * b, mpz_t * c, mpz_t * a1, mpz_t * b1, mpz_t * c1, mpz_t r, mpz_t x, + void benchPreCompPacking1(channel* chan, BYTE * buf, uint32_t packlen, uint32_t numshares, mpz_t * a, mpz_t * b, mpz_t * c, mpz_t * a1, mpz_t * b1, mpz_t * c1, mpz_t r, mpz_t x, mpz_t y, mpz_t z); void sendmpz_t(mpz_t t, channel* chan, BYTE * buf); @@ -62,8 +73,7 @@ class DGKParty { void sendmpz_t(mpz_t t, channel* chan); void receivempz_t(mpz_t t, channel* chan); - void printBuf(BYTE* b, UINT l); - + void printBuf(BYTE* b, uint32_t l); }; #endif //__DGK_PARTY_H__ diff --git a/src/abycore/DJN/djnparty.cpp b/src/abycore/DJN/djnparty.cpp index bf852901..aa66dedf 100644 --- a/src/abycore/DJN/djnparty.cpp +++ b/src/abycore/DJN/djnparty.cpp @@ -2,57 +2,49 @@ \file djnparty.cpp \author daniel.demmler@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Implementation of DJNParty class */ #include "djnparty.h" -#include -#include - -#define CHECKMT 0 -#define DJN_DEBUG 0 -#define NETDEBUG 0 -#define NETDEBUG2 0 -#define WINDOWSIZE 65536//maximum size of a network packet in Byte /** - * initializes a DJN_Party with the asymmetric security parameter and the sharelength. + * initializes a DJN_Party with the asymmetric security parameter and the shareBitLength. * Generates DJN key. * Key Exchange must be done manually after calling this constructor! */ -DJNParty::DJNParty(UINT DJNbits, UINT sharelen, channel* chan) { +DJNParty::DJNParty(uint32_t DJNModulusBits, uint32_t shareBitLength, channel* chan) { - m_nShareLength = sharelen; - m_nDJNbits = DJNbits; - m_nBuflen = DJNbits / 4 + 1; + m_nShareBitLength = shareBitLength; + m_nDJNModulusBits = DJNModulusBits; + m_nBuflen = DJNModulusBits / 4 + 1; #if DJN_DEBUG - std::cout << "(sock) Created party with " << DJNbits << " bits and" << m_nBuflen << std::endl; + std::cout << "(sock) Created party with " << DJNModulusBits << " bits and" << m_nBuflen << std::endl; #endif keyGen(); keyExchange(chan); } -DJNParty::DJNParty(UINT DJNbits, UINT sharelen) { +DJNParty::DJNParty(uint32_t DJNModulusBits, uint32_t shareBitLength) { - m_nShareLength = sharelen; - m_nDJNbits = DJNbits; - m_nBuflen = DJNbits / 4 + 1; + m_nShareBitLength = shareBitLength; + m_nDJNModulusBits = DJNModulusBits; + m_nBuflen = DJNModulusBits / 4 + 1; #if DJN_DEBUG - std::cout << "(nosock) Created party with " << DJNbits << " bits and" << m_nBuflen << std::endl; + std::cout << "(nosock) Created party with " << DJNModulusBits << " bits and" << m_nBuflen << std::endl; #endif keyGen(); @@ -62,11 +54,11 @@ void DJNParty::keyGen() { #if DJN_DEBUG std::cout << "KG" << std::endl; #endif - djn_keygen(m_nDJNbits, &m_localpub, &m_prv); + djn_keygen(m_nDJNModulusBits, &m_localpub, &m_prv); } -void DJNParty::setSharelLength(UINT sharelen) { - m_nShareLength = sharelen; +void DJNParty::setShareBitLength(uint32_t shareBitLength) { + m_nShareBitLength = shareBitLength; } /** @@ -79,28 +71,26 @@ DJNParty::~DJNParty() { djn_freeprvkey(m_prv); djn_freepubkey(m_localpub); djn_freepubkey(m_remotepub); - } /** - * inputs pre-allocates byte buffers for aMT calculation. - * numMTs must be the total number of MTs and divisible by 2 + * inputs: pre-allocates byte buffers for aMT calculation. + * numMTs is total number of MTs */ -void DJNParty::preCompBench(BYTE * bA, BYTE * bB, BYTE * bC, BYTE * bA1, BYTE * bB1, BYTE * bC1, UINT numMTs, channel* chan) { +void DJNParty::computeArithmeticMTs(BYTE * bA, BYTE * bB, BYTE * bC, BYTE * bA1, BYTE * bB1, BYTE * bC1, uint32_t numMTs, channel* chan) { struct timespec start, end; + numMTs = ceil_divide(numMTs, 2); // We can be both sender and receiver at the same time. - numMTs = numMTs / 2; // We can be both sender and receiver at the same time. - - UINT maxShareLen = 2 * m_nShareLength + 41; // length of one share in the packet, sigma = 40 - UINT packshares = m_nDJNbits / maxShareLen; // number of shares in one packet - UINT numpacks = (numMTs + packshares - 1) / packshares; // total number of packets to send in order to generate numMTs = CEIL(numMTs/2*numshares) + uint32_t maxShareBitLength = 2 * m_nShareBitLength + 41; // length of one share in the packet, sigma = 40 + uint32_t packshares = m_nDJNModulusBits / maxShareBitLength; // number of shares in one packet + uint32_t numpacks = ceil_divide(numMTs, packshares); // total number of packets to send in order to generate numMTs - UINT shareBytes = m_nShareLength / 8; - UINT offset = 0; - UINT limit = packshares; // upper bound for a package shares, used to handle non-full last packages / alignment + uint32_t shareBytes = m_nShareBitLength / 8; + uint32_t offset = 0; + uint32_t limit = packshares; // upper bound for a package shares, used to handle non-full last packages / alignment #if DJN_DEBUG - std::cout << "djnbits: " << m_nDJNbits << " sharelen: " << m_nShareLength << " packlen: " << maxShareLen << " numshares: " << packshares << " numpacks: " << numpacks << std::endl; + std::cout << "DJNModulusBits: " << m_nDJNModulusBits << " ShareBitLength: " << m_nShareBitLength << " packlen: " << maxShareBitLength << " numshares: " << packshares << " numpacks: " << numpacks << std::endl; #endif mpz_t r, x, y, z; @@ -116,7 +106,7 @@ void DJNParty::preCompBench(BYTE * bA, BYTE * bB, BYTE * bC, BYTE * bA1, BYTE * mpz_t b1[packshares]; mpz_t c1[packshares]; - for (UINT i = 0; i < packshares; i++) { + for (uint32_t i = 0; i < packshares; i++) { mpz_inits(a[i], b[i], c[i], a1[i], b1[i], c1[i], NULL); } @@ -128,7 +118,7 @@ void DJNParty::preCompBench(BYTE * bA, BYTE * bB, BYTE * bC, BYTE * bA1, BYTE * clock_gettime(CLOCK_MONOTONIC, &start); // read server a,b shares and encrypt them into buffer - for (UINT i = 0; i < numMTs; i++) { + for (uint32_t i = 0; i < numMTs; i++) { mpz_import(x, 1, 1, shareBytes, 0, 0, bA + i * shareBytes); mpz_import(y, 1, 1, shareBytes, 0, 0, bB + i * shareBytes); @@ -140,7 +130,7 @@ void DJNParty::preCompBench(BYTE * bA, BYTE * bB, BYTE * bC, BYTE * bA1, BYTE * } // send & receive encrypted values - int window = WINDOWSIZE; + int window = DJN_WINDOWSIZE; int tosend = m_nBuflen * numMTs; offset = 0; @@ -162,14 +152,14 @@ void DJNParty::preCompBench(BYTE * bA, BYTE * bB, BYTE * bC, BYTE * bA1, BYTE * // pack ALL the packets offset = 0; - for (UINT i = 0; i < numpacks; i++) { + for (uint32_t i = 0; i < numpacks; i++) { if (i == numpacks - 1) { limit = numMTs % packshares; // if last package, only fill buffers to requested size and discard remaining shares } //read shares from client byte arrays - for (UINT j = 0; j < limit; j++) { + for (uint32_t j = 0; j < limit; j++) { mpz_import(a1[j], 1, 1, shareBytes, 0, 0, bA1 + offset); mpz_import(b1[j], 1, 1, shareBytes, 0, 0, bB1 + offset); @@ -183,7 +173,7 @@ void DJNParty::preCompBench(BYTE * bA, BYTE * bB, BYTE * bC, BYTE * bA1, BYTE * // horner packing of shares into 1 ciphertext mpz_set(z, c1[limit - 1]); mpz_set_ui(y, 0); - mpz_setbit(y, maxShareLen); // y = 2^shareLength, for shifting ciphertext + mpz_setbit(y, maxShareBitLength); // y = 2^ShareBitLength, for shifting ciphertext for (int j = limit - 2; j >= 0; j--) { mpz_powm(z, z, y, m_remotepub->n_squared); @@ -206,14 +196,14 @@ void DJNParty::preCompBench(BYTE * bA, BYTE * bB, BYTE * bC, BYTE * bA1, BYTE * offset -= shareBytes * limit; // calculate c shares for client part - for (UINT j = 0; j < limit; j++) { - mpz_mod_2exp(y, x, m_nShareLength); // y = r mod 2^shareLength == read the share from least significant bits - mpz_div_2exp(x, x, maxShareLen); // r = r >> maxShareLen + for (uint32_t j = 0; j < limit; j++) { + mpz_mod_2exp(y, x, m_nShareBitLength); // y = r mod 2^ShareBitLength == read the share from least significant bits + mpz_div_2exp(x, x, maxShareBitLength); // r = r >> maxShareBitLength mpz_mul(c1[j], a1[j], b1[j]); //c = a * b mpz_sub(c1[j], c1[j], y); // c = c - y - mpz_mod_2exp(c1[j], c1[j], m_nShareLength); // c = c mod 2^shareLength + mpz_mod_2exp(c1[j], c1[j], m_nShareBitLength); // c = c mod 2^ShareBitLength mpz_export(bC1 + offset, NULL, 1, shareBytes, 0, 0, c1[j]); offset += shareBytes; @@ -223,7 +213,7 @@ void DJNParty::preCompBench(BYTE * bA, BYTE * bB, BYTE * bC, BYTE * bA1, BYTE * // ----------------############# ###############----------------------- // all packets packed. exchange these packets - window = WINDOWSIZE; + window = DJN_WINDOWSIZE; tosend = m_nBuflen * numpacks; offset = 0; @@ -241,7 +231,7 @@ void DJNParty::preCompBench(BYTE * bA, BYTE * bB, BYTE * bC, BYTE * bA1, BYTE * limit = packshares; offset = 0; - for (UINT i = 0; i < numpacks; i++) { + for (uint32_t i = 0; i < numpacks; i++) { if (i == numpacks - 1) { limit = numMTs % packshares; // if last package, only fill buffers to requested size and discard remaining shares @@ -251,20 +241,20 @@ void DJNParty::preCompBench(BYTE * bA, BYTE * bB, BYTE * bC, BYTE * bA1, BYTE * djn_decrypt(r, m_localpub, m_prv, r); - for (UINT j = 0; j < limit; j++) { + for (uint32_t j = 0; j < limit; j++) { mpz_import(a[j], 1, 1, shareBytes, 0, 0, bA + offset); mpz_import(b[j], 1, 1, shareBytes, 0, 0, bB + offset); - mpz_mod_2exp(c[j], r, m_nShareLength); // c = x mod 2^shareLength == read the share from least significant bits - mpz_div_2exp(r, r, maxShareLen); // x = x >> maxShareLen + mpz_mod_2exp(c[j], r, m_nShareBitLength); // c = x mod 2^ShareBitLength == read the share from least significant bits + mpz_div_2exp(r, r, maxShareBitLength); // x = x >> maxShareBitLength mpz_addmul(c[j], a[j], b[j]); //c = a*b + c - mpz_mod_2exp(c[j], c[j], m_nShareLength); // c = c mod 2^shareLength + mpz_mod_2exp(c[j], c[j], m_nShareBitLength); // c = c mod 2^ShareBitLength mpz_export(bC + offset, NULL, 1, shareBytes, 0, 0, c[j]); offset += shareBytes; } } -#if CHECKMT +#if DJN_CHECKMT std::cout << "Checking MT validity with values from other party:" << std::endl; mpz_t ai, bi, ci, ai1, bi1, ci1, ta, tb; @@ -277,7 +267,7 @@ void DJNParty::preCompBench(BYTE * bA, BYTE * bB, BYTE * bC, BYTE * bA1, BYTE * chan->send(bC, numMTs * shareBytes); chan->blocking_receive(bC, numMTs * shareBytes); - for (UINT i = 0; i < numMTs; i++) { + for (uint32_t i = 0; i < numMTs; i++) { mpz_import(ai, 1, 1, shareBytes, 0, 0, bA + i * shareBytes); mpz_import(bi, 1, 1, shareBytes, 0, 0, bB + i * shareBytes); @@ -291,8 +281,8 @@ void DJNParty::preCompBench(BYTE * bA, BYTE * bB, BYTE * bC, BYTE * bA1, BYTE * mpz_add(tb, bi, bi1); mpz_mul(ta, ta, tb); mpz_add(tb, ci, ci1); - mpz_mod_2exp(ta, ta, m_nShareLength); - mpz_mod_2exp(tb, tb, m_nShareLength); + mpz_mod_2exp(ta, ta, m_nShareBitLength); + mpz_mod_2exp(tb, tb, m_nShareBitLength); if (mpz_cmp(ta, tb) == 0) { std::cout << "MT is fine - i:" << i << "| " << ai << " " << bi << " " << ci << " . " << ai1 << " " << bi1 << " " << ci1 << std::endl; @@ -306,10 +296,13 @@ void DJNParty::preCompBench(BYTE * bA, BYTE * bB, BYTE * bC, BYTE * bA1, BYTE * #endif clock_gettime(CLOCK_MONOTONIC, &end); + +#if DJN_BENCH printf("generating 2x %u MTs took %f\n", numMTs, getMillies(start, end)); +#endif //clean up after ourselves - for (UINT i = 0; i < packshares; i++) { + for (uint32_t i = 0; i < packshares; i++) { mpz_clears(a[i], b[i], c[i], a1[i], b1[i], c1[i], NULL); } @@ -325,13 +318,13 @@ void DJNParty::preCompBench(BYTE * bA, BYTE * bB, BYTE * bC, BYTE * bA1, BYTE * * a,b,c are server shares. a1,b1,c1 are client shares. * All mpz_t values must be pre-initialized. */ -void DJNParty::benchPreCompPacking1(channel* chan, BYTE * buf, UINT packlen, UINT numshares, mpz_t * a, mpz_t * b, mpz_t * c, mpz_t * a1, mpz_t * b1, mpz_t * c1, mpz_t r, mpz_t x, +void DJNParty::benchPreCompPacking1(channel* chan, BYTE * buf, uint32_t packlen, uint32_t numshares, mpz_t * a, mpz_t * b, mpz_t * a1, mpz_t * b1, mpz_t * c1, mpz_t r, mpz_t x, mpz_t y, mpz_t z) { #if DJN_DEBUG std::cout << "packlen: " << packlen << " numshares: " << numshares << std::endl; #endif - for (UINT i = 0; i < numshares; i++) { + for (uint32_t i = 0; i < numshares; i++) { djn_encrypt_crt(r, m_localpub, m_prv, a[i]); mpz_export(buf + 2 * i * m_nBuflen, NULL, -1, 1, 1, 0, r); djn_encrypt_crt(r, m_localpub, m_prv, b[i]); @@ -340,23 +333,23 @@ void DJNParty::benchPreCompPacking1(channel* chan, BYTE * buf, UINT packlen, UIN chan->send(buf, (uint64_t) m_nBuflen * numshares * 2); -#if NETDEBUG +#if DJN_NETDEBUG std::cout << " SEND " << std::endl; - for (UINT xx=0; xx < m_nBuflen * numshares * 2; xx++) { + for (uint32_t xx=0; xx < m_nBuflen * numshares * 2; xx++) { printf("%02x.", *(buf + xx)); } #endif chan->blocking_receive(buf, (uint64_t) m_nBuflen * numshares * 2); -#if NETDEBUG +#if DJN_NETDEBUG std::cout << " RECV " << std::endl; - for (UINT xx=0; xx < m_nBuflen * numshares * 2; xx++) { + for (uint32_t xx=0; xx < m_nBuflen * numshares * 2; xx++) { printf("%02x.", *(buf + xx)); } #endif - for (UINT i = 0; i < numshares; i++) { + for (uint32_t i = 0; i < numshares; i++) { mpz_import(x, m_nBuflen, -1, 1, 1, 0, buf + 2 * i * m_nBuflen); mpz_import(y, m_nBuflen, -1, 1, 1, 0, buf + (2 * i + 1) * m_nBuflen); @@ -366,7 +359,7 @@ void DJNParty::benchPreCompPacking1(channel* chan, BYTE * buf, UINT packlen, UIN // horner packing of shares into 1 ciphertext mpz_set(z, c1[numshares - 1]); mpz_set_ui(y, 0); - mpz_setbit(y, packlen); // y = 2^shareLength, for shifting ciphertext + mpz_setbit(y, packlen); // y = 2^ShareBitLength, for shifting ciphertext for (int i = numshares - 2; i >= 0; i--) { mpz_powm(z, z, y, m_remotepub->n_squared); @@ -384,14 +377,14 @@ void DJNParty::benchPreCompPacking1(channel* chan, BYTE * buf, UINT packlen, UIN mpz_mod(z, z, m_remotepub->n_squared); // calculate c shares for client part - for (UINT i = 0; i < numshares; i++) { - mpz_mod_2exp(y, x, m_nShareLength); // y = r mod 2^shareLength == read the share from least significant bits + for (uint32_t i = 0; i < numshares; i++) { + mpz_mod_2exp(y, x, m_nShareBitLength); // y = r mod 2^ShareBitLength == read the share from least significant bits mpz_div_2exp(x, x, packlen); // r = r >> packlen mpz_mul(c1[i], a1[i], b1[i]); //c = a * b mpz_sub(c1[i], c1[i], y); // c = c - y - mpz_mod_2exp(c1[i], c1[i], m_nShareLength); // c = c mod 2^shareLength + mpz_mod_2exp(c1[i], c1[i], m_nShareBitLength); // c = c mod 2^ShareBitLength } } @@ -409,10 +402,10 @@ void DJNParty::keyExchange(channel* chan) { mpz_inits(a, b, NULL); receivempz_t(a, chan); //n receivempz_t(b, chan); //h - djn_complete_pubkey(m_nDJNbits, &m_remotepub, a, b); + djn_complete_pubkey(m_nDJNModulusBits, &m_remotepub, a, b); // pre calculate table for fixed-base exponentiation for client - fbpowmod_init_g(m_remotepub->h_s, m_remotepub->n_squared, 2 * m_nDJNbits); + fbpowmod_init_g(m_remotepub->h_s, m_remotepub->n_squared, 2 * m_nDJNModulusBits); //free a and b mpz_clears(a, b, NULL); @@ -428,11 +421,11 @@ void DJNParty::keyExchange(channel* chan) { void DJNParty::sendmpz_t(mpz_t t, channel* chan, BYTE * buf) { //clear upper bytes of the buffer, so tailing bytes are zero - for (int i = mpz_sizeinbase(t, 256); i < m_nBuflen; i++) { + for (uint32_t i = mpz_sizeinbase(t, 256); i < m_nBuflen; i++) { *(buf + i) = 0; } -#if NETDEBUG2 +#if DJN_NETDEBUG2 std::cout << mpz_sizeinbase(t, 256) << " vs. " << m_nBuflen << std::endl; #endif @@ -441,9 +434,9 @@ void DJNParty::sendmpz_t(mpz_t t, channel* chan, BYTE * buf) { //send Bytes of t chan->send(buf, (uint64_t) m_nBuflen); -#if NETDEBUG +#if DJN_NETDEBUG std::cout << std::endl << "SEND" << std::endl; - for (int i = 0; i < m_nBuflen; i++) { + for (uint32_t i = 0; i < m_nBuflen; i++) { printf("%02x.", *(m_sendbuf + i)); } @@ -458,9 +451,9 @@ void DJNParty::receivempz_t(mpz_t t, channel* chan, BYTE * buf) { chan->blocking_receive(buf, (uint64_t) m_nBuflen); mpz_import(t, m_nBuflen, -1, 1, 1, 0, buf); -#if NETDEBUG +#if DJN_NETDEBUG std::cout << std::endl << "RECEIVE" << std::endl; - for (int i = 0; i < m_nBuflen; i++) { + for (uint32_t i = 0; i < m_nBuflen; i++) { printf("%02x.", *(m_recbuf + i)); } @@ -483,7 +476,7 @@ void DJNParty::sendmpz_t(mpz_t t, channel* chan) { chan->send(arr, (uint64_t) bytelen); free(arr); -#if NETDEBUG +#if DJN_NETDEBUG std::cout << "sent: " << t << " with len: " << bytelen << std::endl; #endif } @@ -503,14 +496,14 @@ void DJNParty::receivempz_t(mpz_t t, channel* chan) { mpz_import(t, bytelen, 1, 1, 1, 0, arr); free(arr); -#if NETDEBUG +#if DJN_NETDEBUG std::cout << "received: " << t << " with len: " << bytelen << std::endl; #endif } #if DJN_DEBUG -void DJNParty::printBuf(BYTE* b, UINT len) { - for (UINT i = 0; i < len; i++) { +void DJNParty::printBuf(BYTE* b, uint32_t len) { + for (uint32_t i = 0; i < len; i++) { printf("%02x.", *(b + i)); } std::cout << std::endl; diff --git a/src/abycore/DJN/djnparty.h b/src/abycore/DJN/djnparty.h index 9e3f8b8e..03b0af76 100644 --- a/src/abycore/DJN/djnparty.h +++ b/src/abycore/DJN/djnparty.h @@ -2,23 +2,30 @@ \file djnparty.h \author daniel.demmler@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Implementation of DJNParty class */ #ifndef __DJNPARTY_H__ #define __DJNPARTY_H__ +#define DJN_CHECKMT 0 +#define DJN_DEBUG 0 +#define DJN_BENCH 0 +#define DJN_NETDEBUG 0 +#define DJN_NETDEBUG2 0 +#define DJN_WINDOWSIZE 65536//maximum size of a network packet in Byte + #include #include #include @@ -26,32 +33,37 @@ #include #include #include +#include +#include +#if DJN_DEBUG || DJN_BENCH +#include +#endif class DJNParty { public: - DJNParty(UINT DJNbits, UINT sharelen); - DJNParty(UINT DJNbits, UINT sharelen, channel* chan); + DJNParty(uint32_t DJNModulusBits, uint32_t shareBitLength); + DJNParty(uint32_t DJNModulusBits, uint32_t shareBitLength, channel* chan); ~DJNParty(); void keyExchange(channel* chan); - void preCompBench(BYTE * bA, BYTE * bB, BYTE * bC, BYTE * bA1, BYTE * bB1, BYTE * bC1, UINT numMTs, channel* chan); + void computeArithmeticMTs(BYTE * bA, BYTE * bB, BYTE * bC, BYTE * bA1, BYTE * bB1, BYTE * bC1, uint32_t numMTs, channel* chan); - void setSharelLength(UINT sharelen); + void setShareBitLength(uint32_t shareBitLength); void keyGen(); private: - USHORT m_nNumMTThreads; - USHORT m_nShareLength; - UINT m_nDJNbits; - UINT m_nBuflen; + uint16_t m_nNumMTThreads; + uint16_t m_nShareBitLength; + uint32_t m_nDJNModulusBits; + uint32_t m_nBuflen; // Crypto and GMP PRNG djn_pubkey_t *m_localpub, *m_remotepub; djn_prvkey_t *m_prv; - void benchPreCompPacking1(channel* chan, BYTE * buf, UINT packlen, UINT numshares, mpz_t * a, mpz_t * b, mpz_t * c, mpz_t * a1, mpz_t * b1, mpz_t * c1, mpz_t r, mpz_t x, - mpz_t y, mpz_t z); + void benchPreCompPacking1(channel* chan, BYTE * buf, uint32_t packlen, uint32_t numshares, + mpz_t * a, mpz_t * b, mpz_t * a1, mpz_t * b1, mpz_t * c1, mpz_t r, mpz_t x, mpz_t y, mpz_t z); void sendmpz_t(mpz_t t, channel* chan, BYTE * buf); void receivempz_t(mpz_t t, channel* chan, BYTE * buf); @@ -59,7 +71,7 @@ class DJNParty { void sendmpz_t(mpz_t t, channel* chan); void receivempz_t(mpz_t t, channel* chan); - void printBuf(BYTE* b, UINT l); + void printBuf(BYTE* b, uint32_t l); }; diff --git a/src/abycore/aby/abyparty.cpp b/src/abycore/aby/abyparty.cpp index 7a26cba8..02a452c2 100644 --- a/src/abycore/aby/abyparty.cpp +++ b/src/abycore/aby/abyparty.cpp @@ -2,17 +2,17 @@ \file abyparty.cpp \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief ABYParty class implementation. */ @@ -51,6 +51,9 @@ class ABYParty::CPartyWorkerThread: public CThread { m_evt.Set(); } + CEvent* GetEvent() { + return &m_evt; + } private: void ThreadMain(); uint32_t threadid; @@ -62,7 +65,7 @@ class ABYParty::CPartyWorkerThread: public CThread { ABYParty::ABYParty(e_role pid, const std::string& addr, uint16_t port, seclvl seclvl, uint32_t bitlen, uint32_t nthreads, e_mt_gen_alg mg_algo, - uint32_t maxgates) + uint32_t reservegates, const std::string& abycircdir) : m_cCrypt(std::make_unique(seclvl.symbits)), glock(std::make_unique()), m_eMTGenAlg(mg_algo), m_eRole(pid), m_nNumOTThreads(nthreads), m_tComm(std::make_unique()), @@ -94,35 +97,36 @@ ABYParty::ABYParty(e_role pid, const std::string& addr, uint16_t port, seclvl se std::cout << "Generating circuit" << std::endl; #endif StartWatch("Generating circuit", P_CIRCUIT); - if (!InitCircuit(bitlen, maxgates)) { + if (!InitCircuit(bitlen, reservegates, abycircdir)) { std::cout << "There was an while initializing the circuit, ending! " << std::endl; std::exit(EXIT_FAILURE); } StopWatch("Time for circuit generation: ", P_CIRCUIT); } - void ABYParty::ConnectAndBaseOTs() { + if (!is_online) { #ifndef BATCH - std::cout << "Establishing network connection" << std::endl; + std::cout << "Establishing network connection" << std::endl; #endif - //Establish network connection - StartWatch("Establishing network connection: ", P_NETWORK); - if (!EstablishConnection()) { - std::cout << "There was an error during establish connection, ending! " << std::endl; - std::exit(EXIT_FAILURE); - } - StopWatch("Time for network connect: ", P_NETWORK); + //Establish network connection + StartWatch("Establishing network connection: ", P_NETWORK); + if (!EstablishConnection()) { + std::cout << "There was an error during establish connection, ending! " << std::endl; + std::exit(EXIT_FAILURE); + } + StopWatch("Time for network connect: ", P_NETWORK); #ifndef BATCH - std::cout << "Performing base OTs" << std::endl; + std::cout << "Performing base OTs" << std::endl; #endif - /* Pre-Compute Naor-Pinkas base OTs by starting two threads */ - StartRecording("Starting NP OT", P_BASE_OT, m_vSockets); - m_pSetup->PrepareSetupPhase(m_tComm.get()); - StopRecording("Time for NP OT: ", P_BASE_OT, m_vSockets); + /* Pre-Compute Naor-Pinkas base OTs by starting two threads */ + StartRecording("Starting NP OT", P_BASE_OT, m_vSockets); + m_pSetup->PrepareSetupPhase(m_tComm.get()); + StopRecording("Time for NP OT: ", P_BASE_OT, m_vSockets); - is_online = true; + is_online = true; + } } ABYParty::~ABYParty() { @@ -155,8 +159,8 @@ BOOL ABYParty::Init() { void ABYParty::Cleanup() { // free any gates that are still instantiated for(size_t i = 0; i < m_pCircuit->GetGateHead(); i++) { - if(m_pGates[i].instantiated) { - m_vSharings[0]->FreeGate(&m_pGates[i]); + if((*m_vGates)[i].instantiated) { + m_vSharings[0]->FreeGate(&(*m_vGates)[i]); } } for(uint32_t i = 0; i < S_LAST; i++) { @@ -184,9 +188,7 @@ void ABYParty::ExecCircuit() { std::cout << "Finishing circuit generation" << std::endl; #endif - if (!is_online) { - ConnectAndBaseOTs(); - } + ConnectAndBaseOTs(); StartRecording("Starting execution", P_TOTAL, m_vSockets); @@ -211,7 +213,7 @@ void ABYParty::ExecCircuit() { std::cout << "Performing setup phase for " << m_vSharings[i]->sharing_type() << " sharing" << std::endl; #endif if(i == S_YAO) { - StartWatch("Starting Circuit Garbling", P_GARBLE); + StartRecording("Starting Circuit Garbling", P_GARBLE, m_vSockets); if(m_eRole == SERVER) { m_vSharings[S_YAO]->PerformSetupPhase(m_pSetup.get()); m_vSharings[S_YAO_REV]->PerformSetupPhase(m_pSetup.get()); @@ -223,7 +225,7 @@ void ABYParty::ExecCircuit() { m_vSharings[S_YAO_REV]->PerformSetupPhase(m_pSetup.get());*/ m_vSharings[S_YAO]->FinishSetupPhase(m_pSetup.get()); m_vSharings[S_YAO_REV]->FinishSetupPhase(m_pSetup.get()); - StopWatch("Time for Circuit garbling: ", P_GARBLE); + StopRecording("Time for Circuit garbling: ", P_GARBLE, m_vSockets); } else if (i == S_YAO_REV) { //Do nothing, was done in parallel to Yao } else { @@ -265,40 +267,40 @@ void ABYParty::ExecCircuit() { } -BOOL ABYParty::InitCircuit(uint32_t bitlen, uint32_t maxgates) { - // Specification of maximum amount of gates in constructor in abyparty.h - m_pCircuit = new ABYCircuit(maxgates); +BOOL ABYParty::InitCircuit(uint32_t bitlen, uint32_t reservegates, const std::string& abycircdir) { + // Default reserved gates in abyparty.h constructur + m_pCircuit = new ABYCircuit(reservegates); m_vSharings.resize(S_LAST); - m_vSharings[S_BOOL] = new BoolSharing(S_BOOL, m_eRole, 1, m_pCircuit, m_cCrypt.get()); + m_vSharings[S_BOOL] = new BoolSharing(S_BOOL, m_eRole, 1, m_pCircuit, m_cCrypt.get(), abycircdir); if (m_eRole == SERVER) { - m_vSharings[S_YAO] = new YaoServerSharing(S_YAO, SERVER, m_sSecLvl.symbits, m_pCircuit, m_cCrypt.get()); - m_vSharings[S_YAO_REV] = new YaoClientSharing(S_YAO_REV, CLIENT, m_sSecLvl.symbits, m_pCircuit, m_cCrypt.get()); + m_vSharings[S_YAO] = new YaoServerSharing(S_YAO, SERVER, m_sSecLvl.symbits, m_pCircuit, m_cCrypt.get(), abycircdir); + m_vSharings[S_YAO_REV] = new YaoClientSharing(S_YAO_REV, CLIENT, m_sSecLvl.symbits, m_pCircuit, m_cCrypt.get(), abycircdir); } else { - m_vSharings[S_YAO] = new YaoClientSharing(S_YAO, CLIENT, m_sSecLvl.symbits, m_pCircuit, m_cCrypt.get()); - m_vSharings[S_YAO_REV] = new YaoServerSharing(S_YAO_REV, SERVER, m_sSecLvl.symbits, m_pCircuit, m_cCrypt.get()); + m_vSharings[S_YAO] = new YaoClientSharing(S_YAO, CLIENT, m_sSecLvl.symbits, m_pCircuit, m_cCrypt.get(), abycircdir); + m_vSharings[S_YAO_REV] = new YaoServerSharing(S_YAO_REV, SERVER, m_sSecLvl.symbits, m_pCircuit, m_cCrypt.get(), abycircdir); } switch (bitlen) { case 8: - m_vSharings[S_ARITH] = new ArithSharing(S_ARITH, m_eRole, 1, m_pCircuit, m_cCrypt.get(), m_eMTGenAlg); + m_vSharings[S_ARITH] = new ArithSharing(S_ARITH, m_eRole, 1, m_pCircuit, m_cCrypt.get(), m_eMTGenAlg); break; case 16: - m_vSharings[S_ARITH] = new ArithSharing(S_ARITH, m_eRole, 1, m_pCircuit, m_cCrypt.get(), m_eMTGenAlg); + m_vSharings[S_ARITH] = new ArithSharing(S_ARITH, m_eRole, 1, m_pCircuit, m_cCrypt.get(), m_eMTGenAlg); break; case 32: - m_vSharings[S_ARITH] = new ArithSharing(S_ARITH, m_eRole, 1, m_pCircuit, m_cCrypt.get(), m_eMTGenAlg); + m_vSharings[S_ARITH] = new ArithSharing(S_ARITH, m_eRole, 1, m_pCircuit, m_cCrypt.get(), m_eMTGenAlg); break; case 64: - m_vSharings[S_ARITH] = new ArithSharing(S_ARITH, m_eRole, 1, m_pCircuit, m_cCrypt.get(), m_eMTGenAlg); + m_vSharings[S_ARITH] = new ArithSharing(S_ARITH, m_eRole, 1, m_pCircuit, m_cCrypt.get(), m_eMTGenAlg); break; default: - m_vSharings[S_ARITH] = new ArithSharing(S_ARITH, m_eRole, 1, m_pCircuit, m_cCrypt.get(), m_eMTGenAlg); + m_vSharings[S_ARITH] = new ArithSharing(S_ARITH, m_eRole, 1, m_pCircuit, m_cCrypt.get(), m_eMTGenAlg); break; } - m_vSharings[S_SPLUT] = new SetupLUT(S_SPLUT, m_eRole, 1, m_pCircuit, m_cCrypt.get()); + m_vSharings[S_SPLUT] = new SetupLUT(S_SPLUT, m_eRole, 1, m_pCircuit, m_cCrypt.get(), abycircdir); - m_pGates = m_pCircuit->Gates(); + m_vGates = &(m_pCircuit->GatesVec()); #ifndef BATCH std::cout << " circuit initialized..." << std::endl; @@ -378,7 +380,7 @@ BOOL ABYParty::EvaluateCircuit() { clock_gettime(CLOCK_MONOTONIC, &tstart); #endif //std::cout << "Finishing circuit layer for sharing "<< i << std::endl; - m_vSharings[i]->FinishCircuitLayer(depth); + m_vSharings[i]->FinishCircuitLayer(); #if BENCHONLINEPHASE clock_gettime(CLOCK_MONOTONIC, &tend); fincirclayer[i] += getMillies(tstart, tend); @@ -409,7 +411,7 @@ BOOL ABYParty::PerformInteraction() { return success; } -BOOL ABYParty::ThreadSendValues() { +BOOL ABYParty::ThreadSendValues(uint32_t id) { std::vector >sendbuf(m_vSharings.size()); std::vector >sndbytes(m_vSharings.size()); @@ -440,7 +442,7 @@ BOOL ABYParty::ThreadSendValues() { //gettimeofday(&tstart, NULL); if(snd_buf_size_total > 0) { //m_vSockets[2]->Send(snd_buf_total, snd_buf_size_total); - m_tPartyChan->send(snd_buf_total, snd_buf_size_total); + m_tPartyChan->blocking_send(m_vThreads[id]->GetEvent(), snd_buf_total, snd_buf_size_total); } free(snd_buf_total); @@ -586,15 +588,15 @@ BOOL ABYParty::ABYPartyListen() { // TODO: are InstantiateGate and UsedGate needed in ABYParty? They don't // seem to get used anywhere void ABYParty::InstantiateGate(uint32_t gateid) { - m_pGates[gateid].gs.val = (UGATE_T*) malloc(sizeof(UGATE_T) * (ceil_divide(m_pGates[gateid].nvals, GATE_T_BITS))); + (*m_vGates)[gateid].gs.val = (UGATE_T*) malloc(sizeof(UGATE_T) * (ceil_divide((*m_vGates)[gateid].nvals, GATE_T_BITS))); } void ABYParty::UsedGate(uint32_t gateid) { //Decrease the number of further uses of the gate - m_pGates[gateid].nused--; + (*m_vGates)[gateid].nused--; //If the gate is needed in another subsequent gate, delete it - if (!m_pGates[gateid].nused) { - free(m_pGates[gateid].gs.val); + if (!(*m_vGates)[gateid].nused) { + free((*m_vGates)[gateid].gs.val); } } @@ -606,8 +608,8 @@ void ABYParty::Reset() { // free any gates that are still instantiated for(size_t i = 0; i < m_pCircuit->GetGateHead(); i++) { - if(m_pGates[i].instantiated) { - m_vSharings[0]->FreeGate(&m_pGates[i]); + if((*m_vGates)[i].instantiated) { + m_vSharings[0]->FreeGate(&(*m_vGates)[i]); } } for (uint32_t i = 0; i < m_vSharings.size(); i++) { @@ -629,6 +631,14 @@ uint64_t ABYParty::GetReceivedData(ABYPHASE phase) { return GetReceivedDataForPhase(phase); } +uint32_t ABYParty::GetTotalGates() { + return m_pCircuit->GetGateHead(); +} + +uint32_t ABYParty::GetTotalDepth() { + return m_pCircuit->GetTotalDepth(); +} + //=========================================================================== // Thread Management BOOL ABYParty::WakeupWorkerThreads(EPartyJobType e) { @@ -689,7 +699,7 @@ void ABYParty::CPartyWorkerThread::ThreadMain() { return; case e_Party_Comm: if (threadid == 0){ - bSuccess = m_pCallback->ThreadSendValues(); + bSuccess = m_pCallback->ThreadSendValues(threadid); } else{ bSuccess = m_pCallback->ThreadReceiveValues(); diff --git a/src/abycore/aby/abyparty.h b/src/abycore/aby/abyparty.h index 99afd2c3..406de880 100644 --- a/src/abycore/aby/abyparty.h +++ b/src/abycore/aby/abyparty.h @@ -2,17 +2,17 @@ \file abyparty.h \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief ABYParty class. */ @@ -41,7 +41,7 @@ class CLock; class ABYParty { public: ABYParty(e_role pid, const std::string& addr = "127.0.0.1", uint16_t port = 7766, seclvl seclvl = LT, uint32_t bitlen = 32, - uint32_t nthreads = 2, e_mt_gen_alg mg_algo = MT_OT, uint32_t maxgates = 4000000); + uint32_t nthreads = 2, e_mt_gen_alg mg_algo = MT_OT, uint32_t reservegates = 65536, const std::string& abycircdir = ABY_CIRCUIT_DIR); ~ABYParty(); /** @@ -59,13 +59,14 @@ class ABYParty { double GetTiming(ABYPHASE phase); uint64_t GetSentData(ABYPHASE phase); uint64_t GetReceivedData(ABYPHASE phase); - + uint32_t GetTotalGates(); + uint32_t GetTotalDepth(); private: BOOL Init(); void Cleanup(); - BOOL InitCircuit(uint32_t bitlen, uint32_t maxgates); + BOOL InitCircuit(uint32_t bitlen, uint32_t reservegates, const std::string& circdir = ABY_CIRCUIT_DIR); BOOL EstablishConnection(); @@ -82,7 +83,7 @@ class ABYParty { void UsedGate(uint32_t gateid); BOOL PerformInteraction(); - BOOL ThreadSendValues(); + BOOL ThreadSendValues(uint32_t id); BOOL ThreadReceiveValues(); void PrintPerformanceStatistics(); @@ -120,7 +121,7 @@ class ABYParty { uint32_t m_nMyNumInBits; // Ciruit ABYCircuit* m_pCircuit; - GATE* m_pGates; + std::vector* m_vGates; uint32_t m_nSizeOfVal; diff --git a/src/abycore/aby/abysetup.cpp b/src/abycore/aby/abysetup.cpp index 39fef178..fdca9d4f 100644 --- a/src/abycore/aby/abysetup.cpp +++ b/src/abycore/aby/abysetup.cpp @@ -2,24 +2,23 @@ \file abysetup.cpp \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief ABYSetup class implementation. */ #include "abysetup.h" #include #include -#include ABYSetup::ABYSetup(crypto* crypt, uint32_t numThreads, e_role role, e_mt_gen_alg mtalgo) { m_nNumOTThreads = numThreads; @@ -51,22 +50,26 @@ BOOL ABYSetup::Init() { m_vThreads[i]->Start(); } - //the bit length of the DJN and DGK party is irrelevant here, since it is set for each MT Gen task independently + //the bit length of the DJN party is irrelevant here, since it is set for each MT Gen task independently if (m_eMTGenAlg == MT_PAILLIER) { #ifndef BATCH std::cout << "Creating new DJNPart with key bitlen = " << m_cCrypt->get_seclvl().ifcbits << std::endl; #endif - m_cPaillierMTGen = new DJNParty(m_cCrypt->get_seclvl().ifcbits, sizeof(UINT16_T) * 8); - } else if (m_eMTGenAlg == MT_DGK) { -#ifndef BATCH - std::cout << "Creating new DGKPart with key bitlen = " << m_cCrypt->get_seclvl().ifcbits << std::endl; -#endif -#ifdef BENCH_PRECOMP - m_cDGKMTGen = (DGKParty**) malloc(sizeof(DGKParty*)); - m_cDGKMTGen[0] = new DGKParty(m_sSecLvl.ifcbits, sizeof(UINT64_T) * 8, 0); -#endif - //m_cDGKMTGen = new DGKParty(m_cCrypt->get_seclvl().ifcbits, sizeof(UINT16_T) * 8); + m_cPaillierMTGen = new DJNParty(m_cCrypt->get_seclvl().ifcbits, sizeof(uint16_t) * 8); } +// we cannot create a DGKParty here, since we do not know the share bit length yet. +// for DGK this will be done in PerformSetupPhase() + +// else if (m_eMTGenAlg == MT_DGK) { +// #ifndef BATCH +// std::cout << "Creating new DGKPart with key bitlen = " << m_cCrypt->get_seclvl().ifcbits << std::endl; +// #endif +// #ifdef BENCH_PRECOMP +// m_cDGKMTGen = (DGKParty**) malloc(sizeof(DGKParty*)); +// m_cDGKMTGen[0] = new DGKParty(m_sSecLvl.ifcbits, sizeof(uint64_t) * 8, 0); +// #endif +// //m_cDGKMTGen = new DGKParty(m_cCrypt->get_seclvl().ifcbits, sizeof(uint16_t) * 8); +// } return true; } @@ -87,6 +90,10 @@ void ABYSetup::Cleanup() { if(iknp_ot_receiver) { delete iknp_ot_receiver; } + if(m_cPaillierMTGen){ + delete m_cPaillierMTGen; + } + #ifdef USE_KK_OT //FIXME: deleting kk_ot_receiver or sender causes a SegFault in AES with Yao @@ -205,7 +212,10 @@ BOOL ABYSetup::PerformSetupPhase() { //Start Paillier MT generation WakeupWorkerThreads(e_MTPaillier); success &= WaitWorkerThreads(); - } else if (m_eMTGenAlg == MT_DGK) { + } + else if (m_eMTGenAlg == MT_DGK) { + // we cannot create the DGK parties earlier + // since share length in m_vPKMTGenTasks[i]->sharebitlen is required and only known from here on #ifndef BENCH_PRECOMP m_cDGKMTGen = (DGKParty**) malloc(sizeof(DGKParty*) * m_vPKMTGenTasks.size()); #endif @@ -232,7 +242,7 @@ BOOL ABYSetup::FinishSetupPhase() { return true; } -BOOL ABYSetup::ThreadRunNPSnd(uint32_t exec) { +BOOL ABYSetup::ThreadRunNPSnd() { BOOL success = true; iknp_ot_sender->ComputeBaseOTs(P_FIELD); #ifdef USE_KK_OT @@ -241,7 +251,7 @@ BOOL ABYSetup::ThreadRunNPSnd(uint32_t exec) { return success; } -BOOL ABYSetup::ThreadRunNPRcv(uint32_t exec) { +BOOL ABYSetup::ThreadRunNPRcv() { BOOL success = true; iknp_ot_receiver->ComputeBaseOTs(P_FIELD); #ifdef USE_KK_OT @@ -251,10 +261,10 @@ BOOL ABYSetup::ThreadRunNPRcv(uint32_t exec) { } //Receiver and Sender switch roles in the beginning of the OT extension protocol to obliviously transfer a matrix T -BOOL ABYSetup::ThreadRunIKNPSnd(uint32_t exec) { +BOOL ABYSetup::ThreadRunIKNPSnd(uint32_t threadid) { bool success = true; - uint32_t inverse = exec ^ m_eRole; + uint32_t inverse = threadid ^ m_eRole; uint32_t nsndvals = 2; CBitVector** X = (CBitVector**) malloc(sizeof(CBitVector*) * nsndvals); @@ -285,10 +295,10 @@ BOOL ABYSetup::ThreadRunIKNPSnd(uint32_t exec) { return success; } -BOOL ABYSetup::ThreadRunIKNPRcv(uint32_t exec) { +BOOL ABYSetup::ThreadRunIKNPRcv(uint32_t threadid) { bool success = true; - uint32_t inverse = exec ^ m_eRole; + uint32_t inverse = threadid ^ m_eRole; // uint32_t symbits = m_cCrypt->get_seclvl().symbits; uint32_t nsndvals = 2; @@ -319,10 +329,10 @@ BOOL ABYSetup::ThreadRunIKNPRcv(uint32_t exec) { //KK13 OT extension sender and receiver routine outsourced in separate threads -BOOL ABYSetup::ThreadRunKKSnd(uint32_t exec) { +BOOL ABYSetup::ThreadRunKKSnd(uint32_t threadid) { bool success = true; - uint32_t inverse = exec ^ m_eRole; + uint32_t inverse = threadid ^ m_eRole; for (uint32_t i = 0; i < m_vKKOTTasks[inverse].size(); i++) { KK_OTTask* task = m_vKKOTTasks[inverse][i]; @@ -356,10 +366,10 @@ BOOL ABYSetup::ThreadRunKKSnd(uint32_t exec) { return success; } -BOOL ABYSetup::ThreadRunKKRcv(uint32_t exec) { +BOOL ABYSetup::ThreadRunKKRcv(uint32_t threadid) { bool success = true; - uint32_t inverse = exec ^ m_eRole; + uint32_t inverse = threadid ^ m_eRole; // uint32_t symbits = m_cCrypt->get_seclvl().symbits; // uint32_t nsndvals = 2; @@ -388,36 +398,46 @@ BOOL ABYSetup::ThreadRunKKRcv(uint32_t exec) { return success; } - BOOL ABYSetup::ThreadRunPaillierMTGen(uint32_t threadid) { - uint32_t nthreads = 2 * m_nNumOTThreads; - channel* djnchan = new channel(DJN_CHANNEL+threadid, m_tComm->rcv_std.get(), m_tComm->snd_std.get()); - for (uint32_t i = 0; i < m_vPKMTGenTasks.size(); i++) { + channel* djnchan = new channel(DJN_CHANNEL + threadid, m_tComm->rcv_std.get(), m_tComm->snd_std.get()); + for (uint32_t i = 0; i < m_vPKMTGenTasks.size(); i++) { PKMTGenVals* ptask = m_vPKMTGenTasks[i]; - uint32_t nummtsperthread = ceil_divide(ptask->numMTs, nthreads); + // equally distribute MTs to threads. Number of MTs per thread must be multiple of 2. + uint32_t nummtsperthread = ptask->numMTs / (nthreads * 2); + uint32_t threadmod = ptask->numMTs % (nthreads * 2); + uint32_t mynummts = (nummtsperthread + ((threadid * 2) < threadmod)) * 2; - uint32_t mynummts = nummtsperthread; //times two since we need the number of MTs to be a multiple of 2 internally uint32_t sharebytelen = ceil_divide(ptask->sharebitlen, 8); - if (threadid == nthreads - 1) { - mynummts = ptask->numMTs - (nthreads-1 ) * nummtsperthread; - } - - uint32_t mystartpos = nummtsperthread * threadid * sharebytelen; - m_cPaillierMTGen->setSharelLength(ptask->sharebitlen); - - UINT32_T roleoffset = mystartpos + sharebytelen * (mynummts / 2); - if (m_eRole == SERVER) { - m_cPaillierMTGen->preCompBench(ptask->A->GetArr() + mystartpos, ptask->B->GetArr() + mystartpos, ptask->C->GetArr() + mystartpos, ptask->A->GetArr() + roleoffset, - ptask->B->GetArr() + roleoffset, ptask->C->GetArr() + roleoffset, mynummts, djnchan); - } else { - m_cPaillierMTGen->preCompBench(ptask->A->GetArr() + roleoffset, ptask->B->GetArr() + roleoffset, ptask->C->GetArr() + roleoffset, ptask->A->GetArr() + mystartpos, - ptask->B->GetArr() + mystartpos, ptask->C->GetArr() + mystartpos, mynummts, djnchan); + if (mynummts > 0) { + uint32_t mystartpos = 0; + + // add up previous threads numMTs to find start index for this thread + for (uint32_t t = 0; t < threadid; ++t) { + mystartpos += (nummtsperthread + ((t * 2) < threadmod)) * 2; + } + mystartpos *= sharebytelen; + + //add an offset depending on the role of the party + uint32_t roleoffset = mystartpos + sharebytelen * (mynummts / 2); + + m_cPaillierMTGen->setShareBitLength(ptask->sharebitlen); + + if (m_eRole == SERVER) { + m_cPaillierMTGen->computeArithmeticMTs( + ptask->A->GetArr() + mystartpos, ptask->B->GetArr() + mystartpos, ptask->C->GetArr() + mystartpos, + ptask->A->GetArr() + roleoffset, ptask->B->GetArr() + roleoffset, ptask->C->GetArr() + roleoffset, + mynummts, djnchan); + } else { + m_cPaillierMTGen->computeArithmeticMTs( + ptask->A->GetArr() + roleoffset, ptask->B->GetArr() + roleoffset, ptask->C->GetArr() + roleoffset, + ptask->A->GetArr() + mystartpos, ptask->B->GetArr() + mystartpos, ptask->C->GetArr() + mystartpos, + mynummts, djnchan); + } } - free(ptask); } djnchan->synchronize_end(); delete djnchan; @@ -426,37 +446,44 @@ BOOL ABYSetup::ThreadRunPaillierMTGen(uint32_t threadid) { } BOOL ABYSetup::ThreadRunDGKMTGen(uint32_t threadid) { - uint32_t nthreads = 2 * m_nNumOTThreads; - channel* dgkchan = new channel(DGK_CHANNEL+threadid, m_tComm->rcv_std.get(), m_tComm->snd_std.get()); + channel* dgkchan = new channel(DGK_CHANNEL + threadid, m_tComm->rcv_std.get(), m_tComm->snd_std.get()); for (uint32_t i = 0; i < m_vPKMTGenTasks.size(); i++) { PKMTGenVals* ptask = m_vPKMTGenTasks[i]; - //times two since we need the number of MTs to be a multiple of 2 internally - uint32_t nummtsperthread = ceil_divide(ptask->numMTs, nthreads); - uint32_t mynummts = nummtsperthread; - uint32_t sharebytelen = ceil_divide(ptask->sharebitlen, 8); - - //if the number of MTs is not evenly divisible among all threads - if (threadid == nthreads - 1) { - mynummts = ptask->numMTs - (nthreads-1 ) * nummtsperthread; - } + // equally distribute MTs to threads. Number of MTs per thread must be multiple of 2. + uint32_t nummtsperthread = ptask->numMTs / (nthreads * 2); + uint32_t threadmod = ptask->numMTs % (nthreads * 2); + uint32_t mynummts = (nummtsperthread + ((threadid * 2) < threadmod)) * 2; - uint32_t mystartpos = nummtsperthread * threadid * sharebytelen; - - //add an offset depending on the role of the party - UINT32_T roleoffset = mystartpos + sharebytelen * (mynummts / 2); + uint32_t sharebytelen = ceil_divide(ptask->sharebitlen, 8); - if (m_eRole == SERVER) { - m_cDGKMTGen[i]->preCompBench(ptask->A->GetArr() + mystartpos, ptask->B->GetArr() + mystartpos, ptask->C->GetArr() + mystartpos, ptask->A->GetArr() + roleoffset, - ptask->B->GetArr() + roleoffset, ptask->C->GetArr() + roleoffset, mynummts, dgkchan); - } else { - m_cDGKMTGen[i]->preCompBench(ptask->A->GetArr() + roleoffset, ptask->B->GetArr() + roleoffset, ptask->C->GetArr() + roleoffset, ptask->A->GetArr() + mystartpos, - ptask->B->GetArr() + mystartpos, ptask->C->GetArr() + mystartpos, mynummts, dgkchan); + if (mynummts > 0) { + uint32_t mystartpos = 0; + + // add up previous threads numMTs to find start index for this thread + for (uint32_t t = 0; t < threadid; ++t) { + mystartpos += (nummtsperthread + ((t * 2) < threadmod)) * 2; + } + mystartpos *= sharebytelen; + + //add an offset depending on the role of the party + uint32_t roleoffset = mystartpos + sharebytelen * (mynummts / 2); + + if (m_eRole == SERVER) { + m_cDGKMTGen[i]->computeArithmeticMTs( + ptask->A->GetArr() + mystartpos, ptask->B->GetArr() + mystartpos, ptask->C->GetArr() + mystartpos, + ptask->A->GetArr() + roleoffset, ptask->B->GetArr() + roleoffset, ptask->C->GetArr() + roleoffset, + mynummts, dgkchan); + } else { + m_cDGKMTGen[i]->computeArithmeticMTs( + ptask->A->GetArr() + roleoffset, ptask->B->GetArr() + roleoffset, ptask->C->GetArr() + roleoffset, + ptask->A->GetArr() + mystartpos, ptask->B->GetArr() + mystartpos, ptask->C->GetArr() + mystartpos, + mynummts, dgkchan); + } } - free(ptask); } dgkchan->synchronize_end(); delete dgkchan; @@ -484,12 +511,14 @@ void ABYSetup::AddReceiveTask(BYTE* rcvbuf, uint64_t rcvbytes) { WakeupWorkerThreads(e_Receive); } + BOOL ABYSetup::ThreadSendData(uint32_t threadid) { - m_tSetupChan->send(m_tsndtask.sndbuf, m_tsndtask.sndbytes); + m_tSetupChan->blocking_send(m_vThreads[threadid]->GetEvent(), m_tsndtask.sndbuf, m_tsndtask.sndbytes); return true; } -BOOL ABYSetup::ThreadReceiveData(uint32_t threadid) { + +BOOL ABYSetup::ThreadReceiveData() { m_tSetupChan->blocking_receive(m_trcvtask.rcvbuf, m_trcvtask.rcvbytes); return true; } @@ -501,15 +530,17 @@ BOOL ABYSetup::WakeupWorkerThreads(EJobType e) { m_nWorkingThreads = 2; - if (e == e_MTPaillier || e == e_MTDGK) + if (e == e_MTPaillier || e == e_MTDGK) { m_nWorkingThreads = 2 * m_nNumOTThreads; - else if (e == e_Send || e == e_Receive) + } else if (e == e_Send || e == e_Receive) { m_nWorkingThreads = 1; + } uint32_t n = m_nWorkingThreads; - for (uint32_t i = 0; i < n; i++) + for (uint32_t i = 0; i < n; i++){ m_vThreads[i]->PutJob(e); + } return TRUE; } @@ -573,9 +604,9 @@ void ABYSetup::CWorkerThread::ThreadMain() { break; case e_NP: if (threadid == SERVER) - bSuccess = m_pCallback->ThreadRunNPSnd(threadid); + bSuccess = m_pCallback->ThreadRunNPSnd(); else - bSuccess = m_pCallback->ThreadRunNPRcv(threadid); + bSuccess = m_pCallback->ThreadRunNPRcv(); break; case e_MTPaillier: bSuccess = m_pCallback->ThreadRunPaillierMTGen(threadid); @@ -587,7 +618,7 @@ void ABYSetup::CWorkerThread::ThreadMain() { bSuccess = m_pCallback->ThreadSendData(threadid); break; case e_Receive: - bSuccess = m_pCallback->ThreadReceiveData(threadid); + bSuccess = m_pCallback->ThreadReceiveData(); break; case e_Transmit: case e_Undefined: @@ -599,12 +630,18 @@ void ABYSetup::CWorkerThread::ThreadMain() { } void ABYSetup::Reset() { - /* Clear any remaining OT tasks */ + /* Clear any remaining IKNP OT tasks */ for (uint32_t i = 0; i < m_vIKNPOTTasks.size(); i++) { m_vIKNPOTTasks[i].clear(); } - /* Clear any remaining OT tasks */ + /* Clear any remaining KK OT tasks */ for (uint32_t i = 0; i < m_vKKOTTasks.size(); i++) { m_vKKOTTasks[i].clear(); } + + /* Clear any remaining MTGen tasks */ + for (uint32_t i = 0; i < m_vPKMTGenTasks.size(); i++) { + free(m_vPKMTGenTasks[i]); + } + m_vPKMTGenTasks.clear(); } diff --git a/src/abycore/aby/abysetup.h b/src/abycore/aby/abysetup.h index bfd13544..f0d3d693 100644 --- a/src/abycore/aby/abysetup.h +++ b/src/abycore/aby/abysetup.h @@ -2,17 +2,17 @@ \file abysetup.h \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Contains all methods that are processed during the setup phase of ABY */ @@ -152,19 +152,19 @@ class ABYSetup { BOOL Init(); void Cleanup(); - BOOL ThreadRunNPSnd(uint32_t exec); - BOOL ThreadRunNPRcv(uint32_t exec); + BOOL ThreadRunNPSnd(); + BOOL ThreadRunNPRcv(); - BOOL ThreadRunIKNPSnd(uint32_t exec); - BOOL ThreadRunIKNPRcv(uint32_t exec); + BOOL ThreadRunIKNPSnd(uint32_t threadid); + BOOL ThreadRunIKNPRcv(uint32_t threadid); - BOOL ThreadRunKKSnd(uint32_t exec); - BOOL ThreadRunKKRcv(uint32_t exec); + BOOL ThreadRunKKSnd(uint32_t threadid); + BOOL ThreadRunKKRcv(uint32_t threadid); - BOOL ThreadSendData(uint32_t exec); - BOOL ThreadReceiveData(uint32_t exec); + BOOL ThreadSendData(uint32_t threadid); + BOOL ThreadReceiveData(); - BOOL ThreadRunPaillierMTGen(uint32_t exec); + BOOL ThreadRunPaillierMTGen(uint32_t threadid); BOOL ThreadRunDGKMTGen(uint32_t threadid); // IKNP OTTask values @@ -220,6 +220,9 @@ class ABYSetup { m_eJob = e; m_evt.Set(); } + CEvent* GetEvent() { + return &m_evt; + } private: void ThreadMain(); uint32_t threadid; diff --git a/src/abycore/circuit/abycircuit.cpp b/src/abycore/circuit/abycircuit.cpp index cd8c44bf..04e2f99c 100644 --- a/src/abycore/circuit/abycircuit.cpp +++ b/src/abycore/circuit/abycircuit.cpp @@ -2,17 +2,17 @@ \file abycircuit.cpp \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Implementation of ABY Circuit Class. */ @@ -29,142 +29,144 @@ void ABYCircuit::Cleanup() { Reset(); - free(m_pGates); } -ABYCircuit::ABYCircuit(uint32_t maxgates) { - m_nMaxGates = maxgates; - m_pGates = (GATE*) calloc(maxgates, sizeof(GATE)); - m_nNextFreeGate = 0; - m_nMaxVectorSize = 1; - m_nMaxDepth = 0; +ABYCircuit::ABYCircuit(uint32_t reservegates) : + m_nMaxVectorSize{1}, + m_nMaxDepth{0} +{ + m_vGates.reserve(reservegates); +} + +/** + * Gate ID of the just inserted gate + */ +inline uint32_t ABYCircuit::currentGateId() { + return m_vGates.size() - 1; } -inline void ABYCircuit::InitGate(GATE* gate, e_gatetype type) { +inline GATE* ABYCircuit::InitGate(e_gatetype type) { #ifdef DEBUG_CIRCUIT_CONSTRUCTION std::cout << "Putting new gate with type " << type << std::endl; #endif - if(m_nNextFreeGate >= m_nMaxGates) { - std::cerr << "I have more gates than available: " << m_nNextFreeGate << std::endl; - } - assert(m_nNextFreeGate < m_nMaxGates); - - gate->type = type; - gate->nused = 0; - gate->nrounds = 0; + // We abuse resize() to insert a new zero-initialized GATE struct at the end + // of the gate vector + m_vGates.resize(m_vGates.size() + 1); + m_vGates.back().type = type; + return &(m_vGates.back()); } -inline void ABYCircuit::InitGate(GATE* gate, e_gatetype type, uint32_t ina) { - InitGate(gate, type); +inline GATE* ABYCircuit::InitGate(e_gatetype type, uint32_t ina) { + GATE* gate = InitGate(type); - assert(ina < m_nNextFreeGate); - gate->depth = ComputeDepth(m_pGates[ina]); + assert(ina < GetGateHead()); + gate->depth = ComputeDepth(m_vGates[ina]); m_nMaxDepth = std::max(m_nMaxDepth, gate->depth); gate->ingates.ningates = 1; gate->ingates.inputs.parent = ina; - gate->context = m_pGates[ina].context; - gate->sharebitlen = m_pGates[ina].sharebitlen; + gate->context = m_vGates[ina].context; + gate->sharebitlen = m_vGates[ina].sharebitlen; MarkGateAsUsed(ina); + return gate; } -inline void ABYCircuit::InitGate(GATE* gate, e_gatetype type, uint32_t ina, uint32_t inb) { - InitGate(gate, type); +inline GATE* ABYCircuit::InitGate(e_gatetype type, uint32_t ina, uint32_t inb) { + GATE* gate = InitGate(type); - if(ina >= m_nNextFreeGate || inb >= m_nNextFreeGate) { - std::cout << "ina = " << ina << ", inb = " << inb << ", nfg = " << m_nNextFreeGate << std::endl; - assert(ina < m_nNextFreeGate && inb < m_nNextFreeGate); + if(ina >= GetGateHead() || inb >= GetGateHead()) { + std::cout << "ina = " << ina << ", inb = " << inb << ", nfg = " << GetGateHead() << std::endl; + assert(ina < GetGateHead() && inb < GetGateHead()); } - gate->depth = std::max(ComputeDepth(m_pGates[ina]), ComputeDepth(m_pGates[inb])); + gate->depth = std::max(ComputeDepth(m_vGates[ina]), ComputeDepth(m_vGates[inb])); m_nMaxDepth = std::max(m_nMaxDepth, gate->depth); gate->ingates.ningates = 2; gate->ingates.inputs.twin.left = ina; gate->ingates.inputs.twin.right = inb; - assert(m_pGates[ina].context == m_pGates[inb].context); - assert(m_pGates[ina].sharebitlen == m_pGates[inb].sharebitlen); + assert(m_vGates[ina].context == m_vGates[inb].context); + assert(m_vGates[ina].sharebitlen == m_vGates[inb].sharebitlen); - gate->context = m_pGates[ina].context; - gate->sharebitlen = m_pGates[ina].sharebitlen; + gate->context = m_vGates[ina].context; + gate->sharebitlen = m_vGates[ina].sharebitlen; MarkGateAsUsed(ina); MarkGateAsUsed(inb); + return gate; } -inline void ABYCircuit::InitGate(GATE* gate, e_gatetype type, std::vector& inputs) { - InitGate(gate, type); +inline GATE* ABYCircuit::InitGate(e_gatetype type, std::vector& inputs) { + GATE* gate = InitGate(type); gate->ingates.ningates = inputs.size(); gate->depth = 0; if (inputs.size() == 0) - return; + return gate; uint32_t ina = inputs[0]; - assert(ina < m_nNextFreeGate); + assert(ina < GetGateHead()); - gate->depth = ComputeDepth(m_pGates[ina]); + gate->depth = ComputeDepth(m_vGates[ina]); gate->ingates.inputs.parents = (uint32_t*) malloc(sizeof(uint32_t) * inputs.size()); memcpy(gate->ingates.inputs.parents, inputs.data(), inputs.size() * sizeof(uint32_t)); - gate->context = m_pGates[ina].context; - gate->sharebitlen = m_pGates[ina].sharebitlen; + gate->context = m_vGates[ina].context; + gate->sharebitlen = m_vGates[ina].sharebitlen; MarkGateAsUsed(ina); for (uint32_t i = 1; i < inputs.size(); i++) { - assert(inputs[i] < m_nNextFreeGate); - gate->depth = std::max(gate->depth, ComputeDepth(m_pGates[inputs[i]])); - assert(gate->context == m_pGates[inputs[i]].context); - assert(gate->sharebitlen == m_pGates[inputs[i]].sharebitlen); + assert(inputs[i] < GetGateHead()); + gate->depth = std::max(gate->depth, ComputeDepth(m_vGates[inputs[i]])); + assert(gate->context == m_vGates[inputs[i]].context); + assert(gate->sharebitlen == m_vGates[inputs[i]].sharebitlen); MarkGateAsUsed(inputs[i]); } m_nMaxDepth = std::max(m_nMaxDepth, gate->depth); + return gate; } -//Add a gate to m_pGates, increase the gateptr, used for G_LIN or G_NON_LIN +//Add a gate to m_vGates, increase the gateptr, used for G_LIN or G_NON_LIN uint32_t ABYCircuit::PutPrimitiveGate(e_gatetype type, uint32_t inleft, uint32_t inright, uint32_t rounds) { - GATE* gate = m_pGates + m_nNextFreeGate; - InitGate(gate, type, inleft, inright); + GATE* gate = InitGate(type, inleft, inright); - gate->nvals = std::min(m_pGates[inleft].nvals, m_pGates[inright].nvals); + gate->nvals = std::min(m_vGates[inleft].nvals, m_vGates[inright].nvals); gate->nrounds = rounds; #ifdef DEBUG_CIRCUIT_CONSTRUCTION - std::cout << "New primitive gate with id: " << m_nNextFreeGate << ", left in = " << inleft << ", right in = " << inright << ", nvals = " << gate->nvals << + std::cout << "New primitive gate with id: " << currentGateId() << ", left in = " << inleft << ", right in = " << inright << ", nvals = " << gate->nvals << ", depth = " << gate->depth << ", sharingsize = " << gate->sharebitlen << ", nrounds = " << gate->nrounds << std::endl; #endif - return m_nNextFreeGate++; + return currentGateId(); } //add a vector-MT gate, mostly the same as a standard primitive gate but with explicit choiceinput / vectorinput uint32_t ABYCircuit::PutNonLinearVectorGate(e_gatetype type, uint32_t choiceinput, uint32_t vectorinput, uint32_t rounds) { - GATE* gate = m_pGates + m_nNextFreeGate; - InitGate(gate, type, choiceinput, vectorinput); + GATE* gate = InitGate(type, choiceinput, vectorinput); - assert((m_pGates[vectorinput].nvals % m_pGates[choiceinput].nvals) == 0); + assert((m_vGates[vectorinput].nvals % m_vGates[choiceinput].nvals) == 0); - gate->nvals = m_pGates[vectorinput].nvals; + gate->nvals = m_vGates[vectorinput].nvals; gate->nrounds = rounds; - gate->gs.avs.bitlen = m_pGates[vectorinput].nvals / m_pGates[choiceinput].nvals; + gate->gs.avs.bitlen = m_vGates[vectorinput].nvals / m_vGates[choiceinput].nvals; - return m_nNextFreeGate++; + return currentGateId(); } uint32_t ABYCircuit::PutCombinerGate(std::vector input) { - GATE* gate = m_pGates + m_nNextFreeGate; - InitGate(gate, G_COMBINE, input); + GATE* gate = InitGate(G_COMBINE, input); gate->nvals = 0; for(uint32_t i = 0; i < input.size(); i++) { - //std::cout << "size at i = " << i << ": " << m_pGates[input[i]].nvals << std::endl;; - gate->nvals += m_pGates[input[i]].nvals; + //std::cout << "size at i = " << i << ": " << m_vGates[input[i]].nvals << std::endl;; + gate->nvals += m_vGates[input[i]].nvals; } //std::cout << "Putting combiner gate with nvals = " << gate->nvals << std::endl; @@ -172,25 +174,24 @@ uint32_t ABYCircuit::PutCombinerGate(std::vector input) { if (gate->nvals > m_nMaxVectorSize) m_nMaxVectorSize = gate->nvals; - return m_nNextFreeGate++; + return currentGateId(); } //gatelenghts is defaulted to NULL uint32_t ABYCircuit::PutSplitterGate(uint32_t input, uint32_t pos, uint32_t bitlen) { - GATE* gate = m_pGates + m_nNextFreeGate; - InitGate(gate, G_SPLIT, input); + GATE* gate = InitGate(G_SPLIT, input); gate->gs.sinput.pos = pos; gate->nvals = bitlen; - return m_nNextFreeGate++; + return currentGateId(); } //gatelenghts is defaulted to NULL std::vector ABYCircuit::PutSplitterGate(uint32_t input, std::vector bitlen) { - uint32_t nvals = m_pGates[input].nvals; + uint32_t nvals = m_vGates[input].nvals; if(bitlen.size() == 0) { bitlen.resize(nvals, 1); } @@ -198,16 +199,6 @@ std::vector ABYCircuit::PutSplitterGate(uint32_t input, std::vectorgs.sinput.pos = ctr; - - gate->nvals = 1; - - ctr += gate->nvals; - m_nNextFreeGate++;*/ outids[i] = PutSplitterGate(input, ctr, bitlen[i]); ctr += bitlen[i]; //std::cout << "bitlen[" << i << "] = " << bitlen[i] << std::endl; @@ -220,32 +211,30 @@ std::vector ABYCircuit::PutSplitterGate(uint32_t input, std::vector input, uint32_t pos) { - GATE* gate = m_pGates + m_nNextFreeGate; - InitGate(gate, G_COMBINEPOS, input); + GATE* gate = InitGate(G_COMBINEPOS, input); gate->nvals = input.size(); gate->gs.combinepos.pos = pos; for (uint32_t i = 0; i < input.size(); i++) { - assert(pos < m_pGates[input[i]].nvals); + assert(pos < m_vGates[input[i]].nvals); } if (gate->nvals > m_nMaxVectorSize) m_nMaxVectorSize = gate->nvals; - return m_nNextFreeGate++; + return currentGateId(); } uint32_t ABYCircuit::PutSubsetGate(uint32_t input, uint32_t* posids, uint32_t nvals_out, bool copy_posids) { - GATE* gate = m_pGates + m_nNextFreeGate; - InitGate(gate, G_SUBSET, input); + GATE* gate = InitGate(G_SUBSET, input); gate->nvals = nvals_out; - //std::cout << "Putting subset gate with nvals = " << nvals << " on pos " << m_nNextFreeGate << std::endl; - //assert(gate->nvals <= m_pGates[input].nvals); + //std::cout << "Putting subset gate with nvals = " << nvals << " on pos " << currentGateId() << std::endl; + //assert(gate->nvals <= m_vGates[input].nvals); gate->gs.sub_pos.copy_posids = copy_posids; @@ -261,7 +250,7 @@ uint32_t ABYCircuit::PutSubsetGate(uint32_t input, uint32_t* posids, uint32_t nv //std::cout << "copied" << std::endl; //This check can be left out for performance reasons - uint32_t inputnvals = m_pGates[input].nvals; + uint32_t inputnvals = m_vGates[input].nvals; for (uint32_t i = 0; i < gate->nvals; i++) { assert(posids[i] < inputnvals); } @@ -269,12 +258,11 @@ uint32_t ABYCircuit::PutSubsetGate(uint32_t input, uint32_t* posids, uint32_t nv if (gate->nvals > m_nMaxVectorSize) m_nMaxVectorSize = gate->nvals; - return m_nNextFreeGate++; + return currentGateId(); } uint32_t ABYCircuit::PutStructurizedCombinerGate(std::vector input, uint32_t pos_start, uint32_t pos_incr, uint32_t nvals) { - GATE* gate = m_pGates + m_nNextFreeGate; - InitGate(gate, G_STRUCT_COMBINE, input); + GATE* gate = InitGate(G_STRUCT_COMBINE, input); gate->nvals = nvals; @@ -284,28 +272,27 @@ uint32_t ABYCircuit::PutStructurizedCombinerGate(std::vector input, ui /*std::cout << "From " << pos_start << " incr: " << pos_incr << " for " << nvals << " vals with max = "; for (uint32_t i = 0; i < input.size(); i++) { - std::cout << m_pGates[input[i]].nvals << "; "; - //assert(pos_start + ((nvals-1) * pos_incr) <= m_pGates[input[i]].nvals); + std::cout << m_vGates[input[i]].nvals << "; "; + //assert(pos_start + ((nvals-1) * pos_incr) <= m_vGates[input[i]].nvals); } std::cout << std::endl;*/ if (gate->nvals > m_nMaxVectorSize) m_nMaxVectorSize = gate->nvals; - return m_nNextFreeGate++; + return currentGateId(); } uint32_t ABYCircuit::PutRepeaterGate(uint32_t input, uint32_t nvals) { - GATE* gate = m_pGates + m_nNextFreeGate; - InitGate(gate, G_REPEAT, input); + GATE* gate = InitGate(G_REPEAT, input); gate->nvals = nvals; if (gate->nvals > m_nMaxVectorSize) m_nMaxVectorSize = gate->nvals; - return m_nNextFreeGate++; + return currentGateId(); } std::vector ABYCircuit::PutRepeaterGate(std::vector input, uint32_t nvals) { @@ -317,68 +304,63 @@ std::vector ABYCircuit::PutRepeaterGate(std::vector input, u } uint32_t ABYCircuit::PutPermutationGate(std::vector input, uint32_t* positions) { - GATE* gate = m_pGates + m_nNextFreeGate; - InitGate(gate, G_PERM, input); + GATE* gate = InitGate(G_PERM, input); gate->nvals = input.size(); gate->gs.perm.posids = (uint32_t*) malloc(sizeof(uint32_t) * gate->nvals); for (uint32_t i = 0; i < input.size(); i++) { - assert(positions[i] < m_pGates[input[i]].nvals); + assert(positions[i] < m_vGates[input[i]].nvals); gate->gs.perm.posids[i] = positions[i]; } if (gate->nvals > m_nMaxVectorSize) m_nMaxVectorSize = gate->nvals; - return m_nNextFreeGate++; + return currentGateId(); } uint32_t ABYCircuit::PutUniversalGate(uint32_t inleft, uint32_t inright, uint32_t op_id, uint32_t nrounds) { - GATE* gate = m_pGates + m_nNextFreeGate; - InitGate(gate, G_UNIV, inleft, inright); + GATE* gate = InitGate(G_UNIV, inleft, inright); - gate->nvals = std::min(m_pGates[inleft].nvals, m_pGates[inright].nvals); + gate->nvals = std::min(m_vGates[inleft].nvals, m_vGates[inright].nvals); gate->nrounds = nrounds; gate->gs.ttable = op_id; #ifdef DEBUG_CIRCUIT_CONSTRUCTION - cout << "New Universal Gate with id: " << m_nNextFreeGate << ", left in = " << inleft << ", right in = " << inright << ", nvals = " << gate->nvals << + cout << "New Universal Gate with id: " << currentGateId() << ", left in = " << inleft << ", right in = " << inright << ", nvals = " << gate->nvals << ", depth = " << gate->depth << ", sharingsize = " << gate->sharebitlen << ", nrounds = " << gate->nrounds << ", and operation_id = " << op_id << endl; #endif - return m_nNextFreeGate++; + return currentGateId(); } uint32_t ABYCircuit::PutOUTGate(uint32_t in, e_role dst, uint32_t rounds) { - GATE* gate = m_pGates + m_nNextFreeGate; - InitGate(gate, G_OUT, in); + GATE* gate = InitGate(G_OUT, in); - gate->nvals = m_pGates[in].nvals; + gate->nvals = m_vGates[in].nvals; gate->gs.oshare.dst = dst; gate->nrounds = rounds; - return m_nNextFreeGate++; + return currentGateId(); } uint32_t ABYCircuit::PutSharedOUTGate(uint32_t in) { - GATE* gate = m_pGates + m_nNextFreeGate; - InitGate(gate, G_SHARED_OUT, in); + GATE* gate = InitGate(G_SHARED_OUT, in); - gate->nvals = m_pGates[in].nvals; + gate->nvals = m_vGates[in].nvals; gate->nrounds = 0; - return m_nNextFreeGate++; + return currentGateId(); } uint32_t ABYCircuit::PutINGate(e_sharing context, uint32_t nvals, uint32_t sharebitlen, e_role src, uint32_t rounds) { - GATE* gate = m_pGates + m_nNextFreeGate; - InitGate(gate, G_IN); + GATE* gate = InitGate(G_IN); gate->nvals = nvals; gate->depth = 0; @@ -391,12 +373,11 @@ uint32_t ABYCircuit::PutINGate(e_sharing context, uint32_t nvals, uint32_t share if (gate->nvals > m_nMaxVectorSize) m_nMaxVectorSize = gate->nvals; - return m_nNextFreeGate++; + return currentGateId(); } uint32_t ABYCircuit::PutSharedINGate(e_sharing context, uint32_t nvals, uint32_t sharebitlen) { - GATE* gate = m_pGates + m_nNextFreeGate; - InitGate(gate, G_SHARED_IN); + GATE* gate = InitGate(G_SHARED_IN); gate->nvals = nvals; gate->depth = 0; @@ -408,13 +389,12 @@ uint32_t ABYCircuit::PutSharedINGate(e_sharing context, uint32_t nvals, uint32_t if (gate->nvals > m_nMaxVectorSize) m_nMaxVectorSize = gate->nvals; - return m_nNextFreeGate++; + return currentGateId(); } uint32_t ABYCircuit::PutConstantGate(e_sharing context, UGATE_T val, uint32_t nvals, uint32_t sharebitlen) { assert(nvals > 0 && sharebitlen > 0); - GATE* gate = m_pGates + m_nNextFreeGate; - InitGate(gate, G_CONSTANT); + GATE* gate = InitGate(G_CONSTANT); gate->gs.constval = val; gate->depth = 0; gate->nvals = nvals; @@ -422,34 +402,32 @@ uint32_t ABYCircuit::PutConstantGate(e_sharing context, UGATE_T val, uint32_t nv gate->sharebitlen = sharebitlen; gate->nrounds = 0; - if (gate->nvals > m_nMaxVectorSize) + if(gate->nvals > m_nMaxVectorSize) { m_nMaxVectorSize = gate->nvals; - - return m_nNextFreeGate++; + } + return currentGateId(); } uint32_t ABYCircuit::PutINVGate(uint32_t in) { - GATE* gate = m_pGates + m_nNextFreeGate; - InitGate(gate, G_INV, in); + GATE* gate = InitGate(G_INV, in); - gate->nvals = m_pGates[in].nvals; + gate->nvals = m_vGates[in].nvals; - return m_nNextFreeGate++; + return currentGateId(); } uint32_t ABYCircuit::PutCONVGate(std::vector in, uint32_t nrounds, e_sharing dst, uint32_t sharebitlen) { - GATE* gate = m_pGates + m_nNextFreeGate; - InitGate(gate, G_CONV, in); + GATE* gate = InitGate(G_CONV, in); gate->sharebitlen = sharebitlen; gate->context = dst; gate->nrounds = nrounds; - gate->nvals = m_pGates[in[0]].nvals; + gate->nvals = m_vGates[in[0]].nvals; for (uint32_t i = 0; i < in.size(); i++) { - assert(gate->nvals == m_pGates[in[i]].nvals); + assert(gate->nvals == m_vGates[in[i]].nvals); } - return m_nNextFreeGate++; + return currentGateId(); } std::vector ABYCircuit::PutOUTGate(std::vector in, e_role dst, uint32_t rounds) { @@ -470,8 +448,7 @@ std::vector ABYCircuit::PutSharedOUTGate(std::vector in) { uint32_t ABYCircuit::PutCallbackGate(std::vector in, uint32_t rounds, void (*callback)(GATE*, void*), void* infos, uint32_t nvals) { - GATE* gate = m_pGates + m_nNextFreeGate; - InitGate(gate, G_CALLBACK, in); + GATE* gate = InitGate(G_CALLBACK, in); gate->gs.cbgate.callback = callback; gate->gs.cbgate.infos = infos; @@ -480,13 +457,12 @@ uint32_t ABYCircuit::PutCallbackGate(std::vector in, uint32_t rounds, gate->nvals = nvals; - return m_nNextFreeGate++; + return currentGateId(); } uint32_t ABYCircuit::PutTruthTableGate(std::vector in, uint32_t rounds, uint32_t out_bits, uint64_t* truth_table) { - GATE* gate = m_pGates + m_nNextFreeGate; - InitGate(gate, G_TT, in); + GATE* gate = InitGate(G_TT, in); assert(in.size() < 32); assert(in.size() > 0); @@ -498,31 +474,30 @@ uint32_t ABYCircuit::PutTruthTableGate(std::vector in, uint32_t rounds gate->nrounds = rounds; - gate->nvals = m_pGates[in[0]].nvals*out_bits; + gate->nvals = m_vGates[in[0]].nvals*out_bits; for(uint32_t i = 1; i < in.size(); i++) { - assert(gate->nvals/out_bits == m_pGates[in[i]].nvals); + assert(gate->nvals/out_bits == m_vGates[in[i]].nvals); } #ifdef DEBUGBOOL_NO_MT std::cout << "Putting TT gate at depth " << gate->depth << ", predec. "; for(uint32_t i = 0; i < in.size(); i++) { - std::cout << i << ": " << get_gate_type_name(m_pGates[in[0]].type) << " has depth " - << m_pGates[in[0]].depth << " and rounds " << m_pGates[in[0]].nrounds << ", "; + std::cout << i << ": " << get_gate_type_name(m_vGates[in[0]].type) << " has depth " + << m_vGates[in[0]].depth << " and rounds " << m_vGates[in[0]].nrounds << ", "; } std::cout << "my nvals = " << gate->nvals << " and " << out_bits << " output bits "<< std::endl; #endif - return m_nNextFreeGate++; + return currentGateId(); } //TODO change gs.infostr to string uint32_t ABYCircuit::PutPrintValGate(std::vector in, std::string infostr) { - GATE* gate = m_pGates + m_nNextFreeGate; - InitGate(gate, G_PRINT_VAL, in); + GATE* gate = InitGate(G_PRINT_VAL, in); - gate->nvals = m_pGates[in[0]].nvals; + gate->nvals = m_vGates[in[0]].nvals; for(uint32_t i = 1; i < in.size(); i++) { - assert(gate->nvals == m_pGates[in[i]].nvals); + assert(gate->nvals == m_vGates[in[i]].nvals); } // buffer is freed in Sharing::EvaluatePrintValGate @@ -531,17 +506,16 @@ uint32_t ABYCircuit::PutPrintValGate(std::vector in, std::string infos buffer[infostr.size()] = '\0'; gate->gs.infostr = buffer; - return m_nNextFreeGate++; + return currentGateId(); } uint32_t ABYCircuit::PutAssertGate(std::vector in, uint32_t bitlen, UGATE_T* assert_val) { - GATE* gate = m_pGates + m_nNextFreeGate; - InitGate(gate, G_ASSERT, in); + GATE* gate = InitGate(G_ASSERT, in); - gate->nvals = m_pGates[in[0]].nvals; + gate->nvals = m_vGates[in[0]].nvals; for(uint32_t i = 1; i < in.size(); i++) { - assert(gate->nvals == m_pGates[in[i]].nvals); + assert(gate->nvals == m_vGates[in[i]].nvals); } //initialize a new block of memory and copy the assert_val into this block @@ -549,7 +523,7 @@ uint32_t ABYCircuit::PutAssertGate(std::vector in, uint32_t bitlen, UG gate->gs.assertval = (UGATE_T*) calloc(ugatelen, sizeof(UGATE_T)); memcpy(gate->gs.assertval, assert_val, ugatelen * sizeof(UGATE_T)); - return m_nNextFreeGate++; + return currentGateId(); } @@ -570,8 +544,8 @@ uint32_t ABYCircuit::PutAssertGate(std::vector in, uint32_t bitlen, UG #ifdef DEBUGBOOL_NO_MT std::cout << "Putting mutli output TT gate at depth " << gate->depth << ", predec. "; for(uint32_t i = 0; i < in.size(); i++) { - std::cout << i << ": " << get_gate_type_name(m_pGates[in[0]].type) << " has depth " - << m_pGates[in[0]].depth << " and rounds " << m_pGates[in[0]].nrounds << ", "; + std::cout << i << ": " << get_gate_type_name(m_vGates[in[0]].type) << " has depth " + << m_vGates[in[0]].depth << " and rounds " << m_vGates[in[0]].nrounds << ", "; } std::cout << "my nvals = " << gate->nvals << std::endl; #endif @@ -583,11 +557,11 @@ uint32_t ABYCircuit::PutAssertGate(std::vector in, uint32_t bitlen, UG void ABYCircuit::ExportCircuitInBristolFormat(std::vector ingates_client, std::vector ingates_server, std::vector outgates, const char* filename) { //Maps an ABY gate-id into a Bristol gate-id - std::vector gate_id_map(m_nNextFreeGate, -1); + std::vector gate_id_map(m_vGates.size(), -1); //The ABY output gates are not requried and the circuit has to make sure that the output gates appear last std::vector outgate_map(outgates.size()); //There are no constants in the Bristol circuit and hence they need to be propagated using this vector. Init with -1 to show that input is not a constant. - std::vector constant_map(m_nNextFreeGate, -1); + std::vector constant_map(m_vGates.size(), -1); //keeps track of the next free gate id in the Bristol circuit uint32_t bristol_gate_ctr = 0; //a temporary value for assigning the correct id to output gates @@ -624,7 +598,7 @@ void ABYCircuit::ExportCircuitInBristolFormat(std::vector ingates_clie //Remove the ABY output gates for(uint32_t i = 0; i < outgates.size(); i++) { - outgate_map[i] = m_pGates[outgates[i]].ingates.inputs.parent; + outgate_map[i] = m_vGates[outgates[i]].ingates.inputs.parent; } //Check whether any input gates are also output gates. If so, create an extra XOR gate that evaluates to zero and give the output gates again @@ -650,8 +624,8 @@ void ABYCircuit::ExportCircuitInBristolFormat(std::vector ingates_clie total_bristol_gates = bristol_gate_ctr + n_in_out_gates; //count the total number of gates in the Bristol circuit prior to printing the circuit - for(uint32_t i = 0; i < m_nNextFreeGate; i++) { - if(m_pGates[i].type == G_LIN || m_pGates[i].type == G_NON_LIN || m_pGates[i].type == G_INV) { + for(uint32_t i = 0; i < m_vGates.size(); i++) { + if(m_vGates[i].type == G_LIN || m_vGates[i].type == G_NON_LIN || m_vGates[i].type == G_INV) { total_bristol_gates++; } } @@ -683,7 +657,7 @@ void ABYCircuit::ExportCircuitInBristolFormat(std::vector ingates_clie } //Now go through all gates in the ABY circuit - for(uint32_t i = 0; i < m_nNextFreeGate; i++) { + for(uint32_t i = 0; i < m_vGates.size(); i++) { out_gate_present = false; //skip the output gates since they need to be in order for the Bristol file format for(uint32_t j = 0; j < outgate_map.size(); j++) { @@ -707,41 +681,41 @@ void ABYCircuit::ExportCircuitInBristolFormat(std::vector ingates_clie void ABYCircuit::ExportGateInBristolFormat(uint32_t gateid, uint32_t& next_gate_id, std::vector& gate_id_map, std::vector& constant_map, std::ofstream& outfile) { - if(m_pGates[gateid].type == G_IN) { + if(m_vGates[gateid].type == G_IN) { //Ignore input gates - } else if(m_pGates[gateid].type == G_LIN) { + } else if(m_vGates[gateid].type == G_LIN) { //enter gate into map - if(constant_map[m_pGates[gateid].ingates.inputs.twin.left] + constant_map[m_pGates[gateid].ingates.inputs.twin.right] != -2) { + if(constant_map[m_vGates[gateid].ingates.inputs.twin.left] + constant_map[m_vGates[gateid].ingates.inputs.twin.right] != -2) { CheckAndPropagateConstant(gateid, next_gate_id, gate_id_map, constant_map, outfile); } else { - outfile << "2 1 " << gate_id_map[m_pGates[gateid].ingates.inputs.twin.left] << " " << gate_id_map[m_pGates[gateid].ingates.inputs.twin.right] << " " << next_gate_id << " XOR"<< std::endl; + outfile << "2 1 " << gate_id_map[m_vGates[gateid].ingates.inputs.twin.left] << " " << gate_id_map[m_vGates[gateid].ingates.inputs.twin.right] << " " << next_gate_id << " XOR"<< std::endl; gate_id_map[gateid] = next_gate_id++; } - } else if(m_pGates[gateid].type == G_NON_LIN) { - if(constant_map[m_pGates[gateid].ingates.inputs.twin.left] + constant_map[m_pGates[gateid].ingates.inputs.twin.right] != -2) { + } else if(m_vGates[gateid].type == G_NON_LIN) { + if(constant_map[m_vGates[gateid].ingates.inputs.twin.left] + constant_map[m_vGates[gateid].ingates.inputs.twin.right] != -2) { CheckAndPropagateConstant(gateid, next_gate_id, gate_id_map, constant_map, outfile); } else { - outfile << "2 1 " << gate_id_map[m_pGates[gateid].ingates.inputs.twin.left] << " " << gate_id_map[m_pGates[gateid].ingates.inputs.twin.right] << " " << next_gate_id << " AND"<< std::endl; + outfile << "2 1 " << gate_id_map[m_vGates[gateid].ingates.inputs.twin.left] << " " << gate_id_map[m_vGates[gateid].ingates.inputs.twin.right] << " " << next_gate_id << " AND"<< std::endl; gate_id_map[gateid] = next_gate_id++; } - } else if(m_pGates[gateid].type == G_INV) { - if(constant_map[m_pGates[gateid].ingates.inputs.parent] != -1) { - if(constant_map[m_pGates[gateid].ingates.inputs.parent] == 0) { - constant_map[gateid] = constant_map[m_pGates[gateid].ingates.inputs.parent]; + } else if(m_vGates[gateid].type == G_INV) { + if(constant_map[m_vGates[gateid].ingates.inputs.parent] != -1) { + if(constant_map[m_vGates[gateid].ingates.inputs.parent] == 0) { + constant_map[gateid] = constant_map[m_vGates[gateid].ingates.inputs.parent]; } else { - constant_map[gateid] = constant_map[m_pGates[gateid].ingates.inputs.parent] ^ 1; + constant_map[gateid] = constant_map[m_vGates[gateid].ingates.inputs.parent] ^ 1; } } else { - outfile << "1 1 " << gate_id_map[m_pGates[gateid].ingates.inputs.parent] << " " << next_gate_id << " INV"<< std::endl; + outfile << "1 1 " << gate_id_map[m_vGates[gateid].ingates.inputs.parent] << " " << next_gate_id << " INV"<< std::endl; gate_id_map[gateid] = next_gate_id++; } - } else if(m_pGates[gateid].type == G_CONSTANT) { - assert(m_pGates[gateid].gs.constval == 0 || m_pGates[gateid].gs.constval == 1); - constant_map[gateid] = m_pGates[gateid].gs.constval; - } else if(m_pGates[gateid].type == G_OUT) { + } else if(m_vGates[gateid].type == G_CONSTANT) { + assert(m_vGates[gateid].gs.constval == 0 || m_vGates[gateid].gs.constval == 1); + constant_map[gateid] = m_vGates[gateid].gs.constval; + } else if(m_vGates[gateid].type == G_OUT) { //Ignore input gates } else { - std::cerr << "Gate type not available in Bristol format: " << get_gate_type_name(m_pGates[gateid].type) << ". Program exits. " << std::endl; + std::cerr << "Gate type not available in Bristol format: " << get_gate_type_name(m_vGates[gateid].type) << ". Program exits. " << std::endl; outfile.close(); std::exit(EXIT_FAILURE); } @@ -751,71 +725,71 @@ void ABYCircuit::CheckAndPropagateConstant(uint32_t gateid, uint32_t& next_gate_ std::vector& constant_map, std::ofstream& outfile) { //both gates are constant zero - if(constant_map[m_pGates[gateid].ingates.inputs.twin.left] == 0 && constant_map[m_pGates[gateid].ingates.inputs.twin.right] == 0) { + if(constant_map[m_vGates[gateid].ingates.inputs.twin.left] == 0 && constant_map[m_vGates[gateid].ingates.inputs.twin.right] == 0) { constant_map[gateid] = 0; return; } //both gates are constant one - if(constant_map[m_pGates[gateid].ingates.inputs.twin.left] + constant_map[m_pGates[gateid].ingates.inputs.twin.right] == 2) { - if(m_pGates[gateid].type == G_LIN) { + if(constant_map[m_vGates[gateid].ingates.inputs.twin.left] + constant_map[m_vGates[gateid].ingates.inputs.twin.right] == 2) { + if(m_vGates[gateid].type == G_LIN) { constant_map[gateid] = 0; - } else if( m_pGates[gateid].type == G_NON_LIN) { + } else if( m_vGates[gateid].type == G_NON_LIN) { constant_map[gateid] = 1; } return; } //one gate is constant one, the second constant zero - if(constant_map[m_pGates[gateid].ingates.inputs.twin.left] + constant_map[m_pGates[gateid].ingates.inputs.twin.right] == 1) { - if(m_pGates[gateid].type == G_LIN) { + if(constant_map[m_vGates[gateid].ingates.inputs.twin.left] + constant_map[m_vGates[gateid].ingates.inputs.twin.right] == 1) { + if(m_vGates[gateid].type == G_LIN) { constant_map[gateid] = 1; - } else if( m_pGates[gateid].type == G_NON_LIN) { + } else if( m_vGates[gateid].type == G_NON_LIN) { constant_map[gateid] = 0; } return; } //one gate is has a constant zero, the other gate is not a constant - if(constant_map[m_pGates[gateid].ingates.inputs.twin.left] + constant_map[m_pGates[gateid].ingates.inputs.twin.right] == -1) { - if(m_pGates[gateid].type == G_LIN) { - if(constant_map[m_pGates[gateid].ingates.inputs.twin.left] == -1) { - gate_id_map[gateid] = gate_id_map[m_pGates[gateid].ingates.inputs.twin.left]; + if(constant_map[m_vGates[gateid].ingates.inputs.twin.left] + constant_map[m_vGates[gateid].ingates.inputs.twin.right] == -1) { + if(m_vGates[gateid].type == G_LIN) { + if(constant_map[m_vGates[gateid].ingates.inputs.twin.left] == -1) { + gate_id_map[gateid] = gate_id_map[m_vGates[gateid].ingates.inputs.twin.left]; } else { - gate_id_map[gateid] = gate_id_map[m_pGates[gateid].ingates.inputs.twin.right]; + gate_id_map[gateid] = gate_id_map[m_vGates[gateid].ingates.inputs.twin.right]; } - } else if( m_pGates[gateid].type == G_NON_LIN) { + } else if( m_vGates[gateid].type == G_NON_LIN) { constant_map[gateid] = 0; } return; } //one gate is has a constant one, the other gate is not a constant - if(constant_map[m_pGates[gateid].ingates.inputs.twin.left] + constant_map[m_pGates[gateid].ingates.inputs.twin.right] == 0) { - if(m_pGates[gateid].type == G_LIN) { - if(constant_map[m_pGates[gateid].ingates.inputs.twin.left] == -1) { - outfile << "1 1 " << gate_id_map[m_pGates[gateid].ingates.inputs.twin.left] << " " << next_gate_id << " INV"<< std::endl; + if(constant_map[m_vGates[gateid].ingates.inputs.twin.left] + constant_map[m_vGates[gateid].ingates.inputs.twin.right] == 0) { + if(m_vGates[gateid].type == G_LIN) { + if(constant_map[m_vGates[gateid].ingates.inputs.twin.left] == -1) { + outfile << "1 1 " << gate_id_map[m_vGates[gateid].ingates.inputs.twin.left] << " " << next_gate_id << " INV"<< std::endl; gate_id_map[gateid] = next_gate_id++; } else { - outfile << "1 1 " << gate_id_map[m_pGates[gateid].ingates.inputs.twin.right] << " " << next_gate_id << " INV"<< std::endl; + outfile << "1 1 " << gate_id_map[m_vGates[gateid].ingates.inputs.twin.right] << " " << next_gate_id << " INV"<< std::endl; gate_id_map[gateid] = next_gate_id++; } - } else if( m_pGates[gateid].type == G_NON_LIN) { - if(constant_map[m_pGates[gateid].ingates.inputs.twin.left] == -1) { - gate_id_map[gateid] = gate_id_map[m_pGates[gateid].ingates.inputs.twin.left]; + } else if( m_vGates[gateid].type == G_NON_LIN) { + if(constant_map[m_vGates[gateid].ingates.inputs.twin.left] == -1) { + gate_id_map[gateid] = gate_id_map[m_vGates[gateid].ingates.inputs.twin.left]; } else { - gate_id_map[gateid] = gate_id_map[m_pGates[gateid].ingates.inputs.twin.right]; + gate_id_map[gateid] = gate_id_map[m_vGates[gateid].ingates.inputs.twin.right]; } } return; } //The code must have stopped before from one of the conditions assert(false); - //std::cout << "Ran through code and missed something for " << constant_map[m_pGates[gateid].ingates.inputs.twin.left] << ", " << constant_map[m_pGates[gateid].ingates.inputs.twin.right] << std::endl; + //std::cout << "Ran through code and missed something for " << constant_map[m_vGates[gateid].ingates.inputs.twin.left] << ", " << constant_map[m_vGates[gateid].ingates.inputs.twin.right] << std::endl; } inline void ABYCircuit::MarkGateAsUsed(uint32_t gateid, uint32_t uses) { - m_pGates[gateid].nused += uses; + m_vGates[gateid].nused += uses; } @@ -831,8 +805,7 @@ uint32_t FindBitLenPositionInVec(uint32_t bitlen, non_lin_vec_ctx* list, uint32_ } void ABYCircuit::Reset() { - memset(m_pGates, 0, sizeof(GATE) * m_nMaxGates); - m_nNextFreeGate = 0; + m_vGates.clear(); m_nMaxVectorSize = 1; m_nMaxDepth = 0; } diff --git a/src/abycore/circuit/abycircuit.h b/src/abycore/circuit/abycircuit.h index d0f6367a..30c7571f 100644 --- a/src/abycore/circuit/abycircuit.h +++ b/src/abycore/circuit/abycircuit.h @@ -2,17 +2,17 @@ \file abycircuit.h \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief ABYCircuit class. */ #ifndef __ABYCIRCUIT_H_ @@ -186,15 +186,15 @@ uint32_t FindBitLenPositionInVec(uint32_t bitlen, non_lin_vec_ctx* list, uint32_ class ABYCircuit { public: - ABYCircuit(uint32_t maxgates); + ABYCircuit(uint32_t reservegates); virtual ~ABYCircuit() { Cleanup(); } void Cleanup(); void Reset(); - GATE* Gates() { - return m_pGates; + inline std::vector& GatesVec() { + return m_vGates; } uint32_t PutPrimitiveGate(e_gatetype type, uint32_t inleft, uint32_t inright, uint32_t rounds); @@ -232,7 +232,7 @@ class ABYCircuit { uint32_t PutAssertGate(std::vector in, uint32_t bitlen, UGATE_T* assert_val); uint32_t GetGateHead() { - return m_nNextFreeGate; + return m_vGates.size(); } uint32_t GetTotalDepth() { @@ -248,11 +248,11 @@ class ABYCircuit { std::vector outgates, const char* filename); private: - - inline void InitGate(GATE* gate, e_gatetype type); - inline void InitGate(GATE* gate, e_gatetype type, uint32_t ina); - inline void InitGate(GATE* gate, e_gatetype type, uint32_t ina, uint32_t inb); - inline void InitGate(GATE* gate, e_gatetype type, std::vector& inputs); + inline uint32_t currentGateId(); + inline GATE* InitGate(e_gatetype type); + inline GATE* InitGate(e_gatetype type, uint32_t ina); + inline GATE* InitGate(e_gatetype type, uint32_t ina, uint32_t inb); + inline GATE* InitGate(e_gatetype type, std::vector& inputs); inline uint32_t GetNumRounds(e_gatetype type, e_sharing context); inline void MarkGateAsUsed(uint32_t gateid, uint32_t uses = 1); @@ -262,10 +262,8 @@ class ABYCircuit { void CheckAndPropagateConstant(uint32_t gateid, uint32_t& next_gate_id, std::vector& gate_id_map, std::vector& constant_map, std::ofstream& outfile); - GATE* m_pGates; - uint32_t m_nNextFreeGate; // points to the current first unused gate + std::vector m_vGates; uint32_t m_nMaxVectorSize; // The maximum vector size in bits, required for correctly instantiating the 0 and 1 gates - uint32_t m_nMaxGates; // Maximal number of gates that is allowed uint32_t m_nMaxDepth; // maximum depth encountered in the circuit }; diff --git a/src/abycore/circuit/arithmeticcircuits.cpp b/src/abycore/circuit/arithmeticcircuits.cpp index f9fd2d79..7fcc4373 100644 --- a/src/abycore/circuit/arithmeticcircuits.cpp +++ b/src/abycore/circuit/arithmeticcircuits.cpp @@ -2,17 +2,17 @@ \file arithmeticcircuits.cpp \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Arithmetic Circuit class. */ @@ -50,7 +50,7 @@ share* ArithmeticCircuit::PutMULGate(share* ina, share* inb) { uint32_t ArithmeticCircuit::PutMULGate(uint32_t inleft, uint32_t inright) { // check if one of the inputs is a const gate and then use a MULCONST gate // instead. - if (m_pGates[inleft].type == G_CONSTANT || m_pGates[inright].type == G_CONSTANT) { + if (m_vGates[inleft].type == G_CONSTANT || m_vGates[inright].type == G_CONSTANT) { #ifdef DEBUGARITH std::cout << "MUL(" << inleft << ", " << inright << "): Constant factor present, putting a MULCONST gate instead." << std::endl; @@ -61,9 +61,9 @@ uint32_t ArithmeticCircuit::PutMULGate(uint32_t inleft, uint32_t inright) { uint32_t gateid = m_cCircuit->PutPrimitiveGate(G_NON_LIN, inleft, inright, m_nRoundsAND); UpdateInteractiveQueue(gateid); - if (m_pGates[gateid].nvals != INT_MAX) { + if (m_vGates[gateid].nvals != INT_MAX) { //TODO implement for NON_LIN_VEC - m_nMULs += m_pGates[gateid].nvals; + m_nMULs += m_vGates[gateid].nvals; } return gateid; } @@ -76,8 +76,8 @@ share* ArithmeticCircuit::PutMULCONSTGate(share* ina, share* inb) { uint32_t ArithmeticCircuit::PutMULCONSTGate(uint32_t inleft, uint32_t inright) { // One of the gates needs to be a constant gate - assert (m_pGates[inleft].type == G_CONSTANT || m_pGates[inright].type == G_CONSTANT); - if (m_pGates[inleft].type == G_CONSTANT && m_pGates[inright].type == G_CONSTANT) { + assert (m_vGates[inleft].type == G_CONSTANT || m_vGates[inright].type == G_CONSTANT); + if (m_vGates[inleft].type == G_CONSTANT && m_vGates[inright].type == G_CONSTANT) { std::cerr << "MULCONST(" << inleft << "," << inright << "): Both sides are constants, consider just multiplying their values before adding them as CONST gates.\n"; } @@ -119,17 +119,17 @@ uint32_t ArithmeticCircuit::PutINGate(e_role src) { switch (src) { case SERVER: m_vInputGates[0].push_back(gateid); - m_vInputBits[0] += (m_pGates[gateid].nvals * m_nShareBitLen); + m_vInputBits[0] += (m_vGates[gateid].nvals * m_nShareBitLen); break; case CLIENT: m_vInputGates[1].push_back(gateid); - m_vInputBits[1] += (m_pGates[gateid].nvals * m_nShareBitLen); + m_vInputBits[1] += (m_vGates[gateid].nvals * m_nShareBitLen); break; case ALL: m_vInputGates[0].push_back(gateid); m_vInputGates[1].push_back(gateid); - m_vInputBits[0] += (m_pGates[gateid].nvals * m_nShareBitLen); - m_vInputBits[1] += (m_pGates[gateid].nvals * m_nShareBitLen); + m_vInputBits[0] += (m_vGates[gateid].nvals * m_nShareBitLen); + m_vInputBits[1] += (m_vGates[gateid].nvals * m_nShareBitLen); break; default: std::cerr << "Role not recognized" << std::endl; @@ -151,17 +151,17 @@ uint32_t ArithmeticCircuit::PutSIMDINGate(uint32_t ninvals, e_role src) { switch (src) { case SERVER: m_vInputGates[0].push_back(gateid); - m_vInputBits[0] += (m_pGates[gateid].nvals * m_nShareBitLen); + m_vInputBits[0] += (m_vGates[gateid].nvals * m_nShareBitLen); break; case CLIENT: m_vInputGates[1].push_back(gateid); - m_vInputBits[1] += (m_pGates[gateid].nvals * m_nShareBitLen); + m_vInputBits[1] += (m_vGates[gateid].nvals * m_nShareBitLen); break; case ALL: m_vInputGates[0].push_back(gateid); m_vInputGates[1].push_back(gateid); - m_vInputBits[0] += (m_pGates[gateid].nvals * m_nShareBitLen); - m_vInputBits[1] += (m_pGates[gateid].nvals * m_nShareBitLen); + m_vInputBits[0] += (m_vGates[gateid].nvals * m_nShareBitLen); + m_vInputBits[1] += (m_vGates[gateid].nvals * m_nShareBitLen); break; default: std::cerr << "Role not recognized" << std::endl; @@ -179,12 +179,12 @@ uint32_t ArithmeticCircuit::PutSharedSIMDINGate(uint32_t ninvals) { } -share* ArithmeticCircuit::PutDummyINGate(uint32_t bitlen) { +share* ArithmeticCircuit::PutDummyINGate([[maybe_unused]] uint32_t bitlen) { std::vector wires(1); wires[0] = PutINGate((e_role) !m_eMyRole); return new arithshare(wires, this); } -share* ArithmeticCircuit::PutDummySIMDINGate(uint32_t nvals, uint32_t bitlen) { +share* ArithmeticCircuit::PutDummySIMDINGate(uint32_t nvals, [[maybe_unused]] uint32_t bitlen) { std::vector wires(1); wires[0] = PutSIMDINGate(nvals, (e_role) !m_eMyRole); return new arithshare(wires, this); @@ -199,17 +199,17 @@ uint32_t ArithmeticCircuit::PutOUTGate(uint32_t parentid, e_role dst) { switch (dst) { case SERVER: m_vOutputGates[0].push_back(gateid); - m_vOutputBits[0] += (m_pGates[gateid].nvals * m_nShareBitLen); + m_vOutputBits[0] += (m_vGates[gateid].nvals * m_nShareBitLen); break; case CLIENT: m_vOutputGates[1].push_back(gateid); - m_vOutputBits[1] += (m_pGates[gateid].nvals * m_nShareBitLen); + m_vOutputBits[1] += (m_vGates[gateid].nvals * m_nShareBitLen); break; case ALL: m_vOutputGates[0].push_back(gateid); m_vOutputGates[1].push_back(gateid); - m_vOutputBits[0] += (m_pGates[gateid].nvals * m_nShareBitLen); - m_vOutputBits[1] += (m_pGates[gateid].nvals * m_nShareBitLen); + m_vOutputBits[0] += (m_vGates[gateid].nvals * m_nShareBitLen); + m_vOutputBits[1] += (m_vGates[gateid].nvals * m_nShareBitLen); break; default: std::cerr << "Role not recognized" << std::endl; @@ -251,7 +251,7 @@ uint32_t ArithmeticCircuit::PutINVGate(uint32_t parentid) { uint32_t ArithmeticCircuit::PutCONVGate(std::vector parentids) { uint32_t gateid = m_cCircuit->PutCONVGate(parentids, 2, S_ARITH, m_nShareBitLen); UpdateInteractiveQueue(gateid); - m_nCONVGates += m_pGates[gateid].nvals * parentids.size(); + m_nCONVGates += m_vGates[gateid].nvals * parentids.size(); return gateid; } @@ -281,40 +281,79 @@ share* ArithmeticCircuit::PutCallbackGate(share* in, uint32_t rounds, void (*cal return new arithshare(gateid, this); } -share* ArithmeticCircuit::PutTruthTableGate(share* in, uint64_t* ttable) { - std::cerr << "PutTruthTableGate not implemented in ArithmeticCircuit!!" << std::endl; - return NULL; -} - -share* ArithmeticCircuit::PutTruthTableMultiOutputGate(share* in, uint32_t out_bits, uint64_t* ttable) { - std::cerr << "PutTruthTableMultiOutputGate not implemented in ArithmeticCircuit!!" << std::endl; - return NULL; -} - share* ArithmeticCircuit::PutCONSGate(uint8_t* val, uint32_t bitlen) { - //TODO - std::cerr << "Not implemented yet!" << std::endl; - return NULL; //new arithshare(0, this); + return PutSIMDCONSGate(1, val, bitlen); } +//TODO Test the gates properly share* ArithmeticCircuit::PutSIMDCONSGate(uint32_t nvals, uint8_t* val, uint32_t bitlen) { - //TODO - std::cerr << "Not implemented yet!" << std::endl; - return NULL; //new arithshare(0, this); + uint8_t sharebytes = m_nShareBitLen / 8; + uint32_t valamount = bitlen / m_nShareBitLen; + std::vector gateids(valamount); + for(uint32_t i = 0; i < valamount; ++i) { + UGATE_T one_val = 0; + for(uint8_t j = 0; j < sharebytes; ++j) { + one_val |= val[i * sharebytes + j] << (j * 8); + } + gateids[i] = PutConstantGate(one_val, nvals); + } + return new arithshare(gateids, this); } share* ArithmeticCircuit::PutCONSGate(uint32_t* val, uint32_t bitlen) { - //TODO - std::cerr << "Not implemented yet!" << std::endl; - return NULL; //new arithshare(0, this); + return PutSIMDCONSGate(1, val, bitlen); } +//TODO Test the gates properly share* ArithmeticCircuit::PutSIMDCONSGate(uint32_t nvals, uint32_t* val, uint32_t bitlen) { - //TODO - std::cerr << "Not implemented yet!" << std::endl; - return NULL; //new arithshare(0, this); + uint32_t valamount = bitlen / m_nShareBitLen; + std::vector gateids(valamount); + if(m_nShareBitLen == 64) { + for(uint32_t i = 0; i < valamount; ++i) { + gateids[i] = PutConstantGate(((UGATE_T) val[i * 2]) + (((UGATE_T) val[i * 2 + 1]) << 32), nvals); + } + } else if(m_nShareBitLen == 32){ + for(uint32_t i = 0; i < valamount; ++i) { + gateids[i] = PutConstantGate((UGATE_T) val[i], nvals); + } + } else if(m_nShareBitLen == 16) { + uint32_t loopamount = valamount / 2; + for(uint32_t i = 0; i < loopamount; ++i) { + gateids[i * 2] = PutConstantGate((UGATE_T) (val[i] & 0x0000FFFF), nvals); + gateids[i * 2 + 1] = PutConstantGate((UGATE_T) (val[i] & 0xFFFF0000) >> 16, nvals); + } + if(valamount % 2 == 1) { + uint32_t lastamount = valamount - 1; + gateids[lastamount] = PutConstantGate((UGATE_T) (val[loopamount] & 0x0000FFFF), nvals); + } + } else { //m_nShareBitLen == 8 + uint32_t loopamount = valamount / 4; + for(uint32_t i = 0; i < loopamount; ++i) { + gateids[i * 4] = PutConstantGate((UGATE_T) (val[i] & 0x000000FF), nvals); + gateids[i * 4 + 1] = PutConstantGate((UGATE_T) (val[i] & 0x0000FF00) >> 8, nvals); + gateids[i * 4 + 2] = PutConstantGate((UGATE_T) (val[i] & 0x00FF0000) >> 16, nvals); + gateids[i * 4 + 3] = PutConstantGate((UGATE_T) (val[i] & 0xFF000000) >> 24, nvals); + } + if(valamount % 4 == 1) { + uint32_t lastamount = valamount - 1; + gateids[lastamount] = PutConstantGate((UGATE_T) (val[loopamount] & 0x000000FF), nvals); + } else if(valamount % 4 == 2) { + uint32_t lastamount = valamount - 1; + uint32_t secondlastamount = valamount - 2; + gateids[secondlastamount] = PutConstantGate((UGATE_T) (val[loopamount] & 0x000000FF), nvals); + gateids[lastamount] = PutConstantGate((UGATE_T) (val[loopamount] & 0x0000FF00) >> 8, nvals); + } else if(valamount % 4 == 3) { + uint32_t lastamount = valamount - 1; + uint32_t secondlastamount = valamount - 2; + uint32_t thirdlastamount = valamount - 3; + gateids[thirdlastamount] = PutConstantGate((UGATE_T) (val[loopamount] & 0x000000FF), nvals); + gateids[secondlastamount] = PutConstantGate((UGATE_T) (val[loopamount] & 0x0000FF00) >> 8, nvals); + gateids[lastamount] = PutConstantGate((UGATE_T) (val[loopamount] & 0x00FF0000) >> 16, nvals); + } + } + return new arithshare(gateids, this); } @@ -336,24 +375,24 @@ share* ArithmeticCircuit::PutB2AGate(share* ina) { //enqueue interactive gate queue void ArithmeticCircuit::UpdateInteractiveQueue(uint32_t gateid) { - if (m_pGates[gateid].depth + 1 > m_vInteractiveQueueOnLvl.size()) { - m_vInteractiveQueueOnLvl.resize(m_pGates[gateid].depth + 1); - if (m_pGates[gateid].depth + 1 > m_nMaxDepth) { - m_nMaxDepth = m_pGates[gateid].depth + 1; + if (m_vGates[gateid].depth + 1 > m_vInteractiveQueueOnLvl.size()) { + m_vInteractiveQueueOnLvl.resize(m_vGates[gateid].depth + 1); + if (m_vGates[gateid].depth + 1 > m_nMaxDepth) { + m_nMaxDepth = m_vGates[gateid].depth + 1; } } - m_vInteractiveQueueOnLvl[m_pGates[gateid].depth].push_back(gateid); + m_vInteractiveQueueOnLvl[m_vGates[gateid].depth].push_back(gateid); } //enqueue locally evaluated gate queue void ArithmeticCircuit::UpdateLocalQueue(uint32_t gateid) { - if (m_pGates[gateid].depth + 1 > m_vLocalQueueOnLvl.size()) { - m_vLocalQueueOnLvl.resize(m_pGates[gateid].depth + 1); - if (m_pGates[gateid].depth + 1 > m_nMaxDepth) { - m_nMaxDepth = m_pGates[gateid].depth + 1; + if (m_vGates[gateid].depth + 1 > m_vLocalQueueOnLvl.size()) { + m_vLocalQueueOnLvl.resize(m_vGates[gateid].depth + 1); + if (m_vGates[gateid].depth + 1 > m_nMaxDepth) { + m_nMaxDepth = m_vGates[gateid].depth + 1; } } - m_vLocalQueueOnLvl[m_pGates[gateid].depth].push_back(gateid); + m_vLocalQueueOnLvl[m_vGates[gateid].depth].push_back(gateid); } void ArithmeticCircuit::Reset() { diff --git a/src/abycore/circuit/arithmeticcircuits.h b/src/abycore/circuit/arithmeticcircuits.h index cf50fe41..f78b72a4 100644 --- a/src/abycore/circuit/arithmeticcircuits.h +++ b/src/abycore/circuit/arithmeticcircuits.h @@ -2,17 +2,17 @@ \file arithmeticcircuits.h \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief A collection of boolean circuits for boolean and yao sharing in the ABY framework */ @@ -51,7 +51,7 @@ class ArithmeticCircuit: public Circuit { template uint32_t PutINGate(T val, e_role role){ uint32_t gateid = PutINGate(role); if (role == m_eMyRole) { - GATE* gate = m_pGates + gateid; + GATE* gate = &(m_vGates[gateid]); gate->gs.ishare.inval = (UGATE_T*) calloc(ceil_divide(1 * m_nShareBitLen, sizeof(UGATE_T) * 8), sizeof(UGATE_T)); *gate->gs.ishare.inval = (UGATE_T) val; @@ -65,7 +65,7 @@ class ArithmeticCircuit: public Circuit { template uint32_t PutSIMDINGate(uint32_t nvals, T val, e_role role) { uint32_t gateid = PutSIMDINGate(nvals, role); if (role == m_eMyRole) { - GATE* gate = m_pGates + gateid; + GATE* gate = &(m_vGates[gateid]); gate->gs.ishare.inval = (UGATE_T*) calloc(ceil_divide(nvals * m_nShareBitLen, GATE_T_BITS), sizeof(UGATE_T)); *gate->gs.ishare.inval = (UGATE_T) val; @@ -80,7 +80,7 @@ class ArithmeticCircuit: public Circuit { template uint32_t PutSharedINGate(T val) { uint32_t gateid = PutSharedINGate(); - GATE* gate = m_pGates + gateid; + GATE* gate = &(m_vGates[gateid]); gate->gs.val = (UGATE_T*) calloc(ceil_divide(1 * m_nShareBitLen, GATE_T_BITS), sizeof(UGATE_T)); *gate->gs.val = (UGATE_T) val; @@ -92,7 +92,7 @@ class ArithmeticCircuit: public Circuit { template uint32_t PutSharedSIMDINGate(uint32_t nvals, T val) { uint32_t gateid = PutSharedSIMDINGate(nvals); - GATE* gate = m_pGates + gateid; + GATE* gate = &(m_vGates[gateid]); gate->gs.val = (UGATE_T*) calloc(ceil_divide(nvals * m_nShareBitLen, GATE_T_BITS), sizeof(UGATE_T)); *gate->gs.val = (UGATE_T) val; @@ -221,8 +221,16 @@ class ArithmeticCircuit: public Circuit { share* PutCallbackGate(share* in, uint32_t rounds, void (*callback)(GATE*, void*), void* infos, uint32_t nvals); - share* PutTruthTableGate(share* in, uint64_t* ttable); - share* PutTruthTableMultiOutputGate(share* in, uint32_t out_bits, uint64_t* ttable); + + share* PutTruthTableGate(share*, uint64_t*) { + std::cerr << "PutTruthTableGate not implemented in ArithmeticCircuit!!" << std::endl; + return NULL; + } + + share* PutTruthTableMultiOutputGate(share*, uint32_t, uint64_t*) { + std::cerr << "PutTruthTableMultiOutputGate not implemented in ArithmeticCircuit!!" << std::endl; + return NULL; + } @@ -328,11 +336,10 @@ class ArithmeticCircuit: public Circuit { assert(bitlen <= m_nShareBitLen); share* shr = new arithshare(this); uint32_t gateid = PutSharedSIMDINGate(nvals); - uint32_t iters = sizeof(UGATE_T) / sizeof(T); - assert(iters > 0); + assert((sizeof(UGATE_T) / sizeof(T)) > 0); shr->set_wire_id(0, gateid); - GATE* gate = m_pGates + gateid; + GATE* gate = &(m_vGates[gateid]); uint32_t sharebytelen = ceil_divide(m_nShareBitLen, 8); uint32_t inbytelen = ceil_divide(bitlen, 8); gate->gs.val = (UGATE_T*) calloc(nvals, PadToMultiple(sharebytelen, sizeof(UGATE_T))); @@ -343,7 +350,7 @@ class ArithmeticCircuit: public Circuit { return shr; } - template share* InternalPutSharedINGate(uint32_t nvals, T val, uint32_t bitlen) { + template share* InternalPutSharedINGate(uint32_t nvals, T val, [[maybe_unused]] uint32_t bitlen) { share* shr = new arithshare(this); shr->set_wire_id(0, PutSharedSIMDINGate(nvals, val)); return shr; @@ -353,12 +360,11 @@ class ArithmeticCircuit: public Circuit { assert(bitlen <= m_nShareBitLen); share* shr = new arithshare(this); uint32_t gateid = PutSIMDINGate(nvals, role); - uint32_t iters = sizeof(UGATE_T) / sizeof(T); - assert(iters > 0); + assert((sizeof(UGATE_T) / sizeof(T)) > 0); shr->set_wire_id(0, gateid); if (role == m_eMyRole) { - GATE* gate = m_pGates + gateid; + GATE* gate = &(m_vGates[gateid]); uint32_t sharebytelen = ceil_divide(m_nShareBitLen, 8); uint32_t inbytelen = ceil_divide(bitlen, 8); gate->gs.ishare.inval = (UGATE_T*) calloc(nvals, PadToMultiple(sharebytelen, sizeof(UGATE_T))); @@ -372,7 +378,7 @@ class ArithmeticCircuit: public Circuit { return shr; } - template share* InternalPutINGate(uint32_t nvals, T val, uint32_t bitlen, e_role role) { + template share* InternalPutINGate(uint32_t nvals, T val, [[maybe_unused]] uint32_t bitlen, e_role role) { share* shr = new arithshare(this); shr->set_wire_id(0, PutSIMDINGate(nvals, val, role)); return shr; diff --git a/src/abycore/circuit/booleancircuits.cpp b/src/abycore/circuit/booleancircuits.cpp index 9a24ff39..9f5ab5b9 100644 --- a/src/abycore/circuit/booleancircuits.cpp +++ b/src/abycore/circuit/booleancircuits.cpp @@ -2,17 +2,17 @@ \file booleancircuits.cpp \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief A collection of boolean circuits for boolean and yao sharing in the ABY framework */ @@ -110,8 +110,8 @@ uint32_t BooleanCircuit::PutANDGate(uint32_t inleft, uint32_t inright) { std::cerr << "Context not recognized" << std::endl; } - if (m_pGates[gateid].nvals != INT_MAX) { - m_vANDs[0].numgates += m_pGates[gateid].nvals; + if (m_vGates[gateid].nvals != INT_MAX) { + m_vANDs[0].numgates += m_vGates[gateid].nvals; } else { std::cerr << "INT_MAX not allowed as nvals" << std::endl; } @@ -127,10 +127,11 @@ uint32_t BooleanCircuit::PutANDGate(uint32_t inleft, uint32_t inright) { std::vector BooleanCircuit::PutANDGate(std::vector inleft, std::vector inright) { PadWithLeadingZeros(inleft, inright); - uint32_t lim = inleft.size(); - std::vector out(lim); - for (uint32_t i = 0; i < lim; i++) + uint32_t resultbitlen = inleft.size(); + std::vector out(resultbitlen); + for (uint32_t i = 0; i < resultbitlen; i++){ out[i] = PutANDGate(inleft[i], inright[i]); + } return out; } @@ -149,15 +150,15 @@ uint32_t BooleanCircuit::PutVectorANDGate(uint32_t choiceinput, uint32_t vectori uint32_t gateid = m_cCircuit->PutNonLinearVectorGate(G_NON_LIN_VEC, choiceinput, vectorinput, m_nRoundsAND); UpdateInteractiveQueue(gateid); - //std::cout << "Putting a vector and gate between a gate with " << m_pGates[choiceinput].nvals << " and " << - // m_pGates[vectorinput].nvals << ", res gate has nvals = " << m_pGates[gateid].nvals << std::endl; + //std::cout << "Putting a vector and gate between a gate with " << m_vGates[choiceinput].nvals << " and " << + // m_vGates[vectorinput].nvals << ", res gate has nvals = " << m_vGates[gateid].nvals << std::endl; - if (m_pGates[gateid].nvals != INT_MAX) { + if (m_vGates[gateid].nvals != INT_MAX) { //Update vector AND sizes //find location of vector AND bitlength - //int pos = FindBitLenPositionInVec(m_pGates[gateid].nvals, m_vANDs, m_nNumANDSizes); - int pos = FindBitLenPositionInVec(m_pGates[gateid].gs.avs.bitlen, m_vANDs, m_nNumANDSizes); + //int pos = FindBitLenPositionInVec(m_vGates[gateid].nvals, m_vANDs, m_nNumANDSizes); + int pos = FindBitLenPositionInVec(m_vGates[gateid].gs.avs.bitlen, m_vANDs, m_nNumANDSizes); if (pos == -1) { //Create new entry for the bit-length m_nNumANDSizes++; @@ -165,12 +166,12 @@ uint32_t BooleanCircuit::PutVectorANDGate(uint32_t choiceinput, uint32_t vectori memcpy(temp, m_vANDs, (m_nNumANDSizes - 1) * sizeof(non_lin_vec_ctx)); free(m_vANDs); m_vANDs = temp; - //m_vANDs[m_nNumANDSizes - 1].bitlen = m_pGates[gateid].nvals; - m_vANDs[m_nNumANDSizes - 1].bitlen = m_pGates[gateid].gs.avs.bitlen; - m_vANDs[m_nNumANDSizes - 1].numgates = m_pGates[choiceinput].nvals; //1 + //m_vANDs[m_nNumANDSizes - 1].bitlen = m_vGates[gateid].nvals; + m_vANDs[m_nNumANDSizes - 1].bitlen = m_vGates[gateid].gs.avs.bitlen; + m_vANDs[m_nNumANDSizes - 1].numgates = m_vGates[choiceinput].nvals; //1 } else { //increase number of vector ANDs for this bitlength by one - m_vANDs[pos].numgates+=m_pGates[choiceinput].nvals; + m_vANDs[pos].numgates+=m_vGates[choiceinput].nvals; } } return gateid; @@ -184,17 +185,18 @@ uint32_t BooleanCircuit::PutXORGate(uint32_t inleft, uint32_t inright) { //std::cout << "inleft = " << inleft << ", inright = " << inright << std::endl; uint32_t gateid = m_cCircuit->PutPrimitiveGate(G_LIN, inleft, inright, m_nRoundsXOR); UpdateLocalQueue(gateid); - m_nNumXORVals += m_pGates[gateid].nvals; + m_nNumXORVals += m_vGates[gateid].nvals; m_nNumXORGates += 1; return gateid; } std::vector BooleanCircuit::PutXORGate(std::vector inleft, std::vector inright) { PadWithLeadingZeros(inleft, inright); - uint32_t lim = inleft.size(); - std::vector out(lim); - for (uint32_t i = 0; i < lim; i++) + uint32_t resultbitlen = inleft.size(); + std::vector out(resultbitlen); + for (uint32_t i = 0; i < resultbitlen; i++){ out[i] = PutXORGate(inleft[i], inright[i]); + } return out; } @@ -204,17 +206,17 @@ uint32_t BooleanCircuit::PutINGate(e_role src) { switch (src) { case SERVER: m_vInputGates[0].push_back(gateid); - m_vInputBits[0] += m_pGates[gateid].nvals; + m_vInputBits[0] += m_vGates[gateid].nvals; break; case CLIENT: m_vInputGates[1].push_back(gateid); - m_vInputBits[1] += m_pGates[gateid].nvals; + m_vInputBits[1] += m_vGates[gateid].nvals; break; case ALL: m_vInputGates[0].push_back(gateid); m_vInputGates[1].push_back(gateid); - m_vInputBits[0] += m_pGates[gateid].nvals; - m_vInputBits[1] += m_pGates[gateid].nvals; + m_vInputBits[0] += m_vGates[gateid].nvals; + m_vInputBits[1] += m_vGates[gateid].nvals; break; default: std::cerr << "Role not recognized" << std::endl; @@ -230,17 +232,17 @@ uint32_t BooleanCircuit::PutSIMDINGate(uint32_t ninvals, e_role src) { switch (src) { case SERVER: m_vInputGates[0].push_back(gateid); - m_vInputBits[0] += m_pGates[gateid].nvals; + m_vInputBits[0] += m_vGates[gateid].nvals; break; case CLIENT: m_vInputGates[1].push_back(gateid); - m_vInputBits[1] += m_pGates[gateid].nvals; + m_vInputBits[1] += m_vGates[gateid].nvals; break; case ALL: m_vInputGates[0].push_back(gateid); m_vInputGates[1].push_back(gateid); - m_vInputBits[0] += m_pGates[gateid].nvals; - m_vInputBits[1] += m_pGates[gateid].nvals; + m_vInputBits[0] += m_vGates[gateid].nvals; + m_vInputBits[1] += m_vGates[gateid].nvals; break; default: std::cerr << "Role not recognized" << std::endl; @@ -285,7 +287,7 @@ uint32_t BooleanCircuit::PutINGate(uint64_t val, e_role role) { uint32_t gateid = PutINGate(role); if (role == m_eMyRole) { //assign value - GATE* gate = m_pGates + gateid; + GATE* gate = &(m_vGates[gateid]); gate->gs.ishare.inval = (UGATE_T*) calloc(ceil_divide(1 * m_nShareBitLen, sizeof(UGATE_T) * 8), sizeof(UGATE_T)); memcpy(gate->gs.ishare.inval, &val, ceil_divide(1 * m_nShareBitLen, 8)); @@ -299,7 +301,7 @@ uint32_t BooleanCircuit::PutINGate(uint64_t val, e_role role) { uint32_t BooleanCircuit::PutSharedINGate(uint64_t val) { uint32_t gateid = PutSharedINGate(); //assign value - GATE* gate = m_pGates + gateid; + GATE* gate = &(m_vGates[gateid]); gate->gs.val = (UGATE_T*) calloc(ceil_divide(1 * m_nShareBitLen, sizeof(UGATE_T) * 8), sizeof(UGATE_T)); memcpy(gate->gs.val, &val, ceil_divide(1 * m_nShareBitLen, 8)); @@ -312,7 +314,7 @@ uint32_t BooleanCircuit::PutSIMDINGate(uint32_t nvals, uint64_t val, e_role role uint32_t gateid = PutSIMDINGate(nvals, role); if (role == m_eMyRole) { //assign value - GATE* gate = m_pGates + gateid; + GATE* gate = &(m_vGates[gateid]); gate->gs.ishare.inval = (UGATE_T*) calloc(ceil_divide(nvals * m_nShareBitLen, sizeof(UGATE_T) * 8), sizeof(UGATE_T)); memcpy(gate->gs.ishare.inval, &val, ceil_divide(nvals * m_nShareBitLen, 8)); @@ -327,7 +329,7 @@ uint32_t BooleanCircuit::PutSharedSIMDINGate(uint32_t nvals, uint64_t val) { uint32_t gateid = PutSharedSIMDINGate(nvals); //assign value - GATE* gate = m_pGates + gateid; + GATE* gate = &(m_vGates[gateid]); gate->gs.val = (UGATE_T*) calloc(ceil_divide(nvals * m_nShareBitLen, sizeof(UGATE_T) * 8), sizeof(UGATE_T)); memcpy(gate->gs.val, &val, ceil_divide(nvals * m_nShareBitLen, 8)); @@ -339,7 +341,7 @@ uint32_t BooleanCircuit::PutSharedSIMDINGate(uint32_t nvals, uint64_t val) { uint32_t BooleanCircuit::PutYaoSharedSIMDINGate(uint32_t nvals, yao_fields keys) { uint32_t gateid = PutSharedSIMDINGate(nvals); //assign value - GATE* gate = m_pGates + gateid; + GATE* gate = &(m_vGates[gateid]); //TODO: fixed to 128-bit security atm. CHANGE uint8_t keybytelen = ceil_divide(128, 8); if(m_eMyRole == SERVER) { @@ -374,17 +376,17 @@ uint32_t BooleanCircuit::PutOUTGate(uint32_t parentid, e_role dst) { switch (dst) { case SERVER: m_vOutputGates[0].push_back(gateid); - m_vOutputBits[0] += m_pGates[gateid].nvals; + m_vOutputBits[0] += m_vGates[gateid].nvals; break; case CLIENT: m_vOutputGates[1].push_back(gateid); - m_vOutputBits[1] += m_pGates[gateid].nvals; + m_vOutputBits[1] += m_vGates[gateid].nvals; break; case ALL: m_vOutputGates[0].push_back(gateid); m_vOutputGates[1].push_back(gateid); - m_vOutputBits[0] += m_pGates[gateid].nvals; - m_vOutputBits[1] += m_pGates[gateid].nvals; + m_vOutputBits[0] += m_vGates[gateid].nvals; + m_vOutputBits[1] += m_vGates[gateid].nvals; break; default: std::cerr << "Role not recognized" << std::endl; @@ -407,17 +409,17 @@ std::vector BooleanCircuit::PutOUTGate(std::vector parentids switch (dst) { case SERVER: m_vOutputGates[0].push_back(gateid[i]); - m_vOutputBits[0] += m_pGates[gateid[i]].nvals; + m_vOutputBits[0] += m_vGates[gateid[i]].nvals; break; case CLIENT: m_vOutputGates[1].push_back(gateid[i]); - m_vOutputBits[1] += m_pGates[gateid[i]].nvals; + m_vOutputBits[1] += m_vGates[gateid[i]].nvals; break; case ALL: m_vOutputGates[0].push_back(gateid[i]); m_vOutputGates[1].push_back(gateid[i]); - m_vOutputBits[0] += m_pGates[gateid[i]].nvals; - m_vOutputBits[1] += m_pGates[gateid[i]].nvals; + m_vOutputBits[0] += m_vGates[gateid[i]].nvals; + m_vOutputBits[1] += m_vGates[gateid[i]].nvals; break; default: std::cerr << "Role not recognized" << std::endl; @@ -442,58 +444,39 @@ share* BooleanCircuit::PutSharedOUTGate(share* parent) { } share* BooleanCircuit::PutCONSGate(UGATE_T val, uint32_t bitlen) { - share* shr = new boolshare(bitlen, this); - for (uint32_t i = 0; i < bitlen; i++) { - if ((val >> i) & 0x01) { - shr->set_wire_id(i, PutConstantGate(1, 1)); - } else { - shr->set_wire_id(i, PutConstantGate(0, 1)); - } - } - return shr; + return PutSIMDCONSGate(1, val, bitlen); } share* BooleanCircuit::PutCONSGate(uint8_t* val, uint32_t bitlen) { - share* shr = new boolshare(bitlen, this); - for (uint32_t i = 0; i < bitlen; i++) { - shr->set_wire_id(i, PutConstantGate(val[i] & 0x01, 1)); - } - return shr; + return PutSIMDCONSGate(1, val, bitlen); } share* BooleanCircuit::PutCONSGate(uint32_t* val, uint32_t bitlen) { - share* shr = new boolshare(bitlen, this); - for (uint32_t i = 0; i < bitlen; i++) { - shr->set_wire_id(i, PutConstantGate((val[i >> 5] >> i) & 0x01, 1)); - } - return shr; + return PutSIMDCONSGate(1, val, bitlen); } share* BooleanCircuit::PutSIMDCONSGate(uint32_t nvals, UGATE_T val, uint32_t bitlen) { share* shr = new boolshare(bitlen, this); - for (uint32_t i = 0; i < bitlen; i++) { - if ((val >> i) & 0x01) { - shr->set_wire_id(i, PutConstantGate(~0L, nvals)); - } - else { - shr->set_wire_id(i, PutConstantGate(0L, nvals)); - } + for(uint32_t i = 0; i < bitlen; ++i) { + shr->set_wire_id(i, PutConstantGate((val >> i) & 1, nvals)); } return shr; } share* BooleanCircuit::PutSIMDCONSGate(uint32_t nvals, uint8_t* val, uint32_t bitlen) { share* shr = new boolshare(bitlen, this); - for (uint32_t i = 0; i < bitlen; i++) { - shr->set_wire_id(i, PutConstantGate(val[i] & 0x01, nvals)); + for(uint32_t i = 0; i < bitlen; ++i) { + uint32_t shift = i % 8; + shr->set_wire_id(i, PutConstantGate((val[(i / 8)] & (1 << shift)) >> shift, nvals)); } return shr; } share* BooleanCircuit::PutSIMDCONSGate(uint32_t nvals, uint32_t* val, uint32_t bitlen) { share* shr = new boolshare(bitlen, this); - for (uint32_t i = 0; i < bitlen; i++) { - shr->set_wire_id(i, PutConstantGate((val[i >> 5] >> i) & 0x01, nvals)); + for(uint32_t i = 0; i < bitlen; ++i) { + uint32_t shift = i % 32; + shr->set_wire_id(i, PutConstantGate((val[(i / 32)] & (1 << shift)) >> shift, nvals)); } return shr; } @@ -525,10 +508,10 @@ share* BooleanCircuit::PutINVGate(share* parent) { uint32_t BooleanCircuit::PutY2BCONVGate(uint32_t parentid) { std::vector in(1, parentid); uint32_t gateid = m_cCircuit->PutCONVGate(in, 1, S_BOOL, m_nShareBitLen); - m_pGates[gateid].depth++; + m_vGates[gateid].depth++; UpdateLocalQueue(gateid); //a Y input gate cannot be parent to a Y2B gate. Alternatively, put a Boolean input gate - assert(m_pGates[parentid].type != G_IN); + assert(m_vGates[parentid].type != G_IN); return gateid; } @@ -539,7 +522,7 @@ uint32_t BooleanCircuit::PutB2YCONVGate(uint32_t parentid) { UpdateInteractiveQueue(gateid); //treat similar to input gate of client and server - m_nB2YGates += m_pGates[gateid].nvals; + m_nB2YGates += m_vGates[gateid].nvals; return gateid; } @@ -547,12 +530,12 @@ uint32_t BooleanCircuit::PutB2YCONVGate(uint32_t parentid) { uint32_t BooleanCircuit::PutYSwitchRolesGate(uint32_t parentid) { std::vector in(1, parentid); assert(m_eContext == S_YAO || m_eContext == S_YAO_REV); - assert(m_pGates[in[0]].context != m_eContext); + assert(m_vGates[in[0]].context != m_eContext); uint32_t gateid = m_cCircuit->PutCONVGate(in, 2, m_eContext, m_nShareBitLen); UpdateInteractiveQueue(gateid); //treat similar to input gate of client and server - m_nYSwitchGates += m_pGates[gateid].nvals; + m_nYSwitchGates += m_vGates[gateid].nvals; return gateid; } @@ -597,22 +580,22 @@ share* BooleanCircuit::PutYSwitchRolesGate(share* ina) { } std::vector BooleanCircuit::PutA2YCONVGate(std::vector parentid) { - std::vector srvshares(m_pGates[parentid[0]].sharebitlen); - std::vector clishares(m_pGates[parentid[0]].sharebitlen); + std::vector srvshares(m_vGates[parentid[0]].sharebitlen); + std::vector clishares(m_vGates[parentid[0]].sharebitlen); - for (uint32_t i = 0; i < m_pGates[parentid[0]].sharebitlen; i++) { + for (uint32_t i = 0; i < m_vGates[parentid[0]].sharebitlen; i++) { srvshares[i] = m_cCircuit->PutCONVGate(parentid, 1, S_YAO, m_nShareBitLen); - m_pGates[srvshares[i]].gs.pos = 2 * i; - m_pGates[srvshares[i]].depth++; //increase depth by 1 since yao is evaluated before arith + m_vGates[srvshares[i]].gs.pos = 2 * i; + m_vGates[srvshares[i]].depth++; //increase depth by 1 since yao is evaluated before arith UpdateInteractiveQueue(srvshares[i]); clishares[i] = m_cCircuit->PutCONVGate(parentid, 2, S_YAO, m_nShareBitLen); - m_pGates[clishares[i]].gs.pos = 2 * i + 1; - m_pGates[clishares[i]].depth++; //increase depth by 1 since yao is evaluated before arith + m_vGates[clishares[i]].gs.pos = 2 * i + 1; + m_vGates[clishares[i]].depth++; //increase depth by 1 since yao is evaluated before arith UpdateInteractiveQueue(clishares[i]); } - m_nA2YGates += m_pGates[parentid[0]].nvals * m_pGates[parentid[0]].sharebitlen; + m_nA2YGates += m_vGates[parentid[0]].nvals * m_vGates[parentid[0]].sharebitlen; return PutAddGate(srvshares, clishares); @@ -643,7 +626,7 @@ uint32_t BooleanCircuit::PutUniversalGate(uint32_t a, uint32_t b, uint32_t op_id if(m_eContext == S_YAO) { //In case of Yao, put universal gate gateid = m_cCircuit->PutUniversalGate(a, b, op_id, m_nRoundsAND); UpdateLocalQueue(gateid); - m_nUNIVGates+=m_pGates[gateid].nvals; + m_nUNIVGates+=m_vGates[gateid].nvals; } else if (m_eContext == S_BOOL) { //In case of GMW, replace universal gate by sub-circuit gateid = PutUniversalGateCircuit(a, b, op_id); } else { @@ -724,7 +707,7 @@ std::vector BooleanCircuit::PutTruthTableMultiOutputGate(std::vector bitlens(out_bits, m_pGates[in[0]].nvals); + std::vector bitlens(out_bits, m_vGates[in[0]].nvals); //assert(out_bits <= 8); std::vector output = m_cCircuit->PutSplitterGate(tmpgate, bitlens); @@ -760,8 +743,8 @@ share* BooleanCircuit::PutTruthTableGate(share* in, uint64_t* ttable) { //check if the len exists, otherwise allocate new and update void BooleanCircuit::UpdateTruthTableSizes(uint32_t len, uint32_t gateid, uint32_t out_bits) { //check depth and resize if required - uint32_t depth = m_pGates[gateid].depth; - uint32_t nvals = m_pGates[gateid].nvals/out_bits; + uint32_t depth = m_vGates[gateid].depth; + uint32_t nvals = m_vGates[gateid].nvals/out_bits; if(depth >= m_vTTlens.size()) { uint32_t old_depth = m_vTTlens.size(); uint32_t nlens = m_vTTlens[0].size(); @@ -797,7 +780,7 @@ void BooleanCircuit::UpdateTruthTableSizes(uint32_t len, uint32_t gateid, uint32 //In case of OP-LUT, also save the truth table which is needed in the setup phase if(m_eContext == S_BOOL) { for(uint32_t n = 0; n < nvals; n++) { - m_vTTlens[depth][i][j].ttable_values.push_back(m_pGates[gateid].gs.tt.table); + m_vTTlens[depth][i][j].ttable_values.push_back(m_vGates[gateid].gs.tt.table); } } } @@ -819,7 +802,7 @@ void BooleanCircuit::UpdateTruthTableSizes(uint32_t len, uint32_t gateid, uint32 //In case of OP-LUT, also save the truth table which is needed in the setup phase if(m_eContext == S_BOOL) { for(uint32_t n = 0; n < nvals; n++) { - m_vTTlens[depth][old_in_lens][0].ttable_values.push_back(m_pGates[gateid].gs.tt.table); + m_vTTlens[depth][old_in_lens][0].ttable_values.push_back(m_vGates[gateid].gs.tt.table); } } outs_exist = true; @@ -839,7 +822,7 @@ void BooleanCircuit::UpdateTruthTableSizes(uint32_t len, uint32_t gateid, uint32 //In case of OP-LUT, also save the truth table which is needed in the setup phase if(m_eContext == S_BOOL) { for(uint32_t n = 0; n < nvals; n++) { - m_vTTlens[depth][id][old_out_lens].ttable_values.push_back(m_pGates[gateid].gs.tt.table); + m_vTTlens[depth][id][old_out_lens].ttable_values.push_back(m_vGates[gateid].gs.tt.table); } } outs_exist = true; @@ -849,26 +832,26 @@ void BooleanCircuit::UpdateTruthTableSizes(uint32_t len, uint32_t gateid, uint32 //enqueue interactive gate queue void BooleanCircuit::UpdateInteractiveQueue(uint32_t gateid) { - if (m_pGates[gateid].depth + 1 > m_vInteractiveQueueOnLvl.size()) { - m_vInteractiveQueueOnLvl.resize(m_pGates[gateid].depth + 1); - if (m_pGates[gateid].depth + 1 > m_nMaxDepth) { - m_nMaxDepth = m_pGates[gateid].depth + 1; + if (m_vGates[gateid].depth + 1 > m_vInteractiveQueueOnLvl.size()) { + m_vInteractiveQueueOnLvl.resize(m_vGates[gateid].depth + 1); + if (m_vGates[gateid].depth + 1 > m_nMaxDepth) { + m_nMaxDepth = m_vGates[gateid].depth + 1; } } - m_vInteractiveQueueOnLvl[m_pGates[gateid].depth].push_back(gateid); + m_vInteractiveQueueOnLvl[m_vGates[gateid].depth].push_back(gateid); m_nGates++; } //enqueue locally evaluated gate queue void BooleanCircuit::UpdateLocalQueue(uint32_t gateid) { - if (m_pGates[gateid].depth + 1 > m_vLocalQueueOnLvl.size()) { + if (m_vGates[gateid].depth + 1 > m_vLocalQueueOnLvl.size()) { //std::cout << "increasing size of local queue" << std::endl; - m_vLocalQueueOnLvl.resize(m_pGates[gateid].depth + 1); - if (m_pGates[gateid].depth + 1 > m_nMaxDepth) { - m_nMaxDepth = m_pGates[gateid].depth + 1; + m_vLocalQueueOnLvl.resize(m_vGates[gateid].depth + 1); + if (m_vGates[gateid].depth + 1 > m_nMaxDepth) { + m_nMaxDepth = m_vGates[gateid].depth + 1; } } - m_vLocalQueueOnLvl[m_pGates[gateid].depth].push_back(gateid); + m_vLocalQueueOnLvl[m_vGates[gateid].depth].push_back(gateid); m_nGates++; } @@ -890,17 +873,13 @@ std::vector BooleanCircuit::PutLeftShifterGate(std::vector v } // Builds a universal gate that output op_id depending on the circuit -// Only works for nvals <= 32 due to the constant gate implementation in Bool -// sharing. uint32_t BooleanCircuit::PutUniversalGateCircuit(uint32_t a, uint32_t b, uint32_t op_id) { - uint32_t nvals = std::max(m_pGates[a].nvals, m_pGates[b].nvals); - assert(nvals <= 32); + uint32_t nvals = std::max(m_vGates[a].nvals, m_vGates[b].nvals); - uint32_t mask = 0xFFFFFFFF; - uint32_t c0 = PutConstantGate((op_id & 0x01) * mask, nvals); - uint32_t c1 = PutConstantGate(((op_id>>1) & 0x01) * mask, nvals); - uint32_t c2 = PutConstantGate(((op_id>>2) & 0x01) * mask, nvals); - uint32_t c3 = PutConstantGate(((op_id>>3) & 0x01) * mask, nvals); + uint32_t c0 = PutConstantGate(op_id & 0x01, nvals); + uint32_t c1 = PutConstantGate((op_id>>1) & 0x01, nvals); + uint32_t c2 = PutConstantGate((op_id>>2) & 0x01, nvals); + uint32_t c3 = PutConstantGate((op_id>>3) & 0x01, nvals); uint32_t c0c1 = PutXORGate(c0, c1); uint32_t c2c3 = PutXORGate(c2, c3); @@ -942,14 +921,14 @@ std::vector BooleanCircuit::PutSizeOptimizedAddGate(std::vector C(rep); + uint32_t inputbitlen = a.size();// + (!!bCarry); + std::vector C(inputbitlen); uint32_t axc, bxc, acNbc; - C[0] = PutXORGate(a[0], a[0]);//PutConstantGate(0, m_pGates[a[0]].nvals); //the second parameter stands for the number of vals + C[0] = PutXORGate(a[0], a[0]);//PutConstantGate(0, m_vGates[a[0]].nvals); //the second parameter stands for the number of vals uint32_t i = 0; - for (; i < rep - 1; i++) { + for (; i < inputbitlen - 1; i++) { //=================== // New Gates // a[i] xor c[i] @@ -984,8 +963,8 @@ std::vector BooleanCircuit::PutSizeOptimizedAddGate(std::vector AxB(rep); - for (uint32_t i = 0; i < rep; i++) { + std::vector AxB(inputbitlen); + for (uint32_t i = 0; i < inputbitlen; i++) { // a[i] xor b[i] AxB[i] = PutXORGate(a[i], b[i]); } @@ -995,8 +974,8 @@ std::vector BooleanCircuit::PutSizeOptimizedAddGate(std::vector out(rep + (!!bCarry)); - for (uint32_t i = 0; i < rep; i++) { + std::vector out(inputbitlen + (!!bCarry)); + for (uint32_t i = 0; i < inputbitlen; i++) { out[i] = PutXORGate(C[i], AxB[i]); } @@ -1005,7 +984,7 @@ std::vector BooleanCircuit::PutSizeOptimizedAddGate(std::vector BooleanCircuit::PutSizeOptimizedAddGate(std::vector BooleanCircuit::PutDepthOptimizedAddGate(std::vector a, std::vector b, BOOL bCARRY, bool vector_and) { PadWithLeadingZeros(a, b); - uint32_t id, rep = std::min(a.size(), b.size()); + uint32_t id, inputbitlen = std::min(a.size(), b.size()); std::vector out(a.size() + bCARRY); - std::vector parity(a.size()), carry(rep), parity_zero(rep); - uint32_t zerogate = PutConstantGate(0, m_pGates[a[0]].nvals); - uint32_t startid = zerogate; + std::vector parity(a.size()), carry(inputbitlen), parity_zero(inputbitlen); + uint32_t zerogate = PutConstantGate(0, m_vGates[a[0]].nvals); share* zero_share = new boolshare(2, this); share* ina = new boolshare(2, this); share* sel = new boolshare(1, this); @@ -1031,14 +1009,14 @@ std::vector BooleanCircuit::PutDepthOptimizedAddGate(std::vectorset_wire_id(0, zerogate); zero_share->set_wire_id(1, zerogate); - for (uint32_t i = 0; i < rep; i++) { //0-th layer + for (uint32_t i = 0; i < inputbitlen; i++) { //0-th layer parity[i] = PutXORGate(a[i], b[i]); parity_zero[i] = parity[i]; carry[i] = PutANDGate(a[i], b[i]); } - for (uint32_t i = 1; i <= (uint32_t) ceil(log(rep) / log(2)); i++) { - for (uint32_t j = 0; j < rep; j++) { + for (uint32_t i = 1; i <= (uint32_t) ceil(log(inputbitlen) / log(2)); i++) { + for (uint32_t j = 0; j < inputbitlen; j++) { if (j % (uint32_t) pow(2, i) >= pow(2, (i - 1))) { id = pow(2, (i - 1)) + pow(2, i) * ((uint32_t) floor(j / (pow(2, i)))) - 1; if(m_eContext == S_BOOL && vector_and) { @@ -1058,11 +1036,11 @@ std::vector BooleanCircuit::PutDepthOptimizedAddGate(std::vector > BooleanCircuit::PutCarrySaveGate(std::vector * 1) for the inputs, 2) for intermediate carry-forwarding, 3) for critical path on inputs, 4) for the critical path, 5) for the inverse carry tree. */ std::vector BooleanCircuit::PutLUTAddGate(std::vector a, std::vector b, BOOL bCARRY) { - uint32_t id, rep = std::max(a.size(), b.size()); + uint32_t inputbitlen = std::max(a.size(), b.size()); PadWithLeadingZeros(a, b); std::vector out(a.size() + bCARRY); - std::vector parity(rep), carry(rep), parity_zero(rep), tmp; - std::vector lut_in(2*rep); + std::vector parity(inputbitlen), carry(inputbitlen), parity_zero(inputbitlen), tmp; + std::vector lut_in(2*inputbitlen); uint32_t max_ins = 4, processed_ins; - uint32_t max_invs = 7; - uint32_t n_crit_ins = std::min(rep, (uint32_t) max_ins); + uint32_t n_crit_ins = std::min(inputbitlen, (uint32_t) max_ins); std::vector tmpout; - //std::cout << "Building a LUT add gate for " << rep << " input bits" << std::endl; + //std::cout << "Building a LUT add gate for " << inputbitlen << " input bits" << std::endl; //step 1: process the input values and generate carry / parity signals //compute the parity bits for the zero-th layer. Are needed for the result - for (uint32_t i = 0; i < rep; i++) { //0-th layer + for (uint32_t i = 0; i < inputbitlen; i++) { //0-th layer parity_zero[i] = PutXORGate(a[i], b[i]); parity[i] = parity_zero[i]; } @@ -1153,8 +1130,8 @@ std::vector BooleanCircuit::PutLUTAddGate(std::vector a, std } //process the remaining input bits to have all carry / parity signals - for(uint32_t i = n_crit_ins; i < rep; ) { - processed_ins = std::min(rep - i, max_ins); + for(uint32_t i = n_crit_ins; i < inputbitlen; ) { + processed_ins = std::min(inputbitlen - i, max_ins); //assign values to the LUT lut_in.clear(); lut_in.resize(2*processed_ins); @@ -1190,12 +1167,12 @@ std::vector BooleanCircuit::PutLUTAddGate(std::vector a, std } //step 2: process the carry / parity signals and forward them in the tree - for(uint32_t d = 1; d < ceil_log2(rep+1)/2; d++) { + for(uint32_t d = 1; d < ceil_log2(inputbitlen+1)/2; d++) { //step 2.1: process the carry signals on the critical path uint32_t base = 8 * (1<<(2*(d-1))); uint32_t dist = base/2; - processed_ins = 1+ std::min((rep - base)/dist, max_ins-2); + processed_ins = 1+ std::min((inputbitlen - base)/dist, max_ins-2); //std::cout << "critical intermediate base = " << base << ", dist = " << dist << ", processed_ins = " << processed_ins << std::endl; lut_in.clear(); @@ -1216,8 +1193,8 @@ std::vector BooleanCircuit::PutLUTAddGate(std::vector a, std } //step 2.2: forward carry and parity signals down the tree - for(uint32_t i = (base+3*dist)-1; i+dist < rep; i+=(4*dist)) { - processed_ins = std::min(ceil_divide((rep - (i+dist)),2*dist), max_ins-2); + for(uint32_t i = (base+3*dist)-1; i+dist < inputbitlen; i+=(4*dist)) { + processed_ins = std::min(ceil_divide((inputbitlen - (i+dist)),2*dist), max_ins-2); //std::cout << "intermediate base = " << i << ", dist = " << dist << ", processed_ins = " << processed_ins << std::endl; lut_in.clear(); @@ -1241,19 +1218,19 @@ std::vector BooleanCircuit::PutLUTAddGate(std::vector a, std } - //std::cout << "Doing " << (floor_log2(rep/5)/2)+1 << " iterations on the inverse carry tree, " << floor_log2(rep/5) << ", " << rep/5 << std::endl; + //std::cout << "Doing " << (floor_log2(inputbitlen/5)/2)+1 << " iterations on the inverse carry tree, " << floor_log2(inputbitlen/5) << ", " << inputbitlen/5 << std::endl; //step 3: build the inverse carry tree //d increases with d = 0: 5, d = 1: 20, d = 2: 80; d = 3: 320, ... - for(int32_t d = (floor_log2(rep/5)/2); d >= 0; d--) { + for(int32_t d = (floor_log2(inputbitlen/5)/2); d >= 0; d--) { //for d = 0: 4, for d = 1: 16, for d = 2: 64 uint32_t start = 4 * (1<<(2*d)); //for start = 4: 1, start = 16: 4, start = 64: 16 uint32_t dist = start/4; //std::cout << "d = " << d << ", start = " << start << ", dist = " << dist << std::endl; - for(uint32_t i = start; i < rep; i+=start) { + for(uint32_t i = start; i < inputbitlen; i+=start) { //processed_ins here needs to be between 1 and 3 - //processed_ins = std::min(rep - i, max_ins-1); - processed_ins = std::min((rep - i)/dist, max_ins-1); + //processed_ins = std::min(inputbitlen - i, max_ins-1); + processed_ins = std::min((inputbitlen - i)/dist, max_ins-1); if(processed_ins > 0) { //assign values to the LUT lut_in.clear(); @@ -1286,58 +1263,57 @@ std::vector BooleanCircuit::PutLUTAddGate(std::vector a, std //step 4: compute the outputs from the carry signals and the parity bits at the zero-th level out[0] = parity_zero[0]; - for (uint32_t i = 1; i < rep; i++) { + for (uint32_t i = 1; i < inputbitlen; i++) { out[i] = PutXORGate(parity_zero[i], carry[i - 1]); } if (bCARRY) //Do I expect a carry in the most significant bit position? - out[rep] = carry[rep - 1]; + out[inputbitlen] = carry[inputbitlen - 1]; return out; } -std::vector BooleanCircuit::PutMulGate(std::vector a, std::vector b, uint32_t resbitlen, bool depth_optimized, bool vector_ands) { +std::vector BooleanCircuit::PutMulGate(std::vector a, std::vector b, uint32_t resultbitlen, bool depth_optimized, bool vector_ands) { PadWithLeadingZeros(a, b); - //std::cout << "a.size() = " << a.size() << ", b.size() = " << b.size() << std::endl; - uint32_t rep = a.size(); + // std::cout << "a.size() = " << a.size() << ", b.size() = " << b.size() << std::endl; + uint32_t inputbitlen = a.size(); - if(rep == 1) { + if(inputbitlen == 1) { return PutANDGate(a, b); } - std::vector > vAdds(rep); - uint32_t zerogate = PutConstantGate(0, m_pGates[a[0]].nvals); - - uint32_t lim = std::min(resbitlen, 2 * rep); + std::vector > vAdds(inputbitlen); + uint32_t zerogate = PutConstantGate(0, m_vGates[a[0]].nvals); + resultbitlen = std::min(resultbitlen, 2 * inputbitlen); - if(m_eContext== S_BOOL && vector_ands) { + if(m_eContext == S_BOOL && vector_ands) { share *ina, *inb, **mulout, *zero_share; - ina = new boolshare(a, this); //ina = (share**) malloc(sizeof(share*) * 1); - inb = new boolshare(b, this);//inb = (share**) malloc(sizeof(share*) * 1); - zero_share = new boolshare(rep, this); + ina = new boolshare(a, this); + inb = new boolshare(b, this); + zero_share = new boolshare(inputbitlen, this); - mulout = (share**) malloc(sizeof(share*) * rep); + mulout = (share**) malloc(sizeof(share*) * inputbitlen); - for(uint32_t i = 0; i < rep; i++) { - mulout[i] = new boolshare(rep, this); + for(uint32_t i = 0; i < inputbitlen; i++) { + mulout[i] = new boolshare(inputbitlen, this); zero_share->set_wire_id(i, zerogate); } - for(uint32_t i = 0; i < rep; i++) { + for(uint32_t i = 0; i < inputbitlen; i++) { PutMultiMUXGate(&ina, &zero_share, inb->get_wire_ids_as_share(i), 1, &(mulout[i])); } - for (uint32_t i = 0, ctr; i < rep; i++) { + for (uint32_t i = 0, ctr; i < inputbitlen; i++) { ctr = 0; - vAdds[i].resize(lim); + vAdds[i].resize(resultbitlen); - for (uint32_t j = 0; j < i && ctr < lim; j++, ctr++) { + for (uint32_t j = 0; j < i && ctr < resultbitlen; j++, ctr++) { vAdds[i][ctr] = zerogate; } - for (uint32_t j = 0; j < rep && ctr < lim; j++, ctr++) { + for (uint32_t j = 0; j < inputbitlen && ctr < resultbitlen; j++, ctr++) { vAdds[i][ctr] = mulout[j]->get_wire_id(i);//(a[j], b[i]); } - for (uint32_t j = i; j < rep && ctr < lim; j++, ctr++) { + for (uint32_t j = i; j < inputbitlen && ctr < resultbitlen; j++, ctr++) { vAdds[i][ctr] = zerogate; } } @@ -1346,22 +1322,22 @@ std::vector BooleanCircuit::PutMulGate(std::vector a, std::v } else { // Compute AND between all bits #ifdef ZDEBUG - std::cout << "Starting to construct multiplication gate for " << rep << " bits" << std::endl; + std::cout << "Starting to construct multiplication gate for " << inputbitlen << " bits" << std::endl; #endif - for (uint32_t i = 0, ctr; i < rep; i++) { + for (uint32_t i = 0, ctr; i < inputbitlen; i++) { ctr = 0; - vAdds[i].resize(lim); + vAdds[i].resize(resultbitlen); #ifdef ZDEBUG - std::cout << "New Iteration with ctr = " << ctr << ", and lim = " << lim << std::endl; + std::cout << "New Iteration with ctr = " << ctr << ", and resultbitlen = " << resultbitlen << std::endl; #endif - for (uint32_t j = 0; j < i && ctr < lim; j++, ctr++) { + for (uint32_t j = 0; j < i && ctr < resultbitlen; j++, ctr++) { vAdds[i][ctr] = zerogate; } - for (uint32_t j = 0; j < rep && ctr < lim; j++, ctr++) { + for (uint32_t j = 0; j < inputbitlen && ctr < resultbitlen; j++, ctr++) { vAdds[i][ctr] = PutANDGate(a[j], b[i]); } - for (uint32_t j = i; j < rep && ctr < lim; j++, ctr++) { + for (uint32_t j = i; j < inputbitlen && ctr < resultbitlen; j++, ctr++) { vAdds[i][ctr] = zerogate; } } @@ -1373,17 +1349,15 @@ std::vector BooleanCircuit::PutMulGate(std::vector a, std::v return PutDepthOptimizedAddGate(out[0], out[1]); } else { return PutWideAddGate(vAdds); - } - } share* BooleanCircuit::PutMULGate(share* ina, share* inb) { //set the resulting bit length to be the smallest of: 1) bit length of the products or 2) the highest maximum bit length between ina and inb - uint32_t resbitlen = std::min(ina->get_bitlength() + inb->get_bitlength(), std::max(ina->get_max_bitlength(), inb->get_max_bitlength())); - return new boolshare(PutMulGate(ina->get_wires(), inb->get_wires(), resbitlen), this); + uint32_t resultbitlen = std::min(ina->get_bitlength() + inb->get_bitlength(), std::max(ina->get_max_bitlength(), inb->get_max_bitlength())); + return new boolshare(PutMulGate(ina->get_wires(), inb->get_wires(), resultbitlen), this); } share* BooleanCircuit::PutGTGate(share* ina, share* inb) { @@ -1422,14 +1396,14 @@ std::vector BooleanCircuit::PutWideAddGate(std::vector > BooleanCircuit::PutCSNNetwork(std::vector > ins) { // build a balanced carry-save network - uint32_t rep = ins[0].size(); + uint32_t inputbitlen = ins[0].size(); uint32_t wires = ins.size(); std::vector > survivors(wires * 2);// = ins; std::vector > carry_lines(wires-2); std::vector > rem(8); std::vector > out(2); - int p_head=wires, p_tail = 0, c_head = 0, c_tail = 0, temp_gates; - std::vector dummy(rep); + int p_head=wires, p_tail = 0, c_head = 0, c_tail = 0;//, temp_gates; + std::vector dummy(inputbitlen); for(uint32_t i = 0; i < ins.size(); i++) { survivors[i] = ins[i]; @@ -1444,9 +1418,9 @@ std::vector > BooleanCircuit::PutCSNNetwork(std::vector > BooleanCircuit::PutCSNNetwork(std::vector > BooleanCircuit::PutCSNNetwork(std::vector > BooleanCircuit::PutCSNNetwork(std::vector BooleanCircuit::PutSUBGate(std::vector a, std::vector b, uint32_t max_bitlength) { //pad with leading zeros if(a.size() < max_bitlength) { - uint32_t zerogate = PutConstantGate(0, m_pGates[a[0]].nvals); + uint32_t zerogate = PutConstantGate(0, m_vGates[a[0]].nvals); a.resize(max_bitlength, zerogate); } if(b.size() < max_bitlength) { - uint32_t zerogate = PutConstantGate(0, m_pGates[a[0]].nvals); + uint32_t zerogate = PutConstantGate(0, m_vGates[a[0]].nvals); b.resize(max_bitlength, zerogate); } @@ -1520,7 +1494,7 @@ std::vector BooleanCircuit::PutSUBGate(std::vector a, std::v ainv[i] = PutINVGate(a[i]); } - C[0] = PutConstantGate(0, m_pGates[a[0]].nvals); + C[0] = PutConstantGate(0, m_vGates[a[0]].nvals); for (i = 0; i < bitlen - 1; i++) { //=================== @@ -1571,7 +1545,7 @@ uint32_t BooleanCircuit::PutGTGate(std::vector a, std::vector a, std::vector b) { PadWithLeadingZeros(a, b); uint32_t ci = 0, ci1, ac, bc, acNbc; - ci = PutConstantGate((UGATE_T) 0, m_pGates[a[0]].nvals); + ci = PutConstantGate((UGATE_T) 0, m_vGates[a[0]].nvals); for (uint32_t i = 0; i < a.size(); i++, ci = ci1) { ac = PutXORGate(a[i], ci); bc = PutXORGate(b[i], ci); @@ -1586,21 +1560,21 @@ uint32_t BooleanCircuit::PutSizeOptimizedGTGate(std::vector a, std::ve uint32_t BooleanCircuit::PutDepthOptimizedGTGate(std::vector a, std::vector b) { PadWithLeadingZeros(a, b); uint32_t i, rem; - uint32_t rep = std::min(a.size(), b.size()); - std::vector agtb(rep); - std::vector eq(rep); + uint32_t inputbitlen = std::min(a.size(), b.size()); + std::vector agtb(inputbitlen); + std::vector eq(inputbitlen); //Put the leaf comparison nodes from which the tree is built - for (i = 0; i < rep; i++) { + for (i = 0; i < inputbitlen; i++) { agtb[i] = PutANDGate(a[i], PutINVGate(b[i])); //PutBitGreaterThanGate(a[i], b[i]); } - //compute the pairwise bit equality from bits 1 to bit rep - for (i = 1; i < rep; i++) { + //compute the pairwise bit equality from bits 1 to bit inputbitlen + for (i = 1; i < inputbitlen; i++) { eq[i] = PutINVGate(PutXORGate(a[i], b[i])); } - rem = rep; + rem = inputbitlen; while (rem > 1) { uint32_t j = 0; @@ -1699,9 +1673,9 @@ uint32_t BooleanCircuit::PutLUTGTGate(std::vector a, std::vector a, std::vector b) { PadWithLeadingZeros(a, b); - uint32_t rep = a.size(), temp; - std::vector xors(rep); - for (uint32_t i = 0; i < rep; i++) { + uint32_t inputbitlen = a.size(), temp; + std::vector xors(inputbitlen); + for (uint32_t i = 0; i < inputbitlen; i++) { temp = PutXORGate(a[i], b[i]); xors[i] = PutINVGate(temp); } @@ -1736,17 +1710,17 @@ share* BooleanCircuit::PutORGate(share* a, share* b) { /* if c [0] = s & a[0], c[1] = s & a[1], ...*/ share* BooleanCircuit::PutANDVecGate(share* ina, share* inb) { - uint32_t rep = ina->get_bitlength(); - share* out = new boolshare(rep, this); + uint32_t inputbitlen = ina->get_bitlength(); + share* out = new boolshare(inputbitlen, this); if (m_eContext == S_BOOL) { - for (uint32_t i = 0; i < rep; i++) { + for (uint32_t i = 0; i < inputbitlen; i++) { out->set_wire_id(i, PutVectorANDGate(inb->get_wire_id(i), ina->get_wire_id(i))); } } else { //std::cout << "Putting usual AND gate" << std::endl; - for (uint32_t i = 0; i < rep; i++) { - uint32_t bvec = PutRepeaterGate(inb->get_wire_id(i), m_pGates[ina->get_wire_id(i)].nvals); + for (uint32_t i = 0; i < inputbitlen; i++) { + uint32_t bvec = PutRepeaterGate(inb->get_wire_id(i), m_vGates[ina->get_wire_id(i)].nvals); out->set_wire_id(i, PutANDGate(ina->get_wire_id(i), bvec)); } } @@ -1756,21 +1730,21 @@ share* BooleanCircuit::PutANDVecGate(share* ina, share* inb) { /* if s == 0 ? b : a*/ std::vector BooleanCircuit::PutMUXGate(std::vector a, std::vector b, uint32_t s, BOOL vecand) { std::vector out; - uint32_t rep = std::max(a.size(), b.size()); + uint32_t inputbitlen = std::max(a.size(), b.size()); uint32_t sab, ab; PadWithLeadingZeros(a, b); - out.resize(rep); + out.resize(inputbitlen); uint32_t nvals=1; for(uint32_t i = 0; i < a.size(); i++) { - if(m_pGates[a[i]].nvals > nvals) - nvals = m_pGates[a[i]].nvals; + if(m_vGates[a[i]].nvals > nvals) + nvals = m_vGates[a[i]].nvals; } for(uint32_t i = 0; i < b.size(); i++) - if(m_pGates[b[i]].nvals > nvals) - nvals = m_pGates[b[i]].nvals; + if(m_vGates[b[i]].nvals > nvals) + nvals = m_vGates[b[i]].nvals; if (m_eContext == S_BOOL && vecand && nvals == 1) { uint32_t avec = PutCombinerGate(a); @@ -1779,7 +1753,7 @@ std::vector BooleanCircuit::PutMUXGate(std::vector a, std::v out = PutSplitterGate(PutVecANDMUXGate(avec, bvec, s)); } else { - for (uint32_t i = 0; i < rep; i++) { + for (uint32_t i = 0; i < inputbitlen; i++) { ab = PutXORGate(a[i], b[i]); sab = PutANDGate(s, ab); out[i] = PutXORGate(b[i], sab); @@ -1799,14 +1773,11 @@ std::vector BooleanCircuit::PutVecANDMUXGate(std::vector a, PadWithLeadingZeros(a, b); std::vector out(nmuxes); - uint32_t sab, ab; //std::cout << "Putting Vector AND gate" << std::endl; for (uint32_t i = 0; i < nmuxes; i++) { - ab = PutXORGate(a[i], b[i]); - sab = PutVectorANDGate(s[i], ab); - out[i] = PutXORGate(b[i], sab); + out[i] = PutVecANDMUXGate(a[i], b[i], s[i]); } return out; @@ -1819,8 +1790,7 @@ uint32_t BooleanCircuit::PutVecANDMUXGate(uint32_t a, uint32_t b, uint32_t s) { if (m_eContext == S_BOOL) { sab = PutVectorANDGate(s, ab); } else { - uint32_t svec = PutRepeaterGate(s, m_pGates[ab].nvals); - sab = PutANDGate(svec, ab); + sab = PutANDGate(s, ab); } return PutXORGate(b, sab); } @@ -1918,11 +1888,11 @@ share** BooleanCircuit::PutCondSwapGate(share* a, share* b, share* s, BOOL vecto //if s == 0: a stays a, else a becomes b std::vector > BooleanCircuit::PutCondSwapGate(std::vector a, std::vector b, uint32_t s, BOOL vectorized) { std::vector > out(2); - uint32_t rep = std::max(a.size(), b.size()); + uint32_t inputbitlen = std::max(a.size(), b.size()); PadWithLeadingZeros(a, b); - out[0].resize(rep); - out[1].resize(rep); + out[0].resize(inputbitlen); + out[1].resize(inputbitlen); uint32_t ab, snab, svec; @@ -1936,12 +1906,12 @@ std::vector > BooleanCircuit::PutCondSwapGate(std::vector< out[0] = PutSplitterGate(PutXORGate(snab, avec)); out[1] = PutSplitterGate(PutXORGate(snab, bvec)); } else { - if (m_pGates[s].nvals < m_pGates[a[0]].nvals) - svec = PutRepeaterGate(s, m_pGates[a[0]].nvals); + if (m_vGates[s].nvals < m_vGates[a[0]].nvals) + svec = PutRepeaterGate(s, m_vGates[a[0]].nvals); else svec = s; - for (uint32_t i = 0; i < rep; i++) { + for (uint32_t i = 0; i < inputbitlen; i++) { ab = PutXORGate(a[i], b[i]); snab = PutANDGate(svec, ab); @@ -2174,7 +2144,6 @@ void BooleanCircuit::PutMaxIdxGate(std::vector > vals, std std::vector& maxval, std::vector& maxid) { // build a balanced binary tree uint32_t cmp; - uint32_t avec, bvec; std::vector > m_vELMs = vals; #ifdef USE_MULTI_MUX_GATES uint32_t nvariables = 2; @@ -2319,8 +2288,8 @@ std::vector BooleanCircuit::PutGateFromFile(const std::string filename wires[tokens[0]] = PutConstantGate(0, nvals); break; - case '1': // Constant Zero Gate - wires[tokens[0]] = PutConstantGate((1 << nvals) - 1, nvals); + case '1': // Constant One Gate + wires[tokens[0]] = PutConstantGate(1, nvals); break; case 'A': // AND Gate @@ -2360,6 +2329,7 @@ std::vector BooleanCircuit::PutGateFromFile(const std::string filename else { std::cerr << "Error: Unable to open circuit file " << filename << std::endl; + std::exit(EXIT_FAILURE); } wires.clear(); @@ -2386,6 +2356,7 @@ std::vector BooleanCircuit::PutUniversalCircuitFromFile(const std::str if(!p1file.is_open()) { std::cerr << "Error: Unable to open programming file " << p1filename << std::endl; + std::exit(EXIT_FAILURE); } #ifdef DEBUG_UC std::cout << "Server Input Control Bits " ; @@ -2427,6 +2398,7 @@ std::vector BooleanCircuit::PutUniversalCircuitFromFile(const std::str if (!myfile.is_open()) { std::cerr << "Error: Unable to open circuit file " << filename << std::endl; + std::exit(EXIT_FAILURE); } while (getline(myfile, line)) { @@ -2528,6 +2500,7 @@ void BooleanCircuit::GetInputLengthFromFile(const std::string filename, uint32_t if (!myfile.is_open()) { std::cerr << "Error: Unable to open circuit file " << filename << std::endl; + std::exit(EXIT_FAILURE); } while (getline(myfile, line)) { @@ -2675,6 +2648,7 @@ std::vector BooleanCircuit::PutLUTGateFromFile(const std::string filen else { std::cerr << "Error: Unable to open circuit file " << filename << std::endl; + std::exit(EXIT_FAILURE); } wires.clear(); @@ -2718,6 +2692,7 @@ uint32_t BooleanCircuit::GetInputLengthFromFile(const std::string filename){ else { std::cerr << "Error: Unable to open circuit file " << filename << std::endl; + std::exit(EXIT_FAILURE); } tokens.clear(); @@ -2748,9 +2723,8 @@ uint32_t BooleanCircuit::PutIdxGate(uint32_t r, uint32_t maxidx) { void BooleanCircuit::PutMultiMUXGate(share** Sa, share** Sb, share* sel, uint32_t nshares, share** Sout) { std::vector inputsa, inputsb; - uint32_t *posids; uint32_t bitlen = 0; - uint32_t nvals = m_pGates[sel->get_wire_id(0)].nvals; + uint32_t nvals = m_vGates[sel->get_wire_id(0)].nvals; //Yao not allowed, if so just put standard muxes assert(m_eContext == S_BOOL); @@ -2821,389 +2795,390 @@ void BooleanCircuit::Reset() { void BooleanCircuit::PadWithLeadingZeros(std::vector &a, std::vector &b) { uint32_t maxlen = std::max(a.size(), b.size()); if(a.size() != b.size()) { - uint32_t zerogate = PutConstantGate(0, m_pGates[a[0]].nvals); + uint32_t zerogate = PutConstantGate(0, m_vGates[a[0]].nvals); a.resize(maxlen, zerogate); b.resize(maxlen, zerogate); } } share* BooleanCircuit::PutFullAdderGate(uint32_t a, uint32_t b, uint32_t carry_in) { - std::vector out(2); - uint32_t sum, carry_out; + std::vector out(2); #ifdef FA_DEBUG - std::vector v_a(1); v_a[0]=a; - std::vector v_b(1); v_b[0]=b; - std::vector v_c_in(1); v_c_in[0]=carry_in; - share * s_a = new boolshare(v_a, this); - share * s_b = new boolshare(v_b, this); - share * s_c_in = new boolshare(v_c_in, this); - - PutPrintValueGate(s_a, "a"); - PutPrintValueGate(s_b, "b"); - PutPrintValueGate(s_c_in, "carry_in"); - - share * s_a_xor_b = PutXORGate(s_a, s_b); - share * s_b_xor_c_in = PutXORGate(s_b, s_c_in); - share * s_and = PutANDGate(s_a_xor_b, s_b_xor_c_in); - - - PutPrintValueGate(s_a_xor_b, "a^b"); - PutPrintValueGate(s_b_xor_c_in, "b^c_in"); - PutPrintValueGate(s_and, "(a^b)&(b^c_in)"); + std::vector v_a(1); v_a[0]=a; + std::vector v_b(1); v_b[0]=b; + std::vector v_c_in(1); v_c_in[0]=carry_in; + share * s_a = new boolshare(v_a, this); + share * s_b = new boolshare(v_b, this); + share * s_c_in = new boolshare(v_c_in, this); + + PutPrintValueGate(s_a, "a"); + PutPrintValueGate(s_b, "b"); + PutPrintValueGate(s_c_in, "carry_in"); + + share * s_a_xor_b = PutXORGate(s_a, s_b); + share * s_b_xor_c_in = PutXORGate(s_b, s_c_in); + share * s_and = PutANDGate(s_a_xor_b, s_b_xor_c_in); + + + PutPrintValueGate(s_a_xor_b, "a^b"); + PutPrintValueGate(s_b_xor_c_in, "b^c_in"); + PutPrintValueGate(s_and, "(a^b)&(b^c_in)"); #endif - uint32_t a_xor_b = PutXORGate(a,b); - out[1] = PutXORGate(PutANDGate(a_xor_b, PutXORGate(b, carry_in)),b); - out[0] = PutXORGate(a_xor_b, carry_in); - - share* s_out = new boolshare(out, this); - + uint32_t a_xor_b = PutXORGate(a,b); + out[1] = PutXORGate(PutANDGate(a_xor_b, PutXORGate(b, carry_in)),b); + out[0] = PutXORGate(a_xor_b, carry_in); + + share* s_out = new boolshare(out, this); + #ifdef FA_DEBUG - std::vector in(3); - in[2] = a; - in[1] = b; - in[0] = carry_in; - share* s_in = new boolshare(in, this); - - PutPrintValueGate(s_in, "Full Adder Input"); - PutPrintValueGate(s_out, "Full Adder Output"); + std::vector in(3); + in[2] = a; + in[1] = b; + in[0] = carry_in; + share* s_in = new boolshare(in, this); + + PutPrintValueGate(s_in, "Full Adder Input"); + PutPrintValueGate(s_out, "Full Adder Output"); #endif - - return s_out; + + return s_out; } share* BooleanCircuit::PutADDChainGate(std::vector a, std::vector b, uint32_t carry_in) { - PadWithLeadingZeros(a, b); - std::vector out(a.size()); - std::vector v_c_in(1); v_c_in[0] = carry_in; - share * s_c_in = new boolshare(v_c_in, this); - share * last = PutFullAdderGate(a[0], b[0], carry_in); - out[0] = last->get_wires()[0]; + PadWithLeadingZeros(a, b); + std::vector out(a.size()); + std::vector v_c_in(1); v_c_in[0] = carry_in; + share * last = PutFullAdderGate(a[0], b[0], carry_in); + out[0] = last->get_wires()[0]; #ifdef AC_DEBUG - PutPrintValueGate(s_c_in, "carry in"); - PutPrintValueGate(last, "last"); + share * s_c_in = new boolshare(v_c_in, this); + PutPrintValueGate(s_c_in, "carry in"); + PutPrintValueGate(last, "last"); #endif - for (size_t i = 1; i < out.size(); ++i) { - share * tmp = PutFullAdderGate(a[i], b[i], last->get_wires()[1]); - out[i] = tmp->get_wires()[0]; - last = tmp; + for (size_t i = 1; i < out.size(); ++i) { + share * tmp = PutFullAdderGate(a[i], b[i], last->get_wires()[1]); + out[i] = tmp->get_wires()[0]; + last = tmp; #ifdef AC_DEBUG - PutPrintValueGate(new boolshare(std::vector(&a[i], &a[i+1]), this), "a i"); - PutPrintValueGate(new boolshare(std::vector(&b[i], &b[i+1]), this), "b i"); - PutPrintValueGate(tmp, "tmp"); + PutPrintValueGate(new boolshare(std::vector(&a[i], &a[i+1]), this), "a i"); + PutPrintValueGate(new boolshare(std::vector(&b[i], &b[i+1]), this), "b i"); + PutPrintValueGate(tmp, "tmp"); #endif - } - std::vector l = last->get_wires(); - if (last->get_wires()[1] && out.size() < last->get_max_bitlength()) - out.insert(out.end(), &l[1], &l[2]); + } + std::vector l = last->get_wires(); + if (last->get_wires()[1] && out.size() < last->get_max_bitlength()) + out.insert(out.end(), &l[1], &l[2]); #ifdef AC_DEBUG - PutPrintValueGate(last, "last last"); - PutPrintValueGate(new boolshare(out, this), "out"); + PutPrintValueGate(last, "last last"); + PutPrintValueGate(new boolshare(out, this), "out"); #endif - return new boolshare(out, this); + return new boolshare(out, this); } share* BooleanCircuit::PutHammingWeightGate(share* s_in) { - return PutHammingWeightGate(s_in, s_in->get_bitlength()); + return PutHammingWeightGate(s_in, s_in->get_bitlength()); } share* BooleanCircuit::PutHammingWeightGate(share* s_in, uint32_t bitlen) { #ifdef HW_DEBUG - PutPrintValueGate(s_in, "INPUT_BUILD"); + PutPrintValueGate(s_in, "INPUT_BUILD"); #endif - // force all nvals equal assert - s_in->get_nvals(); - std::vector wires = s_in->get_wires(); - return PutHammingWeightGateRec(wires.data(), bitlen); + // force all nvals equal assert + s_in->get_nvals(); + std::vector wires = s_in->get_wires(); + return PutHammingWeightGateRec(wires.data(), bitlen); } share* BooleanCircuit::PutHammingWeightGateRec(uint32_t * wires, uint32_t bitlen) { - share* out; - uint32_t nvals = GetNumVals(wires[0]); + share* out; + uint32_t nvals = GetNumVals(wires[0]); - UGATE_T zero = 0u; - share* zero_share = PutSIMDCONSGate(nvals, zero, 1); - uint32_t zero_wire = zero_share->get_wire_id(0); + UGATE_T zero = 0u; + share* zero_share = PutSIMDCONSGate(nvals, zero, 1); + uint32_t zero_wire = zero_share->get_wire_id(0); #ifdef HW_DEBUG - std::vector in(wires, wires + bitlen); - share * s = new boolshare(in, this); - PutPrintValueGate(s, "INPUT3"); - delete s; + std::vector in(wires, wires + bitlen); + share * s = new boolshare(in, this); + PutPrintValueGate(s, "INPUT3"); + delete s; #endif - if (bitlen > 3) { - share *v, *u; - uint32_t i; - size_t bitlen_v = pow(2, (uint) (log(bitlen) / log(2))) - 1; - size_t bitlen_u = bitlen - bitlen_v - 1; + if (bitlen > 3) { + share *v, *u; + uint32_t i; + size_t bitlen_v = pow(2, (uint) (log(bitlen) / log(2))) - 1; + size_t bitlen_u = bitlen - bitlen_v - 1; #ifdef HW_DEBUG - std::cout << "Input bitlen: " << bitlen << "\tBitlen v: " << bitlen_v << - "\tBitlen u: " << bitlen_u << "\tBitlen i: " << - bitlen - bitlen_v - bitlen_u << std::endl; + std::cout << "Input bitlen: " << bitlen << "\tBitlen v: " << bitlen_v << + "\tBitlen u: " << bitlen_u << "\tBitlen i: " << + bitlen - bitlen_v - bitlen_u << std::endl; #endif - //build v - v = PutHammingWeightGateRec(&wires[bitlen - bitlen_v], bitlen_v); - - //build u - if (bitlen_u > 0) { - u = PutHammingWeightGateRec(&wires[1], bitlen_u); - } else { - u = zero_share; - } - - //build i - if (bitlen - bitlen_v > 0) { - i = wires[0]; - } else { - i = zero_wire; - } + //build v + v = PutHammingWeightGateRec(&wires[bitlen - bitlen_v], bitlen_v); + + //build u + if (bitlen_u > 0) { + u = PutHammingWeightGateRec(&wires[1], bitlen_u); + } else { + u = zero_share; + } + + //build i + if (bitlen - bitlen_v > 0) { + i = wires[0]; + } else { + i = zero_wire; + } #ifdef HW_DEBUG - PutPrintValueGate(v, "V"); - PutPrintValueGate(u, "U"); - std::vector v_i(1, i); - PutPrintValueGate(std::make_unique(v_i, this).get(), "i"); - std::cout << std::endl; + PutPrintValueGate(v, "V"); + PutPrintValueGate(u, "U"); + std::vector v_i(1, i); + PutPrintValueGate(std::make_unique(v_i, this).get(), "i"); + std::cout << std::endl; #endif - out = PutADDChainGate(v->get_wires(), u->get_wires(), i); - delete v; - if (bitlen_u>0) delete u; // u == zero_share otherwise and deleted later - } else if (bitlen > 2) - out = PutFullAdderGate(wires[2], wires[1], wires[0]); - else if (bitlen > 1) { - out = PutFullAdderGate(wires[1], wires[0], zero_wire); - } else if (bitlen > 0) { - std::vector out_v(1, wires[0]); - out = new boolshare(out_v, this); - } else { - return zero_share; - } - - delete zero_share; - return out; + out = PutADDChainGate(v->get_wires(), u->get_wires(), i); + delete v; + if (bitlen_u>0) delete u; // u == zero_share otherwise and deleted later + } else if (bitlen > 2) + out = PutFullAdderGate(wires[2], wires[1], wires[0]); + else if (bitlen > 1) { + out = PutFullAdderGate(wires[1], wires[0], zero_wire); + } else if (bitlen > 0) { + std::vector out_v(1, wires[0]); + out = new boolshare(out_v, this); + } else { + return zero_share; + } + + delete zero_share; + return out; } share* BooleanCircuit::PutUint2DoubleGate(share* input){ - UINT32 from; - FP64 to; - return PutConvTypeGate(input, &from, &to); + UINT32 from; + FP64 to; + return PutConvTypeGate(input, &from, &to); } share* BooleanCircuit::PutConvTypeGate(share * value, ConvType* from, ConvType* to, uint32_t nvals){ - return new boolshare(PutConvTypeGate(value->get_wires(),from,to, nvals), this); + return new boolshare(PutConvTypeGate(value->get_wires(), from, to, nvals), this); } std::vector BooleanCircuit::PutConvTypeGate(std::vector wires, ConvType* from, ConvType* to, uint32_t nvals){ - uint32_t out; - switch(to->getType()){ - case ENUM_FP_TYPE: - return PutUint2FpGate(wires, (UINTType*)from , (FPType*)to, nvals); - case ENUM_UINT_TYPE: - return PutFp2UintGate(wires, (FPType*)from , (UINTType*)to); - default: - std::cout <<"Unknown data type in CONVType %zu" << to << std::endl; - std::exit(EXIT_FAILURE); - } + switch(to->getType()){ + case ENUM_FP_TYPE: + return PutUint2FpGate(wires, (UINTType*)from , (FPType*)to, nvals); + // case ENUM_UINT_TYPE: + // return PutFp2UintGate(wires, (FPType*)from , (UINTType*)to); + default: + std::cout <<"Unknown data type in CONVType %zu" << to << std::endl; + std::exit(EXIT_FAILURE); + } } -std::vector BooleanCircuit::PutUint2FpGate(std::vector wires, UINTType* from, FPType* to, uint32_t nvals){ +//TODO: value is in wires, remove paramter "from"? +std::vector BooleanCircuit::PutUint2FpGate(std::vector wires, [[maybe_unused]] UINTType* from, FPType* to, uint32_t nvals){ #ifdef UINT2FP_DEBUG - PutPrintValueGate(new boolshare(wires, this), "INPUT"); - std::cout << "wires size: " << wires.size() << std::endl; + PutPrintValueGate(new boolshare(wires, this), "INPUT"); + std::cout << "wires size: " << wires.size() << std::endl; #endif - //constants - uint64_t zero = 0, one = 1; - uint32_t one_bit_len = 1; - share* zero_gate = PutSIMDCONSGate(nvals, zero, one_bit_len); - share* one_gate = PutSIMDCONSGate(nvals, one, one_bit_len); - //pad to the length of fraction or remove the most significant bits - wires.resize(to->getNumOfDigits(), zero_gate->get_wires()[0]); - share * s_in = new boolshare(wires, this); - - //check if input is zero - share* eq_zero = PutEQGate(zero_gate, s_in); - - //calculate prefix or - std::vector prefix_or = PutPreOrGate(wires); - share * s_prefix_or = new boolshare(prefix_or, this); + //constants + uint64_t zero = 0, one = 1; + uint32_t one_bit_len = 1; + share* zero_gate = PutSIMDCONSGate(nvals, zero, one_bit_len); + share* one_gate = PutSIMDCONSGate(nvals, one, one_bit_len); + //pad to the length of fraction or remove the most significant bits + wires.resize(to->getNumOfDigits(), zero_gate->get_wires()[0]); + share * s_in = new boolshare(wires, this); + + //check if input is zero + share* eq_zero = PutEQGate(zero_gate, s_in); + + //calculate prefix or + std::vector prefix_or = PutPreOrGate(wires); + share * s_prefix_or = new boolshare(prefix_or, this); #ifdef UINT2FP_DEBUG - PutPrintValueGate(s_prefix_or, "PREFIX OR"); + PutPrintValueGate(s_prefix_or, "PREFIX OR"); #endif - - std::vector reversed_preor; - reversed_preor.insert(reversed_preor.begin(), prefix_or.rbegin(), prefix_or.rend()); - share * value = new boolshare(PutINVGate(reversed_preor), this); - - value->set_max_bitlength(to->getNumOfDigits()+1); - std::vector tmp_inv_out = value->get_wires(); - - std::vector power_of_2; - power_of_2.insert(power_of_2.begin(), tmp_inv_out.begin(), tmp_inv_out.end()); - power_of_2.push_back(one_gate->get_wires()[0]); - share * p2 = new boolshare(power_of_2,this); - - value = PutHammingWeightGate(p2, nvals); - - value = new boolshare(PutBarrelLeftShifterGate(s_in->get_wires(), value->get_wires(), nvals), this); - std::vector tmp_fract = value->get_wires(); - tmp_fract.resize(to->getNumOfDigits()); - - value = new boolshare(tmp_fract ,this); - - std::vector value_v = value->get_wires(); + + std::vector reversed_preor; + reversed_preor.insert(reversed_preor.begin(), prefix_or.rbegin(), prefix_or.rend()); + share * value = new boolshare(PutINVGate(reversed_preor), this); + + value->set_max_bitlength(to->getNumOfDigits()+1); + std::vector tmp_inv_out = value->get_wires(); + + std::vector power_of_2; + power_of_2.insert(power_of_2.begin(), tmp_inv_out.begin(), tmp_inv_out.end()); + power_of_2.push_back(one_gate->get_wires()[0]); + share * p2 = new boolshare(power_of_2,this); + + value = PutHammingWeightGate(p2, nvals); + + value = new boolshare(PutBarrelLeftShifterGate(s_in->get_wires(), value->get_wires(), nvals), this); + std::vector tmp_fract = value->get_wires(); + tmp_fract.resize(to->getNumOfDigits()); + + value = new boolshare(tmp_fract ,this); + + std::vector value_v = value->get_wires(); #ifdef UINT2FP_DEBUG - PutPrintValueGate(value, "VALUE"); + PutPrintValueGate(value, "VALUE"); #endif - std::reverse(value_v.begin(), value_v.end()); - - value_v.resize(to->getNumOfDigits(), zero_gate->get_wires()[0]); + std::reverse(value_v.begin(), value_v.end()); + + value_v.resize(to->getNumOfDigits(), zero_gate->get_wires()[0]); #ifdef UINT2FP_DEBUG - //PutPrintValueGate(new boolshare(value_v, this), "RESIZED"); - std::cout << "fraction vector size: " << value_v.size() << std::endl; + //PutPrintValueGate(new boolshare(value_v, this), "RESIZED"); + std::cout << "fraction vector size: " << value_v.size() << std::endl; #endif - //Calculate number of 1-bits in Prefix OR output - share* pre_or_for_exp = PutHammingWeightGate(s_prefix_or, nvals); + //Calculate number of 1-bits in Prefix OR output + share* pre_or_for_exp = PutHammingWeightGate(s_prefix_or, nvals); #ifdef UINT2FP_DEBUG - std::cout << "HW out size: " << pre_or_for_exp->get_wires().size() << std::endl; - PutPrintValueGate(pre_or_for_exp, "pre or for exp"); + std::cout << "HW out size: " << pre_or_for_exp->get_wires().size() << std::endl; + PutPrintValueGate(pre_or_for_exp, "pre or for exp"); #endif - share * exp = PutSIMDCONSGate(nvals, (uint64_t)(to->getExpBias()-1), to->getExpBits()); + share * exp = PutSIMDCONSGate(nvals, (uint64_t)(to->getExpBias()-1), to->getExpBits()); #ifdef UINT2FP_DEBUG - PutPrintValueGate(exp, "exp initialized with bias"); - std::cout << "bias bit length: " << exp->get_wires().size() << std::endl; + PutPrintValueGate(exp, "exp initialized with bias"); + std::cout << "bias bit length: " << exp->get_wires().size() << std::endl; #endif - exp = PutADDGate(exp, pre_or_for_exp); - - std::vector tmp_exp = exp->get_wires(); - //exp = PutXORGate(exp, PutMUXGate(zero_gate,exp,eq_zero)); - exp = PutMUXGate(exp, zero_gate, eq_zero); - - tmp_exp.resize(to->getExpBits(), zero_gate->get_wires()[0]); - - std::vector v_out(1); - v_out[0]=zero_gate->get_wires()[0]; - std::vector exp_v(&tmp_exp[0], &tmp_exp[to->getExpBits()]); - v_out.insert(v_out.end() ,exp_v.rbegin(), exp_v.rend()); + exp = PutADDGate(exp, pre_or_for_exp); + + std::vector tmp_exp = exp->get_wires(); + //exp = PutXORGate(exp, PutMUXGate(zero_gate,exp,eq_zero)); + exp = PutMUXGate(exp, zero_gate, eq_zero); + + tmp_exp.resize(to->getExpBits(), zero_gate->get_wires()[0]); + + std::vector v_out(1); + v_out[0]=zero_gate->get_wires()[0]; + std::vector exp_v(&tmp_exp[0], &tmp_exp[to->getExpBits()]); + v_out.insert(v_out.end() ,exp_v.rbegin(), exp_v.rend()); #ifdef UINT2FP_DEBUG - std::cout << "out+exp size: " << v_out.size() << std::endl; + std::cout << "out+exp size: " << v_out.size() << std::endl; #endif - v_out.insert(v_out.end(), value_v.begin(), value_v.end()); - + v_out.insert(v_out.end(), value_v.begin(), value_v.end()); + #ifdef UINT2FP_DEBUG - PutPrintValueGate(new boolshare(exp_v, this), "exponent"); - PutPrintValueGate(new boolshare(value_v, this), "fraction"); + PutPrintValueGate(new boolshare(exp_v, this), "exponent"); + PutPrintValueGate(new boolshare(value_v, this), "fraction"); #endif - - std::reverse(v_out.begin(), v_out.end()); + + std::reverse(v_out.begin(), v_out.end()); #ifdef UINT2FP_DEBUG - std::cout << "Num of gates, end:" << GetNumGates() << std::endl; - //PutPrintValueGate(new boolshare(v_out, this), "RESULT"); + std::cout << "Num of gates, end:" << GetNumGates() << std::endl; + //PutPrintValueGate(new boolshare(v_out, this), "RESULT"); #endif - return v_out; + return v_out; } +/* +// TODO implement PutFP2INTGate std::vector BooleanCircuit::PutFp2UintGate(std::vector wires, FPType* from, UINTType* to){ - std::vector out; - // TODO implement PutFP2INTGate - std::cout << "PutFP2INTGate is not implemented yet" << std::endl; - std::exit(EXIT_FAILURE); - return out; + std::vector out; + std::cout << "PutFP2INTGate is not implemented yet" << std::endl; + std::exit(EXIT_FAILURE); + return out; } +*/ share * BooleanCircuit::PutPreOrGate(share * input){ - return new boolshare(PutPreOrGate(input->get_wires()), this); + return new boolshare(PutPreOrGate(input->get_wires()), this); } std::vector BooleanCircuit::PutPreOrGate(std::vector wires){ - //TODO optimize circuit - if(!wires.size()){ - std::cout << "PreORGate wires of size 0. Exitting." << std::endl; - std::exit(EXIT_FAILURE); - } + //TODO optimize circuit + if(!wires.size()){ + std::cout << "PreORGate wires of size 0. Exitting." << std::endl; + std::exit(EXIT_FAILURE); + } std::vector out(wires.size()); - out[wires.size()-1] = wires[wires.size()-1]; - - if(wires.size()==1) - return out; - - uint32_t tmp = PutORGate(wires[wires.size()-1], wires[wires.size()-2]); - out[wires.size()-2] = tmp; - - if(wires.size()==2) - return out; - - for(size_t i = 2; i < wires.size(); i++){ - tmp = PutORGate(tmp, wires[wires.size()-i-1]); - out[wires.size()-i-1]= tmp; - } - return out; + out[wires.size()-1] = wires[wires.size()-1]; + + if(wires.size()==1) + return out; + + uint32_t tmp = PutORGate(wires[wires.size()-1], wires[wires.size()-2]); + out[wires.size()-2] = tmp; + + if(wires.size()==2) + return out; + + for(size_t i = 2; i < wires.size(); i++){ + tmp = PutORGate(tmp, wires[wires.size()-i-1]); + out[wires.size()-i-1]= tmp; + } + return out; } share * BooleanCircuit::PutBarrelLeftShifterGate(share * input, share * n){ - return new boolshare(PutBarrelLeftShifterGate(input->get_wires(), n->get_wires()), this); -} - -std::vector BooleanCircuit::PutBarrelLeftShifterGate(std::vector wires, - std::vector n, uint32_t nvals){ - uint n_size = (uint)(log(wires.size())/log(2)); - uint step = pow(2, (double)n_size); - auto out_size = step*2; - - std::vector res(out_size); - std::vector last; - - uint64_t zero = 0; - share* zero_gate = PutSIMDCONSGate(nvals, zero, 1); - - n.resize(n_size, zero_gate->get_wires()[0]); - wires.resize(out_size, zero_gate->get_wires()[0]); - for(int i = n_size; i >=0 ; i--, step/=2){ - for(auto j = 0; j < out_size; j++){ - std::vector tmp_right(1); - std::vector tmp_left(1); - if(step == out_size/2){ - tmp_right[0] = wires[j]; - tmp_left[0] = j < step ? zero_gate->get_wires()[0] : wires[j-step]; - } - else{ - tmp_right[0] = last[j]; - tmp_left[0] = j < step ? zero_gate->get_wires()[0] : last[j-step]; - } - res[j] = PutMUXGate(tmp_left, tmp_right, n[i])[0]; - } - last.clear(); - last.insert(last.begin(), res.begin(), res.end()); - } - return res; + return new boolshare(PutBarrelLeftShifterGate(input->get_wires(), n->get_wires()), this); +} + +std::vector BooleanCircuit::PutBarrelLeftShifterGate(std::vector wires, + std::vector n, uint32_t nvals){ + uint n_size = (uint)(log(wires.size())/log(2)); + auto step = pow(2, (double)n_size); + auto out_size = step*2; + + std::vector res(out_size); + std::vector last; + + uint64_t zero = 0; + share* zero_gate = PutSIMDCONSGate(nvals, zero, 1); + + n.resize(n_size, zero_gate->get_wires()[0]); + wires.resize(out_size, zero_gate->get_wires()[0]); + for(int i = n_size; i >=0 ; i--, step/=2){ + for(auto j = 0; j < out_size; j++){ + std::vector tmp_right(1); + std::vector tmp_left(1); + if(step == out_size/2){ + tmp_right[0] = wires[j]; + tmp_left[0] = j < step ? zero_gate->get_wires()[0] : wires[j-step]; + } + else{ + tmp_right[0] = last[j]; + tmp_left[0] = j < step ? zero_gate->get_wires()[0] : last[j-step]; + } + res[j] = PutMUXGate(tmp_left, tmp_right, n[i])[0]; + } + last.clear(); + last.insert(last.begin(), res.begin(), res.end()); + } + return res; } share * BooleanCircuit::PutBarrelRightShifterGate(share * input, share * n){ - return new boolshare(PutBarrelRightShifterGate(input->get_wires(), n->get_wires()), this); + return new boolshare(PutBarrelRightShifterGate(input->get_wires(), n->get_wires()), this); } std::vector BooleanCircuit::PutBarrelRightShifterGate(std::vector wires, std::vector n){ - std::reverse(wires.begin(), wires.end()); - std::vector res = PutBarrelLeftShifterGate(wires, n); - std::reverse(res.begin(), res.end()); - res.erase(res.begin(), res.begin() + wires.size()); - return res; + std::reverse(wires.begin(), wires.end()); + std::vector res = PutBarrelLeftShifterGate(wires, n); + std::reverse(res.begin(), res.end()); + res.erase(res.begin(), res.begin() + wires.size()); + return res; } share * BooleanCircuit::PutFPGate(share * in, op_t op, uint8_t bitlen, uint32_t nvals, fp_op_setting s){ @@ -3214,39 +3189,37 @@ share * BooleanCircuit::PutFPGate(share * in, op_t op, uint8_t bitlen, uint32_t if (nvals == 0) { nvals = in->get_nvals(); } - const char * o; - switch(op){ - case COS: - o = "ieee_cos"; - break; - case EXP: - o = "nostatus_exp"; - break; - case EXP2: - o = "nostatus_exp2"; - break; - case LN: - o = "nostatus_ln"; - break; - case LOG2: - o = "nostatus_log2"; - break; - case SIN: - o = "ieee_sin"; - break; - case SQR: - o = s==no_status ? "nostatus_sqr" : "ieee_sqr"; - break; - case SQRT: - o = s==no_status ? "nostatus_sqrt" : "ieee_sqrt"; - break; - default: - std::cerr << "Wrong operation in floating point gate with one input."; - std::exit(EXIT_FAILURE); - } - return new boolshare(PutFPGate(o, in->get_wires(), - (uint8_t) bitlen, - nvals), this); + const char * o; + switch(op){ + case COS: + o = "ieee_cos"; + break; + case EXP: + o = "nostatus_exp"; + break; + case EXP2: + o = "nostatus_exp2"; + break; + case LN: + o = "nostatus_ln"; + break; + case LOG2: + o = "nostatus_log2"; + break; + case SIN: + o = "ieee_sin"; + break; + case SQR: + o = s==no_status ? "nostatus_sqr" : "ieee_sqr"; + break; + case SQRT: + o = s==no_status ? "nostatus_sqrt" : "ieee_sqrt"; + break; + default: + std::cerr << "Wrong operation in floating point gate with one input."; + std::exit(EXIT_FAILURE); + } + return new boolshare(PutFPGate(o, in->get_wires(), bitlen, nvals), this); } share * BooleanCircuit::PutFPGate(share * in_a, share * in_b, op_t op, uint8_t bitlen, uint32_t nvals, fp_op_setting s){ @@ -3257,28 +3230,26 @@ share * BooleanCircuit::PutFPGate(share * in_a, share * in_b, op_t op, uint8_t b if (nvals == 0) { nvals = in_a->get_nvals(); } - const char * o; - switch(op){ - case ADD: - o = s==no_status ? "nostatus_add" : "ieee_add"; - break; - case CMP: - o = "nostatus_cmp"; - break; - case DIV: - o = s==no_status ? "nostatus_div" : "ieee_div"; - break; - case MUL: - o = s==no_status ? "nostatus_mult" : "ieee_mult"; - break; - case SUB: - o = s==no_status ? "nostatus_sub" : "ieee_sub"; - break; - default: - std::cerr << "Wrong operation in floating point gate with two inputs."; - std::exit(EXIT_FAILURE); - } - return new boolshare(PutFPGate(o, in_a->get_wires(), - in_b->get_wires(), (uint8_t) bitlen, - nvals), this); + const char * o; + switch(op){ + case ADD: + o = s==no_status ? "nostatus_add" : "ieee_add"; + break; + case CMP: + o = "nostatus_cmp"; + break; + case DIV: + o = s==no_status ? "nostatus_div" : "ieee_div"; + break; + case MUL: + o = s==no_status ? "nostatus_mult" : "ieee_mult"; + break; + case SUB: + o = s==no_status ? "nostatus_sub" : "ieee_sub"; + break; + default: + std::cerr << "Wrong operation in floating point gate with two inputs."; + std::exit(EXIT_FAILURE); + } + return new boolshare(PutFPGate(o, in_a->get_wires(), in_b->get_wires(), bitlen, nvals), this); } diff --git a/src/abycore/circuit/booleancircuits.h b/src/abycore/circuit/booleancircuits.h index dfb77934..76198624 100755 --- a/src/abycore/circuit/booleancircuits.h +++ b/src/abycore/circuit/booleancircuits.h @@ -2,17 +2,17 @@ \file booleancircuits.h \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief A collection of boolean circuits for boolean and yao sharing in the ABY framework */ #ifndef __BOOLEANCIRCUITS_H_ @@ -33,8 +33,7 @@ /** BooleanCircuit class. */ class BooleanCircuit: public Circuit { public: - //TODO this default circdir works for now, but should be changed, if things move some place else - BooleanCircuit(ABYCircuit* aby, e_role myrole, e_sharing context, const std::string& circdir = "../../bin/circ/") : + BooleanCircuit(ABYCircuit* aby, e_role myrole, e_sharing context, const std::string& circdir = ABY_CIRCUIT_DIR) : Circuit(aby, context, myrole, 1, C_BOOLEAN), m_cCircuitFileDir(circdir) { @@ -69,7 +68,7 @@ class BooleanCircuit: public Circuit { uint32_t gateid = PutINGate(m_eMyRole); //assign value - GATE* gate = m_pGates + gateid; + GATE* gate = &(m_vGates[gateid]); gate->gs.ishare.inval = (UGATE_T*) calloc(1 * m_nShareBitLen, sizeof(UGATE_T)); *gate->gs.ishare.inval = (UGATE_T) val; @@ -84,7 +83,7 @@ class BooleanCircuit: public Circuit { uint32_t gateid = PutINGate(role); if (role == m_eMyRole) { //assign value - GATE* gate = m_pGates + gateid; + GATE* gate = &(m_vGates[gateid]); gate->gs.ishare.inval = (UGATE_T*) calloc(ceil_divide(1 * m_nShareBitLen, GATE_T_BITS), sizeof(UGATE_T)); memcpy(gate->gs.ishare.inval, val, ceil_divide(1 * m_nShareBitLen, 8)); @@ -98,7 +97,7 @@ class BooleanCircuit: public Circuit { uint32_t gateid = PutSIMDINGate(ninvals, m_eMyRole); //assign value - GATE* gate = m_pGates + gateid; + GATE* gate = &(m_vGates[gateid]); gate->gs.ishare.inval = (UGATE_T*) calloc(ninvals * m_nShareBitLen, sizeof(UGATE_T)); *gate->gs.ishare.inval = (UGATE_T) val; @@ -111,7 +110,7 @@ class BooleanCircuit: public Circuit { uint32_t gateid = PutSIMDINGate(ninvals, role); if (role == m_eMyRole) { //assign value - GATE* gate = m_pGates + gateid; + GATE* gate = &(m_vGates[gateid]); gate->gs.ishare.inval = (UGATE_T*) calloc(ceil_divide(ninvals * m_nShareBitLen, GATE_T_BITS), sizeof(UGATE_T)); memcpy(gate->gs.ishare.inval, val, ceil_divide(ninvals * m_nShareBitLen, 8)); gate->instantiated = true; @@ -125,7 +124,7 @@ class BooleanCircuit: public Circuit { uint32_t gateid = PutSharedINGate(); //assign value - GATE* gate = m_pGates + gateid; + GATE* gate = &(m_vGates[gateid]); gate->gs.val = (UGATE_T*) calloc(1 * m_nShareBitLen, sizeof(UGATE_T)); *gate->gs.val = (UGATE_T) val; @@ -138,7 +137,7 @@ class BooleanCircuit: public Circuit { uint32_t gateid = PutSharedINGate(); //assign value - GATE* gate = m_pGates + gateid; + GATE* gate = &(m_vGates[gateid]); gate->gs.val = (UGATE_T*) calloc(ceil_divide(1 * m_nShareBitLen, GATE_T_BITS), sizeof(UGATE_T)); memcpy(gate->gs.val, val, ceil_divide(1 * m_nShareBitLen, 8)); @@ -153,7 +152,7 @@ class BooleanCircuit: public Circuit { uint32_t gateid = PutSharedSIMDINGate(ninvals); //assign value - GATE* gate = m_pGates + gateid; + GATE* gate = &(m_vGates[gateid]); gate->gs.val = (UGATE_T*) calloc(ninvals * m_nShareBitLen, sizeof(UGATE_T)); *gate->gs.val = (UGATE_T) val; @@ -165,7 +164,7 @@ class BooleanCircuit: public Circuit { template uint32_t PutSharedSIMDINGate(uint32_t ninvals, T* val) { uint32_t gateid = PutSharedSIMDINGate(ninvals); //assign value - GATE* gate = m_pGates + gateid; + GATE* gate = &(m_vGates[gateid]); gate->gs.val = (UGATE_T*) calloc(ceil_divide(ninvals * m_nShareBitLen, GATE_T_BITS), sizeof(UGATE_T)); memcpy(gate->gs.val, val, ceil_divide(ninvals * m_nShareBitLen, 8)); gate->instantiated = true; @@ -326,7 +325,7 @@ class BooleanCircuit: public Circuit { return m_nNumANDSizes; } ; - std::vector > > GetTTLens() { + std::vector > > GetTTLens() { //inptr = m_vTTlens; return m_vTTlens; } @@ -492,158 +491,159 @@ class BooleanCircuit: public Circuit { uint32_t PutUniversalGateCircuit(uint32_t a, uint32_t b, uint32_t op_id); - /** - * Constructs optimal Hamming Weight Gate. Described by Boyar, Joan, and - * René Peralta in "Tight bounds for the multiplicative complexity of - * symmetric functions." - * @param s_in Input share - * @return Number of 1's in the input bit string - */ - share* PutHammingWeightGate(share* s_in); - - /** - * Constructs optimal Hamming Weight Gate. Described by Boyar, Joan, and - * René Peralta in "Tight bounds for the multiplicative complexity of - * symmetric functions." - * @param s_in Input share - * @param bitlen Bit length of the input - * @return Number of 1's in the input bit string - */ - share* PutHammingWeightGate(share* s_in, uint32_t bitlen); - - /** - * Recursively constructs optimal Hamming Weight Gate. Described by - * Boyar, Joan, and René Peralta in "Tight bounds for the multiplicative - * complexity of symmetric functions." - * @param array Array of wires - * @param bitlen Bit length of the input - * @return Number of 1's in the input bit string - */ - share* PutHammingWeightGateRec(uint32_t * array, uint32_t bitlen); - - /** - * Constructs Full Adder Gate - * @param a Input bit a - * @param b Input bit b - * @param carry_in Input bit carry in - * @return sum of input bits - */ - share* PutFullAdderGate(uint32_t a, uint32_t b, uint32_t carry_in); - - /** - * Constructs Adder Chain Gate - * @param a vector of wires a - * @param b vector of wires b - * @param carry_in optional carry in bit c (zero gate if not needed) - * @return sum of values on wires a and b - */ - share* PutADDChainGate(std::vector a, std::vector b, uint32_t carry_in); - - - /** - * Converts unsigned integer input to floating point number of double precision - * @param input unsigned integer input - * @return floating point number of double precision - */ - share* PutUint2DoubleGate(share* input); - - /** - * Converts a number "value" from the type "from" to the type "to" - * @param value input value - * @param from type of the value - * @param to type to which value will be converted - * @return converted value - */ - share* PutConvTypeGate(share* value, ConvType* from, ConvType* to, uint32_t nvals = 1); - - /** - * Converts a number "value" from the type "from" to the type "to" - * @param wires wires of the input value - * @param from type of the value - * @param to type to which value will be converted - * @return wires of the converted value - */ - std::vector PutConvTypeGate(std::vector wires, ConvType* from, ConvType* to, uint32_t nvals = 1); - - /** - * Converts unsigned integer to floating point number - * @param wires wires of the input value - * @param from type of the value - * @param to type to which value will be converted - * @return wires of the converted value - */ - std::vector PutUint2FpGate(std::vector wires, UINTType* from, FPType* to, uint32_t nvals = 1); - - /** - * Converts floating point to unsigned integer number - * @param wires wires of the input value - * @param from type of the value - * @param to type to which value will be converted - * @return wires of the converted value - */ - std::vector PutFp2UintGate(std::vector wires, FPType* from, UINTType* to); - - /** - * Computes Prefix Or operation, thus, zeros before first seen 1 and 1s after (e.g. 0010100 => 0011111). - * @param input input value - * @return return value of prefix or - */ - share * PutPreOrGate(share * input); - - /** - * Computes Prefix Or operation, thus, zeros before first seen 1 and 1s after (e.g. 0010100 => 0011111). - * @param wires input value - * @return value of prefix or - */ - std::vector PutPreOrGate(std::vector wires); - - /** - * Uses MUXs to shift bits of the value to the left. - * @param input input value - * @param n number of bits to shift - * @return shifted value - */ - share * PutBarrelLeftShifterGate(share * input, share * n); - /** - * Uses MUXs to shift bits of the value to the left. - * @param wires input value - * @param n number of bits to shift - * @return shifted value - */ - std::vector PutBarrelLeftShifterGate(std::vector wires, std::vector n, uint32_t nvals = 1); - /** - * Uses MUXs to shift bits of the value to the right. - * @param input input value - * @param n number of bits to shift - * @return shifted value - */ - share * PutBarrelRightShifterGate(share * input, share * n); - /** - * Uses MUXs to shift bits of the value to the right. - * @param wires input value - * @param n number of bits to shift - * @return shifted value - */ - std::vector PutBarrelRightShifterGate(std::vector wires, std::vector n); - - /** - * Put floating point gate with one input - * @param in input share - * @param op operation to perform - * @param s setting for operation - * @return result of the operation - */ - share * PutFPGate(share * in, op_t op, uint8_t bitlen = 0, uint32_t nvals = 0, fp_op_setting s = no_status); - - /** - * Put floating point gate with two inputs - * @param in_a input share a - * @param in_b input share b - * @param op operation to perform - * @param s setting for operation - * @return result of the operation - */ - share * PutFPGate(share * in_a, share * in_b, op_t op, uint8_t bitlen = 0, uint32_t nvals = 0, fp_op_setting s = no_status); + /** + * Constructs optimal Hamming Weight Gate. Described by Boyar, Joan, and + * René Peralta in "Tight bounds for the multiplicative complexity of + * symmetric functions." + * @param s_in Input share + * @return Number of 1's in the input bit string + */ + share* PutHammingWeightGate(share* s_in); + + /** + * Constructs optimal Hamming Weight Gate. Described by Boyar, Joan, and + * René Peralta in "Tight bounds for the multiplicative complexity of + * symmetric functions." + * @param s_in Input share + * @param bitlen Bit length of the input + * @return Number of 1's in the input bit string + */ + share* PutHammingWeightGate(share* s_in, uint32_t bitlen); + + /** + * Recursively constructs optimal Hamming Weight Gate. Described by + * Boyar, Joan, and René Peralta in "Tight bounds for the multiplicative + * complexity of symmetric functions." + * @param array Array of wires + * @param bitlen Bit length of the input + * @return Number of 1's in the input bit string + */ + share* PutHammingWeightGateRec(uint32_t * array, uint32_t bitlen); + + /** + * Constructs Full Adder Gate + * @param a Input bit a + * @param b Input bit b + * @param carry_in Input bit carry in + * @return sum of input bits + */ + share* PutFullAdderGate(uint32_t a, uint32_t b, uint32_t carry_in); + + /** + * Constructs Adder Chain Gate + * @param a vector of wires a + * @param b vector of wires b + * @param carry_in optional carry in bit c (zero gate if not needed) + * @return sum of values on wires a and b + */ + share* PutADDChainGate(std::vector a, std::vector b, uint32_t carry_in); + + + /** + * Converts unsigned integer input to floating point number of double precision + * @param input unsigned integer input + * @return floating point number of double precision + */ + share* PutUint2DoubleGate(share* input); + + /** + * Converts a number "value" from the type "from" to the type "to" + * @param value input value + * @param from type of the value + * @param to type to which value will be converted + * @return converted value + */ + share* PutConvTypeGate(share* value, ConvType* from, ConvType* to, uint32_t nvals = 1); + + /** + * Converts a number "value" from the type "from" to the type "to" + * @param wires wires of the input value + * @param from type of the value + * @param to type to which value will be converted + * @return wires of the converted value + */ + std::vector PutConvTypeGate(std::vector wires, ConvType* from, ConvType* to, uint32_t nvals = 1); + + /** + * Converts unsigned integer to floating point number + * @param wires wires of the input value + * @param from type of the value + * @param to type to which value will be converted + * @return wires of the converted value + */ + std::vector PutUint2FpGate(std::vector wires, UINTType* from, FPType* to, uint32_t nvals = 1); + + /** + * Converts floating point to unsigned integer number + * @param wires wires of the input value + * @param from type of the value + * @param to type to which value will be converted + * @return wires of the converted value + */ + //TODO implement + //std::vector PutFp2UintGate(std::vector wires, FPType* from, UINTType* to); + + /** + * Computes Prefix Or operation, thus, zeros before first seen 1 and 1s after (e.g. 0010100 => 0011111). + * @param input input value + * @return return value of prefix or + */ + share * PutPreOrGate(share * input); + + /** + * Computes Prefix Or operation, thus, zeros before first seen 1 and 1s after (e.g. 0010100 => 0011111). + * @param wires input value + * @return value of prefix or + */ + std::vector PutPreOrGate(std::vector wires); + + /** + * Uses MUXs to shift bits of the value to the left. + * @param input input value + * @param n number of bits to shift + * @return shifted value + */ + share * PutBarrelLeftShifterGate(share * input, share * n); + /** + * Uses MUXs to shift bits of the value to the left. + * @param wires input value + * @param n number of bits to shift + * @return shifted value + */ + std::vector PutBarrelLeftShifterGate(std::vector wires, std::vector n, uint32_t nvals = 1); + /** + * Uses MUXs to shift bits of the value to the right. + * @param input input value + * @param n number of bits to shift + * @return shifted value + */ + share * PutBarrelRightShifterGate(share * input, share * n); + /** + * Uses MUXs to shift bits of the value to the right. + * @param wires input value + * @param n number of bits to shift + * @return shifted value + */ + std::vector PutBarrelRightShifterGate(std::vector wires, std::vector n); + + /** + * Put floating point gate with one input + * @param in input share + * @param op operation to perform + * @param s setting for operation + * @return result of the operation + */ + share * PutFPGate(share * in, op_t op, uint8_t bitlen = 0, uint32_t nvals = 0, fp_op_setting s = no_status); + + /** + * Put floating point gate with two inputs + * @param in_a input share a + * @param in_b input share b + * @param op operation to perform + * @param s setting for operation + * @return result of the operation + */ + share * PutFPGate(share * in_a, share * in_b, op_t op, uint8_t bitlen = 0, uint32_t nvals = 0, fp_op_setting s = no_status); private: /** @@ -692,7 +692,8 @@ class BooleanCircuit: public Circuit { memset(tmpval, 0, tmpval_bytes); for (uint32_t j = 0; j < nvals; j++) { //tmpval[j / typebitlen] += ((val[j] >> (i % typebitlen) & 0x01) << j); - tmpval[j /typebitlen] += (((val[j * typebyteiters + i/typebitlen] >> (i % typebitlen)) & 0x01) << (j%typebitlen)); + tmpval[j / typebitlen] += + (((val[j * typebyteiters + i / typebitlen] >> (i % typebitlen)) & 0x01) << (j % typebitlen)); } shr->set_wire_id(i, PutSIMDINGate(nvals, tmpval, role)); } @@ -712,7 +713,8 @@ class BooleanCircuit: public Circuit { memset(tmpval, 0, tmpval_bytes); for (uint32_t j = 0; j < nvals; j++) { //tmpval[j / typebitlen] += ((val[j] >> (i % typebitlen) & 0x01) << j); - tmpval[j /typebitlen] += (((val[j * typebyteiters + i/typebitlen] >> (i % typebitlen)) & 0x01) << (j%typebitlen)); + tmpval[j / typebitlen] += + (((val[j * typebyteiters + i / typebitlen] >> (i % typebitlen)) & 0x01) << (j % typebitlen)); } shr->set_wire_id(i, PutSharedSIMDINGate(nvals, tmpval)); } diff --git a/src/abycore/circuit/circuit.cpp b/src/abycore/circuit/circuit.cpp index 242a192f..0228c44e 100644 --- a/src/abycore/circuit/circuit.cpp +++ b/src/abycore/circuit/circuit.cpp @@ -2,17 +2,17 @@ \file circuit.cpp \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Circuit class implementation. */ @@ -22,9 +22,6 @@ void Circuit::Init() { - - m_pGates = m_cCircuit->Gates(); - m_nMaxDepth = 0; m_vInputGates.resize(2); m_vOutputGates.resize(2); @@ -61,24 +58,24 @@ void Circuit::Reset() { m_nMaxDepth = 0; m_nGates = 0; - for (int i = 0; i < m_vLocalQueueOnLvl.size(); i++) { + for (size_t i = 0; i < m_vLocalQueueOnLvl.size(); i++) { m_vLocalQueueOnLvl[i].clear(); } m_vLocalQueueOnLvl.resize(0); - for (int i = 0; i < m_vInteractiveQueueOnLvl.size(); i++) { + for (size_t i = 0; i < m_vInteractiveQueueOnLvl.size(); i++) { m_vInteractiveQueueOnLvl[i].clear(); } m_vInteractiveQueueOnLvl.resize(0); - for (int i = 0; i < m_vInputGates.size(); i++) { + for (size_t i = 0; i < m_vInputGates.size(); i++) { m_vInputGates[i].clear(); } - for (int i = 0; i < m_vOutputGates.size(); i++) { + for (size_t i = 0; i < m_vOutputGates.size(); i++) { m_vOutputGates[i].clear(); } - for (int i = 0; i < m_vInputBits.size(); i++) + for (size_t i = 0; i < m_vInputBits.size(); i++) m_vInputBits[i] = 0; - for (int i = 0; i < m_vOutputBits.size(); i++) + for (size_t i = 0; i < m_vOutputBits.size(); i++) m_vOutputBits[i] = 0; // reset number of SIMD gates @@ -94,19 +91,27 @@ void Circuit::Reset() { } gate_specific Circuit::GetGateSpecificOutput(uint32_t gateid) { - assert(m_pGates[gateid].instantiated); - return m_pGates[gateid].gs; + assert(m_vGates[gateid].instantiated); + return m_vGates[gateid].gs; } uint32_t Circuit::GetOutputGateValue(uint32_t gateid, UGATE_T*& outval) { - assert(m_pGates[gateid].instantiated); - outval = m_pGates[gateid].gs.val; - return m_pGates[gateid].nvals; + //assert(m_vGates[gateid].instantiated); + if(!m_vGates[gateid].instantiated){ + std::cerr << "Output not allowed for this role. Returned value will be wrong!" << std::endl; + return 0; + } + outval = m_vGates[gateid].gs.val; + return m_vGates[gateid].nvals; } UGATE_T* Circuit::GetOutputGateValue(uint32_t gateid) { - assert(m_pGates[gateid].instantiated); - return m_pGates[gateid].gs.val; + //assert(m_vGates[gateid].instantiated); + if(!m_vGates[gateid].instantiated){ + std::cerr << "Output not allowed for this role! Returned value will be wrong!" << std::endl; + return nullptr; + } + return m_vGates[gateid].gs.val; } /* Converts a Yao share to an Arithmetic share. The boolsharing circuit needs to be from type S_BOOL! */ @@ -210,8 +215,8 @@ share* Circuit::PutCombinerGate(share* input) { share* Circuit::PutCombinerGate(share* ina, share* inb) { assert(ina->get_circuit_type() == inb->get_circuit_type()); std::vector wires(ina->get_bitlength() + inb->get_bitlength()); -// std::cout << "Size on left = " << ina->get_bitlength() << " (" << m_pGates[ina->get_wire_id(0)].nvals << ") on right = " << inb->get_bitlength() -// << " ("<< m_pGates[inb->get_wire_id(0)].nvals << ")" << std::endl; +// std::cout << "Size on left = " << ina->get_bitlength() << " (" << m_vGates[ina->get_wire_id(0)].nvals << ") on right = " << inb->get_bitlength() +// << " ("<< m_vGates[inb->get_wire_id(0)].nvals << ")" << std::endl; for(uint32_t i = 0; i < ina->get_bitlength(); i++) { wires[i] = ina->get_wire_id(i); @@ -266,7 +271,7 @@ void Circuit::UpdateLocalQueue(share* gateids) { share* Circuit::EnsureOutputGate(share* in) { bool is_output = true; for (uint32_t i = 0; i < in->get_bitlength(); i++) { - is_output &= (m_pGates[in->get_wire_id(i)].type == G_OUT); + is_output &= (m_vGates[in->get_wire_id(i)].type == G_OUT); } share* outgates = in; @@ -329,7 +334,7 @@ share* Circuit::PutSIMDAssertGate(share* in, uint32_t nvals, uint64_t* assert_va assert(bitlen == in->get_bitlength()); for (uint32_t i = 0; i < in->get_bitlength(); i++) { - assert(m_pGates[in->get_wire_id(i)].nvals == nvals); + assert(m_vGates[in->get_wire_id(i)].nvals == nvals); } uint32_t tmp = m_cCircuit->PutAssertGate(outgates->get_wires(), bitlen, (UGATE_T*) assert_val); diff --git a/src/abycore/circuit/circuit.h b/src/abycore/circuit/circuit.h index c45ec018..01d67af3 100644 --- a/src/abycore/circuit/circuit.h +++ b/src/abycore/circuit/circuit.h @@ -2,17 +2,17 @@ \file circuit.h \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Contains the class for generic circuits, which is a super-class of Boolean and Arithmetic circuits. */ @@ -45,7 +45,7 @@ struct non_lin_on_layers { */ template T binary_accumulate(std::vector vals, - std::function& op) { + std::function& op) { for(size_t j, n{vals.size()}; n > 1; n = j) { j = 0; for(size_t i{0}; i < n; ++j) { @@ -74,7 +74,8 @@ class Circuit { public: Circuit(ABYCircuit* aby, e_sharing context, e_role myrole, uint32_t bitlen, e_circuit circ) : - m_cCircuit(aby), m_eContext(context), m_eMyRole(myrole), m_nShareBitLen(bitlen), m_eCirctype(circ) { + m_cCircuit(aby), m_eContext(context), m_eMyRole(myrole), + m_nShareBitLen(bitlen), m_eCirctype(circ), m_vGates(aby->GatesVec()) { Init(); } @@ -114,7 +115,7 @@ class Circuit { \param lvl Required level of local queue. \return Local queue on the required level */ - std::deque GetLocalQueueOnLvl(uint32_t lvl) { + std::deque GetLocalQueueOnLvl(uint32_t lvl) { if (lvl < m_vLocalQueueOnLvl.size()) return m_vLocalQueueOnLvl[lvl]; @@ -127,19 +128,19 @@ class Circuit { \param lvl Required level of interactive queue. \return Interactive queue on the required level */ - std::deque GetInteractiveQueueOnLvl(uint32_t lvl) { + std::deque GetInteractiveQueueOnLvl(uint32_t lvl) { if (lvl < m_vInteractiveQueueOnLvl.size()) { return m_vInteractiveQueueOnLvl[lvl]; - } else { + } else { return EMPTYQUEUE; - } + } } /* * print the number of interactive operations for each layer */ void PrintInteractiveQueues(){ - std::vector sharingnames {"GMW", "Yao", "Arith", "Yao_Rev", "SPLUT"}; + std::vector sharingnames {"GMW", "Yao", "Arith", "Yao_Rev", "SPLUT"}; std::cout << "Interactive Queue Sizes " << sharingnames[this->m_eContext] << std::endl; @@ -196,7 +197,7 @@ class Circuit { \param party Party role based on which the Output gates are returned. \return Output gates for the provided party */ - std::deque GetOutputGatesForParty(e_role party) { + std::deque GetOutputGatesForParty(e_role party) { return m_vOutputGates[party]; } @@ -218,13 +219,13 @@ class Circuit { UGATE_T* GetOutputGateValue(uint32_t gateid); uint32_t GetOutputGateValue(uint32_t gateid, UGATE_T*& outval); template void GetOutputGateValueT(uint32_t gateid, T& val) { - assert(sizeof(T) * 8 >= m_pGates[gateid].nvals * m_nShareBitLen); - val = *((T*) m_pGates[gateid].gs.val); + assert(sizeof(T) * 8 >= m_vGates[gateid].nvals * m_nShareBitLen); + val = *((T*) m_vGates[gateid].gs.val); } uint32_t GetNumVals(uint32_t gateid) { assert(gateid < m_cCircuit->GetGateHead()); - return m_pGates[gateid].nvals; + return m_vGates[gateid].nvals; } /* Common gate-building routines */ @@ -415,32 +416,32 @@ class Circuit { std::vector PutSplitterGate(uint32_t input, const std::vector& new_nvals); //Templates may not be virtual, hence use dummy functions - template uint32_t PutINGate(T val) { - std::cout << "IN gate not implemented in super-class, stopping!" << std::endl; + template uint32_t PutINGate([[maybe_unused]] T val) { + std::cout << "IN gate not implemented in super-class, stopping!" << std::endl; return -1; } - template uint32_t PutINGate(T val, e_role role) { + template uint32_t PutINGate([[maybe_unused]] T val, [[maybe_unused]] e_role role) { std::cout << "IN gate not implemented in super-class, stopping!" << std::endl; return -1; } - template uint32_t PutSharedINGate(T val) { + template uint32_t PutSharedINGate([[maybe_unused]] T val) { std::cout << "IN gate not implemented in super-class, stopping!" << std::endl; return -1; } - template uint32_t PutSIMDINGate(uint32_t nvals, T val) { + template uint32_t PutSIMDINGate([[maybe_unused]]uint32_t nvals, [[maybe_unused]] T val) { std::cout << "IN gate not implemented in super-class, stopping!" << std::endl; return -1; } - template uint32_t PutSIMDINGate(uint32_t nvals, T val, e_role role) { + template uint32_t PutSIMDINGate([[maybe_unused]] uint32_t nvals, [[maybe_unused]] T val, [[maybe_unused]] e_role role) { std::cout << "IN gate not implemented in super-class, stopping!" << std::endl; return -1; } - template uint32_t PutSharedSIMDINGate(uint32_t nvals, T val) { + template uint32_t PutSharedSIMDINGate([[maybe_unused]]uint32_t nvals, [[maybe_unused]] T val) { std::cout << "IN gate not implemented in super-class, stopping!" << std::endl; return -1; } @@ -495,12 +496,13 @@ class Circuit { share* EnsureOutputGate(share* in); ABYCircuit* m_cCircuit; /** ABYCircuit Object */ - GATE* m_pGates; /** Gates vector which stores the */ + e_sharing m_eContext; e_role m_eMyRole; uint32_t m_nShareBitLen; e_circuit m_eCirctype; uint32_t m_nMaxDepth; + std::vector& m_vGates; std::vector > m_vLocalQueueOnLvl; //for locally evaluatable gates, first dimension is the level of the gates, second dimension presents the queue on which the gateids are put std::vector > m_vInteractiveQueueOnLvl; //for gates that need interaction, first dimension is the level of the gates, second dimension presents the queue on which the gateids are put diff --git a/src/abycore/circuit/share.cpp b/src/abycore/circuit/share.cpp index 2c71e409..ae65defb 100644 --- a/src/abycore/circuit/share.cpp +++ b/src/abycore/circuit/share.cpp @@ -2,17 +2,17 @@ \file share.cpp \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Share class implementation. */ @@ -118,76 +118,82 @@ uint8_t* boolshare::get_clear_value_ptr() { uint32_t nvals = m_ccirc->GetNumVals(m_ngateids[0]); uint32_t bytelen = ceil_divide(m_ngateids.size(), 8); - out = (uint8_t*) calloc(ceil_divide(m_ngateids.size(), 8) * nvals, sizeof(uint8_t)); + out = (uint8_t*)calloc(ceil_divide(m_ngateids.size(), 8) * nvals, sizeof(uint8_t)); for (uint32_t i = 0, ibytes; i < m_ngateids.size(); i++) { assert(nvals == m_ccirc->GetNumVals(m_ngateids[i])); gatevals = m_ccirc->GetOutputGateValue(m_ngateids[i]); - ibytes = i / 8; - for (uint32_t j = 0; j < nvals; j++) { - out[j * bytelen + ibytes] += (((gatevals[j / 64] >> (j % 64)) & 0x01) << (i & 0x07)); + // only write sth if there are values (output might not be for this party) + if (gatevals != nullptr) { + ibytes = i / 8; + for (uint32_t j = 0; j < nvals; j++) { + out[j * bytelen + ibytes] += (((gatevals[j / 64] >> (j % 64)) & 0x01) << (i & 0x07)); + } } } return out; } - //TODO This method will only work up to a bitlength of 32 -void boolshare::get_clear_value_vec(uint32_t** vec, uint32_t *bitlen, uint32_t *nvals) { +void boolshare::get_clear_value_vec(uint32_t** vec, uint32_t* bitlen, uint32_t* nvals) { assert(m_ngateids.size() <= sizeof(uint32_t) * 8); UGATE_T* outvalptr; - uint32_t gnvals = 1; + uint32_t gnvals; - *nvals = 1; + *nvals = 0; *nvals = m_ccirc->GetOutputGateValue(m_ngateids[0], outvalptr); - *vec = (uint32_t*) calloc(*nvals, sizeof(uint32_t)); - - for (uint32_t j = 0; j < *nvals; j++) { - (*vec)[j] = (outvalptr[j / 64] >> (j % 64)) & 0x01; - } - for (uint32_t i = 1; i < m_ngateids.size(); i++) { - gnvals = m_ccirc->GetOutputGateValue(m_ngateids[i], outvalptr); - assert(*nvals == gnvals); + // only continue if there are values (output might not be for this party) + if (*nvals > 0) { + *vec = (uint32_t*)calloc(*nvals, sizeof(uint32_t)); for (uint32_t j = 0; j < *nvals; j++) { - (*vec)[j] = (*vec)[j] + (((outvalptr[j / 64] >> (j % 64)) & 0x01) << i); + (*vec)[j] = (outvalptr[j / 64] >> (j % 64)) & 0x01; } + + for (uint32_t i = 1; i < m_ngateids.size(); i++) { + gnvals = m_ccirc->GetOutputGateValue(m_ngateids[i], outvalptr); + assert(*nvals == gnvals); //check that all wires have same nvals + + for (uint32_t j = 0; j < *nvals; j++) { + (*vec)[j] = (*vec)[j] + (((outvalptr[j / 64] >> (j % 64)) & 0x01) << i); + } + } + *bitlen = m_ngateids.size(); } - *bitlen = m_ngateids.size(); - //return nvals; } - //TODO: copied from 32 bits. Put template in and test later on! //TODO This method will only work up to a bitlength of 64 -void boolshare::get_clear_value_vec(uint64_t** vec, uint32_t *bitlen, uint32_t *nvals) { +void boolshare::get_clear_value_vec(uint64_t** vec, uint32_t* bitlen, uint32_t* nvals) { assert(m_ngateids.size() <= sizeof(uint64_t) * 8); UGATE_T* outvalptr; - uint32_t gnvals = 1; + uint32_t gnvals; - *nvals = 1; + *nvals = 0; *nvals = m_ccirc->GetOutputGateValue(m_ngateids[0], outvalptr); - *vec = (uint64_t*) calloc(*nvals, sizeof(uint64_t)); - - for (uint32_t j = 0; j < *nvals; j++) { - (*vec)[j] = (outvalptr[j / 64] >> (j % 64)) & 0x01; - } - for (uint32_t i = 1; i < m_ngateids.size(); i++) { - gnvals = m_ccirc->GetOutputGateValue(m_ngateids[i], outvalptr); - assert(*nvals == gnvals); + // only continue if there are values (output might not be for this party) + if (*nvals > 0) { + *vec = (uint64_t*)calloc(*nvals, sizeof(uint64_t)); for (uint32_t j = 0; j < *nvals; j++) { - (*vec)[j] = (*vec)[j] + (((outvalptr[j / 64] >> (j % 64)) & 0x01) << i); + (*vec)[j] = (outvalptr[j / 64] >> (j % 64)) & 0x01; + } + + for (uint32_t i = 1; i < m_ngateids.size(); i++) { + gnvals = m_ccirc->GetOutputGateValue(m_ngateids[i], outvalptr); + assert(*nvals == gnvals); //check that all wires have same nvals + + for (uint32_t j = 0; j < *nvals; j++) { + (*vec)[j] = (*vec)[j] + (((outvalptr[j / 64] >> (j % 64)) & 0x01) << i); + } } + *bitlen = m_ngateids.size(); } - *bitlen = m_ngateids.size(); - //return nvals; } - yao_fields* boolshare::get_internal_yao_keys() { yao_fields* out; uint32_t nvals = m_ccirc->GetNumVals(m_ngateids[0]); @@ -219,11 +225,16 @@ yao_fields* boolshare::get_internal_yao_keys() { uint8_t* arithshare::get_clear_value_ptr() { UGATE_T* gate_val; uint32_t nvals = m_ccirc->GetOutputGateValue(m_ngateids[0], gate_val); - uint8_t* out = (uint8_t*) malloc(nvals * sizeof(uint32_t)); - for (uint32_t i = 0; i < nvals; i++) { - ((uint32_t*) out)[i] = (uint32_t) gate_val[i]; + if (nvals > 0) { + uint8_t* out = (uint8_t*)malloc(nvals * sizeof(uint32_t)); + for (uint32_t i = 0; i < nvals; i++) { + ((uint32_t*)out)[i] = (uint32_t)gate_val[i]; + } + return out; + } + else{ + return nullptr; } - return out; } void arithshare::get_clear_value_vec(uint32_t** vec, uint32_t* bitlen, uint32_t* nvals) { @@ -231,23 +242,27 @@ void arithshare::get_clear_value_vec(uint32_t** vec, uint32_t* bitlen, uint32_t* UGATE_T* gate_val; *nvals = 0; - for(uint32_t i = 0; i < m_ngateids.size(); i++) { - (*nvals) += m_ccirc->GetOutputGateValue(m_ngateids[i], gate_val); - } - uint32_t sharebytes = ceil_divide(m_ccirc->GetShareBitLen(), 8); - //*nvals = m_ccirc->GetOutputGateValue(m_ngateids[0], gate_val); - *vec = (uint32_t*) calloc(*nvals, sizeof(uint32_t)); + // only continue if there are values (output might not be for this party) + if (m_ccirc->GetOutputGateValue(m_ngateids[0], gate_val) > 0) { + for (uint32_t i = 0; i < m_ngateids.size(); i++) { + (*nvals) += m_ccirc->GetOutputGateValue(m_ngateids[i], gate_val); + } + uint32_t sharebytes = ceil_divide(m_ccirc->GetShareBitLen(), 8); + + //*nvals = m_ccirc->GetOutputGateValue(m_ngateids[0], gate_val); + *vec = (uint32_t*)calloc(*nvals, sizeof(uint32_t)); - for(uint32_t i = 0, tmpctr=0, tmpnvals; i < m_ngateids.size(); i++) { - tmpnvals = m_ccirc->GetOutputGateValue(m_ngateids[i], gate_val); - //cout << m_ngateids[i] << " gateval = " << gate_val[0] << ", nvals = " << *nvals << ", sharebitlen = " << m_ccirc->GetShareBitLen() << endl; - for(uint32_t j = 0; j < tmpnvals; j++, tmpctr++) { - memcpy((*vec)+tmpctr, ((uint8_t*) gate_val)+(j*sharebytes), sharebytes); + for (uint32_t i = 0, tmpctr = 0, tmpnvals; i < m_ngateids.size(); i++) { + tmpnvals = m_ccirc->GetOutputGateValue(m_ngateids[i], gate_val); + //cout << m_ngateids[i] << " gateval = " << gate_val[0] << ", nvals = " << *nvals << ", sharebitlen = " << m_ccirc->GetShareBitLen() << endl; + for (uint32_t j = 0; j < tmpnvals; j++, tmpctr++) { + memcpy((*vec) + tmpctr, ((uint8_t*)gate_val) + (j * sharebytes), sharebytes); + } } - } - *bitlen = m_ccirc->GetShareBitLen(); + *bitlen = m_ccirc->GetShareBitLen(); + } } //TODO: copied from 32 bits. Put template in and test later on! @@ -256,23 +271,26 @@ void arithshare::get_clear_value_vec(uint64_t** vec, uint32_t* bitlen, uint32_t* UGATE_T* gate_val; *nvals = 0; - for(uint32_t i = 0; i < m_ngateids.size(); i++) { - (*nvals) += m_ccirc->GetOutputGateValue(m_ngateids[i], gate_val); - } - uint32_t sharebytes = ceil_divide(m_ccirc->GetShareBitLen(), 8); + // only continue if there are values (output might not be for this party) + if (m_ccirc->GetOutputGateValue(m_ngateids[0], gate_val) > 0) { + for (uint32_t i = 0; i < m_ngateids.size(); i++) { + (*nvals) += m_ccirc->GetOutputGateValue(m_ngateids[i], gate_val); + } + uint32_t sharebytes = ceil_divide(m_ccirc->GetShareBitLen(), 8); - //*nvals = m_ccirc->GetOutputGateValue(m_ngateids[0], gate_val); - *vec = (uint64_t*) calloc(*nvals, sizeof(uint64_t)); + //*nvals = m_ccirc->GetOutputGateValue(m_ngateids[0], gate_val); + *vec = (uint64_t*)calloc(*nvals, sizeof(uint64_t)); - for(uint32_t i = 0, tmpctr=0, tmpnvals; i < m_ngateids.size(); i++) { - tmpnvals = m_ccirc->GetOutputGateValue(m_ngateids[i], gate_val); - //cout << m_ngateids[i] << " gateval = " << gate_val[0] << ", nvals = " << *nvals << ", sharebitlen = " << m_ccirc->GetShareBitLen() << endl; - for(uint32_t j = 0; j < tmpnvals; j++, tmpctr++) { - memcpy((*vec)+tmpctr, ((uint8_t*) gate_val)+(j*sharebytes), sharebytes); + for (uint32_t i = 0, tmpctr = 0, tmpnvals; i < m_ngateids.size(); i++) { + tmpnvals = m_ccirc->GetOutputGateValue(m_ngateids[i], gate_val); + //cout << m_ngateids[i] << " gateval = " << gate_val[0] << ", nvals = " << *nvals << ", sharebitlen = " << m_ccirc->GetShareBitLen() << endl; + for (uint32_t j = 0; j < tmpnvals; j++, tmpctr++) { + memcpy((*vec) + tmpctr, ((uint8_t*)gate_val) + (j * sharebytes), sharebytes); + } } - } - *bitlen = m_ccirc->GetShareBitLen(); + *bitlen = m_ccirc->GetShareBitLen(); + } } share* arithshare::get_share_from_wire_id(uint32_t shareid) { @@ -288,7 +306,3 @@ share* boolshare::get_share_from_wire_id(uint32_t shareid) { new_shr->set_wire_id(shareid,get_wire_id(shareid)); return new_shr; } - - - - diff --git a/src/abycore/circuit/share.h b/src/abycore/circuit/share.h index 6c11a7b3..76557334 100644 --- a/src/abycore/circuit/share.h +++ b/src/abycore/circuit/share.h @@ -2,17 +2,17 @@ \file share.h \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Contains the class the share object as well as the sub-classes for Boolean and Aritmetic shares. */ @@ -45,7 +45,7 @@ class share { } ; - std::vector get_wires() { + std::vector & get_wires() { return m_ngateids; } ; diff --git a/src/abycore/cmake/AndroidGMPConfig.cmake.in b/src/abycore/cmake/AndroidGMPConfig.cmake.in deleted file mode 100644 index a30e33a3..00000000 --- a/src/abycore/cmake/AndroidGMPConfig.cmake.in +++ /dev/null @@ -1,4 +0,0 @@ -include(CMakeFindDependencyMacro) -if(ANDROID) - find_dependency(AndroidGMP-${ANDROID_PLATFORM_LEVEL}) -endif() diff --git a/src/abycore/cmake/GMPConfig.cmake.in b/src/abycore/cmake/GMPConfig.cmake.in index 22624f9b..d1ecc1ff 100644 --- a/src/abycore/cmake/GMPConfig.cmake.in +++ b/src/abycore/cmake/GMPConfig.cmake.in @@ -1,24 +1,18 @@ -if(ANDROID AND ANDROID_ARM_NEON) - find_path(GMP_INCLUDE_DIR gmp.h PATHS "${ANDROID_SYSTEM_LIBRARY_PATH}/NEON/include") - #TODO: get version - find_library(GMP_LIBRARY NAMES gmp PATHS "${ANDROID_SYSTEM_LIBRARY_PATH}/NEON/lib") -elseif(ANDROID AND NOT ANDROID_ARM_NEON) - find_path(GMP_INCLUDE_DIR gmp.h PATHS "${ANDROID_SYSTEM_LIBRARY_PATH}/include") - #TODO: get version - find_library(GMP_LIBRARY NAMES gmp PATHS "${ANDROID_SYSTEM_LIBRARY_PATH}/lib") -else() - find_path(GMP_INCLUDE_DIR gmp.h) - # TODO: get version - find_library(GMP_LIBRARY NAMES gmp) +if(NOT "${GMP_LIBRARY_TYPE}" STREQUAL "STATIC" AND NOT "${GMP_LIBRARY_TYPE}" STREQUAL "SHARED") + set(GMP_LIBRARY_TYPE "@GMP_LIBRARY_TYPE@") endif() +set(LIB_PREFIX "${CMAKE_${GMP_LIBRARY_TYPE}_LIBRARY_PREFIX}") +set(LIB_SUFFIX "${CMAKE_${GMP_LIBRARY_TYPE}_LIBRARY_SUFFIX}") -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(GMP - FOUND_VAR GMP_FOUND - REQUIRED_VARS - GMP_LIBRARY - GMP_INCLUDE_DIR -) +find_path(GMP_INCLUDE_DIR gmp.h PATHS "@ANDROID_NDK@/@ABY_INSTALL_INCLUDE@") + +set(GMP_LIBRARY "@ANDROID_NDK@/@ABY_INSTALL_LIB@/${LIB_PREFIX}gmp${LIB_SUFFIX}") +if(EXISTS "${GMP_INCLUDE_DIR}" AND EXISTS "${GMP_LIBRARY}") + set(GMP_FOUND TRUE) +else() + set(GMP_LIBRARY ) + set(GMP_FOUND FALSE) +endif() if(GMP_FOUND AND NOT TARGET GMP::GMP) add_library(GMP::GMP UNKNOWN IMPORTED) @@ -32,3 +26,6 @@ mark_as_advanced( GMP_INCLUDE_DIR GMP_LIBRARY ) + +set(LIBRARIES_FULL_PATH "@ANDROID_NDK@/@ABY_INSTALL_LIB@/${LIB_PREFIX}gmp${LIB_SUFFIX}") +set(LIB_NAME "GMP") diff --git a/src/abycore/cmake/GMPXXConfig.cmake.in b/src/abycore/cmake/GMPXXConfig.cmake.in index 58e3c392..a84a703c 100644 --- a/src/abycore/cmake/GMPXXConfig.cmake.in +++ b/src/abycore/cmake/GMPXXConfig.cmake.in @@ -1,24 +1,18 @@ -if(ANDROID AND ANDROID_ARM_NEON) - find_path(GMPXX_INCLUDE_DIR gmpxx.h PATHS "${ANDROID_SYSTEM_LIBRARY_PATH}/NEON/include") - #TODO: get version - find_library(GMPXX_LIBRARY NAMES gmpxx PATHS "${ANDROID_SYSTEM_LIBRARY_PATH}/NEON/lib") -elseif(ANDROID AND NOT ANDROID_ARM_NEON) - find_path(GMPXX_INCLUDE_DIR gmpxx.h PATHS "${ANDROID_SYSTEM_LIBRARY_PATH}/include") - #TODO: get version - find_library(GMPXX_LIBRARY NAMES gmpxx PATHS "${ANDROID_SYSTEM_LIBRARY_PATH}/lib") -else() - find_path(GMPXX_INCLUDE_DIR gmpxx.h) - # TODO: get version - find_library(GMPXX_LIBRARY NAMES gmpxx) +if(NOT "${GMP_LIBRARY_TYPE}" STREQUAL "STATIC" AND NOT "${GMP_LIBRARY_TYPE}" STREQUAL "SHARED") + set(GMP_LIBRARY_TYPE "@GMP_LIBRARY_TYPE@") endif() +set(LIB_PREFIX "${CMAKE_${GMP_LIBRARY_TYPE}_LIBRARY_PREFIX}") +set(LIB_SUFFIX "${CMAKE_${GMP_LIBRARY_TYPE}_LIBRARY_SUFFIX}") -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(GMPXX - FOUND_VAR GMPXX_FOUND - REQUIRED_VARS - GMPXX_LIBRARY - GMPXX_INCLUDE_DIR -) +find_path(GMPXX_INCLUDE_DIR gmpxx.h PATHS "@ANDROID_NDK@/@ABY_INSTALL_INCLUDE@") + +set(GMPXX_LIBRARY "@ANDROID_NDK@/@ABY_INSTALL_LIB@/${LIB_PREFIX}gmpxx${LIB_SUFFIX}") +if(EXISTS "${GMPXX_INCLUDE_DIR}" AND EXISTS "${GMPXX_LIBRARY}") + set(GMPXX_FOUND TRUE) +else() + set(GMPXX_LIBRARY ) + set(GMPXX_FOUND FALSE) +endif() if(GMPXX_FOUND AND NOT TARGET GMP::GMPXX) add_library(GMP::GMPXX UNKNOWN IMPORTED) @@ -32,3 +26,6 @@ mark_as_advanced( GMPXX_INCLUDE_DIR GMPXX_LIBRARY ) + +set(LIBRARIES_FULL_PATH "@ANDROID_NDK@/@ABY_INSTALL_LIB@/${LIB_PREFIX}gmpxx${LIB_SUFFIX}") +set(LIB_NAME "GMP") diff --git a/src/abycore/cmake/Modules/AddBoost.cmake b/src/abycore/cmake/Modules/AddBoost.cmake index 132672c1..1558096e 100644 --- a/src/abycore/cmake/Modules/AddBoost.cmake +++ b/src/abycore/cmake/Modules/AddBoost.cmake @@ -1,9 +1,23 @@ cmake_minimum_required(VERSION 3.13) -if(ANDROID AND NOT TARGET Boost::boost OR TARGET Boost::filesystem) - message(STATUS "Fetching Boost sources. This might take several minutes. " - "No progress is shown, please wait...") - include(FetchBOOST_CMAKE) -elseif(NOT TARGET Boost::boost) - find_package(Boost VERSION 1.67 REQUIRED) +option(DOWNLOAD_BOOST "Set to download boost libraries. " OFF) +set(BOOST_CMAKE_SOURCE CACHE PATH "Path to boost-cmake source.") +set(BOOST_CMAKE_URL https://github.com/Orphis/boost-cmake/archive/f0f64adda5ac1312549056dab502da55b9c45b7b.zip CACHE STRING "URL to boost-cmake project.") +set(BOOST_CMAKE_URL_HASH SHA256=0be1ccdebe0a4f77dae683273984770937dd5ef4ee1f5a7552bf862e478f81dd CACHE STRING "Hash of boost-cmake archive.") +set(BOOST_SOURCE CACHE PATH "Path to boost source location.") +set(BOOST_URL https://dl.bintray.com/boostorg/release/1.69.0/source/boost_1_69_0.tar.bz2 CACHE STRING "Boost download URL.") +set(BOOST_URL_HASH SHA256=8f32d4617390d1c2d16f26a27ab60d97807b35440d45891fa340fc2648b04406 CACHE STRING "Boost download URL SHA256 checksum.") + +if(NOT TARGET Boost::boost OR NOT TARGET Boost::filesystem) + if(DOWNLOAD_BOOST) + message(STATUS "Fetching Boost sources. This might take several minutes. " + "No progress is shown, please wait...") + include(AddBOOST_CMAKE) + elseif(ANDROID AND NOT DOWNLOAD_BOOST AND EXISTS BOOST_SOURCE) + include(AddBOOST_CMAKE) + elseif(ANDROID) + message(FATAL_ERROR "Please provide a valid directory for BOOST_SOURCE (recommended) or automatically download boost libraries by setting DOWNLOAD_BOOST.") + else() + find_package(Boost 1.67 REQUIRED COMPONENTS filesystem) + endif() endif() diff --git a/cmake/Modules/AddENCRYPTO_utils.cmake b/src/abycore/cmake/Modules/AddENCRYPTO_utils.cmake similarity index 89% rename from cmake/Modules/AddENCRYPTO_utils.cmake rename to src/abycore/cmake/Modules/AddENCRYPTO_utils.cmake index c699eaf8..2ed38161 100644 --- a/cmake/Modules/AddENCRYPTO_utils.cmake +++ b/src/abycore/cmake/Modules/AddENCRYPTO_utils.cmake @@ -4,7 +4,9 @@ find_package(ENCRYPTO_utils QUIET) if(ENCRYPTO_utils_FOUND) message(STATUS "Found ENCRYPTO_utils.") elseif(NOT ENCRYPTO_utils_FOUND AND NOT TARGET ENCRYPTO_utils::encrypto_utils) - set(ENCRYPTO_utils_LIBRARY_TYPE ${ENCRYPTO_utils_LIBRARY_TYPE}) + if(NOT ENCRYPTO_utils_LIBRARY_TYPE) + set(ENCRYPTO_utils_LIBRARY_TYPE ${ABY_LIBRARY_TYPE}) + endif() file(GLOB ENCRYPTO_utils_FILE_LIST "${PROJECT_SOURCE_DIR}/extern/ENCRYPTO_utils/*") list(LENGTH ENCRYPTO_utils_FILE_LIST ENCRYPTO_utils_NUM_FILES) #if ENCRYPTO_utils directory is empty diff --git a/src/abycore/cmake/Modules/AddGMP.cmake b/src/abycore/cmake/Modules/AddGMP.cmake index f47319d6..3e549154 100644 --- a/src/abycore/cmake/Modules/AddGMP.cmake +++ b/src/abycore/cmake/Modules/AddGMP.cmake @@ -1,9 +1,27 @@ cmake_minimum_required(VERSION 3.13) -option(FORCE_GMP_COMPILATION "Force compilation of GMP, even if GMP is found." OFF) -mark_as_advanced(FORCE_GMP_COMPILATION) +option(BUILD_GMP "Compile GMP library if none is found." OFF) +option(FORCE_GMP_BUILD "Force Build of GMP library (use if installed GMP library is incompatible with build)." OFF) +set(GMP_LIB_DIR "" CACHE PATH "Path to GMP library.") +set(GMP_INCLUDE_DIR "" CACHE PATH "Path to GMP include directories.") +set(GMP_SOURCE CACHE PATH "Path to GMP source (If building GMP).") +set(GMP_URL https://gmplib.org/download/gmp/gmp-6.1.2.tar.lz CACHE STRING "URL of GMP source.") +set(GMP_URL_HASH SHA256=12fed0532d440d2dc902e64f016aa89a33af6044b90bd1f7bca7396635105dbb CACHE STRING "Hash of GMP source archive.") +set(GMP_LIBRARY_TYPE "${GMP_LIBRARY_TYPE}" CACHE STRING "[SHARED | STATIC]: Type of GMP library linked to project.") +set_property(CACHE GMP_LIBRARY_TYPE PROPERTY STRINGS STATIC SHARED) -if(NOT FORCE_GMP_COMPILATION) +mark_as_advanced(FORCE_GMP_BUILD GMP_LIBRARY_TYPE) + +if(NOT ANDROID AND GMP_LIBRARY_TYPE STREQUAL "") + set(GMP_LIBRARY_TYPE "${ABY_LIBRARY_TYPE}") +elseif(ANDROID AND NOT GMP_LIBRARY_TYPE STREQUAL "" AND NOT GMP_LIBRARY_TYPE STREQUAL "SHARED") + set(GMP_LIBRARY_TYPE "SHARED") + message(STATUS "Only shared GMP builds supported for Android.") +elseif(ANDROID) + set(GMP_LIBRARY_TYPE "SHARED") +endif() + +if(NOT FORCE_GMP_BUILD) find_package(GMP QUIET) find_package(GMPXX QUIET) if(TARGET GMP::GMP) @@ -15,38 +33,38 @@ if(NOT FORCE_GMP_COMPILATION) if(GMP_FOUND AND GMPXX_FOUND) message(STATUS "Found GMP and GMPXX.") endif() - if(NOT GMP_FOUND AND GMPXX_FOUND) - message(SEND_ERROR - "GMPXX without GMP found. " - "GMPXX requires GMP. " - "Either set FORCE_GMP_COMPILATION " - "or provide a path to prebuilt GMP library") - endif() - if(GMP_FOUND AND NOT GMPXX_FOUND) - message(SEND_ERROR - "GMP without GMPXX found. " - "ABY requires GMPXX. " - "Either set FORCE_GMP_COMPILATION " - "or provide a path to prebuilt GMPXX library") - endif() endif() -if(FORCE_GMP_COMPILATION OR (NOT GMP_FOUND AND NOT GMPXX_FOUND)) - message(STATUS "Adding GMP and GMPXX library to build.") - set(GMP_ONLY OFF) - if(ANDROID) - set(GMP_LIBRARY_TYPE SHARED) - else(ANDROID) - set(GMP_LIBRARY_TYPE ${ABY_LIBRARY_TYPE}) - endif(ANDROID) - include(BuildGMP) +if(NOT GMP_FOUND OR NOT GMPXX_FOUND) + set(GMP_LIBRARY_NAME ${CMAKE_${GMP_LIBRARY_TYPE}_LIBRARY_PREFIX}gmp${CMAKE_${GMP_LIBRARY_TYPE}_LIBRARY_SUFFIX}) + set(GMPXX_LIBRARY_NAME ${CMAKE_${GMP_LIBRARY_TYPE}_LIBRARY_PREFIX}gmpxx${CMAKE_${GMP_LIBRARY_TYPE}_LIBRARY_SUFFIX}) + if(BUILD_GMP OR FORCE_GMP_BUILD) + message(STATUS "Adding GMP and GMPXX library to build.") + set(GMP_ONLY OFF) + include(BuildGMP) + elseif(NOT EXISTS "${GMP_LIB_DIR}/${GMP_LIBRARY_NAME}" OR + NOT EXISTS "${GMP_LIB_DIR}/${GMPXX_LIBRARY_NAME}" OR + NOT EXISTS "${GMP_INCLUDE_DIR}/gmp.h" OR + NOT EXISTS "${GMP_INCLUDE_DIR}/gmpxx.h") + message(FATAL_ERROR " Did not find gmp in standard location." + " Either set GMP_LIB_DIR and GMP_INCLUDE_DIR to valid locations" + " or enable GMP build by setting BUILD_GMP. ") + endif() include(InstallConfig) install_config(IGNORED "GMP" "${ABY_INSTALL_CONFIG}") install_config(IGNORED "GMPXX" "${ABY_INSTALL_CONFIG}") - install(DIRECTORY - "${GMP_LIB_DIR}" - DESTINATION "${ABY_INSTALL_PREFIX}" - ) + if(ANDROID) + install(DIRECTORY + "${GMP_LIB_DIR}" + DESTINATION "${ABY_INSTALL_PREFIX}" + FILES_MATCHING PATTERN "*${CMAKE_${GMP_LIBRARY_TYPE}_LIBRARY_SUFFIX}" + ) + else() + install(DIRECTORY + "${GMP_LIB_DIR}" + DESTINATION "${ABY_INSTALL_PREFIX}" + ) + endif() install(DIRECTORY "${GMP_INCLUDE_DIR}" DESTINATION "${ABY_INSTALL_PREFIX}" diff --git a/src/abycore/cmake/Modules/AddOTExtension.cmake b/src/abycore/cmake/Modules/AddOTExtension.cmake index 289b3817..5d591750 100644 --- a/src/abycore/cmake/Modules/AddOTExtension.cmake +++ b/src/abycore/cmake/Modules/AddOTExtension.cmake @@ -4,7 +4,9 @@ find_package(OTExtension QUIET) if(OTExtension_FOUND) message(STATUS "Found OTExtension.") elseif(NOT OTExtension_FOUND AND NOT TARGET OTExtension::otextension) - set(OTExtension_LIBRARY_TYPE ${ENCRYPTO_utils_LIBRARY_TYPE}) + if(NOT OTExtension_LIBRARY_TYPE) + set(OTExtension_LIBRARY_TYPE ${ABY_LIBRARY_TYPE}) + endif() file(GLOB OTExtension_FILE_LIST "${PROJECT_SOURCE_DIR}/extern/OTExtension/*") list(LENGTH OTExtension_FILE_LIST OTExtension_NUM_FILES) #if OTExtension directory is empty diff --git a/src/abycore/cmake/Modules/BOOST_CMAKEPatches/libs/header.cmake b/src/abycore/cmake/Modules/BOOST_CMAKEPatches/libs/header.cmake new file mode 100644 index 00000000..9a4b8c10 --- /dev/null +++ b/src/abycore/cmake/Modules/BOOST_CMAKEPatches/libs/header.cmake @@ -0,0 +1,9 @@ +# Define the header-only Boost target +add_library(Boost::boost INTERFACE IMPORTED GLOBAL) +target_include_directories(Boost::boost SYSTEM INTERFACE + $ + $ +) + +# Disable autolink +target_compile_definitions(Boost::boost INTERFACE BOOST_ALL_NO_LIB=1) diff --git a/src/abycore/cmake/Modules/BuildGMP.cmake b/src/abycore/cmake/Modules/BuildGMP.cmake index b14fa841..1add560d 100644 --- a/src/abycore/cmake/Modules/BuildGMP.cmake +++ b/src/abycore/cmake/Modules/BuildGMP.cmake @@ -1,36 +1,5 @@ cmake_minimum_required(VERSION 3.13) -option(GMP_ONLY "Set to build only for GMP. GMPXX will not be built" OFF) -set(GMP_SOURCE - CACHE PATH - "Path to a location where the GMP source resides, which will be built." -) -set(GMP_URL https://gmplib.org/download/gmp/gmp-6.1.2.tar.lz - CACHE STRING - [=["URL where an archive of the GMP source can be downloaded." - "If a non-empty URL is provided, then GMP_URL_HASH needs to be provided."]=] -) -set(GMP_URL_HASH SHA256=12fed0532d440d2dc902e64f016aa89a33af6044b90bd1f7bca7396635105dbb - CACHE STRING - [=["Checksum of the downloaded GMP archive of the form =, " - "with being any hashing algorithm supporting the file() command."]=] -) -set(GMP_LIBRARY_TYPE - CACHE STRING - [=["[SHARED | STATIC]: The type of library that GMP should build in any case. " - "Set to SHARED on default. " - "Other types of the GMP library might also be built. "]=] -) -set_property(CACHE GMP_LIBRARY_TYPE PROPERTY STRINGS STATIC SHARED) -mark_as_advanced(GMP_LIBRARY_TYPE) -if("${GMP_LIBRARY_TYPE}" STREQUAL "") - set(GMP_LIBRARY_TYPE "SHARED") -elseif(NOT "${GMP_LIBRARY_TYPE}" STREQUAL "STATIC" AND NOT "${GMP_LIBRARY_TYPE}" STREQUAL "SHARED") - message(WARNING - "Unrecognized option for GMP_LIBRARY_TYPE. " - "Overriding value: ${GMP_LIBRARY_TYPE} with default value SHARED." - ) - set(GMP_LIBRARY_TYPE "SHARED") -endif() + if(NOT ${GMP_SOURCE} STREQUAL "") set(GMP_LOCATION ${GMP_SOURCE}) set(GMP_URL_HASH_COMMAND) @@ -39,9 +8,15 @@ else() set(GMP_URL_HASH_COMMAND URL_HASH ${GMP_URL_HASH}) endif() -if(ANDROID) - include(NDKMakeStandaloneBuild) -endif(ANDROID) +if("${ANDROID_ABI}" STREQUAL "armeabi-v7a" OR "${ANDROID_ABI}" STREQUAL "armeabi-v7a with NEON") + set(GMP_COMPILER_PREFIX "${ANDROID_TOOLCHAIN_ROOT}/bin/armv7a-linux-androideabi${ANDROID_PLATFORM_LEVEL}-") +elseif("${ANDROID_ABI}" STREQUAL "arm64-v8a") + set(GMP_COMPILER_PREFIX "${ANDROID_TOOLCHAIN_ROOT}/bin/aarch64-linux-android${ANDROID_PLATFORM_LEVEL}-") +elseif("${ANDROID_ABI}" STREQUAL "x86") + set(GMP_COMPILER_PREFIX "${ANDROID_TOOLCHAIN_ROOT}/bin/i686-linux-android${ANDROID_PLATFORM_LEVEL}-") +elseif("${ANDROID_ABI}" STREQUAL "x86_64") + set(GMP_COMPILER_PREFIX "${ANDROID_TOOLCHAIN_ROOT}/bin/x86_64-linux-android${ANDROID_PLATFORM_LEVEL}-") +endif() if(NOT "${DEPENDENCY_DIR}" STREQUAL "") set(GMP_DOWNLOAD_DIR_COMMAND DOWNLOAD_DIR ${DEPENDENCY_DIR}) @@ -54,33 +29,27 @@ set(GMP_C_FLAGS ${CMAKE_C_FLAGS}) set(GMP_CXX_FLAGS ${CMAKE_CXX_FLAGS}) string(TOLOWER "${GMP_LIBRARY_TYPE}" GMP_LIBRARY_TYPE_LOWER) -macro(add_gmp_suppress_warnings_flags flags) +macro(add_gmp_flags flags) string(APPEND ${flags} " -Wno-unused-command-line-argument") string(APPEND ${flags} " -Wno-unused-value") string(APPEND ${flags} " -Wno-shift-op-parentheses") -endmacro(add_gmp_suppress_warnings_flags) + string(APPEND ${flags} " -fPIC") +endmacro(add_gmp_flags) -add_gmp_suppress_warnings_flags(GMP_C_FLAGS) +add_gmp_flags(GMP_C_FLAGS) if(NOT GMP_ONLY) - add_gmp_suppress_warnings_flags(GMP_CXX_FLAGS) + add_gmp_flags(GMP_CXX_FLAGS) endif() - if(ANDROID) set(GMP_ENVIRONMENT_VARIABLES - "CC=${ANDROID_HEADER_TRIPLE}-clang" - "AR=${ANDROID_HEADER_TRIPLE}-ar" - "AS=${ANDROID_HEADER_TRIPLE}-as" - "LD=${ANDROID_HEADER_TRIPLE}-ld" - "STRIP=${ANDROID_HEADER_TRIPLE}-strip" - "RANDLIB=${ANDROID_HEADER_TRIPLE}-ranlib" - "PATH=$ENV{PATH}:${NDK_STANDALONE_TOOLCHAIN_PATH}/bin" + "CC=${GMP_COMPILER_PREFIX}clang" "CFLAGS=${GMP_C_FLAGS}" "LDFLAGS=${CMAKE_SHARED_LINKER_FLAGS}" ) if(NOT GMP_ONLY) set(GMP_ENVIRONMENT_VARIABLES ${GMP_ENVIRONMENT_VARIABLES} - "CXX=${ANDROID_HEADER_TRIPLE}-clang++" + "CXX=${GMP_COMPILER_PREFIX}clang++" "CXXFLAGS=${GMP_CXX_FLAGS}" ) endif() @@ -114,7 +83,6 @@ if(NOT GMP_ONLY) endif() if(ANDROID) set(GMP_CONFIGURE_COMMAND - ${NDK_MAKE_STANDALONE_TOOLCHAIN_COMMAND} && /configure ${GMP_CONFIGURE_FLAGS} ) else() diff --git a/src/abycore/cmake/Modules/FetchBOOST_CMAKE.cmake b/src/abycore/cmake/Modules/FetchBOOST_CMAKE.cmake index bde2c98c..de791884 100644 --- a/src/abycore/cmake/Modules/FetchBOOST_CMAKE.cmake +++ b/src/abycore/cmake/Modules/FetchBOOST_CMAKE.cmake @@ -1,34 +1,6 @@ cmake_minimum_required(VERSION 3.13) include(FetchContent) -set(BOOST_CMAKE_SOURCE - CACHE PATH - "Path to boost-cmake source." -) -set(BOOST_CMAKE_URL - https://github.com/Orphis/boost-cmake/archive/f0f64adda5ac1312549056dab502da55b9c45b7b.zip - CACHE STRING - "URL to boost-cmake project." -) -set(BOOST_CMAKE_URL_HASH - SHA256=0be1ccdebe0a4f77dae683273984770937dd5ef4ee1f5a7552bf862e478f81dd - CACHE STRING - "Hash of boost-cmake archive." -) -set(BOOST_SOURCE - CACHE PATH - "Path to boost source location." -) -set(BOOST_URL - https://dl.bintray.com/boostorg/release/1.69.0/source/boost_1_69_0.tar.bz2 - CACHE STRING - "Boost download URL." -) -set(BOOST_URL_HASH - SHA256=8f32d4617390d1c2d16f26a27ab60d97807b35440d45891fa340fc2648b04406 - CACHE STRING - "Boost download URL SHA256 checksum." -) if(NOT "${BOOST_SOURCE}" STREQUAL "") set(FETCHCONTENT_SOURCE_DIR_BOOST "${BOOST_SOURCE}") elseif(NOT "${DEPENDENCY_DIR}" STREQUAL "") @@ -47,4 +19,4 @@ else() endif() include(FetchHelper) -fetch_helper(BOOST_CMAKE) +fetch_helper(BOOST_CMAKE true) diff --git a/cmake/Modules/FetchENCRYPTO_utils.cmake b/src/abycore/cmake/Modules/FetchENCRYPTO_utils.cmake similarity index 64% rename from cmake/Modules/FetchENCRYPTO_utils.cmake rename to src/abycore/cmake/Modules/FetchENCRYPTO_utils.cmake index 52acd407..0c9c36e9 100644 --- a/cmake/Modules/FetchENCRYPTO_utils.cmake +++ b/src/abycore/cmake/Modules/FetchENCRYPTO_utils.cmake @@ -5,12 +5,12 @@ set(ENCRYPTO_utils_SOURCE "Path to ENCRYPTO_utils source." ) set(ENCRYPTO_utils_URL - https://github.com/oliver-schick/ENCRYPTO_utils/archive/bb17c63b323ecb4e933492f77fa350377accff7c.zip + https://github.com/oliver-schick/ENCRYPTO_utils/archive/23639b335f64532abdf64cdd131473599799ad62.zip CACHE STRING "URL of ENCRYPTO_utils project." ) set(ENCRYPTO_utils_URL_HASH - SHA256=cd1b3bea4a42fe8d23193296fa3ea106fa0ddfedb7c22696070c1386ac488005 + SHA256=37a4de5c943cd98592e1af2f8cd3b6f76337ccdbdba80dbf777a2f7c951dae15 CACHE STRING "Hash of ENCRYPTO_utils archive." ) diff --git a/src/abycore/cmake/Modules/FetchOTExtension.cmake b/src/abycore/cmake/Modules/FetchOTExtension.cmake index 1208b030..b3faff74 100644 --- a/src/abycore/cmake/Modules/FetchOTExtension.cmake +++ b/src/abycore/cmake/Modules/FetchOTExtension.cmake @@ -5,12 +5,12 @@ set(OTExtension_SOURCE "Path to OTExtension source." ) set(OTExtension_URL - https://github.com/oliver-schick/OTExtension/archive/f708859f6185018e2eb45ab6ecbf9dbb1b5c7f30.zip + https://github.com/oliver-schick/OTExtension/archive/a923a0b72faf5203a99233e696c163af1e5c17d2.zip CACHE STRING "URL of OTExtension project." ) set(OTExtension_URL_HASH - SHA256=4f77e9a51d08e3505ad52a2804154721c2e8755b1f38eabfff354ed6233ae67e + SHA256=58e8ff999ee2fddd985072c8f629b402609f8dbb6ec5c41b3c2f0e1c452a88a8 CACHE STRING "Hash of OTExtension archive." ) diff --git a/src/abycore/cmake/Modules/InstallConfig.cmake b/src/abycore/cmake/Modules/InstallConfig.cmake index bf627971..438792c6 100644 --- a/src/abycore/cmake/Modules/InstallConfig.cmake +++ b/src/abycore/cmake/Modules/InstallConfig.cmake @@ -12,10 +12,11 @@ function(install_config CONFIG_LOCATION INSTALL_NAME INSTALL_DIR) endif() configure_file("${PROJECT_SOURCE_DIR}/cmake/${INSTALL_NAME}Config.cmake.in" - ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}Config.cmake - COPYONLY + "${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}Config.cmake" + @ONLY ) - + file(READ "${PROJECT_SOURCE_DIR}/cmake/ImportIntoAndroidStudio.cmake" IMPORT_INTO_ANDROID_STUDIO) + file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}Config.cmake" "${IMPORT_INTO_ANDROID_STUDIO}") install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}Config.cmake" DESTINATION "${INSTALL_DIR}/${CONFIG_NAME}" diff --git a/src/abycore/cmake/Modules/PatchBOOST_CMAKE.cmake b/src/abycore/cmake/Modules/PatchBOOST_CMAKE.cmake new file mode 100644 index 00000000..fb1276aa --- /dev/null +++ b/src/abycore/cmake/Modules/PatchBOOST_CMAKE.cmake @@ -0,0 +1,5 @@ +configure_file( + "${CMAKE_CURRENT_LIST_DIR}/BOOST_CMAKEPatches/libs/header.cmake" + "${boost_cmake_SOURCE_DIR}/libs/header.cmake" + COPYONLY +) diff --git a/src/abycore/ot/arithmtmasking.h b/src/abycore/ot/arithmtmasking.h index 5eed3245..68e2637b 100644 --- a/src/abycore/ot/arithmtmasking.h +++ b/src/abycore/ot/arithmtmasking.h @@ -53,7 +53,7 @@ class ArithMTMasking: public MaskingFunction { ; //In total K' OTs will be performed - void Mask(uint32_t progress, uint32_t len, CBitVector** values, CBitVector* snd_buf, snd_ot_flavor protocol) { + void Mask(uint32_t progress, uint32_t len, CBitVector** values, CBitVector* snd_buf, [[maybe_unused]] snd_ot_flavor protocol) { //progress and processedOTs should always be divisible by MTBitLen if (progress % m_nMTBitLen != 0 || len % m_nMTBitLen != 0) { @@ -120,7 +120,7 @@ class ArithMTMasking: public MaskingFunction { //rcv_buf holds the masked values that were sent by the sender, output holds the masks that were generated by the receiver //void UnMask(uint32_t progress, uint32_t processedOTs, CBitVector& choices, CBitVector& output, CBitVector& rcv_buf, CBitVector& tmpmasks, BYTE version) { - void UnMask(uint32_t progress, uint32_t len, CBitVector* choices, CBitVector* output, CBitVector* rcv_buf, CBitVector* tmpmask, snd_ot_flavor version) { + void UnMask(uint32_t progress, uint32_t len, CBitVector* choices, CBitVector* output, CBitVector* rcv_buf, CBitVector* tmpmask, [[maybe_unused]] snd_ot_flavor version) { //progress and len should always be divisible by MTBitLen if (progress % m_nMTBitLen != 0 || len % m_nMTBitLen != 0) { std::cerr << "progress or processed OTs not divisible by MTBitLen, cannot guarantee correct result. Progress = " << progress << ", processed OTs " << len @@ -137,7 +137,6 @@ class ArithMTMasking: public MaskingFunction { uint32_t startpos = progress / (m_nMTBitLen * m_nElements); T* masks = (T*) tmpmask->GetArr(); - T* rcvedvals = (T*) rcv_buf->GetArr(); T* outvals = ((T*) output->GetArr()) + startpos * m_nElements; for (uint32_t mtid = startpos, i = progress, mtbit, j, maskctr = 0; i < lim; mtid++) { @@ -180,7 +179,7 @@ class ArithMTMasking: public MaskingFunction { ; //void expandMask(CBitVector& out, BYTE* sbp, uint32_t offset, uint32_t processedOTs, uint32_t bitlength, crypto* crypt) { - void expandMask(CBitVector* out, BYTE* sbp, uint32_t offset, uint32_t processedOTs, uint32_t bitlength, crypto* crypt) { + void expandMask(CBitVector* out, BYTE* sbp, uint32_t offset, uint32_t processedOTs, [[maybe_unused]] uint32_t bitlength, crypto* crypt) { //the CBitVector to store the random values in if (!aesexpand) { @@ -190,7 +189,7 @@ class ArithMTMasking: public MaskingFunction { } } else { uint32_t* counter = reinterpret_cast(m_bCtrBuf.data()); - for (uint32_t i = 0, rem; i < processedOTs; i++, sbp += AES_KEY_BYTES) { + for (uint32_t i = 0; i < processedOTs; i++, sbp += AES_KEY_BYTES) { //Generate sufficient random bits crypt->init_aes_key(&tkey, sbp); for (counter[0] = 0; counter[0] < ceil_divide(m_nOTByteLen, AES_BYTES); counter[0]++) { diff --git a/src/abycore/sharing/arithsharing.cpp b/src/abycore/sharing/arithsharing.cpp index c07b2565..20e9fd51 100644 --- a/src/abycore/sharing/arithsharing.cpp +++ b/src/abycore/sharing/arithsharing.cpp @@ -2,17 +2,17 @@ \file arithsharing.cpp \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Arithmetic Sharing class implementation */ @@ -156,16 +156,16 @@ void ArithSharing::PrepareSetupPhase(ABYSetup* setup) { } template -void ArithSharing::PerformSetupPhase(ABYSetup* setup) { +void ArithSharing::PerformSetupPhase([[maybe_unused]] ABYSetup* setup) { //Do nothing } template -void ArithSharing::FinishSetupPhase(ABYSetup* setup) { +void ArithSharing::FinishSetupPhase([[maybe_unused]] ABYSetup* setup) { #ifdef DEBUGARITH for(uint32_t i = 0; i < m_nMTs; i++) { - std::cout << "Output from OT: A: " << (UINT64_T) m_vA[0].template Get(i * m_nTypeBitLen, m_nTypeBitLen) << ", B: " << (UINT64_T) m_vB[0].template Get(i * m_nTypeBitLen, m_nTypeBitLen) - << ", C: " << (UINT64_T) m_vC[0].template Get(i * m_nTypeBitLen, m_nTypeBitLen) << ", S: " << (UINT64_T) m_vS[0].template Get(i * m_nTypeBitLen, m_nTypeBitLen) << std::endl; + std::cout << "Output from OT: A: " << (uint64_t) m_vA[0].template Get(i * m_nTypeBitLen, m_nTypeBitLen) << ", B: " << (uint64_t) m_vB[0].template Get(i * m_nTypeBitLen, m_nTypeBitLen) + << ", C: " << (uint64_t) m_vC[0].template Get(i * m_nTypeBitLen, m_nTypeBitLen) << ", S: " << (uint64_t) m_vS[0].template Get(i * m_nTypeBitLen, m_nTypeBitLen) << std::endl; } #endif if (m_eMTGenAlg == MT_OT) { @@ -188,16 +188,14 @@ template void ArithSharing::InitMTs() { m_vMTIdx.resize(1, 0); m_vMTStartIdx.resize(1, 0); + m_vA.resize(1); m_vC.resize(1); m_vB.resize(1); - - m_vC[0].Create(m_nMTs, m_nTypeBitLen); - m_vB[0].Create(m_nMTs, m_nTypeBitLen, m_cCrypto); - - m_vA.resize(1); m_vS.resize(1); m_vA[0].Create(m_nMTs, m_nTypeBitLen, m_cCrypto); + m_vB[0].Create(m_nMTs, m_nTypeBitLen, m_cCrypto); + m_vC[0].Create(m_nMTs, m_nTypeBitLen); m_vS[0].Create(m_nMTs, m_nTypeBitLen); m_vD_snd.resize(1); @@ -211,8 +209,6 @@ void ArithSharing::InitMTs() { template void ArithSharing::ComputeMTsFromOTs() { - uint32_t bytesMTs = ceil_divide(m_nMTs * m_nTypeBitLen, 8); - CBitVector temp(m_nMTs); T tmp; @@ -224,8 +220,8 @@ void ArithSharing::ComputeMTsFromOTs() { m_vC[0].template Set(tmp, i * m_nTypeBitLen, m_nTypeBitLen); #ifdef DEBUGARITH std::cout << "Computed MT " << i << ": "; - std::cout << "A: " << (UINT64_T) m_vA[0].template Get(i * m_nTypeBitLen, m_nTypeBitLen) << ", B: " << (UINT64_T) m_vB[0].template Get(i * m_nTypeBitLen, m_nTypeBitLen) - << ", C: " << (UINT64_T) m_vC[0].template Get(i * m_nTypeBitLen, m_nTypeBitLen) << std::endl; + std::cout << "A: " << (uint64_t) m_vA[0].template Get(i * m_nTypeBitLen, m_nTypeBitLen) << ", B: " << (uint64_t) m_vB[0].template Get(i * m_nTypeBitLen, m_nTypeBitLen) + << ", C: " << (uint64_t) m_vC[0].template Get(i * m_nTypeBitLen, m_nTypeBitLen) << std::endl; #endif } @@ -279,7 +275,7 @@ void ArithSharing::EvaluateLocalOperations(uint32_t depth) { std::deque localops = m_cArithCircuit->GetLocalQueueOnLvl(depth); for (uint32_t i = 0; i < localops.size(); i++) { - GATE* gate = m_pGates + localops[i]; + GATE* gate = &(m_vGates[localops[i]]); #ifdef DEBUGARITH std::cout << "Evaluating gate with id = " << localops[i] << " of type " << gate->type << std::endl; @@ -309,7 +305,7 @@ void ArithSharing::EvaluateLocalOperations(uint32_t depth) { } else if (gate->type == G_SHARED_IN) { // nothing to do here } else if (gate->type == G_SHARED_OUT) { - GATE* parent = m_pGates + gate->ingates.inputs.parent; + GATE* parent = &(m_vGates[gate->ingates.inputs.parent]); InstantiateGate(gate); memcpy(gate->gs.val, parent->gs.val, gate->nvals * sizeof(T)); UsedGate(gate->ingates.inputs.parent); @@ -329,7 +325,7 @@ void ArithSharing::EvaluateInteractiveOperations(uint32_t depth) { std::deque interactiveops = m_cArithCircuit->GetInteractiveQueueOnLvl(depth); for (uint32_t i = 0; i < interactiveops.size(); i++) { - GATE* gate = m_pGates + interactiveops[i]; + GATE* gate = &(m_vGates[interactiveops[i]]); if (gate->type == G_NON_LIN) { #ifdef DEBUGARITH @@ -403,9 +399,9 @@ void ArithSharing::EvaluateADDGate(GATE* gate) { InstantiateGate(gate); for (uint32_t i = 0; i < nvals; i++) { - ((T*) gate->gs.aval)[i] = ((T*) m_pGates[idleft].gs.aval)[i] + ((T*) m_pGates[idright].gs.aval)[i]; + ((T*) gate->gs.aval)[i] = ((T*) m_vGates[idleft].gs.aval)[i] + ((T*) m_vGates[idright].gs.aval)[i]; #ifdef DEBUGARITH - std::cout << "Result ADD (" << i << "): "<< ((T*)gate->gs.aval)[i] << " = " << ((T*) m_pGates[idleft].gs.aval)[i] << " + " << ((T*)m_pGates[idright].gs.aval)[i] << std::endl; + std::cout << "Result ADD (" << i << "): "<< ((T*)gate->gs.aval)[i] << " = " << ((T*) m_vGates[idleft].gs.aval)[i] << " + " << ((T*)m_vGates[idright].gs.aval)[i] << std::endl; #endif } @@ -421,8 +417,8 @@ void ArithSharing::EvaluateMULCONSTGate(GATE* gate) { InstantiateGate(gate); // Find first constant. Doesn't matter if 2nd is also a constant, which would be // a weird circuit anyways... - GATE* gate_const = &(m_pGates[idleft]); - GATE* gate_var = &(m_pGates[idright]); + GATE* gate_const = &(m_vGates[idleft]); + GATE* gate_var = &(m_vGates[idright]); if (!(gate_const->type == G_CONSTANT)) std::swap(gate_const, gate_var); assert (gate_const->type == G_CONSTANT && "At least one of the inputs in a MULCONST gate must be a constant."); // Current implementation of evaluation of CONST gates writes 0s to gs.aval @@ -455,8 +451,8 @@ void ArithSharing::ShareValues(GATE* gate) { tmpval = m_vInputShareSndBuf.template Get(m_nInputShareSndCtr); ((T*) gate->gs.aval)[i] = MOD_SUB(input[i], tmpval, m_nTypeBitMask); #ifdef DEBUGARITH - std::cout << "Shared: " << (UINT64_T) ((T*)gate->gs.aval)[i] << " = " << (UINT64_T) input[i] << " - " << - (UINT64_T) m_vInputShareSndBuf.template Get(m_nInputShareSndCtr) << ", " << m_nTypeBitMask << + std::cout << "Shared: " << (uint64_t) ((T*)gate->gs.aval)[i] << " = " << (uint64_t) input[i] << " - " << + (uint64_t) m_vInputShareSndBuf.template Get(m_nInputShareSndCtr) << ", " << m_nTypeBitMask << ", inputid on this layer = " << m_nInputShareSndCtr << ", tmpval = " << tmpval << std::endl; m_vInputShareSndBuf.PrintHex(); #endif @@ -471,13 +467,13 @@ void ArithSharing::EvaluateCONVGate(GATE* gate) { uint32_t nvals = gate->nvals; #ifdef DEBUGARITH - std::cout << "Values of B2A gates with id " << ((((uint64_t) gate)-((uint64_t)m_pGates))/sizeof(GATE)) << ": "; + std::cout << "Values of B2A gates with id " << ((((uint64_t) gate)-((uint64_t)m_vGates.data()))/sizeof(GATE)) << ": "; #endif for (uint32_t i = 0; i < nparents; i++) { - if (m_pGates[parentids[i]].context == S_YAO) + if (m_vGates[parentids[i]].context == S_YAO) std::cerr << "can't convert from yao representation directly into arithmetic" << std::endl; #ifdef DEBUGARITH - std::cout << (uint32_t) m_pGates[parentids[i]].gs.val[0]; + std::cout << (uint32_t) m_vGates[parentids[i]].gs.val[0]; #endif } @@ -497,7 +493,7 @@ void ArithSharing::EvaluateCONVGate(GATE* gate) { m_nConvShareSndCtr, nparents * nvals); for (uint32_t i = 0; i < nparents; ++i) { //XOR the choice bits and the current values of the gate and write into the snd buffer - m_vConvShareSndBuf.XORBits((BYTE*) m_pGates[parentids[i]].gs.val, + m_vConvShareSndBuf.XORBits((BYTE*) m_vGates[parentids[i]].gs.val, m_nConvShareSndCtr, nvals); m_nConvShareSndCtr += nvals; } @@ -513,9 +509,9 @@ void ArithSharing::ReconstructValue(GATE* gate) { uint32_t parentid = gate->ingates.inputs.parent; for (uint32_t i = 0; i < gate->nvals; i++, m_nOutputShareSndCtr++) { - m_vOutputShareSndBuf.template Set(((T*) m_pGates[parentid].gs.aval)[i], m_nOutputShareSndCtr); + m_vOutputShareSndBuf.template Set(((T*) m_vGates[parentid].gs.aval)[i], m_nOutputShareSndCtr); #ifdef DEBUGARITH - std::cout << "Sending output share: " << (UINT64_T) ((T*)m_pGates[parentid].gs.aval)[i] << std::endl; + std::cout << "Sending output share: " << (uint64_t) ((T*)m_vGates[parentid].gs.aval)[i] << std::endl; #endif } if (gate->gs.oshare.dst != ALL) @@ -530,11 +526,11 @@ void ArithSharing::SelectiveOpen(GATE* gate) { T d, e, x, y, a, b; for (uint32_t i = 0; i < gate->nvals; i++, m_vMTIdx[0]++) { a = m_vD_snd[0].template Get(m_vMTIdx[0]); - x = ((T*) m_pGates[idleft].gs.aval)[i]; + x = ((T*) m_vGates[idleft].gs.aval)[i]; d = MOD_SUB(x, a, m_nTypeBitMask); //a > x ? m_nTypeBitMask - (a - 1) + x : x - a; m_vD_snd[0].template Set(d, m_vMTIdx[0]); b = m_vE_snd[0].template Get(m_vMTIdx[0]); - y = ((T*) m_pGates[idright].gs.aval)[i]; + y = ((T*) m_vGates[idright].gs.aval)[i]; e = MOD_SUB(y, b, m_nTypeBitMask); //b > y ? m_nTypeBitMask - (b - 1) + y : y - b; m_vE_snd[0].template Set(e, m_vMTIdx[0]); } @@ -545,7 +541,7 @@ void ArithSharing::SelectiveOpen(GATE* gate) { } template -void ArithSharing::FinishCircuitLayer(uint32_t depth) { +void ArithSharing::FinishCircuitLayer() { #ifdef DEBUGARITH if(m_nInputShareRcvCtr > 0) { std::cout << "Received "<< m_nInputShareRcvCtr << " input shares: "; @@ -599,8 +595,8 @@ void ArithSharing::EvaluateMTs() { tempres = (tempres + (d * e)) & m_nTypeBitMask; } #ifdef DEBUGARITH - std::cout << "mt result = " << (UINT64_T) tempres << " = ((" << (UINT64_T) a << " * " << (UINT64_T) e << " ) + ( " << (UINT64_T) b - << " * " << (UINT64_T) d << ") + " << (UINT64_T) c << ")" << std::endl; + std::cout << "mt result = " << (uint64_t) tempres << " = ((" << (uint64_t) a << " * " << (uint64_t) e << " ) + ( " << (uint64_t) b + << " * " << (uint64_t) d << ") + " << (uint64_t) c << ")" << std::endl; #endif m_vResA[0].template Set(tempres, i); } @@ -631,7 +627,7 @@ void ArithSharing::AssignInputShares() { for (uint32_t j = 0; j < gate->nvals; j++, rcvshareidx++) { ((T*) gate->gs.aval)[j] = m_vInputShareRcvBuf.template Get(rcvshareidx); #ifdef DEBUGARITH - std::cout << "Received inshare: " << (UINT64_T) ((T*)gate->gs.aval)[j] << " = " << (UINT64_T) m_vInputShareRcvBuf.template Get(rcvshareidx) << std::endl; + std::cout << "Received inshare: " << (uint64_t) ((T*)gate->gs.aval)[j] << " = " << (uint64_t) m_vInputShareRcvBuf.template Get(rcvshareidx) << std::endl; #endif } } @@ -646,11 +642,11 @@ void ArithSharing::AssignOutputShares() { InstantiateGate(gate); for (uint32_t j = 0; j < gate->nvals; j++, rcvshareidx++) { - ((T*) gate->gs.val)[j] = ((T*) m_pGates[parentid].gs.aval)[j] + m_vOutputShareRcvBuf.template Get(rcvshareidx) + ((T*) gate->gs.val)[j] = (((T*) m_vGates[parentid].gs.aval)[j] + m_vOutputShareRcvBuf.template Get(rcvshareidx)) & m_nTypeBitMask; #ifdef DEBUGARITH std::cout << "Received output share: " << m_vOutputShareRcvBuf.template Get(rcvshareidx) << std::endl; - std::cout << "Computed output: " << (UINT64_T) ((T*)gate->gs.aval)[j] << " = " << (UINT64_T) ((T*)m_pGates[parentid].gs.aval)[j] << " + " << (UINT64_T) m_vOutputShareRcvBuf.template Get(rcvshareidx) << std::endl; + std::cout << "Computed output: " << (uint64_t) ((T*)gate->gs.aval)[j] << " = " << (uint64_t) ((T*)m_vGates[parentid].gs.aval)[j] << " + " << (uint64_t) m_vOutputShareRcvBuf.template Get(rcvshareidx) << std::endl; #endif } UsedGate(parentid); @@ -717,7 +713,7 @@ void ArithSharing::AssignServerConversionShares() { for (uint32_t j = 0; j < nparents; j++) { for (uint32_t k = 0; k < nvals; k++, lctr++, gctr++) { clientpermbit = m_vConvShareRcvBuf.GetBitNoMask(lctr); - cor = (m_pGates[parentids[j]].gs.val[k / GATE_T_BITS] >> (k % GATE_T_BITS)) & 0x01; + cor = (m_vGates[parentids[j]].gs.val[k / GATE_T_BITS] >> (k % GATE_T_BITS)) & 0x01; T rnd = m_vConversionRandomness.template Get(gctr); tmpa = (m_nTypeBitMask - (rnd - 1)) + (cor) * (1L << j); @@ -788,13 +784,13 @@ void ArithSharing::AssignClientConversionShares() { for (uint32_t j = 0; j < nparents; j++) { for (uint32_t k = 0; k < nvals; k++, lctr++, gctr++) { rcv = m_vConvShareRcvBuf.template Get( - (2 * lctr + ((m_pGates[parentids[j]].gs.val[k / GATE_T_BITS] >> (k % GATE_T_BITS)) & 0x01)) ); + (2 * lctr + ((m_vGates[parentids[j]].gs.val[k / GATE_T_BITS] >> (k % GATE_T_BITS)) & 0x01)) ); mask = m_vConversionMasks[1].template Get(gctr); tmp = rcv ^ mask; tmpsum[k] += tmp; #ifdef DEBUGARITH std::cout << "Gate " << i << ", " << j << ", " << k << ": " << tmp << " = " << rcv << " ^ " << mask << ", tmpsum = " << tmpsum[k] << ", " << - ((uint32_t) ((m_pGates[parentids[j]].gs.val[k / GATE_T_BITS] >> (k % GATE_T_BITS)) & 0x01)) << ", gctr = " << gctr << std::endl; + ((uint32_t) ((m_vGates[parentids[j]].gs.val[k / GATE_T_BITS] >> (k % GATE_T_BITS)) & 0x01)) << ", gctr = " << gctr << std::endl; #endif } UsedGate(parentids[j]); @@ -824,8 +820,8 @@ void ArithSharing::EvaluateINVGate(GATE* gate) { uint32_t parentid = gate->ingates.inputs.parent; InstantiateGate(gate); for (uint32_t i = 0; i < gate->nvals; i++) { -// ((T*) gate->gs.aval)[i] = MOD_SUB(0, ((T*) m_pGates[parentid].gs.aval)[i], m_nTypeBitMask);//0 - ((T*) m_pGates[parentid].gs.aval)[i]; - ((T*) gate->gs.aval)[i] = -((T*) m_pGates[parentid].gs.aval)[i]; +// ((T*) gate->gs.aval)[i] = MOD_SUB(0, ((T*) m_vGates[parentid].gs.aval)[i], m_nTypeBitMask);//0 - ((T*) m_vGates[parentid].gs.aval)[i]; + ((T*) gate->gs.aval)[i] = -((T*) m_vGates[parentid].gs.aval)[i]; } UsedGate(parentid); } @@ -951,7 +947,7 @@ void ArithSharing::InstantiateGate(GATE* gate) { template void ArithSharing::EvaluateSIMDGate(uint32_t gateid) { - GATE* gate = m_pGates + gateid; + GATE* gate = &(m_vGates[gateid]); uint32_t vsize = gate->nvals; if (gate->type == G_COMBINE) { @@ -964,8 +960,8 @@ void ArithSharing::EvaluateSIMDGate(uint32_t gateid) { T* valptr = ((T*) gate->gs.aval); for (uint32_t k = 0; k < nparents; k++) { - memcpy(valptr, m_pGates[input[k]].gs.aval, sizeof(T) * m_pGates[input[k]].nvals); - valptr += m_pGates[input[k]].nvals; + memcpy(valptr, m_vGates[input[k]].gs.aval, sizeof(T) * m_vGates[input[k]].nvals); + valptr += m_vGates[input[k]].nvals; UsedGate(input[k]); } @@ -979,7 +975,7 @@ void ArithSharing::EvaluateSIMDGate(uint32_t gateid) { InstantiateGate(gate); for (uint32_t i = 0; i < vsize; i++) { - ((T*) gate->gs.aval)[i] = ((T*) m_pGates[idparent].gs.aval)[pos + i]; + ((T*) gate->gs.aval)[i] = ((T*) m_vGates[idparent].gs.aval)[pos + i]; } UsedGate(idparent); @@ -991,7 +987,7 @@ void ArithSharing::EvaluateSIMDGate(uint32_t gateid) { InstantiateGate(gate); for (uint32_t i = 0; i < vsize; i++) { - ((T*) gate->gs.aval)[i] = ((T*) m_pGates[idparent].gs.aval)[0]; + ((T*) gate->gs.aval)[i] = ((T*) m_vGates[idparent].gs.aval)[0]; } UsedGate(idparent); } else if (gate->type == G_PERM) { @@ -1008,7 +1004,7 @@ void ArithSharing::EvaluateSIMDGate(uint32_t gateid) { //TODO: Optimize for (uint32_t i = 0; i < vsize; i++) { - ((T*) gate->gs.aval)[i] = ((T*) m_pGates[perm[i]].gs.aval)[pos[i]]; + ((T*) gate->gs.aval)[i] = ((T*) m_vGates[perm[i]].gs.aval)[pos[i]]; UsedGate(perm[i]); } free(perm); @@ -1025,7 +1021,7 @@ void ArithSharing::EvaluateSIMDGate(uint32_t gateid) { //TODO: Optimize for (uint32_t i = 0; i < vsize; i++) { uint32_t idparent = combinepos[i]; - ((T*) gate->gs.aval)[i] = ((T*) m_pGates[idparent].gs.aval)[arraypos]; + ((T*) gate->gs.aval)[i] = ((T*) m_vGates[idparent].gs.aval)[arraypos]; UsedGate(idparent); } free(combinepos); @@ -1040,7 +1036,7 @@ void ArithSharing::EvaluateSIMDGate(uint32_t gateid) { InstantiateGate(gate); for (uint32_t i = 0; i < vsize; i++) { - ((T*) gate->gs.aval)[i] = ((T*) m_pGates[idparent].gs.aval)[positions[i]]; + ((T*) gate->gs.aval)[i] = ((T*) m_vGates[idparent].gs.aval)[positions[i]]; } UsedGate(idparent); if (del_pos) @@ -1077,8 +1073,8 @@ void ArithSharing::VerifyArithMT(ABYSetup* setup) { c = m_vC[0].template Get(i) + Crcv.template Get(i); res = a * b; if(res != c) { - std::cerr << "Error: " << i << "-th multiplication triples differs: a (" << (UINT64_T) a << ") * b (" << - (UINT64_T) b << ") = c (" << (UINT64_T) c << "), correct = " << (UINT64_T) res << std::endl; + std::cerr << "Error: " << i << "-th multiplication triples differs: a (" << (uint64_t) a << ") * b (" << + (uint64_t) b << ") = c (" << (uint64_t) c << "), correct = " << (uint64_t) res << std::endl; correct = false; } } @@ -1100,7 +1096,7 @@ uint32_t ArithSharing::AssignInput(CBitVector& inputvals) { GATE* gate; for (uint32_t i = 0, inbitctr = 0; i < myingates.size(); i++) { - gate = m_pGates + myingates[i]; + gate = &(m_vGates[myingates[i]]); if (!gate->instantiated) { UGATE_T* inval = (UGATE_T*) calloc(ceil_divide(gate->nvals, typebytes), sizeof(UGATE_T)); @@ -1124,7 +1120,7 @@ uint32_t ArithSharing::GetOutput(CBitVector& out) { GATE* gate; for (uint32_t i = 0, outbitctr = 0; i < myoutgates.size(); i++) { - gate = m_pGates + myoutgates[i]; + gate = &(m_vGates[myoutgates[i]]); for (uint32_t j = 0; j < gate->nvals; j++) { out.template Set(((T*) gate->gs.val)[j], outbitctr); @@ -1189,7 +1185,7 @@ void ArithSharing::Reset() { } //The explicit instantiation part -template class ArithSharing ; -template class ArithSharing ; -template class ArithSharing ; -template class ArithSharing ; +template class ArithSharing ; +template class ArithSharing ; +template class ArithSharing ; +template class ArithSharing ; diff --git a/src/abycore/sharing/arithsharing.h b/src/abycore/sharing/arithsharing.h index 3e68c737..62fc104a 100644 --- a/src/abycore/sharing/arithsharing.h +++ b/src/abycore/sharing/arithsharing.h @@ -2,17 +2,17 @@ \file arithsharing.h \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Arithmetic Sharing class. */ @@ -54,7 +54,7 @@ class ArithSharing: public Sharing { void EvaluateLocalOperations(uint32_t depth); void EvaluateInteractiveOperations(uint32_t depth); - void FinishCircuitLayer(uint32_t depth); + void FinishCircuitLayer(); void PrepareOnlinePhase(); diff --git a/src/abycore/sharing/boolsharing.cpp b/src/abycore/sharing/boolsharing.cpp index 67ed2780..81873668 100644 --- a/src/abycore/sharing/boolsharing.cpp +++ b/src/abycore/sharing/boolsharing.cpp @@ -2,25 +2,36 @@ \file boolsharing.cpp \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Bool sharing class implementation. */ #include "boolsharing.h" #include "../aby/abysetup.h" #include +#if ANDROID #include namespace filesystem = boost::filesystem; +#elif __has_include() +#include +namespace filesystem = std::filesystem; +#elif __has_include() +#include +namespace filesystem = std::experimental::filesystem; +#else +#error "C++17 filesystem library not found" +#endif + void BoolSharing::Init() { @@ -35,7 +46,7 @@ void BoolSharing::Init() { m_nInputShareRcvSize = 0; m_nOutputShareRcvSize = 0; - m_cBoolCircuit = new BooleanCircuit(m_pCircuit, m_eRole, m_eContext); + m_cBoolCircuit = new BooleanCircuit(m_pCircuit, m_eRole, m_eContext, m_cCircuitFileDir); #ifdef BENCHBOOLTIME m_nCombTime = 0; @@ -273,7 +284,7 @@ void BoolSharing::PrepareSetupPhaseOPLUT(ABYSetup* setup) { //The server initializes the possible values for the OT and pre-compute the rotated truth-tables //TODO: Optimize with rotation instead of Set Bits! Also change loop order to make it more efficient! if(m_eRole == SERVER) { - uint32_t tab_ele_bits = sizeof(uint64_t) * 8; + // uint32_t tab_ele_bits = sizeof(uint64_t) * 8; uint32_t tt_len = 1<n_inbits; lut_data->rot_OT_vals = (CBitVector**) malloc(sizeof(CBitVector*) * tt_len); @@ -341,10 +352,10 @@ void BoolSharing::PrepareSetupPhaseOPLUT(ABYSetup* setup) { } -void BoolSharing::PerformSetupPhase(ABYSetup* setup) { +void BoolSharing::PerformSetupPhase([[maybe_unused]] ABYSetup* setup) { //Do nothing } -void BoolSharing::FinishSetupPhase(ABYSetup* setup) { +void BoolSharing::FinishSetupPhase([[maybe_unused]] ABYSetup* setup) { if (m_nTotalNumMTs == 0 && m_nOPLUT_Tables == 0) return; @@ -357,7 +368,7 @@ void BoolSharing::FinishSetupPhase(ABYSetup* setup) { //Delete the X values for OP-LUT of the sender when pre-computing the OTs for(auto it=m_vOP_LUT_data.begin(); it!=m_vOP_LUT_data.end(); it++) { if(it->second->n_gates > 0 && m_eRole == SERVER) { - for(uint32_t i = 0; i < 1<second->n_inbits; i++) { + for(uint32_t i = 0; i < (uint32_t) 1<second->n_inbits; i++) { it->second->rot_OT_vals[i]->delCBitVector(); } free(it->second->rot_OT_vals); @@ -574,7 +585,7 @@ void BoolSharing::EvaluateLocalOperations(uint32_t depth) { timespec tstart, tend; #endif for (uint32_t i = 0; i < localops.size(); i++) { - gate = m_pGates + localops[i]; + gate = &(m_vGates[localops[i]]); #ifdef DEBUGBOOL std::cout << "Evaluating local gate with id = " << localops[i] << " and type " << get_gate_type_name(gate->type) << std::endl; @@ -602,7 +613,7 @@ void BoolSharing::EvaluateLocalOperations(uint32_t depth) { break; case G_SHARED_OUT: InstantiateGate(gate); - memcpy(gate->gs.val, ((GATE*) m_pGates + gate->ingates.inputs.parent)->gs.val, bits_in_bytes(gate->nvals)); + memcpy(gate->gs.val, ((GATE*) &(m_vGates[gate->ingates.inputs.parent]))->gs.val, bits_in_bytes(gate->nvals)); UsedGate(gate->ingates.inputs.parent); break; case G_SHARED_IN: @@ -633,7 +644,7 @@ void BoolSharing::EvaluateInteractiveOperations(uint32_t depth) { std::deque interactiveops = m_cBoolCircuit->GetInteractiveQueueOnLvl(depth); for (uint32_t i = 0; i < interactiveops.size(); i++) { - GATE* gate = m_pGates + interactiveops[i]; + GATE* gate = &(m_vGates[interactiveops[i]]); #ifdef DEBUGBOOL std::cout << "Evaluating interactive gate with id = " << interactiveops[i] << " and type " << get_gate_type_name(gate->type) << std::endl; @@ -680,14 +691,14 @@ void BoolSharing::EvaluateInteractiveOperations(uint32_t depth) { } inline void BoolSharing::EvaluateXORGate(uint32_t gateid) { - GATE* gate = m_pGates + gateid; + GATE* gate = &(m_vGates[gateid]); uint32_t nvals = gate->nvals; uint32_t idleft = gate->ingates.inputs.twin.left; uint32_t idright = gate->ingates.inputs.twin.right; InstantiateGate(gate); for (uint32_t i = 0; i < ceil_divide(nvals, GATE_T_BITS); i++) { - gate->gs.val[i] = m_pGates[idleft].gs.val[i] ^ m_pGates[idright].gs.val[i]; + gate->gs.val[i] = m_vGates[idleft].gs.val[i] ^ m_vGates[idright].gs.val[i]; } UsedGate(idleft); @@ -695,18 +706,26 @@ inline void BoolSharing::EvaluateXORGate(uint32_t gateid) { } inline void BoolSharing::EvaluateConstantGate(uint32_t gateid) { - GATE* gate = m_pGates + gateid; + GATE* gate = &(m_vGates[gateid]); UGATE_T value = gate->gs.constval; InstantiateGate(gate); value = value * (m_eRole != CLIENT); - for (uint32_t i = 0; i < ceil_divide(gate->nvals, GATE_T_BITS); i++) { - gate->gs.val[i] = value; - if(value) { - gate->gs.val[i] = ~(0L); - } + uint32_t valsize = ceil_divide(gate->nvals, GATE_T_BITS); + UGATE_T setval; + if(value == 1L) { + setval = ~(0L); + } else { + setval = 0L; } - gate->gs.val[ceil_divide(gate->nvals, GATE_T_BITS)-1] &= ((1L<<(gate->nvals%64)) -1L); + for (uint32_t i = 0; i < valsize; ++i) { + gate->gs.val[i] = setval; + } + uint32_t valmod = gate->nvals % GATE_T_BITS; + if(valmod != 0) { + gate->gs.val[valsize - 1] &= (1L << valmod) - 1L; + } + #ifdef DEBUGBOOL std::cout << "Constant gate value: "<< value << std::endl; #endif @@ -714,7 +733,7 @@ inline void BoolSharing::EvaluateConstantGate(uint32_t gateid) { inline void BoolSharing::ShareValues(uint32_t gateid) { - GATE* gate = m_pGates + gateid; + GATE* gate = &(m_vGates[gateid]); UGATE_T* input = gate->gs.ishare.inval; InstantiateGate(gate); @@ -731,7 +750,7 @@ inline void BoolSharing::ShareValues(uint32_t gateid) { } inline void BoolSharing::EvaluateINVGate(uint32_t gateid) { - GATE* gate = m_pGates + gateid; + GATE* gate = &(m_vGates[gateid]); uint32_t parentid = gate->ingates.inputs.parent; uint32_t i; InstantiateGate(gate); @@ -742,35 +761,35 @@ inline void BoolSharing::EvaluateINVGate(uint32_t gateid) { memset(&tmpval, 0x00, sizeof(UGATE_T)); } for (i = 0; i < ceil_divide((gate->nvals+1), GATE_T_BITS) - 1; i++) { - gate->gs.val[i] = m_pGates[parentid].gs.val[i] ^ tmpval; + gate->gs.val[i] = m_vGates[parentid].gs.val[i] ^ tmpval; } //set only the remaining nvals%GATE_T_BITS if(gate->nvals % GATE_T_BITS != 0) { - gate->gs.val[i] = (m_pGates[parentid].gs.val[i] ^ tmpval) & (((UGATE_T) 1) << ((gate->nvals % GATE_T_BITS))) - 1; + gate->gs.val[i] = (m_vGates[parentid].gs.val[i] ^ tmpval) & (((UGATE_T) 1) << ((gate->nvals % GATE_T_BITS))) - 1; } #ifdef DEBUGBOOL std::cout << "Evaluated INV gate " << gateid << " with result: " << (std::hex) << gate->gs.val[0] << - " and input: " << m_pGates[parentid].gs.val[0]<< (std::dec) << std::endl; + " and input: " << m_vGates[parentid].gs.val[0]<< (std::dec) << std::endl; #endif UsedGate(parentid); } inline void BoolSharing::EvaluateCONVGate(uint32_t gateid) { - GATE* gate = m_pGates + gateid; + GATE* gate = &(m_vGates[gateid]); uint32_t parentid = gate->ingates.inputs.parents[0]; - if (m_pGates[parentid].context == S_ARITH) + if (m_vGates[parentid].context == S_ARITH) std::cerr << "can't convert from arithmetic representation directly into Boolean" << std::endl; - assert(m_pGates[parentid].context == S_YAO); + assert(m_vGates[parentid].context == S_YAO); InstantiateGate(gate); memset(gate->gs.val, 0, ceil_divide(gate->nvals, 8)); if (m_eRole == SERVER) { for (uint32_t i = 0; i < gate->nvals; i++) { - gate->gs.val[i / GATE_T_BITS] |= ((uint64_t) m_pGates[parentid].gs.yinput.pi[i]) << (i % GATE_T_BITS); + gate->gs.val[i / GATE_T_BITS] |= ((uint64_t) m_vGates[parentid].gs.yinput.pi[i]) << (i % GATE_T_BITS); } } else { for (uint32_t i = 0; i < gate->nvals; i++) { - gate->gs.val[i / GATE_T_BITS] |= ((uint64_t) (m_pGates[parentid].gs.yval[((i + 1) * m_nSecParamBytes) - 1] & 0x01) << (i % GATE_T_BITS)); + gate->gs.val[i / GATE_T_BITS] |= ((uint64_t) (m_vGates[parentid].gs.yval[((i + 1) * m_nSecParamBytes) - 1] & 0x01) << (i % GATE_T_BITS)); } } #ifdef DEBUGBOOL @@ -782,16 +801,16 @@ inline void BoolSharing::EvaluateCONVGate(uint32_t gateid) { } inline void BoolSharing::ReconstructValue(uint32_t gateid) { - GATE* gate = m_pGates + gateid; + GATE* gate = &(m_vGates[gateid]); uint32_t parentid = gate->ingates.inputs.parent; - assert(m_pGates[parentid].instantiated); + assert(m_vGates[parentid].instantiated); for (uint32_t i = 0, bitstocopy = gate->nvals, len; i < ceil_divide(gate->nvals, GATE_T_BITS); i++, bitstocopy -= GATE_T_BITS) { len = std::min(bitstocopy, (uint32_t) GATE_T_BITS); #ifdef DEBUGBOOL std::cout << "m_vOutputShareSndBuf.size = " << m_vOutputShareSndBuf.GetSize() << ", ctr = " <parent = " << parentid - << " and val = " << (std::hex) << m_pGates[parentid].gs.val[i] << (std::dec) << std::endl; + << " and val = " << (std::hex) << m_vGates[parentid].gs.val[i] << (std::dec) << std::endl; #endif - m_vOutputShareSndBuf.Set(m_pGates[parentid].gs.val[i], m_nOutputShareSndSize, len); //gate->gs.val[i], len); + m_vOutputShareSndBuf.Set(m_vGates[parentid].gs.val[i], m_nOutputShareSndSize, len); //gate->gs.val[i], len); m_nOutputShareSndSize += len; } if (gate->gs.oshare.dst != ALL) @@ -799,17 +818,17 @@ inline void BoolSharing::ReconstructValue(uint32_t gateid) { } inline void BoolSharing::SelectiveOpen(uint32_t gateid) { - GATE* gate = m_pGates + gateid; + GATE* gate = &(m_vGates[gateid]); uint32_t idleft = gate->ingates.inputs.twin.left; uint32_t idright = gate->ingates.inputs.twin.right; for (uint32_t i = 0, bitstocopy = gate->nvals, len; i < ceil_divide(gate->nvals, GATE_T_BITS); i++, bitstocopy -= GATE_T_BITS) { len = std::min(bitstocopy, (uint32_t) GATE_T_BITS); - m_vD_snd[0].XOR(m_pGates[idleft].gs.val[i], m_vMTIdx[0], len); - m_vE_snd[0].XOR(m_pGates[idright].gs.val[i], m_vMTIdx[0], len); + m_vD_snd[0].XOR(m_vGates[idleft].gs.val[i], m_vMTIdx[0], len); + m_vE_snd[0].XOR(m_vGates[idright].gs.val[i], m_vMTIdx[0], len); m_vMTIdx[0] += len; #ifdef DEBUGBOOL - std::cout << "opening " << idleft << " = " << m_pGates[idleft].gs.val[i] << " , and " << idright << " = " << m_pGates[idright].gs.val[i] << std::endl; + std::cout << "opening " << idleft << " = " << m_vGates[idleft].gs.val[i] << " , and " << idright << " = " << m_vGates[idright].gs.val[i] << std::endl; #endif } m_vANDGates[0].push_back(gateid); @@ -819,7 +838,7 @@ inline void BoolSharing::SelectiveOpen(uint32_t gateid) { } inline void BoolSharing::SelectiveOpenVec(uint32_t gateid) { - GATE* gate = m_pGates + gateid; + GATE* gate = &(m_vGates[gateid]); uint32_t idchoice = gate->ingates.inputs.twin.left; uint32_t idvector = gate->ingates.inputs.twin.right; @@ -833,20 +852,20 @@ inline void BoolSharing::SelectiveOpenVec(uint32_t gateid) { // ", nandvals = " << nandvals << ", mtidx = " << m_vMTIdx[pos] << std::endl; //XOR the choice bit onto the D-vector - m_vD_snd[pos].XORBits((uint8_t*) m_pGates[idchoice].gs.val, m_vMTIdx[pos], nandvals); - //m_vD_snd[pos].XORBitNoMask(m_vMTIdx[pos], m_pGates[idchoice].gs.val[0]); + m_vD_snd[pos].XORBits((uint8_t*) m_vGates[idchoice].gs.val, m_vMTIdx[pos], nandvals); + //m_vD_snd[pos].XORBitNoMask(m_vMTIdx[pos], m_vGates[idchoice].gs.val[0]); - //std::cout << "choice_val: " << m_pGates[idchoice].gs.val[0] << ", vec_val: " << m_pGates[idvector].gs.val[0] << " (" << gateid << ")" << std::endl; + //std::cout << "choice_val: " << m_vGates[idchoice].gs.val[0] << ", vec_val: " << m_vGates[idvector].gs.val[0] << " (" << gateid << ")" << std::endl; //for (uint32_t i = 0, bitstocopy = gate->nvals * m_vANDs[pos].bitlen, ncopiedvals; i < ceil_divide(gate->nvals, GATE_T_BITS); i++, bitstocopy -= GATE_T_BITS) { for (uint32_t i = 0, bitstocopy = gate->nvals, ncopiedvals; i < ceil_divide(gate->nvals, GATE_T_BITS); i++, bitstocopy -= GATE_T_BITS, startpos+=GATE_T_BITS) { ncopiedvals = std::min(bitstocopy, (uint32_t) GATE_T_BITS); - //m_vE_snd[pos].XOR(m_pGates[idvector].gs.val[i], m_vMTIdx[pos] * m_vANDs[pos].bitlen, ncopiedvals); //*m_vANDs[pos].bitlen); - m_vE_snd[pos].XOR(m_pGates[idvector].gs.val[i], startpos, ncopiedvals); //*m_vANDs[pos].bitlen); + //m_vE_snd[pos].XOR(m_vGates[idvector].gs.val[i], m_vMTIdx[pos] * m_vANDs[pos].bitlen, ncopiedvals); //*m_vANDs[pos].bitlen); + m_vE_snd[pos].XOR(m_vGates[idvector].gs.val[i], startpos, ncopiedvals); //*m_vANDs[pos].bitlen); #ifdef DEBUGBOOL std::cout << "copying from " << m_vMTIdx[pos]*m_vANDs[pos].bitlen << " with len = " << ncopiedvals << std::endl; - std::cout << "choice-gate " << idchoice << " = " << m_pGates[idchoice].gs.val[0] << " , and vec-gate " << idvector << - " = " <<(std::hex) << m_pGates[idvector].gs.val[i] << (std::dec) << std::endl; + std::cout << "choice-gate " << idchoice << " = " << m_vGates[idchoice].gs.val[0] << " , and vec-gate " << idvector << + " = " <<(std::hex) << m_vGates[idvector].gs.val[i] << (std::dec) << std::endl; #endif } //m_vMTIdx[pos]++; @@ -860,11 +879,11 @@ inline void BoolSharing::SelectiveOpenVec(uint32_t gateid) { inline void BoolSharing::SelectiveOpenOPLUT(uint32_t gateid) { - GATE* gate = m_pGates + gateid, *ingate; + GATE *gate = &(m_vGates[gateid]), *ingate; uint32_t* input = gate->ingates.inputs.parents; uint32_t nparents = gate->ingates.ningates; uint32_t typebitlen = sizeof(uint64_t) * 8; - uint32_t nvals = m_pGates[input[0]].nvals; + uint32_t nvals = m_vGates[input[0]].nvals; uint32_t outbits = (uint64_t) gate->nvals / nvals; uint64_t op_lut_id = (((uint64_t) nparents) << 32) | outbits ; @@ -881,7 +900,7 @@ inline void BoolSharing::SelectiveOpenOPLUT(uint32_t gateid) { //iterate over all parent wires and construct the input gate value for(uint32_t j = 0; j < nparents; j++) { - ingate = m_pGates + input[j]; + ingate = &(m_vGates[input[j]]); selective_opening |= (((ingate->gs.val[(i/typebitlen)] >> (i%typebitlen)) & 0x01)<rot_val->Get(lut_ctx->sel_opening_ctr * nparents, nparents); @@ -897,7 +916,7 @@ inline void BoolSharing::SelectiveOpenOPLUT(uint32_t gateid) { #endif } -void BoolSharing::FinishCircuitLayer(uint32_t level) { +void BoolSharing::FinishCircuitLayer() { //Compute the values of the AND gates #ifdef DEBUGBOOL if(m_nInputShareRcvSize > 0) { @@ -1058,7 +1077,7 @@ void BoolSharing::EvaluateANDGate() { GATE* gate; for (uint32_t k = 0; k < m_nNumANDSizes; k++) { for (uint32_t i = 0, j, bitstocopy, len, idx = m_vMTStartIdx[k]*m_vANDs[k].bitlen; i < m_vANDGates[k].size(); i++) { - gate = m_pGates + m_vANDGates[k][i]; + gate = &(m_vGates[m_vANDGates[k][i]]); InstantiateGate(gate); bitstocopy = gate->nvals; @@ -1111,11 +1130,11 @@ void BoolSharing::EvaluateOPLUTGates() { uint32_t gatectr = 0; uint32_t maskbit_ctr = m_vOP_LUT_data[op_lut_id]->mask_ctr * (1<n_inbits) * m_vOP_LUT_data[op_lut_id]->n_outbits; for(uint32_t i = 0; i < it->second.size(); i++) { - gate = m_pGates+it->second[i]; + gate = &(m_vGates[it->second[i]]); inputs = gate->ingates.inputs.parents; nparents = gate->ingates.ningates; - nvals = m_pGates[inputs[0]].nvals; + nvals = m_vGates[inputs[0]].nvals; outbits = (uint64_t) gate->nvals / nvals; InstantiateGate(gate); @@ -1147,7 +1166,7 @@ void BoolSharing::EvaluateOPLUTGates() { void BoolSharing::AssignInputShares() { GATE* gate; for (uint32_t i = 0, j, rcvshareidx = 0, bitstocopy, len; i < m_vInputShareGates.size(); i++) { - gate = m_pGates + m_vInputShareGates[i]; + gate = &(m_vGates[m_vInputShareGates[i]]); InstantiateGate(gate); bitstocopy = gate->nvals; @@ -1165,16 +1184,16 @@ void BoolSharing::AssignInputShares() { void BoolSharing::AssignOutputShares() { GATE* gate; for (uint32_t i = 0, j, rcvshareidx = 0, bitstocopy, len, parentid; i < m_vOutputShareGates.size(); i++) { - gate = m_pGates + m_vOutputShareGates[i]; + gate = &(m_vGates[m_vOutputShareGates[i]]); parentid = gate->ingates.inputs.parent; InstantiateGate(gate); bitstocopy = gate->nvals; for (j = 0; j < ceil_divide(gate->nvals, GATE_T_BITS); j++, bitstocopy -= GATE_T_BITS) { len = std::min(bitstocopy, (uint32_t) GATE_T_BITS); - gate->gs.val[j] = m_pGates[parentid].gs.val[j] ^ m_vOutputShareRcvBuf.Get(rcvshareidx, len); + gate->gs.val[j] = m_vGates[parentid].gs.val[j] ^ m_vOutputShareRcvBuf.Get(rcvshareidx, len); #ifdef DEBUGBOOL - std::cout << "Outshare: " << (std::hex) << gate->gs.val[j] << " = " << m_pGates[parentid].gs.val[j] << " ^ " << + std::cout << "Outshare: " << (std::hex) << gate->gs.val[j] << " = " << m_vGates[parentid].gs.val[j] << " ^ " << m_vOutputShareRcvBuf.Get(rcvshareidx, len) << (std::dec) << std::endl; #endif rcvshareidx += len; @@ -1277,7 +1296,7 @@ inline void BoolSharing::InstantiateGate(GATE* gate) { } void BoolSharing::EvaluateSIMDGate(uint32_t gateid) { - GATE* gate = m_pGates + gateid; + GATE* gate = &(m_vGates[gateid]); uint32_t vsize = gate->nvals; #ifdef BENCHBOOLTIME @@ -1297,10 +1316,10 @@ void BoolSharing::EvaluateSIMDGate(uint32_t gateid) { tmp.AttachBuf((uint8_t*) gate->gs.val, (int) ceil_divide(vsize, 8)); - for(uint64_t i = 0, bit_ctr = 0, ctr=0; i < nparents; i++) { - uint64_t in_size = m_pGates[input[i]].nvals; + for(uint64_t i = 0, bit_ctr = 0; i < nparents; i++) { + uint64_t in_size = m_vGates[input[i]].nvals; - tmp.SetBits((uint8_t*) m_pGates[input[i]].gs.val, bit_ctr, in_size); + tmp.SetBits((uint8_t*) m_vGates[input[i]].gs.val, bit_ctr, in_size); bit_ctr += in_size; } @@ -1319,7 +1338,7 @@ void BoolSharing::EvaluateSIMDGate(uint32_t gateid) { gate->gs.val[k] = 0; //TODO: not working if valsize of the original gate is greater than GATE_T_BITS!, replace for variable sized function for (uint32_t i = 0; i < size; i++) { - gate->gs.val[k] |= m_pGates[input[i + k * GATE_T_BITS]].gs.val[0] << i; + gate->gs.val[k] |= m_vGates[input[i + k * GATE_T_BITS]].gs.val[0] << i; UsedGate(input[i + k * GATE_T_BITS]); } }*/ @@ -1337,7 +1356,7 @@ void BoolSharing::EvaluateSIMDGate(uint32_t gateid) { InstantiateGate(gate); //TODO optimize for (uint32_t i = 0; i < vsize; i++) { - gate->gs.val[i / GATE_T_BITS] |= ((m_pGates[idparent].gs.val[(pos + i) / GATE_T_BITS] >> ((pos + i) % GATE_T_BITS)) & 0x1) << (i % GATE_T_BITS); + gate->gs.val[i / GATE_T_BITS] |= ((m_vGates[idparent].gs.val[(pos + i) / GATE_T_BITS] >> ((pos + i) % GATE_T_BITS)) & 0x1) << (i % GATE_T_BITS); } UsedGate(idparent); } else if (gate->type == G_REPEAT) //TODO only meant for single bit values, update @@ -1348,7 +1367,7 @@ void BoolSharing::EvaluateSIMDGate(uint32_t gateid) { uint32_t idparent = gate->ingates.inputs.parent; InstantiateGate(gate); - BYTE byte_val = m_pGates[idparent].gs.val[0] ? MAX_BYTE : ZERO_BYTE; + BYTE byte_val = m_vGates[idparent].gs.val[0] ? MAX_BYTE : ZERO_BYTE; memset(gate->gs.val, byte_val, sizeof(UGATE_T) * ceil_divide(vsize, GATE_T_BITS)); UsedGate(idparent); } else if (gate->type == G_PERM) { @@ -1366,7 +1385,7 @@ void BoolSharing::EvaluateSIMDGate(uint32_t gateid) { //TODO: Optimize for (uint32_t i = 0; i < vsize; i++) { - gate->gs.val[i / GATE_T_BITS] |= (((m_pGates[inputs[i]].gs.val[posids[i] / GATE_T_BITS] >> (posids[i] % GATE_T_BITS)) & 0x1) << (i % GATE_T_BITS)); + gate->gs.val[i / GATE_T_BITS] |= (((m_vGates[inputs[i]].gs.val[posids[i] / GATE_T_BITS] >> (posids[i] % GATE_T_BITS)) & 0x1) << (i % GATE_T_BITS)); UsedGate(inputs[i]); } free(inputs); @@ -1384,7 +1403,7 @@ void BoolSharing::EvaluateSIMDGate(uint32_t gateid) { //TODO: Optimize for (uint32_t i = 0; i < vsize; i++) { uint32_t idparent = combinepos[i]; - gate->gs.val[i / GATE_T_BITS] |= (((m_pGates[idparent].gs.val[arraypos] >> bitpos) & 0x1) << (i % GATE_T_BITS)); + gate->gs.val[i / GATE_T_BITS] |= (((m_vGates[idparent].gs.val[arraypos] >> bitpos) & 0x1) << (i % GATE_T_BITS)); UsedGate(idparent); } free(combinepos); @@ -1399,7 +1418,7 @@ void BoolSharing::EvaluateSIMDGate(uint32_t gateid) { uint32_t bitpos; InstantiateGate(gate); memset(gate->gs.val, 0x00, ceil_divide(vsize, 8)); - UGATE_T* valptr = m_pGates[idparent].gs.val; + UGATE_T* valptr = m_vGates[idparent].gs.val; for (uint32_t i = 0; i < vsize; i++) { arraypos = positions[i] >> 6; bitpos = positions[i] & 0x3F; @@ -1433,13 +1452,13 @@ void BoolSharing::EvaluateSIMDGate(uint32_t gateid) { p_tmp_idx = pos_ctr / GATE_T_BITS; p_tmp_pos = pos_ctr % GATE_T_BITS; for(uint32_t in_ctr = 0; in_ctrgs.val[ctr / GATE_T_BITS] |= (((m_pGates[inputs[in_ctr]].gs.val[p_tmp_idx] >> p_tmp_pos) & 0x1) << (ctr % GATE_T_BITS)); - //gate->gs.val[ctr / GATE_T_BITS] |= (((m_pGates[inputs[in_ctr]].gs.val[pos_ctr / GATE_T_BITS] >> (pos_ctr % GATE_T_BITS)) & 0x1) << (ctr % GATE_T_BITS)); + gate->gs.val[ctr / GATE_T_BITS] |= (((m_vGates[inputs[in_ctr]].gs.val[p_tmp_idx] >> p_tmp_pos) & 0x1) << (ctr % GATE_T_BITS)); + //gate->gs.val[ctr / GATE_T_BITS] |= (((m_vGates[inputs[in_ctr]].gs.val[pos_ctr / GATE_T_BITS] >> (pos_ctr % GATE_T_BITS)) & 0x1) << (ctr % GATE_T_BITS)); } } //for (uint32_t i = 0, in_ctr=0, pos_ctr=pos_start; i < vsize; i++, in_ctr=(in_ctr+1)%ninputs, pos_ctr+=pos_incr ) { - // gate->gs.val[i / GATE_T_BITS] |= (((m_pGates[inputs[in_ctr]].gs.val[pos_ctr / GATE_T_BITS] >> (pos_ctr % GATE_T_BITS)) & 0x1) << (i % GATE_T_BITS)); + // gate->gs.val[i / GATE_T_BITS] |= (((m_vGates[inputs[in_ctr]].gs.val[pos_ctr / GATE_T_BITS] >> (pos_ctr % GATE_T_BITS)) & 0x1) << (i % GATE_T_BITS)); //} for(uint32_t i = 0; i < ninputs; i++) { @@ -1465,7 +1484,7 @@ uint32_t BoolSharing::AssignInput(CBitVector& inputvals) { GATE* gate; uint32_t inbits = 0; for (uint32_t i = 0, inbitstart = 0, bitstocopy, len, lim; i < myingates.size(); i++) { - gate = m_pGates + myingates[i]; + gate = &(m_vGates[myingates[i]]); if (!gate->instantiated) { bitstocopy = gate->nvals * gate->sharebitlen; inbits += bitstocopy; @@ -1490,8 +1509,8 @@ uint32_t BoolSharing::GetOutput(CBitVector& out) { out.Create(outbits); GATE* gate; - for (uint32_t i = 0, outbitstart = 0, bitstocopy, len, lim; i < myoutgates.size(); i++) { - gate = m_pGates + myoutgates[i]; + for (uint32_t i = 0, outbitstart = 0, lim; i < myoutgates.size(); i++) { + gate = &(m_vGates[myoutgates[i]]); lim = gate->nvals * gate->sharebitlen; for (uint32_t j = 0; j < lim; j++, outbitstart++) { @@ -1683,7 +1702,7 @@ void BoolSharing::StoreMTsToFile(const char *filename) { /**Writing the MTs and bytelen of the MTs o the file.*/ for (uint32_t i = 0; i < m_nNumANDSizes; i++) { uint32_t andbytelen = ceil_divide(m_nNumMTs[i], 8); - uint32_t stringbytelen = ceil_divide(m_nNumMTs[i] * m_vANDs[i].bitlen, 8); + // uint32_t stringbytelen = ceil_divide(m_nNumMTs[i] * m_vANDs[i].bitlen, 8); fwrite(&andbytelen, sizeof(uint32_t), 1, fp); fwrite(m_vA[i].GetArr(), andbytelen, 1, fp); fwrite(m_vB[i].GetArr(), andbytelen, 1, fp); @@ -1697,8 +1716,8 @@ void BoolSharing::StoreMTsToFile(const char *filename) { void BoolSharing::ReadMTsFromFile(const char *filename) { FILE *fp; - /**Calculate the file size*/ - uint64_t file_size = filesystem::file_size(filename); + // /**Calculate the file size*/ + // uint64_t file_size = filesystem::file_size(filename); /**Variable for the storing the NUMANDSizes value from the file.*/ uint32_t num_and_sizes; diff --git a/src/abycore/sharing/boolsharing.h b/src/abycore/sharing/boolsharing.h index b445476e..25857a4b 100644 --- a/src/abycore/sharing/boolsharing.h +++ b/src/abycore/sharing/boolsharing.h @@ -2,17 +2,17 @@ \file boolsharing.h \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Bool Sharing class. */ @@ -50,9 +50,8 @@ class BoolSharing: public Sharing { public: /** Constructor of the class.*/ - BoolSharing(e_sharing context, e_role role, uint32_t sharebitlen, ABYCircuit* circuit, crypto* crypt) :\ - - Sharing(context, role, sharebitlen, circuit, crypt) { + BoolSharing(e_sharing context, e_role role, uint32_t sharebitlen, ABYCircuit* circuit, crypto* crypt, const std::string& circdir = ABY_CIRCUIT_DIR) : + Sharing(context, role, sharebitlen, circuit, crypt, circdir) { Init(); } ; @@ -70,7 +69,7 @@ class BoolSharing: public Sharing { void EvaluateLocalOperations(uint32_t level); void EvaluateInteractiveOperations(uint32_t level); - void FinishCircuitLayer(uint32_t level); + void FinishCircuitLayer(); void PrepareOnlinePhase(); diff --git a/src/abycore/sharing/sharing.cpp b/src/abycore/sharing/sharing.cpp index d2ff07b8..ba929c88 100644 --- a/src/abycore/sharing/sharing.cpp +++ b/src/abycore/sharing/sharing.cpp @@ -2,17 +2,17 @@ \file sharing.cpp \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Sharing class implementation. */ #include "sharing.h" @@ -23,32 +23,47 @@ #include #include +#if ANDROID #include namespace filesystem = boost::filesystem; +typedef boost::system::error_code error_code; +#elif __has_include() +#include +namespace filesystem = std::filesystem; +typedef std::error_code error_code; +#elif __has_include() +#include +namespace filesystem = std::experimental::filesystem; +typedef std::error_code error_code; +#else +#error "filesystem library not found" +#endif #include #include #include #include -Sharing::Sharing(e_sharing context, e_role role, uint32_t sharebitlen, ABYCircuit* circuit, crypto* crypt) { - m_eContext = context; - m_nShareBitLen = sharebitlen; - m_pCircuit = circuit; - m_pGates = m_pCircuit->Gates(); - m_eRole = role; - m_cCrypto = crypt; - m_nSecParamBytes = ceil_divide(m_cCrypto->get_seclvl().symbits, 8); - m_ePhaseValue = ePreCompDefault; - m_nFilePos = -1; - m_nTypeBitLen = sharebitlen; -} +Sharing::Sharing(e_sharing context, e_role role, uint32_t sharebitlen, ABYCircuit* circuit, crypto* crypt, const std::string& circdir) : + m_eContext(context), + m_nShareBitLen(sharebitlen), + m_pCircuit(circuit), + m_vGates(m_pCircuit->GatesVec()), + m_eRole(role), + m_cCrypto(crypt), + m_nSecParamBytes(ceil_divide(m_cCrypto->get_seclvl().symbits, 8)), + m_nTypeBitLen(sharebitlen), + m_nFilePos(-1), + m_ePhaseValue(ePreCompDefault), + m_cCircuitFileDir(circdir) +{} + Sharing::~Sharing() { } void Sharing::EvaluateCallbackGate(uint32_t gateid) { - GATE* gate = m_pGates + gateid; + GATE* gate = &(m_vGates[gateid]); void (*callback)(GATE*, void*) = gate->gs.cbgate.callback; void* infos = gate->gs.cbgate.infos; InstantiateGate(gate); @@ -85,7 +100,7 @@ void Sharing::PreCompFileDelete() { } else { truncation_size = filesystem::file_size(filename) - m_nFilePos; - boost::system::error_code ec; + error_code ec; filesystem::resize_file(filename, truncation_size, ec); if(ec) { std::cout << "Error occured in truncate:" << ec.message() << std::endl; @@ -105,7 +120,7 @@ UGATE_T* Sharing::ReadOutputValue(uint32_t gateid, e_circuit circ_type, uint32_t UGATE_T* value; GATE *parentgate, *gate; - gate = m_pGates + gateid; + gate = &(m_vGates[gateid]); nvals = gate->nvals; //in case the values are in Boolean form, reformat them. @@ -116,7 +131,7 @@ UGATE_T* Sharing::ReadOutputValue(uint32_t gateid, e_circuit circ_type, uint32_t value = (UGATE_T*) calloc(val_offset * nvals, sizeof(UGATE_T)); for (uint32_t i = 0; i < *bitlen; i++) { - parentgate = m_pGates + gate->ingates.inputs.parents[i]; + parentgate = &(m_vGates[gate->ingates.inputs.parents[i]]); assert(parentgate->nvals == nvals); assert(parentgate->instantiated); @@ -129,7 +144,7 @@ UGATE_T* Sharing::ReadOutputValue(uint32_t gateid, e_circuit circ_type, uint32_t *bitlen = m_nTypeBitLen; valbytelen = ceil_divide((*bitlen), 8); - parentgate = m_pGates + gate->ingates.inputs.parents[0]; + parentgate = &(m_vGates[gate->ingates.inputs.parents[0]]); value = (UGATE_T*) calloc(nvals, sizeof(UGATE_T)); for(uint32_t i = 0; i < nvals; i++) { @@ -152,21 +167,21 @@ void Sharing::EvaluateAssertGate(uint32_t gateid, e_circuit circ_type) { //get the gate value in a standardized form UGATE_T* value = ReadOutputValue(gateid, circ_type, &bitlen); - nvals = m_pGates[gateid].nvals; + nvals = m_vGates[gateid].nvals; uint32_t ugate_len = ceil_divide(bitlen, sizeof(UGATE_T) * 8) * nvals; //check gate value against reference for(uint32_t i = 0; i < ugate_len; i++) { - if(m_pGates[gateid].gs.assertval[i] != value[i]) { + if(m_vGates[gateid].gs.assertval[i] != value[i]) { std::cout << "Data in Assert gate is not matching for nval = " << i << ": Circuit " << value[i] << - " vs. Reference " << m_pGates[gateid].gs.assertval[i] << std::endl; + " vs. Reference " << m_vGates[gateid].gs.assertval[i] << std::endl; } - assert(m_pGates[gateid].gs.assertval[i] == value[i]); + assert(m_vGates[gateid].gs.assertval[i] == value[i]); } free(value); - free(m_pGates[gateid].gs.assertval); + free(m_vGates[gateid].gs.assertval); } /* @@ -177,9 +192,9 @@ void Sharing::EvaluatePrintValGate(uint32_t gateid, e_circuit circ_type) { //get the gate value in a standardized form UGATE_T* value = ReadOutputValue(gateid, circ_type, &bitlen); - nvals = m_pGates[gateid].nvals; + nvals = m_vGates[gateid].nvals; - std::cout << m_pGates[gateid].gs.infostr << ": "; + std::cout << m_vGates[gateid].gs.infostr << ": "; //print the resulting value depending on its bitlength and nvals if(bitlen <= 64) {//for bitlen <= 64 print numbers @@ -212,7 +227,7 @@ void Sharing::EvaluatePrintValGate(uint32_t gateid, e_circuit circ_type) { } free(value); - delete[] m_pGates[gateid].gs.infostr; + delete[] m_vGates[gateid].gs.infostr; } // Delete dynamically allocated gate contents depending on gate type @@ -239,13 +254,15 @@ void Sharing::FreeGate(GATE *gate) { free(gate->gs.yval); } break; + default: + std::cerr << "Error: unhandled sharing in FreeGate(). context: " << get_sharing_name(context) << std::endl; } gate->instantiated = false; } // Mark gate as used. If it is no longer needed, free it. void Sharing::UsedGate(uint32_t gateid) { - GATE *gate = &m_pGates[gateid]; + GATE *gate = &m_vGates[gateid]; if(!gate->instantiated) { return; } gate->nused--; if(!gate->nused && gate->type != G_CONV) { diff --git a/src/abycore/sharing/sharing.h b/src/abycore/sharing/sharing.h index 5747f36a..fe545e13 100644 --- a/src/abycore/sharing/sharing.h +++ b/src/abycore/sharing/sharing.h @@ -2,17 +2,17 @@ \file sharing.h \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Sharing class. A virtual class that contains the methods which the sharing schemes have to implement @@ -48,7 +48,7 @@ class Sharing { \brief Initialises the members of the class. */ - Sharing(e_sharing context, e_role role, uint32_t sharebitlen, ABYCircuit* circuit, crypto* crypt); + Sharing(e_sharing context, e_role role, uint32_t sharebitlen, ABYCircuit* circuit, crypto* crypt, const std::string& circdir = ABY_CIRCUIT_DIR); /** Destructor of class. @@ -101,7 +101,7 @@ class Sharing { /** Method for finishing the circuit layer */ - virtual void FinishCircuitLayer(uint32_t level) = 0; + virtual void FinishCircuitLayer() = 0; /** Method for sending the data. @@ -235,16 +235,17 @@ class Sharing { UGATE_T* ReadOutputValue(uint32_t gateid, e_circuit circ_type, uint32_t* bitlen); + e_sharing m_eContext; /** Which sharing is executed */ uint32_t m_nShareBitLen; /**< Bit length of shared item. */ - GATE* m_pGates; /**< Pointer to array of Logical Gates. */ ABYCircuit* m_pCircuit; /**< Circuit pointer. */ + std::vector& m_vGates; /**< Reference to vector of gates. */ e_role m_eRole; /**< Role object. */ - uint32_t m_nSecParamBytes; /**< Number of security param bytes. */ crypto* m_cCrypto; /**< Class that contains cryptographic routines */ - e_sharing m_eContext; /** Which sharing is executed */ + uint32_t m_nSecParamBytes; /**< Number of security param bytes. */ uint32_t m_nTypeBitLen; /** Bit-length of the arithmetic shares in arithsharing */ uint64_t m_nFilePos;/**< Variable which stores the position of the file pointer. */ ePreCompPhase m_ePhaseValue;/**< Variable storing the current Precomputation Mode */ + const std::string m_cCircuitFileDir; /** Storing path to .aby circuit files (e.g. floating point) */ }; diff --git a/src/abycore/sharing/splut.cpp b/src/abycore/sharing/splut.cpp index cbd667ef..147446fd 100644 --- a/src/abycore/sharing/splut.cpp +++ b/src/abycore/sharing/splut.cpp @@ -2,17 +2,17 @@ \file splut.cpp \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Implementation of the SP-LUT protocol */ #include "splut.h" @@ -26,8 +26,8 @@ #include "../circuit/booleancircuits.h" -SetupLUT::SetupLUT(e_sharing context, e_role role, uint32_t sharebitlen, ABYCircuit* circuit, crypto* crypt) - : Sharing(context, role, sharebitlen, circuit, crypt) { +SetupLUT::SetupLUT(e_sharing context, e_role role, uint32_t sharebitlen, ABYCircuit* circuit, crypto* crypt, const std::string& circdir) + : Sharing(context, role, sharebitlen, circuit, crypt, circdir) { Init(); } @@ -90,7 +90,7 @@ void SetupLUT::Init() { m_nInputShareRcvSize = 0; m_nOutputShareRcvSize = 0; - m_cBoolCircuit = new BooleanCircuit(m_pCircuit, m_eRole, m_eContext); + m_cBoolCircuit = new BooleanCircuit(m_pCircuit, m_eRole, m_eContext, m_cCircuitFileDir); //first round: the server is the active part and skips the first send iteration while the client waits until the server is done with depth 1 m_bPlaySender = !((bool) m_eRole); @@ -205,7 +205,7 @@ void SetupLUT::PrepareSetupPhase(ABYSetup* setup) { } } //create the outbit mapping - assert(max_out_bits < (1<<31));//some maximal bitlen + assert(max_out_bits < (uint32_t) (1<<31));//some maximal bitlen m_vOutBitMapping[i].resize(max_out_bits+1, 0); for(uint32_t j = 0; j < ingatelens[i]; j++) { @@ -342,10 +342,10 @@ void SetupLUT::PrepareSetupPhase(ABYSetup* setup) { } -void SetupLUT::PerformSetupPhase(ABYSetup* setup) { +void SetupLUT::PerformSetupPhase([[maybe_unused]] ABYSetup* setup) { //Do nothing } -void SetupLUT::FinishSetupPhase(ABYSetup* setup) { +void SetupLUT::FinishSetupPhase([[maybe_unused]] ABYSetup* setup) { if (m_nTotalTTs == 0) return; @@ -426,7 +426,7 @@ void SetupLUT::EvaluateLocalOperations(uint32_t depth) { timeval tstart, tend; #endif for (uint32_t i = 0; i < localops.size(); i++) { - gate = m_pGates + localops[i]; + gate = &(m_vGates[localops[i]]); #ifdef DEBUGBOOL_NO_MT std::cout << "Evaluating local gate with id = " << localops[i] << " and type " << get_gate_type_name(gate->type) << std::endl; #endif @@ -461,7 +461,7 @@ void SetupLUT::EvaluateLocalOperations(uint32_t depth) { break; case G_SHARED_OUT: InstantiateGate(gate); - memcpy(gate->gs.val, ((GATE*) m_pGates + gate->ingates.inputs.parent)->gs.val, bits_in_bytes(gate->nvals)); + memcpy(gate->gs.val, m_vGates[gate->ingates.inputs.parent].gs.val, bits_in_bytes(gate->nvals)); UsedGate(gate->ingates.inputs.parent); break; case G_SHARED_IN: @@ -486,7 +486,7 @@ void SetupLUT::EvaluateInteractiveOperations(uint32_t depth) { std::deque interactiveops = m_cBoolCircuit->GetInteractiveQueueOnLvl(depth); for (uint32_t i = 0; i < interactiveops.size(); i++) { - GATE* gate = m_pGates + interactiveops[i]; + GATE* gate = &(m_vGates[interactiveops[i]]); #ifdef DEBUG_SPLUT std::cout << "Evaluating interactive gate with id = " << interactiveops[i] << " and type " << get_gate_type_name(gate->type) << std::endl; @@ -535,10 +535,10 @@ void SetupLUT::EvaluateInteractiveOperations(uint32_t depth) { inline void SetupLUT::EvaluateTTGate(uint32_t gateid) { //Evaluate Truth Table gate - GATE* gate = m_pGates + gateid; + GATE* gate = &(m_vGates[gateid]); uint32_t* input = gate->ingates.inputs.parents; uint32_t nparents = gate->ingates.ningates; - uint32_t nvals = m_pGates[input[0]].nvals; + uint32_t nvals = m_vGates[input[0]].nvals; assert(nparents >= 0 && nparents < 32); @@ -568,7 +568,7 @@ inline void SetupLUT::EvaluateTTGate(uint32_t gateid) { uint32_t ctr = m_nChoiceUpdateSndCtr[nparents][outbit_id]; //iterate over all parent wires and construct the input gate value for(uint32_t j = 0; j < nparents; j++) { - ingate = m_pGates + input[j]; + ingate = &(m_vGates[input[j]]); gate_shares |= (((ingate->gs.val[(i/typebitlen)] >> (i%typebitlen)) & 0x01)<nvals; uint32_t idleft = gate->ingates.inputs.twin.left; uint32_t idright = gate->ingates.inputs.twin.right; InstantiateGate(gate); for (uint32_t i = 0; i < ceil_divide(nvals, GATE_T_BITS); i++) { - gate->gs.val[i] = m_pGates[idleft].gs.val[i] ^ m_pGates[idright].gs.val[i]; + gate->gs.val[i] = m_vGates[idleft].gs.val[i] ^ m_vGates[idright].gs.val[i]; } - //std::cout << "value = " << gate->gs.val[0] << " = " << m_pGates[idleft].gs.val[0] << " ^ " << m_pGates[idright].gs.val[0] << std::endl; + //std::cout << "value = " << gate->gs.val[0] << " = " << m_vGates[idleft].gs.val[0] << " ^ " << m_vGates[idright].gs.val[0] << std::endl; UsedGate(idleft); UsedGate(idright); } inline void SetupLUT::EvaluateConstantGate(uint32_t gateid) { - GATE* gate = m_pGates + gateid; + GATE* gate = &(m_vGates[gateid]); UGATE_T value = gate->gs.constval; InstantiateGate(gate); value = value * (m_eRole != CLIENT); - for (uint32_t i = 0; i < ceil_divide(gate->nvals, GATE_T_BITS); i++) { - gate->gs.val[i] = value; + uint32_t valsize = ceil_divide(gate->nvals, GATE_T_BITS); + UGATE_T setval; + if(value == 1L) { + setval = ~(0L); + } else { + setval = 0L; + } + for (uint32_t i = 0; i < valsize; ++i) { + gate->gs.val[i] = setval; + } + uint32_t valmod = gate->nvals % GATE_T_BITS; + if(valmod != 0) { + gate->gs.val[valsize - 1] &= (1L << valmod) - 1L; } #ifdef DEBUG_SPLUT std::cout << "Constant gate value: "<< value << std::endl; @@ -635,7 +646,7 @@ inline void SetupLUT::EvaluateConstantGate(uint32_t gateid) { inline void SetupLUT::ShareValues(uint32_t gateid) { - GATE* gate = m_pGates + gateid; + GATE* gate = &(m_vGates[gateid]); UGATE_T* input = gate->gs.ishare.inval; InstantiateGate(gate); @@ -653,7 +664,7 @@ inline void SetupLUT::ShareValues(uint32_t gateid) { } inline void SetupLUT::EvaluateINVGate(uint32_t gateid) { - GATE* gate = m_pGates + gateid; + GATE* gate = &(m_vGates[gateid]); uint32_t parentid = gate->ingates.inputs.parent; uint32_t i; InstantiateGate(gate); @@ -664,34 +675,34 @@ inline void SetupLUT::EvaluateINVGate(uint32_t gateid) { memset(&tmpval, 0x00, sizeof(UGATE_T)); } for (i = 0; i < ceil_divide((gate->nvals+1), GATE_T_BITS) - 1; i++) { - gate->gs.val[i] = m_pGates[parentid].gs.val[i] ^ tmpval; + gate->gs.val[i] = m_vGates[parentid].gs.val[i] ^ tmpval; } //set only the remaining nvals%GATE_T_BITS if(gate->nvals % GATE_T_BITS != 0) { - gate->gs.val[i] = (m_pGates[parentid].gs.val[i] ^ tmpval) & (((UGATE_T) 1) << ((gate->nvals % GATE_T_BITS))) - 1; + gate->gs.val[i] = (m_vGates[parentid].gs.val[i] ^ tmpval) & (((UGATE_T) 1) << ((gate->nvals % GATE_T_BITS))) - 1; } #ifdef DEBUG_SPLUT std::cout << "Evaluated INV gate " << gateid << " with result: " << (hex) << gate->gs.val[0] << - " and input: " << m_pGates[parentid].gs.val[0]<< (dec) << std::endl; + " and input: " << m_vGates[parentid].gs.val[0]<< (dec) << std::endl; #endif UsedGate(parentid); } inline void SetupLUT::EvaluateCONVGate(uint32_t gateid) { - GATE* gate = m_pGates + gateid; + GATE* gate = &(m_vGates[gateid]); uint32_t parentid = gate->ingates.inputs.parents[0]; - if (m_pGates[parentid].context == S_ARITH) + if (m_vGates[parentid].context == S_ARITH) std::cerr << "can't convert from arithmetic representation directly into Boolean" << std::endl; InstantiateGate(gate); memset(gate->gs.val, 0, ceil_divide(gate->nvals, 8)); if (m_eRole == SERVER) { for (uint32_t i = 0; i < gate->nvals; i++) { - gate->gs.val[i / GATE_T_BITS] |= ((uint64_t) m_pGates[parentid].gs.yinput.pi[i]) << (i % GATE_T_BITS); + gate->gs.val[i / GATE_T_BITS] |= ((uint64_t) m_vGates[parentid].gs.yinput.pi[i]) << (i % GATE_T_BITS); } } else { for (uint32_t i = 0; i < gate->nvals; i++) { - gate->gs.val[i / GATE_T_BITS] |= ((uint64_t) (m_pGates[parentid].gs.yval[((i + 1) * m_nSecParamBytes) - 1] & 0x01) << (i % GATE_T_BITS)); + gate->gs.val[i / GATE_T_BITS] |= ((uint64_t) (m_vGates[parentid].gs.yval[((i + 1) * m_nSecParamBytes) - 1] & 0x01) << (i % GATE_T_BITS)); } } #ifdef DEBUG_SPLUT @@ -702,16 +713,16 @@ inline void SetupLUT::EvaluateCONVGate(uint32_t gateid) { } inline void SetupLUT::ReconstructValue(uint32_t gateid) { - GATE* gate = m_pGates + gateid; + GATE* gate = &(m_vGates[gateid]); uint32_t parentid = gate->ingates.inputs.parent; - assert(m_pGates[parentid].instantiated); + assert(m_vGates[parentid].instantiated); for (uint32_t i = 0, bitstocopy = gate->nvals, len; i < ceil_divide(gate->nvals, GATE_T_BITS); i++, bitstocopy -= GATE_T_BITS) { len = std::min(bitstocopy, (uint32_t) GATE_T_BITS); #ifdef DEBUG_SPLUT std::cout << "m_vOutputShareSndBuf.size = " << m_vOutputShareSndBuf.GetSize() << ", ctr = " <parent = " << parentid - << " and val = " << (hex) << m_pGates[parentid].gs.val[i] << (dec) << std::endl; + << " and val = " << (hex) << m_vGates[parentid].gs.val[i] << (dec) << std::endl; #endif - m_vOutputShareSndBuf.Set(m_pGates[parentid].gs.val[i], m_nOutputShareSndSize, len); //gate->gs.val[i], len); + m_vOutputShareSndBuf.Set(m_vGates[parentid].gs.val[i], m_nOutputShareSndSize, len); //gate->gs.val[i], len); m_nOutputShareSndSize += len; } if (gate->gs.oshare.dst != ALL) @@ -719,7 +730,7 @@ inline void SetupLUT::ReconstructValue(uint32_t gateid) { } -void SetupLUT::FinishCircuitLayer(uint32_t level) { +void SetupLUT::FinishCircuitLayer() { //Compute the values of the AND gates #ifdef DEBUGBOOL_NO_MT if(m_nInputShareRcvSize > 0) { @@ -763,7 +774,8 @@ void SetupLUT::FinishCircuitLayer(uint32_t level) { void SetupLUT::SenderEvaluateTTGates() { uint64_t* ttable; uint32_t len, choicelen, nvals; - uint64_t gate_mask, updated_choice, tmpmaskidx, tmp_table, parents_value, tmp_pre_mask; + uint64_t gate_mask, updated_choice, tmp_table, parents_value, tmp_pre_mask; + //uint64_t tmpmaskidx; uint32_t typebitlen = sizeof(uint64_t) * 8; timespec t_start, t_end; clock_gettime(CLOCK_MONOTONIC, &t_start); @@ -777,7 +789,7 @@ void SetupLUT::SenderEvaluateTTGates() { std::vector ctr_idx(m_vOutBitMapping[i].size(), 0); for(uint32_t g = 0; g < m_vTTGates[i].size(); g++) { - GATE* gate = m_pGates + m_vTTGates[i][g]; + GATE* gate = &(m_vGates[m_vTTGates[i][g]]); ttable = gate->gs.tt.table; @@ -819,7 +831,7 @@ void SetupLUT::SenderEvaluateTTGates() { parents_value = 0; //std::cout << "Sender getting mask " << tmpmaskidx << std::endl; for(uint32_t j = 0; j < nparents; j++) { - parents_value ^= (((m_pGates[input[j]].gs.val[n/typebitlen] >> (n%typebitlen)) & 0x01) << j); + parents_value ^= (((m_vGates[input[j]].gs.val[n/typebitlen] >> (n%typebitlen)) & 0x01) << j); } //get the correct random mask bits that were assigned to the gate @@ -939,7 +951,7 @@ void SetupLUT::SenderEvaluateTTGates() { uint8_t* mytable_tmp = (uint8_t*) calloc(512, sizeof(uint8_t));//TODO: static at the moment!, replace by (uint8_t*) calloc(2*len, sizeof(uint8_t)); for(uint32_t g = 0; g < m_vTTGates[i].size(); g++) { - GATE* gate = m_pGates + m_vTTGates[i][g]; + GATE* gate = &(m_vGates[m_vTTGates[i][g]]); ttable = gate->gs.tt.table; //assert(gate->nvals < 65); @@ -983,7 +995,7 @@ void SetupLUT::SenderEvaluateTTGates() { tmp_val = 0; //std::cout << "Sender getting mask " << tmpmaskidx << std::endl; for(uint32_t j = 0; j < nparents; j++) { - tmp_val ^= (((m_pGates[input[j]].gs.val[n/typebitlen] >> (n%typebitlen)) & 0x01) << j); + tmp_val ^= (((m_vGates[input[j]].gs.val[n/typebitlen] >> (n%typebitlen)) & 0x01) << j); } //TODO: extend to arbitrary length outbits. currently capped to 64 outbits @@ -1119,9 +1131,8 @@ void SetupLUT::SenderEvaluateTTGates() { */ void SetupLUT::ReceiverEvaluateTTGates() { uint32_t len, choicelen; - uint64_t tmp_mask, tmp_choice, tmp_rcv; + uint64_t tmp_choice, tmp_rcv; uint32_t typebitlen = sizeof(uint64_t) * 8; - GATE* ingate; timespec t_start, t_end; clock_gettime(CLOCK_MONOTONIC, &t_start); @@ -1134,7 +1145,7 @@ void SetupLUT::ReceiverEvaluateTTGates() { std::vector rcvbufaddr(m_vOutBitMapping[i].size(), 0); for(uint32_t g = 0; g < m_vTTGates[i].size(); g++) { - GATE* gate = m_pGates + m_vTTGates[i][g]; + GATE* gate = &(m_vGates[m_vTTGates[i][g]]); uint32_t* input = gate->ingates.inputs.parents; uint32_t nparents = gate->ingates.ningates; @@ -1211,7 +1222,7 @@ void SetupLUT::ReceiverEvaluateTTGates() { void SetupLUT::AssignInputShares() { GATE* gate; for (uint32_t i = 0, j, rcvshareidx = 0, bitstocopy, len; i < m_vInputShareGates.size(); i++) { - gate = m_pGates + m_vInputShareGates[i]; + gate = &(m_vGates[m_vInputShareGates[i]]); InstantiateGate(gate); bitstocopy = gate->nvals; @@ -1229,16 +1240,16 @@ void SetupLUT::AssignInputShares() { void SetupLUT::AssignOutputShares() { GATE* gate; for (uint32_t i = 0, j, rcvshareidx = 0, bitstocopy, len, parentid; i < m_vOutputShareGates.size(); i++) { - gate = m_pGates + m_vOutputShareGates[i]; + gate = &(m_vGates[m_vOutputShareGates[i]]); parentid = gate->ingates.inputs.parent; InstantiateGate(gate); bitstocopy = gate->nvals; for (j = 0; j < ceil_divide(gate->nvals, GATE_T_BITS); j++, bitstocopy -= GATE_T_BITS) { len = std::min(bitstocopy, (uint32_t) GATE_T_BITS); - gate->gs.val[j] = m_pGates[parentid].gs.val[j] ^ m_vOutputShareRcvBuf.Get(rcvshareidx, len); + gate->gs.val[j] = m_vGates[parentid].gs.val[j] ^ m_vOutputShareRcvBuf.Get(rcvshareidx, len); #ifdef DEBUG_SPLUT - std::cout << "Outshare: " << (hex) << gate->gs.val[j] << " = " << m_pGates[parentid].gs.val[j] << " (mine) ^ " << + std::cout << "Outshare: " << (hex) << gate->gs.val[j] << " = " << m_vGates[parentid].gs.val[j] << " (mine) ^ " << m_vOutputShareRcvBuf.Get(rcvshareidx, len) << " (others)" << (dec) << std::endl; #endif rcvshareidx += len; @@ -1442,7 +1453,7 @@ inline void SetupLUT::InstantiateGate(GATE* gate) { } void SetupLUT::EvaluateSIMDGate(uint32_t gateid) { - GATE* gate = m_pGates + gateid; + GATE* gate = &(m_vGates[gateid]); uint32_t vsize = gate->nvals; #ifdef BENCHBOOLTIME @@ -1462,10 +1473,10 @@ void SetupLUT::EvaluateSIMDGate(uint32_t gateid) { tmp.AttachBuf((uint8_t*) gate->gs.val, (int) ceil_divide(vsize, 8)); - for(uint64_t i = 0, bit_ctr = 0, ctr=0; i < nparents; i++) { - uint64_t in_size = m_pGates[input[i]].nvals; + for(uint64_t i = 0, bit_ctr = 0; i < nparents; i++) { + uint64_t in_size = m_vGates[input[i]].nvals; - tmp.SetBits((uint8_t*) m_pGates[input[i]].gs.val, bit_ctr, in_size); + tmp.SetBits((uint8_t*) m_vGates[input[i]].gs.val, bit_ctr, in_size); bit_ctr += in_size; } @@ -1485,7 +1496,7 @@ void SetupLUT::EvaluateSIMDGate(uint32_t gateid) { InstantiateGate(gate); //TODO: optimize for (uint32_t i = 0; i < vsize; i++) { - gate->gs.val[i / GATE_T_BITS] |= ((m_pGates[idparent].gs.val[(pos + i) / GATE_T_BITS] >> ((pos + i) % GATE_T_BITS)) & 0x1) << (i % GATE_T_BITS); + gate->gs.val[i / GATE_T_BITS] |= ((m_vGates[idparent].gs.val[(pos + i) / GATE_T_BITS] >> ((pos + i) % GATE_T_BITS)) & 0x1) << (i % GATE_T_BITS); } UsedGate(idparent); } else if (gate->type == G_REPEAT) //TODO only meant for single bit values, update @@ -1496,7 +1507,7 @@ void SetupLUT::EvaluateSIMDGate(uint32_t gateid) { uint32_t idparent = gate->ingates.inputs.parent; InstantiateGate(gate); - BYTE byte_val = m_pGates[idparent].gs.val[0] ? MAX_BYTE : ZERO_BYTE; + BYTE byte_val = m_vGates[idparent].gs.val[0] ? MAX_BYTE : ZERO_BYTE; memset(gate->gs.val, byte_val, sizeof(UGATE_T) * ceil_divide(vsize, GATE_T_BITS)); UsedGate(idparent); } else if (gate->type == G_PERM) { @@ -1514,7 +1525,7 @@ void SetupLUT::EvaluateSIMDGate(uint32_t gateid) { //TODO: Optimize for (uint32_t i = 0; i < vsize; i++) { - gate->gs.val[i / GATE_T_BITS] |= (((m_pGates[inputs[i]].gs.val[posids[i] / GATE_T_BITS] >> (posids[i] % GATE_T_BITS)) & 0x1) << (i % GATE_T_BITS)); + gate->gs.val[i / GATE_T_BITS] |= (((m_vGates[inputs[i]].gs.val[posids[i] / GATE_T_BITS] >> (posids[i] % GATE_T_BITS)) & 0x1) << (i % GATE_T_BITS)); UsedGate(inputs[i]); } free(inputs); @@ -1532,7 +1543,7 @@ void SetupLUT::EvaluateSIMDGate(uint32_t gateid) { //TODO: Optimize for (uint32_t i = 0; i < vsize; i++) { uint32_t idparent = combinepos[i]; - gate->gs.val[i / GATE_T_BITS] |= (((m_pGates[idparent].gs.val[arraypos] >> bitpos) & 0x1) << (i % GATE_T_BITS)); + gate->gs.val[i / GATE_T_BITS] |= (((m_vGates[idparent].gs.val[arraypos] >> bitpos) & 0x1) << (i % GATE_T_BITS)); UsedGate(idparent); } free(combinepos); @@ -1547,11 +1558,11 @@ void SetupLUT::EvaluateSIMDGate(uint32_t gateid) { uint32_t bitpos; InstantiateGate(gate); memset(gate->gs.val, 0x00, ceil_divide(vsize, 8)); - UGATE_T* valptr = m_pGates[idparent].gs.val; + UGATE_T* valptr = m_vGates[idparent].gs.val; for (uint32_t i = 0; i < vsize; i++) { //arraypos = positions[i] / GATE_T_BITS; //bitpos = positions[i] % GATE_T_BITS; - //gate->gs.val[i / GATE_T_BITS] |= (((m_pGates[idparent].gs.val[arraypos] >> bitpos) & 0x1) << (i % GATE_T_BITS)); + //gate->gs.val[i / GATE_T_BITS] |= (((m_vGates[idparent].gs.val[arraypos] >> bitpos) & 0x1) << (i % GATE_T_BITS)); arraypos = positions[i] >> 6; bitpos = positions[i] & 0x3F; gate->gs.val[i >> 6] |= (((valptr[arraypos] >> bitpos) & 0x1) << (i & 0x3F)); @@ -1584,13 +1595,13 @@ void SetupLUT::EvaluateSIMDGate(uint32_t gateid) { p_tmp_idx = pos_ctr / GATE_T_BITS; p_tmp_pos = pos_ctr % GATE_T_BITS; for(uint32_t in_ctr = 0; in_ctrgs.val[ctr / GATE_T_BITS] |= (((m_pGates[inputs[in_ctr]].gs.val[p_tmp_idx] >> p_tmp_pos) & 0x1) << (ctr % GATE_T_BITS)); - //gate->gs.val[ctr / GATE_T_BITS] |= (((m_pGates[inputs[in_ctr]].gs.val[pos_ctr / GATE_T_BITS] >> (pos_ctr % GATE_T_BITS)) & 0x1) << (ctr % GATE_T_BITS)); + gate->gs.val[ctr / GATE_T_BITS] |= (((m_vGates[inputs[in_ctr]].gs.val[p_tmp_idx] >> p_tmp_pos) & 0x1) << (ctr % GATE_T_BITS)); + //gate->gs.val[ctr / GATE_T_BITS] |= (((m_vGates[inputs[in_ctr]].gs.val[pos_ctr / GATE_T_BITS] >> (pos_ctr % GATE_T_BITS)) & 0x1) << (ctr % GATE_T_BITS)); } } //for (uint32_t i = 0, in_ctr=0, pos_ctr=pos_start; i < vsize; i++, in_ctr=(in_ctr+1)%ninputs, pos_ctr+=pos_incr ) { - // gate->gs.val[i / GATE_T_BITS] |= (((m_pGates[inputs[in_ctr]].gs.val[pos_ctr / GATE_T_BITS] >> (pos_ctr % GATE_T_BITS)) & 0x1) << (i % GATE_T_BITS)); + // gate->gs.val[i / GATE_T_BITS] |= (((m_vGates[inputs[in_ctr]].gs.val[pos_ctr / GATE_T_BITS] >> (pos_ctr % GATE_T_BITS)) & 0x1) << (i % GATE_T_BITS)); //} for(uint32_t i = 0; i < ninputs; i++) { @@ -1620,7 +1631,7 @@ uint32_t SetupLUT::AssignInput(CBitVector& inputvals) { GATE* gate; uint32_t inbits = 0; for (uint32_t i = 0, inbitstart = 0, bitstocopy, len, lim; i < myingates.size(); i++) { - gate = m_pGates + myingates[i]; + gate = &(m_vGates[myingates[i]]); if (!gate->instantiated) { bitstocopy = gate->nvals * gate->sharebitlen; inbits += bitstocopy; @@ -1645,8 +1656,8 @@ uint32_t SetupLUT::GetOutput(CBitVector& out) { out.Create(outbits); GATE* gate; - for (uint32_t i = 0, outbitstart = 0, bitstocopy, len, lim; i < myoutgates.size(); i++) { - gate = m_pGates + myoutgates[i]; + for (uint32_t i = 0, outbitstart = 0, lim; i < myoutgates.size(); i++) { + gate = &(m_vGates[myoutgates[i]]); lim = gate->nvals * gate->sharebitlen; for (uint32_t j = 0; j < lim; j++, outbitstart++) { @@ -1703,7 +1714,7 @@ void SetupLUT::Reset() { //Delete the pre-computed OT values for (uint32_t i = 0; i < m_vPreCompOTX.size(); i++) { for(uint32_t k = 0; k < m_vPreCompOTX[i].size(); k++) { - for(uint32_t j = 0; j < (1<. + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Implementation of the SP-LUT protocol */ @@ -60,7 +60,7 @@ class SetupLUT: public Sharing { public: /** Constructor of the class.*/ - SetupLUT(e_sharing context, e_role role, uint32_t sharebitlen, ABYCircuit* circuit, crypto* crypt); + SetupLUT(e_sharing context, e_role role, uint32_t sharebitlen, ABYCircuit* circuit, crypto* crypt, const std::string& circdir = ABY_CIRCUIT_DIR); /** Destructor of the class.*/ virtual ~SetupLUT(); @@ -72,7 +72,7 @@ class SetupLUT: public Sharing { void EvaluateLocalOperations(uint32_t level); void EvaluateInteractiveOperations(uint32_t level); - void FinishCircuitLayer(uint32_t level); + void FinishCircuitLayer(); void PrepareOnlinePhase(); diff --git a/src/abycore/sharing/yaoclientsharing.cpp b/src/abycore/sharing/yaoclientsharing.cpp index 77344c7a..df8d4643 100644 --- a/src/abycore/sharing/yaoclientsharing.cpp +++ b/src/abycore/sharing/yaoclientsharing.cpp @@ -2,17 +2,17 @@ \file yaoclientsharing.cpp \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Yao Client Sharing class implementation. */ #include "yaoclientsharing.h" @@ -167,7 +167,7 @@ void YaoClientSharing::EvaluateLocalOperations(uint32_t depth) { //std::cout << "In total I have " << localops.size() << " local operations to evaluate on this level " << std::endl; for (uint32_t i = 0; i < localops.size(); i++) { - GATE* gate = m_pGates + localops[i]; + GATE* gate = &(m_vGates[localops[i]]); //std::cout << "Evaluating gate " << localops[i] << " with context = " << gate->context << std::endl; if (gate->type == G_LIN) { EvaluateXORGate(gate); @@ -183,10 +183,10 @@ void YaoClientSharing::EvaluateLocalOperations(uint32_t depth) { //only copy values, SERVER did the inversion uint32_t parentid = gate->ingates.inputs.parent; // gate->gs.invinput; InstantiateGate(gate); - memcpy(gate->gs.yval, m_pGates[parentid].gs.yval, m_nSecParamBytes * gate->nvals); + memcpy(gate->gs.yval, m_vGates[parentid].gs.yval, m_nSecParamBytes * gate->nvals); UsedGate(parentid); } else if (gate->type == G_SHARED_OUT) { - GATE* parent = m_pGates + gate->ingates.inputs.parent; + GATE* parent = &(m_vGates[gate->ingates.inputs.parent]); InstantiateGate(gate); memcpy(gate->gs.yval, parent->gs.yval, gate->nvals * m_nSecParamBytes); UsedGate(gate->ingates.inputs.parent); @@ -201,7 +201,7 @@ void YaoClientSharing::EvaluateLocalOperations(uint32_t depth) { } else if(gate->type == G_ASSERT) { EvaluateAssertGate(localops[i], C_BOOLEAN); } else if (gate->type == G_UNIV) { - //cout << "Client: Evaluating Universal Circuit gate" << endl; + //cout << "Client: Evaluating Universal Circuit gate" << std::endl; EvaluateUNIVGate(gate); } else { std::cerr << "YaoClientSharing: Non-interactive operation not recognized: " << @@ -216,7 +216,7 @@ void YaoClientSharing::EvaluateInteractiveOperations(uint32_t depth) { //std::cout << "In total I have " << localops.size() << " local operations to evaluate on this level " << std::endl; for (uint32_t i = 0; i < interactiveops.size(); i++) { - GATE* gate = m_pGates + interactiveops[i]; + GATE* gate = &(m_vGates[interactiveops[i]]); #ifdef DEBUGYAOCLIENT std::cout << "Evaluating interactive operation in Yao client sharing with type = " << get_gate_type_name(gate->type) << std::endl; #endif @@ -231,7 +231,7 @@ void YaoClientSharing::EvaluateInteractiveOperations(uint32_t depth) { } else if (gate->type == G_OUT) { #ifdef DEBUGYAOCLIENT std::cout << "Obtained output gate with key = "; - PrintKey(m_pGates[gate->ingates.inputs.parent].gs.yval); + PrintKey(m_vGates[gate->ingates.inputs.parent].gs.yval); std::cout << std::endl; #endif if (gate->gs.oshare.dst == SERVER) { @@ -263,22 +263,22 @@ void YaoClientSharing::EvaluateXORGate(GATE* gate) { uint32_t idright = gate->ingates.inputs.twin.right; //gate->gs.ginput.right; InstantiateGate(gate); - //TODO: optimize for UINT64_T pointers, there might be some problems here, code is untested + //TODO: optimize for uint64_t pointers, there might be some problems here, code is untested /*for(uint32_t i = 0; i < m_nSecParamBytes * nvals; i++) { - gate->gs.yval[i] = m_pGates[idleft].gs.yval[i] ^ m_pGates[idright].gs.yval[i]; + gate->gs.yval[i] = m_vGates[idleft].gs.yval[i] ^ m_vGates[idright].gs.yval[i]; }*/ //std::cout << "doing " << m_nSecParamIters << "iters on " << nvals << " vals " << std::endl; for (uint32_t i = 0; i < m_nSecParamIters * nvals; i++) { - ((UGATE_T*) gate->gs.yval)[i] = ((UGATE_T*) m_pGates[idleft].gs.yval)[i] ^ ((UGATE_T*) m_pGates[idright].gs.yval)[i]; + ((UGATE_T*) gate->gs.yval)[i] = ((UGATE_T*) m_vGates[idleft].gs.yval)[i] ^ ((UGATE_T*) m_vGates[idright].gs.yval)[i]; } //std::cout << "Keyval (" << 0 << ")= " << (gate->gs.yval[m_nSecParamBytes-1] & 0x01) << std::endl; //std::cout << (gate->gs.yval[m_nSecParamBytes-1] & 0x01); #ifdef DEBUGYAOCLIENT PrintKey(gate->gs.yval); std::cout << " = "; - PrintKey(m_pGates[idleft].gs.yval); + PrintKey(m_vGates[idleft].gs.yval); std::cout << " (" << idleft << ") ^ "; - PrintKey(m_pGates[idright].gs.yval); + PrintKey(m_vGates[idright].gs.yval); std::cout << " (" << idright << ")" << std::endl; #endif @@ -289,8 +289,8 @@ void YaoClientSharing::EvaluateXORGate(GATE* gate) { void YaoClientSharing::EvaluateANDGate(GATE* gate) { uint32_t idleft = gate->ingates.inputs.twin.left; //gate->gs.ginput.left; uint32_t idright = gate->ingates.inputs.twin.right; //gate->gs.ginput.right; - GATE* gleft = m_pGates + idleft; - GATE* gright = m_pGates + idright; + GATE* gleft = &(m_vGates[idleft]); + GATE* gright = &(m_vGates[idright]); //evaluate garbled table InstantiateGate(gate); @@ -366,8 +366,8 @@ BOOL YaoClientSharing::EvaluateGarbledTable(GATE* gate, uint32_t pos, GATE* glef void YaoClientSharing::EvaluateUNIVGate(GATE* gate) { uint32_t idleft = gate->ingates.inputs.twin.left; //gate->gs.ginput.left; uint32_t idright = gate->ingates.inputs.twin.right; //gate->gs.ginput.right; - GATE* gleft = m_pGates + idleft; - GATE* gright = m_pGates + idright; + GATE* gleft = &(m_vGates[idleft]); + GATE* gright = &(m_vGates[idright]); //evaluate univeral gate table InstantiateGate(gate); @@ -395,25 +395,25 @@ BOOL YaoClientSharing::EvaluateUniversalGate(GATE* gate, uint32_t pos, GATE* gle if(id == 0) { EncryptWireGRR3(okey, m_bZeroBuf, lkey, rkey, id); #ifdef DEBUGYAOCLIENT - cout << " decrypted : "; + std::cout << " decrypted : "; PrintKey(m_bZeroBuf); #endif } else { #ifdef DEBUGYAOCLIENT - cout << " decrypted : "; + std::cout << " decrypted : "; PrintKey(m_vUniversalGateTable.GetArr() + m_nSecParamBytes * (KEYS_PER_UNIV_GATE_IN_TABLE * m_nUniversalGateTableCtr + id-1)); #endif EncryptWireGRR3(okey, m_vUniversalGateTable.GetArr() + m_nSecParamBytes * (KEYS_PER_UNIV_GATE_IN_TABLE * m_nUniversalGateTableCtr + id-1), lkey, rkey, id); } #ifdef DEBUGYAOCLIENT - cout << " using: "; + std::cout << " using: "; PrintKey(lkey); - cout << " and : "; + std::cout << " and : "; PrintKey(rkey); - cout << " to : "; + std::cout << " to : "; PrintKey(okey); - cout << endl; + std::cout << std::endl; #endif return true; @@ -421,17 +421,19 @@ BOOL YaoClientSharing::EvaluateUniversalGate(GATE* gate, uint32_t pos, GATE* gle /* Evaluate the gate and use the servers output permutation bits to compute the output */ void YaoClientSharing::EvaluateClientOutputGate(uint32_t gateid) { - GATE* gate = m_pGates + gateid; + GATE* gate = &(m_vGates[gateid]); uint32_t parentid = gate->ingates.inputs.parent; //gate->gs.oshare.parentgate; - uint32_t in; InstantiateGate(gate); #ifdef DEBUGYAOCLIENT + uint32_t in; std::cout << "ClientOutput: "; #endif for (uint32_t i = 0; i < gate->nvals; i++) { - in = (m_pGates[parentid].gs.yval[(i + 1) * m_nSecParamBytes - 1] & 0x01); - gate->gs.val[i / GATE_T_BITS] ^= ((((UGATE_T) m_pGates[parentid].gs.yval[(i + 1) * m_nSecParamBytes - 1] & 0x01) +#ifdef DEBUGYAOCLIENT + in = (m_vGates[parentid].gs.yval[(i + 1) * m_nSecParamBytes - 1] & 0x01); +#endif + gate->gs.val[i / GATE_T_BITS] ^= ((((UGATE_T) m_vGates[parentid].gs.yval[(i + 1) * m_nSecParamBytes - 1] & 0x01) ^ ((UGATE_T) m_vOutputShareRcvBuf.GetBit(m_nClientOUTBitCtr))) << (i % GATE_T_BITS)); #ifdef DEBUGYAOCLIENT std::cout << (uint32_t) gate->gs.val[i/GATE_T_BITS] << " = " << in << " ^ " << (uint32_t) m_vOutputShareRcvBuf.GetBit(m_nClientOUTBitCtr) << std::endl; @@ -447,9 +449,9 @@ void YaoClientSharing::EvaluateServerOutputGate(GATE* gate) { uint32_t parentid = gate->ingates.inputs.parent; //gate->gs.oshare.parentgate; for (uint32_t i = 0; i < gate->nvals; i++, m_nServerOutputShareCtr++) { - m_vOutputShareSndBuf.SetBit(m_nServerOutputShareCtr, m_pGates[parentid].gs.yval[((i + 1) * m_nSecParamBytes) - 1] & 0x01); + m_vOutputShareSndBuf.SetBit(m_nServerOutputShareCtr, m_vGates[parentid].gs.yval[((i + 1) * m_nSecParamBytes) - 1] & 0x01); #ifdef DEBUGYAOCLIENT - std::cout << "Setting ServerOutputShare to " << ((uint32_t) m_pGates[parentid].gs.yval[((i+1)*m_nSecParamBytes) - 1] & 0x01) << std::endl; + std::cout << "Setting ServerOutputShare to " << ((uint32_t) m_vGates[parentid].gs.yval[((i+1)*m_nSecParamBytes) - 1] & 0x01) << std::endl; #endif } @@ -459,7 +461,7 @@ void YaoClientSharing::EvaluateServerOutputGate(GATE* gate) { /* Store the input bits of my gates to send the correlation with the R-OTs later on */ void YaoClientSharing::ReceiveClientKeys(uint32_t gateid) { - GATE* gate = m_pGates + gateid; + GATE* gate = &(m_vGates[gateid]); UGATE_T* input = gate->gs.ishare.inval; m_vROTSndBuf.SetBits((BYTE*) input, (int) m_nClientSndOTCtr, gate->nvals); m_nClientSndOTCtr += gate->nvals; @@ -468,15 +470,15 @@ void YaoClientSharing::ReceiveClientKeys(uint32_t gateid) { /* Add the servers input keys to the queue to receive them later on */ void YaoClientSharing::ReceiveServerKeys(uint32_t gateid) { - GATE* gate = m_pGates + gateid; + GATE* gate = &(m_vGates[gateid]); m_vServerInputGates.push_back(gateid); m_nServerInBitCtr += gate->nvals; } void YaoClientSharing::EvaluateConversionGate(uint32_t gateid) { - GATE* gate = m_pGates + gateid; - GATE* parent = m_pGates + gate->ingates.inputs.parents[0]; + GATE* gate = &(m_vGates[gateid]); + GATE* parent = &(m_vGates[gate->ingates.inputs.parents[0]]); assert(parent->instantiated); UGATE_T* val = parent->gs.val; @@ -588,7 +590,7 @@ void YaoClientSharing::GetBuffersToReceive(std::vector& rcvbuf, std::vect } } -void YaoClientSharing::FinishCircuitLayer(uint32_t level) { +void YaoClientSharing::FinishCircuitLayer() { //Assign the servers input keys that were received this round if (m_nServerInBitCtr > 0) AssignServerInputKeys(); @@ -617,7 +619,7 @@ void YaoClientSharing::FinishCircuitLayer(uint32_t level) { void YaoClientSharing::AssignServerInputKeys() { GATE* gate; for (uint32_t i = 0, offset = 0; i < m_vServerInputGates.size(); i++) { - gate = m_pGates + m_vServerInputGates[i]; + gate = &(m_vGates[m_vServerInputGates[i]]); InstantiateGate(gate); //Assign the keys to the gate memcpy(gate->gs.yval, m_vServerInputKeys.GetArr() + offset, m_nSecParamBytes * gate->nvals); @@ -635,9 +637,9 @@ void YaoClientSharing::AssignServerInputKeys() { /* Assign the received server input keys to the pushed back gates in this round */ void YaoClientSharing::AssignClientInputKeys() { - GATE* gate, *parent; + GATE* gate; for (uint32_t i = 0, offset = 0; i < m_vClientRcvInputKeyGates.size(); i++) { - gate = m_pGates + m_vClientRcvInputKeyGates[i]; + gate = &(m_vGates[m_vClientRcvInputKeyGates[i]]); //input = ; InstantiateGate(gate); @@ -675,7 +677,7 @@ void YaoClientSharing::InstantiateGate(GATE* gate) { } void YaoClientSharing::EvaluateSIMDGate(uint32_t gateid) { - GATE* gate = m_pGates + gateid; + GATE* gate = &(m_vGates[gateid]); if (gate->type == G_COMBINE) { uint32_t* inptr = gate->ingates.inputs.parents; //gate->gs.cinput; uint32_t nparents = gate->ingates.ningates; @@ -684,8 +686,8 @@ void YaoClientSharing::EvaluateSIMDGate(uint32_t gateid) { InstantiateGate(gate); BYTE* keyptr = gate->gs.yval; for (uint32_t g = 0; g < nparents; g++) { - parent_nvals = m_pGates[inptr[g]].nvals; - memcpy(keyptr, m_pGates[inptr[g]].gs.yval, m_nSecParamBytes * parent_nvals); + parent_nvals = m_vGates[inptr[g]].nvals; + memcpy(keyptr, m_vGates[inptr[g]].gs.yval, m_nSecParamBytes * parent_nvals); keyptr += m_nSecParamBytes * parent_nvals; UsedGate(inptr[g]); } @@ -694,14 +696,14 @@ void YaoClientSharing::EvaluateSIMDGate(uint32_t gateid) { uint32_t pos = gate->gs.sinput.pos; uint32_t idleft = gate->ingates.inputs.parent; // gate->gs.sinput.input; InstantiateGate(gate); - memcpy(gate->gs.yval, m_pGates[idleft].gs.yval + pos * m_nSecParamBytes, m_nSecParamBytes * gate->nvals); + memcpy(gate->gs.yval, m_vGates[idleft].gs.yval + pos * m_nSecParamBytes, m_nSecParamBytes * gate->nvals); UsedGate(idleft); } else if (gate->type == G_REPEAT) { uint32_t idleft = gate->ingates.inputs.parent; //gate->gs.rinput; InstantiateGate(gate); BYTE* keyptr = gate->gs.yval; for (uint32_t g = 0; g < gate->nvals; g++, keyptr += m_nSecParamBytes) { - memcpy(keyptr, m_pGates[idleft].gs.yval, m_nSecParamBytes); + memcpy(keyptr, m_vGates[idleft].gs.yval, m_nSecParamBytes); } UsedGate(idleft); } else if (gate->type == G_COMBINEPOS) { @@ -711,7 +713,7 @@ void YaoClientSharing::EvaluateSIMDGate(uint32_t gateid) { BYTE* keyptr = gate->gs.yval; for (uint32_t g = 0; g < gate->nvals; g++, keyptr += m_nSecParamBytes) { uint32_t idleft = combinepos[g]; - memcpy(keyptr, m_pGates[idleft].gs.yval + pos * m_nSecParamBytes, m_nSecParamBytes); + memcpy(keyptr, m_vGates[idleft].gs.yval + pos * m_nSecParamBytes, m_nSecParamBytes); UsedGate(idleft); } free(combinepos); @@ -729,7 +731,7 @@ void YaoClientSharing::EvaluateSIMDGate(uint32_t gateid) { InstantiateGate(gate); BYTE* keyptr = gate->gs.yval; for (uint32_t g = 0; g < gate->nvals; g++, keyptr += m_nSecParamBytes) { - memcpy(keyptr, m_pGates[idparent].gs.yval + positions[g] * m_nSecParamBytes, m_nSecParamBytes); + memcpy(keyptr, m_vGates[idparent].gs.yval + positions[g] * m_nSecParamBytes, m_nSecParamBytes); } UsedGate(idparent); if(del_pos) @@ -744,7 +746,7 @@ uint32_t YaoClientSharing::AssignInput(CBitVector& inputvals) { GATE* gate; uint32_t inbits = 0; for (uint32_t i = 0, inbitstart = 0, bitstocopy, len, lim; i < myingates.size(); i++) { - gate = m_pGates + myingates[i]; + gate = &(m_vGates[myingates[i]]); if (!gate->instantiated) { bitstocopy = gate->nvals * gate->sharebitlen; inbits += bitstocopy; @@ -769,8 +771,8 @@ uint32_t YaoClientSharing::GetOutput(CBitVector& out) { out.Create(outbits); GATE* gate; - for (uint32_t i = 0, outbitstart = 0, bitstocopy, len, lim; i < myoutgates.size(); i++) { - gate = m_pGates + myoutgates[i]; + for (uint32_t i = 0, outbitstart = 0, lim; i < myoutgates.size(); i++) { + gate = &(m_vGates[myoutgates[i]]); lim = gate->nvals * gate->sharebitlen; std::cout << "outgate no " << i << " : " << myoutgates[i] << " with nvals = " << gate->nvals << " and sharebitlen = " << gate->sharebitlen << std::endl; diff --git a/src/abycore/sharing/yaoclientsharing.h b/src/abycore/sharing/yaoclientsharing.h index 1c05e1c7..4b775629 100644 --- a/src/abycore/sharing/yaoclientsharing.h +++ b/src/abycore/sharing/yaoclientsharing.h @@ -2,17 +2,17 @@ \file yaoclientsharing.h \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Yao Client Sharing class. */ #ifndef __YAOCLIENTSHARING_H__ @@ -31,8 +31,8 @@ class YaoClientSharing: public YaoSharing { public: /** Constructor of the class.*/ - YaoClientSharing(e_sharing context, e_role role, uint32_t sharebitlen, ABYCircuit* circuit, crypto* crypt) : - YaoSharing(context, role, sharebitlen, circuit, crypt) { + YaoClientSharing(e_sharing context, e_role role, uint32_t sharebitlen, ABYCircuit* circuit, crypto* crypt, const std::string& circdir = ABY_CIRCUIT_DIR) : + YaoSharing(context, role, sharebitlen, circuit, crypt, circdir) { InitClient(); } ; @@ -48,7 +48,7 @@ class YaoClientSharing: public YaoSharing { void EvaluateInteractiveOperations(uint32_t gateid); void EvaluateConversionGate(uint32_t gateid); - void FinishCircuitLayer(uint32_t level); + void FinishCircuitLayer(); void PrepareOnlinePhase(); @@ -152,7 +152,7 @@ class YaoClientSharing: public YaoSharing { \param gleft left gate in the queue. \param gright right gate in the queue. */ - BOOL EvaluateUniversalGate(GATE* gate, uint32_t pos, GATE* gleft, GATE* gright); + BOOL EvaluateUniversalGate(GATE* gate, uint32_t pos, GATE* gleft, GATE* gright); /** Method for server output Gate for the inputted Gate. \param gate Gate Object diff --git a/src/abycore/sharing/yaoserversharing.cpp b/src/abycore/sharing/yaoserversharing.cpp index 861c7c2a..26ea0642 100644 --- a/src/abycore/sharing/yaoserversharing.cpp +++ b/src/abycore/sharing/yaoserversharing.cpp @@ -2,17 +2,17 @@ \file yaoserversharing.cpp \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Yao Server Sharing class implementation. */ @@ -173,24 +173,24 @@ void YaoServerSharing::FinishSetupPhase(ABYSetup* setup) { //TODO: Change execution std::deque insrvgates = m_cBoolCircuit->GetInputGatesForParty(SERVER); for (uint32_t i = 0; i < insrvgates.size(); i++) { - m_pGates[insrvgates[i]].gs.ishare.src = SERVER; + m_vGates[insrvgates[i]].gs.ishare.src = SERVER; } //Set pre-initialized input values that were instantiated before the setup phase for (uint32_t i = 0; i < m_vPreSetInputGates.size(); i++) { - m_pGates[m_vPreSetInputGates[i].gateid].gs.ishare.inval = m_vPreSetInputGates[i].inval; + m_vGates[m_vPreSetInputGates[i].gateid].gs.ishare.inval = m_vPreSetInputGates[i].inval; } m_vPreSetInputGates.clear(); //Set pre-initialized input values that were instantiated before the setup phase for (uint32_t i = 0; i < m_vPreSetA2YPositions.size(); i++) { - m_pGates[m_vPreSetA2YPositions[i].gateid].gs.pos = m_vPreSetA2YPositions[i].pos; + m_vGates[m_vPreSetA2YPositions[i].gateid].gs.pos = m_vPreSetA2YPositions[i].pos; } m_vPreSetA2YPositions.clear(); std::deque incligates = m_cBoolCircuit->GetInputGatesForParty(CLIENT); for (uint32_t i = 0; i < incligates.size(); i++) { - m_pGates[incligates[i]].gs.ishare.src = CLIENT; + m_vGates[incligates[i]].gs.ishare.src = CLIENT; } @@ -207,7 +207,7 @@ void YaoServerSharing::EvaluateLocalOperations(uint32_t depth) { std::deque localqueue = m_cBoolCircuit->GetLocalQueueOnLvl(depth); GATE* gate; for (uint32_t i = 0; i < localqueue.size(); i++) { - gate = m_pGates + localqueue[i]; + gate = &(m_vGates[localqueue[i]]); if(gate->type == G_PRINT_VAL) { EvaluatePrintValGate(localqueue[i], C_BOOLEAN); } else if(gate->type == G_ASSERT) { @@ -221,10 +221,9 @@ void YaoServerSharing::EvaluateLocalOperations(uint32_t depth) { void YaoServerSharing::EvaluateInteractiveOperations(uint32_t depth) { std::deque interactivequeue = m_cBoolCircuit->GetInteractiveQueueOnLvl(depth); GATE *gate, *parent; - e_role dst; for (uint32_t i = 0; i < interactivequeue.size(); i++) { - gate = m_pGates + interactivequeue[i]; + gate = &(m_vGates[interactivequeue[i]]); #ifdef DEBUGYAOSERVER std::cout << "Evaluating gate with id = " << interactivequeue[i] << ", and type = "<< get_gate_type_name(gate->type) << ", and depth = " << gate->depth << std::endl; #endif @@ -246,7 +245,7 @@ void YaoServerSharing::EvaluateInteractiveOperations(uint32_t depth) { //else do nothing since the client has already been given the output break; case G_CONV: - parent = m_pGates + gate->ingates.inputs.parents[0]; + parent = &(m_vGates[gate->ingates.inputs.parents[0]]); if (parent->context == S_ARITH) { SendConversionValues(interactivequeue[i]); } else if(parent->context == S_BOOL || parent->context == S_YAO || parent->context == S_YAO_REV) { @@ -265,8 +264,8 @@ void YaoServerSharing::EvaluateInteractiveOperations(uint32_t depth) { } void YaoServerSharing::SendConversionValues(uint32_t gateid) { - GATE* gate = m_pGates + gateid; - GATE* parent = m_pGates + gate->ingates.inputs.parents[0]; + GATE* gate = &(m_vGates[gateid]); + GATE* parent = &(m_vGates[gate->ingates.inputs.parents[0]]); uint32_t pos = gate->gs.pos; uint32_t id = pos >> 1; @@ -300,7 +299,7 @@ void YaoServerSharing::SendConversionValues(uint32_t gateid) { } void YaoServerSharing::SendServerInputKey(uint32_t gateid) { - GATE* gate = m_pGates + gateid; + GATE* gate = &(m_vGates[gateid]); UGATE_T* input = gate->gs.ishare.inval; for (uint32_t i = 0; i < gate->nvals; i++, m_nServerKeyCtr++, m_nPermBitCtr++) { @@ -317,7 +316,7 @@ void YaoServerSharing::SendServerInputKey(uint32_t gateid) { void YaoServerSharing::SendClientInputKey(uint32_t gateid) { //push back and wait for bit of client - GATE* gate = m_pGates + gateid; + GATE* gate = &(m_vGates[gateid]); m_nClientInBitCtr += gate->nvals; m_vClientInputGate.push_back(gateid); } @@ -366,7 +365,7 @@ void YaoServerSharing::CreateAndSendGarbledCircuit(ABYSetup* setup) { void YaoServerSharing::PrecomputeGC(std::deque& queue, ABYSetup* setup) { for (uint32_t i = 0; i < queue.size(); i++) { - GATE* gate = m_pGates + queue[i]; + GATE* gate = &(m_vGates[queue[i]]); #ifdef DEBUGYAOSERVER std::cout << "Evaluating gate with id = " << queue[i] << ", and type = "<< get_gate_type_name(gate->type) << "(" << gate->type << "), depth = " << gate->depth << ", nvals = " << gate->nvals << ", sharebitlen = " << gate->sharebitlen << std::endl; @@ -383,8 +382,8 @@ void YaoServerSharing::PrecomputeGC(std::deque& queue, ABYSetup* setup #ifdef DEBUGYAOSERVER std::cout << "Obtained output gate with key = "; uint32_t parentid = gate->ingates.inputs.parent; - PrintKey(m_pGates[parentid].gs.yinput.outKey); - std::cout << " and pi = " << (uint32_t) m_pGates[parentid].gs.yinput.pi[0] << std::endl; + PrintKey(m_vGates[parentid].gs.yinput.outKey); + std::cout << " and pi = " << (uint32_t) m_vGates[parentid].gs.yinput.pi[0] << std::endl; #endif EvaluateOutputGate(gate); } else if (gate->type == G_CONV) { @@ -393,13 +392,7 @@ void YaoServerSharing::PrecomputeGC(std::deque& queue, ABYSetup* setup #endif EvaluateConversionGate(queue[i]); } else if (gate->type == G_CONSTANT) { - //assign 0 and 1 gates - UGATE_T constval = gate->gs.constval; - InstantiateGate(gate); - memset(gate->gs.yinput.outKey, 0, m_nSecParamBytes * gate->nvals); - for(uint32_t i = 0; i < gate->nvals; i++) { - gate->gs.yinput.pi[i] = (constval>>i) & 0x01; - } + EvaluateConstantGate(gate); #ifdef DEBUGYAOSERVER std::cout << "Assigned key to constant gate " << queue[i] << " (" << (uint32_t) gate->gs.yinput.pi[0] << ") : "; PrintKey(gate->gs.yinput.outKey); @@ -414,7 +407,7 @@ void YaoServerSharing::PrecomputeGC(std::deque& queue, ABYSetup* setup } else if (gate->type == G_UNIV) { EvaluateUniversalGate(gate); } else if (gate->type == G_SHARED_OUT) { - GATE* parent = m_pGates + gate->ingates.inputs.parent; + GATE* parent = &(m_vGates[gate->ingates.inputs.parent]); InstantiateGate(gate); memcpy(gate->gs.yinput.outKey, parent->gs.yinput.outKey, gate->nvals * m_nSecParamBytes); memcpy(gate->gs.yinput.pi, parent->gs.yinput.pi, gate->nvals); @@ -437,19 +430,19 @@ void YaoServerSharing::PrecomputeGC(std::deque& queue, ABYSetup* setup void YaoServerSharing::EvaluateInversionGate(GATE* gate) { uint32_t parentid = gate->ingates.inputs.parent; InstantiateGate(gate); - assert((gate - m_pGates) > parentid); - memcpy(gate->gs.yinput.outKey, m_pGates[parentid].gs.yinput.outKey, m_nSecParamBytes * gate->nvals); + assert((gate - m_vGates.data()) > parentid); + memcpy(gate->gs.yinput.outKey, m_vGates[parentid].gs.yinput.outKey, m_nSecParamBytes * gate->nvals); for (uint32_t i = 0; i < gate->nvals; i++) { - gate->gs.yinput.pi[i] = m_pGates[parentid].gs.yinput.pi[i] ^ 0x01; + gate->gs.yinput.pi[i] = m_vGates[parentid].gs.yinput.pi[i] ^ 0x01; - assert(gate->gs.yinput.pi[i] < 2 && m_pGates[parentid].gs.yinput.pi[i] < 2); + assert(gate->gs.yinput.pi[i] < 2 && m_vGates[parentid].gs.yinput.pi[i] < 2); } UsedGate(parentid); } void YaoServerSharing::EvaluateInputGate(uint32_t gateid) { - GATE* gate = m_pGates + gateid; + GATE* gate = &(m_vGates[gateid]); if (gate->gs.ishare.src == SERVER) { if(gate->instantiated) { @@ -484,8 +477,8 @@ void YaoServerSharing::EvaluateInputGate(uint32_t gateid) { * and perform an oblivious transfer */ void YaoServerSharing::EvaluateConversionGate(uint32_t gateid) { - GATE* gate = m_pGates + gateid; - GATE* parent = m_pGates + gate->ingates.inputs.parents[0]; + GATE* gate = &(m_vGates[gateid]); + GATE* parent = &(m_vGates[gate->ingates.inputs.parents[0]]); uint32_t pos = gate->gs.pos; InstantiateGate(gate); @@ -548,24 +541,24 @@ void YaoServerSharing::EvaluateConversionGate(uint32_t gateid) { // is called in YaoServerSharing::FinishCircuitLayer() } -//TODO: optimize for UINT64_T pointers +//TODO: optimize for uint64_t pointers void YaoServerSharing::EvaluateXORGate(GATE* gate) { uint32_t idleft = gate->ingates.inputs.twin.left; //gate->gs.ginput.left; uint32_t idright = gate->ingates.inputs.twin.right; //gate->gs.ginput.right; - BYTE* lpi = (m_pGates + idleft)->gs.yinput.pi; - BYTE* rpi = (m_pGates + idright)->gs.yinput.pi; + BYTE* lpi = m_vGates[idleft].gs.yinput.pi; + BYTE* rpi = m_vGates[idright].gs.yinput.pi; - BYTE* lkey = (m_pGates + idleft)->gs.yinput.outKey; - BYTE* rkey = (m_pGates + idright)->gs.yinput.outKey; + BYTE* lkey = m_vGates[idleft].gs.yinput.outKey; + BYTE* rkey = m_vGates[idright].gs.yinput.outKey; InstantiateGate(gate); BYTE* gpi = gate->gs.yinput.pi; BYTE* gkey = gate->gs.yinput.outKey; #ifdef GATE_INST_FLAG - assert((m_pGates + idleft)->instantiated); - assert((m_pGates + idright)->instantiated); + assert(m_vGates[idleft].instantiated); + assert(m_vGates[idright].instantiated); #endif for (uint32_t g = 0; g < gate->nvals; g++, gpi++, lpi++, rpi++, lkey += m_nSecParamBytes, rkey += m_nSecParamBytes, gkey += m_nSecParamBytes) { *gpi = *lpi ^ *rpi; @@ -576,13 +569,13 @@ void YaoServerSharing::EvaluateXORGate(GATE* gate) { #ifdef DEBUGYAOSERVER PrintKey(gate->gs.yinput.outKey); std::cout << " (" << (uint32_t) gate->gs.yinput.pi[0] << ") = "; - PrintKey((m_pGates + idleft)->gs.yinput.outKey); - std::cout << " (" << (uint32_t) (m_pGates + idleft)->gs.yinput.pi[0] << ")(" << idleft << ") ^ "; - PrintKey((m_pGates + idright)->gs.yinput.outKey); - std::cout << " (" << (uint32_t) (m_pGates + idright)->gs.yinput.pi[0] << ")(" << idright << ")" << std::endl; + PrintKey(m_vGates[idleft].gs.yinput.outKey); + std::cout << " (" << (uint32_t) m_vGates[idleft].gs.yinput.pi[0] << ")(" << idleft << ") ^ "; + PrintKey(m_vGates[idright].gs.yinput.outKey); + std::cout << " (" << (uint32_t) m_vGates[idright].gs.yinput.pi[0] << ")(" << idright << ")" << std::endl; #endif - assert((m_pGates + idleft)->gs.yinput.pi[0] < 2 && (m_pGates + idright)->gs.yinput.pi[0] < 2); + assert(m_vGates[idleft].gs.yinput.pi[0] < 2 && m_vGates[idright].gs.yinput.pi[0] < 2); UsedGate(idleft); UsedGate(idright); } @@ -592,8 +585,8 @@ void YaoServerSharing::EvaluateANDGate(GATE* gate, ABYSetup* setup) { uint32_t idleft = gate->ingates.inputs.twin.left;//gate->gs.ginput.left; uint32_t idright = gate->ingates.inputs.twin.right;//gate->gs.ginput.right; - GATE* gleft = m_pGates + idleft; - GATE* gright = m_pGates + idright; + GATE* gleft = &(m_vGates[idleft]); + GATE* gright = &(m_vGates[idright]); InstantiateGate(gate); @@ -617,9 +610,6 @@ void YaoServerSharing::EvaluateANDGate(GATE* gate, ABYSetup* setup) { void YaoServerSharing::CreateGarbledTable(GATE* ggate, uint32_t pos, GATE* gleft, GATE* gright){ - - uint32_t outkey; - uint8_t *table, *lkey, *rkey, *outwire_key; uint8_t lpbit = gleft->gs.yinput.pi[pos]; uint8_t rpbit = gright->gs.yinput.pi[pos]; @@ -720,8 +710,8 @@ void YaoServerSharing::EvaluateUniversalGate(GATE* gate) { uint32_t idleft = gate->ingates.inputs.twin.left; uint32_t idright = gate->ingates.inputs.twin.right; - GATE* gleft = m_pGates + idleft; - GATE* gright = m_pGates + idright; + GATE* gleft = &(m_vGates[idleft]); + GATE* gright = &(m_vGates[idright]); uint32_t ttable = gate->gs.ttable; InstantiateGate(gate); @@ -762,15 +752,15 @@ void YaoServerSharing::GarbleUniversalGate(GATE* ggate, uint32_t pos, GATE* glef ggate->gs.yinput.pi[pos] = ((ttable>>ttid)&0x01) ^ kbit;//((kbit^1) & (ttid == 3)) | (kbit & (ttid != 3)); #ifdef DEBUGYAOSERVER - cout << " encrypting : "; + std::cout << " encrypting : "; PrintKey(m_bZeroBuf); - cout << " using: "; + std::cout << " using: "; PrintKey(m_bLMaskBuf[0]); - cout << " (" << (uint32_t) gleft->gs.yinput.pi[pos] << ") and : "; + std::cout << " (" << (uint32_t) gleft->gs.yinput.pi[pos] << ") and : "; PrintKey(m_bRMaskBuf[0]); - cout << " (" << (uint32_t) gright->gs.yinput.pi[pos] << ") to : "; + std::cout << " (" << (uint32_t) gright->gs.yinput.pi[pos] << ") to : "; PrintKey(m_bOKeyBuf[0]); - cout << endl; + std::cout << std::endl; #endif memcpy(outkey[kbit], outkey[0], m_nSecParamBytes); m_pKeyOps->XOR(outkey[kbit^1], outkey[kbit], m_vR.GetArr()); @@ -782,15 +772,15 @@ void YaoServerSharing::GarbleUniversalGate(GATE* ggate, uint32_t pos, GATE* glef // ", truthtable = " << (unsigned uint32_t) g_TruthTable[id^i] << ", mypermbit = " << (unsigned uint32_t) ggate->gs.yinput.pi[pos] << ", id = " << id << endl; EncryptWireGRR3(univ_table, outkey[keyid], m_bLMaskBuf[i>>1], m_bRMaskBuf[i&0x01], i); #ifdef DEBUGYAOSERVER - cout << " encrypting : "; - PrintKey(m_bOKeyBuf[outkey]); - cout << " using: "; + std::cout << " encrypting : "; + PrintKey(m_bOKeyBuf[0]); // TODO: check that we print the right value + std::cout << " using: "; PrintKey(m_bLMaskBuf[i>>1]); - cout << " (" << (uint32_t) gleft->gs.yinput.pi[pos] << ") and : "; + std::cout << " (" << (uint32_t) gleft->gs.yinput.pi[pos] << ") and : "; PrintKey(m_bRMaskBuf[i&0x01]); - cout << " (" << (uint32_t) gright->gs.yinput.pi[pos] << ") to : "; - PrintKey(table); - cout << endl; + std::cout << " (" << (uint32_t) gright->gs.yinput.pi[pos] << ") to : "; + PrintKey(univ_table); // TODO: check that we print the right value + std::cout << std::endl; #endif } } @@ -799,13 +789,27 @@ void YaoServerSharing::GarbleUniversalGate(GATE* ggate, uint32_t pos, GATE* glef void YaoServerSharing::CollectClientOutputShares() { std::deque out = m_cBoolCircuit->GetOutputGatesForParty(CLIENT); while (out.size() > 0) { - for (uint32_t j = 0; j < m_pGates[out.front()].nvals; j++, m_nOutputShareSndSize++) { - m_vOutputShareSndBuf.SetBit(m_nOutputShareSndSize, !!((m_pGates[out.front()].gs.val[j / GATE_T_BITS]) & ((UGATE_T) 1 << (j % GATE_T_BITS)))); + for (uint32_t j = 0; j < m_vGates[out.front()].nvals; j++, m_nOutputShareSndSize++) { + m_vOutputShareSndBuf.SetBit(m_nOutputShareSndSize, !!((m_vGates[out.front()].gs.val[j / GATE_T_BITS]) & ((UGATE_T) 1 << (j % GATE_T_BITS)))); } out.pop_front(); } } +void YaoServerSharing::EvaluateConstantGate(GATE* gate) { + //assign 0 and 1 gates + UGATE_T constval = gate->gs.constval; + InstantiateGate(gate); + memset(gate->gs.yinput.outKey, 0, m_nSecParamBytes * gate->nvals); + for (uint32_t i = 0; i < gate->nvals; ++i) { + if(constval == 1L) { + gate->gs.yinput.pi[i] = 1; + } else { + gate->gs.yinput.pi[i] = 0; + } + } +} + void YaoServerSharing::EvaluateOutputGate(GATE* gate) { uint32_t parentid = gate->ingates.inputs.parent; @@ -819,7 +823,7 @@ void YaoServerSharing::EvaluateOutputGate(GATE* gate) { gate->gs.val = (UGATE_T*) calloc(ceil_divide(gate->nvals, GATE_T_BITS), sizeof(UGATE_T)); gate->instantiated = true; for (uint32_t i = 0; i < gate->nvals; i++) { - gate->gs.val[i / GATE_T_BITS] |= (((UGATE_T) m_pGates[parentid].gs.yinput.pi[i]) << (i % GATE_T_BITS)); + gate->gs.val[i / GATE_T_BITS] |= (((UGATE_T) m_vGates[parentid].gs.yinput.pi[i]) << (i % GATE_T_BITS)); } #ifdef DEBUGYAOSERVER @@ -856,13 +860,13 @@ void YaoServerSharing::GetDataToSend(std::vector& sendbuf, std::vector 0) { for (uint32_t i = 0, linbitctr = 0; i < m_vClientInputGate.size() && linbitctr < m_nClientInBitCtr; i++) { uint32_t gateid = m_vClientInputGate[i]; - if (m_pGates[gateid].type == G_IN) { - for (uint32_t k = 0; k < m_pGates[gateid].nvals; k++, linbitctr++, m_nClientInputKexIdx++, m_nClientInputKeyCtr++) { + if (m_vGates[gateid].type == G_IN) { + for (uint32_t k = 0; k < m_vGates[gateid].nvals; k++, linbitctr++, m_nClientInputKexIdx++, m_nClientInputKeyCtr++) { m_pKeyOps->XOR(m_bTempKeyBuf, m_vClientInputKeys.GetArr() + m_nClientInputKexIdx * m_nSecParamBytes, m_vR.GetArr()); if (m_vClientROTRcvBuf.GetBitNoMask(linbitctr) == 1) { @@ -913,24 +917,24 @@ void YaoServerSharing::FinishCircuitLayer(uint32_t level) { } } } else { //Evaluate conversion gates - uint32_t input = m_pGates[gateid].ingates.inputs.parents[0]; + uint32_t input = m_vGates[gateid].ingates.inputs.parents[0]; - for (uint32_t k = 0; k < m_pGates[gateid].nvals; k++, linbitctr++, m_nClientInputKexIdx++, m_nClientInputKeyCtr++) { + for (uint32_t k = 0; k < m_vGates[gateid].nvals; k++, linbitctr++, m_nClientInputKexIdx++, m_nClientInputKeyCtr++) { m_pKeyOps->XOR(m_bTempKeyBuf, m_vClientInputKeys.GetArr() + m_nClientInputKexIdx * m_nSecParamBytes, m_vR.GetArr()); uint32_t permval = 0; - if (m_pGates[input].context == S_BOOL) { - uint32_t val = (m_pGates[input].gs.val[k / GATE_T_BITS] >> (k % GATE_T_BITS)) & 0x01; - permval = val ^ m_pGates[gateid].gs.yinput.pi[k]; - } else if (m_pGates[input].context == S_YAO || m_pGates[input].context == S_YAO_REV) {//switch roles gate + if (m_vGates[input].context == S_BOOL) { + uint32_t val = (m_vGates[input].gs.val[k / GATE_T_BITS] >> (k % GATE_T_BITS)) & 0x01; + permval = val ^ m_vGates[gateid].gs.yinput.pi[k]; + } else if (m_vGates[input].context == S_YAO || m_vGates[input].context == S_YAO_REV) {//switch roles gate //std::cout << "copying keys from input " << input << " at position " << k << std::endl; - assert(m_pGates[input].instantiated); - uint32_t val = m_pGates[input].gs.yval[((k+1) * m_nSecParamBytes)-1] & 0x01; //get client permutation bit + assert(m_vGates[input].instantiated); + uint32_t val = m_vGates[input].gs.yval[((k+1) * m_nSecParamBytes)-1] & 0x01; //get client permutation bit //std::cout << "Server conv share = " << val << std::endl; - permval = val ^ m_pGates[gateid].gs.yinput.pi[k]; + permval = val ^ m_vGates[gateid].gs.yinput.pi[k]; //std::cout << "done copying keys" << std::endl; } #ifdef DEBUGYAOSERVER - std::cout << "Processing keys for gate " << gateid << ", perm-bit = " << (uint32_t) m_pGates[gateid].gs.yinput.pi[k] << + std::cout << "Processing keys for gate " << gateid << ", perm-bit = " << (uint32_t) m_vGates[gateid].gs.yinput.pi[k] << ", client-cor: " << (uint32_t) m_vClientROTRcvBuf.GetBitNoMask(linbitctr) << std::endl; PrintKey(m_vClientInputKeys.GetArr() + m_nClientInputKexIdx * m_nSecParamBytes); @@ -1029,7 +1033,7 @@ void YaoServerSharing::InstantiateGate(GATE* gate) { } void YaoServerSharing::EvaluateSIMDGate(uint32_t gateid) { - GATE* gate = m_pGates + gateid; + GATE* gate = &(m_vGates[gateid]); if (gate->type == G_COMBINE) { uint32_t* inptr = gate->ingates.inputs.parents; //gate->gs.cinput; uint32_t nparents = gate->ingates.ningates; @@ -1038,11 +1042,11 @@ void YaoServerSharing::EvaluateSIMDGate(uint32_t gateid) { BYTE* keyptr = gate->gs.yinput.outKey; BYTE* piptr = gate->gs.yinput.pi; for(uint32_t g = 0; g < nparents; g++) { - parent_nvals = m_pGates[inptr[g]].nvals; - memcpy(keyptr, m_pGates[inptr[g]].gs.yinput.outKey, m_nSecParamBytes * parent_nvals); + parent_nvals = m_vGates[inptr[g]].nvals; + memcpy(keyptr, m_vGates[inptr[g]].gs.yinput.outKey, m_nSecParamBytes * parent_nvals); keyptr += m_nSecParamBytes * parent_nvals; - memcpy(piptr, m_pGates[inptr[g]].gs.yinput.pi, parent_nvals); + memcpy(piptr, m_vGates[inptr[g]].gs.yinput.pi, parent_nvals); piptr += parent_nvals; UsedGate(inptr[g]); @@ -1052,16 +1056,16 @@ void YaoServerSharing::EvaluateSIMDGate(uint32_t gateid) { uint32_t pos = gate->gs.sinput.pos; uint32_t idleft = gate->ingates.inputs.parent; //gate->gs.sinput.input; InstantiateGate(gate); - memcpy(gate->gs.yinput.outKey, m_pGates[idleft].gs.yinput.outKey + pos * m_nSecParamBytes, m_nSecParamBytes * gate->nvals); - memcpy(gate->gs.yinput.pi, m_pGates[idleft].gs.yinput.pi + pos, gate->nvals); + memcpy(gate->gs.yinput.outKey, m_vGates[idleft].gs.yinput.outKey + pos * m_nSecParamBytes, m_nSecParamBytes * gate->nvals); + memcpy(gate->gs.yinput.pi, m_vGates[idleft].gs.yinput.pi + pos, gate->nvals); UsedGate(idleft); } else if (gate->type == G_REPEAT) { uint32_t idleft = gate->ingates.inputs.parent; //gate->gs.rinput; InstantiateGate(gate); BYTE* keyptr = gate->gs.yinput.outKey; for (uint32_t g = 0; g < gate->nvals; g++, keyptr += m_nSecParamBytes) { - memcpy(keyptr, m_pGates[idleft].gs.yinput.outKey, m_nSecParamBytes); - gate->gs.yinput.pi[g] = m_pGates[idleft].gs.yinput.pi[0]; + memcpy(keyptr, m_vGates[idleft].gs.yinput.outKey, m_nSecParamBytes); + gate->gs.yinput.pi[g] = m_vGates[idleft].gs.yinput.pi[0]; assert(gate->gs.yinput.pi[g] < 2); } UsedGate(idleft); @@ -1072,8 +1076,8 @@ void YaoServerSharing::EvaluateSIMDGate(uint32_t gateid) { BYTE* keyptr = gate->gs.yinput.outKey; for (uint32_t g = 0; g < gate->nvals; g++, keyptr += m_nSecParamBytes) { uint32_t idleft = combinepos[g]; - memcpy(keyptr, m_pGates[idleft].gs.yinput.outKey + pos * m_nSecParamBytes, m_nSecParamBytes); - gate->gs.yinput.pi[g] = m_pGates[idleft].gs.yinput.pi[pos]; + memcpy(keyptr, m_vGates[idleft].gs.yinput.outKey + pos * m_nSecParamBytes, m_nSecParamBytes); + gate->gs.yinput.pi[g] = m_vGates[idleft].gs.yinput.pi[pos]; assert(gate->gs.yinput.pi[g] < 2); UsedGate(idleft); } @@ -1086,8 +1090,8 @@ void YaoServerSharing::EvaluateSIMDGate(uint32_t gateid) { InstantiateGate(gate); BYTE* keyptr = gate->gs.yinput.outKey; for (uint32_t g = 0; g < gate->nvals; g++, keyptr += m_nSecParamBytes) { - memcpy(keyptr, m_pGates[idparent].gs.yinput.outKey + positions[g] * m_nSecParamBytes, m_nSecParamBytes); - gate->gs.yinput.pi[g] = m_pGates[idparent].gs.yinput.pi[positions[g]]; + memcpy(keyptr, m_vGates[idparent].gs.yinput.outKey + positions[g] * m_nSecParamBytes, m_nSecParamBytes); + gate->gs.yinput.pi[g] = m_vGates[idparent].gs.yinput.pi[positions[g]]; assert(gate->gs.yinput.pi[g] < 2); } UsedGate(idparent); @@ -1103,7 +1107,7 @@ uint32_t YaoServerSharing::AssignInput(CBitVector& inputvals) { GATE* gate; uint32_t inbits = 0; for (uint32_t i = 0, inbitstart = 0, bitstocopy, len, lim; i < myingates.size(); i++) { - gate = m_pGates + myingates[i]; + gate = &(m_vGates[myingates[i]]); if (!gate->instantiated) { bitstocopy = gate->nvals * gate->sharebitlen; inbits += bitstocopy; @@ -1128,8 +1132,8 @@ uint32_t YaoServerSharing::GetOutput(CBitVector& out) { out.Create(outbits); GATE* gate; - for (uint32_t i = 0, outbitstart = 0, bitstocopy, len, lim; i < myoutgates.size(); i++) { - gate = m_pGates + myoutgates[i]; + for (uint32_t i = 0, outbitstart = 0, lim; i < myoutgates.size(); i++) { + gate = &(m_vGates[myoutgates[i]]); lim = gate->nvals * gate->sharebitlen; for (uint32_t j = 0; j < lim; j++, outbitstart++) { diff --git a/src/abycore/sharing/yaoserversharing.h b/src/abycore/sharing/yaoserversharing.h index e8640660..ff8e1dd2 100644 --- a/src/abycore/sharing/yaoserversharing.h +++ b/src/abycore/sharing/yaoserversharing.h @@ -2,17 +2,17 @@ \file yaoserversharing.h \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Yao Server Sharing class. */ @@ -36,8 +36,8 @@ class YaoServerSharing: public YaoSharing { /** Constructor of the class. */ - YaoServerSharing(e_sharing context, e_role role, uint32_t sharebitlen, ABYCircuit* circuit, crypto* crypt) : - YaoSharing(context, role, sharebitlen, circuit, crypt) { + YaoServerSharing(e_sharing context, e_role role, uint32_t sharebitlen, ABYCircuit* circuit, crypto* crypt, const std::string& circdir = ABY_CIRCUIT_DIR) : + YaoSharing(context, role, sharebitlen, circuit, crypt, circdir) { InitServer(); } ; @@ -55,7 +55,7 @@ class YaoServerSharing: public YaoSharing { void EvaluateInteractiveOperations(uint32_t level); void SendConversionValues(uint32_t gateid); - void FinishCircuitLayer(uint32_t level); + void FinishCircuitLayer(); void PrepareOnlinePhase(); @@ -209,6 +209,12 @@ class YaoServerSharing: public YaoSharing { //void EvaluateClientOutputGate(GATE* gate); void CollectClientOutputShares(); + /** + Method for evaluating a constant gate for the inputted + gate id. + \param gateid Gate Identifier + */ + void EvaluateConstantGate(GATE* gate); /** Method for evaluating Output gate for the inputted gate object. diff --git a/src/abycore/sharing/yaosharing.cpp b/src/abycore/sharing/yaosharing.cpp index 2bbcb40f..a104cdc0 100644 --- a/src/abycore/sharing/yaosharing.cpp +++ b/src/abycore/sharing/yaosharing.cpp @@ -2,17 +2,17 @@ \file yaosharing.cpp \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Yao Sharing class implementation. */ @@ -26,7 +26,7 @@ void YaoSharing::Init() { /* init the class for correctly sized Yao key operations*/ InitYaoKey(&m_pKeyOps, m_cCrypto->get_seclvl().symbits); - m_cBoolCircuit = new BooleanCircuit(m_pCircuit, m_eRole, m_eContext); + m_cBoolCircuit = new BooleanCircuit(m_pCircuit, m_eRole, m_eContext, m_cCircuitFileDir); m_bZeroBuf = (BYTE*) calloc(m_nSecParamBytes, sizeof(BYTE)); m_bTempKeyBuf = (BYTE*) malloc(sizeof(BYTE) * AES_BYTES); diff --git a/src/abycore/sharing/yaosharing.h b/src/abycore/sharing/yaosharing.h index a5324ebf..d703daec 100644 --- a/src/abycore/sharing/yaosharing.h +++ b/src/abycore/sharing/yaosharing.h @@ -2,17 +2,17 @@ \file yaosharing.h \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Yao Sharing class. */ @@ -59,8 +59,8 @@ class YaoSharing: public Sharing { public: /** Constructor for the class. */ - YaoSharing(e_sharing context, e_role role, uint32_t sharebitlen, ABYCircuit* circuit, crypto* crypt) : - Sharing(context, role, sharebitlen, circuit, crypt) { + YaoSharing(e_sharing context, e_role role, uint32_t sharebitlen, ABYCircuit* circuit, crypto* crypt, const std::string& circdir = ABY_CIRCUIT_DIR) : + Sharing(context, role, sharebitlen, circuit, crypt, circdir) { Init(); } ; @@ -74,7 +74,7 @@ class YaoSharing: public Sharing { virtual void FinishSetupPhase(ABYSetup* setup) = 0; virtual void EvaluateLocalOperations(uint32_t gateid) = 0; - virtual void FinishCircuitLayer(uint32_t level) = 0; + virtual void FinishCircuitLayer() = 0; virtual void PrepareOnlinePhase() = 0; diff --git a/src/examples/aes/aes_test.cpp b/src/examples/aes/aes_test.cpp index 1bff1ef9..63acd6f5 100644 --- a/src/examples/aes/aes_test.cpp +++ b/src/examples/aes/aes_test.cpp @@ -2,17 +2,17 @@ \file aes_test.cpp \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief AES Test class implementation. */ @@ -26,7 +26,7 @@ int32_t read_test_options(int32_t* argcp, char*** argvp, e_role* role, uint32_t* bitlen, uint32_t* nvals, uint32_t* secparam, std::string* address, uint16_t* port, e_sharing* sharing, bool* verbose, uint32_t* nthreads, - bool* use_vec_ands) { + bool* use_vec_ands, bool* expand_in_sfe, bool* client_only) { uint32_t int_role = 0, int_port = 0, int_sharing = 0; bool useffc = false; @@ -40,7 +40,9 @@ int32_t read_test_options(int32_t* argcp, char*** argvp, e_role* role, uint32_t* { (void*) &int_sharing, T_NUM, "g", "Sharing in which the AES circuit should be evaluated [0: BOOL, 1: YAO, 4: SP_LUT], default: BOOL", false, false }, { (void*) verbose, T_FLAG, "v", "Do not print the result of the evaluation, default: off", false, false }, { (void*) nthreads, T_NUM, "t", "Number of threads, default: 1", false, false }, - { (void*) use_vec_ands, T_FLAG, "u", "Use vector AND optimization for AES circuit for Bool sharing, default: off", false, false } }; + { (void*) use_vec_ands, T_FLAG, "u", "Use vector AND optimization for AES circuit for Bool sharing, default: off", false, false }, + { (void*) expand_in_sfe, T_FLAG, "x", "Calculate the key expansion during the SFE, default: false", false, false }, + { (void*) client_only, T_FLAG, "c", "Both the key and the value are inputted by the client, default: false", false, false } }; if (!parse_options(argcp, argvp, options, sizeof(options) / sizeof(parsing_ctx))) { print_usage(*argvp[0], options, sizeof(options) / sizeof(parsing_ctx)); @@ -72,15 +74,17 @@ int main(int argc, char** argv) { std::string address = "127.0.0.1"; bool verbose = false; bool use_vec_ands = false; + bool expand_in_sfe = false; + bool client_only = false; e_mt_gen_alg mt_alg = MT_OT; e_sharing sharing = S_BOOL; - read_test_options(&argc, &argv, &role, &bitlen, &nvals, &secparam, &address, &port, &sharing, &verbose, &nthreads, &use_vec_ands); + read_test_options(&argc, &argv, &role, &bitlen, &nvals, &secparam, &address, &port, &sharing, &verbose, &nthreads, &use_vec_ands, &expand_in_sfe, &client_only); seclvl seclvl = get_sec_lvl(secparam); - test_aes_circuit(role, address, port, seclvl, nvals, nthreads, mt_alg, sharing, verbose, use_vec_ands); + test_aes_circuit(role, address, port, seclvl, nvals, nthreads, mt_alg, sharing, verbose, use_vec_ands, expand_in_sfe, client_only); return 0; } diff --git a/src/examples/aes/common/aescircuit.cpp b/src/examples/aes/common/aescircuit.cpp index 475cbfcc..7c89fd8e 100644 --- a/src/examples/aes/common/aescircuit.cpp +++ b/src/examples/aes/common/aescircuit.cpp @@ -2,17 +2,17 @@ \file aescircuit.cpp \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Implementation of AESCiruit */ #include "aescircuit.h" @@ -20,8 +20,12 @@ #include "../../../abycore/sharing/sharing.h" #include +static uint32_t* pos_even; +static uint32_t* pos_odd; + + int32_t test_aes_circuit(e_role role, const std::string& address, uint16_t port, seclvl seclvl, uint32_t nvals, uint32_t nthreads, - e_mt_gen_alg mt_alg, e_sharing sharing, bool verbose, bool use_vec_ands) { + e_mt_gen_alg mt_alg, e_sharing sharing, [[maybe_unused]] bool verbose, bool use_vec_ands, bool expand_in_sfe, bool client_only) { uint32_t bitlen = 32; uint32_t aes_key_bits; ABYParty* party = new ABYParty(role, address, port, seclvl, bitlen, nthreads, mt_alg, 4000000); @@ -45,16 +49,22 @@ int32_t test_aes_circuit(e_role role, const std::string& address, uint16_t port, verify.Create(AES_BITS * nvals); key.CreateBytes(AES_EXP_KEY_BYTES); - - - //TODO create random key and perform key schedule, right now a static (expanded) key is used - key.Copy((uint8_t*) AES_TEST_EXPANDED_KEY, 0, AES_EXP_KEY_BYTES); + uint8_t aes_test_key[AES_KEY_BYTES]; + srand(7438); + for(uint32_t i = 0; i < AES_KEY_BYTES; i++) { + aes_test_key[i] = (uint8_t) (rand() % 256); + } + uint8_t expanded_key[AES_EXP_KEY_BYTES]; + ExpandKey(expanded_key, aes_test_key); + key.Copy(expanded_key, 0, AES_EXP_KEY_BYTES); uint8_t* output; - CBitVector out(nvals * AES_BITS); if(sharing == S_YAO_REV) { + //Currently the expand_in_sfe and client_only features are not supported in S_YAO_REV + assert(expand_in_sfe == false && client_only == false); + Circuit* yao_circ = sharings[S_YAO]->GetCircuitBuildRoutine(); Circuit* yao_rev_circ = sharings[S_YAO_REV]->GetCircuitBuildRoutine(); @@ -98,7 +108,18 @@ int32_t test_aes_circuit(e_role role, const std::string& address, uint16_t port, share *s_in, *s_key, *s_ciphertext; s_in = circ->PutSIMDINGate(nvals, input.GetArr(), aes_key_bits, CLIENT); - s_key = circ->PutINGate(key.GetArr(), aes_key_bits * (AES_ROUNDS + 1), SERVER); + e_role key_inputter; + if(client_only) { + key_inputter = CLIENT; + } else { + key_inputter = SERVER; + } + if(expand_in_sfe) { + s_key = circ->PutINGate(aes_test_key, AES_KEY_BITS, key_inputter); + s_key = BuildKeyExpansion(s_key, (BooleanCircuit*) circ, use_vec_ands); + } else { + s_key = circ->PutINGate(key.GetArr(), aes_key_bits * (AES_ROUNDS + 1), key_inputter); + } s_key = circ->PutRepeaterGate(nvals,s_key); s_ciphertext = BuildAESCircuit(s_in, s_key, (BooleanCircuit*) circ, use_vec_ands); @@ -154,7 +175,7 @@ int32_t test_aes_circuit(e_role role, const std::string& address, uint16_t port, } share* BuildAESCircuit(share* val, share* key, BooleanCircuit* circ, bool use_vec_ands) { - uint32_t round, byte, i, j, k; + uint32_t round, i, j, k; std::vector > > state(AES_STATE_COLS); //the state is treated as a matrix std::vector > > state_temp(AES_STATE_COLS); //the state is treated as a matrix std::vector out(128); @@ -228,7 +249,7 @@ std::vector Mul2(std::vector& element, BooleanCircuit* circ) } std::vector > PutAESMixColumnGate(std::vector >& rows, BooleanCircuit* circ) { - UINT i, j, temp; + uint32_t i, j, temp; std::vector > out(4); std::vector > temp_mul2(4); @@ -692,6 +713,99 @@ std::vector AESSBox_Forward_SPLUT(std::vector input, Boolean return out; } +// The basic construction was partally taken from the KeyExpansion function of the +// tiny-AES-c project, https://github.com/kokke/tiny-AES-c +// This function produces NB_CONSTANT(AES_ROUNDS+1) round keys in SFE. +// The round keys are used in each round to decrypt the states. +share* BuildKeyExpansion(share* key, BooleanCircuit* circ, bool use_vec_ands) { + + //TODO make the function SIMD-able if multiple keys are needed + assert(key->get_nvals() == 1); + + //During the function the representation of the extended key is bytewise + std::vector> ex_key_vec(AES_EXP_KEY_BYTES, std::vector(8)); + + uint32_t i, j, k; + + // The first round key is the key itself. + { + std::vector key_vec = key->get_wires(); + for (i = 0; i < key_vec.size(); i++) { + ex_key_vec[i / 8][i % 8] = key_vec[i]; + } + } + + std::vector s_rc[RCON_SIZE]; + + for(i = 0; i < RCON_SIZE; i++) { + uint8_t rc_temp = Rcon[i]; + s_rc[i] = circ->PutCONSGate(rc_temp, 8)->get_wires(); + } + + std::vector> tempa(4); // Used for the column/row operations + + // All other round keys are found from the previous round keys. + for (i = AES_STATE_COLS; i < NB_CONSTANT * (AES_ROUNDS + 1); ++i) { + { + k = (i - 1) * 4; + tempa[0] = ex_key_vec[k]; + tempa[1] = ex_key_vec[k + 1]; + tempa[2] = ex_key_vec[k + 2]; + tempa[3] = ex_key_vec[k + 3]; + } + + if (i % AES_STATE_COLS == 0) { + // This function shifts the 4 bytes in a word to the left once. + // [a0,a1,a2,a3] becomes [a1,a2,a3,a0] + + // Function RotWord() + { + const std::vector u8tmp = tempa[0]; + tempa[0] = tempa[1]; + tempa[1] = tempa[2]; + tempa[2] = tempa[3]; + tempa[3] = u8tmp; + } + + // SubWord() is a function that takes a four-byte input word and + // applies the S-box to each of the four bytes to produce an output word. + + // Function Subword() + { + tempa[0] = PutAESSBoxGate(tempa[0], circ, use_vec_ands); + tempa[1] = PutAESSBoxGate(tempa[1], circ, use_vec_ands); + tempa[2] = PutAESSBoxGate(tempa[2], circ, use_vec_ands); + tempa[3] = PutAESSBoxGate(tempa[3], circ, use_vec_ands); + } + tempa[0] = circ->PutXORGate(tempa[0], s_rc[i/AES_STATE_COLS]); + } +#if AES_STATE_KEY_BITS == 256 + if (i % AES_STATE_COLS == 4) { + // Function Subword() + { + tempa[0] = PutAESSBoxGate(tempa[0], circ, use_vec_ands); + tempa[1] = PutAESSBoxGate(tempa[1], circ, use_vec_ands); + tempa[2] = PutAESSBoxGate(tempa[2], circ, use_vec_ands); + tempa[3] = PutAESSBoxGate(tempa[3], circ, use_vec_ands); + } + } +#endif + k = (i - AES_STATE_COLS) * 4; + j = i * 4; + ex_key_vec[j] = circ->PutXORGate(ex_key_vec[k], tempa[0]); + ex_key_vec[j + 1] = circ->PutXORGate(ex_key_vec[k + 1], tempa[1]); + ex_key_vec[j + 2] = circ->PutXORGate(ex_key_vec[k + 2], tempa[2]); + ex_key_vec[j + 3] = circ->PutXORGate(ex_key_vec[k + 3], tempa[3]); + } + + std::vector result(AES_EXP_KEY_BITS); + for(uint32_t i = 0; i < AES_EXP_KEY_BYTES; i++) { + for(uint32_t j = 0; j < 8; j++) { + result[i * 8 + j] = ex_key_vec[i][j]; + } + } + return new boolshare(result, circ); +} void verify_AES_encryption(uint8_t* input, uint8_t* key, uint32_t nvals, uint8_t* out, crypto* crypt) { AES_KEY_CTX* aes_key = (AES_KEY_CTX*) malloc(sizeof(AES_KEY_CTX)); @@ -701,3 +815,77 @@ void verify_AES_encryption(uint8_t* input, uint8_t* key, uint32_t nvals, uint8_t } free(aes_key); } + +// Copied from the KeyExpansion function of the +// tiny-AES-c project, https://github.com/kokke/tiny-AES-c, original license is public domain +// This function produces NB_CONSTANT(AES_ROUNDS+1) round keys. +// The round keys are used in each round to decrypt the states. +void ExpandKey(uint8_t* roundKey, const uint8_t* key) { +//static void KeyExpansion(uint8_t* RoundKey, const uint8_t* Key) +//{ + unsigned i, j, k; + uint8_t tempa[4]; // Used for the column/row operations + + // The first round key is the key itself. + for (i = 0; i < AES_STATE_COLS; ++i) { + roundKey[(i * 4) + 0] = key[(i * 4) + 0]; + roundKey[(i * 4) + 1] = key[(i * 4) + 1]; + roundKey[(i * 4) + 2] = key[(i * 4) + 2]; + roundKey[(i * 4) + 3] = key[(i * 4) + 3]; + } + + // All other round keys are found from the previous round keys. + for (i = AES_STATE_COLS; i < NB_CONSTANT * (AES_ROUNDS + 1); ++i) { + { + k = (i - 1) * 4; + tempa[0] = roundKey[k + 0]; + tempa[1] = roundKey[k + 1]; + tempa[2] = roundKey[k + 2]; + tempa[3] = roundKey[k + 3]; + } + + if (i % AES_STATE_COLS == 0) { + // This function shifts the 4 bytes in a word to the left once. + // [a0,a1,a2,a3] becomes [a1,a2,a3,a0] + + // Function RotWord() + { + const uint8_t u8tmp = tempa[0]; + tempa[0] = tempa[1]; + tempa[1] = tempa[2]; + tempa[2] = tempa[3]; + tempa[3] = u8tmp; + } + + // SubWord() is a function that takes a four-byte input word and + // applies the S-box to each of the four bytes to produce an output word. + + // Function Subword() + { + tempa[0] = plaintext_aes_sbox[tempa[0]]; + tempa[1] = plaintext_aes_sbox[tempa[1]]; + tempa[2] = plaintext_aes_sbox[tempa[2]]; + tempa[3] = plaintext_aes_sbox[tempa[3]]; + } + + tempa[0] = tempa[0] ^ Rcon[i/AES_STATE_COLS]; + } +#if AES_STATE_KEY_BITS == 256 + if (i % AES_STATE_COLS == 4) { + // Function Subword() + { + tempa[0] = plaintext_aes_sbox[tempa[0]]; + tempa[1] = plaintext_aes_sbox[tempa[1]]; + tempa[2] = plaintext_aes_sbox[tempa[2]]; + tempa[3] = plaintext_aes_sbox[tempa[3]]; + } + } +#endif + j = i * 4; + k = (i - AES_STATE_COLS) * 4; + roundKey[j + 0] = roundKey[k + 0] ^ tempa[0]; + roundKey[j + 1] = roundKey[k + 1] ^ tempa[1]; + roundKey[j + 2] = roundKey[k + 2] ^ tempa[2]; + roundKey[j + 3] = roundKey[k + 3] ^ tempa[3]; + } +} diff --git a/src/examples/aes/common/aescircuit.h b/src/examples/aes/common/aescircuit.h index 1d944b4b..351ebf2f 100644 --- a/src/examples/aes/common/aescircuit.h +++ b/src/examples/aes/common/aescircuit.h @@ -2,17 +2,17 @@ \file aescircuit.h \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Implementation of AESCiruit */ @@ -26,30 +26,49 @@ class BooleanCircuit; -#define AES_ROUNDS 10 -#define AES_STATE_SIZE 16 +// If you change these values and want to test the functionallity with test_aes_circuit, +// you will have to change the AES_BITS, AES_BYTES, AES_KEY_BITS and AES_KEY_BYTES definitions +// on the constant.h definition on the encrypto utils as well. +// WARNING: Currently a correct running of the algorithms cannot be guaranteed if these values are changed. +// There might be some work to do. +#define AES_STATE_KEY_BITS 128 #define AES_STATE_SIZE_BITS 128 -//Size of the expanded key -#define AES_EXP_KEY_BITS 1408 -#define AES_EXP_KEY_BYTES AES_EXP_KEY_BITS/8 +// The round constant word array, Rcon[i], contains the values given by +// x to the power (i-1) being powers of x (x is denoted as {02}) in the field GF(2^8) +// It is used for the key expansion algorithm +// Please extend the array if the aes key size changes +#define RCON_SIZE 11 +const uint8_t Rcon[RCON_SIZE] = { + 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 +}; + +#define NB_CONSTANT 4 -#define AES_STATE_COLS 4 -#define AES_STATE_ROWS AES_STATE_SIZE/AES_STATE_COLS #define INV_GATE_ID 666 -const uint8_t AES_TEST_KEY[AES_KEY_BYTES] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +// Derived constants or constants to AES +#if (AES_STATE_KEY_BITS == 192) + #define AES_ROUNDS 12 + #define AES_STATE_COLS 6 +#elif (AES_STATE_KEY_BITS == 256) + #define AES_ROUNDS 14 + #define AES_STATE_COLS 8 +#else //AES_STATE_KEY__BITS == 128 + #define AES_ROUNDS 10 + #define AES_STATE_COLS 4 +#endif + +#define AES_STATE_SIZE (AES_STATE_SIZE_BITS/8) -const uint8_t AES_TEST_INPUT[AES_BYTES] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }; +// Size of the key +#define AES_STATE_KEY_BYTES (AES_STATE_KEY_BITS/8) -const uint8_t AES_TEST_EXPANDED_KEY[AES_EXP_KEY_BITS] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x63, 0x63, 0x63, - 0x62, 0x63, 0x63, 0x63, 0x62, 0x63, 0x63, 0x63, 0x62, 0x63, 0x63, 0x63, 0x9b, 0x98, 0x98, 0xc9, 0xf9, 0xfb, 0xfb, 0xaa, 0x9b, 0x98, 0x98, 0xc9, 0xf9, 0xfb, 0xfb, 0xaa, - 0x90, 0x97, 0x34, 0x50, 0x69, 0x6c, 0xcf, 0xfa, 0xf2, 0xf4, 0x57, 0x33, 0x0b, 0x0f, 0xac, 0x99, 0xee, 0x06, 0xda, 0x7b, 0x87, 0x6a, 0x15, 0x81, 0x75, 0x9e, 0x42, 0xb2, - 0x7e, 0x91, 0xee, 0x2b, 0x7f, 0x2e, 0x2b, 0x88, 0xf8, 0x44, 0x3e, 0x09, 0x8d, 0xda, 0x7c, 0xbb, 0xf3, 0x4b, 0x92, 0x90, 0xec, 0x61, 0x4b, 0x85, 0x14, 0x25, 0x75, 0x8c, - 0x99, 0xff, 0x09, 0x37, 0x6a, 0xb4, 0x9b, 0xa7, 0x21, 0x75, 0x17, 0x87, 0x35, 0x50, 0x62, 0x0b, 0xac, 0xaf, 0x6b, 0x3c, 0xc6, 0x1b, 0xf0, 0x9b, 0x0e, 0xf9, 0x03, 0x33, - 0x3b, 0xa9, 0x61, 0x38, 0x97, 0x06, 0x0a, 0x04, 0x51, 0x1d, 0xfa, 0x9f, 0xb1, 0xd4, 0xd8, 0xe2, 0x8a, 0x7d, 0xb9, 0xda, 0x1d, 0x7b, 0xb3, 0xde, 0x4c, 0x66, 0x49, 0x41, - 0xb4, 0xef, 0x5b, 0xcb, 0x3e, 0x92, 0xe2, 0x11, 0x23, 0xe9, 0x51, 0xcf, 0x6f, 0x8f, 0x18, 0x8e }; +// Size of the expanded key +#define AES_EXP_KEY_BYTES (AES_STATE_KEY_BYTES*(AES_ROUNDS+1)) +#define AES_EXP_KEY_BITS (AES_EXP_KEY_BYTES*8) +#define AES_STATE_ROWS (AES_STATE_SIZE/AES_STATE_COLS) const uint64_t aes_sbox_ttables[8][4] = {{ 0xb14ede67096c6eedL, 0x68ab4bfa8acb7a13L, 0x10bdb210c006eab5L, 0x4f1ead396f247a04L}, @@ -131,12 +150,51 @@ const uint32_t do_wire_mapping[140][2] = { { 7, 4 }, { 7, 2 }, { 7, 1 }, { 4, 2 + 11, 98 + 14 }, { 98 + 11, 98 + 17 }, { 98 + 16, INV_GATE_ID }, { 98 + 19, INV_GATE_ID }, { 98 + 13, INV_GATE_ID }, { 98 + 6, INV_GATE_ID }, { 98 + 33, 98 + 23 }, { 98 + 32, 98 + 27 }, { 98 + 25, 98 + 29 }, { 98 + 20, 98 + 22 }, { 98 + 6, 98 + 21 }, { 98 + 31, 98 + 28 }, { 98 + 30, 98 + 26 }, { 98 + 6, 98 + 24 } }; -static uint32_t* pos_even; -static uint32_t* pos_odd; +//Testing functions void verify_AES_encryption(uint8_t* input, uint8_t* key, uint32_t nvals, uint8_t* out, crypto* crypt); -int32_t test_aes_circuit(e_role role, const std::string& address, uint16_t port, seclvl seclvl, uint32_t nvals, uint32_t nthreads, e_mt_gen_alg mt_alg, e_sharing sharing, bool verbose = false, bool use_vec_ands=false); +/** + \param role the role of the user; possible roles: "CLIENT" and "SERVER" + \param adress the adress of the server the client connects to + \param port the port of the server the client connects to + \param seclvl the definition of the security level the SFE should be using, see on + to get more information + \param nvals the amount of concurrent encryptions to be calculated + \param nthreads the amount of threads used + \param mt_alg the Oblivious Extension algorithm to be used; see e_mt_gen_alg in the ABYConstants.h for possible algorithms + \param sharing the sharing algorithm to be used; see e_sharing in the ABYConstants.h for possible algorithms + \param verbose if true some output values will be suppressed for printing; default is false + \param use_vec_ands if true the vector AND optimization for AES circuit for Bool sharing will be usedM default is false + \param expand_in_sfe if true the key will be expanded in the SFE, otherwise the key will be expanded before the SFE; default is false + \param client_only if true both the key and the values will be inputted by the client; default is false +*/ +int32_t test_aes_circuit(e_role role, const std::string& address, uint16_t port, seclvl seclvl, uint32_t nvals, uint32_t nthreads, e_mt_gen_alg mt_alg, e_sharing sharing, bool verbose = false, bool use_vec_ands = false, bool expand_in_sfe = false, bool client_only = false); +/** + \param key the key to be expanded + \param roundKey the result as the expansion of the small key. WARNING: This function uses call by reference, + therefore you must preallocate AES_EXP_KEY_BYTES bytes before calling this function. + \brief This function precalculates the expansion of the given (small) key into the expanded key for the AES encryption. + */ +void ExpandKey(uint8_t* roundKey, const uint8_t* key); + +//SFE functions +/** + \param val the value to be encrypted + \param key the expanded key which encrypts the value + \param circ the circuit which generates and evaluates the SFE + \param use_vec_ands if true the vector optimaziation will be used during the SBox replacement, default is false + \brief This function calculates a ciphertext using AES given the val to be enctypted and the keyin SFE. + */ share* BuildAESCircuit(share* val, share* key, BooleanCircuit* circ, bool use_vec_ands=false); +/** + \param key the key to be expanded during SFE, the key must not be a SIMD share with nvals > 1 + \param circ the circuit which generates and evaluates the SFE + \param use_vec_ands if true the vector optimaziation will be used during the SBox replacement, default is false + \brief This function calculates the expansion of the given (small) key into the expanded key for the AES encryption during SFE. + */ +share* BuildKeyExpansion(share* key, BooleanCircuit* circ, bool use_vec_ands = false); + +//Helper functions used for the implementation of the SFE functions above; std::vector AddAESRoundKey(std::vector& val, std::vector key, uint32_t keyaddr, BooleanCircuit* circ); std::vector Mul2(std::vector& element, BooleanCircuit* circ); std::vector > PutAESMixColumnGate(std::vector >& rows, BooleanCircuit* circ); diff --git a/src/examples/bench_operations/bench_operations.cpp b/src/examples/bench_operations/bench_operations.cpp index a3bec3a7..6a351348 100644 --- a/src/examples/bench_operations/bench_operations.cpp +++ b/src/examples/bench_operations/bench_operations.cpp @@ -2,17 +2,17 @@ \file bench_operations.cpp \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Benchmark Primitive Operations */ @@ -45,6 +45,7 @@ static const aby_ops_t m_tBenchOps[] = { { OP_EQ, S_BOOL, "eqbool" }, { OP_MUX, S_BOOL, "muxbool" }, { OP_MUX, S_BOOL, "muxvecbool" }, + { OP_INV, S_BOOL, "invbool" }, { OP_SBOX, S_BOOL, "sboxsobool" }, { OP_SBOX, S_BOOL, "sboxdobool" }, @@ -58,6 +59,7 @@ static const aby_ops_t m_tBenchOps[] = { { OP_EQ, S_YAO, "eqyao" }, { OP_MUX, S_YAO, "muxyao" }, + { OP_INV, S_YAO, "invyao" }, { OP_SBOX, S_YAO, "sboxsoyao" }, { OP_ADD, S_ARITH, "addarith" }, { OP_MUL, S_ARITH, "mularith" }, @@ -142,6 +144,7 @@ int32_t bench_operations(aby_ops_t* bench_ops, uint32_t nops, ABYParty* party, u Circuit *bc, *yc, *ac, *ycr; double op_time, o_time, s_time, o_comm, s_comm; uint32_t non_linears, depth, ynvals, yrnvals; + bool aes_remark = false; avec = (uint64_t*) malloc(nvals * sizeof(uint64_t)); bvec = (uint64_t*) malloc(nvals * sizeof(uint64_t)); @@ -357,6 +360,11 @@ int32_t bench_operations(aby_ops_t* bench_ops, uint32_t nops, ABYParty* party, u for (uint32_t j = 0; j < nvals; j++) verifyvec[j] = (avec[j] + bvec[j]) & typebitmask; break; + case OP_INV: + shrres = ((BooleanCircuit*) circ)->PutINVGate(shra); + for (uint32_t j = 0; j < nvals; j++) + verifyvec[j] = avec[j] ^ typebitmask; + break; case OP_SBOX: if (bitlen >= 8) { shrsel = new boolshare(8, circ); @@ -375,7 +383,8 @@ int32_t bench_operations(aby_ops_t* bench_ops, uint32_t nops, ABYParty* party, u verifyvec[j] = (uint64_t) plaintext_aes_sbox[avec[j] & 0xFF]; //(avec[j] + bvec[j]) & typebitmask; } else{ - std::cout << "AES only works with bitlen >= 8!\t"; + std::cout << "*\t"; + aes_remark = true; shrres = shra; for (uint32_t j = 0; j < nvals; j++){ verifyvec[j] = avec[j]; @@ -467,6 +476,10 @@ int32_t bench_operations(aby_ops_t* bench_ops, uint32_t nops, ABYParty* party, u } + if(aes_remark){ + std::cout << "\n* = AES only works with bitlen >= 8" << std::endl; + } + free(avec); free(bvec); free(cvec); diff --git a/src/examples/euclidean_distance/common/euclidean_dist.cpp b/src/examples/euclidean_distance/common/euclidean_dist.cpp index dd6c0e27..75bf3b5d 100644 --- a/src/examples/euclidean_distance/common/euclidean_dist.cpp +++ b/src/examples/euclidean_distance/common/euclidean_dist.cpp @@ -2,17 +2,17 @@ \file euclidean_dist.cpp \author sreeram.sadasivam@cased.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Testing the implementation of the Euclidean distance for two coordinates */ @@ -20,9 +20,13 @@ #include "../../../abycore/sharing/sharing.h" int32_t test_euclid_dist_circuit(e_role role, const std::string& address, uint16_t port, seclvl seclvl, - uint32_t nvals, uint32_t bitlen, uint32_t nthreads, e_mt_gen_alg mt_alg, + uint32_t nvals, uint32_t nthreads, e_mt_gen_alg mt_alg, e_sharing sharing) { + // defines the operation/output bitlength operations for boolean and arithmetic circuits + // this is why the output bitlen is 32 bits and not 8 bits like the input length + uint32_t bitlen = 32; + /** Step 1: Create the ABY Party object which defines the basis of all the operations which are happening. Operations performed @@ -57,31 +61,33 @@ int32_t test_euclid_dist_circuit(e_role role, const std::string& address, uint16 here we know both pairs for verification later on. */ - uint8_t x1 = 0, x2 = 0, y1 = 0, y2 = 0; + uint8_t* x1 = new uint8_t[nvals]; + uint8_t* x2 = new uint8_t[nvals]; + uint8_t* y1 = new uint8_t[nvals]; + uint8_t* y2 = new uint8_t[nvals]; srand(time(NULL)); - x1 = rand(); - y1 = rand(); - y2 = rand(); - x2 = rand(); + for(uint32_t i = 0; i < nvals; ++i) { + x1[i] = rand(); + y1[i] = rand(); + y2[i] = rand(); + x2[i] = rand(); + } /** Step 6: Set the coordinates as inputs for the circuit for the respective party. - The other party's inputs must be specified but can be set arbitrarily (dummy). - The values will be secret shared before the circuit evaluation. + The other party's input length must be specified. */ - uint8_t dummy = 0; - if (role == SERVER) { - s_x1 = circ->PutINGate(x1, 32, SERVER); - s_y1 = circ->PutINGate(y1, 32, SERVER); - s_x2 = circ->PutINGate(dummy, 32, CLIENT); - s_y2 = circ->PutINGate(dummy, 32, CLIENT); + s_x1 = circ->PutSIMDINGate(nvals, x1, 8, SERVER); + s_y1 = circ->PutSIMDINGate(nvals, y1, 8, SERVER); + s_x2 = circ->PutDummySIMDINGate(nvals, 8); + s_y2 = circ->PutDummySIMDINGate(nvals, 8); } else { - s_x1 = circ->PutINGate(dummy, 32, SERVER); - s_y1 = circ->PutINGate(dummy, 32, SERVER); - s_x2 = circ->PutINGate(x2, 32, CLIENT); - s_y2 = circ->PutINGate(y2, 32, CLIENT); + s_x1 = circ->PutDummySIMDINGate(nvals, 8); + s_y1 = circ->PutDummySIMDINGate(nvals, 8); + s_x2 = circ->PutSIMDINGate(nvals, x2, 8, CLIENT); + s_y2 = circ->PutSIMDINGate(nvals, y2, 8, CLIENT); } /** @@ -104,33 +110,45 @@ int32_t test_euclid_dist_circuit(e_role role, const std::string& address, uint16 party->ExecCircuit(); /** - Step 10: Print plaintext output of the circuit. + Step 10: Obtain the output from */ - uint32_t output; - output = s_out->get_clear_value(); + uint32_t* output; + uint32_t out_bitlen, out_nvals; + // This method only works for an output length of maximum 64 bits in general, + // if the output length is higher you must use get_clear_value_ptr + s_out->get_clear_value_vec(&output, &out_bitlen, &out_nvals); + + /** + Step 11:Print plaintext output of the circuit. + */ std::cout << "Testing Euclidean Distance in " << get_sharing_name(sharing) - << " sharing: " << std::endl; + << " sharing, out_bitlen=" << out_bitlen << " and out_nvals=" << out_nvals << ":" << std::endl; - printf("\n x1: %d, y1: %d \n x2: %d, y2: %d\n", x1, y1, x2, y2); - printf(" Circuit result: %lf ", sqrt(output)); + for(uint32_t i = 0; i < nvals; ++i) { + std::cout << "x1: " << (int) x1[i] << ", y1: " << (int) y1[i] << "; x2: " << (int) x2[i] << ", y2: " << (int) y2[i] << std::endl; + std::cout << "Circuit result: " << sqrt(output[i]); - printf("\n Verification: %lf \n\n", - sqrt((pow((double)abs(y2 - y1), (double)2) + pow((double)abs(x2 - x1),(double) 2)))); + std::cout << " Verification: " << + sqrt((pow((double)abs(y2[i] - y1[i]), (double)2) + pow((double)abs(x2[i] - x1[i]),(double) 2))) << std::endl; + } delete party; + delete x1; + delete x2; + delete y1; + delete y2; return 0; } /** - * \brief Builds a Euclidean distance circuit for two pairs of coordinate shares + * \brief Builds a Euclidean distance circuit for two pairs of coordinate shares (without the computation of sqrt at the end) */ share* BuildEuclidDistanceCircuit(share *s_x1, share *s_x2, share *s_y1, share *s_y2, BooleanCircuit *bc) { - m_nBitLength = 64; - share* out, *t_a, *t_b, *t_ay, *t_by, *res_x, *res_y, *check_sel, + share* out, *t_a, *t_b, *res_x, *res_y, *check_sel, *check_sel_inv; /** Following code performs (x2-x1)*(x2-x1) */ @@ -143,14 +161,12 @@ share* BuildEuclidDistanceCircuit(share *s_x1, share *s_x2, share *s_y1, res_x = bc->PutMULGate(res_x, res_x); /** Following code performs (y2-y1)*(y2-y1) */ - check_sel = bc->PutGTGate(s_y1, s_y2); check_sel_inv = bc->PutINVGate(check_sel); t_a = bc->PutMUXGate(s_y1, s_y2, check_sel); t_b = bc->PutMUXGate(s_y1, s_y2, check_sel_inv); res_y = bc->PutSUBGate(t_a, t_b); - res_y = bc->PutMULGate(res_y, res_y); /** Following code performs out = res_y + res_x*/ diff --git a/src/examples/euclidean_distance/common/euclidean_dist.h b/src/examples/euclidean_distance/common/euclidean_dist.h index e1160d42..d0014497 100644 --- a/src/examples/euclidean_distance/common/euclidean_dist.h +++ b/src/examples/euclidean_distance/common/euclidean_dist.h @@ -2,17 +2,17 @@ \file euclidean_dist.h \author sreeram.sadasivam@cased.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Implementation of the Euclidean Distance using ABY Framework. */ @@ -39,7 +39,7 @@ Euclidean Distance. */ int32_t test_euclid_dist_circuit(e_role role, const std::string& address, uint16_t port, seclvl seclvl, - uint32_t nvals, uint32_t bitlen, uint32_t nthreads, e_mt_gen_alg mt_alg, + uint32_t nvals, uint32_t nthreads, e_mt_gen_alg mt_alg, e_sharing sharing); /** @@ -49,11 +49,9 @@ int32_t test_euclid_dist_circuit(e_role role, const std::string& address, uint16 \param s_y2 shared object of first coordinate y2. \param bc boolean circuit object. - \brief This function is used to build and find the Euclidean Distance. + \brief This function is used to build and find the Euclidean Distance (without computing the sqrt at the end). */ share* BuildEuclidDistanceCircuit(share *s_x1, share *s_x2, share *s_y1, share *s_y2, BooleanCircuit *bc); -static uint32_t m_nBitLength; - #endif /* __EUCLIDEAN_DIST_H_ */ diff --git a/src/examples/euclidean_distance/euclidean_distance_test.cpp b/src/examples/euclidean_distance/euclidean_distance_test.cpp index 0c670503..66c50ce3 100644 --- a/src/examples/euclidean_distance/euclidean_distance_test.cpp +++ b/src/examples/euclidean_distance/euclidean_distance_test.cpp @@ -2,17 +2,17 @@ \file euclidean_distance_test.cpp \author sreeram.sadasivam@cased.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Testing the implementation of the Euclidean distance for two coordinates */ @@ -22,15 +22,13 @@ #include "common/euclidean_dist.h" int32_t read_test_options(int32_t* argcp, char*** argvp, e_role* role, - uint32_t* bitlen, uint32_t* nvals, uint32_t* secparam, std::string* address, - uint16_t* port) { + uint32_t* nvals, uint32_t* secparam, std::string* address, uint16_t* port) { uint32_t int_role = 0, int_port = 0; parsing_ctx options[] = { {(void*) &int_role, T_NUM, "r", "Role: 0/1", true, false }, {(void*) nvals, T_NUM, "n", "Number of parallel elements", false, false }, - {(void*) bitlen, T_NUM, "b", "Bit-length, default 32", false, false }, {(void*) secparam, T_NUM, "s", "Symmetric Security Bits, default: 128", false, false }, {(void*) address, T_STR, "a", "IP-address, default: localhost", false, false }, {(void*) &int_port, T_NUM, "p", "Port, default: 7766", false, false } @@ -57,20 +55,20 @@ int32_t read_test_options(int32_t* argcp, char*** argvp, e_role* role, int main(int argc, char** argv) { e_role role; - uint32_t bitlen = 32, nvals = 31, secparam = 128, nthreads = 1; + uint32_t nvals = 31, secparam = 128, nthreads = 1; uint16_t port = 7766; std::string address = "127.0.0.1"; e_mt_gen_alg mt_alg = MT_OT; - read_test_options(&argc, &argv, &role, &bitlen, &nvals, &secparam, &address, + read_test_options(&argc, &argv, &role, &nvals, &secparam, &address, &port); seclvl seclvl = get_sec_lvl(secparam); - test_euclid_dist_circuit(role, address, port, seclvl, 1, 32, + test_euclid_dist_circuit(role, address, port, seclvl, nvals, nthreads, mt_alg, S_YAO); - test_euclid_dist_circuit(role, address, port, seclvl, 1, 32, + test_euclid_dist_circuit(role, address, port, seclvl, nvals, nthreads, mt_alg, S_BOOL); return 0; diff --git a/src/examples/float/abyfloat.cpp b/src/examples/float/abyfloat.cpp index c8a040fe..021d403c 100644 --- a/src/examples/float/abyfloat.cpp +++ b/src/examples/float/abyfloat.cpp @@ -2,17 +2,17 @@ \file abyfloat.cpp \author daniel.demmler@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2017 Engineering Cryptographic Protocols Group, TU Darmstadt - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . */ #include @@ -28,7 +28,7 @@ void read_test_options(int32_t* argcp, char*** argvp, e_role* role, uint32_t* bitlen, uint32_t* nvals, uint32_t* secparam, std::string* address, - uint16_t* port, int32_t* test_op, uint32_t* test_bit, std::string* circuit, double* fpa, double* fpb) { + uint16_t* port, int32_t* test_op, uint32_t* test_bit, double* fpa, double* fpb) { uint32_t int_role = 0, int_port = 0, int_testbit = 0; @@ -39,7 +39,6 @@ void read_test_options(int32_t* argcp, char*** argvp, e_role* role, {(void*) bitlen, T_NUM, "b", "Bit-length, default 32", false,false }, {(void*) secparam, T_NUM, "s", "Symmetric Security Bits, default: 128", false, false }, {(void*) address, T_STR, "a", "IP-address, default: localhost", false, false }, - {(void*) circuit, T_STR, "c", "circuit file name", false, false }, {(void*) &int_port, T_NUM, "p", "Port, default: 7766", false, false }, {(void*) test_op, T_NUM, "t", "Single test (leave out for all operations), default: off", false, false }, {(void*) fpa, T_DOUBLE, "x", "FP a", false, false }, @@ -71,7 +70,9 @@ void test_verilog_add64_SIMD(e_role role, const std::string& address, uint16_t p // for addition we operate on doubles, so set bitlen to 64 bits uint32_t bitlen = 64; - ABYParty* party = new ABYParty(role, address, port, seclvl, bitlen, nthreads, mt_alg); + std::string circuit_dir = "../../bin/circ/"; + + ABYParty* party = new ABYParty(role, address, port, seclvl, bitlen, nthreads, mt_alg, 100000, circuit_dir); std::vector& sharings = party->GetSharings(); @@ -110,31 +111,38 @@ void test_verilog_add64_SIMD(e_role role, const std::string& address, uint16_t p // FP addition gate share* sum = circ->PutFPGate(ain, bin, ADD, bitlen, nvals, no_status); - + // 32-bit FP addition gate (bitlen, nvals, no_status are omitted) share* sqrt_share = circ->PutFPGate(asqrtin, SQRT); + share* cmp = circ->PutFPGate(ain, bin, CMP, bitlen, nvals); + // output gate share* add_out = circ->PutOUTGate(sum, ALL); share* sqrt_out = circ->PutOUTGate(sqrt_share, ALL); + share* cmp_out = circ->PutOUTGate(cmp, ALL); // run SMPC party->ExecCircuit(); // retrieve plain text output - uint32_t out_bitlen, out_nvals; - uint64_t *out_vals; + uint32_t out_bitlen_add, out_bitlen_cmp, out_nvals; + uint64_t *out_vals_add, *out_vals_cmp; - add_out->get_clear_value_vec(&out_vals, &out_bitlen, &out_nvals); + add_out->get_clear_value_vec(&out_vals_add, &out_bitlen_add, &out_nvals); + cmp_out->get_clear_value_vec(&out_vals_cmp, &out_bitlen_cmp, &out_nvals); // print every output for (uint32_t i = 0; i < nvals; i++) { // dereference output value as double without casting the content - double val = *((double*) &out_vals[i]); + double val = *((double*) &out_vals_add[i]); std::cout << "ADD RES: " << val << " = " << *(double*) &avals[i] << " + " << *(double*) &bvals[i] << " | nv: " << out_nvals - << " bitlen: " << out_bitlen << std::endl; + << " bitlen: " << out_bitlen_add << std::endl; + + std::cout << "CMP RES: " << out_vals_cmp[i] << " = " << *(double*) &avals[i] << " > " << *(double*) &bvals[i] << " | nv: " << out_nvals + << " bitlen: " << out_bitlen_cmp << std::endl; } uint32_t *sqrt_out_vals = (uint32_t*) sqrt_out->get_clear_value_ptr(); @@ -152,14 +160,13 @@ int main(int argc, char** argv) { uint16_t port = 7766; std::string address = "127.0.0.1"; - std::string circuit = "none.aby"; int32_t test_op = -1; e_mt_gen_alg mt_alg = MT_OT; uint32_t test_bit = 0; double fpa = 0, fpb = 0; read_test_options(&argc, &argv, &role, &bitlen, &nvals, &secparam, &address, - &port, &test_op, &test_bit, &circuit, &fpa, &fpb); + &port, &test_op, &test_bit, &fpa, &fpb); std::cout << std::fixed << std::setprecision(3); std::cout << "double input values: " << fpa << " ; " << fpb << std::endl; diff --git a/src/examples/innerproduct/common/innerproduct.cpp b/src/examples/innerproduct/common/innerproduct.cpp index 4930fba6..d6dcada6 100644 --- a/src/examples/innerproduct/common/innerproduct.cpp +++ b/src/examples/innerproduct/common/innerproduct.cpp @@ -2,17 +2,17 @@ \file innerproduct.cpp \author sreeram.sadasivam@cased.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Implementation of the Inner Product using ABY Framework. */ @@ -20,8 +20,8 @@ #include "../../../abycore/sharing/sharing.h" int32_t test_inner_product_circuit(e_role role, const std::string& address, uint16_t port, seclvl seclvl, - uint32_t nvals, uint32_t bitlen, uint32_t nthreads, e_mt_gen_alg mt_alg, - e_sharing sharing, uint32_t num) { + uint32_t numbers, uint32_t bitlen, uint32_t nthreads, e_mt_gen_alg mt_alg, + e_sharing sharing) { /** Step 1: Create the ABYParty object which defines the basis of all the @@ -57,8 +57,8 @@ int32_t test_inner_product_circuit(e_role role, const std::string& address, uint uint16_t output, v_sum = 0; - std::vector xvals(num); - std::vector yvals(num); + std::vector xvals(numbers); + std::vector yvals(numbers); uint32_t i; srand(time(NULL)); @@ -73,7 +73,7 @@ int32_t test_inner_product_circuit(e_role role, const std::string& address, uint The values for the party different from role is ignored, but PutINGate() must always be called for both roles. */ - for (i = 0; i < num; i++) { + for (i = 0; i < numbers; i++) { x = rand(); y = rand(); @@ -84,15 +84,15 @@ int32_t test_inner_product_circuit(e_role role, const std::string& address, uint yvals[i] = y; } - s_x_vec = circ->PutSIMDINGate(num, xvals.data(), 16, SERVER); - s_y_vec = circ->PutSIMDINGate(num, yvals.data(), 16, CLIENT); + s_x_vec = circ->PutSIMDINGate(numbers, xvals.data(), 16, SERVER); + s_y_vec = circ->PutSIMDINGate(numbers, yvals.data(), 16, CLIENT); /** Step 7: Call the build method for building the circuit for the problem by passing the shared objects and circuit object. Don't forget to type cast the circuit object to type of share */ - s_out = BuildInnerProductCircuit(s_x_vec, s_y_vec, num, + s_out = BuildInnerProductCircuit(s_x_vec, s_y_vec, numbers, (ArithmeticCircuit*) circ); /** @@ -124,7 +124,7 @@ int32_t test_inner_product_circuit(e_role role, const std::string& address, uint /* Constructs the inner product circuit. num multiplications and num additions. */ -share* BuildInnerProductCircuit(share *s_x, share *s_y, uint32_t num, ArithmeticCircuit *ac) { +share* BuildInnerProductCircuit(share *s_x, share *s_y, uint32_t numbers, ArithmeticCircuit *ac) { uint32_t i; // pairwise multiplication of all input values @@ -135,7 +135,7 @@ share* BuildInnerProductCircuit(share *s_x, share *s_y, uint32_t num, Arithmetic // add up the individual multiplication results and store result on wire 0 // in arithmetic sharing ADD is for free, and does not add circuit depth, thus simple sequential adding - for (i = 1; i < num; i++) { + for (i = 1; i < numbers; i++) { s_x->set_wire_id(0, ac->PutADDGate(s_x->get_wire_id(0), s_x->get_wire_id(i))); } diff --git a/src/examples/innerproduct/common/innerproduct.h b/src/examples/innerproduct/common/innerproduct.h index bea627b1..1c4ef03e 100644 --- a/src/examples/innerproduct/common/innerproduct.h +++ b/src/examples/innerproduct/common/innerproduct.h @@ -2,17 +2,17 @@ \file innerproduct.h \author sreeram.sadasivam@cased.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Implementation of the Inner Product using ABY Framework. */ @@ -41,19 +41,19 @@ Inner Product. */ int32_t test_inner_product_circuit(e_role role, const std::string& address, uint16_t port, seclvl seclvl, - uint32_t nvals, uint32_t bitlen, uint32_t nthreads, e_mt_gen_alg mt_alg, - e_sharing sharing, uint32_t num); + uint32_t numbers, uint32_t bitlen, uint32_t nthreads, e_mt_gen_alg mt_alg, + e_sharing sharing); /** \param s_x share of X values \param s_y share of Y values - \param num the number of elements in the inner product + \param numbers the number of elements in the inner product \param ac Arithmetic Circuit object. \brief This function is used to build and solve the Inner Product modulo 2^16. It computes the inner product by multiplying each value in x and y, and adding those multiplied results to evaluate the inner product. The addition is performed in a tree, thus with logarithmic depth. */ -share* BuildInnerProductCircuit(share *s_x, share *s_y, uint32_t num, ArithmeticCircuit *ac); +share* BuildInnerProductCircuit(share *s_x, share *s_y, uint32_t numbers, ArithmeticCircuit *ac); #endif diff --git a/src/examples/innerproduct/innerproduct_test.cpp b/src/examples/innerproduct/innerproduct_test.cpp index 6fe93a35..070f8426 100644 --- a/src/examples/innerproduct/innerproduct_test.cpp +++ b/src/examples/innerproduct/innerproduct_test.cpp @@ -2,17 +2,17 @@ \file innerproduct_test.cpp \author sreeram.sadasivam@cased.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Inner Product Test class implementation. */ @@ -25,15 +25,15 @@ #include "common/innerproduct.h" int32_t read_test_options(int32_t* argcp, char*** argvp, e_role* role, - uint32_t* bitlen, uint32_t* nvals, uint32_t* secparam, std::string* address, + uint32_t* bitlen, uint32_t* numbers, uint32_t* secparam, std::string* address, uint16_t* port, int32_t* test_op) { uint32_t int_role = 0, int_port = 0; parsing_ctx options[] = { { (void*) &int_role, T_NUM, "r", "Role: 0/1", true, false }, - { (void*) nvals, T_NUM, "n", "Number of elements for inner product", false, false }, - { (void*) bitlen, T_NUM, "b", "Bit-length, default 32", false, false }, + { (void*) numbers, T_NUM, "n", "Number of elements for inner product, default: 128", false, false }, + { (void*) bitlen, T_NUM, "b", "Bit-length, default 16", false, false }, { (void*) secparam, T_NUM, "s", "Symmetric Security Bits, default: 128", false, false }, { (void*) address, T_STR, "a", "IP-address, default: localhost", false, false }, { (void*) &int_port, T_NUM, "p", "Port, default: 7766", false, false }, @@ -61,18 +61,18 @@ int32_t read_test_options(int32_t* argcp, char*** argvp, e_role* role, int main(int argc, char** argv) { e_role role; - uint32_t bitlen = 16, nvals = 128, secparam = 128, nthreads = 1; + uint32_t bitlen = 16, numbers = 128, secparam = 128, nthreads = 1; uint16_t port = 7766; std::string address = "127.0.0.1"; int32_t test_op = -1; e_mt_gen_alg mt_alg = MT_OT; - read_test_options(&argc, &argv, &role, &bitlen, &nvals, &secparam, &address, &port, &test_op); + read_test_options(&argc, &argv, &role, &bitlen, &numbers, &secparam, &address, &port, &test_op); seclvl seclvl = get_sec_lvl(secparam); // call inner product routine. set size with cmd-parameter -n - test_inner_product_circuit(role, address, port, seclvl, 1, 16, nthreads, mt_alg, S_ARITH, nvals); + test_inner_product_circuit(role, address, port, seclvl, numbers, bitlen, nthreads, mt_alg, S_ARITH); return 0; } diff --git a/src/examples/lowmc/common/lowmccircuit.cpp b/src/examples/lowmc/common/lowmccircuit.cpp index 8b1fa83e..2eb006a4 100644 --- a/src/examples/lowmc/common/lowmccircuit.cpp +++ b/src/examples/lowmc/common/lowmccircuit.cpp @@ -2,23 +2,28 @@ \file lowmccircuit.cpp \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Prototypical benchmark implementation of LowMCCiruit. Attention: Does not yield correct result! */ #include "lowmccircuit.h" #include "../../../abycore/sharing/sharing.h" #include +static uint32_t m_nRndCtr; +static uint32_t* m_tGrayCode; +static uint32_t* m_tGrayCodeIncrement; +static uint32_t m_nZeroGate; + //sboxes (m), key-length (k), statesize (n), data (d), rounds (r) int32_t test_lowmc_circuit(e_role role, const std::string& address, uint16_t port, uint32_t nvals, uint32_t nthreads, e_mt_gen_alg mt_alg, e_sharing sharing, uint32_t statesize, uint32_t keysize, @@ -29,13 +34,13 @@ int32_t test_lowmc_circuit(e_role role, const std::string& address, uint16_t por } int32_t test_lowmc_circuit(e_role role, const std::string& address, uint16_t port, uint32_t nvals, uint32_t nthreads, - e_mt_gen_alg mt_alg, e_sharing sharing, LowMCParams* param, uint32_t maxgates, crypto* crypt) { + e_mt_gen_alg mt_alg, e_sharing sharing, LowMCParams* param, uint32_t reservegates, crypto* crypt) { uint32_t bitlen = 32, ctr = 0, exp_key_bitlen = param->blocksize * (param->nrounds+1), zero_gate; ABYParty* party; - if(maxgates > 0) - party = new ABYParty(role, address, port, crypt->get_seclvl(), bitlen, nthreads, mt_alg, maxgates); + if(reservegates > 0) + party = new ABYParty(role, address, port, crypt->get_seclvl(), bitlen, nthreads, mt_alg, reservegates); else party = new ABYParty(role, address, port, crypt->get_seclvl(), bitlen, nthreads, mt_alg); @@ -87,8 +92,8 @@ share* BuildLowMCCircuit(share* val, share* key, BooleanCircuit* circ, LowMCPara m_nZeroGate = zerogate; //Build the GrayCode for the optimal window-size - uint32_t wsize = floor_log2(statesize) - 2; - m_tGrayCode = build_code(wsize); + m_tGrayCode = BuildGrayCode(statesize); + m_tGrayCodeIncrement = BuildGrayCodeIncrement(statesize); //copy the input to the current state for (i = 0; i < statesize; i++) @@ -113,7 +118,8 @@ share* BuildLowMCCircuit(share* val, share* key, BooleanCircuit* circ, LowMCPara } - destroy_code(m_tGrayCode); + free(m_tGrayCode); + free(m_tGrayCodeIncrement); #if PRINT_PERFORMANCE_STATS std::cout << "Total Number of Boolean Gates: " << circ->GetNumGates() << std::endl; @@ -216,7 +222,7 @@ void FourRussiansMatrixMult(std::vector& state, uint32_t lowmcstatesiz for (i = 0, bitctr = 0; i < ceil_divide(lowmcstatesize, wsize); i++) { //for each column-window for (j = 1; j < (1 << wsize); j++) { - lut[m_tGrayCode->ord[j]] = circ->PutXORGate(lut[m_tGrayCode->ord[j - 1]], state_pad[i * wsize + m_tGrayCode->inc[j - 1]]); + lut[m_tGrayCode[j]] = circ->PutXORGate(lut[m_tGrayCode[j - 1]], state_pad[i * wsize + m_tGrayCodeIncrement[j - 1]]); } for (j = 0; j < lowmcstatesize; j++, bitctr += wsize) { @@ -269,3 +275,27 @@ void CallbackMultiplyAndDestroy4RMatrix(GATE* gate, void* matrix) { //TODO } +uint32_t* BuildGrayCode(uint32_t length) { + uint32_t* gray_code = (uint32_t*) malloc(sizeof(uint32_t) * length); + for(uint32_t i = 0; i < length; ++i) { + gray_code[i] = i ^ (i >> 1); + } + return gray_code; +} + +uint32_t* BuildGrayCodeIncrement(uint32_t length) { + uint32_t* gray_code_increment = (uint32_t*) malloc(sizeof(uint32_t) * length); + for(uint32_t i = 0; i < length; ++i) { + gray_code_increment[i] = 0; + } + uint32_t length_inc = 2; + while(length_inc < length) { + uint32_t length_count = length_inc - 1; + while(length_count <= length) { + (gray_code_increment[length_count])++; + length_count += length_inc; + } + length_inc <<= 1; + } + return gray_code_increment; +} diff --git a/src/examples/lowmc/common/lowmccircuit.h b/src/examples/lowmc/common/lowmccircuit.h index 0a4ca9c7..ad4eaf76 100644 --- a/src/examples/lowmc/common/lowmccircuit.h +++ b/src/examples/lowmc/common/lowmccircuit.h @@ -2,17 +2,17 @@ \file lowmccircuit.h \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Implementation of LowMCCiruit */ #ifndef __LOWMCCIRCUIT_H_ @@ -22,7 +22,6 @@ #include "../../../abycore/aby/abyparty.h" #include #include -#include #include static const BYTE mpccseed[16] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF }; @@ -51,14 +50,11 @@ static const LowMCParams ltp = { 63, 128, 256, 128, 14 }; static const LowMCParams lowmcparamlookup[] = { stp, ltp}; -static uint32_t m_nRndCtr; static CBitVector m_vRandomBits; -static code* m_tGrayCode; -static uint32_t m_nZeroGate; int32_t test_lowmc_circuit(e_role role, const std::string& address, uint16_t port, uint32_t nvals, uint32_t nthreads, e_mt_gen_alg mt_alg, e_sharing sharing, uint32_t statesize, uint32_t keysize, uint32_t sboxes, uint32_t rounds, uint32_t maxnumgates, crypto* crypt); -int32_t test_lowmc_circuit(e_role role, const std::string& address, uint16_t port, uint32_t nvals, uint32_t nthreads, e_mt_gen_alg mt_alg, e_sharing sharing, LowMCParams* param, uint32_t maxgates, +int32_t test_lowmc_circuit(e_role role, const std::string& address, uint16_t port, uint32_t nvals, uint32_t nthreads, e_mt_gen_alg mt_alg, e_sharing sharing, LowMCParams* param, uint32_t reservegates, crypto* crypt); share* BuildLowMCCircuit(share* val, share* key, BooleanCircuit* circ, LowMCParams* param, uint32_t zerogate, crypto* crypt); void LowMCAddRoundKey(std::vector& val, std::vector key, uint32_t locmcstatesize, uint32_t round, BooleanCircuit* circ); @@ -76,4 +72,7 @@ void CallbackMultiplyAndDestroy4RMatrix(GATE* gate, void* matrix); void FourRussiansMatrixMult(std::vector& state, uint32_t lowmcstatesize, BooleanCircuit* circ); +uint32_t* BuildGrayCode(uint32_t length); +uint32_t* BuildGrayCodeIncrement(uint32_t length); + #endif /* __LOWMCCIRCUIT_H_ */ diff --git a/src/examples/lowmc/lowmc.cpp b/src/examples/lowmc/lowmc.cpp index 12a8ee42..0f9529b7 100644 --- a/src/examples/lowmc/lowmc.cpp +++ b/src/examples/lowmc/lowmc.cpp @@ -2,17 +2,17 @@ \file lowmc.cpp \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief LowMC implementation. */ diff --git a/src/examples/millionaire_prob/common/millionaire_prob.cpp b/src/examples/millionaire_prob/common/millionaire_prob.cpp index 5587aa51..f1a27557 100644 --- a/src/examples/millionaire_prob/common/millionaire_prob.cpp +++ b/src/examples/millionaire_prob/common/millionaire_prob.cpp @@ -2,17 +2,17 @@ \file millionaire_prob.cpp \author sreeram.sadasivam@cased.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Implementation of the millionaire problem using ABY Framework. */ @@ -21,8 +21,7 @@ #include "../../../abycore/sharing/sharing.h" int32_t test_millionaire_prob_circuit(e_role role, const std::string& address, uint16_t port, seclvl seclvl, - uint32_t nvals, uint32_t bitlen, uint32_t nthreads, e_mt_gen_alg mt_alg, - e_sharing sharing) { + uint32_t bitlen, uint32_t nthreads, e_mt_gen_alg mt_alg, e_sharing sharing) { /** Step 1: Create the ABYParty object which defines the basis of all the diff --git a/src/examples/millionaire_prob/common/millionaire_prob.h b/src/examples/millionaire_prob/common/millionaire_prob.h index 3435e5a9..51cd562c 100644 --- a/src/examples/millionaire_prob/common/millionaire_prob.h +++ b/src/examples/millionaire_prob/common/millionaire_prob.h @@ -2,17 +2,17 @@ \file millionaire_prob.h \author sreeram.sadasivam@cased.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Implementation of the millionaire problem using ABY Framework. */ @@ -33,7 +33,6 @@ \param role role played by the program which can be server or client part. \param address IP Address \param seclvl Security level - \param nvals Number of values \param bitlen Bit length of the inputs \param nthreads Number of threads \param mt_alg The algorithm for generation of multiplication triples @@ -42,8 +41,7 @@ millionaire's problem */ int32_t test_millionaire_prob_circuit(e_role role, const std::string& address, uint16_t port, seclvl seclvl, - uint32_t nvals, uint32_t bitlen, uint32_t nthreads, e_mt_gen_alg mt_alg, - e_sharing sharing); + uint32_t bitlen, uint32_t nthreads, e_mt_gen_alg mt_alg, e_sharing sharing); /** \param s_alice shared object of alice. diff --git a/src/examples/millionaire_prob/millionaire_prob_test.cpp b/src/examples/millionaire_prob/millionaire_prob_test.cpp index 9bae3685..a0637403 100644 --- a/src/examples/millionaire_prob/millionaire_prob_test.cpp +++ b/src/examples/millionaire_prob/millionaire_prob_test.cpp @@ -2,17 +2,17 @@ \file millionaire_prob_test.cpp \author sreeram.sadasivam@cased.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Millionaire problem Test class implementation. */ @@ -29,7 +29,6 @@ int32_t read_test_options(int32_t* argcp, char*** argvp, e_role* role, uint16_t* port, int32_t* test_op) { uint32_t int_role = 0, int_port = 0; - bool useffc = false; parsing_ctx options[] = { { (void*) &int_role, T_NUM, "r", "Role: 0/1", true, false }, { @@ -80,10 +79,10 @@ int main(int argc, char** argv) { seclvl seclvl = get_sec_lvl(secparam); //evaluate the millionaires circuit using Yao - test_millionaire_prob_circuit(role, address, port, seclvl, 1, 32, + test_millionaire_prob_circuit(role, address, port, seclvl, 32, nthreads, mt_alg, S_YAO); //evaluate the millionaires circuit using GMW - //test_millionaire_prob_circuit(role, address, seclvl, 1, 32, + //test_millionaire_prob_circuit(role, address, port, seclvl, 32, // nthreads, mt_alg, S_BOOL); return 0; diff --git a/src/examples/min-euclidean-dist/common/min-euclidean-dist-circuit.cpp b/src/examples/min-euclidean-dist/common/min-euclidean-dist-circuit.cpp index 5b3a0025..d53ab9da 100644 --- a/src/examples/min-euclidean-dist/common/min-euclidean-dist-circuit.cpp +++ b/src/examples/min-euclidean-dist/common/min-euclidean-dist-circuit.cpp @@ -2,17 +2,17 @@ \file min-euclidean-dist-circuit.cpp \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Implementation of Minimum Euclidean Distance Circuit */ #include "min-euclidean-dist-circuit.h" @@ -41,9 +41,9 @@ int32_t test_min_eucliden_dist_circuit(e_role role, const std::string& address, uint64_t verify; Circuit *distcirc, *mincirc; - + share ***Sshr, **Cshr, **Ssqr, *Csqr, *mindst; - + srand(time(NULL)); //generate dbsize * dim * bitlen random bits as server db @@ -74,7 +74,7 @@ int32_t test_min_eucliden_dist_circuit(e_role role, const std::string& address, Ssqr = (share**) malloc(sizeof(share*) * dbsize); for (i = 0; i < dbsize; i++) { - tempsum = 0; + tempsum = 0; for (j = 0; j < dim; j++) { temp = serverdb[i][j]; tempsum += (temp * temp); @@ -161,7 +161,7 @@ share* build_min_euclidean_dist_circuit(share*** S, share** C, uint32_t n, uint3 distance[i] = mincirc->PutA2YGate(distance[i]); } } - + mindist = mincirc->PutMinGate(distance, n); free(distance); return mindist; @@ -171,7 +171,7 @@ uint64_t verify_min_euclidean_dist(uint32_t** serverdb, uint32_t* clientquery, u uint32_t i, j; uint64_t mindist, tmpdist; - mindist = MAX_UINT; + mindist = ULLONG_MAX; for(i=0; i < dbsize; i++) { tmpdist = 0; for(j=0; j < dim; j++) { diff --git a/src/examples/min-euclidean-dist/common/min-euclidean-dist-circuit.h b/src/examples/min-euclidean-dist/common/min-euclidean-dist-circuit.h index 1b5712d8..d86453ba 100644 --- a/src/examples/min-euclidean-dist/common/min-euclidean-dist-circuit.h +++ b/src/examples/min-euclidean-dist/common/min-euclidean-dist-circuit.h @@ -2,17 +2,17 @@ \file min-euclidean-dist-circuit.h \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Implementation of Minimum Euclidean Distance Circuit */ diff --git a/src/examples/min-euclidean-dist/min-euclidean-dist.cpp b/src/examples/min-euclidean-dist/min-euclidean-dist.cpp index 4f074004..9cc5c9cc 100644 --- a/src/examples/min-euclidean-dist/min-euclidean-dist.cpp +++ b/src/examples/min-euclidean-dist/min-euclidean-dist.cpp @@ -2,17 +2,17 @@ \file min-euclidean-dist.cpp \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Minimum Euclidean distance Test class implementation. */ diff --git a/src/examples/psi_phasing/common/hashing/cuckoo.cpp b/src/examples/psi_phasing/common/hashing/cuckoo.cpp index ed0d46e1..2a4ab3ad 100644 --- a/src/examples/psi_phasing/common/hashing/cuckoo.cpp +++ b/src/examples/psi_phasing/common/hashing/cuckoo.cpp @@ -1,11 +1,25 @@ -/* - * cuckoo.cpp - * - * Created on: Oct 7, 2014 - * Author: mzohner +/** + \file cuckoo.cpp + \author michael.zohner@ec-spride.de + \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . + \brief */ + #include +#include +#include #include "cuckoo.h" //returns a cuckoo hash table with the first dimension being the bins and the second dimension being the pointer to the elements @@ -22,11 +36,8 @@ cuckoo_hashing(uint8_t* elements, uint32_t neles, uint32_t nbins, uint32_t bitle uint8_t* hash_table; cuckoo_entry_ctx** cuckoo_table; cuckoo_entry_ctx** cuckoo_stash; - cuckoo_entry_ctx* cuckoo_entries; - uint32_t i, j, stashctr=0, elebytelen; + uint32_t stashctr=0, elebytelen; uint32_t *perm_ptr; - pthread_t* entry_gen_tasks; - cuckoo_entry_gen_ctx* ctx; hs_t hs; elebytelen = ceil_divide(bitlen, 8); @@ -42,28 +53,34 @@ cuckoo_hashing(uint8_t* elements, uint32_t neles, uint32_t nbins, uint32_t bitle cuckoo_table = (cuckoo_entry_ctx**) calloc(nbins, sizeof(cuckoo_entry_ctx*)); cuckoo_stash = (cuckoo_entry_ctx**) calloc(maxstashsize, sizeof(cuckoo_entry_ctx*)); - cuckoo_entries = (cuckoo_entry_ctx*) malloc(neles * sizeof(cuckoo_entry_ctx)); - entry_gen_tasks = (pthread_t*) malloc(sizeof(pthread_t) * ntasks); - ctx = (cuckoo_entry_gen_ctx*) malloc(sizeof(cuckoo_entry_gen_ctx) * ntasks); + std::vector cuckoo_entries(neles); + std::vector entry_gen_tasks(ntasks); + std::vector ctx(ntasks); #ifndef TEST_UTILIZATION - for(i = 0; i < ntasks; i++) { + for(uint32_t i = 0; i < ntasks; i++) { ctx[i].elements = elements; - ctx[i].cuckoo_entries = cuckoo_entries; + ctx[i].cuckoo_entries = cuckoo_entries.data(); ctx[i].hs = &hs; ctx[i].startpos = i * ceil_divide(neles, ntasks); ctx[i].endpos = std::min(ctx[i].startpos + ceil_divide(neles, ntasks), neles); //std::cout << "Thread " << i << " starting from " << ctx[i].startpos << " going to " << ctx[i].endpos << " for " << neles << " elements" << std::endl; - if(pthread_create(entry_gen_tasks+i, NULL, gen_cuckoo_entries, (void*) (ctx+i))) { - std::cerr << "Error in creating new pthread at cuckoo hashing!" << std::endl; - exit(0); + try { + entry_gen_tasks[i] = std::thread(gen_cuckoo_entries, &ctx[i]); + } catch (const std::system_error& e) { + std::cerr << "Error in creating new thread at cuckoo hashing!\n" + << e.what() << std::endl; + exit(1); } } - for(i = 0; i < ntasks; i++) { - if(pthread_join(entry_gen_tasks[i], NULL)) { - std::cerr << "Error in joining pthread at cuckoo hashing!" << std::endl; - exit(0); + for(uint32_t i = 0; i < ntasks; i++) { + try { + entry_gen_tasks[i].join(); + } catch (const std::system_error& e) { + std::cerr << "Error in joining thread at cuckoo hashing!\n" + << e.what() << std::endl; + exit(1); } } #else @@ -78,8 +95,8 @@ cuckoo_hashing(uint8_t* elements, uint32_t neles, uint32_t nbins, uint32_t bitle // std::cout << "Address " << i << " mapped to " << hs.address_used[i] << " times" << std::endl; //} //insert all elements into the cuckoo hash table - for(i = 0; i < neles; i++) { - if(!(insert_element(cuckoo_table, cuckoo_entries + i, neles, hs.nhashfuns))) { + for(uint32_t i = 0; i < neles; i++) { + if(!(insert_element(cuckoo_table, &cuckoo_entries[i], neles, hs.nhashfuns))) { #ifdef COUNT_FAILS fails++; /*std::cout << "insertion failed for element " << (hex) << (*(((uint32_t*) elements)+i)) << ", inserting to address: "; @@ -90,7 +107,7 @@ cuckoo_hashing(uint8_t* elements, uint32_t neles, uint32_t nbins, uint32_t bitle #else if(stashctr < maxstashsize) { std::cout << "Insertion not successful for element " << i <<", putting it on the stash" << std::endl; - cuckoo_stash[stashctr] = cuckoo_entries+i; + cuckoo_stash[stashctr] = &cuckoo_entries[i]; stashctr++; } else { std::cerr << "Stash exceeded maximum stash size of " << maxstashsize << ", terminating program" << std::endl; @@ -107,7 +124,7 @@ cuckoo_hashing(uint8_t* elements, uint32_t neles, uint32_t nbins, uint32_t bitle #ifndef TEST_UTILIZATION hash_table = (uint8_t*) calloc(nbins, hs.outbytelen); - for(i = 0; i < nbins; i++) { + for(uint32_t i = 0; i < nbins; i++) { if(cuckoo_table[i] != NULL) { //std::cout << "Element: " << ((uint32_t*) cuckoo_table[i]->val)[0] << ", position = " << (cuckoo_table[i]->pos & 0x03) << ", in bin " << i << std::endl; cuckoo_table[i]->val[0] ^= (cuckoo_table[i]->pos & 0x03); @@ -128,7 +145,7 @@ cuckoo_hashing(uint8_t* elements, uint32_t neles, uint32_t nbins, uint32_t bitle *stash_elements = (uint8_t*) malloc(maxstashsize * elebytelen); *stashperm = (uint32_t*) malloc(sizeof(uint32_t) * maxstashsize); - for(i = 0; i < maxstashsize; i++) { + for(uint32_t i = 0; i < maxstashsize; i++) { if(cuckoo_stash[i] != NULL) { memcpy(*stash_elements + i * elebytelen, elements + cuckoo_stash[i]->eleid * elebytelen, elebytelen); (*stashperm)[i] = cuckoo_stash[i]->eleid; @@ -142,16 +159,13 @@ cuckoo_hashing(uint8_t* elements, uint32_t neles, uint32_t nbins, uint32_t bitle #ifndef TEST_UTILIZATION //Cleanup - for(i = 0; i < neles; i++) { + for(uint32_t i = 0; i < neles; i++) { free(cuckoo_entries[i].val); free(cuckoo_entries[i].address); } #endif - free(cuckoo_entries); free(cuckoo_table); free(cuckoo_stash); - free(entry_gen_tasks); - free(ctx); free_hashing_state(&hs); @@ -163,8 +177,7 @@ cuckoo_hashing(uint8_t* elements, uint32_t neles, uint32_t nbins, uint32_t bitle } -void *gen_cuckoo_entries(void *ctx_void) { - cuckoo_entry_gen_ctx* ctx = (cuckoo_entry_gen_ctx*) ctx_void; +void gen_cuckoo_entries(cuckoo_entry_gen_ctx* ctx) { hs_t* hs = ctx->hs; uint32_t i, inbytelen = ceil_divide(hs->inbitlen, 8); uint8_t* eleptr = ctx->elements + inbytelen * ctx->startpos; @@ -178,8 +191,6 @@ void *gen_cuckoo_entries(void *ctx_void) { inline void gen_cuckoo_entry(uint8_t* in, cuckoo_entry_ctx* out, hs_t* hs, uint32_t ele_id) { - uint32_t i; - out->pos = 0; out->eleid = ele_id; @@ -193,7 +204,7 @@ inline void gen_cuckoo_entry(uint8_t* in, cuckoo_entry_ctx* out, hs_t* hs, uint3 inline bool insert_element(cuckoo_entry_ctx** ctable, cuckoo_entry_ctx* element, uint32_t max_iterations, uint32_t nhashfuns) { cuckoo_entry_ctx *evicted, *tmp_evicted; - uint32_t i, ev_pos, iter_cnt; + uint32_t ev_pos, iter_cnt; #ifdef DEBUG_CUCKOO std::cout << "iter_cnt = " << iter_cnt << " for element " << (hex) << (*((uint32_t*) element->element)) << (dec) << ", inserting to address: " << element->address[element->pos] << " or " << element->address[element->pos^1] << std::endl; @@ -201,7 +212,7 @@ inline bool insert_element(cuckoo_entry_ctx** ctable, cuckoo_entry_ctx* element, for(iter_cnt = 0, evicted = element; iter_cnt < max_iterations; iter_cnt++) { //TODO: assert(addr < MAX_TAB_ENTRIES) - for(i = 0; i < nhashfuns; i++) {//, ele_pos=(ele_pos+1)%NUM_HASH_FUNCTIONS) { + for(uint32_t i = 0; i < nhashfuns; i++) {//, ele_pos=(ele_pos+1)%NUM_HASH_FUNCTIONS) { if(ctable[evicted->address[i]] == NULL) { ctable[evicted->address[i]] = evicted; evicted->pos = i; @@ -232,7 +243,7 @@ inline bool insert_element(cuckoo_entry_ctx** ctable, cuckoo_entry_ctx* element, return false; } -inline uint32_t compute_stash_size(uint32_t nbins, uint32_t neles) { +inline uint32_t compute_stash_size([[maybe_unused]] uint32_t nbins, [[maybe_unused]] uint32_t neles) { return 4; } diff --git a/src/examples/psi_phasing/common/hashing/cuckoo.h b/src/examples/psi_phasing/common/hashing/cuckoo.h index a2e6da28..24ea4cda 100644 --- a/src/examples/psi_phasing/common/hashing/cuckoo.h +++ b/src/examples/psi_phasing/common/hashing/cuckoo.h @@ -1,8 +1,19 @@ -/* - * cuckoo.h - * - * Created on: Oct 7, 2014 - * Author: mzohner +/** + \file cuckoo.h + \author michael.zohner@ec-spride.de + \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . + \brief */ #ifndef CUCKOO_H_ @@ -67,7 +78,7 @@ cuckoo_hashing(uint8_t* elements, uint32_t neles, uint32_t nbins, uint32_t bitle uint32_t* perm, uint32_t ntasks, uint8_t** stash_elements, uint32_t maxstashsize, uint32_t** stashperm, uint32_t nhashfuns, prf_state_ctx* prf_state); //routine for generating the entries, is invoked by the threads -void *gen_cuckoo_entries(void *ctx); +void gen_cuckoo_entries(cuckoo_entry_gen_ctx* ctx); inline void gen_cuckoo_entry(uint8_t* in, cuckoo_entry_ctx* out, hs_t* hs, uint32_t ele_id); inline bool insert_element(cuckoo_entry_ctx** ctable, cuckoo_entry_ctx* element, uint32_t max_iterations, uint32_t nhashfuns); inline uint32_t compute_stash_size(uint32_t nbins, uint32_t neles); diff --git a/src/examples/psi_phasing/common/hashing/hashing_util.h b/src/examples/psi_phasing/common/hashing/hashing_util.h index 90954ed4..5b0ab231 100644 --- a/src/examples/psi_phasing/common/hashing/hashing_util.h +++ b/src/examples/psi_phasing/common/hashing/hashing_util.h @@ -1,8 +1,19 @@ -/* - * hashing_util.h - * - * Created on: Oct 8, 2014 - * Author: mzohner +/** + \file hashing_util.h + \author michael.zohner@ec-spride.de + \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . + \brief */ #ifndef HASHING_UTIL_H_ @@ -60,7 +71,7 @@ static const uint32_t SELECT_BITS_INV[33] = \ static const uint8_t BYTE_SELECT_BITS_INV[8] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01}; //Init the values for the hash function -static void init_hashing_state(hs_t* hs, uint32_t nelements, uint32_t inbitlen, uint32_t nbins, +inline void init_hashing_state(hs_t* hs, uint32_t nelements, uint32_t inbitlen, uint32_t nbins, uint32_t nhashfuns, prf_state_ctx* prf_state) { uint32_t i, j, nrndbytes; hs->nhashfuns = nhashfuns; @@ -112,7 +123,7 @@ static void init_hashing_state(hs_t* hs, uint32_t nelements, uint32_t inbitlen, } } -static void free_hashing_state(hs_t* hs) { +inline void free_hashing_state(hs_t* hs) { uint32_t i, j; for(i = 0; i < hs->nhashfuns; i++) { for(j = 0; j < hs->nhfvals; j++) { diff --git a/src/examples/psi_phasing/common/hashing/simple_hashing.cpp b/src/examples/psi_phasing/common/hashing/simple_hashing.cpp index 86a0dbf6..47247b70 100644 --- a/src/examples/psi_phasing/common/hashing/simple_hashing.cpp +++ b/src/examples/psi_phasing/common/hashing/simple_hashing.cpp @@ -1,30 +1,41 @@ -/* - * simple_hashing.cpp - * - * Created on: Oct 8, 2014 - * Author: mzohner +/** + \file simple_hashing.cpp + \author michael.zohner@ec-spride.de + \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . + \brief */ #include +#include +#include #include "simple_hashing.h" uint8_t* simple_hashing(uint8_t* elements, uint32_t neles, uint32_t bitlen, uint32_t *outbitlen, uint32_t* nelesinbin, uint32_t nbins, uint32_t* maxbinsize, uint32_t ntasks, uint32_t nhashfuns, prf_state_ctx* prf_state) { - sht_ctx* table; - //uint8_t** bin_content; - uint8_t *eleptr, *bin_ptr, *result, *res_bins; + // uint8_t** bin_content; + // uint8_t *eleptr; + uint8_t *bin_ptr, *res_bins; uint32_t i, j, tmpneles; - sheg_ctx* ctx; - pthread_t* entry_gen_tasks; hs_t hs; init_hashing_state(&hs, neles, bitlen, nbins, nhashfuns, prf_state); //Set the output bit-length of the hashed elements *outbitlen = hs.outbitlen; - entry_gen_tasks = (pthread_t*) malloc(sizeof(pthread_t) * ntasks); - ctx = (sheg_ctx*) malloc(sizeof(sheg_ctx) * ntasks); - table = (sht_ctx*) malloc(sizeof(sht_ctx) * ntasks); + std::vector entry_gen_tasks(ntasks); + std::vector ctx(ntasks); + std::vector table(ntasks); //in case no maxbinsize is specified, compute based on Eq3 in eprint 2016/930 @@ -35,7 +46,10 @@ uint8_t* simple_hashing(uint8_t* elements, uint32_t neles, uint32_t bitlen, uint } for(i = 0; i < ntasks; i++) { - init_hash_table(table + i, ceil_divide(neles, ntasks), &hs, *maxbinsize); + // old call, but init_hash_table does not use #elements + // init_hash_table(&table[i], ceil_divide(neles, ntasks), &hs, *maxbinsize); + + init_hash_table(&table[i], &hs, *maxbinsize); } //for(i = 0; i < nbins; i++) @@ -45,26 +59,32 @@ uint8_t* simple_hashing(uint8_t* elements, uint32_t neles, uint32_t bitlen, uint for(i = 0; i < ntasks; i++) { ctx[i].elements = elements; - ctx[i].table = table + i; + ctx[i].table = &table[i]; ctx[i].startpos = i * ceil_divide(neles, ntasks); ctx[i].endpos = std::min(ctx[i].startpos + ceil_divide(neles, ntasks), neles); ctx[i].hs = &hs; //std::cout << "Thread " << i << " starting from " << ctx[i].startpos << " going to " << ctx[i].endpos << " for " << neles << " elements" << std::endl; - if(pthread_create(entry_gen_tasks+i, NULL, gen_entries, (void*) (ctx+i))) { - std::cerr << "Error in creating new pthread at simple hashing!" << std::endl; - exit(0); + try { + entry_gen_tasks[i] = std::thread(gen_entries, &ctx[i]); + } catch (const std::system_error& e) { + std::cerr << "Error in creating new thread at simple hashing!\n" + << e.what() << std::endl; + exit(1); } } for(i = 0; i < ntasks; i++) { - if(pthread_join(entry_gen_tasks[i], NULL)) { - std::cerr << "Error in joining pthread at simple hashing!" << std::endl; - exit(0); + try { + entry_gen_tasks[i].join(); + } catch (const std::system_error& e) { + std::cerr << "Error in joining thread at simple hashing!\n" + << e.what() << std::endl; + exit(1); } } - *maxbinsize = table->maxbinsize; + *maxbinsize = table[0].maxbinsize; //for(i = 0, eleptr=elements; i < neles; i++, eleptr+=inbytelen) { // insert_element(table, eleptr, tmpbuf); @@ -81,20 +101,17 @@ uint8_t* simple_hashing(uint8_t* elements, uint32_t neles, uint32_t bitlen, uint for(i = 0; i < hs.nbins; i++) { nelesinbin[i] = 0; for(j = 0; j < ntasks; j++) { - tmpneles = (table +j)->bins[i].nvals; + tmpneles = table[j].bins[i].nvals; nelesinbin[i] += tmpneles; //bin_content[i] = (uint8_t*) malloc(nelesinbin[i] * table->outbytelen); - memcpy(bin_ptr, (table + j)->bins[i].values, tmpneles * hs.outbytelen); + memcpy(bin_ptr, table[j].bins[i].values, tmpneles * hs.outbytelen); bin_ptr += (tmpneles * hs.outbytelen); } //right now only the number of elements in each bin is copied instead of the max bin size } for(j = 0; j < ntasks; j++) - free_hash_table(table + j); - free(table); - free(entry_gen_tasks); - free(ctx); + free_hash_table(&table[j]); //for(i = 0; i < nbins; i++) // pthread_mutex_destroy(locks+i); @@ -105,32 +122,29 @@ uint8_t* simple_hashing(uint8_t* elements, uint32_t neles, uint32_t bitlen, uint return res_bins; } -void *gen_entries(void *ctx_tmp) { +void gen_entries(sheg_ctx* ctx) { //Insert elements in parallel, use lock to communicate - uint8_t *tmpbuf, *eleptr; - sheg_ctx* ctx = (sheg_ctx*) ctx_tmp; - uint32_t i, inbytelen, *address; + uint8_t *eleptr; + uint32_t i, inbytelen; - address = (uint32_t*) malloc(ctx->hs->nhashfuns * sizeof(uint32_t)); - tmpbuf = (uint8_t*) calloc(ceil_divide(ctx->hs->outbitlen, 8), sizeof(uint8_t)); //for(i = 0; i < NUM_HASH_FUNCTIONS; i++) { + std::vector address(ctx->hs->nhashfuns); + std::vector tmpbuf(ceil_divide(ctx->hs->outbitlen, 8), 0); + //for(i = 0; i < NUM_HASH_FUNCTIONS; i++) { // tmpbuf[i] = (uint8_t*) malloc(ceil_divide(ctx->hs->outbitlen, 8)); //} for(i = ctx->startpos, eleptr=ctx->elements, inbytelen=ctx->hs->inbytelen; i < ctx->endpos; i++, eleptr+=inbytelen) { - insert_element(ctx->table, eleptr, address, tmpbuf, ctx->hs); + insert_element(ctx->table, eleptr, address.data(), tmpbuf.data(), ctx->hs); } - free(tmpbuf); - free(address); } inline void insert_element(sht_ctx* table, uint8_t* element, uint32_t* address, uint8_t* tmpbuf, hs_t* hs) { - uint32_t i, j; bin_ctx* tmp_bin; hashElement(element, address, tmpbuf, hs); //std::cout << "Element " << - for(i = 0; i < hs->nhashfuns; i++) { + for(uint32_t i = 0; i < hs->nhashfuns; i++) { tmp_bin=table->bins + address[i]; //pthread_mutex_lock(locks + address[i]); @@ -158,15 +172,13 @@ inline void insert_element(sht_ctx* table, uint8_t* element, uint32_t* address, } } -void init_hash_table(sht_ctx* table, uint32_t nelements, hs_t* hs, uint32_t maxbinsize) { - uint32_t i; - +void init_hash_table(sht_ctx* table, hs_t* hs, uint32_t maxbinsize) { table->nbins = hs->nbins; table->maxbinsize = maxbinsize; table->bins = (bin_ctx*) calloc(hs->nbins, sizeof(bin_ctx)); - for(i = 0; i < hs->nbins; i++) { + for(uint32_t i = 0; i < hs->nbins; i++) { table->bins[i].values = (uint8_t*) malloc(table->maxbinsize * hs->outbytelen); } } @@ -185,20 +197,16 @@ void free_hash_table(sht_ctx* table) { } inline uint32_t get_max_bin_size(uint32_t nbins, uint32_t neles) { - double n = neles; - if(ceil_divide(neles, nbins) < 3) { - if(neles >= (1<<24)) - return 27; - if(neles >= (1<<20)) - return 26; - if(neles >= (1<<16)) - return 25; - if(neles >= (1<<12)) - return 24; - if(neles >= (1<<8)) - return 23; - } else - return 6*std::max((uint32_t) ceil_divide(neles, nbins), (uint32_t) 3); + if (ceil_divide(neles, nbins) < 3) { + if (neles >= (1 << 24)) return 27; + if (neles >= (1 << 20)) return 26; + if (neles >= (1 << 16)) return 25; + if (neles >= (1 << 12)) return 24; + if (neles >= (1 << 8)) return 23; + else return 22; //TODO is 22 a good max bin size in this case? + } else { + return 6 * ceil_divide(neles, nbins); + } } void increase_max_bin_size(sht_ctx* table, uint32_t valbytelen) { diff --git a/src/examples/psi_phasing/common/hashing/simple_hashing.h b/src/examples/psi_phasing/common/hashing/simple_hashing.h index 96b96671..363b7aa7 100644 --- a/src/examples/psi_phasing/common/hashing/simple_hashing.h +++ b/src/examples/psi_phasing/common/hashing/simple_hashing.h @@ -1,8 +1,19 @@ -/* - * simle_hashing.h - * - * Created on: Oct 8, 2014 - * Author: mzohner +/** + \file simple_hashing.h + \author michael.zohner@ec-spride.de + \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . + \brief */ #ifndef SIMLE_HASHING_H_ @@ -46,8 +57,8 @@ typedef struct simple_hash_entry_gen_ctx { uint8_t* simple_hashing(uint8_t* elements, uint32_t neles, uint32_t bitlen, uint32_t* outbitlen, uint32_t* nelesinbin, uint32_t nbins, uint32_t* maxbinsize, uint32_t ntasks, uint32_t nhashfuns, prf_state_ctx* prf_state); //routine for generating the entries, is invoked by the threads -void *gen_entries(void *ctx); -void init_hash_table(sht_ctx* table, uint32_t nelements, hs_t* hs, uint32_t maxbinsize); +void gen_entries(sheg_ctx *ctx); +void init_hash_table(sht_ctx* table, hs_t* hs, uint32_t maxbinsize); void increase_max_bin_size(sht_ctx* table, uint32_t valbytelen); void free_hash_table(sht_ctx* table); inline void insert_element(sht_ctx* table, uint8_t* element, uint32_t* address, uint8_t* tmpbuf, hs_t* hs); diff --git a/src/examples/psi_phasing/common/hashing_includes.h b/src/examples/psi_phasing/common/hashing_includes.h index 35e19340..04d53e16 100644 --- a/src/examples/psi_phasing/common/hashing_includes.h +++ b/src/examples/psi_phasing/common/hashing_includes.h @@ -2,17 +2,17 @@ \file hashing_includes.h \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Header file that is used to point to the correct path of crypto.h and typedefs.h needed by the hashing repository in hashing/ */ diff --git a/src/examples/psi_phasing/common/phasing_circuit.cpp b/src/examples/psi_phasing/common/phasing_circuit.cpp index 23d8f26c..2021f4b7 100644 --- a/src/examples/psi_phasing/common/phasing_circuit.cpp +++ b/src/examples/psi_phasing/common/phasing_circuit.cpp @@ -2,17 +2,17 @@ \file phasing_circuit.cpp \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Implementation of ABYSetIntersection. */ @@ -62,7 +62,7 @@ int32_t test_phasing_circuit(e_role role, const std::string& address, uint16_t p //sample random server and client sets //sample_random_elements(neles, bitlen, srv_set, cli_set); //sample fixed server and client sets (is faster than random sets for larger sets) - set_fixed_elements(server_neles, client_neles, bitlen, srv_set, cli_set); + set_fixed_elements(server_neles, client_neles, srv_set, cli_set); /*for(uint32_t i = 0; i < neles; i++) { std::cout << i << ": " << srv_set[i] << " , " << cli_set[i] << std::endl; }*/ @@ -128,8 +128,12 @@ int32_t test_phasing_circuit(e_role role, const std::string& address, uint16_t p shr_cli_stash[i] = circ->PutRepeaterGate(server_neles, shr_cli_stash[i]); } - shr_stash_out = BuildPhasingStashCircuit(shr_srv_set, shr_cli_stash, server_neles, bitlen, maxstashsize, circ); - shr_stash_out = circ->PutOUTGate(shr_stash_out, CLIENT); + shr_stash_out = BuildPhasingStashCircuit(shr_srv_set, shr_cli_stash, server_neles, maxstashsize, circ); + { + auto tmp = shr_stash_out; + shr_stash_out = circ->PutOUTGate(shr_stash_out, CLIENT); + delete tmp; + } party->ExecCircuit(); //Only the client obtains the outputs and performs the checks @@ -189,6 +193,7 @@ int32_t test_phasing_circuit(e_role role, const std::string& address, uint16_t p for(uint32_t i = 0; i < circ_inter_ctr; i++) { assert(ver_intersect[i] == circ_intersect[i]); } + free(output); } #ifdef BATCH @@ -200,12 +205,18 @@ int32_t test_phasing_circuit(e_role role, const std::string& address, uint16_t p free(srv_set); free(cli_set); free(shr_srv_hash_table); - free(shr_cli_hash_table); - free(shr_out); + free(shr_cli_stash); + delete shr_cli_hash_table; + delete shr_out; + delete shr_stash_out; free(ver_intersect); free(circ_intersect); free(inv_perm); free(stash); + free(client_hash_table); + free(server_hash_table); + free(stashperm); + delete crypt; return 0; } @@ -241,8 +252,7 @@ void sample_random_elements(uint32_t neles, uint32_t bitlen, uint32_t* srv_set, } //generate client and server set such that half of the elements overlap -void set_fixed_elements(uint32_t server_neles, uint32_t client_neles, uint32_t bitlen, - uint32_t* srv_set, uint32_t* cli_set) { +void set_fixed_elements(uint32_t server_neles, uint32_t client_neles, uint32_t* srv_set, uint32_t* cli_set) { uint32_t incr = 15875162; uint32_t offset = (server_neles+client_neles)/2; for(uint32_t i = 0; i < server_neles; i++) { @@ -274,7 +284,7 @@ share* BuildPhasingCircuit(share** shr_srv_set, share* shr_cli_set, uint32_t bin } -share* BuildPhasingStashCircuit(share* shr_srv_set, share** shr_cli_stash, uint32_t neles, uint32_t bitlen, +share* BuildPhasingStashCircuit(share* shr_srv_set, share** shr_cli_stash, uint32_t neles, uint32_t maxstashsize, BooleanCircuit* circ) { share* out = new boolshare(maxstashsize, circ); @@ -354,9 +364,7 @@ void ClientHashingRoutine(uint8_t* elements, uint32_t neles, uint32_t elebitlen, uint8_t** hash_table, uint32_t* inv_perm, uint32_t* outbitlen, uint8_t** stash, uint32_t maxstashsize, uint32_t** stashperm, uint32_t ntasks, crypto* crypt, uint32_t nhashfuns) { - uint32_t outbytelen; prf_state_ctx prf_state; - uint8_t *tmphashtable, *client_dummy; uint32_t *nelesinbin = (uint32_t*) calloc(nbins, sizeof(uint32_t)); uint32_t* perm = (uint32_t*) malloc(sizeof(uint32_t) * nbins); diff --git a/src/examples/psi_phasing/common/phasing_circuit.h b/src/examples/psi_phasing/common/phasing_circuit.h index 261957fc..3bbcdacc 100644 --- a/src/examples/psi_phasing/common/phasing_circuit.h +++ b/src/examples/psi_phasing/common/phasing_circuit.h @@ -2,17 +2,17 @@ \file phasing_circuit.h \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Implementation of PSI using Phasing */ #ifndef __PHASING_CIRCUIT_ @@ -33,12 +33,12 @@ int32_t test_phasing_circuit(e_role role, const std::string& address, uint16_t p uint32_t maxbinsize, uint32_t mhashfuns); void sample_random_elements(uint32_t neles, uint32_t bitlen, uint32_t* srv_set, uint32_t* cli_set); -void set_fixed_elements(uint32_t server_neles, uint32_t client_neles, uint32_t bitlen, uint32_t* srv_set, uint32_t* cli_set); +void set_fixed_elements(uint32_t server_neles, uint32_t client_neles, uint32_t* srv_set, uint32_t* cli_set); share* BuildPhasingCircuit(share** shr_srv_set, share* shr_cli_set, uint32_t binsize, BooleanCircuit* circ); -share* BuildPhasingStashCircuit(share* shr_srv_set, share** shr_cli_stash, uint32_t neles, uint32_t bitlen, +share* BuildPhasingStashCircuit(share* shr_srv_set, share** shr_cli_stash, uint32_t neles, uint32_t maxstashsize, BooleanCircuit* circ); void ServerHashingRoutine(uint8_t* elements, uint32_t neles, uint32_t elebitlen, uint32_t nbins, diff --git a/src/examples/psi_phasing/psi_phasing.cpp b/src/examples/psi_phasing/psi_phasing.cpp index 4b99125f..62278fc4 100644 --- a/src/examples/psi_phasing/psi_phasing.cpp +++ b/src/examples/psi_phasing/psi_phasing.cpp @@ -2,17 +2,17 @@ \file psi_phasing.cpp \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Private Set Intersection Test class implementation. */ diff --git a/src/examples/psi_scs/common/WaksmanPermutation.cpp b/src/examples/psi_scs/common/WaksmanPermutation.cpp index e59e914e..36525811 100644 --- a/src/examples/psi_scs/common/WaksmanPermutation.cpp +++ b/src/examples/psi_scs/common/WaksmanPermutation.cpp @@ -2,17 +2,17 @@ \file WaksmanPermutation.cpp \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Implementation of WaksmanPermutation */ #include "WaksmanPermutation.h" @@ -22,8 +22,9 @@ PermutationNetwork::WaksmanPermutation::~WaksmanPermutation() { } uint32_t estimateGates(uint32_t numGates) { - if (numGates == 1) + if (numGates == 1){ return 0; + } else { uint32_t s1count = numGates / 2; uint32_t s2count = (numGates % 2 == 0) ? numGates / 2 - 1 : numGates / 2; @@ -34,7 +35,7 @@ uint32_t estimateGates(uint32_t numGates) { void PermutationNetwork::WaksmanPermutation::program_rec(uint32_t in, uint32_t block, uint32_t* p1, uint32_t* p2, uint32_t* rows, uint32_t* cols) { uint32_t out = rows[in]; - if ((in ^ 1) < m_nNumInputs && rows[in ^ 1] != -1) { + if ((in ^ 1) < m_nNumInputs && rows[in ^ 1] != UINT_MAX) { m_PM->setSwitchProgram(s1[in / 2], (block == 0) != (in % 2 == 0)); Todo->remove(in / 2); } @@ -50,17 +51,17 @@ void PermutationNetwork::WaksmanPermutation::program_rec(uint32_t in, uint32_t b m_PM->setSwitchProgram(s2[out / 2], out % 2 == 1); } } - rows[in] = -1; - cols[out] = -1; + rows[in] = UINT_MAX; + cols[out] = UINT_MAX; uint32_t newout = out ^ 1; - if (newout < m_nNumInputs && cols[newout] != -1) { + if (newout < m_nNumInputs && cols[newout] != UINT_MAX) { uint32_t newin = cols[newout]; - cols[newout] = -1; + cols[newout] = UINT_MAX; program_rec(newin, block ^ 1, p1, p2, rows, cols); } - if ((in ^ 1) < m_nNumInputs && rows[in ^ 1] != -1) { + if ((in ^ 1) < m_nNumInputs && rows[in ^ 1] != UINT_MAX) { program_rec(in ^ 1, block ^ 1, p1, p2, rows, cols); } } @@ -84,18 +85,18 @@ void PermutationNetwork::WaksmanPermutation::program(uint32_t* perm) { Todo = new TodoList(m_nNumInputs / 2); if (m_nNumInputs % 2 == 1) { // case c+d and b+d program_rec(m_nNumInputs - 1, 1, p1, p2, rows, cols); - if (cols[m_nNumInputs - 1] != -1) + if (cols[m_nNumInputs - 1] != UINT_MAX) program_rec(cols[m_nNumInputs - 1], 1, p1, p2, rows, cols); } if (m_nNumInputs % 2 == 0) { // case a - if (cols[m_nNumInputs - 1] != -1) + if (cols[m_nNumInputs - 1] != UINT_MAX) program_rec(cols[m_nNumInputs - 1], 1, p1, p2, rows, cols); - if (cols[m_nNumInputs - 2] != -1) + if (cols[m_nNumInputs - 2] != UINT_MAX) program_rec(cols[m_nNumInputs - 2], 0, p1, p2, rows, cols); } - for (uint32_t n = Todo->next(); n != -1; n = Todo->next()) { + for (uint32_t n = Todo->next(); n != UINT_MAX; n = Todo->next()) { program_rec(2 * n, 0, p1, p2, rows, cols); } diff --git a/src/examples/psi_scs/common/WaksmanPermutation.h b/src/examples/psi_scs/common/WaksmanPermutation.h index 6437668b..cedb481e 100644 --- a/src/examples/psi_scs/common/WaksmanPermutation.h +++ b/src/examples/psi_scs/common/WaksmanPermutation.h @@ -2,17 +2,17 @@ \file WaksmanPermutation.h \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Implementation of WaksmanPermutation */ #ifndef __ABY_WAKSMANPERMUTATION_H_ diff --git a/src/examples/psi_scs/common/sort_compare_shuffle.cpp b/src/examples/psi_scs/common/sort_compare_shuffle.cpp index c4a0b6a0..dc187d61 100644 --- a/src/examples/psi_scs/common/sort_compare_shuffle.cpp +++ b/src/examples/psi_scs/common/sort_compare_shuffle.cpp @@ -2,17 +2,17 @@ \file sort_compare_shuffle.cpp \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Implementation of ABYSetIntersection. */ @@ -30,17 +30,14 @@ int32_t test_psi_scs_circuit(e_role role, const std::string& address, uint16_t p uint32_t prot_version, bool verify) { uint32_t *srv_set, *cli_set, *circ_intersect, *ver_intersect; - uint32_t seqsize = 2* neles, ver_inter_ctr = 0, circ_inter_ctr = 0; + uint32_t ver_inter_ctr = 0, circ_inter_ctr = 0; uint32_t nswapgates = estimateGates(neles); share **shr_server_set, **shr_client_set, **shr_out; assert(bitlen <= 32); uint64_t mask = ((uint64_t) 1 << bitlen)-1; e_sharing sort, permute; - if(prot_version == 0) { - sort = S_BOOL; - permute = S_BOOL; - } else if (prot_version == 1) { + if (prot_version == 1) { sort = S_YAO; permute = S_YAO; } else if (prot_version == 2) { @@ -49,7 +46,10 @@ int32_t test_psi_scs_circuit(e_role role, const std::string& address, uint16_t p } else if (prot_version == 3) { sort = S_YAO; permute = S_YAO_REV; - } + } else { // prot_version == 0 and others + sort = S_BOOL; + permute = S_BOOL; + } //vector sel_bits(nswapgates); @@ -325,16 +325,16 @@ vector PutVectorBitonicSortGate(share** srv_set, share** cli_set, uint //TODO: Introduce specific gate that allows the permutation of vector gates from different input gates + bit positions - for (j = 0; j < bitlen; j++) { - //cout << "j = " << j << endl; + for (uint32_t l = 0; l < bitlen; l++) { + //cout << "l = " << l << endl; for (k = 0; k < ctr; k++) { parenta[k] = c[compa[k]]; parentb[k] = c[compb[k]]; - posa[k] = j; - posb[k] = j; + posa[k] = l; + posb[k] = l; } - tempcmpveca[j] = circ->PutCombineAtPosGate(parenta, j); - tempcmpvecb[j] = circ->PutCombineAtPosGate(parentb, j); + tempcmpveca[l] = circ->PutCombineAtPosGate(parenta, l); + tempcmpvecb[l] = circ->PutCombineAtPosGate(parentb, l); } diff --git a/src/examples/psi_scs/common/sort_compare_shuffle.h b/src/examples/psi_scs/common/sort_compare_shuffle.h index 598531a2..db3f66e7 100644 --- a/src/examples/psi_scs/common/sort_compare_shuffle.h +++ b/src/examples/psi_scs/common/sort_compare_shuffle.h @@ -2,17 +2,17 @@ \file abysetintersection.h \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Implementation of ABYSetIntersection. */ #ifndef __SORT_COMPARE_SHUFFLE_ diff --git a/src/examples/psi_scs/psi_scs.cpp b/src/examples/psi_scs/psi_scs.cpp index 12202b94..f079ddb4 100644 --- a/src/examples/psi_scs/psi_scs.cpp +++ b/src/examples/psi_scs/psi_scs.cpp @@ -2,17 +2,17 @@ \file psi_scs.cpp \author michael.zohner@cased.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Private Set Intersection with Sort-Compare-Shuffle of "Huang, Katz, Evans: Private Set Intersection: Are Garbled Circuits better than Custom Protocols? At NDSS 2012". diff --git a/src/examples/sha1/common/sha1_circuit.cpp b/src/examples/sha1/common/sha1_circuit.cpp index f9c9e02e..deed7d41 100644 --- a/src/examples/sha1/common/sha1_circuit.cpp +++ b/src/examples/sha1/common/sha1_circuit.cpp @@ -2,17 +2,17 @@ \file sha1_circuit.cpp \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Implementation of the SHA1 hash function (which should not be used in practice anymore!) */ #include "sha1_circuit.h" @@ -31,7 +31,7 @@ int32_t test_sha1_circuit(e_role role, const std::string& address, uint16_t port crypto* crypt = new crypto(seclvl.symbits, (uint8_t*) const_seed); CBitVector msgS, msgC, verify; - uint32_t testvec = 0x616263; + // uint32_t testvec = 0x616263; //The plaintext output computation will only be done once instead of nvals times! uint8_t* plain_out = (uint8_t*) malloc(ABY_SHA1_OUTPUT_BYTES); diff --git a/src/examples/sha1/common/sha1_circuit.h b/src/examples/sha1/common/sha1_circuit.h index eb595e90..29d722be 100644 --- a/src/examples/sha1/common/sha1_circuit.h +++ b/src/examples/sha1/common/sha1_circuit.h @@ -2,17 +2,17 @@ \file aescircuit.h \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Implementation of the SHA1 hash function (which should not be used in practice anymore!) */ diff --git a/src/examples/sha1/sha1_test.cpp b/src/examples/sha1/sha1_test.cpp index c0b80522..57a66d6f 100644 --- a/src/examples/sha1/sha1_test.cpp +++ b/src/examples/sha1/sha1_test.cpp @@ -2,17 +2,17 @@ \file aes_test.cpp \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief AES Test class implementation. */ diff --git a/src/examples/threshold_euclidean_dist_2d_simd/common/threshold-euclidean-dist.cpp b/src/examples/threshold_euclidean_dist_2d_simd/common/threshold-euclidean-dist.cpp index e4aa17d3..9621be90 100644 --- a/src/examples/threshold_euclidean_dist_2d_simd/common/threshold-euclidean-dist.cpp +++ b/src/examples/threshold_euclidean_dist_2d_simd/common/threshold-euclidean-dist.cpp @@ -3,17 +3,17 @@ \author michael.zohner@ec-spride.de \author oleksandr.tkachenko@crisp-da.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief 2D SIMD Threshold Euclidean distance Test class implementation. * Implements the functionality from PST’15 (http://ieeexplore.ieee.org/document/7232947/). */ @@ -22,60 +22,72 @@ #include "../../../abycore/sharing/sharing.h" #include -int32_t test_min_eucliden_dist_circuit(e_role role, const std::string& address, uint16_t port, seclvl seclvl, uint32_t pointbitlen, - uint32_t thresbitlen, uint32_t nthreads, e_mt_gen_alg mt_alg, e_sharing dstsharing, e_sharing minsharing, uint32_t n, - bool only_yao) { +int32_t test_min_eucliden_dist_circuit(e_role role, const std::string& address, uint16_t port, seclvl seclvl, uint32_t operationbitlen, + uint32_t nthreads, e_mt_gen_alg mt_alg, e_sharing dstsharing, e_sharing minsharing, uint32_t n, bool only_yao) { uint64_t * output; - ABYParty* party = new ABYParty(role, address, port, seclvl, pointbitlen, nthreads, mt_alg); + ABYParty* party = new ABYParty(role, address, port, seclvl, operationbitlen, nthreads, mt_alg); std::vector& sharings = party->GetSharings(); - crypto* crypt = new crypto(seclvl.symbits, (uint8_t*) const_seed); - - uint64_t x1[n], x2[n], y1[n], y2[n]; + uint64_t* x1 = new uint64_t[n]; + uint64_t* x2 = new uint64_t[n]; + uint64_t* y1 = new uint64_t[n]; + uint64_t* y2 = new uint64_t[n]; Circuit *arithcirc, *yaocirc; share *s_x1, *s_x2, *s_y1, *s_y2; + uint32_t input_length = operationbitlen / 4; + srand(time(NULL)); - uint64_t t = rand() % ((uint64_t) 1 << 8); ///< threshold + uint64_t t; ///< threshold + if(operationbitlen == 64) { + t = (uint64_t) rand(); + } else { //operationbitlen == 32 + t = rand() % ((uint64_t) 1 << operationbitlen); + } for (uint32_t i = 0; i < n; i++) { - x1[i] = rand() % ((uint64_t) 1 << 8); - x2[i] = rand() % ((uint64_t) 1 << 8); - y1[i] = rand() % ((uint64_t) 1 << 8); - y2[i] = rand() % ((uint64_t) 1 << 8); + x1[i] = rand() % ((uint64_t) 1 << input_length); + x2[i] = rand() % ((uint64_t) 1 << input_length); + y1[i] = rand() % ((uint64_t) 1 << input_length); + y2[i] = rand() % ((uint64_t) 1 << input_length); } yaocirc = sharings[minsharing]->GetCircuitBuildRoutine(); arithcirc = only_yao ? yaocirc : sharings[dstsharing]->GetCircuitBuildRoutine(); if (role == SERVER) { - s_x1 = arithcirc->PutSIMDINGate(n, x1, pointbitlen, role); - s_y1 = arithcirc->PutSIMDINGate(n, y1, pointbitlen, role); - s_x2 = arithcirc->PutDummySIMDINGate(n, pointbitlen); - s_y2 = arithcirc->PutDummySIMDINGate(n, pointbitlen); + s_x1 = arithcirc->PutSIMDINGate(n, x1, input_length, role); + s_y1 = arithcirc->PutSIMDINGate(n, y1, input_length, role); + s_x2 = arithcirc->PutDummySIMDINGate(n, input_length); + s_y2 = arithcirc->PutDummySIMDINGate(n, input_length); } else { - s_x1 = arithcirc->PutDummySIMDINGate(n, pointbitlen); - s_y1 = arithcirc->PutDummySIMDINGate(n, pointbitlen); - s_x2 = arithcirc->PutSIMDINGate(n, x2, pointbitlen, role); - s_y2 = arithcirc->PutSIMDINGate(n, y2, pointbitlen, role); + s_x1 = arithcirc->PutDummySIMDINGate(n, input_length); + s_y1 = arithcirc->PutDummySIMDINGate(n, input_length); + s_x2 = arithcirc->PutSIMDINGate(n, x2, input_length, role); + s_y2 = arithcirc->PutSIMDINGate(n, y2, input_length, role); } share * dst = build_min_euclidean_dist_circuit(s_x1, s_y1, s_x2, s_y2, n, t, - pointbitlen, arithcirc, (BooleanCircuit*) yaocirc, only_yao); + operationbitlen, arithcirc, (BooleanCircuit*) yaocirc, only_yao); dst = yaocirc->PutOUTGate(dst, SERVER); party->ExecCircuit(); if(role == SERVER){ - dst->get_clear_value_vec(&output, &pointbitlen, &n); - verify_min_euclidean_dist(x1, x2, y1, y2, output, n, t); + dst->get_clear_value_vec(&output, &operationbitlen, &n); + verify_min_euclidean_dist(x1, x2, y1, y2, output, n, t); } - + + delete x1; + delete x2; + delete y1; + delete y2; + return 0; } @@ -84,23 +96,24 @@ int32_t test_min_eucliden_dist_circuit(e_role role, const std::string& address, share* build_min_euclidean_dist_circuit(share* x1, share* y1, share* x2, share* y2, uint32_t n, uint64_t t, uint32_t bitlen, Circuit* distcirc, BooleanCircuit* mincirc, bool only_yao) { - uint32_t i, j, _one = 1, _zero = 0, _two = 2; + uint64_t _one = 1, _zero = 0; share * s_dx, *s_dy, *distance; // v Constants v - share * s_two = distcirc->PutSIMDCONSGate(n, _two, bitlen); share * s_t = mincirc->PutSIMDCONSGate(n, t, bitlen); share * s_one = mincirc->PutSIMDCONSGate(n, _one, bitlen); share * s_zero = mincirc->PutSIMDCONSGate(n, _zero, bitlen); // ^ Constants ^ // (a - b)^2 = ! a^2 - 2*a*b + b^2 ! + share* s_x_one_two = distcirc->PutMULGate(x1, x2); s_dx = distcirc->PutADDGate(distcirc->PutMULGate(x1, x1), distcirc->PutMULGate(x2, x2)); - s_dx = distcirc->PutSUBGate(s_dx, distcirc->PutMULGate(s_two, distcirc->PutMULGate(x1, x2))); + s_dx = distcirc->PutSUBGate(s_dx, distcirc->PutADDGate(s_x_one_two, s_x_one_two)); + share* s_y_one_two = distcirc->PutMULGate(y1, y2); s_dy = distcirc->PutADDGate(distcirc->PutMULGate(y1, y1), distcirc->PutMULGate(y2, y2)); - s_dy = distcirc->PutSUBGate(s_dy, distcirc->PutMULGate(s_two, distcirc->PutMULGate(y1, y2))); + s_dy = distcirc->PutSUBGate(s_dy, distcirc->PutADDGate(s_y_one_two, s_y_one_two)); //d = d_x + d_y = (x_1 - x_2)^2 + (y_1 - y_2)^2 distance = distcirc->PutADDGate(s_dx, s_dy); diff --git a/src/examples/threshold_euclidean_dist_2d_simd/common/threshold-euclidean-dist.h b/src/examples/threshold_euclidean_dist_2d_simd/common/threshold-euclidean-dist.h index 4ecfa0eb..c44ef276 100644 --- a/src/examples/threshold_euclidean_dist_2d_simd/common/threshold-euclidean-dist.h +++ b/src/examples/threshold_euclidean_dist_2d_simd/common/threshold-euclidean-dist.h @@ -3,17 +3,17 @@ \author michael.zohner@ec-spride.de \author oleksandr.tkachenko@crisp-da.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief 2D SIMD Threshold Euclidean distance Test class implementation. * Implements the functionality from PST’15 (http://ieeexplore.ieee.org/document/7232947/). */ @@ -33,7 +33,7 @@ class BooleanCircuit; // uint32_t* y2, uint32_t * res, uint32_t n, uint32_t t); void verify_min_euclidean_dist(uint64_t* x1, uint64_t* x2, uint64_t* y1, uint64_t* y2, uint64_t * res, uint32_t n, uint64_t t); -int32_t test_min_eucliden_dist_circuit(e_role role, const std::string& address, uint16_t port, seclvl seclvl, uint32_t dbsize, uint32_t dim, +int32_t test_min_eucliden_dist_circuit(e_role role, const std::string& address, uint16_t port, seclvl seclvl, uint32_t operationbitlen, uint32_t nthreads, e_mt_gen_alg mt_alg, e_sharing dstsharing, e_sharing minsharing, uint32_t n, bool only_yao); share* build_min_euclidean_dist_circuit(share* x1, share* y1, share* x2, share* y2, uint32_t n, uint64_t t, uint32_t bitlen, Circuit* distcirc, BooleanCircuit* mincirc, diff --git a/src/examples/threshold_euclidean_dist_2d_simd/threshold-euclidean-dist.cpp b/src/examples/threshold_euclidean_dist_2d_simd/threshold-euclidean-dist.cpp index 5384f7ef..e52c4d6b 100644 --- a/src/examples/threshold_euclidean_dist_2d_simd/threshold-euclidean-dist.cpp +++ b/src/examples/threshold_euclidean_dist_2d_simd/threshold-euclidean-dist.cpp @@ -3,17 +3,17 @@ \author michael.zohner@ec-spride.de \author oleksandr.tkachenko@crisp-da.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief 2D SIMD Threshold Euclidean distance Test class implementation. * Implements the functionality from PST’15 (http://ieeexplore.ieee.org/document/7232947/). */ @@ -26,23 +26,18 @@ #include "common/threshold-euclidean-dist.h" -int32_t read_test_options(int32_t* argcp, char*** argvp, e_role* role, - uint32_t* pointbitlen, uint32_t* threshbitlen, uint32_t* secparam, - std::string* address, uint16_t* port, int32_t* test_op, uint32_t * n , - bool * only_yao) { +int32_t read_test_options(int32_t* argcp, char*** argvp, e_role* role, uint32_t* operationbitlen, + uint32_t* secparam, std::string* address, uint16_t* port, uint32_t * n, bool* only_yao) { uint32_t int_role = 0, int_port = 0; - bool useffc = false; parsing_ctx options[] = { { (void*) &int_role, T_NUM, "r", "Role: 0/1", true, false }, { (void*) n, T_NUM, "n", "Number of parallel evaluations", true, false }, - { (void*) pointbitlen, T_NUM, "b", "Bit-length of points, default 16", false, false }, + { (void*) operationbitlen, T_NUM, "b", "Bit-length of threshold; input length is set to a quarter of this value; only values allowed are 32 (inputlengh=8) and 64 (inputlength=16), default 64", false, false }, { (void*) secparam, T_NUM, "s", "Symmetric Security Bits, default: 128", false, false }, - { (void*) threshbitlen, T_NUM, "e", "Bit-length of threshold, default 32", false, false }, { (void*) address, T_STR, "a", "IP-address, default: localhost", false, false }, { (void*) &int_port, T_NUM, "p", "Port, default: 7766", false, false }, - { (void*) test_op, T_NUM, "t", "Single test (leave out for all operations), default: off", false, false }, { (void*) n, T_NUM, "n", "Number of parallel evaluations, default: 1000", false, false }, { (void*) only_yao, T_FLAG, "y", "Force using only the Yao sharing: false", false, false } }; @@ -61,6 +56,8 @@ int32_t read_test_options(int32_t* argcp, char*** argvp, e_role* role, *port = (uint16_t) int_port; } + assert(*operationbitlen == 64 || *operationbitlen == 32); + //delete options; return 1; @@ -68,21 +65,20 @@ int32_t read_test_options(int32_t* argcp, char*** argvp, e_role* role, int main(int argc, char** argv) { e_role role; - uint32_t pointbitlen = 32, thresbitlen=64, secparam = 128, nthreads = 1; + uint32_t operationbitlen = 64, secparam = 128, nthreads = 2; uint16_t port = 7766; std::string address = "127.0.0.1"; - int32_t test_op = -1; uint32_t n = 1000; e_mt_gen_alg mt_alg = MT_OT; bool only_yao = false; - read_test_options(&argc, &argv, &role, &pointbitlen, &thresbitlen, - &secparam, &address, &port, &test_op, &n, &only_yao); + read_test_options(&argc, &argv, &role, &operationbitlen, + &secparam, &address, &port, &n, &only_yao); seclvl seclvl = get_sec_lvl(secparam); test_min_eucliden_dist_circuit(role, address, port, - seclvl, pointbitlen, thresbitlen, 2, mt_alg, S_ARITH, S_YAO, n, only_yao); + seclvl, operationbitlen, nthreads, mt_alg, S_ARITH, S_YAO, n, only_yao); return 0; } diff --git a/src/examples/uc_circuit/common/uc_circuit.cpp b/src/examples/uc_circuit/common/uc_circuit.cpp index 339cd100..76e4632d 100644 --- a/src/examples/uc_circuit/common/uc_circuit.cpp +++ b/src/examples/uc_circuit/common/uc_circuit.cpp @@ -2,17 +2,17 @@ \file uc_gate_test.cpp \author kiss@encrypto.cs.tu-darmstadt.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Test the universal circuit evaluation */ diff --git a/src/examples/uc_circuit/common/uc_circuit.h b/src/examples/uc_circuit/common/uc_circuit.h index 3919573a..fb6af11b 100644 --- a/src/examples/uc_circuit/common/uc_circuit.h +++ b/src/examples/uc_circuit/common/uc_circuit.h @@ -2,17 +2,17 @@ \file uc_gate_test.cpp \author kiss@encrypto.cs.tu-darmstadt.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Test the universal circuit evaluation */ diff --git a/src/examples/uc_circuit/uc_circuit_test.cpp b/src/examples/uc_circuit/uc_circuit_test.cpp index 40cfd091..c4cb04d1 100755 --- a/src/examples/uc_circuit/uc_circuit_test.cpp +++ b/src/examples/uc_circuit/uc_circuit_test.cpp @@ -2,17 +2,17 @@ \file uc_gate_test.cpp \author kiss@encrypto.cs.tu-darmstadt.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief Test the universal circuit evaluation */ diff --git a/src/test/abytest.cpp b/src/test/abytest.cpp index 36a87fd1..08abd377 100644 --- a/src/test/abytest.cpp +++ b/src/test/abytest.cpp @@ -2,17 +2,17 @@ \file abytest.cpp \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief ABYTest class implementation. */ @@ -37,51 +37,60 @@ int main(int argc, char** argv) { uint32_t bitlen = 32, nvals = 65, secparam = 128, nthreads = 1, nelements=1024; uint16_t port = 7766; string address = "127.0.0.1"; - bool verbose = false; + bool quiet = false; bool randomseed = false; + bool ignore_verification = false; int32_t test_op = -1; e_mt_gen_alg mt_alg = MT_OT; uint32_t num_test_runs = 2; - read_test_options(&argc, &argv, &role, &bitlen, &nvals, &secparam, &address, &port, &test_op, &num_test_runs, &mt_alg, &verbose, &randomseed); + read_test_options(&argc, &argv, &role, &bitlen, &nvals, &secparam, &address, &port, &test_op, &num_test_runs, &mt_alg, &quiet, &ignore_verification, &randomseed); + + // FIXME: fix verification for different bitlengths + if (!ignore_verification && bitlen != 32){ + bitlen = 32; + std::cerr << "Verification currenlty only works for 32-bit values. Changing bitlen to 32." << std::endl; + } seclvl seclvl = get_sec_lvl(secparam); - run_tests(role, (char*) address.c_str(), port, seclvl, bitlen, nvals, nthreads, mt_alg, test_op, num_test_runs, verbose, randomseed); + run_tests(role, (char*) address.c_str(), port, seclvl, bitlen, nvals, nthreads, mt_alg, test_op, num_test_runs, quiet, ignore_verification, randomseed); if (test_op == -1) { //Test the AES circuit - cout << "Testing AES circuit in Boolean sharing" << endl; + std::cout << "Testing AES circuit in Boolean sharing" << std::endl; test_aes_circuit(role, (char*) address.c_str(), port, seclvl, nvals, nthreads, mt_alg, S_BOOL); - cout << "Testing AES circuit in Yao sharing" << endl; + std::cout << "Testing AES circuit in Yao sharing" << std::endl; test_aes_circuit(role, (char*) address.c_str(), port, seclvl, nvals, nthreads, mt_alg, S_YAO); - // cout << "Testing AES circuit in Setup-LUT sharing" << endl; + std::cout << "Testing AES circuit in Yao sharing, key expansion during SFE and client only input" << std::endl; + test_aes_circuit(role, (char*) address.c_str(), port, seclvl, nvals, nthreads, mt_alg, S_YAO, false, true, true); + // std::cout << "Testing AES circuit in Setup-LUT sharing" << std::endl; // test_aes_circuit(role, (char*) address.c_str(), port, seclvl, nvals, nthreads, mt_alg, S_SPLUT); //Test the SHA1 circuit TODO: Constant gates are limited to nvals < 64. Fix! - cout << "Testing SHA1 circuit in Boolean sharing" << endl; + std::cout << "Testing SHA1 circuit in Boolean sharing" << std::endl; test_sha1_circuit(role, (char*) address.c_str(), port, seclvl, 63, nthreads, mt_alg, S_BOOL); - cout << "Testing SHA1 circuit in Yao sharing" << endl; + std::cout << "Testing SHA1 circuit in Yao sharing" << std::endl; test_sha1_circuit(role, (char*) address.c_str(), port, seclvl, 63, nthreads, mt_alg, S_YAO); - //cout << "Testing SHA1 circuit in Setup-LUT sharing" << endl; + //std::cout << "Testing SHA1 circuit in Setup-LUT sharing" << std::endl; //test_sha1_circuit(role, (char*) address.c_str(), seclvl, 63, nthreads, mt_alg, S_SPLUT); //Test the Sort-Compare-Shuffle PSI circuit - cout << "Testing SCS PSI circuit in Boolean sharing" << endl; + std::cout << "Testing SCS PSI circuit in Boolean sharing" << std::endl; test_psi_scs_circuit(role, (char*) address.c_str(), port, seclvl, nelements, bitlen, nthreads, mt_alg, 0, true); - cout << "Testing SCS PSI circuit in Yao sharing" << endl; + std::cout << "Testing SCS PSI circuit in Yao sharing" << std::endl; test_psi_scs_circuit(role, (char*) address.c_str(), port, seclvl, nelements, bitlen, nthreads, mt_alg, 1, true); - //cout << "Testing SCS PSI circuit in Setup-LUT sharing" << endl; + //std::cout << "Testing SCS PSI circuit in Setup-LUT sharing" << std::endl; //test_psi_scs_circuit(role, (char*) address.c_str(), seclvl, nelements, bitlen, nthreads, mt_alg, S_SPLUT); //Test the Phasing PSI circuit - // cout << "Testing PSI Phasing circuit in Boolean sharing" << endl; + // std::cout << "Testing PSI Phasing circuit in Boolean sharing" << std::endl; // test_phasing_circuit(role, (char*) address.c_str(), port, seclvl, nelements, nelements, bitlen, epsilon, nthreads, mt_alg, // S_BOOL, 1, 0, 3); - // cout << "Testing PSI Phasing circuit in Yao sharing" << endl; + // std::cout << "Testing PSI Phasing circuit in Yao sharing" << std::endl; // test_phasing_circuit(role, (char*) address.c_str(), port, seclvl, nelements, nelements, bitlen, epsilon, nthreads, mt_alg, // S_YAO, 1, 0, 3); - // cout << "Testing PSI Phasing circuit in Setup-LUT sharing" << endl; + // std::cout << "Testing PSI Phasing circuit in Setup-LUT sharing" << std::endl; // test_phasing_circuit(role, (char*) address.c_str(), port, seclvl, nelements, nelements, bitlen, epsilon, nthreads, mt_alg, S_SPLUT, 1, 0, 3); //test_lowmc_circuit(role, (char*) address.c_str(), seclvl, nvals, nthreads, mt_alg, S_BOOL, (LowMCParams*) &stp); @@ -90,13 +99,13 @@ int main(int argc, char** argv) { } - cout << "All tests successfully passed." << endl; + std::cout << "All tests successfully passed." << std::endl; - return 0; + return EXIT_SUCCESS; } bool run_tests(e_role role, char* address, uint16_t port, seclvl seclvl, uint32_t bitlen, uint32_t nvals, uint32_t nthreads, - e_mt_gen_alg mt_alg, int32_t test_op, uint32_t num_test_runs, bool verbose, bool randomseed) { + e_mt_gen_alg mt_alg, int32_t test_op, uint32_t num_test_runs, bool quiet, bool ignore_verification, bool randomseed) { ABYParty* party = new ABYParty(role, address, port, seclvl, bitlen, nthreads, mt_alg); uint32_t nops; @@ -124,8 +133,8 @@ bool run_tests(e_role role, char* address, uint16_t port, seclvl seclvl, uint32_ srand(seed); } - test_standard_ops(test_ops, party, bitlen, num_test_runs, nops, role, verbose); - test_vector_ops(test_ops, party, bitlen, nvals, num_test_runs, nops, role, verbose); + test_standard_ops(test_ops, party, bitlen, num_test_runs, nops, role, quiet, ignore_verification); + test_vector_ops(test_ops, party, bitlen, nvals, num_test_runs, nops, role, quiet, ignore_verification); delete party; if (test_ops != m_tAllOps) @@ -135,13 +144,15 @@ bool run_tests(e_role role, char* address, uint16_t port, seclvl seclvl, uint32_ } int32_t test_standard_ops(aby_ops_t* test_ops, ABYParty* party, uint32_t bitlen, uint32_t num_test_runs, uint32_t nops, - e_role role, bool verbose) { + e_role role, bool quiet, bool ignore_verification) { uint32_t a = 0, b = 0, c, verify, sa, sb, sc, xbit, ybit, op; share *shra, *shrb, *shrres, *shrout, *shrsel; share **shrres_vec; vector& sharings = party->GetSharings(); Circuit *bc, *yc, *ac; + if (quiet) {std::cout << "Running operation test quietly."<< std::endl;} + for (uint32_t r = 0; r < num_test_runs; r++) { for (uint32_t i = 0; i < nops; i++) { Circuit* circ = sharings[test_ops[i].sharing]->GetCircuitBuildRoutine(); @@ -276,24 +287,34 @@ int32_t test_standard_ops(aby_ops_t* test_ops, ABYParty* party, uint32_t bitlen, } shrout = circ->PutOUTGate(shrres, ALL); - if (!verbose) - cout << "Running test no. " << i << " on operation " << test_ops[i].opname; - cout << endl; + if (!quiet){ + std::cout << "Running test no. " << i << " on operation " << test_ops[i].opname << std::endl; + } + party->ExecCircuit(); c = shrout->get_clear_value(); - if (!verbose) - cout << get_role_name(role) << " " << test_ops[i].opname << ": values: a = " << - a << ", b = " << b << ", c = " << c << ", verify = " << verify << endl; + if (!quiet){ + std::cout << get_role_name(role) << " " << test_ops[i].opname << ": values: a = " << + a << ", b = " << b << ", c = " << c << ", verify = " << verify << std::endl; + } party->Reset(); - assert(verify == c); + + if (!ignore_verification) { + if (verify != c) { + std::cerr << "ERROR in test verification! " << std::endl; + std::cerr << get_role_name(role) << " " << test_ops[i].opname << ": values: a = " << a + << ", b = " << b << ", c = " << c << ", verify = " << verify << std::endl; + exit(EXIT_FAILURE); + } + } } } - return 1; + return EXIT_SUCCESS; } int32_t test_vector_ops(aby_ops_t* test_ops, ABYParty* party, uint32_t bitlen, uint32_t nvals, uint32_t num_test_runs, - uint32_t nops, e_role role, bool verbose) { + uint32_t nops, e_role role, bool quiet, bool ignore_verification) { uint32_t *avec, *bvec, *cvec, *verifyvec, tmpbitlen, tmpnvals, sc, op, xbit, ybit; uint8_t *sa, *sb; uint32_t nvals_orig = nvals; @@ -314,8 +335,8 @@ int32_t test_vector_ops(aby_ops_t* test_ops, ABYParty* party, uint32_t bitlen, u for (uint32_t r = 0; r < num_test_runs; r++) { for (uint32_t i = 0; i < nops; i++) { - if (!verbose) - cout << "Running vector test no. " << i << " on operation " << test_ops[i].opname << endl; + if (!quiet) + std::cout << "Running vector test no. " << i << " on operation " << test_ops[i].opname << std::endl; if(test_ops[i].op == OP_UNIV && nvals > 32) { nvals = 32; //max nvals for universal gates @@ -340,11 +361,11 @@ int32_t test_vector_ops(aby_ops_t* test_ops, ABYParty* party, uint32_t bitlen, u share* tmp; if(circ->GetCircuitType() == C_BOOLEAN) { tmp = new boolshare(2, circ); - cout << "Boolean, max share len = " << tmp->max_size() << endl; + std::cout << "Boolean, max share len = " << tmp->max_size() << std::endl; } else { tmp = new arithshare(2, circ); - cout << "Arithmetic" << endl; + std::cout << "Arithmetic" << std::endl; } for(uint32_t j = 0; j < bitlen; j++) { @@ -524,35 +545,49 @@ int32_t test_vector_ops(aby_ops_t* test_ops, ABYParty* party, uint32_t bitlen, u party->ExecCircuit(); - //cout << "Size of output: " << shrout->size() << endl; + //std::cout << "Size of output: " << shrout->size() << std::endl; // this allocates buffer put into cvec with calloc shrout->get_clear_value_vec(&cvec, &tmpbitlen, &tmpnvals); - assert(tmpnvals == nvals); + + if(!ignore_verification){ + assert(tmpnvals == nvals); + } + party->Reset(); for (uint32_t j = 0; j < nvals; j++) { - if (!verbose) - cout << "\t" << get_role_name(role) << " " << test_ops[i].opname << ": values[" << j << + if (!quiet){ + std::cout << "\t" << get_role_name(role) << " " << test_ops[i].opname << ": values[" << j << "]: a = " << avec[j] << ", b = " << bvec[j] << ", c = " << cvec[j] << ", verify = " << - verifyvec[j] << endl; - assert(verifyvec[j] == cvec[j]); + verifyvec[j] << std::endl; + } + if(!ignore_verification){ + if(verifyvec[j] != cvec[j]){ + std::cerr << "ERROR in test verification! " << std::endl; + std::cerr << "\t" << get_role_name(role) << " " << test_ops[i].opname << ": values[" << j << + "]: a = " << avec[j] << ", b = " << bvec[j] << ", c = " << cvec[j] << ", verify = " << + verifyvec[j] << std::endl; + exit(EXIT_FAILURE); + } + } + } - free(cvec); + std::free(cvec); } } - free(sa); - free(sb); - free(avec); - free(bvec); - free(verifyvec); + std::free(sa); + std::free(sb); + std::free(avec); + std::free(bvec); + std::free(verifyvec); - return 1; + return EXIT_SUCCESS; } int32_t read_test_options(int32_t* argcp, char*** argvp, e_role* role, uint32_t* bitlen, uint32_t* nvals, uint32_t* secparam, - string* address, uint16_t* port, int32_t* test_op, uint32_t* num_test_runs, e_mt_gen_alg *mt_alg, bool* verbose, bool* randomseed) { + string* address, uint16_t* port, int32_t* test_op, uint32_t* num_test_runs, e_mt_gen_alg *mt_alg, bool* quiet, bool* ignore_verification, bool* randomseed) { uint32_t int_role = 0, int_port = 0, int_mtalg = 0; @@ -564,7 +599,8 @@ int32_t read_test_options(int32_t* argcp, char*** argvp, e_role* role, uint32_t* { (void*) address, T_STR, "a", "IP-address, default: localhost", false, false }, { (void*) &int_port, T_NUM, "p", "Port, default: 7766", false, false }, { (void*) test_op, T_NUM, "t", "Single test (leave out for all operations), default: off", false, false }, - { (void*) verbose, T_FLAG, "v", "Do not print computation results, default: off", false, false }, + { (void*) quiet, T_FLAG, "q", "Do not print computation results, default: off", false, false }, + { (void*) ignore_verification, T_FLAG, "v", "Do not abort on failed verification, default: off", false, false }, { (void*) randomseed, T_FLAG, "R", "Use random seed (likely breaks verification when not on localhost), default: off", false, false }, { (void*) num_test_runs, T_NUM, "i", "Number of test runs for operation tests, default: 5", false, false }, { (void*) &int_mtalg, T_NUM, "m", "Arithmetic MT gen algo [0: OT, 1: Paillier, 2: DGK], default: 0", false, false } @@ -572,7 +608,7 @@ int32_t read_test_options(int32_t* argcp, char*** argvp, e_role* role, uint32_t* if (!parse_options(argcp, argvp, options, sizeof(options) / sizeof(parsing_ctx))) { print_usage(*argvp[0], options, sizeof(options) / sizeof(parsing_ctx)); - cout << "Exiting" << endl; + std::cout << "Exiting" << std::endl; exit(0); } @@ -589,8 +625,5 @@ int32_t read_test_options(int32_t* argcp, char*** argvp, e_role* role, uint32_t* //delete options; - return 1; + return EXIT_SUCCESS; } - - - diff --git a/src/test/abytest.h b/src/test/abytest.h index 1f236cb5..f2fd9c3b 100644 --- a/src/test/abytest.h +++ b/src/test/abytest.h @@ -2,17 +2,17 @@ \file abytest.h \author michael.zohner@ec-spride.de \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation - Copyright (C) 2015 Engineering Cryptographic Protocols Group, TU Darmstadt + Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ABY is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . \brief ABY Test class. */ @@ -37,16 +37,16 @@ #include "../examples/min-euclidean-dist/common/min-euclidean-dist-circuit.h" bool run_tests(e_role role, char* address, uint16_t port, seclvl seclvl, uint32_t bitlen, uint32_t nvals, uint32_t nthreads, e_mt_gen_alg mt_alg, - int32_t testop, uint32_t num_test_runs, bool verbose, bool randomseed); + int32_t testop, uint32_t num_test_runs, bool quiet, bool ignore_verification, bool randomseed); int32_t read_test_options(int32_t* argcp, char*** argvp, e_role* role, uint32_t* bitlen, uint32_t* nreps, uint32_t* secparam, - string* address, uint16_t* port, int32_t* test_op, uint32_t* num_test_runs, e_mt_gen_alg *mt_alg, bool* verbose, bool* randomseed); + string* address, uint16_t* port, int32_t* test_op, uint32_t* num_test_runs, e_mt_gen_alg *mt_alg, bool* quiet, bool* ignore_verification, bool* randomseed); int32_t test_standard_ops(aby_ops_t* test_ops, ABYParty* party, uint32_t bitlen, uint32_t num_test_runs, uint32_t nops, - e_role role, bool verbose); + e_role role, bool quiet, bool ignore_verification); int32_t test_vector_ops(aby_ops_t* test_ops, ABYParty* party, uint32_t bitlen, uint32_t nvals, uint32_t num_test_runs, - uint32_t nops, e_role role, bool verbose); + uint32_t nops, e_role role, bool quiet, bool ignore_verification); string get_op_name(e_operation op);